@charset "UTF-8";
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Fraunces:opsz,wght@9..144,600..900&family=Heebo:wght@400;500;700;800&family=Frank+Ruhl+Libre:wght@700;800;900&family=Noto+Kufi+Arabic:wght@500;700&family=Noto+Sans+Arabic:wght@400;500;700&family=Noto+Sans+Devanagari:wght@400;700&family=Noto+Sans+Bengali:wght@400;700&family=Noto+Sans+Tamil:wght@400;700&family=Noto+Sans+Thai:wght@400;700&family=Noto+Sans+Ethiopic:wght@400;700&display=swap");

/* ==========================================================================
   NXEWS — assets/css/nx.css
   The only stylesheet.  No framework, no build step, no @layer (a layered
   !important loses to an unlayered one and this file is the whole cascade).

   CONTENTS
     01  Fonts per script          — data-script on <html> picks the face
     02  Tokens                    — OKLCH palette, light + dark, type, rhythm
                                     02.1 @property  02.2 the eleven hues
                                     02.3 neutrals   02.4 rhythm/type
                                     02.5 the section ramp
     03  Reset and base
     04  Backdrop                  — colour field + paper grain
     05  Layout                    — .nx-wrap .nx-grid .nx-main
     06  Masthead                  — .nx-top .nx-live-pill .nx-capsule .nx-brand
     07  Ticker                    — .nx-ticker
     08  Section nav               — .nx-nav
     09  Overlays                  — .nx-langmenu .nx-searchpanel .nx-drawer
     10  Cards                     — .nx-card and every variant
     11  Section heads and rails   — .nx-sect .nx-rowscroll
     12  Live column               — .nx-live
     13  Most read                 — .nx-numlist .nx-rank
     14  Article prose             — defensive, for article.php
     15  Footer                    — .nx-foot
     16  Motion                    — reveal, reduced motion
     17  Responsive                — 1180 / 980 / 760 / 480 / 360
     18  Print and forced colours
     19  Page skeletons            — the containers the pages emit:
                                     .nx-heroblock .nx-tri .nx-secband
                                     .nx-art* .nx-keypoints .nx-sources
                                     .nx-masthead .nx-pager .nx-livewall
                                     .nx-vodfeat .nx-results .nx-facts .nx-404
                                     (its own breakpoints live in 19.11 — it
                                      comes after 17 and would beat it)
     20  Photography               — the house treatment: one grade, one
                                     duotone keyed to --sec, one cut corner
     21  Container queries         — cards size from their SLOT, not the
         and subgrid                 window.  21.1 explains why a card cannot
                                     be a subgrid, and where subgrid is used

   Notes that cost time to relearn:
     · The palette is LIGHT by default and dark is a complete second palette,
       switched by `color-scheme` through light-dark().  Section 02 explains
       why, and why --ink is now paper and --panel is now white.
     · CJK faces are NOT web-loaded (the Google CSS alone is ~100 KB per family
       and every OS ships a good one) — jp/kr/sc/tc use system stacks.
     · Every directional value is logical.  There is no `left` or `right` in
       this file outside of gradient angles and RTL-mirrored transforms.
     · Cards are visible by default; nx.js opts them into the reveal, so a
       JS failure can never leave the page blank.
     · Sections 20 and 21 come after 19 on purpose and are refinements only:
       remove either one and the layout is still correct.
   ========================================================================== */


/* ==========================================================================
   01  FONTS PER SCRIPT
   ========================================================================== */

/* --------------------------------------------------------------------------
   Metric-matched fallbacks — the entire measured CLS on this site was the
   webfont swap: `.nx-top-in` and `.nx-card-body` change height the moment
   Inter/Heebo land on top of Arial.  With fonts blocked, CLS measured exactly
   0.000, so nothing else moves.  These faces make the fallback occupy the same
   vertical space as the real one, so the swap is invisible instead of shoving
   forty cards down the page.  Values are the standard Inter/Heebo-over-Arial
   overrides; `local()` only, so they cost no request.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Inter Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 107.12%;
  ascent-override: 90.49%;
  descent-override: 22.56%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Heebo Fallback";
  src: local("Arial"), local("Segoe UI"), local("Liberation Sans");
  size-adjust: 103.4%;
  ascent-override: 96.2%;
  descent-override: 25.6%;
  line-gap-override: 0%;
}


:root {
  /* UI / body — one grotesk that already carries latin, cyrillic and greek. */
  --f-ui: "Inter", "Inter Fallback", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  /* Display — the headline voice.  Overridden per script below. */
  --f-hl: "Fraunces", "Iowan Old Style", "Times New Roman", Georgia, serif;
  --f-num: "Inter", "Inter Fallback", ui-monospace, "SF Mono", Menlo, monospace;
  /* Optical-size + wonk axes: Fraunces defaults to a quirky g/y. Not here. */
  --hl-var: "SOFT" 0, "WONK" 0;
  --hl-weight: 700;
  /* Per-script metric corrections, applied to every headline size. */
  --hl-scale: 1;
  --hl-lh: 1.06;
  --body-lh: 1.62;
}

:root[data-script="hebrew"] {
  --f-ui: "Heebo", "Heebo Fallback", "Segoe UI", system-ui, Arial, sans-serif;
  --f-hl: "Frank Ruhl Libre", "Heebo", "David Libre", Georgia, serif;
  --hl-var: normal;
  --hl-weight: 800;
  --hl-scale: .92;   /* Hebrew has no ascenders/descenders: same px reads small */
  --hl-lh: 1.22;
  --body-lh: 1.72;
}

:root[data-script="arabic"] {
  --f-ui: "Noto Sans Arabic", "Segoe UI", system-ui, Tahoma, sans-serif;
  --f-hl: "Noto Kufi Arabic", "Noto Sans Arabic", Tahoma, sans-serif;
  --hl-var: normal;
  --hl-weight: 700;
  --hl-scale: .88;   /* Kufi sets wide; and Arabic needs room under the line */
  --hl-lh: 1.5;
  --body-lh: 1.92;
}

:root[data-script="cyrillic"],
:root[data-script="greek"] {
  --f-hl: "Inter", system-ui, sans-serif;   /* Fraunces has neither script */
  --hl-var: normal;
  --hl-weight: 800;
  --hl-lh: 1.1;
}

:root[data-script="devanagari"] {
  --f-ui: "Noto Sans Devanagari", system-ui, sans-serif;
  --f-hl: "Noto Sans Devanagari", system-ui, sans-serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .94; --hl-lh: 1.44; --body-lh: 1.86;
}
:root[data-script="bengali"] {
  --f-ui: "Noto Sans Bengali", system-ui, sans-serif;
  --f-hl: "Noto Sans Bengali", system-ui, sans-serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .94; --hl-lh: 1.46; --body-lh: 1.88;
}
:root[data-script="tamil"] {
  --f-ui: "Noto Sans Tamil", system-ui, sans-serif;
  --f-hl: "Noto Sans Tamil", system-ui, sans-serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .88; --hl-lh: 1.5; --body-lh: 1.94;
}
:root[data-script="thai"] {
  --f-ui: "Noto Sans Thai", system-ui, sans-serif;
  --f-hl: "Noto Sans Thai", system-ui, sans-serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .94; --hl-lh: 1.52; --body-lh: 1.96;
}
:root[data-script="ethiopic"] {
  --f-ui: "Noto Sans Ethiopic", system-ui, sans-serif;
  --f-hl: "Noto Sans Ethiopic", system-ui, sans-serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .92; --hl-lh: 1.4; --body-lh: 1.84;
}

/* CJK: system faces only — loading four Noto CJK families would cost more
   than the rest of the page put together. */
:root[data-script="jp"] {
  --f-ui: "Hiragino Kaku Gothic ProN", "Yu Gothic", "Yu Gothic UI", "Meiryo", system-ui, sans-serif;
  --f-hl: "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .94; --hl-lh: 1.4; --body-lh: 1.9;
}
:root[data-script="kr"] {
  --f-ui: "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", system-ui, sans-serif;
  --f-hl: "Apple SD Gothic Neo", "Malgun Gothic", system-ui, sans-serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .94; --hl-lh: 1.38; --body-lh: 1.88;
}
:root[data-script="sc"] {
  --f-ui: "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", system-ui, sans-serif;
  --f-hl: "Songti SC", "SimSun", "Source Han Serif SC", serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .96; --hl-lh: 1.34; --body-lh: 1.86;
}
:root[data-script="tc"] {
  --f-ui: "PingFang TC", "Microsoft JhengHei", "Source Han Sans TC", system-ui, sans-serif;
  --f-hl: "Songti TC", "PMingLiU", serif;
  --hl-var: normal; --hl-weight: 700; --hl-scale: .96; --hl-lh: 1.34; --body-lh: 1.86;
}

/* ==========================================================================
   02  TOKENS
   --------------------------------------------------------------------------
   The palette is LIGHT first.  Paper, white panels, ink type — and eleven
   section colours that are structure rather than decoration: a band, a
   masthead, a filled kicker, a rule, a numeral.  Dark is a complete second
   palette, not a filter.

   Three things here are load-bearing and each one is a decision, not a taste:

   1. OKLCH, not HSL.  In HSL a "50% lightness" yellow-green and a "50%"
      blue are nowhere near the same lightness, so an eleven-colour system
      built in HSL always has three colours that shout and three that vanish.
      In OKLCH one L is one lightness for every hue, which is why every
      section chip below lands between 5.4:1 and 6.2:1 against its own label
      instead of between 2:1 and 11:1.  sRGB cannot reach the same chroma at
      every hue (cyan tops out around .09 where blue reaches .27), so --sec-c
      is a REQUEST: the browser gamut-maps it per hue, and on a P3 screen the
      same declaration simply renders more of it.

   2. light-dark(), so every themed value has ONE declaration site.  The
      switch is `color-scheme`, which is why the ramp is declared on
      `[data-theme]` as well as `:root` — agent H3's toggle may put the
      attribute on <html> or on <body>, and light-dark() resolves against the
      color-scheme of the element that DECLARES the custom property.  A
      browser old enough to have oklch() but not light-dark() (Chrome
      111-122) gets the light palette, which is the primary design, and the
      @supports block after the ramp restores dark for the common case.

   3. Everything that can be derived, is.  --tx-2/-3/-dim are --tx mixed
      toward --surface, hairlines are --tx mixed toward transparent, section
      tints are --sec-base mixed into --paper.  Flip the six primitives and
      the whole sheet follows; there is no second list to keep in step.

   Compatibility: --ink/--panel/--sec-1/--sec-2/--sec-3/--sec-ink and the
   rest of the old names are still here as aliases, because the feature
   stylesheets under assets/css/parts/ are written against them.  --ink is now paper and --panel
   is now white; the NAMES survived, the values did not.
   ========================================================================== */

/* --- 02.1  animated custom properties ------------------------------------ *
   A bare custom property is a token stream, so it steps rather than eases.
   These two are typed, which is what lets the sweep and the kicker fill be
   transitions instead of keyframes on a wrapper element. */

@property --nx-sweep {
  syntax: "<percentage>";
  inherits: false;
  initial-value: -40%;
}
@property --nx-fill {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}


/* --- 02.2  the eleven section hues --------------------------------------- *
   i18n.php hands CSS an HSL angle in --sec and it cannot be edited from here.
   Left alone, five of the eleven desks land inside a 60-degree arc of
   blue-green (world 212 and israel 205 are SEVEN degrees apart, which is no
   difference at all) while a 90-degree arc of the wheel goes unused.  --sec-h
   is the OKLCH angle the design actually uses: the same eleven desks spread
   23-37 degrees apart, with a deliberate 72-degree hole from 350 round to 62
   that belongs to the live red and to nothing else.

   The map is keyed on the style attribute, and it is keyed FOUR ways on
   purpose.  render.php writes `style="--sec:152"` with no space and no
   trailing semicolon; the moment nx.js calls setProperty('--rv-d', …) on the
   same element the browser re-serialises the whole attribute as
   `--sec: 152; --rv-d: 0ms;` — a space appears, a semicolon appears, and an
   exact-match selector silently stops matching.  That is not hypothetical: it
   is what happened here, and the symptom was eleven desks quietly rendering in
   their unmapped hues on the front page and in their mapped ones everywhere
   nx.js had not run.  So each desk matches `…:N;` and `…: N;` for the
   rewritten form and `$=` for the raw one.  The semicolon and the end anchor
   are load-bearing: without them `--sec:8` matches `--sec:88` and `--sec:34`
   matches `--sec:340`.

   An unknown hue — a regional edition, a future desk — falls through to the
   identity mapping on the line above and still gets a correct colour, just not
   a placed one.  The real fix is an `oklch` key in NX_SECTIONS. */

:root,
[style*="--sec"] { --sec-h: var(--sec); }

[style*="--sec:34;"], [style*="--sec: 34;"],
[style$="--sec:34"],  [style$="--sec: 34"]  { --sec-h: 62; }   /* culture  · amber */
[style*="--sec:88;"], [style*="--sec: 88;"],
[style$="--sec:88"],  [style$="--sec: 88"]  { --sec-h: 108; }   /* sports   · gold-olive */
[style*="--sec:128;"], [style*="--sec: 128;"],
[style$="--sec:128"],  [style$="--sec: 128"]  { --sec-h: 145; }   /* climate  · leaf */
[style*="--sec:152;"], [style*="--sec: 152;"],
[style$="--sec:152"],  [style$="--sec: 152"]  { --sec-h: 172; }   /* economy  · emerald */
[style*="--sec:172;"], [style*="--sec: 172;"],
[style$="--sec:172"],  [style$="--sec: 172"]  { --sec-h: 200; }   /* science  · cyan */
[style*="--sec:205;"], [style*="--sec: 205;"],
[style$="--sec:205"],  [style$="--sec: 205"]  { --sec-h: 228; }   /* israel   · azure */
[style*="--sec:212;"], [style*="--sec: 212;"],
[style$="--sec:212"],  [style$="--sec: 212"]  { --sec-h: 258; }   /* world    · royal blue */
[style*="--sec:8;"], [style*="--sec: 8;"],
[style$="--sec:8"],  [style$="--sec: 8"]  { --sec-h: 282; }   /* defence  · steel */
[style*="--sec:190;"], [style*="--sec: 190;"],
[style$="--sec:190"],  [style$="--sec: 190"]  { --sec-h: 307; }   /* tech     · violet */
[style*="--sec:268;"], [style*="--sec: 268;"],
[style$="--sec:268"],  [style$="--sec: 268"]  { --sec-h: 332; }   /* politics · magenta */
[style*="--sec:340;"], [style*="--sec: 340;"],
[style$="--sec:340"],  [style$="--sec: 340"]  { --sec-h: 350; }   /* health   · rose */


/* --- 02.3  neutrals ------------------------------------------------------ */

:root,
[data-theme] {
  color-scheme: light dark;

  /* The six primitives.  Everything below is mixed from these. */
  --paper:     light-dark(oklch(97.8% .006 84),  oklch(15.5% .014 266));
  --paper-2:   light-dark(oklch(95.2% .009 84),  oklch(18.5% .016 266));
  --surface:   light-dark(oklch(100%  0    0),   oklch(21.5% .016 266));
  --surface-2: light-dark(oklch(98.6% .005 84),  oklch(25%   .018 266));
  --surface-3: light-dark(oklch(95.8% .008 84),  oklch(29%   .020 266));
  --tx:        light-dark(oklch(24%   .022 268), oklch(95.5% .008 84));

  /* Type ramp.  Mixed toward the panel it sits on, so one set of percentages
     produces a correct ladder in both themes.  Measured on the rendered page,
     not calculated: --tx-dim is 5.1:1 on a card in light and 6.0:1 in dark.
     It started at 60% and measured 4.53 — passing, with no headroom for the
     one part file that puts it on a tinted panel. */
  --tx-2:   color-mix(in oklab, var(--tx) 78%, var(--surface));
  --tx-3:   color-mix(in oklab, var(--tx) 66%, var(--surface));
  --tx-dim: color-mix(in oklab, var(--tx) 64%, var(--surface));

  /* Hairlines and press states, as a fraction of the ink. */
  --hair:   color-mix(in oklab, var(--tx) 13%, transparent);
  --hair-2: color-mix(in oklab, var(--tx) 22%, transparent);
  --tap-1:  color-mix(in oklab, var(--tx)  4%, transparent);
  --tap-2:  color-mix(in oklab, var(--tx)  7%, transparent);
  --tap-3:  color-mix(in oklab, var(--tx) 11%, transparent);

  /* Translucent page ground, for the sticky masthead and day headers.  A
     backdrop-filter needs something to filter, so these keep some alpha. */
  --veil:   color-mix(in oklab, var(--paper) 86%, transparent);
  --veil-2: color-mix(in oklab, var(--paper) 96%, transparent);

  /* Compatibility aliases — the feature stylesheets are written against
     these names, so the names survived even though the values inverted. */
  --ink:     var(--paper);
  --ink-2:   var(--paper-2);
  --panel:   var(--surface);
  --panel-2: var(--surface-2);
  --panel-3: var(--surface-3);

  /* Type over a photograph is white in both themes: the scrim under it is
     dark in both themes, because a photograph does not have a theme. */
  --on-img:   #fff;
  --on-img-2: rgb(255 255 255 / .86);
  --on-img-3: rgb(255 255 255 / .68);

  /* The one loud colour.  LIVE and BREAKING and nothing else — which is why
     the section wheel above leaves the whole red arc empty.  It does NOT
     change with the theme: an alarm that is a different red at night is two
     alarms.  White on it measures 5.18:1. */
  --live:      oklch(56% .21 26);
  --live-hi:   oklch(64% .20 32);
  --live-glow: oklch(56% .21 26 / .40);
  --live-tint: color-mix(in oklab, oklch(56% .21 26) 12%, var(--paper));
  --live-hair: color-mix(in oklab, oklch(56% .21 26) 38%, transparent);
  --on-live:   #fff;

  /* Editorial status, for the feature stylesheets under parts/.  These are
     NOT section colours and never take a --sec: a correction is amber whatever
     desk it lands on, and a verified claim is green on the sports page too.
     Held at the same OKLCH lightness as the section fills, so a status chip
     and a desk chip in the same row are the same weight of colour. */
  --warn:      light-dark(oklch(52% .12 74),  oklch(78% .13 78));
  --warn-tint: color-mix(in oklab, var(--warn) 14%, var(--surface));
  --warn-hair: color-mix(in oklab, var(--warn) 40%, transparent);
  --ok:        light-dark(oklch(48% .12 160), oklch(78% .13 162));
  --ok-tint:   color-mix(in oklab, var(--ok) 13%, var(--surface));
  --ok-hair:   color-mix(in oklab, var(--ok) 38%, transparent);

  /* Photo scrims.  Always dark, both themes, for the reason above. */
  --scrim-1: rgb(6 8 14 / .94);
  --scrim-2: rgb(6 8 14 / .62);
  --scrim-3: rgb(6 8 14 / .24);
}

[data-theme="light"] { color-scheme: light; }
[data-theme="dark"]  { color-scheme: dark; }

/* The dark palette for browsers that have oklch() and color-mix() but not
   light-dark() — Chrome 111-122, Safari 16.2-17.4.  Only the six primitives
   are restated; the forty tokens derived from them follow on their own. */
@supports not (color: light-dark(#fff, #000)) {
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
      color-scheme: dark;
      --paper: oklch(15.5% .014 266); --paper-2: oklch(18.5% .016 266);
      --surface: oklch(21.5% .016 266); --surface-2: oklch(25% .018 266);
      --surface-3: oklch(29% .020 266); --tx: oklch(95.5% .008 84);
    }
  }
  [data-theme="dark"] {
    color-scheme: dark;
    --paper: oklch(15.5% .014 266); --paper-2: oklch(18.5% .016 266);
    --surface: oklch(21.5% .016 266); --surface-2: oklch(25% .018 266);
    --surface-3: oklch(29% .020 266); --tx: oklch(95.5% .008 84);
  }
}


/* --- 02.4  rhythm, type scale, motion ------------------------------------ */

:root {
  --wrap: 1480px;
  --gut:  clamp(14px, 2.6vw, 34px);
  --gap:  clamp(14px, 1.5vw, 26px);
  --rowgap: clamp(30px, 4.2vw, 66px);
  --r-s: 6px;
  --r-m: 12px;
  --r-l: 18px;
  --r-xl: 24px;
  --r-pill: 999px;

  /* Type scale — every headline size is clamp()ed and script-corrected. */
  --t-hero: calc(clamp(2.05rem, 1.1rem + 3.5vw, 4.5rem) * var(--hl-scale));
  --t-lead: calc(clamp(1.6rem, 1.05rem + 2vw, 2.75rem) * var(--hl-scale));
  --t-wide: calc(clamp(1.24rem, 1rem + .95vw, 1.78rem) * var(--hl-scale));
  --t-tile: calc(clamp(1.04rem, .93rem + .48vw, 1.34rem) * var(--hl-scale));
  --t-list: calc(clamp(.98rem, .92rem + .26vw, 1.14rem) * var(--hl-scale));
  --t-mini: calc(clamp(.92rem, .88rem + .18vw, 1.02rem) * var(--hl-scale));
  --t-sect: calc(clamp(1.28rem, 1.05rem + .8vw, 1.8rem) * var(--hl-scale));
  --t-dek:  clamp(.92rem, .88rem + .22vw, 1.05rem);
  --t-meta: .78rem;
  --t-kick: .715rem;

  --ease: cubic-bezier(.22, .8, .28, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --top-h: 68px;

  /* Card internals a container query rewrites in section 20.  Declared here
     so a browser without container queries still gets every value. */
  --card-pad: clamp(13px, 1.3vw, 20px);
  --card-gap: 8px;
  --sec: 212;
  --sec-h: 258;
}


/* --- 02.5  the section ramp ---------------------------------------------- *
   Re-derived on every element that carries its own --sec.  render.php puts
   style="--sec:NN" on <body>, .nx-card, .nx-caplink, .nx-navlink,
   .nx-drawer-link and .nx-sect-head, and the page files put it on section
   wrappers, so the attribute selector catches all of them and any future one.
   A custom property holding var() is substituted on the element that DECLARES
   it — deriving these once at :root would freeze every card to the default
   blue, which is why this block is not merged into 02.3. */

:root,
[data-theme],
[style*="--sec"] {
  /* Requested chroma.  Gamut-mapped per hue by the browser: blue renders all
     of it, cyan renders what sRGB has. */
  --sec-c: .125;

  /* Four tones.  deep = type on paper; fill = a block with --sec-on over it;
     base = the hue's identity, what tints are mixed from; onimg = the only
     one that ignores the theme, because it lives on a photograph. */
  --sec-deep:  light-dark(oklch(41% var(--sec-c) var(--sec-h)),
                          oklch(84% calc(var(--sec-c) * .8) var(--sec-h)));
  --sec-fill:  light-dark(oklch(51% var(--sec-c) var(--sec-h)),
                          oklch(66% var(--sec-c) var(--sec-h)));
  --sec-base:  light-dark(oklch(56% var(--sec-c) var(--sec-h)),
                          oklch(70% var(--sec-c) var(--sec-h)));
  --sec-on:    light-dark(#fff, oklch(16% .03 var(--sec-h)));
  --sec-onimg: oklch(76% var(--sec-c) var(--sec-h));
  /* The neighbouring hue, for the second light in the backdrop field. */
  --sec-far:   oklch(62% var(--sec-c) calc(var(--sec-h) + 52));

  /* Surfaces and lines, mixed from the tone above so they follow the theme
     with no second declaration.  --sec-tint is the full-bleed band, --sec-pan
     the panel that sits on it, --sec-chip the quiet chip fill. */
  --sec-tint:  color-mix(in oklab, var(--sec-base)  9%, var(--paper));
  --sec-tint2: color-mix(in oklab, var(--sec-base) 15%, var(--paper));
  --sec-chip:  color-mix(in oklab, var(--sec-base) 16%, var(--surface));
  --sec-soft:  color-mix(in oklab, var(--sec-base) 13%, transparent);
  --sec-hair:  color-mix(in oklab, var(--sec-base) 40%, transparent);
  --sec-line:  color-mix(in oklab, var(--sec-base) 62%, transparent);
  --sec-glow:  color-mix(in oklab, var(--sec-base) 26%, transparent);

  /* A shadow that borrows the section hue reads as depth; a grey one reads as
     a border with a blur on it.  Both stops are the SAME hue at different
     alpha, which is what keeps eleven differently-coloured cards on one page
     looking like one page. */
  --sh-c: light-dark(oklch(46% var(--sec-c) var(--sec-h)), oklch(5% var(--sec-c) var(--sec-h)));
  --sh-a: light-dark(color-mix(in oklab, var(--sh-c) 11%, transparent),
                     color-mix(in oklab, var(--sh-c) 55%, transparent));
  --sh-b: light-dark(color-mix(in oklab, var(--sh-c) 22%, transparent),
                     color-mix(in oklab, var(--sh-c) 82%, transparent));

  --sh-1: 0 1px 2px var(--sh-a), 0 8px 20px -12px var(--sh-b);
  --sh-2: 0 2px 5px var(--sh-a), 0 26px 50px -24px var(--sh-b);
  --sh-hot: 0 2px 6px var(--sh-a),
            0 30px 60px -26px var(--sh-b),
            0 0 0 1px var(--sec-hair),
            0 20px 54px -30px var(--sec-glow);

  /* Compatibility aliases.  --sec-1 was the bright accent on ink and is now
     the readable tone on paper; --sec-ink was near-black and is now the
     lightest tint.  Same names, inverted jobs — that is the whole redesign. */
  --sec-1:   var(--sec-deep);
  --sec-2:   var(--sec-fill);
  --sec-3:   light-dark(oklch(41% var(--sec-c) var(--sec-h)),
                        oklch(54% var(--sec-c) var(--sec-h)));
  --sec-ink: var(--sec-chip);
}


/* ==========================================================================
   03  RESET AND BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: calc(var(--top-h) + 24px);
}

body.nx {
  margin: 0;
  min-block-size: 100svh;
  /* Explicit, never inherited: a light surface that borrows its colour from a
     dark ancestor is how a whole panel goes invisible. */
  background: var(--paper);
  color: var(--tx);
  font-family: var(--f-ui);
  font-size: 16px;
  line-height: var(--body-lh);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;            /* nothing may push the page sideways */
  text-rendering: optimizeLegibility;
}

/* Keep the layout viewport pinned to the physical device width.  This belongs
   in the always-loaded core sheet: a long RTL ticker can otherwise double the
   root width before mobile media queries run, and Chrome may restore the page
   at that off-screen horizontal position. */
html,
body.nx {
  inline-size: 100%;
  max-inline-size: 100%;
  overflow-x: hidden;
}

@supports (overflow: clip) {
  html,
  body.nx { overflow-x: clip; }
}

h1, h2, h3, h4, p, figure, blockquote, ul, ol { margin: 0; }
ul, ol { padding-inline-start: 0; list-style: none; }

img, svg, video { display: block; max-inline-size: 100%; }
/* The placeholder a photo paints over while it loads carries the section
   hue, so a grid mid-load already reads as the right desk. */
img { block-size: auto; background: var(--sec-chip); }

a { color: inherit; text-decoration: none; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  margin: 0;
}
button { cursor: pointer; }

:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--sec-fill);
  outline-offset: 3px;
  border-radius: var(--r-s);
}

::selection { background: var(--sec-fill); color: var(--sec-on); }

.nx-i { flex: none; }

.nx-skip {
  position: fixed;
  inset-block-start: 8px;
  inset-inline-start: 8px;
  z-index: 300;
  padding: 12px 18px;
  border-radius: var(--r-m);
  background: var(--surface);
  color: var(--tx);
  border: 1px solid var(--sec-hair);
  box-shadow: var(--sh-2);
  font-weight: 600;
  translate: 0 -160%;
  transition: translate .2s var(--ease);
}
.nx-skip:focus-visible { translate: 0 0; }

/* Latin/number runs inside RTL copy — "09:00–20:00" reverses without this. */
.nx-ltr {
  unicode-bidi: isolate;
  direction: ltr;
  font-family: var(--f-num);
  font-variant-numeric: tabular-nums;
}

.nx-sep {
  border: 0;
  block-size: 1px;
  background: linear-gradient(90deg, transparent, var(--hair-2) 18%, var(--hair-2) 82%, transparent);
  margin-block: var(--rowgap);
}

.nx-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--r-s);
  border: 1px solid var(--hair-2);
  background: var(--surface);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tx-3);
  font-family: var(--f-ui);
}
.nx-chip.is-lang { color: var(--sec-deep); border-color: var(--sec-hair); background: var(--sec-chip); }


/* ==========================================================================
   04  BACKDROP — colour field + paper grain
   ========================================================================== */

/* The paper is not white; it carries the desk's colour at about a tenth of
   the strength the cards do.  On a dark page this is the old aurora; on a
   light one it is what stops a white grid from reading as a spreadsheet.
   Two radial gradients on one fixed element, and the amount is a token so
   the light and dark versions are one declaration. */
body.nx::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* light-dark() takes colours, not amounts, so the amount is baked into a
     colour on each side rather than passed as a percentage. */
  --field-a: light-dark(color-mix(in oklab, var(--sec-base) 13%, transparent),
                        color-mix(in oklab, var(--sec-base) 27%, transparent));
  --field-b: light-dark(color-mix(in oklab, var(--sec-far) 9%, transparent),
                        color-mix(in oklab, var(--sec-far) 19%, transparent));
  background:
    radial-gradient(118% 62% at var(--field-x, 14%) -14%, var(--field-a), transparent 66%),
    radial-gradient(96% 54% at var(--field-x2, 88%) -8%,  var(--field-b), transparent 70%);
  animation: nx-aurora 42s var(--ease) infinite alternate;
}
/* The field leans toward the corner the reader starts from, in either script. */
[dir="rtl"] body.nx::before { --field-x: 86%; --field-x2: 12%; }

@keyframes nx-aurora {
  0%   { transform: translate3d(-2%, 0, 0) scale(1.02); opacity: .92; }
  50%  { transform: translate3d(3%, 1.6%, 0) scale(1.09); opacity: 1; }
  100% { transform: translate3d(-1%, -1%, 0) scale(1.04); opacity: .86; }
}

/* Paper grain — one 90-byte turbulence tile, repeated.  `overlay` on a light
   ground turns the noise into dirt; `multiply` on a dark one erases it.  The
   blend mode is therefore part of the theme, not a constant. */
body.nx::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Opacity and blend mode are not colours, so light-dark() cannot carry them:
   these two are the only place in the sheet where the theme is written out
   three times, and it is three lines rather than forty. */
body.nx::after { opacity: .034; mix-blend-mode: multiply; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body.nx::after { opacity: .055; mix-blend-mode: overlay; }
}
[data-theme="dark"] body.nx::after,
body.nx[data-theme="dark"]::after { opacity: .055; mix-blend-mode: overlay; }


/* ==========================================================================
   05  LAYOUT
   ========================================================================== */

.nx-main {
  position: relative;
  z-index: 1;
  display: block;
  padding-block: clamp(20px, 3vw, 40px) clamp(40px, 6vw, 90px);
}

.nx-wrap {
  inline-size: min(100% - (var(--gut) * 2), var(--wrap));
  margin-inline: auto;
}

.nx-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--gap);
  align-items: start;
}

/* Sensible default spans so any composition the page author writes lands
   somewhere reasonable without them having to know this file. */
.nx-grid > .nx-card.is-hero,
.nx-grid > .nx-sect,
.nx-grid > .nx-numlist   { grid-column: span 12; }
.nx-grid > .nx-card.is-lead  { grid-column: span 8; }
.nx-grid > .nx-card.is-wide  { grid-column: span 6; }
.nx-grid > .nx-card.is-tile,
.nx-grid > .nx-card.is-vod   { grid-column: span 4; }
.nx-grid > .nx-card.is-list,
.nx-grid > .nx-card.is-mini  { grid-column: span 3; }
.nx-grid > .nx-live          { grid-column: span 4; }
.nx-grid > .nx-col           { grid-column: span 4; }

.nx-grid.is-main-rail    { grid-template-columns: minmax(0, 1fr) minmax(0, 340px); }
.nx-grid.is-main-rail > * { grid-column: auto; }

.nx-col { display: grid; gap: var(--gap); align-content: start; }

/* The tinted section band lives with .nx-secband in 19.4, because that is the
   only container the pages actually emit for one.  A generic .nx-band helper
   was written here first and no page ever used it — dead CSS in a design
   system is worse than none, because the next author styles against it. */


/* ==========================================================================
   06  MASTHEAD
   ========================================================================== */

.nx-top {
  position: sticky;
  inset-block-start: 0;
  z-index: 90;
  /* A border on a sticky header is what makes it shift on scroll — the border
     lives on a pseudo element instead, so .is-stuck never changes the box. */
  background: linear-gradient(180deg, var(--veil-2), var(--veil) 64%, transparent);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  transition: background .3s var(--ease), box-shadow .3s var(--ease);
}
/* The desk's colour, full width, at the very top of the page.  This is the
   one place a section hue is allowed to be a solid unbroken bar. */
.nx-top::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  block-size: 3px;
  background: linear-gradient(to right,
    var(--sec-fill) 0%,
    var(--sec-base) 44%,
    color-mix(in oklab, var(--sec-base), var(--live) 45%) 100%);
}
.nx-top::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 1px;
  background: linear-gradient(90deg, transparent, var(--sec-hair) 12%, var(--hair-2) 50%, var(--sec-hair) 88%, transparent);
  opacity: 0;
  transition: opacity .3s var(--ease);
}
.nx-top.is-stuck {
  background: var(--veil-2);
  box-shadow: 0 16px 34px -30px var(--sh-b);
}
.nx-top.is-stuck::after { opacity: 1; }

.nx-top-in {
  inline-size: min(100% - (var(--gut) * 2), var(--wrap));
  margin-inline: auto;
  min-block-size: var(--top-h);
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.4vw, 20px);
}

/* Brand sits at the inline-start even though the markup puts it later. */
.nx-brand {
  order: -2;
  display: flex;
  align-items: center;
  flex: none;
  padding-inline-end: 4px;
}
.nx-brand-mark { display: block; line-height: 0; }
.nx-brand svg { block-size: clamp(22px, 2.2vw, 30px); inline-size: auto; }
/* The wordmark is drawn in render.php with fill="url(#gradient)", which is a
   presentation attribute — any CSS rule outranks it.  That is the only way to
   make a mark authored for an ink page legible on a paper one. */
.nx-mark text { fill: var(--tx); }
.nx-mark circle { fill: var(--live); }
.nx-brand svg { transition: filter .25s var(--ease); }
.nx-brand:hover .nx-mark text { fill: var(--sec-deep); }
.nx-brand:hover svg { filter: drop-shadow(0 6px 14px var(--sec-glow)); }

/* --- LIVE pill ---------------------------------------------------------- */

.nx-live-pill {
  order: -1;
  flex: none;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 12px;
  padding-inline: 12px 14px;
  border-radius: var(--r-pill);
  background: linear-gradient(135deg, var(--live-hi), var(--live));
  color: var(--on-live);
  font-family: var(--f-ui);
  font-weight: 800;
  font-size: .74rem;
  letter-spacing: .13em;
  text-transform: uppercase;
  box-shadow: 0 0 0 1px var(--live-hair), 0 10px 24px -10px var(--live-glow);
  isolation: isolate;
  overflow: hidden;
}
/* A slow shine across the pill.  --nx-sweep is registered with @property, so
   this is an animated gradient stop rather than a keyframed wrapper. */
.nx-live-pill::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent var(--nx-sweep),
    rgb(255 255 255 / .40) calc(var(--nx-sweep) + 11%),
    transparent calc(var(--nx-sweep) + 24%));
  animation: nx-sweep 5.4s var(--ease) infinite;
}
@keyframes nx-sweep { 0%, 62% { --nx-sweep: -40%; } 100% { --nx-sweep: 130%; } }
.nx-live-pill::before {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: inherit;
  background: var(--live);
  opacity: .3;
  z-index: -1;
  animation: nx-halo 2.6s var(--ease) infinite;
}
@keyframes nx-halo {
  0%, 100% { transform: scale(.94); opacity: .16; }
  50%      { transform: scale(1.1); opacity: .42; }
}
.nx-live-pill:hover { filter: brightness(1.08); }

.nx-live-wave {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  block-size: 13px;
}
.nx-live-wave i {
  inline-size: 3px;
  border-radius: 2px;
  background: currentColor;
  block-size: 40%;
  transform-origin: bottom;
  animation: nx-wave 1.05s var(--ease) infinite;
}
.nx-live-wave i:nth-child(1) { animation-delay: -.35s; }
.nx-live-wave i:nth-child(2) { animation-delay: -.7s; }
.nx-live-wave i:nth-child(3) { animation-delay: -.15s; }
@keyframes nx-wave {
  0%, 100% { block-size: 30%; }
  40%      { block-size: 100%; }
  70%      { block-size: 55%; }
}

/* --- Capsule ------------------------------------------------------------ */

.nx-capsule {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px;
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 1px solid var(--hair);
  box-shadow: var(--sh-1);
  min-inline-size: 0;
}

.nx-caplinks {
  display: flex;
  align-items: center;
  gap: 2px;
  min-inline-size: 0;
}
.nx-caplink {
  position: relative;
  padding: 8px 12px;
  border-radius: var(--r-pill);
  font-size: .855rem;
  font-weight: 600;
  color: var(--tx-2);
  white-space: nowrap;
  transition: color .18s var(--ease), background .18s var(--ease);
}
.nx-caplink::after {
  content: "";
  position: absolute;
  inset-block-end: 3px;
  inset-inline: 12px;
  block-size: 2px;
  border-radius: 2px;
  background: var(--sec-fill);
  scale: 0 1;
  transform-origin: var(--uline-origin, left);
  transition: scale .26s var(--ease-out);
}
[dir="rtl"] .nx-caplink::after { transform-origin: right; }
.nx-caplink:hover { color: var(--sec-deep); background: var(--sec-soft); }
.nx-caplink:hover::after { scale: 1 1; }

.nx-icons { display: flex; align-items: center; gap: 2px; }

.nx-ic {
  display: inline-grid;
  place-items: center;
  inline-size: 38px;
  block-size: 38px;
  border-radius: var(--r-pill);
  color: var(--tx-2);
  transition: color .18s var(--ease), background .18s var(--ease);
}
.nx-ic { color: var(--tx-3); }
.nx-ic:hover { color: var(--sec-deep); background: var(--sec-soft); }
.nx-ic-lang { display: inline-flex; align-items: center; gap: 5px; }
.nx-ic-lang b {
  font-size: .68rem;
  font-weight: 800;
  letter-spacing: .06em;
  font-family: var(--f-ui);
}

.nx-burger { display: none; }


/* ==========================================================================
   07  TICKER
   ========================================================================== */

.nx-ticker {
  position: relative;
  z-index: 20;
  border-block: 1px solid var(--hair);
  background: linear-gradient(to right, var(--live-tint), var(--paper-2) 44%, var(--paper-2));
}
.nx-ticker-in {
  inline-size: min(100% - (var(--gut) * 2), var(--wrap));
  margin-inline: auto;
  display: flex;
  align-items: stretch;
  gap: 0;
  min-inline-size: 0;
}

.nx-ticker-lbl {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding-inline: 14px;
  padding-block: 9px;
  margin-inline-end: 14px;
  background: var(--live);
  color: var(--on-live);
  font-size: .7rem;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  clip-path: polygon(0 0, 100% 0, calc(100% - 9px) 100%, 0 100%);
}
[dir="rtl"] .nx-ticker-lbl { clip-path: polygon(0 0, 100% 0, 100% 100%, 9px 100%); }

.nx-ticker-view {
  position: relative;
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 26px, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 26px, #000 calc(100% - 40px), transparent);
}

.nx-ticker-track {
  display: flex;
  align-items: center;
  inline-size: max-content;
  gap: 0;
  animation: nx-tick var(--tick-dur, 52s) linear infinite;
  will-change: transform;
}
[dir="rtl"] .nx-ticker-track { animation-name: nx-tick-rtl; }
.nx-ticker:hover .nx-ticker-track,
.nx-ticker.is-held .nx-ticker-track,
.nx-ticker:focus-within .nx-ticker-track { animation-play-state: paused; }

@keyframes nx-tick      { from { translate: 0 0; }  to { translate: -50% 0; } }
@keyframes nx-tick-rtl  { from { translate: 0 0; }  to { translate: 50% 0; } }

.nx-ticker-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding-block: 9px;
  padding-inline-end: 30px;
  font-size: .87rem;
  color: var(--tx-2);
  white-space: nowrap;
  transition: color .18s var(--ease);
}
.nx-ticker-item::after {
  content: "";
  inline-size: 4px;
  block-size: 4px;
  border-radius: 50%;
  background: var(--hair-2);
  margin-inline-start: 30px;
  margin-inline-end: -30px;
}
.nx-ticker-item:hover { color: var(--tx); }
.nx-ticker-item time {
  font-family: var(--f-num);
  font-size: .72rem;
  font-variant-numeric: tabular-nums;
  color: var(--tx-dim);
  unicode-bidi: isolate;
}

.nx-live-dot {
  inline-size: 7px;
  block-size: 7px;
  border-radius: 50%;
  background: var(--live);
  flex: none;
  box-shadow: 0 0 0 0 var(--live-glow);
  animation: nx-dot 2.2s var(--ease) infinite;
}
@keyframes nx-dot {
  0%   { box-shadow: 0 0 0 0 var(--live-glow); }
  70%  { box-shadow: 0 0 0 7px oklch(56% .21 26 / 0); }
  100% { box-shadow: 0 0 0 0 oklch(56% .21 26 / 0); }
}


/* ==========================================================================
   08  SECTION NAV
   ========================================================================== */

.nx-nav {
  position: relative;
  z-index: 15;
  border-block-end: 1px solid var(--hair);
  background: var(--surface);
}
.nx-nav-in {
  inline-size: min(100% - (var(--gut) * 2), var(--wrap));
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: clamp(2px, .5vw, 8px);
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
}
.nx-nav-in::-webkit-scrollbar { display: none; }

.nx-navlink {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 13px 12px 12px;
  font-size: .875rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--tx-3);
  white-space: nowrap;
  transition: color .18s var(--ease);
}
.nx-navlink::after {
  content: "";
  position: absolute;
  inset-inline: 8px;
  inset-block-end: 0;
  block-size: 3px;
  border-radius: 3px 3px 0 0;
  background: var(--sec-fill);
  scale: 0 1;
  transition: scale .26s var(--ease-out);
}
.nx-navlink:hover { color: var(--sec-deep); }
.nx-navlink:hover::after { scale: 1 1; }
.nx-navlink.is-on { color: var(--sec-deep); font-weight: 700; }
.nx-navlink.is-on::after { scale: 1 1; }
.nx-navlink.is-vod { color: var(--tx-2); }
.nx-navlink.is-vod:hover { color: var(--live); }
.nx-navlink.is-vod .nx-i { color: var(--live); }


/* ==========================================================================
   09  OVERLAYS — language menu, search, drawer
   ========================================================================== */

.nx-langmenu[hidden],
.nx-searchpanel[hidden],
.nx-drawer[hidden] { display: none; }

.nx-langmenu,
.nx-searchpanel,
.nx-drawer {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: color-mix(in oklab, oklch(18% .03 268) 64%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity .22s var(--ease);
}
.nx-langmenu.is-open,
.nx-searchpanel.is-open,
.nx-drawer.is-open { opacity: 1; }

/* --- language menu ------------------------------------------------------ */

.nx-langmenu { display: grid; place-items: center; padding: var(--gut); }
.nx-langmenu-in {
  inline-size: min(100%, 820px);
  max-block-size: min(84svh, 720px);
  overflow: auto;
  overscroll-behavior: contain;
  background: var(--surface);
  color: var(--tx);
  border: 1px solid var(--hair);
  border-block-start: 3px solid var(--sec-fill);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-2);
  padding: clamp(16px, 2.4vw, 28px);
  translate: 0 14px;
  scale: .985;
  transition: translate .26s var(--ease-out), scale .26s var(--ease-out);
}
.nx-langmenu.is-open .nx-langmenu-in { translate: 0 0; scale: 1; }

.nx-langmenu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: clamp(1.15rem, 1rem + .6vw, 1.5rem);
  line-height: var(--hl-lh);
  padding-block-end: 14px;
  margin-block-end: 14px;
  border-block-end: 1px solid var(--hair);
}

.nx-langgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 6px;
}
.nx-langopt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  min-block-size: 44px;
  border-radius: var(--r-m);
  border: 1px solid transparent;
  color: var(--tx-2);
  transition: background .16s var(--ease), color .16s var(--ease);
}
/* render.php puts dir="rtl" on the Hebrew/Arabic options so the native name
   shapes correctly.  Left alone that also flips the row, so half the grid put
   its code on the left and half on the right.  The row follows the PAGE
   direction; only the name gets its own bidi context. */
.nx-langopt { direction: inherit; }
.nx-langopt b { font-weight: 600; font-size: .95rem; unicode-bidi: plaintext; }
.nx-langopt span {
  font-family: var(--f-num);
  font-size: .68rem;
  letter-spacing: .08em;
  color: var(--tx-dim);
}
.nx-langopt:hover { background: var(--sec-soft); color: var(--sec-deep); }
.nx-langopt.is-on {
  background: var(--sec-soft);
  border-color: var(--sec-hair);
  color: var(--tx);
}
.nx-langopt.is-on span { color: var(--sec-deep); }

/* --- search ------------------------------------------------------------- */

.nx-searchpanel { align-content: start; display: grid; }
.nx-searchform {
  inline-size: min(100% - (var(--gut) * 2), 900px);
  margin: clamp(60px, 16vh, 180px) auto 0;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: clamp(10px, 1.6vw, 16px) clamp(14px, 2vw, 22px);
  background: var(--surface);
  color: var(--tx);
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-2), 0 0 0 6px var(--sec-soft);
  translate: 0 -18px;
  transition: translate .26s var(--ease-out);
}
.nx-searchpanel.is-open .nx-searchform { translate: 0 0; }
.nx-searchform > .nx-i { color: var(--sec-deep); }
.nx-searchform input {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: clamp(1.15rem, 1rem + 1.1vw, 1.9rem);
  line-height: 1.4;
  padding-block: 6px;
}
.nx-searchform input::placeholder { color: var(--tx-dim); }
.nx-searchform input::-webkit-search-cancel-button { display: none; }

/* --- drawer ------------------------------------------------------------- */

.nx-drawer-in {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: min(88vw, 360px);
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 16px 14px calc(24px + env(safe-area-inset-bottom));
  background: var(--surface);
  color: var(--tx);
  border-inline-end: 1px solid var(--hair);
  box-shadow: var(--sh-2);
  translate: -100% 0;
  transition: translate .3s var(--ease-out);
}
[dir="rtl"] .nx-drawer-in { translate: 100% 0; }
.nx-drawer.is-open .nx-drawer-in { translate: 0 0; }

.nx-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-block-end: 14px;
  margin-block-end: 10px;
  border-block-end: 1px solid var(--hair);
}
.nx-drawer-head svg { block-size: 26px; inline-size: auto; }

.nx-drawer-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 12px;
  min-block-size: 46px;
  border-radius: var(--r-m);
  font-size: 1rem;
  font-weight: 600;
  color: var(--tx-2);
  text-align: start;
  transition: background .16s var(--ease), color .16s var(--ease);
}
.nx-drawer-link .nx-i { color: var(--sec-fill); }
.nx-drawer-link b {
  margin-inline-start: auto;
  font-weight: 500;
  font-size: .82rem;
  color: var(--tx-dim);
}
.nx-drawer-link:hover { background: var(--sec-soft); color: var(--sec-deep); }
.nx-drawer-sep {
  block-size: 1px;
  background: var(--hair);
  margin-block: 10px;
}


/* ==========================================================================
   10  CARDS
   ========================================================================== */

.nx-card {
  position: relative;
  min-inline-size: 0;
  --card-bg: var(--surface);
  /* Every card is a container, so the rules in section 20 can size a card
     from the width of the SLOT it landed in — hero, rail or sidebar — rather
     than from the viewport, which knows nothing about any of them. */
  container-type: inline-size;
  container-name: card;
}

.nx-card-link {
  /* A grid row is as tall as its tallest card, and every card in that row is
     stretched to match.  As a plain block the extra height fell through to the
     bottom of the card as a band of bare panel — the hole visible under short
     headlines.  As a flex column the body absorbs it instead, and the meta line
     lands on the baseline shared by the whole row.
     Cards whose body overlays the image (hero, lead) position it absolutely,
     so they are out of this flow and unaffected. */
  display: flex;
  flex-direction: column;
  block-size: 100%;
  border-radius: var(--r-l);
  overflow: hidden;
  background: var(--card-bg);
  /* Explicit, never inherited: a white panel that takes its colour from a
     dark ancestor is a panel with invisible type in it. */
  color: var(--tx);
  border: 1px solid var(--hair);
  box-shadow: var(--sh-1);
  transition: transform .34s var(--ease-out), box-shadow .34s var(--ease-out),
              border-color .34s var(--ease-out);
}
.nx-card-link:focus-visible { outline-offset: 4px; }

.nx-card-media {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  background: linear-gradient(140deg, var(--sec-chip), var(--sec-tint2));
  /* The house treatment for photography lives in section 20 and hangs off
     this element; the isolation is what lets it blend against the picture
     without reaching the card behind it. */
  isolation: isolate;
}
.nx-card-media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform .7s var(--ease-out), filter .5s var(--ease);
  transform-origin: 50% 45%;
}

/* The scrim is one element carrying two gradients: a vertical wash plus a
   soft radial from the corner the reader starts at (mirrors under RTL). */
.nx-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to top, var(--scrim-1) 0%, var(--scrim-2) 34%, var(--scrim-3) 62%, transparent 100%),
    radial-gradient(120% 110% at var(--scrim-x, 6%) 108%, var(--scrim-1), transparent 62%);
}
[dir="rtl"] .nx-scrim { --scrim-x: 94%; }

.nx-card-body {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;          /* take the row's spare height instead of leaving a hole */
  gap: var(--card-gap);
  padding: var(--card-pad);
}

/* The timestamp sits at the foot of the card, so a row of cards shares one
   baseline however long each headline runs. */
.nx-card:not(.is-hero):not(.is-lead) .nx-card-body > .nx-meta {
  margin-block-start: auto;
  padding-block-start: 2px;
}

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

.nx-kicker {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-block-size: 20px;
}
/* The kicker is where the desk's colour actually lands on a card: a solid
   block of it, with --sec-on over the top.  Filled rather than outlined
   because eleven outlined chips on one page read as eleven grey chips.
   Measured across the eleven hues: 5.45:1 to 6.17:1 in light, 5.9 to 6.6 in
   dark, which is the whole point of holding one OKLCH lightness. */
.nx-kick-sec {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: var(--r-s);
  border: 1px solid transparent;
  color: var(--sec-on);
  background: var(--sec-fill);
  font-family: var(--f-ui);
  font-size: var(--t-kick);
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  line-height: 1.5;
  transition: background .22s var(--ease), color .22s var(--ease),
              box-shadow .22s var(--ease);
}

.nx-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--r-s);
  font-family: var(--f-ui);
  font-size: var(--t-kick);
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  line-height: 1.5;
}
.nx-badge.is-breaking {
  background: var(--live);
  color: var(--on-live);
  box-shadow: 0 6px 16px -9px var(--live-glow);
}
.nx-badge.is-live {
  background: var(--live-tint);
  border: 1px solid var(--live-hair);
  color: var(--live);
}
.nx-badge.is-live .nx-live-dot { inline-size: 6px; block-size: 6px; }

/* --- headline and dek --------------------------------------------------- */

.nx-hl {
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: var(--t-tile);
  line-height: var(--hl-lh);
  letter-spacing: -.016em;
  color: var(--tx);
  text-wrap: balance;
  margin: 0;
}
:root[data-script="hebrew"] .nx-hl,
:root[data-script="arabic"] .nx-hl,
:root[data-script="thai"] .nx-hl,
:root[data-script="tamil"] .nx-hl { letter-spacing: 0; }

.nx-dek {
  font-size: var(--t-dek);
  line-height: 1.58;
  color: var(--tx-2);
  text-wrap: pretty;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

.nx-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-block-start: auto;
  padding-block-start: 2px;
  font-size: var(--t-meta);
  color: var(--tx-dim);
}
.nx-time {
  font-family: var(--f-num);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
  unicode-bidi: isolate;
}
.nx-src { color: var(--tx-dim); font-weight: 600; }
.nx-src::before { content: ""; }

/* --- video affordances -------------------------------------------------- */

.nx-play {
  position: absolute;
  inset-block-end: 12px;
  inset-inline-start: 12px;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  border-radius: 50%;
  background: rgb(10 12 20 / .58);
  border: 1px solid rgb(255 255 255 / .34);
  color: #fff;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background .24s var(--ease), scale .24s var(--ease-out);
}
[dir="rtl"] .nx-play .nx-i { transform: scaleX(-1); }
.nx-dur {
  position: absolute;
  inset-block-end: 12px;
  inset-inline-end: 12px;
  padding: 3px 7px;
  border-radius: var(--r-s);
  background: rgb(6 7 12 / .8);
  color: #fff;
  font-family: var(--f-num);
  font-size: .72rem;
  font-variant-numeric: tabular-nums;
}

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

@media (hover: hover) and (pointer: fine) {
  .nx-card:hover .nx-card-link {
    transform: translateY(-5px);
    border-color: var(--sec-hair);
    box-shadow: var(--sh-hot);
  }
  .nx-card:hover .nx-card-media img { transform: scale(1.045); }
  .nx-card:hover .nx-kick-sec {
    background: var(--sec-base);
    box-shadow: 0 6px 16px -8px var(--sec-glow);
  }
  .nx-card:hover .nx-play { background: var(--live); border-color: var(--live-hi); scale: 1.06; }
  .nx-card:hover .nx-hl { color: var(--sec-deep); }
  .nx-card.is-hero:hover .nx-hl { color: var(--on-img); }
}
.nx-card:focus-within .nx-card-link { border-color: var(--sec-hair); }

/* --- variant: hero ------------------------------------------------------ */

/* The media and the body share one grid cell.  Absolute positioning looked
   right until a four-line headline on a phone grew taller than a 4:3 image and
   was clipped off the top — with grid the row simply takes the taller of the
   two and the photo stretches to meet it. */
.nx-card.is-hero .nx-card-link {
  position: relative;
  display: grid;
  grid-template-areas: "hero";
  border-radius: var(--r-xl);
  border-color: transparent;
  box-shadow: var(--sh-2);
}
.nx-card.is-hero .nx-card-media {
  grid-area: hero;
  aspect-ratio: 16 / 9;
  min-block-size: 0;
}
.nx-card.is-hero .nx-card-media img { block-size: 100%; }
.nx-card.is-hero .nx-scrim {
  background:
    linear-gradient(to top, var(--scrim-1) 2%, var(--scrim-2) 28%, var(--scrim-3) 54%, transparent 78%),
    radial-gradient(90% 120% at var(--scrim-x, 2%) 106%, var(--scrim-1), transparent 60%);
}
.nx-card.is-hero .nx-card-body {
  grid-area: hero;
  align-self: end;
  gap: 12px;
  padding: clamp(18px, 3.4vw, 52px);
  padding-block-start: clamp(24px, 4vw, 60px);
  inline-size: min(100%, 940px);
}
/* The hairline that separates the scrim from the type. */
.nx-card.is-hero .nx-card-body::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: clamp(18px, 3.4vw, 52px);
  inline-size: clamp(70px, 12vw, 160px);
  block-size: 3px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--sec-onimg), transparent);
}
[dir="rtl"] .nx-card.is-hero .nx-card-body::before {
  background: linear-gradient(270deg, var(--sec-onimg), transparent);
}
.nx-card.is-hero .nx-hl {
  font-size: var(--t-hero);
  letter-spacing: -.028em;
  color: var(--on-img);
  text-shadow: 0 2px 30px rgb(0 0 0 / .6), 0 1px 3px rgb(0 0 0 / .78);
}
.nx-card.is-hero .nx-dek {
  font-size: clamp(.98rem, .9rem + .5vw, 1.24rem);
  color: var(--on-img-2);
  max-inline-size: 62ch;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  text-shadow: 0 1px 14px rgb(0 0 0 / .7);
}
.nx-card.is-hero .nx-meta { color: var(--on-img-3); }
/* --sec-on, not #fff.  The hero chip sits on a photograph, so white LOOKS
   like the right answer — but the chip has its own fill under it, and in dark
   that fill is the light end of the ramp.  Hardcoding white here measured
   2.94:1 on the economy desk while every other chip on the page measured six. */
.nx-card.is-hero .nx-kick-sec {
  background: var(--sec-fill);
  color: var(--sec-on);
  box-shadow: 0 4px 14px -6px rgb(0 0 0 / .6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.nx-card.is-hero .nx-play { inline-size: 62px; block-size: 62px; inset-block-end: auto; inset-inline-start: auto; }

/* --- variant: lead ------------------------------------------------------ */

.nx-card.is-lead .nx-card-link { position: relative; }
.nx-card.is-lead .nx-card-media { aspect-ratio: 16 / 9; }
.nx-card.is-lead .nx-hl { font-size: var(--t-lead); letter-spacing: -.024em; }
.nx-card.is-lead .nx-card-body { gap: 10px; padding: clamp(15px, 1.7vw, 26px); }
.nx-card.is-lead .nx-dek { -webkit-line-clamp: 3; line-clamp: 3; }

/* --- variant: wide ------------------------------------------------------ */

.nx-card.is-wide .nx-hl { font-size: var(--t-wide); letter-spacing: -.02em; }
.nx-card.is-wide .nx-dek { -webkit-line-clamp: 2; line-clamp: 2; }

/* --- variant: tile ------------------------------------------------------ */

.nx-card.is-tile .nx-hl { font-size: var(--t-tile); }
.nx-card.is-tile .nx-dek { -webkit-line-clamp: 2; line-clamp: 2; }

/* --- variant: list ------------------------------------------------------ */

.nx-card.is-list .nx-card-link {
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  border-block-end: 1px solid var(--hair);
}
.nx-card.is-list .nx-card-body { padding: 13px 4px 14px; gap: 6px; }
.nx-card.is-list .nx-hl { font-size: var(--t-list); letter-spacing: -.012em; }
.nx-card.is-list:last-child .nx-card-link { border-block-end: 0; }
@media (hover: hover) and (pointer: fine) {
  .nx-card.is-list:hover .nx-card-link {
    transform: none;
    box-shadow: none;
    background: linear-gradient(90deg, var(--sec-soft), transparent 70%);
  }
  .nx-card.is-list:hover .nx-hl,
  .nx-card.is-mini:hover .nx-hl { color: var(--sec-deep); }
  [dir="rtl"] .nx-card.is-list:hover .nx-card-link {
    background: linear-gradient(270deg, var(--sec-soft), transparent 70%);
  }
}

/* --- variant: mini ------------------------------------------------------ */

.nx-card.is-mini .nx-card-link {
  border: 0;
  background: none;
  box-shadow: none;
  border-radius: var(--r-m);
  /* .nx-card-link clips by default for the image zoom; the ghost numeral is
     deliberately outside it, so mini and list opt out. */
  overflow: visible;
}
.nx-card.is-list .nx-card-link { overflow: visible; }
.nx-card.is-mini .nx-card-body { padding: 9px 4px; gap: 4px; }
.nx-card.is-mini .nx-hl { font-size: var(--t-mini); font-weight: 600; letter-spacing: 0; }
.nx-card.is-mini .nx-kicker { min-block-size: 0; }
/* At mini size a filled block would be a stamp on a one-line headline; the
   desk still reads, as a word in its own colour. */
.nx-card.is-mini .nx-kick-sec {
  padding: 1px 0;
  font-size: .64rem;
  background: none;
  color: var(--sec-deep);
  box-shadow: none;
}
.nx-card.is-mini:hover .nx-kick-sec { background: none; color: var(--sec-fill); }

/* --- variant: vod ------------------------------------------------------- */

.nx-card.is-vod .nx-card-media { aspect-ratio: 16 / 9; }
.nx-card.is-vod .nx-card-link { background: var(--surface-2); }
.nx-card.is-vod .nx-hl { font-size: var(--t-tile); }
.nx-card.is-vod .nx-play { opacity: 1; }

/* --- variant: opinion --------------------------------------------------- */

.nx-card.is-opinion .nx-card-link {
  background: linear-gradient(180deg, var(--sec-chip), var(--surface) 70%);
  border-color: var(--sec-hair);
}
.nx-card.is-opinion .nx-hl { font-style: italic; }
.nx-card.is-opinion .nx-kick-sec::before {
  content: "";
  inline-size: 5px;
  block-size: 5px;
  border-radius: 50%;
  background: currentColor;
  margin-inline-end: 6px;
}

/* --- procedural art vs. wire photo -------------------------------------- */

/* The grade, and only the grade — the tinting, the scrim and the masks are
   the treatment system in section 20, because they apply to the article hero
   and the topic art as well as to a card. */
.nx-card.has-photo .nx-card-media img { filter: var(--photo-grade); }
.nx-card.has-art .nx-card-media { background: var(--sec-chip); }


/* ==========================================================================
   11  SECTION HEADS AND RAILS
   ========================================================================== */

.nx-sect { display: block; margin-block-start: var(--rowgap); }
.nx-sect:first-child { margin-block-start: 0; }

/* The desk's nameplate.  A hairline under a grey word was the old version;
   this one is a rule in the section colour with the title sitting on it, so
   a reader scrolling past a nine-desk front page can tell where they are
   from the colour alone. */
.nx-sect-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-block-end: clamp(12px, 1.6vw, 22px);
  padding-block-end: 10px;
  border-block-end: 2px solid var(--sec-fill);
}

.nx-sect-title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: var(--t-sect);
  line-height: var(--hl-lh);
  letter-spacing: -.02em;
  color: var(--tx);
}
.nx-sect-title::before {
  content: "";
  inline-size: 12px;
  block-size: 12px;
  border-radius: 3px;
  background: var(--sec-fill);
  box-shadow: 0 0 0 4px var(--sec-soft);
  flex: none;
}

.nx-more {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
  padding: 6px 4px;
  font-size: .82rem;
  font-weight: 600;
  color: var(--sec-1);
  transition: gap .2s var(--ease), color .2s var(--ease);
}
.nx-more .nx-i { transition: transform .2s var(--ease); }
[dir="rtl"] .nx-more .nx-i { transform: scaleX(-1); }
.nx-more { color: var(--sec-deep); }
.nx-more:hover { gap: 9px; color: var(--sec-fill); }

/* --- horizontal rail ---------------------------------------------------- */

.nx-rowscroll { position: relative; }

.nx-rowscroll-in {
  display: flex;
  gap: var(--gap);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  overscroll-behavior-inline: contain;
  scrollbar-width: none;
  padding-block: 4px 12px;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
}
.nx-rowscroll-in::-webkit-scrollbar { display: none; }

.nx-rowscroll-in > .nx-card {
  flex: 0 0 clamp(232px, 24vw, 320px);
  scroll-snap-align: start;
}
.nx-rowscroll-in > .nx-card.is-wide { flex-basis: clamp(300px, 34vw, 460px); }
.nx-rowscroll-in > .nx-card.is-vod  { flex-basis: clamp(250px, 26vw, 360px); }
.nx-rowscroll-in > .nx-card.is-mini,
.nx-rowscroll-in > .nx-card.is-list { flex-basis: clamp(210px, 22vw, 280px); }

.nx-rowbtn {
  position: absolute;
  inset-block-start: 50%;
  z-index: 5;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  translate: 0 -50%;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--hair-2);
  color: var(--tx);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: var(--sh-1);
  opacity: 0;
  transition: opacity .22s var(--ease), background .22s var(--ease), scale .22s var(--ease-out);
}
.nx-rowbtn.is-prev { inset-inline-start: -6px; }
.nx-rowbtn.is-next { inset-inline-end: -6px; }
/* The chev glyph points inline-end; prev must point back, in either direction. */
.nx-rowbtn.is-prev .nx-i { transform: scaleX(-1); }
[dir="rtl"] .nx-rowbtn.is-prev .nx-i { transform: none; }
[dir="rtl"] .nx-rowbtn.is-next .nx-i { transform: scaleX(-1); }

.nx-rowscroll:hover .nx-rowbtn,
.nx-rowscroll:focus-within .nx-rowbtn { opacity: 1; }
.nx-rowbtn:hover { background: var(--sec-fill); color: var(--sec-on); border-color: var(--sec-fill); scale: 1.06; }
.nx-rowbtn:focus-visible { opacity: 1; }
.nx-rowbtn[disabled] { opacity: 0 !important; pointer-events: none; }

@media (hover: none) {
  .nx-rowbtn { display: none; }
  .nx-rowscroll-in { padding-inline-end: var(--gut); }
}


/* ==========================================================================
   12  LIVE COLUMN
   ========================================================================== */

.nx-live {
  display: block;
  border-radius: var(--r-l);
  border: 1px solid var(--hair);
  background: var(--surface);
  color: var(--tx);
  box-shadow: var(--sh-1);
  overflow: hidden;
  position: sticky;
  inset-block-start: calc(var(--top-h) + 14px);
}

.nx-live-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 14px 16px;
  background: var(--live);
  font-family: var(--f-ui);
  font-weight: 800;
  font-size: .8rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--on-live);
}
.nx-live-head .nx-live-dot { background: var(--on-live); box-shadow: none; animation: none; }
.nx-live-head .nx-more {
  margin-inline-start: auto;
  letter-spacing: .02em;
  text-transform: none;
  color: var(--on-live);
  opacity: .88;
}
.nx-live-head .nx-more:hover { color: var(--on-live); opacity: 1; }

.nx-live-body {
  display: flex;
  flex-direction: column;
  max-block-size: min(62svh, 640px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--hair-2) transparent;
}

.nx-live-item {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 12px;
  padding: 12px 16px 12px 16px;
  padding-inline: 16px;
  border-block-end: 1px solid var(--hair);
  transition: background .18s var(--ease);
}
/* Timeline rail behind the timestamps. */
.nx-live-item::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 55px;
  inline-size: 1px;
  background: var(--hair);
}
.nx-live-item::after {
  content: "";
  position: absolute;
  inset-block-start: 17px;
  inset-inline-start: 52px;
  inline-size: 7px;
  block-size: 7px;
  border-radius: 50%;
  background: var(--hair-2);
  border: 2px solid var(--surface);
  transition: background .18s var(--ease), scale .18s var(--ease-out);
}
.nx-live-item:hover { background: var(--sec-soft); }
.nx-live-item:hover::after { background: var(--sec-fill); scale: 1.25; }
.nx-live-item:last-child { border-block-end: 0; }

.nx-live-time {
  font-family: var(--f-num);
  font-size: .74rem;
  font-variant-numeric: tabular-nums;
  color: var(--tx-dim);
  padding-block-start: 2px;
  inline-size: 38px;
}
.nx-live-txt2 {
  font-size: .92rem;
  line-height: 1.5;
  color: var(--tx-2);
  padding-inline-start: 14px;
}
.nx-live-item:hover .nx-live-txt2 { color: var(--tx); }

.nx-live-item.is-alert .nx-live-txt2 { color: var(--tx); font-weight: 600; }
.nx-live-item.is-alert::after { background: var(--live); box-shadow: 0 0 12px var(--live-glow); }
.nx-live-item.is-alert {
  background: linear-gradient(90deg, var(--live-tint), transparent 62%);
}
[dir="rtl"] .nx-live-item.is-alert {
  background: linear-gradient(270deg, var(--live-tint), transparent 62%);
}

/* Flashes injected by the poller arrive with this class for one beat. */
.nx-live-item.is-new { animation: nx-flash-in .6s var(--ease-out) both; }
@keyframes nx-flash-in {
  from { opacity: 0; translate: 0 -10px; background: var(--sec-soft); }
  to   { opacity: 1; translate: 0 0; }
}


/* ==========================================================================
   13  MOST READ
   ========================================================================== */

.nx-numlist {
  display: grid;
  gap: 2px;
  counter-reset: nx;
}
.nx-numlist > .nx-card { padding-inline-start: var(--rank-w); --rank-w: clamp(46px, 4vw, 58px); }
.nx-numlist > .nx-card + .nx-card { border-block-start: 1px solid var(--hair); }

/* The oversized ghost numeral, bleeding out of the card's inline-start edge. */
/* .nx-card-body is position:relative, so it — not .nx-card — is this box's
   containing block; the numeral has to be pulled back out over the gutter. */
.nx-rank {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: calc(var(--rank-w, 56px) * -1);
  translate: 0 -50%;
  z-index: 0;
  font-family: var(--f-num);
  inline-size: var(--rank-w, 56px);
  text-align: center;
  font-size: clamp(2.5rem, 3.4vw, 3.7rem);
  font-weight: 800;
  line-height: .8;
  letter-spacing: -.05em;
  /* Solid, in the desk's colour.  An outlined ghost numeral needs a dark
     ground to read against; on paper it just looks unfinished. */
  color: var(--sec-fill);
  -webkit-text-stroke: 0;
  opacity: .92;
  pointer-events: none;
  unicode-bidi: isolate;
  transition: color .3s var(--ease), opacity .3s var(--ease);
}
.nx-numlist > .nx-card:hover .nx-rank { color: var(--sec-deep); opacity: 1; }


/* Share button acknowledgement (nx.js toggles .is-done for ~1.8s). */
[data-nx="share"] { position: relative; }
[data-nx="share"].is-done { color: var(--sec-deep); }
[data-nx="share"].is-done::after {
  content: attr(data-done);
  position: absolute;
  inset-block-end: calc(100% + 8px);
  inset-inline-start: 50%;
  translate: -50% 0;
  padding: 5px 10px;
  border-radius: var(--r-s);
  background: var(--surface-3);
  color: var(--tx);
  border: 1px solid var(--hair-2);
  box-shadow: var(--sh-1);
  font-size: .74rem;
  white-space: nowrap;
  pointer-events: none;
}


/* ==========================================================================
   14  ARTICLE PROSE  (defensive — article.php is another agent's file)
   ========================================================================== */

.nx-article, .nx-body, .nx-prose {
  font-size: clamp(1.02rem, .97rem + .3vw, 1.16rem);
  line-height: var(--body-lh);
  color: var(--tx-2);
  max-inline-size: 74ch;
}
.nx-article p, .nx-body p, .nx-prose p { margin-block: 0 1.15em; }
.nx-article h2, .nx-body h2, .nx-prose h2,
.nx-article h3, .nx-body h3, .nx-prose h3 {
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  line-height: var(--hl-lh);
  letter-spacing: -.02em;
  color: var(--tx);
  margin-block: 1.7em .5em;
  text-wrap: balance;
}
.nx-article h2, .nx-body h2, .nx-prose h2 { font-size: calc(1.5rem * var(--hl-scale)); }
.nx-article h3, .nx-body h3, .nx-prose h3 { font-size: calc(1.2rem * var(--hl-scale)); }
.nx-article a, .nx-body a, .nx-prose a {
  color: var(--sec-deep);
  text-decoration: underline;
  text-decoration-color: var(--sec-hair);
  text-underline-offset: 3px;
}
.nx-article a:hover, .nx-body a:hover, .nx-prose a:hover { text-decoration-color: currentColor; }
.nx-article blockquote, .nx-body blockquote, .nx-prose blockquote {
  margin-block: 1.6em;
  padding-inline-start: clamp(16px, 2vw, 26px);
  border-inline-start: 3px solid var(--sec-fill);
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-size: calc(1.28rem * var(--hl-scale));
  line-height: 1.44;
  color: var(--tx);
}
.nx-article ul, .nx-body ul, .nx-prose ul { margin-block: 0 1.15em; padding-inline-start: 1.1em; list-style: disc; }
.nx-article li, .nx-body li, .nx-prose li { margin-block-end: .45em; }


/* ==========================================================================
   15  FOOTER
   ========================================================================== */

/* An ink slab under a paper page.  It gives the front page a floor, and it
   is the one surface whose polarity is opposite to the page it sits on — so
   the WHOLE derived ramp is restated here rather than inherited.  Inheriting
   would leave near-black type on near-black ground, which is the exact
   failure this sheet is written to avoid. */
.nx-foot {
  position: relative;
  z-index: 1;
  margin-block-start: clamp(40px, 6vw, 90px);

  /* Literal on BOTH sides.  `--paper: light-dark(x, var(--paper))` reads as
     "keep the page value in dark mode" and is in fact a self-reference: a
     custom property whose value contains var(--itself) is invalid at
     computed-value time, which takes --tx-2/-3/-dim and both hairlines down
     with it because they are mixed from it. */
  --surface: light-dark(oklch(23% .024 266), oklch(21.5% .016 266));
  --paper:   light-dark(oklch(19% .024 266), oklch(15.5% .014 266));
  --paper-2: light-dark(oklch(22% .024 266), oklch(18.5% .016 266));
  --tx:      light-dark(oklch(96% .008 84), oklch(95.5% .008 84));
  --tx-2:    color-mix(in oklab, var(--tx) 78%, var(--surface));
  --tx-3:    color-mix(in oklab, var(--tx) 66%, var(--surface));
  --tx-dim:  color-mix(in oklab, var(--tx) 64%, var(--surface));
  --hair:    color-mix(in oklab, var(--tx) 13%, transparent);
  --hair-2:  color-mix(in oklab, var(--tx) 22%, transparent);
  /* On ink the readable tone of the section colour is the bright one. */
  --sec-1:   var(--sec-onimg);
  --sec-deep: var(--sec-onimg);

  border-block-start: 3px solid var(--sec-fill);
  background: var(--paper);
  color: var(--tx);
}
.nx-foot .nx-mark text { fill: var(--tx); }
.nx-foot-in {
  inline-size: min(100% - (var(--gut) * 2), var(--wrap));
  margin-inline: auto;
  padding-block: clamp(30px, 4vw, 56px) clamp(24px, 3vw, 40px);
  display: grid;
  gap: clamp(24px, 3vw, 44px);
  grid-template-columns: minmax(220px, 1fr) minmax(0, 2.2fr);
}
.nx-foot-brand svg { block-size: 30px; inline-size: auto; }
.nx-foot-brand p {
  margin-block-start: 12px;
  color: var(--tx-3);
  font-size: .9rem;
  max-inline-size: 30ch;
}
.nx-foot-cols {
  display: grid;
  gap: clamp(18px, 2.4vw, 34px);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.nx-foot-cols h4 {
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--sec-onimg);
  margin-block-end: 12px;
}
.nx-foot-cols a {
  display: block;
  padding-block: 5px;
  font-size: .88rem;
  color: var(--tx-3);
  transition: color .16s var(--ease);
}
.nx-foot-cols a:hover { color: var(--tx); }
.nx-foot-langs { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.nx-foot-langs a { padding-block: 4px; }
.nx-foot-more { color: var(--sec-onimg) !important; font-weight: 700; }
.nx-foot-legal {
  grid-column: 1 / -1;
  padding-block-start: clamp(18px, 2.4vw, 30px);
  border-block-start: 1px solid var(--hair);
  color: var(--tx-dim);
  font-size: .8rem;
  line-height: 1.7;
  max-inline-size: 100ch;
}


/* ==========================================================================
   16  MOTION
   ========================================================================== */

/* nx.js adds .nx-rv (hides) then .is-in (reveals). Without JS nothing is
   hidden — that is deliberate. */
.nx-rv {
  opacity: 0;
  translate: 0 16px;
  transition: opacity .55s var(--ease-out), translate .55s var(--ease-out);
  transition-delay: var(--rv-d, 0ms);
}
.nx-rv.is-in { opacity: 1; translate: 0 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .nx-rv, .nx-rv.is-in { opacity: 1; translate: none; }

  /* The marquee becomes a plain scrollable list rather than a frozen one. */
  .nx-ticker-track {
    animation: none;
    inline-size: auto;
    translate: none;
  }
  .nx-ticker-view {
    overflow-x: auto;
    scrollbar-width: thin;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .nx-live-pill::before { display: none; }
  .nx-live-wave i { block-size: 60%; }
  body.nx::before { animation: none; }
}


/* ==========================================================================
   17  RESPONSIVE
   ========================================================================== */

@media screen and (max-width: 1180px) {
  :root { --wrap: 1100px; }
  .nx-caplink { padding-inline: 9px; font-size: .82rem; }
  .nx-caplinks > .nx-caplink:nth-child(n + 5) { display: none; }
}

@media screen and (max-width: 980px) {
  :root { --top-h: 62px; }

  /* Rails collapse under the main column. */
  .nx-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .nx-grid.is-main-rail { grid-template-columns: minmax(0, 1fr); }
  .nx-grid > .nx-card.is-lead,
  .nx-grid > .nx-card.is-wide { grid-column: span 6; }
  .nx-grid > .nx-card.is-tile,
  .nx-grid > .nx-card.is-vod  { grid-column: span 3; }
  .nx-grid > .nx-card.is-list,
  .nx-grid > .nx-card.is-mini { grid-column: span 3; }
  .nx-grid > .nx-live,
  .nx-grid > .nx-col  { grid-column: span 6; }

  .nx-live { position: static; max-block-size: none; }
  .nx-live-body { max-block-size: 420px; }

  .nx-foot-in { grid-template-columns: minmax(0, 1fr); }
}

@media screen and (max-width: 760px) {
  :root { --top-h: 58px; --wrap: 100%; }

  .nx-capsule { display: none; }
  .nx-nav { display: none; }
  .nx-burger {
    display: grid;
    place-items: center;
    inline-size: 44px;
    block-size: 44px;
    margin-inline-start: auto;
    border-radius: var(--r-pill);
    color: var(--tx);
  }
  .nx-burger:hover { background: var(--sec-soft); color: var(--sec-deep); }
  .nx-live-pill { order: 0; margin-inline-start: auto; padding-inline: 10px 12px; font-size: .68rem; }
  .nx-brand svg { block-size: 24px; }

  .nx-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
  .nx-grid > .nx-card.is-hero,
  .nx-grid > .nx-card.is-lead,
  .nx-grid > .nx-card.is-wide,
  .nx-grid > .nx-sect,
  .nx-grid > .nx-numlist,
  .nx-grid > .nx-col,
  .nx-grid > .nx-live { grid-column: span 2; }
  .nx-grid > .nx-card.is-tile,
  .nx-grid > .nx-card.is-vod,
  .nx-grid > .nx-card.is-list,
  .nx-grid > .nx-card.is-mini { grid-column: span 1; }

  /* Hero goes 4:3 — a 16:9 hero on a phone is a letterbox with no room for
     the headline that lives inside it. */
  .nx-card.is-hero .nx-card-media { aspect-ratio: 4 / 3; }
  .nx-card.is-hero .nx-card-body { inline-size: 100%; padding: 18px 16px 20px; }
  .nx-card.is-hero .nx-hl { text-wrap: pretty; }
  .nx-card.is-hero .nx-dek { -webkit-line-clamp: 2; line-clamp: 2; }

  .nx-ticker-lbl { padding-inline: 10px; font-size: .64rem; }

  .nx-rowscroll-in > .nx-card { flex-basis: min(74vw, 300px); }
  .nx-rowscroll-in > .nx-card.is-wide { flex-basis: min(86vw, 360px); }

  .nx-searchform { margin-block-start: 74px; border-radius: var(--r-l); }
  .nx-langgrid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }

  /* Touch targets. */
  .nx-ic, .nx-rowbtn, .nx-drawer-link, .nx-langopt { min-block-size: 44px; }
}

@media screen and (max-width: 480px) {
  .nx-grid { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .nx-grid > .nx-card,
  .nx-grid > .nx-col { grid-column: span 1 !important; }
  .nx-card.is-tile .nx-card-media,
  .nx-card.is-vod .nx-card-media { aspect-ratio: 16 / 9; }
  /* Below 480 a 4:3 hero leaves ~50px of photo above the headline block; a
     square one gives the picture back its half of the card. */
  .nx-card.is-hero .nx-card-media { aspect-ratio: 1 / 1; }
  .nx-numlist > .nx-card { --rank-w: 44px; }
  .nx-rank { font-size: 2.3rem; }
  .nx-live-item::before { inset-inline-start: 50px; }
  .nx-live-item::after { inset-inline-start: 47px; }
}

@media screen and (max-width: 380px) {
  :root { --gut: 12px; }
  .nx-brand svg { block-size: 21px; }
  .nx-live-pill .nx-live-txt { font-size: .64rem; }
  .nx-card.is-hero .nx-card-body { padding: 14px 13px 16px; }
}


/* ==========================================================================
   18  PRINT AND FORCED COLOURS
   ========================================================================== */

@media print {
  body.nx { background: #fff; color: #000; }
  .nx-kick-sec { background: none !important; color: #000 !important; border: 1px solid #999; }
  body.nx::before, body.nx::after,
  .nx-top, .nx-ticker, .nx-nav, .nx-drawer, .nx-langmenu, .nx-searchpanel,
  .nx-rowbtn, .nx-foot { display: none !important; }
  .nx-card-link { border-color: #ccc; box-shadow: none; }
  .nx-hl, .nx-dek { color: #000; }
}

@media (forced-colors: active) {
  .nx-card-link { border: 1px solid CanvasText; }
  .nx-scrim { display: none; }
  .nx-rowbtn, .nx-ic { border: 1px solid CanvasText; }
}


/* ==========================================================================
   19  PAGE SKELETONS
   ========================================================================== */

/* The containers index/article/section/live/vod/search/about/404 emit.  Section
   10 draws the cards; this section is the furniture they sit in.

   Three rules govern everything below and each one has a reason:
     - Direction is expressed with logical properties and grid `order`.  A
       front page that is RTL half the time cannot own a single `left`.
     - These rules come after section 17, so an unqualified rule here would
       silently beat a responsive rule there.  Every skeleton that changes at a
       breakpoint therefore carries its own override in 19.11 — nothing here
       relies on a media query further up the file.
     - Nothing may be wider than its container.  Wide things scroll inside
       themselves; the page never does. */


/* --- 19.1  grid hints ---------------------------------------------------- */

/* .nx-grid is 12 columns; the page author asks for a tile count instead of a
   span, which is the thing they actually mean.  is-2 = 2 across (span 6),
   is-3 = 3 (span 4), is-4 = 4 (span 3), is-6 = 6 (span 2).  Declaring the
   track count rather than the span keeps a short last row from stretching. */
.nx-grid.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.nx-grid.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.nx-grid.is-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.nx-grid.is-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }

/* The span defaults in section 05 are written for the bare 12-column grid and
   would drop a tile into the wrong track here. */
.nx-grid.is-2 > *, .nx-grid.is-3 > *, .nx-grid.is-4 > *, .nx-grid.is-6 > *,
.nx-grid.is-2 > .nx-card, .nx-grid.is-3 > .nx-card,
.nx-grid.is-4 > .nx-card, .nx-grid.is-6 > .nx-card { grid-column: auto; }

/* A wall of tiles wants a flat baseline.  The bare grid is align-items:start
   because a rail of mixed card variants must not stretch; a tile grid is one
   variant, and .nx-meta already has margin-block-start:auto to sit on the
   bottom edge of whatever height the row settles on. */
.nx-grid.is-2, .nx-grid.is-3, .nx-grid.is-4, .nx-grid.is-6 { align-items: stretch; }


/* --- 19.2  front page: the hero block ------------------------------------ */

/* One story owns the page, two or three chase it in a column beside it.  8/4
   of the grid, and the chasers are horizontal rows so the block ends level
   with the hero instead of running a screen past it. */
.nx-heroblock {
  display: grid;
  grid-template-columns: minmax(0, 8fr) minmax(0, 4fr);
  gap: var(--gap) clamp(16px, 2vw, 30px);
  align-items: stretch;
}

/* display:grid, not block: block-size:100% on the card inside resolves against
   an auto-height parent as `auto`, so the wrapper has to be a formatting
   context that actually hands its stretched height down. */
.nx-heroblock-main { display: grid; min-inline-size: 0; }

/* The stack decides the height of the block and the hero photograph grows to
   meet it, so the two columns finish level.  A fixed aspect ratio here left a
   250px hole under one side or the other at every width. */
.nx-heroblock-main .nx-card.is-hero .nx-card-media {
  aspect-ratio: auto;
  block-size: 100%;
  min-block-size: clamp(300px, 32vw, 520px);
}

.nx-heroblock-stack {
  display: grid;
  gap: 10px;
  align-content: start;
  min-inline-size: 0;
}

/* The first chaser keeps its picture on top — it is still a headline story. */
.nx-heroblock-stack > .nx-card:first-child .nx-hl {
  font-size: calc(clamp(1.16rem, .98rem + .62vw, 1.6rem) * var(--hl-scale));
  letter-spacing: -.018em;
}
.nx-heroblock-stack > .nx-card:first-child .nx-dek {
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

/* The rest turn into thumbnail rows.  `order` puts the picture on the far side
   of the text without naming a side. */
.nx-heroblock-stack > .nx-card + .nx-card .nx-card-link {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(88px, 9vw, 124px);
  align-items: stretch;
}
.nx-heroblock-stack > .nx-card + .nx-card .nx-card-media {
  order: 2;
  aspect-ratio: auto;
  block-size: 100%;
  min-block-size: 84px;
}
.nx-heroblock-stack > .nx-card + .nx-card .nx-card-body {
  order: 1;
  gap: 7px;
  padding: 13px 15px;
}
.nx-heroblock-stack > .nx-card + .nx-card .nx-hl {
  font-size: var(--t-list);
  letter-spacing: -.012em;
}
.nx-heroblock-stack > .nx-card + .nx-card .nx-dek { display: none; }


/* --- 19.3  front page: the three-column band ----------------------------- */

/* Mosaic | flash column | most read.  Roughly 7 / 2.5 / 2.5.  The wrappers
   stretch so the sticky flash panel inside has a track tall enough to slide
   along; the two outer columns pin themselves to the top of the row. */
.nx-tri {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 2.5fr) minmax(0, 2.5fr);
  gap: var(--gap) clamp(18px, 2.2vw, 36px);
  align-items: stretch;
  margin-block-start: var(--rowgap);
}
.nx-tri-main, .nx-tri-read { align-self: start; }
.nx-tri-main, .nx-tri-live, .nx-tri-read { min-inline-size: 0; }

/* The mosaic is dense on purpose — deks would turn nine tiles into a list. */
.nx-tri-main .nx-grid > .nx-card.is-tile .nx-dek { display: none; }

.nx-tri-read .nx-sect-head,
.nx-tri-main .nx-sect-head { margin-block-end: clamp(10px, 1.2vw, 16px); }

/* Most read.  index.php wraps each card in an <li>, so the section 13 rules,
   which expect .nx-numlist > .nx-card, never match — restate them one level
   deeper rather than reaching into another agent's markup. */
.nx-numlist > li { min-inline-size: 0; }
.nx-numlist > li > .nx-card {
  --rank-w: clamp(42px, 3.4vw, 54px);
  padding-inline-start: var(--rank-w);
}
.nx-numlist > li + li > .nx-card { border-block-start: 1px solid var(--hair); }
.nx-numlist > li > .nx-card:hover .nx-rank { color: var(--sec-deep); opacity: 1; }


/* --- 19.4  front page: section bands, rails, strip ----------------------- */

/* A lead card beside a block of tiles, on a band of the desk's colour that
   runs out past the gutters.  The tint sits UNDER the cards, which stay
   white, so the band groups them without flattening them.  The bleed is the
   gutter, NOT 100vw: a vw unit includes the classic scrollbar and puts 15px
   of horizontal scroll on the whole document, which is the one regression QA
   measures at 390px.  Up to --wrap plus two gutters this reaches both viewport
   edges; past that it stops at a wide inset, which reads as deliberate. */
.nx-secband {
  position: relative;
  isolation: isolate;
  padding-block: clamp(18px, 2.4vw, 34px) clamp(20px, 2.8vw, 40px);
}
.nx-secband::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block: 0;
  inset-inline: calc(var(--gut) * -1);
  border-radius: var(--r-xl);
  background: linear-gradient(180deg, var(--sec-tint2), var(--sec-tint) 52%, transparent);
  border-block-start: 2px solid var(--sec-fill);
}
/* The band already carries the colour; the head inside it drops back to a
   hairline so the two rules do not stack into a stripe. */
.nx-secband > .nx-sect-head { border-block-end-color: var(--sec-hair); }

.nx-secband-in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--gap) clamp(20px, 2.4vw, 40px);
  align-items: start;
}
.nx-secband-lead, .nx-secband-rest { min-inline-size: 0; }

.nx-secband.is-flip .nx-secband-lead { order: 2; }
.nx-secband.is-flip .nx-secband-rest { order: 1; }

/* Four tiles in half a page are a 2x2 block whatever the page asked for:
   three columns here would leave one tile orphaned on its own row. */
.nx-secband-rest.nx-grid.is-2,
.nx-secband-rest.nx-grid.is-3,
.nx-secband-rest.nx-grid.is-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* --t-lead is sized for a card that owns two thirds of the page. */
.nx-secband-lead .nx-card.is-lead .nx-hl {
  font-size: calc(clamp(1.34rem, 1.05rem + 1.05vw, 2.05rem) * var(--hl-scale));
}
.nx-secband-rest .nx-card.is-tile .nx-dek {
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

/* The closing strip is small and dense — six across, headline only.  Its
   kickers are dropped: six repetitions of the same word in the same colour
   is a pattern, not information. */
.nx-sect.is-strip .nx-card.is-tile .nx-kick-sec { display: none; }

.nx-sect.is-strip .nx-card.is-tile .nx-dek { display: none; }
.nx-sect.is-strip .nx-card.is-tile .nx-hl {
  font-size: calc(clamp(.92rem, .88rem + .2vw, 1.06rem) * var(--hl-scale));
}
.nx-sect.is-strip .nx-card-body { gap: 6px; padding: 11px 12px 13px; }


/* --- 19.5  empty states -------------------------------------------------- */

.nx-empty {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 16px;
  margin-block-start: var(--rowgap);
  padding: clamp(34px, 6vw, 80px) var(--gut);
  border: 1px dashed var(--sec-hair);
  border-radius: var(--r-l);
  background: var(--sec-tint);
  color: var(--tx-3);
  text-align: center;
}
.nx-empty .nx-chip { padding: 9px 16px; font-size: .76rem; }
.nx-empty .nx-chip:hover { border-color: var(--sec-fill); background: var(--sec-fill); color: var(--sec-on); }


/* --- 19.6  article ------------------------------------------------------- */

.nx-art { display: block; }

/* Hero.  Contained rather than full-bleed: a 1440-wide photo above a 760-wide
   column reads as a banner, not as a newspaper. */
.nx-art-hero {
  position: relative;
  inline-size: min(100% - (var(--gut) * 2), 1180px);
  margin-inline: auto;
  margin-block-end: clamp(20px, 3vw, 40px);
  border-radius: var(--r-xl);
  border: 0;
  overflow: hidden;
  isolation: isolate;
  aspect-ratio: 16 / 9;
  max-block-size: min(62svh, 620px);
  background: linear-gradient(140deg, var(--sec-chip), var(--sec-tint2));
  box-shadow: var(--sh-2);
}
.nx-art-hero-img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}
.nx-art-hero.has-photo .nx-art-hero-img { filter: var(--photo-grade); }

/* Section 10's scrim is built to carry a headline; here it only has to keep a
   credit legible, so it is a quarter of the weight. */
.nx-art-hero .nx-scrim {
  background: linear-gradient(to top, var(--scrim-2) 0%, var(--scrim-3) 26%, transparent 54%);
}

.nx-art-credit {
  position: absolute;
  inset-block-end: 10px;
  inset-inline-end: 14px;
  max-inline-size: min(58ch, 76%);
  font-size: .72rem;
  letter-spacing: .02em;
  color: var(--on-img-3);
  text-align: end;
  text-shadow: 0 1px 8px rgb(0 0 0 / .8);
}
.nx-art-credit a { text-decoration: underline; text-decoration-color: rgb(255 255 255 / .32); text-underline-offset: 2px; }
.nx-art-credit a:hover { color: #fff; text-decoration-color: currentColor; }

/* The reading measure.  Five tracks: prose sits in `text`, the boxes that earn
   more presence (key points, player, sources) sit in `wide`, and both are
   centred by the two outer 1fr tracks.  min(...,100%) is what stops the fixed
   text track from pushing the page sideways on a 360px phone. */
.nx-art-in {
  display: grid;
  grid-template-columns:
    minmax(0, 1fr)
    [wide-start] minmax(0, 100px)
    [text-start] min(760px, 100%) [text-end]
    minmax(0, 100px) [wide-end]
    minmax(0, 1fr);
  row-gap: clamp(22px, 2.8vw, 36px);
}
.nx-art-in > * { grid-column: text; }
.nx-art-in > .nx-keypoints,
.nx-art-in > .nx-player,
.nx-art-in > .nx-sources { grid-column: wide; }
.nx-art-in > .nx-prose { max-inline-size: none; }

.nx-art-head { display: grid; gap: clamp(12px, 1.4vw, 18px); }

.nx-art-h1 {
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: calc(clamp(1.86rem, 1.2rem + 2.3vw, 3.1rem) * var(--hl-scale));
  line-height: var(--hl-lh);
  letter-spacing: -.026em;
  color: var(--tx);
  text-wrap: balance;
}
:root[data-script="hebrew"] .nx-art-h1,
:root[data-script="arabic"] .nx-art-h1,
:root[data-script="thai"] .nx-art-h1,
:root[data-script="tamil"] .nx-art-h1 { letter-spacing: 0; }

.nx-art-dek {
  font-size: clamp(1.04rem, .98rem + .45vw, 1.28rem);
  line-height: 1.56;
  color: var(--tx-2);
  text-wrap: pretty;
}

/* --- byline ------------------------------------------------------------- */

.nx-byline {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 0;
  padding-block: 13px;
  border-block: 1px solid var(--hair);
  font-size: .82rem;
  color: var(--tx-3);
}
.nx-byline-brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--f-ui);
  font-size: .74rem;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--tx);
}
.nx-byline-brand::before {
  content: "";
  inline-size: 4px;
  block-size: 1.15em;
  border-radius: 3px;
  background: var(--sec-fill);
  flex: none;
}
.nx-byline-item {
  display: inline-flex;
  align-items: center;
  unicode-bidi: isolate;
}
.nx-byline-item::before {
  content: "\00B7";
  margin-inline: 12px;
  color: var(--tx-dim);
}
.nx-byline-item.is-upd { color: var(--sec-deep); font-weight: 600; }

.nx-share {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-inline-start: auto;
  padding: 8px 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--hair-2);
  background: var(--surface);
  color: var(--tx-2);
  font-size: .8rem;
  font-weight: 600;
  transition: background .22s var(--ease), border-color .22s var(--ease), color .22s var(--ease);
}
.nx-share:hover { background: var(--sec-fill); border-color: var(--sec-fill); color: var(--sec-on); }

.nx-origin-note {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 11px 15px;
  border-radius: var(--r-m);
  border: 1px solid var(--sec-hair);
  background: var(--sec-soft);
  color: var(--tx-2);
  font-size: .84rem;
  line-height: 1.5;
}
.nx-origin-note::before {
  content: "";
  inline-size: 7px;
  block-size: 7px;
  border-radius: 50%;
  background: var(--sec-fill);
  margin-block-start: .55em;
  flex: none;
}

/* --- key points --------------------------------------------------------- */

/* The box a reader in a hurry actually reads.  It is meant to have weight. */
.nx-keypoints {
  position: relative;
  border-radius: var(--r-l);
  border: 1px solid var(--sec-hair);
  background: linear-gradient(165deg, var(--sec-chip), var(--surface) 64%);
  color: var(--tx);
  box-shadow: var(--sh-1);
  padding: clamp(18px, 2.2vw, 30px);
  padding-inline-start: clamp(22px, 2.6vw, 36px);
  overflow: hidden;
}
.nx-keypoints::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 4px;
  background: var(--sec-fill);
}
.nx-keypoints-t {
  font-family: var(--f-ui);
  font-size: .74rem;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--sec-deep);
  margin-block-end: 15px;
}
.nx-keypoints ul { display: grid; gap: 11px; }
.nx-keypoints li {
  position: relative;
  padding-inline-start: 27px;
  font-size: clamp(.97rem, .93rem + .2vw, 1.07rem);
  line-height: 1.55;
  color: var(--tx);
}
.nx-keypoints li::before {
  content: "";
  position: absolute;
  inset-inline-start: 4px;
  inset-block-start: .6em;
  inline-size: 7px;
  block-size: 7px;
  border-radius: 50%;
  background: var(--sec-fill);
  box-shadow: 0 0 0 4px var(--sec-soft);
}

/* --- video player ------------------------------------------------------- */

.nx-player {
  position: relative;
  inline-size: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-l);
  border: 1px solid var(--hair);
  overflow: hidden;
  background: var(--sec-chip);
  box-shadow: var(--sh-1);
}
/* The facade stacks poster and button in one cell — centring with inset plus
   translate is the classic thing that lands off-centre under RTL. */
.nx-player.is-yt {
  display: grid;
  grid-template-areas: "yt";
  place-items: center;
  cursor: pointer;
}
.nx-player-poster {
  grid-area: yt;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}
.nx-yt-play {
  grid-area: yt;
  position: relative;
  display: grid;
  place-items: center;
  inline-size: clamp(62px, 7vw, 84px);
  block-size: clamp(62px, 7vw, 84px);
  border-radius: 50%;
  background: rgb(10 12 20 / .55);
  border: 1px solid rgb(255 255 255 / .34);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  color: #fff;
  box-shadow: 0 20px 50px -20px rgb(0 0 0 / .5);
  transition: background .24s var(--ease), scale .24s var(--ease-out);
}
[dir="rtl"] .nx-yt-play .nx-i { transform: scaleX(-1); }
.nx-yt-play:hover { background: var(--live); border-color: var(--live-hi); scale: 1.06; }

/* --- pull quote --------------------------------------------------------- */

/* Wider than the column it interrupts, which is the whole point of one. */
.nx-prose .nx-pull {
  --pull-out: clamp(0px, 3.2vw, 58px);
  position: relative;
  margin-block: clamp(26px, 3.2vw, 44px);
  margin-inline: calc(var(--pull-out) * -1);
  padding: clamp(20px, 2.4vw, 32px) clamp(20px, 2.6vw, 40px);
  border: 0;
  border-block: 1px solid var(--sec-hair);
  background: linear-gradient(180deg, var(--sec-tint2), transparent);
}
.nx-prose .nx-pull::before {
  content: "";
  position: absolute;
  inset-block-start: -1px;
  inset-inline-start: clamp(20px, 2.6vw, 40px);
  inline-size: clamp(46px, 8%, 96px);
  block-size: 3px;
  border-radius: 3px;
  background: var(--sec-fill);
}
.nx-prose .nx-pull p {
  margin: 0;
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: calc(clamp(1.22rem, 1.04rem + .78vw, 1.68rem) * var(--hl-scale));
  line-height: 1.34;
  letter-spacing: -.015em;
  color: var(--tx);
  text-wrap: balance;
}
:root[data-script="hebrew"] .nx-prose .nx-pull p,
:root[data-script="arabic"] .nx-prose .nx-pull p { letter-spacing: 0; line-height: 1.5; }

/* --- sources ------------------------------------------------------------ */

/* Where the story came from, numbered.  Attribution is the product. */
.nx-sources {
  margin-block-start: clamp(10px, 1.4vw, 18px);
  padding: clamp(20px, 2.4vw, 32px);
  border-radius: var(--r-l);
  border: 1px solid var(--hair);
  background: var(--surface);
  color: var(--tx);
  box-shadow: var(--sh-1);
}
.nx-sources-t {
  font-family: var(--f-ui);
  font-size: .74rem;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--tx-3);
  margin-block-end: 6px;
}
.nx-sources ul { counter-reset: nxsrc; display: block; }
.nx-source {
  position: relative;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 3px 10px;
  padding-block: 12px;
  padding-inline-start: 38px;
  border-block-end: 1px solid var(--hair);
  margin: 0;
}
.nx-source:last-child { border-block-end: 0; padding-block-end: 4px; }
.nx-source::before {
  counter-increment: nxsrc;
  content: counter(nxsrc);
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 12px;
  inline-size: 24px;
  block-size: 24px;
  display: grid;
  place-items: center;
  border-radius: var(--r-s);
  border: 1px solid var(--sec-hair);
  background: var(--sec-chip);
  font-family: var(--f-num);
  font-size: .7rem;
  font-weight: 700;
  color: var(--sec-deep);
  unicode-bidi: isolate;
}
.nx-source-link {
  font-size: .94rem;
  font-weight: 600;
  color: var(--tx);
  overflow-wrap: anywhere;
}
a.nx-source-link {
  text-decoration: underline;
  text-decoration-color: var(--sec-hair);
  text-underline-offset: 3px;
  transition: color .2s var(--ease);
}
a.nx-source-link:hover { color: var(--sec-deep); text-decoration-color: currentColor; }

/* .nx-sep is a full-width rule everywhere else; inside a source row it is the
   dot between the outlet and the timestamp. */
.nx-source .nx-sep {
  flex: none;
  inline-size: 3px;
  block-size: 3px;
  border-radius: 50%;
  background: var(--tx-dim);
  margin: 0;
}
.nx-sources-note {
  margin-block-start: 16px;
  padding-block-start: 14px;
  border-block-start: 1px solid var(--hair);
  font-size: .78rem;
  line-height: 1.55;
  color: var(--tx-dim);
}

.nx-art-related { margin-block-start: clamp(34px, 5vw, 72px); }


/* --- 19.7  section page -------------------------------------------------- */

/* The desk's own front page opens with its colour, not with a grey rule:
   the nameplate sits on a tinted plinth that bleeds past the gutters. */
.nx-masthead {
  position: relative;
  isolation: isolate;
  display: grid;
  gap: 9px;
  padding-block: clamp(20px, 3vw, 40px) clamp(18px, 2.4vw, 32px);
  margin-block-end: clamp(16px, 2.2vw, 30px);
  border-block-end: 0;
}
.nx-masthead::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block: calc(clamp(12px, 2vw, 26px) * -1) 0;
  inset-inline: calc(var(--gut) * -1);
  border-end-start-radius: var(--r-xl);
  border-end-end-radius: var(--r-xl);
  background: linear-gradient(180deg, var(--sec-tint2), var(--sec-tint) 60%, transparent);
  border-block-end: 2px solid var(--sec-fill);
}
.nx-masthead::after {
  content: "";
  position: absolute;
  inset-block-end: -1px;
  inset-inline-start: 0;
  inline-size: clamp(64px, 13%, 176px);
  block-size: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--sec-deep), transparent);
}
[dir="rtl"] .nx-masthead::after { background: linear-gradient(270deg, var(--sec-deep), transparent); }

.nx-masthead-title {
  display: flex;
  align-items: center;
  gap: 13px;
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: calc(clamp(1.68rem, 1.2rem + 1.7vw, 2.55rem) * var(--hl-scale));
  line-height: var(--hl-lh);
  letter-spacing: -.022em;
  color: var(--tx);
}
.nx-masthead-title .nx-i { color: var(--sec-fill); }
.nx-masthead.is-livehead .nx-masthead-title .nx-live-dot { inline-size: 13px; block-size: 13px; }
.nx-masthead-desc {
  max-inline-size: 70ch;
  font-size: clamp(.93rem, .89rem + .24vw, 1.05rem);
  line-height: 1.55;
  color: var(--tx-3);
}

.nx-secpage-lead { margin-block-end: clamp(20px, 2.8vw, 38px); }
/* A 16:9 hero across the full 1480 measure is an 830px wall of photograph. */
.nx-secpage-lead .nx-card.is-hero .nx-card-media { aspect-ratio: 2.45 / 1; }

.nx-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-block-start: clamp(28px, 4vw, 56px);
  padding-block-start: clamp(18px, 2.4vw, 30px);
  border-block-start: 1px solid var(--hair);
}
.nx-pager-nums { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.nx-pager-num {
  display: grid;
  place-items: center;
  min-inline-size: 42px;
  min-block-size: 42px;
  padding-inline: 10px;
  border-radius: var(--r-m);
  border: 1px solid var(--hair);
  font-family: var(--f-num);
  font-variant-numeric: tabular-nums;
  font-size: .92rem;
  color: var(--tx-2);
  unicode-bidi: isolate;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.nx-pager-num { background: var(--surface); }
a.nx-pager-num:hover { border-color: var(--sec-fill); background: var(--sec-chip); color: var(--sec-deep); }
.nx-pager-num.is-on {
  background: var(--sec-fill);
  border-color: var(--sec-fill);
  color: var(--sec-on);
  font-weight: 800;
}
.nx-pager-gap { color: var(--tx-dim); padding-inline: 2px; }
.nx-pager-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-block-size: 42px;
  padding-inline: 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--hair-2);
  font-size: .87rem;
  font-weight: 600;
  color: var(--tx-2);
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.nx-pager-link { background: var(--surface); }
.nx-pager-link:hover { background: var(--sec-fill); border-color: var(--sec-fill); color: var(--sec-on); }
/* The chevron points the way the reader travels, which flips with the script. */
.nx-pager-link.is-prev .nx-i { transform: scaleX(-1); }
[dir="rtl"] .nx-pager-link.is-prev .nx-i { transform: none; }
[dir="rtl"] .nx-pager-link.is-next .nx-i { transform: scaleX(-1); }


/* --- 19.8  live wall ----------------------------------------------------- */

.nx-livewall { position: relative; }

.nx-livewall-day {
  position: sticky;
  inset-block-start: calc(var(--top-h) + 2px);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 14px;
  margin-block: clamp(18px, 2.4vw, 32px) 8px;
  padding-block: 9px;
  font-family: var(--f-ui);
  font-size: .73rem;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--tx-3);
  background: linear-gradient(180deg, var(--paper) 58%, transparent);
}
.nx-livewall-day:first-child { margin-block-start: 0; }
.nx-livewall-day::after {
  content: "";
  flex: 1;
  block-size: 1px;
  background: linear-gradient(90deg, var(--hair) 0%, transparent 92%);
}
[dir="rtl"] .nx-livewall-day::after { background: linear-gradient(270deg, var(--hair) 0%, transparent 92%); }

.nx-livewall-list { display: grid; }

.nx-livewall-item {
  --wall-time: clamp(44px, 5vw, 58px);
  position: relative;
  display: grid;
  grid-template-columns: var(--wall-time) 10px minmax(0, 1fr);
  align-items: start;
  column-gap: 14px;
  padding-block: 15px;
  border-block-end: 1px solid var(--hair);
}
/* The rule that turns a list of flashes into a timeline. */
.nx-livewall-item::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: calc(var(--wall-time) + 19px);
  inline-size: 1px;
  background: var(--sec-hair);
}
.nx-livewall-item:first-child::before { inset-block-start: 12px; }
.nx-livewall-item:last-child { border-block-end: 0; }
.nx-livewall-item:last-child::before { inset-block-end: calc(100% - 30px); }

.nx-livewall-time {
  font-family: var(--f-num);
  font-size: .78rem;
  font-variant-numeric: tabular-nums;
  color: var(--tx-dim);
  padding-block-start: 3px;
  text-align: end;
  unicode-bidi: isolate;
}
.nx-livewall-item > .nx-live-dot {
  position: relative;
  z-index: 1;
  inline-size: 10px;
  block-size: 10px;
  margin-block-start: 6px;
  background: var(--sec-fill);
  animation: none;
  box-shadow: 0 0 0 3px var(--paper);
}
.nx-livewall-item.is-alert > .nx-live-dot {
  background: var(--live);
  box-shadow: 0 0 0 3px var(--paper), 0 0 14px var(--live-glow);
}
.nx-livewall-body { min-inline-size: 0; display: grid; gap: 7px; justify-items: start; }
.nx-livewall-txt {
  font-size: clamp(.98rem, .94rem + .24vw, 1.1rem);
  line-height: 1.55;
  color: var(--tx-2);
}
.nx-livewall-item.is-alert .nx-livewall-txt { color: var(--tx); font-weight: 600; }
.nx-livewall-item.is-alert {
  background: linear-gradient(90deg, var(--live-tint), transparent 58%);
}
[dir="rtl"] .nx-livewall-item.is-alert {
  background: linear-gradient(270deg, var(--live-tint), transparent 58%);
}
.nx-livewall-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: .8rem;
  font-weight: 600;
  color: var(--sec-deep);
  transition: gap .2s var(--ease);
}
[dir="rtl"] .nx-livewall-link .nx-i { transform: scaleX(-1); }
.nx-livewall-link:hover { gap: 9px; }
/* Items the poller injects arrive with .is-new for one beat. */
.nx-livewall-item.is-new { animation: nx-flash-in .6s var(--ease-out) both; }


/* --- 19.9  video page ---------------------------------------------------- */

.nx-vodfeat { margin-block-end: clamp(6px, 1vw, 14px); }
.nx-vodfeat .nx-card.is-hero .nx-card-media { aspect-ratio: 2.45 / 1; }
.nx-vodgrid, .nx-vodrail { margin-block-start: var(--rowgap); }


/* --- 19.10  search, about, 404 ------------------------------------------- */

.nx-searchbig { inline-size: min(100%, 720px); margin-block-start: 4px; }
.nx-searchbig-in {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block: 7px;
  padding-inline: 18px 7px;
  border-radius: var(--r-pill);
  border: 1px solid var(--hair-2);
  background: var(--surface);
  color: var(--tx);
  box-shadow: var(--sh-1);
  transition: border-color .22s var(--ease), box-shadow .22s var(--ease);
}
.nx-searchbig-in:focus-within { border-color: var(--sec-fill); box-shadow: var(--sh-hot); }
.nx-searchbig-in > .nx-i { color: var(--sec-deep); }
.nx-searchbig input {
  flex: 1 1 auto;
  min-inline-size: 0;
  padding-block: 11px;
  font-size: clamp(1rem, .95rem + .4vw, 1.18rem);
}
.nx-searchbig input::placeholder { color: var(--tx-dim); }
.nx-searchbig input::-webkit-search-cancel-button { display: none; }
.nx-searchbig-go {
  flex: none;
  padding: 11px 20px;
  border-radius: var(--r-pill);
  background: var(--sec-fill);
  color: var(--sec-on);
  font-size: .87rem;
  font-weight: 700;
  letter-spacing: .02em;
  transition: filter .2s var(--ease), scale .2s var(--ease-out);
}
.nx-searchbig-go:hover { filter: brightness(1.12); scale: 1.02; }

.nx-results {
  display: grid;
  gap: 12px;
  inline-size: min(100%, 1000px);
  /* .nx-wrap centres itself; the results column instead lines up with the
     search field above it, which starts at the inline edge of the page. */
  margin-inline: 0 auto;
  margin-block-start: clamp(8px, 1.4vw, 16px);
}
.nx-results-count {
  padding-block-end: 6px;
  font-size: .88rem;
  color: var(--tx-3);
}
/* A .is-wide card across a 1000px column would be a 560px-tall photograph per
   result; a result is a row. */
.nx-results > .nx-card.is-wide > .nx-card-link {
  display: grid;
  grid-template-columns: clamp(150px, 22%, 260px) minmax(0, 1fr);
  align-items: stretch;
}
.nx-results > .nx-card.is-wide .nx-card-media {
  aspect-ratio: auto;
  block-size: 100%;
  min-block-size: 128px;
}
.nx-results > .nx-card.is-wide .nx-hl {
  font-size: calc(clamp(1.08rem, .98rem + .48vw, 1.42rem) * var(--hl-scale));
}
/* `mark.` is not decoration.  .nx-mark is TWO things in the class contract:
   search.php wraps every hit in <mark class="nx-mark">, and render.php draws
   the wordmark as <svg class="nx-mark">.  The old rule was translucent enough
   to hide the collision on an ink page; on paper an opaque fill put a pale
   plate behind the masthead logo on every page of the site.  Tag-qualified,
   the two stop being the same selector. */
mark.nx-mark {
  background: var(--sec-chip);
  box-shadow: 0 1px 0 var(--sec-fill);
  border-radius: 3px;
  padding-inline: 2px;
  color: var(--sec-deep);
  font-weight: 700;
}

.nx-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--gap);
  margin-block: clamp(14px, 2vw, 24px) clamp(24px, 3.4vw, 46px);
}
.nx-fact {
  display: grid;
  gap: 8px;
  justify-items: center;
  text-align: center;
  padding: clamp(18px, 2.2vw, 30px) clamp(14px, 1.6vw, 22px);
  border-radius: var(--r-l);
  border: 1px solid var(--sec-hair);
  background: linear-gradient(160deg, var(--sec-chip), var(--surface) 72%);
  color: var(--tx);
  box-shadow: var(--sh-1);
}
.nx-fact-n {
  font-family: var(--f-num);
  font-size: clamp(2rem, 1.2rem + 2.4vw, 3.1rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.035em;
  background: linear-gradient(180deg, var(--sec-fill), var(--sec-deep));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.nx-fact-l {
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tx-3);
}

.nx-page {
  display: grid;
  justify-items: center;
  gap: clamp(30px, 4.4vw, 60px);
  padding-block-end: clamp(16px, 2.4vw, 32px);
}
.nx-page > .nx-prose { inline-size: min(100%, 760px); max-inline-size: none; }
.nx-page > .nx-langwall { inline-size: min(100%, 980px); }

.nx-prose .nx-steps {
  counter-reset: nxstep;
  display: grid;
  gap: 4px;
  margin-block: .4em 1.6em;
  padding-inline-start: 0;
  list-style: none;
}
.nx-prose .nx-steps > li {
  position: relative;
  margin: 0;
  padding-block: 11px;
  padding-inline-start: 46px;
  border-block-end: 1px solid var(--hair);
}
.nx-prose .nx-steps > li:last-child { border-block-end: 0; }
.nx-prose .nx-steps > li::before {
  counter-increment: nxstep;
  content: counter(nxstep);
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 9px;
  inline-size: 30px;
  block-size: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--sec-fill);
  background: var(--sec-fill);
  color: var(--sec-on);
  font-family: var(--f-num);
  font-size: .82rem;
  font-weight: 800;
  unicode-bidi: isolate;
}

.nx-langwall {
  padding: clamp(20px, 2.6vw, 34px);
  border-radius: var(--r-l);
  border: 1px solid var(--hair);
  background: var(--surface);
  color: var(--tx);
  box-shadow: var(--sh-1);
}
.nx-langwall-t {
  font-family: var(--f-ui);
  font-size: .74rem;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--tx-3);
  margin-block-end: 16px;
}
.nx-langwall-in { display: flex; flex-wrap: wrap; gap: 8px; }
.nx-langwall .nx-chip {
  padding: 8px 13px;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tx-2);
  unicode-bidi: isolate;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.nx-langwall .nx-chip:hover { border-color: var(--sec-fill); background: var(--sec-chip); color: var(--sec-deep); }
.nx-langwall .nx-chip.is-on { border-color: var(--sec-fill); background: var(--sec-fill); color: var(--sec-on); }

.nx-404 {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 14px;
  text-align: center;
  padding-block: clamp(36px, 7vw, 100px) clamp(28px, 4.5vw, 64px);
}
.nx-404-code {
  font-family: var(--f-num);
  font-size: clamp(4.4rem, 3rem + 8.5vw, 10.5rem);
  font-weight: 800;
  line-height: .84;
  letter-spacing: -.05em;
  color: var(--sec-chip);
  -webkit-text-stroke: 2px var(--sec-fill);
  unicode-bidi: isolate;
}
.nx-404-title {
  font-family: var(--f-hl);
  font-variation-settings: var(--hl-var);
  font-weight: var(--hl-weight);
  font-size: calc(clamp(1.5rem, 1.15rem + 1.4vw, 2.3rem) * var(--hl-scale));
  line-height: var(--hl-lh);
  letter-spacing: -.02em;
  color: var(--tx);
}
.nx-404-desc { max-inline-size: 54ch; color: var(--tx-3); }
.nx-404-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-block-start: 8px;
}
.nx-404-links .nx-chip {
  padding: 9px 16px;
  font-size: .76rem;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.nx-404-links .nx-chip:hover { border-color: var(--sec-fill); background: var(--sec-fill); color: var(--sec-on); }

/* Photo credit chip on a card.  It rides in .nx-meta beside the timestamp and
   must never be the thing that makes a card two lines taller. */
/* inline-block, not inline-flex: text-overflow only ever applies to the text
   directly inside a block container, so a flex box truncates mid-word with no
   ellipsis — which is exactly how "DER SPIEGEL — Schlagzei" got shipped. */
.nx-meta .nx-src {
  display: inline-block;
  max-inline-size: 22ch;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  vertical-align: bottom;
  font-size: .72rem;
  font-weight: 600;
  color: var(--tx-dim);
}
.nx-meta .nx-src::before {
  content: "\00B7";
  margin-inline-end: 6px;
  opacity: .75;
}
.nx-card.is-hero .nx-meta .nx-src { color: var(--on-img-3); max-inline-size: 34ch; }

/* The wordmark, in RTL.  render.php draws it as <text x="0"> inside the SVG,
   and `direction` is inherited into SVG: under RTL, x="0" becomes the END of
   the run, so all five letters are laid out to the left of the viewBox and the
   masthead renders as an empty rounded box in every RTL language.  Pinning the
   mark to LTR restores it.  The real fix is a text-anchor on the <text> in
   lib/render.php; this is the half that lives in a stylesheet. */
svg.nx-mark { direction: ltr; unicode-bidi: isolate; }


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

/* These rules live here, not in section 17, because section 19 comes after it:
   a breakpoint written up there would be overruled by the rules above. */

@media screen and (max-width: 1280px) {
  .nx-grid.is-6 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media screen and (max-width: 1100px) {
  /* Mosaic takes the full width; the two rails pair off underneath it. */
  .nx-tri { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nx-tri-main { grid-column: 1 / -1; }
  .nx-tri-live, .nx-tri-read { align-self: start; }
  .nx-grid.is-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media screen and (max-width: 980px) {
  .nx-heroblock { grid-template-columns: minmax(0, 1fr); }
  .nx-secband-in { grid-template-columns: minmax(0, 1fr); }
  /* On one column the lead always leads — a flipped band would otherwise open
     with its tiles and bury the story it is about. */
  .nx-secband.is-flip .nx-secband-lead { order: 0; }
  .nx-secband.is-flip .nx-secband-rest { order: 0; }
  .nx-grid.is-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nx-grid.is-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .nx-tri-main .nx-grid > .nx-card.is-tile .nx-dek { display: block; }
  /* One column: the hero has nothing to match heights with any more. */
  .nx-heroblock-main .nx-card.is-hero .nx-card-media,
  .nx-secpage-lead .nx-card.is-hero .nx-card-media,
  .nx-vodfeat .nx-card.is-hero .nx-card-media {
    aspect-ratio: 16 / 9;
    block-size: auto;
    min-block-size: 0;
  }
  .nx-art-in { row-gap: clamp(20px, 3vw, 30px); }
}

@media screen and (max-width: 760px) {
  .nx-tri { grid-template-columns: minmax(0, 1fr); }
  /* One column, flashes above most-read — which is the document order. */
  .nx-tri-main { grid-column: auto; }
  .nx-grid.is-4, .nx-grid.is-6 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nx-secband-rest.nx-grid.is-2,
  .nx-secband-rest.nx-grid.is-3,
  .nx-secband-rest.nx-grid.is-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nx-heroblock-main .nx-card.is-hero .nx-card-media,
  .nx-secpage-lead .nx-card.is-hero .nx-card-media,
  .nx-vodfeat .nx-card.is-hero .nx-card-media { aspect-ratio: 4 / 3; }
  .nx-heroblock-stack > .nx-card + .nx-card .nx-card-link {
    grid-template-columns: minmax(0, 1fr) clamp(96px, 30vw, 130px);
  }
  .nx-byline { font-size: .78rem; }
  /* No room to push it to the far edge; it just joins the run of meta. */
  .nx-share { margin-inline-start: 14px; }
  .nx-livewall-day { inset-block-start: 2px; }
  .nx-results > .nx-card.is-wide > .nx-card-link { grid-template-columns: clamp(110px, 32%, 160px) minmax(0, 1fr); }
  .nx-pager-link { padding-inline: 12px; }
}

/* Matches section 17's own 480 rule for .nx-card.is-hero, which the more
   specific rules above would otherwise outrank. */
@media screen and (max-width: 480px) {
  .nx-heroblock-main .nx-card.is-hero .nx-card-media { aspect-ratio: 1 / 1; }
}

@media screen and (max-width: 560px) {
  .nx-grid.is-2, .nx-grid.is-3, .nx-grid.is-4, .nx-grid.is-6,
  .nx-secband-rest.nx-grid.is-2,
  .nx-secband-rest.nx-grid.is-3,
  .nx-secband-rest.nx-grid.is-4 { grid-template-columns: minmax(0, 1fr); }
  .nx-secpage-lead .nx-card.is-hero .nx-card-media,
  .nx-vodfeat .nx-card.is-hero .nx-card-media { aspect-ratio: 1 / 1; }
  .nx-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nx-facts > .nx-fact:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .nx-searchbig-in { padding-inline: 14px 6px; gap: 8px; }
  .nx-searchbig-go { padding: 10px 14px; font-size: .8rem; }
  .nx-results > .nx-card.is-wide > .nx-card-link { grid-template-columns: minmax(0, 1fr); }
  .nx-results > .nx-card.is-wide .nx-card-media { aspect-ratio: 16 / 9; block-size: auto; min-block-size: 0; }
  .nx-source { padding-inline-start: 32px; }
  .nx-livewall-item { column-gap: 11px; }
  .nx-prose .nx-steps > li { padding-inline-start: 40px; }
}

@media screen and (max-width: 400px) {
  .nx-heroblock-stack > .nx-card + .nx-card .nx-card-link { grid-template-columns: minmax(0, 1fr) 96px; }
  .nx-404-code { -webkit-text-stroke-width: 1.5px; }
  .nx-livewall-item { --wall-time: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  .nx-share, .nx-pager-link, .nx-pager-num, .nx-yt-play,
  .nx-searchbig-go, .nx-langwall .nx-chip, .nx-livewall-link { transition: none; }
  .nx-livewall-item.is-new { animation: none; }
}

@media print {
  .nx-livewall-day { position: static; background: none; }
  .nx-art-hero { box-shadow: none; max-block-size: 320px; }
  .nx-share, .nx-pager, .nx-langwall, .nx-art-related { display: none !important; }
  .nx-keypoints, .nx-sources { background: none; border-color: #999; }
  .nx-art-h1, .nx-art-dek, .nx-keypoints li, .nx-source-link { color: #000; }
}

@media (forced-colors: active) {
  /* background-clip:text leaves the numeral invisible in a forced palette. */
  .nx-fact-n { color: CanvasText; -webkit-text-fill-color: CanvasText; background: none; }
  .nx-404-code { color: CanvasText; -webkit-text-stroke: 0; }
  .nx-keypoints, .nx-sources, .nx-langwall, .nx-empty, .nx-player { border: 1px solid CanvasText; }
  .nx-pager-num.is-on { forced-color-adjust: none; }
}


/* ==========================================================================
   20  PHOTOGRAPHY — the house treatment
   --------------------------------------------------------------------------
   Pictures arrive from a hundred wire desks in a hundred grades: one is
   crushed and blue, the next is blown out and warm, and side by side in a
   grid they read as a scrapbook rather than as one publication.  Nothing here
   tries to fix a bad photograph.  It gives every photograph the same three
   things, so the differences between them stop being the loudest thing on the
   page:

     1  one grade            — the same saturation, contrast and black point
     2  one duotone          — a wash of the desk's hue across the frame,
                               applied with soft-light so it tints the midtones
                               and leaves faces alone
     3  one edge             — the same scrim, the same cut corner, the same
                               hue-tinted placeholder underneath

   Agent H2 owns the drawn covers and the deeper image work; the classes that
   carry a treatment are listed below and every one of them keys off --sec-h,
   so both halves land on the same hue with no second palette.

   Everything is expressed as a token so a treatment can be dialled back per
   surface: a card gets the full duotone, an article hero gets half of it,
   because a reader looking at one photograph for thirty seconds notices a
   tint that a reader scanning forty of them does not.
   ========================================================================== */

:root {
  /* One grade for every photograph on the site. */
  --photo-grade: saturate(1.06) contrast(1.05) brightness(.98);
  /* How much of the desk's colour the frame takes. */
  --duo-o: .62;
  /* The wash runs from the corner the reader starts at; 20.2 mirrors it. */
  --duo-dir: 138deg;
}

/* The two ends of the duotone.  The warm end is the hue itself; the cool end
   is the hue rotated far enough to read as a shadow rather than as more of
   the same colour.  soft-light means neither one paints over a face. */
:root,
[data-theme],
[style*="--sec"] {
  --duo-a: oklch(72% var(--sec-c) var(--sec-h) / .85);
  --duo-b: oklch(28% calc(var(--sec-c) * .9) calc(var(--sec-h) + 44) / .8);
}


/* --- 20.1  the wash ------------------------------------------------------ */

/* .nx-card-media and .nx-art-hero both isolate, so the blend resolves against
   the picture and stops there — it must never reach the card behind it. */
.nx-card-media::after,
.nx-art-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(var(--duo-dir), var(--duo-a), transparent 54%),
    linear-gradient(var(--duo-dir), transparent 46%, var(--duo-b));
  mix-blend-mode: soft-light;
  opacity: var(--duo-o);
}

/* A drawn cover was composed in the section colour to begin with; tinting it
   again only muddies it. */
.nx-card.has-art .nx-card-media::after { opacity: .22; }

/* An article hero is looked at, not scanned. */
.nx-art-hero::after { opacity: calc(var(--duo-o) * .55); }

/* The scrim carries the headline and must sit ON TOP of the wash. */
.nx-scrim { z-index: 2; }
.nx-play, .nx-dur { z-index: 3; }
.nx-card-body { z-index: 3; }

/* --- 20.2  direction ----------------------------------------------------- */

/* Every angled treatment mirrors, or a Hebrew front page is lit from the
   wrong side while its type runs the other way. */
/* Not `[dir="rtl"] .nx-card` — render.php puts dir on the CARD, so a Hebrew
   story inside an English front page is itself the [dir="rtl"] element and a
   descendant selector never reaches it.  The token is set on any RTL element
   and inherits from there. */
[dir="rtl"] { --duo-dir: 222deg; }


/* --- 20.3  the placeholder ----------------------------------------------- */

/* Before a photograph arrives, the frame is already the right colour — so a
   grid mid-load reads as the desk it belongs to rather than as grey holes.
   lib/perf.php may put a dominant-colour LQIP inline on the <img>; this is
   what shows through where it does not. */
.nx-card-media,
.nx-art-hero {
  background-image:
    radial-gradient(120% 120% at 22% 8%, var(--sec-chip), transparent 62%),
    linear-gradient(var(--duo-dir), var(--sec-tint2), var(--sec-chip));
}


/* --- 20.4  the cut corner ------------------------------------------------ */

/* One shape, used everywhere a label is filled with a colour: the desk chip,
   the breaking badge, the flash label.  It is the only ornament in the design
   and it is the same ornament every time, which is what makes it read as a
   masthead rather than as decoration.  clip-path takes physical points, so
   the RTL variant is written out rather than mirrored. */
.nx-kick-sec,
.nx-badge.is-breaking {
  clip-path: polygon(0 0, 100% 0, calc(100% - 7px) 100%, 0 100%);
  border-radius: var(--r-s) 0 0 var(--r-s);
  padding-inline-end: 13px;
}
[dir="rtl"] .nx-kick-sec,
[dir="rtl"] .nx-badge.is-breaking {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 7px 100%);
  border-radius: 0 var(--r-s) var(--r-s) 0;
}
/* A chip with no fill has nothing to cut. */
.nx-card.is-mini .nx-kick-sec { clip-path: none; padding-inline-end: 0; }

@supports not (clip-path: polygon(0 0, 100% 0, 90% 100%, 0 100%)) {
  .nx-kick-sec, .nx-badge.is-breaking { border-radius: var(--r-s); padding-inline-end: 9px; }
}


/* --- 20.5  the article hero ---------------------------------------------- */

/* A mask rather than a border: the picture ends in the paper instead of in a
   line, which is what stops a 1180px photograph from reading as a banner ad.
   The fade is small — 4% — because a heavier one starts eating the picture. */
.nx-art-hero {
  -webkit-mask-image: linear-gradient(180deg, #000 92%, rgb(0 0 0 / .82));
  mask-image: linear-gradient(180deg, #000 92%, rgb(0 0 0 / .82));
}


/* --- 20.6  forced colours and print -------------------------------------- */

@media (forced-colors: active) {
  .nx-card-media::after, .nx-art-hero::after { display: none; }
  .nx-kick-sec, .nx-badge.is-breaking { clip-path: none; forced-color-adjust: none; }
}
@media print {
  .nx-card-media::after, .nx-art-hero::after { display: none; }
  .nx-art-hero { -webkit-mask-image: none; mask-image: none; }
}


/* ==========================================================================
   21  CONTAINER QUERIES AND SUBGRID
   --------------------------------------------------------------------------
   A card is the same markup in four places: 700px wide in a hero block,
   430px in a section band, 300px in a scrolling rail and 210px in a sidebar.
   A viewport media query knows none of that — it fires on the window, so the
   sidebar card gets the desktop treatment at 1440px and is unreadable.  Every
   .nx-card is an inline-size container (section 10) and the rules below size
   it from its own slot.

   This section comes AFTER 19, so it can refine what the skeletons set; that
   also means nothing in here may set a property a skeleton depends on.  Which
   is why the container rules move padding, gap, line clamps and one headline
   size, and touch no track, span or aspect ratio.

   Everything here is a REFINEMENT.  A browser with no container queries and
   no subgrid gets the layout from sections 10, 17 and 19, which is correct on
   its own — the @container blocks simply never match.

   Measured slot widths on the front page at 1440: mosaic tile 240, band tile
   324, rail card 320, closing-strip tile 211, band lead 660, hero 895.  Four
   different cards, one media query's worth of viewport.
   ========================================================================== */

@container card (max-width: 252px) {
  .nx-card-body { --card-pad: 11px; --card-gap: 6px; }
  .nx-card.is-tile .nx-dek,
  .nx-card.is-wide .nx-dek,
  .nx-card.is-vod .nx-dek { display: none; }
  .nx-meta .nx-src { display: none; }
  .nx-kick-sec { font-size: .62rem; letter-spacing: .1em; }
  /* At this width BREAKING and LIVE together wrap the kicker onto a second
     line and push the headline down by half a line against its neighbours.
     The dot alone still says it is live. */
  .nx-badge.is-live { font-size: 0; padding-inline: 5px; gap: 0; }
}

@container card (min-width: 430px) {
  .nx-card-body { --card-pad: clamp(16px, 2.6cqi, 26px); --card-gap: 10px; }
  .nx-card.is-tile .nx-dek,
  .nx-card.is-vod .nx-dek { -webkit-line-clamp: 3; line-clamp: 3; }
  /* cqi, not vw: a tile that lands in a wide slot earns a bigger headline
     even though the window has not changed size. */
  .nx-card.is-tile .nx-hl,
  .nx-card.is-vod .nx-hl {
    font-size: calc(clamp(1.12rem, .82rem + 1.5cqi, 1.54rem) * var(--hl-scale));
  }
}

@container card (min-width: 640px) {
  .nx-card-body { --card-gap: 13px; }
  .nx-card.is-wide .nx-hl,
  .nx-card.is-lead .nx-hl {
    font-size: calc(clamp(1.5rem, .9rem + 2.2cqi, 2.4rem) * var(--hl-scale));
  }
  .nx-card.is-wide .nx-dek { -webkit-line-clamp: 3; line-clamp: 3; }
}

/* --- 21.1  subgrid ------------------------------------------------------- */

/* A CARD CANNOT BE A SUBGRID.  Measured, not assumed: an element with
   `container-type: inline-size` has layout containment, and a containment box
   computes `grid-template-rows: subgrid` to `none`.  Every .nx-card is a
   container (section 10), so mapping media and body onto shared rows across a
   card row is not available with this markup — the card, the link and the body
   would all have to be subgrids, and the outermost one is the container.
   Container queries are worth more here than shared rows, so the cards keep
   theirs and subgrid is used where the grid item is NOT a container.

   `align-items: stretch` on the tile grids (19.1) already levels the cards
   themselves; what it cannot level is the two boxes below, whose parts live
   one element deeper. */

@supports (grid-template-rows: subgrid) {
  /* Statistics on /about.  Without this, one number that wraps to two lines
     drops its own label half a line below every other label in the row. */
  .nx-facts { grid-template-rows: auto auto; }
  .nx-facts > .nx-fact {
    grid-row: span 2;
    grid-template-rows: subgrid;
    gap: 8px;
  }
}

@supports (grid-template-columns: subgrid) {
  /* The live wall.  Each row declares the same three tracks today, so they
     line up only while every timestamp is the same width — which stops being
     true the moment the page is served in a language with wider digits, or a
     day header pushes one row's time column out.  Subgrid makes the column a
     property of the LIST, so every flash on the page shares one rail. */
  .nx-livewall-list {
    display: grid;
    grid-template-columns: var(--wall-time, clamp(44px, 5vw, 58px)) 10px minmax(0, 1fr);
    column-gap: 14px;
  }
  .nx-livewall-list > .nx-livewall-item {
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    column-gap: 0;
  }
}
