/* notis — site.css
   The front page of "Notis Main Website.dc.html", ported rule for rule. "P:n"
   is a line of that file, "R" its README. Every class name is templates/
   index.html's. Colour is --bn-* only (static/bn/tokens/colors.css,
   dataviz.css); the three aurora tints (P:883-885, R) are the one literal
   exception. Shadows 1-3 only: --bn-shadow-4 does not exist (R).

   Order: 1 page frame and state · 2 sky · 3 header · keyframes and reduced
   motion · then the tail (hero, calendar, weather, deck, grid, editorial,
   my page, popover, bar, and the two things base.html adds).

   State vocabulary (index.html): is-open on a panel's owner; is-on for a
   toggle, and for the current wording of a pair; is-active on the filter when
   anything is set; is-here on the current area row; is-live on the clock;
   data-view on .page picks one of deck | grid | editorial | mine; the sky
   reads data-wx-state on .page until the script takes over. */

/* ================================================================= 1. page */

body:has(> .page) { overflow-x: hidden; }                                    /* P:14; .page sits directly under body here, index.html overriding the shell's block */                              /* P:14; margin 0 is notis.css's already */
main#main:has(> .page) { max-width: none; margin: 0; padding: 0; }            /* NOT IN THE PROTOTYPE: base.html's .wrap column would box the page */
.page {                                                                        /* P:38 */
  position: relative; min-height: 100vh; display: flex; flex-direction: column; background: var(--bn-bg);
  overflow-x: clip;                                                            /* NOT IN THE PROTOTYPE: the cards enter from 118vw (dc-in-a); on Chrome for Android that moment widened the layout viewport and a fixed bar was laid out 1.6 screens wide until the first scroll. clip, not hidden: no scroll container, the fixed sky is untouched */
  /* Defaults for the tail's var(--beat) and var(--kind*) (P:441-443, 380). The
     solid/outline kind modifiers (P:1454-1457) need the card macro's names. */
  --beat: var(--bn-border-strong); --kind: var(--bn-border); --kind-bg: transparent; --kind-ink: var(--bn-text-2);
}
[data-beat="models"] { --beat: var(--beat-models); }                           /* the three seeded beats, notis.css:50-52 */
[data-beat="tooling"] { --beat: var(--beat-tooling); }
[data-beat="research"] { --beat: var(--beat-research); }
[data-beat="compute"] { --beat: var(--beat-compute); }                         /* the two the taxonomy added */
[data-beat="policy"] { --beat: var(--beat-policy); }
.page a { color: var(--bn-link); text-decoration: none; }                     /* P:15 */
.page a:hover { color: var(--bn-link-hover); }                                /* P:16 */
.cat-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--beat); flex: 0 0 auto; }   /* P:380; 7px in the filter (P:191) */

/* Everything the prototype renders on a condition is in the markup and hidden
   here, so the page is complete before any script runs. Specificity is two
   classes and up so the tail's own display values cannot re-show a view. */
.page .view { display: none; width: 100%; }
.page[data-view="deck"] .view-deck { display: flex; }                         /* P:430-431 */
.page[data-view="grid"] .view-grid, .page[data-view="editorial"] .view-editorial { display: flex; flex-direction: column; align-items: center; }   /* P:560, 655 */
.page[data-view="mine"] .view-mine { display: grid; }                          /* P:338-339 */
.page:not([data-view="deck"]) .fan-toggle { display: none; }                   /* P:759: the fan control is the deck's only */
.page .pop { display: none; }                                                  /* P:713 */
.page .pop.is-open { display: block; }
.deck .deck-empty, .deck .deck-spent { display: none; }                        /* P:539, 550 */
.deck.is-empty .deck-empty, .deck.is-spent .deck-spent { display: flex; }
.page .cal-panel, .page .wx-drop { display: none; }                            /* P:246, 295 */
.date-control.is-open .cal-panel, .wx.is-open .wx-drop { display: block; }
/* The pairs: both wordings are in the markup, is-on (is-live on the clock) picks one. */
.hint-item, .fan-label-on, .cal-live-on, .mine-follow-on, .pop-notify-on, .pop-col-check, .mine-digest-note { display: none; }
.hint-item.is-on, .fan-toggle.is-on .fan-label-on, .cal-live.is-live .cal-live-on, .mine-follow.is-on .mine-follow-on,
.pop-notify.is-on .pop-notify-on, .pop-col.is-on .pop-col-check, .mine-digest-note.is-on { display: inline; }
.fan-toggle.is-on .fan-label-off, .cal-live.is-live .cal-live-off, .mine-follow.is-on .mine-follow-off, .pop-notify.is-on .pop-notify-off { display: none; }
.mine-saved .mine-rows, .mine-saved .mine-clear { display: none; }             /* P:1714-1715 */
.mine-saved.has-saved .mine-rows { display: grid; }
.mine-saved.has-saved .mine-clear { display: inline-block; }
.mine-saved.has-saved .mine-empty { display: none; }
.filter-saved-n:empty, .mine-pill-n:empty { display: none; }                   /* " · N" only once the script has a count (P:1667, 1707) */

/* ================================================================== 2. sky
   P:40-117. One fixed root at z 0 (P:40) with every layer absolute in it, in
   place of the prototype's per-layer fixed boxes. The hour's colours (SKY
   P:888-913, RIDGE P:869-878) are the script's, written inline on .sky-grad,
   .sky-glow, .sky-horizon and the ridge; so are the generated sets (38 stars
   P:955-965, 7 fireflies P:1008-1016, drops P:979-988, flakes P:990-1000),
   geometry and tint included (P:55, 72, 103, 110). What the file fixes is
   here: the aurora, the clouds, the birds, the fog banks, the scrims, the
   ridge frame, the shimmer, the flash, and the fourteen weather states. */

.sky { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }   /* P:40-42, 52 */
.sky > * { position: absolute; inset: 0; }

/* the aurora: 22-58vh, between the header scrim and the ridge (P:880-885, R) */
.sky-aurora { overflow: hidden; opacity: 0; }                                  /* P:42; SKY[h].au, .55 at midnight, .66 at 02:00, 0 by sunrise (P:1580) */
.sky-band { position: absolute; left: -14%; right: -14%; }                     /* P:44 */
.sky-band > span { position: absolute; inset: 0; animation: skAurora 34s ease-in-out 0s infinite; }   /* P:45 */
.sky-band:nth-child(1) { top: 27%; height: 27vh; transform: skewY(-8deg); }   /* P:883 */
.sky-band:nth-child(1) > span { background: linear-gradient(100deg, transparent 0%, rgba(76,203,151,.82) 42%, transparent 78%); filter: blur(46px); }
.sky-band:nth-child(2) { top: 22%; height: 22vh; transform: skewY(6deg); }    /* P:884 */
.sky-band:nth-child(2) > span { background: linear-gradient(100deg, transparent 0%, rgba(231,107,163,.54) 42%, transparent 78%); filter: blur(54px); animation-duration: 47s; animation-delay: -11s; }
.sky-band:nth-child(3) { top: 37%; height: 21vh; transform: skewY(-4deg); }   /* P:885 */
.sky-band:nth-child(3) > span { background: linear-gradient(100deg, transparent 0%, rgba(116,168,233,.48) 42%, transparent 78%); filter: blur(42px); animation-duration: 58s; animation-delay: -26s; }

.sky-veil { background: var(--bn-bg); opacity: 0; }                            /* P:50; SKY[h].v, .27 at noon to .45 in deep night (P:1577) */

/* the field: stars, clouds, birds, fireflies */
.sky-field { overflow: hidden; }                                              /* P:52 */
.sky-field > * { position: absolute; inset: 0; }
.sky-stars { opacity: 0; }                                                    /* P:53; SKY[h].st cut by cloud and fog (P:1592) */
.sky-star { position: absolute; border-radius: 999px; }                       /* P:55; place, size, tint and twinkle are inline */
.sky-clouds { opacity: var(--wx-cloud, 0); }                                  /* P:58; max(SKY[h].cl, WX.cloud) once the script runs (P:1593) */
.sky-cloud { position: absolute; left: 0; border-radius: 999px; background: color-mix(in srgb, var(--bn-stone-0) 50%, transparent); animation: skDrift 184s linear 0s infinite; }   /* P:60; rgba(255,255,255,.5/.38/.3) in the file, --bn-stone-0 is #FFFFFF */
.sky-cloud:nth-child(1) { top: 13%; width: 42vw; height: 8vh; filter: blur(42px); }   /* P:968 */
.sky-cloud:nth-child(2) { top: 27%; width: 56vw; height: 11vh; filter: blur(56px); background: color-mix(in srgb, var(--bn-stone-0) 38%, transparent); animation-duration: 246s; animation-delay: -70s; }   /* P:969 */
.sky-cloud:nth-child(3) { top: 44%; width: 34vw; height: 7vh; filter: blur(38px); background: color-mix(in srgb, var(--bn-stone-0) 30%, transparent); animation-duration: 308s; animation-delay: -150s; }   /* P:970 */
.sky-birds { opacity: 0; }                                                    /* P:63; SKY[h].bd (P:1640) */
.sky-bird { position: absolute; left: 0; color: color-mix(in srgb, var(--bn-night-850) 50%, transparent); animation: skGlide 62s linear 0s infinite; }   /* P:65-66; the markup strokes currentColor. APPROXIMATION: rgba(28,34,48,a) in the file, --bn-night-850 (#16223A) is the nearest token */
.sky-bird:nth-child(1) { top: 21%; }                                          /* P:974; 20px wide */
.sky-bird:nth-child(2) { top: 29%; color: color-mix(in srgb, var(--bn-night-850) 42%, transparent); animation-duration: 78s; animation-delay: -22s; }   /* P:975; 15px */
.sky-bird:nth-child(3) { top: 17%; color: color-mix(in srgb, var(--bn-night-850) 34%, transparent); animation-duration: 94s; animation-delay: -48s; }   /* P:976; 12px */
.sky-flies { opacity: 0; }                                                    /* P:70; SKY[h].ff (P:1641) */
.sky-fly { position: absolute; width: 4px; height: 4px; border-radius: 999px; }   /* P:72; tint and glow are inline */

/* the weather over the field */
.sky-dim { background: color-mix(in srgb, var(--bn-night-500), var(--bn-stone-600)); opacity: var(--wx-dim, 0); }   /* P:77; WX.dim (P:1594). APPROXIMATION: #59626F in the file, no token is that grey; the even mix lands at #62687A */
.sky-fog { overflow: hidden; opacity: var(--wx-fog, 0); }                     /* P:79; WX.fog (P:1596) */
.sky-fogbank { position: absolute; left: -12%; right: -12%; animation: wxFog 62s ease-in-out 0s infinite; }   /* P:81. APPROXIMATION: rgba(226,232,238,a) in the file, --bn-night-100 (#D8E0ED) at a is the nearest token */
.sky-fogbank:nth-child(1) { top: 48%; height: 22vh; filter: blur(30px); background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--bn-night-100) 55%, transparent) 45%, transparent); }   /* P:1003 */
.sky-fogbank:nth-child(2) { top: 62%; height: 26vh; filter: blur(38px); background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--bn-night-100) 70%, transparent) 45%, transparent); animation-duration: 88s; animation-delay: -24s; }   /* P:1004 */
.sky-fogbank:nth-child(3) { top: 76%; height: 24vh; filter: blur(26px); background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--bn-night-100) 85%, transparent) 45%, transparent); animation-duration: 110s; animation-delay: -52s; }   /* P:1005 */

/* the scrims, the horizon, the ridge */
.sky-scrim-top { inset: 0 0 auto; height: 48vh; background: linear-gradient(to bottom, var(--bn-bg) 0%, transparent 100%); opacity: .9; }   /* P:85: the reader's paper over the masthead, and why the aurora starts at 22vh (R) */
.sky-scrim-bottom { inset: auto 0 0; height: 26vh; background: linear-gradient(to top, var(--bn-bg) 0%, transparent 100%); opacity: .92; }   /* P:86 */
.sky-horizon { inset: auto 0 0; height: 34vh; }                               /* P:88; radial-gradient(120% 62% at 50% 112%, SKY[h].hg, transparent 76%) is the script's (P:1581) */
.sky-ridge { inset: auto 0 0; width: 100%; height: clamp(150px, 24vh, 290px); }   /* P:90; far ridge, near ridge, valley and lake take fill and opacity from RIDGE[SKY[h].rg] (P:1582-1590), the shimmer its fill from .hi */
.sky-ridge rect { animation: skShimmer 9s ease-in-out infinite; }             /* P:95 */
.sky-ridge rect:nth-of-type(2) { animation: skShimmer 15s ease-in-out -6s infinite; }   /* P:96 */
.sky-ridge rect:nth-of-type(3) { animation: skShimmer 13s ease-in-out -4s infinite; }   /* P:97 */
.sky-ridge rect:nth-of-type(4) { animation: skShimmer 11s ease-in-out -9s infinite; }   /* P:98 */

/* the particles: RAIN_COUNT[rain] drops and SNOW_COUNT[snow] flakes (P:947-948), made by the script */
.sky-rain { overflow: hidden; transform: skewX(-4deg); }                      /* P:101; -(4 + wind × .7)deg, wind capped at 18 (P:1359, 1598): -4deg is still air */
.sky-drop { position: absolute; top: 0; width: 1.4px; border-radius: 1px; }   /* P:103; height, place, tint, opacity and fall are inline; speed base × (1.5 − rain × .22) (P:1360) */
.sky-snow { overflow: hidden; }                                               /* P:107 */
.sky-flake { position: absolute; top: 0; }                                    /* P:109; falls on wxFall at base × (1.35 − snow × .16) (P:1361) */
.sky-flake > span { display: block; border-radius: 999px; }                   /* P:110; sways on wxSway */
.sky-flash { display: none; opacity: 0; background: var(--bn-night-50); animation: wxFlash 11s linear infinite; }   /* P:116. APPROXIMATION: #EAF1FB in the file, --bn-night-50 is #EDF1F8 */
.page[data-wx-state="thunder"] .sky-flash { display: block; }                 /* P:115, 930: thunder alone flashes */

/* The fourteen states (WX, P:917-930): cloud, fog and dim are opacities;
   rain and snow are the intensity steps the script sizes its sets by. Keyed
   on data-wx-state, which the page carries from weather.current(), so the
   weather is right before the script paints the hour; fair is the state the
   sky must never fail to render (R). */
.page[data-wx-state="clear"]     { --wx-cloud: 0;   --wx-fog: 0;   --wx-dim: 0; }     /* P:917 */
.page[data-wx-state="fair"]      { --wx-cloud: .35; --wx-fog: 0;   --wx-dim: .04; }   /* P:918 */
.page[data-wx-state="cloudy"]    { --wx-cloud: .75; --wx-fog: .05; --wx-dim: .10; }   /* P:919 */
.page[data-wx-state="overcast"]  { --wx-cloud: 1;   --wx-fog: .15; --wx-dim: .19; }   /* P:920 */
.page[data-wx-state="fog"]       { --wx-cloud: .6;  --wx-fog: .9;  --wx-dim: .17; }   /* P:921 */
.page[data-wx-state="drizzle"]   { --wx-cloud: .85; --wx-fog: .28; --wx-dim: .15; }   /* P:922, rain 1 */
.page[data-wx-state="rain"]      { --wx-cloud: 1;   --wx-fog: .22; --wx-dim: .21; }   /* P:923, rain 2 */
.page[data-wx-state="heavyrain"] { --wx-cloud: 1;   --wx-fog: .32; --wx-dim: .28; }   /* P:924, rain 3 */
.page[data-wx-state="downpour"]  { --wx-cloud: 1;   --wx-fog: .42; --wx-dim: .35; }   /* P:925, rain 4 */
.page[data-wx-state="sleet"]     { --wx-cloud: 1;   --wx-fog: .28; --wx-dim: .25; }   /* P:926, rain 2 snow 1 */
.page[data-wx-state="lightsnow"] { --wx-cloud: .9;  --wx-fog: .2;  --wx-dim: .16; }   /* P:927, snow 1 */
.page[data-wx-state="snow"]      { --wx-cloud: 1;   --wx-fog: .32; --wx-dim: .22; }   /* P:928, snow 2 */
.page[data-wx-state="blizzard"]  { --wx-cloud: 1;   --wx-fog: .6;  --wx-dim: .30; }   /* P:929, snow 3 */
.page[data-wx-state="thunder"]   { --wx-cloud: 1;   --wx-fog: .32; --wx-dim: .34; }   /* P:930, rain 3, flash */

/* =============================================================== 3. header
   P:119-224. Fixed, z 60, wrapping. .masthead, .wordmark and .nav are scoped
   under .top because notis.css styles base.html's own elements by those
   names; the scope also outranks `.page a` on the header's links. */

.top {                                                                         /* P:119 */
  position: fixed; top: 0; left: 0; right: 0; z-index: 60; display: flex; align-items: center;
  justify-content: space-between; gap: 20px; padding: 16px 30px 10px; flex-wrap: wrap;
}
/* NOT IN THE PROTOTYPE: the fixed header has no background, but its box spans the width and
   reaches over the date row, so it took the clicks meant for the date arrows and the calendar
   chip (Karl, 24 Sep: "back button doesnt work"). The box lets clicks through; its own
   pieces, and everything they open, still take them. */
.top { pointer-events: none; }
.top > * { pointer-events: auto; }
.top-left { display: flex; align-items: center; gap: 13px; }                   /* P:120 */

/* the spine: bordered so it reads as something that opens (R) */
.top .spine {                                                                  /* P:121 */
  display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 8px 5px; border-radius: 6px;
  border: 1px solid var(--bn-border); background: transparent; text-decoration: none; color: var(--bn-text-2);
}
.top .spine:hover { border-color: var(--bn-accent-green); color: var(--bn-accent-green); background: var(--bn-surface); }   /* P:121 style-hover */
.spine-text { font: 500 10px/1 var(--bn-font-mono); letter-spacing: .18em; writing-mode: vertical-rl; transform: rotate(180deg); }   /* P:122 */

/* the masthead */
/* "ai ▎notis" (Karl's direction A, 30 Sep): the edition's word before the bar, on the wordmark's
   baseline. One grid, so the word and the name share a row and the bar spans the area's row too. */
.top .masthead { display: grid; grid-template-columns: auto auto auto; column-gap: 13px; row-gap: 6px; align-items: baseline; border: 0; background: transparent; }   /* P:125 */
.masthead-ed { grid-column: 1; grid-row: 1; font: 700 25px/1 var(--bn-font-ui); color: var(--bn-accent-green); letter-spacing: -.01em; }
.masthead-rule { grid-column: 2; grid-row: 1 / span 2; align-self: center; width: 3.5px; height: 66px; background: var(--bn-accent-green); }   /* P:126 */
.masthead-grid { display: contents; }             /* P:127: its two children join the masthead's grid */
.top .masthead .wordmark { grid-column: 3; grid-row: 1; }
.top .masthead .area { grid-column: 3; grid-row: 2; justify-self: start; }
.top .wordmark { display: inline; font: 700 42px/1 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.025em; text-decoration: none; }   /* P:128; set type, not artwork (R) */

/* the area switcher and its 288px panel */
.area { position: relative; display: flex; }                                  /* P:129 */
.area-toggle {                                                                 /* P:130; ink P:1744 */
  display: inline-flex; align-items: center; gap: 7px; padding: 2px 5px 2px 0; border: 0; background: transparent;
  color: var(--bn-text-3); font: 500 11px/1 var(--bn-font-mono); letter-spacing: .26em; cursor: pointer;
}
.area.is-open .area-toggle { color: var(--bn-text); }
.area-chev { transform: rotate(0deg); transition: transform .22s ease; }      /* P:132; P:1745 */
.area.is-open .area-chev { transform: rotate(180deg); }
.area-panel {                                                                  /* P:135; shown P:134 */
  display: none; position: absolute; left: -6px; top: 26px; z-index: 70; width: 288px; border-radius: 10px;
  border: 1px solid var(--bn-border-strong); background: var(--bn-surface); box-shadow: var(--bn-shadow-3); overflow: hidden;
}
.area.is-open .area-panel { display: block; }
.area-head { display: block; padding: 12px 14px 9px; border-bottom: 1px solid var(--bn-border-subtle); font: 500 9.5px/1 var(--bn-font-mono); letter-spacing: .14em; color: var(--bn-text-3); }   /* P:136 */
.area-row { display: grid; gap: 4px; padding: 11px 14px; border-bottom: 1px solid var(--bn-border-subtle); text-decoration: none; background: transparent; }   /* P:138; row tint P:1749 */
.area-row.is-here { background: var(--bn-surface-2); }
.area-name { display: flex; align-items: center; gap: 8px; font: 700 14px/1.2 var(--bn-font-reading); color: var(--bn-text); }   /* P:139 */
.area-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--bn-border-strong); }   /* P:140; P:1750 */
.area-row.is-here .area-dot { background: var(--bn-accent-green); }
.area-tag { font: 500 9px/1 var(--bn-font-mono); letter-spacing: .1em; color: var(--bn-text-3); }   /* P:141 */
.area-note { font: 400 12.5px/1.4 var(--bn-font-reading); color: var(--bn-text-2); padding-left: 14px; text-wrap: pretty; }   /* P:143 */
.area-host { font: 500 10px/1 var(--bn-font-mono); color: var(--bn-text-3); padding-left: 14px; }   /* P:144 */
.area-foot { display: block; padding: 11px 14px; font: 400 12px/1.4 var(--bn-font-reading); color: var(--bn-text-3); }   /* P:147 */

/* the nav and its dropdowns */
.top-right, .top .nav, .top-tools { display: flex; align-items: center; gap: 24px; border: 0; }   /* P:154: one 24px gap across links and tools; the split is index.html's, for the phone */
.nav-item { position: relative; display: inline-flex; align-items: center; } /* P:156 */
.top .nav-link { display: inline-flex; align-items: center; gap: 6px; font: 500 12.5px/1 var(--bn-font-ui); color: var(--bn-text-2); text-decoration: none; }   /* P:157; ink P:1680 */
.nav-item.is-open > .nav-link, .nav-item:hover > .nav-link { color: var(--bn-text); }
.nav-chev { opacity: .55; }                                                   /* P:158 */
.nav-tab-icon { display: none; }                                              /* NOT IN THE PROTOTYPE: drawn only when the nav is the phone's tab bar (§13) */
.counter--phone { display: none; }                                           /* NOT IN THE PROTOTYPE: the phone's count (§13); hidden there too since t-39, the deck's progress line counts */
.menu, .menu-date, .top .menu-tab { display: none; }                         /* t-50, t-51: the phone's one-row header and its Menu tab (§13); the desktop never shows them (.top: past .top .nav-link) */
.nav-drop { display: none; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); padding-top: 11px; z-index: 95; }   /* P:161; the 11px is the hover bridge (R) */
.nav-item.is-open > .nav-drop, .nav-item:hover > .nav-drop { display: block; }   /* P:1676-1683: pointer enter and leave, so :hover is the same rule without script */
.nav-panel { display: grid; gap: 2px; min-width: 176px; padding: 7px; border-radius: 11px; background: var(--bn-surface); border: 1px solid var(--bn-border); box-shadow: var(--bn-shadow-3); }   /* P:162 */
.top .nav-sub { display: block; padding: 9px 11px; border-radius: 7px; font: 500 12.5px/1.2 var(--bn-font-ui); color: var(--bn-text-2); text-decoration: none; white-space: nowrap; }   /* P:164 */
.top .nav-sub:hover { background: var(--bn-surface-2); color: var(--bn-text); }   /* P:164 style-hover */

/* the filter */
.filter { position: relative; display: inline-flex; align-items: center; }   /* P:172 */
.filter-toggle {                                                               /* P:173; edge and bg P:1687-1689 */
  display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 14px; border-radius: 999px;
  border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text); font: 500 12.5px/1 var(--bn-font-ui); cursor: pointer;
}
.filter.is-open .filter-toggle { background: var(--bn-surface); }
.filter.is-open .filter-toggle, .filter.is-active .filter-toggle { border-color: var(--bn-accent-green); }
.filter-count {                                                                /* P:177; shown P:176 */
  display: none; align-items: center; justify-content: center; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
  background: var(--bn-accent-green); color: var(--bn-text-inverse); font: 600 9.5px/1 var(--bn-font-mono);
}
.filter.is-active .filter-count { display: inline-flex; }
.filter-drop { display: none; position: absolute; top: 100%; right: 0; padding-top: 11px; z-index: 96; }   /* P:181 */
.filter.is-open .filter-drop { display: block; }
.filter-panel { display: grid; gap: 4px; width: 252px; padding: 12px; border-radius: 12px; background: var(--bn-surface); border: 1px solid var(--bn-border); box-shadow: var(--bn-shadow-3); }   /* P:182 */
.filter-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 0 3px 7px; }   /* P:183 */
.filter-label { font: 500 9.5px/1 var(--bn-font-mono); letter-spacing: .13em; color: var(--bn-text-3); }   /* P:184 */
.filter-clear { display: none; border: 0; background: transparent; padding: 0; color: var(--bn-link); font: 500 10.5px/1 var(--bn-font-mono); cursor: pointer; }   /* P:186; shown P:185 */
.filter.is-active .filter-clear { display: inline-block; }
.filter-chip, .filter-saved {                                                  /* P:190, 197 */
  display: flex; align-items: center; gap: 10px; height: 34px; padding: 0 11px; border-radius: 8px;
  border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-2); font: 500 12.5px/1 var(--bn-font-ui); cursor: pointer; text-align: left;
}
.filter-chip.is-on { border-color: var(--beat); background: var(--bn-surface); color: var(--bn-text); }   /* P:1661-1663: the edge takes the category's hue */
.filter-chip .cat-dot { width: 7px; height: 7px; }                             /* P:191; index.html also writes the hue inline */
.filter-chip-label, .filter-saved-label { flex: 1; }                           /* P:192, 199 */
.filter-chip-count { font: 500 10px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:193 */
.filter-rule { height: 1px; background: var(--bn-border-subtle); margin: 6px 3px; }   /* P:196 */
.filter-saved svg { flex: 0 0 auto; fill: none; }                              /* P:198; fills when on (P:1668) */
.filter-saved.is-on { border-color: var(--bn-text); background: var(--bn-text); color: var(--bn-bg); }   /* P:1670-1672 */
.filter-saved.is-on svg { fill: currentColor; }

/* the search: the icon, then the field it becomes (P:206-219, is-open P:1690-1691) */
.search { display: inline-flex; align-items: center; }
.search-toggle { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 999px; border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-2); cursor: pointer; }   /* P:207 */
.search.is-open .search-toggle { display: none; }
.search-field { display: none; align-items: center; gap: 9px; height: 34px; padding: 0 6px 0 13px; border-radius: 999px; border: 1px solid var(--bn-accent-green); background: var(--bn-surface); }   /* P:212 */
.search.is-open .search-field { display: inline-flex; }
.search-field-icon { flex: 0 0 auto; color: var(--bn-text-3); width: 14px; height: 14px; }   /* P:213; the markup strokes currentColor */

/* ============================================================== keyframes
   P:18-31, under the file's names because the script writes them inline
   (skAurora, skTwinkle, skDrift, skGlide, skBob, wxFall, wxSway, wxFog,
   wxFlash, gxOpen, and scInA/scInB for the restack, P:1386). The tail's
   dc-in-a, dc-in-b and grid-open are the same three under its own names;
   all six are declared so either name resolves. scInA and scInB must stay
   byte-identical twins: alternating the name is what replays the entry. */
@keyframes scInA { from { transform: translate3d(118vw,-2%,0) rotate(9deg) scale(.95); opacity: 0 } }      /* P:18 */
@keyframes scInB { from { transform: translate3d(118vw,-2%,0) rotate(9deg) scale(.95); opacity: 0 } }      /* P:19 */
@keyframes dc-in-a { from { transform: translate3d(118vw,-2%,0) rotate(9deg) scale(.95); opacity: 0 } }    /* P:18, the tail's name */
@keyframes dc-in-b { from { transform: translate3d(118vw,-2%,0) rotate(9deg) scale(.95); opacity: 0 } }    /* P:19, the tail's name */
@keyframes skTwinkle { 0%,100% { opacity: .25 } 50% { opacity: 1 } }                                        /* P:20 */
@keyframes skDrift { from { transform: translateX(-16vw) } to { transform: translateX(116vw) } }            /* P:21 */
@keyframes skGlide { 0% { transform: translate(-12vw,0) } 50% { transform: translate(50vw,-3vh) } 100% { transform: translate(112vw,1vh) } }   /* P:22 */
@keyframes skBob { 0%,100% { transform: translate(0,0); opacity: .2 } 30% { opacity: .9 } 50% { transform: translate(2vw,-4vh); opacity: .55 } }   /* P:23 */
@keyframes skAurora { 0%,100% { transform: translateX(-7%) scaleY(1); opacity: .62 } 50% { transform: translateX(9%) scaleY(1.3); opacity: 1 } }   /* P:24 */
@keyframes skShimmer { 0%,100% { opacity: .14 } 50% { opacity: .58 } }                                      /* P:25 */
@keyframes wxFall { from { transform: translate3d(0,-16vh,0) } to { transform: translate3d(0,118vh,0) } }   /* P:26; rain and snow both fall on it */
@keyframes wxFlake { from { transform: translate3d(0,-12vh,0) } to { transform: translate3d(0,114vh,0) } }  /* P:27; declared in the file, used nowhere in it (P:109 uses wxFall) */
@keyframes wxSway { 0%,100% { margin-left: -16px } 50% { margin-left: 16px } }                               /* P:28 */
@keyframes wxFog { 0%,100% { transform: translateX(-9%) } 50% { transform: translateX(9%) } }               /* P:29 */
@keyframes wxFlash { 0%,90%,100% { opacity: 0 } 91% { opacity: .46 } 92.5% { opacity: .06 } 94% { opacity: .34 } 95.5% { opacity: 0 } }   /* P:30 */
@keyframes gxOpen { from { opacity: 0; transform: translateY(14px) } }                                      /* P:31 */
@keyframes grid-open { from { opacity: 0; transform: translateY(14px) } }                                   /* P:31, the tail's name */

@media (prefers-reduced-motion: reduce) {                                     /* P:32-34: the sky and the grid-open wrapper carry sk-anim; the cards do not */
  .sk-anim { animation: none !important; }
}

/* ==================================================== 4. the header's tail
   P:214-222: what the head stops short of. The search field's input and its
   close, the My page pill, and a few labels that carried no rule of their own. */

.search-input {                                                                /* P:214 */
  width: min(240px, 34vw); border: 0; outline: none; background: transparent;
  color: var(--bn-text); font: 400 12.5px/1 var(--bn-font-ui);
}
.search-close {                                                                /* P:215 */
  display: flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  border-radius: 999px; border: 0; background: transparent; color: var(--bn-text-3); cursor: pointer;
}
.mine-pill {                                                                   /* P:220, states P:1708-1710 */
  display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 14px;
  border-radius: 999px; border: 1px solid var(--bn-border); background: transparent;
  color: var(--bn-text-2); font: 500 11.5px/1 var(--bn-font-mono); cursor: pointer; flex: 0 0 auto;
}
.page[data-view="mine"] .mine-pill { border-color: var(--bn-text); background: var(--bn-text); color: var(--bn-bg); }   /* P:1708-1710: solid while My page is the view */
.mine-pill-label { white-space: nowrap; }                                      /* P:222 */
.mine-pill-n::before, .filter-saved-n::before { content: " · "; }             /* P:1707, 1667: "My page · N", "Saved · N"; the script writes N, the head hides the span while it is empty */
.area-label { white-space: nowrap; }                                           /* P:131 */
.sky-grad, .sky-glow { transition: background 1.8s linear; }                   /* P:40-41: painted inline by the script (P:1575-1576); the 1.8s is the aurora's pace (P:1578) */

/* ================================================================= 5. stage
   P:227, the prototype's <main>. The page ships it as .stage.is-still and the
   script lifts is-still once the document timeline is known to run
   (P:1021-1025); the deck's entry animation waits on that (section 6). */

.stage {                                                                       /* P:227 */
  position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: flex-start; gap: 0; padding: 84px 20px 152px; min-height: 0;
}
.notice-line { display: grid; gap: 14px; justify-items: center; text-align: center; }   /* P:229 */
.notice-label { font: 500 11.5px/1 var(--bn-font-mono); letter-spacing: .15em; color: var(--bn-text); }   /* P:230, reads NOTICE OF THE WEEK */
/* NOT IN THE PROTOTYPE: the label switches day and week (Karl, 24 Sep); it keeps its look,
   with a quiet underline on hover so it reads as the switch it is. */
.page a.notice-switch { color: var(--bn-text); text-decoration: none; text-underline-offset: 4px; }
.page a.notice-switch:hover { color: var(--bn-text); text-decoration: underline; text-decoration-color: var(--bn-accent-green); }
.span-switch { display: none; }                                              /* the phone's day/week chip (index.html); the desktop switches on the label */
.viewswitch, .ph-deck, .ph-grid, .ph-front-head, .ph-front { display: none; }   /* t-39: the phone's view switch and its three views (§13); the desktop never shows them */
.cal-switch { display: inline-block; margin-top: 10px; font: 500 12px/1 var(--bn-font-mono); letter-spacing: .06em; color: var(--bn-accent-green); text-decoration: none; }

/* ------------------------------------------------------------- the calendar */
.date-control { position: relative; display: flex; align-items: center; gap: 8px; }   /* P:232 */
.date-control .date-prev, .date-control .date-next {                           /* P:233, 242; scoped past `.page a` (P:15), the arrows being links here */
  display: flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  border-radius: 999px; border: 1px solid var(--bn-border); background: transparent;
  color: var(--bn-text-2); cursor: pointer;
}
.date-control a.date-prev:hover, .date-control a.date-next:hover { color: var(--bn-text-2); }   /* NOT IN THE PROTOTYPE: holds the ink against `.page a:hover` (P:16) */
.date-control .date-prev:disabled, .date-control .date-next:disabled { opacity: .4; cursor: default; }   /* NOT IN THE PROTOTYPE: the newest week has no next, the oldest no previous */
.date-toggle {                                                                 /* P:236, states P:1788-1789 */
  display: inline-flex; align-items: center; gap: 10px; height: 34px; padding: 0 16px;
  border-radius: 999px; border: 1px solid var(--bn-border); background: transparent;
  color: var(--bn-text); font: 500 13px/1 var(--bn-font-mono); cursor: pointer;
}
.date-control.is-open .date-toggle, .date-toggle[aria-expanded="true"] { border-color: var(--bn-accent-green); background: var(--bn-surface-2); }
.date-label { white-space: nowrap; }                                           /* P:238 */
.date-short { display: none; }                                                 /* t-39: the phone's form of the date, before the script writes it (§13) */
.date-sep { color: var(--bn-border-strong); }                                  /* P:239: the middle dot; the grid's and the lead's are the glue's (P:587, 675) */
.clock { font-variant-numeric: tabular-nums; }                                 /* P:240, 271 */

.cal-panel {                                                                   /* P:247; shown by the head under .date-control.is-open */
  position: absolute; top: calc(100% + 12px); left: 50%; transform: translateX(-50%); z-index: 90;
  width: 324px; padding: 16px; border-radius: 13px; background: var(--bn-surface);
  border: 1px solid var(--bn-border); box-shadow: var(--bn-shadow-3); text-align: left;
}
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 13px; }   /* P:248 */
.cal-month { font: 700 15px/1 var(--bn-font-reading); color: var(--bn-text); }   /* P:249 */
.cal-count { font: 500 10px/1 var(--bn-font-mono); letter-spacing: .11em; color: var(--bn-text-3); }   /* P:250 */
.cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; margin-bottom: 5px; }   /* P:252 */
.cal-weekday { text-align: center; font: 500 9.5px/1 var(--bn-font-mono); letter-spacing: .06em; color: var(--bn-text-3); padding: 4px 0; }   /* P:254 */
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }   /* P:257 */
.cal-cell {                                                                    /* P:259, states P:1502, 1509-1512 */
  position: relative; display: flex; align-items: center; justify-content: center; height: 32px;
  border-radius: 7px; border: 1px solid transparent; background: transparent; color: var(--bn-text-3);
  font: 500 12.5px/1 var(--bn-font-mono); cursor: default;
}
.cal-blank { pointer-events: none; }                                           /* P:1500-1503: the lead's empty cells */
.cal-day { cursor: default; }                                                  /* P:1507: a day that carries no edition */
.cal-day.has-edition { border-color: var(--bn-border); color: var(--bn-text); cursor: pointer; }   /* P:1509-1511 */
.cal-day.is-selected, .cal-day[aria-current="date"] { border-color: var(--bn-accent-green); background: var(--bn-action-subtle); color: var(--bn-text); cursor: pointer; }   /* P:1512 */
.cal-grid a.cal-day:hover { color: var(--bn-text); }                           /* NOT IN THE PROTOTYPE: holds the ink against `.page a:hover` (P:16) */
.cal-dot { position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 999px; background: var(--bn-accent-green); }   /* P:261 */
.cal-note { margin: 13px 0 0; font: 400 12.5px/1.45 var(--bn-font-reading); color: var(--bn-text-3); text-wrap: pretty; }   /* P:266 */

.cal-clock { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--bn-border-subtle); display: grid; gap: 10px; }   /* P:268 */
.cal-clock-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }   /* P:269 */
.cal-clock-now { display: flex; align-items: baseline; gap: 9px; }            /* P:270 */
.cal-clock-time { font: 700 26px/1 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.03em; font-variant-numeric: tabular-nums; }   /* P:271 */
.cal-clock-name { font: 400 12.5px/1 var(--bn-font-reading); color: var(--bn-text-2); }   /* P:272 */
.cal-live {                                                                    /* P:274, states P:1645-1647: HOUR nn is the bordered look, LIVE the lit one */
  display: inline-flex; align-items: center; gap: 6px; height: 23px; padding: 0 10px;
  border-radius: 999px; border: 1px solid var(--bn-border); background: transparent;
  color: var(--bn-text-2); font: 500 9.5px/1 var(--bn-font-mono); letter-spacing: .09em;
  cursor: pointer; flex: 0 0 auto;
}
.cal-live.is-live { border-color: transparent; background: var(--bn-action-subtle); color: var(--bn-link); }
.cal-live-dot { width: 5px; height: 5px; border-radius: 999px; background: var(--bn-text-3); }   /* P:275, 1648 */
.cal-live.is-live .cal-live-dot { background: var(--bn-accent-green); }
.cal-live-hour { font-variant-numeric: tabular-nums; }                         /* P:275 */
.cal-ticks { display: flex; align-items: flex-end; gap: 2px; height: 20px; }   /* P:278 */
.cal-tick {                                                                    /* P:280; the hour's 22px accent-green, a night hour's 8px border-strong and a dawn hour's 13px border (P:1563-1567) are the script's, written inline */
  width: 9px; height: 13px; padding: 0; border: 0; border-radius: 2px; background: var(--bn-border);
  cursor: pointer; transition: height .25s ease, background .25s ease;
}

/* -------------------------------------------------------------- the weather */
.wx-line { display: grid; gap: 9px; justify-items: center; }                  /* P:288 */
.wx { position: relative; display: flex; align-items: center; gap: 10px; }    /* P:289 */
.wx-pill {                                                                     /* P:290, edge P:1606 */
  display: inline-flex; align-items: center; gap: 9px; height: 28px; padding: 0 13px;
  border-radius: 999px; border: 1px solid var(--bn-border); background: var(--bn-surface);
  font: 500 11px/1 var(--bn-font-mono); letter-spacing: .05em; color: var(--bn-text); cursor: pointer;
}
.wx.is-open .wx-pill, .wx-pill[aria-expanded="true"], .wx-pill.is-on { border-color: var(--bn-accent-green); }   /* P:1606: open, or a state forced by hand */
.wx-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--bn-accent-green); }   /* P:291, colour P:1602 */
.wx-pill[data-state="drizzle"] .wx-dot, .wx-pill[data-state="rain"] .wx-dot, .wx-pill[data-state="sleet"] .wx-dot,
.wx-pill[data-state="lightsnow"] .wx-dot { background: var(--bn-link); }      /* rain or snow at all */
.wx-pill[data-state="heavyrain"] .wx-dot, .wx-pill[data-state="downpour"] .wx-dot, .wx-pill[data-state="thunder"] .wx-dot,
.wx-pill[data-state="snow"] .wx-dot, .wx-pill[data-state="blizzard"] .wx-dot { background: var(--bn-accent-gold); }   /* rain above 2 or snow above 1 */
.wx-readout { white-space: nowrap; }                                           /* P:291 */
.wx-chev { opacity: .5; }                                                      /* P:292 */

.wx-drop { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); padding-top: 10px; z-index: 94; }   /* P:296; shown by the head under .wx.is-open */
.wx-panel {                                                                    /* P:297 */
  display: grid; gap: 12px; width: 306px; padding: 14px; border-radius: 12px;
  background: var(--bn-surface); border: 1px solid var(--bn-border); box-shadow: var(--bn-shadow-3); text-align: left;
}
.wx-group { display: grid; gap: 7px; }                                         /* P:298 */
.wx-group + .wx-group { padding-top: 11px; border-top: 1px solid var(--bn-border-subtle); }   /* P:306, 314 */
.wx-group-label { font: 500 9.5px/1 var(--bn-font-mono); letter-spacing: .13em; color: var(--bn-text-3); }   /* P:299, 307, 315 */
.wx-options { display: flex; flex-wrap: wrap; gap: 5px; }                      /* P:300 */
.wx-option {                                                                   /* P:302, states P:1612-1614 */
  display: inline-flex; align-items: center; height: 27px; padding: 0 10px; border-radius: 7px;
  border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-2);
  font: 500 11px/1 var(--bn-font-ui); cursor: pointer;
}
.wx-options--row { flex-wrap: nowrap; }                                        /* P:308, 316: three equal, then five */
.wx-options--row .wx-option { flex: 1; justify-content: center; height: 29px; padding: 0 4px; }   /* P:310, 318; states P:1622-1624, 1634-1636 */
.wx-option[data-step] { font-size: 10.5px; }                                   /* P:318 */
.wx-option.is-on { border-color: var(--bn-accent-green); background: var(--bn-action-subtle); color: var(--bn-text); }
.locate {                                                                      /* P:326: the one press that may ask the browser where the reader is */
  display: inline-flex; align-items: center; gap: 7px; height: 28px; padding: 0 13px;
  border-radius: 999px; border: 1px solid var(--bn-border-strong); background: transparent;
  color: var(--bn-text); font: 500 11px/1 var(--bn-font-mono); cursor: pointer;
}

.stage-title { margin: 0; font: 700 36px/1.12 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.026em; text-wrap: pretty; }   /* P:335 */

/* ================================================================== 6. deck */

.view-deck { flex: 1; width: 100%; align-items: flex-start; justify-content: center; padding: 44px 0 66px; min-height: 0; }   /* P:431; display is the head's, under data-view */
.deck {                                                                        /* P:432 */
  --step: 1;
  position: relative; width: min(446px, 86vw); aspect-ratio: 9 / 13; perspective: 2200px;
  touch-action: pan-y; user-select: none; -webkit-user-select: none;
}

/* The resting pile is the card's default state, so the leads render with no
   script: each card sits 14px * step lower and 3.5% smaller per depth, from
   its bottom edge (P:1432-1434). */
.dc {                                                                          /* P:434 */
  --depth: 0;
  --fan-t: 0;
  --fan-push: 1;
  --fan-lift: 0px;
  --fan-scale: .78;
  --fan-z: 50;
  --drag-x: 0;
  --drag-y: 0;
  --fly-dir: 1;
  position: absolute; inset: 0; transform-style: preserve-3d; will-change: transform;
  transform-origin: bottom center;                                             /* P:1433 */
  transform: translate3d(0, calc(var(--depth) * 14px * var(--step)), 0) scale(calc(1 - var(--depth) * .035));   /* P:1434 */
  transition: transform .62s cubic-bezier(.26,.9,.24,1), opacity .5s ease;   /* P:1435 */
  z-index: calc(50 - var(--depth));                                            /* P:1389 */
  opacity: 1; pointer-events: auto; cursor: default;                           /* P:1388, 1390, 1448 */
  animation: dc-in-a calc(880ms - var(--depth) * 80ms) cubic-bezier(.26,.9,.24,1);   /* P:1385-1387: 880ms on top, 80ms less per depth; the restack replays it under scInA/scInB, written inline (P:1386) */
}
.stage.is-still .dc, .stage.is-still .dc-inner { animation: none; transition: none; }   /* P:1387, 1442, 1476: the page ships .stage.is-still; until the script lifts it no card enters or moves */
.dc.is-top { transform: translate3d(0, 0, 30px) scale(1); cursor: grab; }     /* P:1384, 1390, 1434 */

.dc.is-fanned {                                                                /* P:1404-1425 */
  transform-origin: center;                                                    /* P:1391 */
  transform: translate3d(calc(var(--fan-t) * var(--fan-push) * min(140px, 10.5vw)), calc(var(--fan-t) * var(--fan-t) * 16px + var(--fan-lift)), 0) rotate(calc(var(--fan-t) * 8deg)) scale(var(--fan-scale));   /* P:1418 */
  transition: transform .48s cubic-bezier(.26,.9,.24,1), opacity .35s ease;   /* P:1422 */
  animation: none; cursor: pointer; z-index: var(--fan-z);                    /* P:1419, 1423-1424 */
}
.dc.is-fanned.is-hovered { --fan-lift: -16px; --fan-scale: .82; z-index: 56; }   /* P:1416-1419 */
.dc.is-fanned.is-focused { transform: translate3d(0px, -10px, 80px) rotate(0deg) scale(1); z-index: 62; opacity: 1; }   /* P:1410-1411 */

.dc.is-dragging {                                                              /* P:1426-1430 */
  transform-origin: center;
  transform: translate3d(calc(var(--drag-x) * 1px), calc(var(--drag-y) * .4px), 40px) rotate(calc(var(--drag-x) * .028deg)) scale(1.008);   /* P:1427 */
  transition: transform .07s linear; animation: none; cursor: grabbing;      /* P:1428-1429 */
}
.dc.is-flying {                                                                /* P:1393-1398 */
  transform-origin: center;
  transform: translate3d(calc(var(--fly-dir) * 135%), -6%, 0) rotate(calc(var(--fly-dir) * 26deg)) scale(.96);   /* P:1394 */
  transition: transform .42s cubic-bezier(.3,.6,.2,1), opacity .42s ease;    /* P:1395 */
  opacity: 0; animation: none;                                                 /* P:1396-1397 */
}
.dc.is-out { transform: translate3d(0, 0, 0) scale(.96); transition: none; opacity: 0; animation: none; }   /* P:1399-1403: filtered out */
.dc.is-flying, .dc.is-out { z-index: 0; pointer-events: none; }               /* P:1445, 1448: an invisible card never wins a hit test */

.dc-inner {                                                                    /* P:435; shadow P:1388, flip P:1475-1476 */
  position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
  transform: rotateY(0deg); transition: transform .6s cubic-bezier(.4,.02,.2,1);
  box-shadow: var(--bn-shadow-2); border-radius: 13px;
}
.dc.is-flipped .dc-inner { transform: rotateY(180deg); }
.dc.is-top .dc-inner, .dc.is-fanned .dc-inner, .dc.is-dragging .dc-inner, .dc.is-flying .dc-inner { box-shadow: var(--bn-shadow-3); }   /* P:1398, 1425, 1430, 1437 */

.dc-face, .dc-back {                                                           /* P:17 */
  position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  border-radius: 13px; overflow: hidden; background: var(--bn-surface); border: 1px solid var(--bn-border);
  display: flex; flex-direction: column;
}
.dc-back { transform: rotateY(180deg); background: var(--bn-surface-2); }      /* P:510 */

/* the front */
.dc-head { padding: 20px 22px 16px; display: grid; gap: 11px; flex: 0 0 auto; }   /* P:438 */
.dc-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; }   /* P:439 */
.dc-pills { display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap; }   /* P:440 */
.dc-kind {                                                                     /* P:441, colours P:1454-1457 */
  display: inline-flex; align-items: center; height: 25px; padding: 0 10px; border-radius: 5px;
  border: 1px solid var(--kind); background: var(--kind-bg); color: var(--kind-ink);
  font: 600 9.5px/1 var(--bn-font-mono); letter-spacing: .13em; text-transform: uppercase;
}
.dc-cat {                                                                      /* P:442, ink P:1453 */
  display: inline-flex; align-items: center; gap: 7px; height: 25px; padding: 0 11px; border-radius: 999px;
  border: 1px solid var(--bn-border); font: 600 10px/1 var(--bn-font-mono); letter-spacing: .11em;
  text-transform: uppercase; color: var(--bn-text-2);
}
.dc-cat-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--beat); }   /* P:443 */
.dc-date { font: 500 11px/1 var(--bn-font-mono); letter-spacing: .09em; color: var(--bn-text-3); }   /* P:445 */
.dc-actions { display: flex; align-items: center; gap: 7px; flex: 0 0 auto; }   /* P:447 */
.dc-copied { font: 500 9.5px/1 var(--bn-font-mono); letter-spacing: .1em; color: var(--bn-accent-green); }   /* P:449, gone again after 1800ms (P:1214) */
.dc-share, .dc-save {                                                          /* P:451, 459; inks P:1460, 1470 */
  display: flex; align-items: center; justify-content: center; width: 32px; height: 32px;
  border-radius: 999px; border: 1px solid var(--bn-border); background: transparent;
  color: var(--bn-text-3); cursor: pointer; flex: 0 0 auto;
}
.dc.is-copied .dc-share, .dc.is-saved .dc-save, .dc-save[aria-pressed="true"] { color: var(--bn-accent-green); }
.dc-save svg { fill: none; }                                                   /* P:460, 1461 */
.dc.is-saved .dc-save svg, .dc-save[aria-pressed="true"] svg { fill: currentColor; }
.dc-title { margin: 0; font: 700 29px/1.13 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.022em; text-wrap: pretty; }   /* P:464 */
.dc-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }   /* P:465 */
.dc-tag {                                                                      /* P:467 */
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 5px;
  background: var(--bn-surface-2); border: 1px solid var(--bn-border-subtle);
  font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-2);
}
/* The image frame. The prototype's wash and art were placeholder gradients
   per notice (P:471-472, README); ours is the note's media, so the ground is a
   surface token and the picture fills the frame. */
.dc-art { position: relative; overflow: hidden; background: var(--bn-surface-2); aspect-ratio: 16 / 9; flex: 0 0 auto; }   /* P:471 */
/* No picture: the prototype's c.wash and c.art, one dark tint per beat with a
   diagonal fall-off (P:790-794). Mixed from the beat's hue so a new beat brings
   its own wash without a new rule; --beat is the card's data-beat (head). */
.dc-art--wash {
  background: linear-gradient(140deg, color-mix(in srgb, var(--beat) 34%, var(--bn-surface-2)), color-mix(in srgb, var(--beat) 12%, var(--bn-bg)) 72%);
}
.dc-art-img, .dc-art > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }   /* P:472 */
.dc-body { padding: 18px 24px 20px; display: flex; flex-direction: column; gap: 14px; flex: 1 1 auto; min-height: 0; }   /* P:481 */
.dc-dek { margin: 0; font: 400 18px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; flex: 0 0 auto; }   /* P:482 */
/* The provenance band. Its rows are flex: 1 1 0 so the slack goes into row
   spacing and never pools as a void at the foot of a tall card (P:484). */
.dc-band { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }   /* P:483 */
.dc-row {                                                                      /* P:484, 488, 492, 496 */
  display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 0;
  border-top: 1px solid var(--bn-border-subtle); flex: 1 0 auto;
}
/* A card holds a fixed shape (9:13), so a long title, two rows of tags and a
   three-line standfirst can ask for more height than it has. The rows used to
   shrink to nothing and print over each other and over the foot (Karl's phone,
   24 Sep). Now they keep their height and the picture gives way: its frame may
   shrink from 16:9 down to 96px, and the image crops rather than squashes. */
.dc-art { flex-shrink: 1; min-height: 96px; }
.dc-body, .dc-band { flex-shrink: 0; }                                        /* the text keeps its height; only the picture yields */
.dc-label { font: 500 10.5px/1 var(--bn-font-mono); letter-spacing: .12em; color: var(--bn-text-3); flex: 0 0 auto; }   /* P:485 */
.dc-val { font: 400 13.5px/1.3 var(--bn-font-reading); color: var(--bn-text-2); text-align: right; }   /* P:486 */
.dc-val-link { color: var(--bn-link); }                                        /* P:494; its links take `.page a` */
.dc-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex: 0 0 auto; padding-top: 2px; }   /* P:501 */
.dc-kicker { font: 500 11px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:502 */
.dc-cue { display: inline-flex; align-items: center; gap: 6px; font: 500 11.5px/1 var(--bn-font-mono); color: var(--bn-link); }   /* P:503 */

/* the back */
.dc-back-head { display: flex; align-items: flex-start; gap: 14px; padding: 20px 24px 15px; border-bottom: 1px solid var(--bn-border-subtle); }   /* P:511 */
.dc-back-thumb { width: 46px; height: 46px; border-radius: 7px; background: var(--bn-surface-3); background-size: cover; flex: 0 0 auto; overflow: hidden; }   /* P:512 */
.dc-back-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dc-back-meta { display: grid; gap: 8px; min-width: 0; }                       /* P:513 */
.dc-back-kicker { font: 500 11px/1 var(--bn-font-mono); letter-spacing: .09em; color: var(--bn-text-3); }   /* P:514 */
.dc-back-title { margin: 0; font: 700 21px/1.2 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.014em; text-wrap: pretty; }   /* P:515 */
.dc-back-body { padding: 17px 24px; display: grid; gap: 13px; flex: 1; overflow: auto; }   /* P:518 */
.dc-back-body p { margin: 0; font: 400 15.5px/1.6 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:519-521 */
.dc-back-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding-top: 4px; border-top: 1px solid var(--bn-border-subtle); }   /* P:522 */
.dc-back-tags-label { font: 500 10px/1 var(--bn-font-mono); letter-spacing: .12em; color: var(--bn-text-3); margin-right: 4px; padding-top: 9px; }   /* P:523 */
.dc-back-tag {                                                                 /* P:525 */
  display: inline-flex; align-items: center; height: 22px; margin-top: 9px; padding: 0 9px; border-radius: 5px;
  background: var(--bn-surface); border: 1px solid var(--bn-border-subtle);
  font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-2);
}
.dc-back-foot { padding: 14px 24px 18px; border-top: 1px solid var(--bn-border-subtle); display: flex; align-items: center; justify-content: space-between; gap: 10px; }   /* P:529 */
.dc-back-source { font: 500 11.5px/1 var(--bn-font-mono); color: var(--bn-link); }   /* P:530 */
.dc-back-close { font: 500 11px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:531 */

/* the two end states over the deck; the head shows them under .deck.is-empty and .deck.is-spent */
.deck-empty, .deck-spent {                                                     /* P:540 (nothing in this filter), 551 (that is the week) */
  position: absolute; inset: 0; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; padding: 32px; border-radius: 13px; border: 1px dashed var(--bn-border-strong);
  background: var(--bn-surface-2); text-align: center;
}
.deck-spent { gap: 18px; padding: 0; }                                         /* P:551 */
.deck-empty-label { font: 500 10.5px/1 var(--bn-font-mono); letter-spacing: .14em; color: var(--bn-text-3); }   /* P:541 */
.deck-empty-text, .deck-spent-text { font: 400 19px/1.35 var(--bn-font-reading); color: var(--bn-text-2); max-width: 24ch; text-wrap: pretty; }   /* P:542 */
.deck-spent-text { max-width: 26ch; text-align: center; }                     /* P:552 */
.deck-empty-actions { display: flex; align-items: center; gap: 10px; }        /* P:543 */
.deck-clear, .deck-restack {                                                   /* P:544 */
  height: 42px; padding: 0 22px; border-radius: 999px; border: 0; background: var(--bn-accent-green);
  color: var(--bn-text-inverse); font: 600 12px/1 var(--bn-font-mono); cursor: pointer;
}
.deck-restack { height: 44px; padding: 0 24px; font-size: 12.5px; }           /* P:553 */
.deck-archive { font: 500 11.5px/1 var(--bn-font-mono); }                      /* P:545; link ink from `.page a` */

/* NOT IN THE PROTOTYPE: launch week, before any edition exists. The site's own
   words in the deck's place, set as the card's face sets its title and dek. */
.deck-launch { width: min(560px, 86vw); display: grid; gap: 14px; text-align: center; padding: 24px 0; }
.deck-launch-title { margin: 0; font: 700 29px/1.13 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.022em; text-wrap: pretty; }
.deck-launch p { margin: 0; font: 400 16.5px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }
.deck-launch .thin { color: var(--bn-text-3); }
.deck-launch a { text-decoration: underline; text-underline-offset: 2px; }

/* ================================================================== 7. grid */

.grid {                                                                        /* P:561 */
  width: 100%; max-width: 1200px; padding: 30px 0 10px; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)); gap: 20px; align-items: stretch;
  grid-auto-flow: dense; grid-auto-rows: minmax(384px, auto);
}
.grid-card {                                                                   /* P:563; edge, shadow, span P:1536-1542 */
  grid-column: auto; grid-row: auto; border-radius: 12px; overflow: hidden; background: var(--bn-surface);
  border: 1px solid var(--bn-border); box-shadow: var(--bn-shadow-2); display: flex; flex-direction: column;
  cursor: pointer; transition: box-shadow .45s cubic-bezier(.22,.9,.26,1), border-color .45s ease;
}
.grid-card.is-top, .grid-card.is-open, .grid-card[aria-expanded="true"] { border-color: var(--bn-accent-green); }
.grid-card.is-open, .grid-card[aria-expanded="true"] { grid-column: span 2; grid-row: span 2; box-shadow: var(--bn-shadow-3); }

/* open; the glue shows one face and hides the other */
.grid-card-open { display: flex; flex-direction: column; animation: grid-open .62s cubic-bezier(.2,.86,.24,1); }   /* P:565 */
.grid-card-open-body { display: grid; gap: 14px; align-content: start; padding: 20px 24px 24px; }   /* P:566 */
.grid-card-open-meta { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }   /* P:567 */
.grid-card-open-kind {                                                         /* P:568 */
  display: inline-flex; align-items: center; height: 23px; padding: 0 9px; border-radius: 5px;
  border: 1px solid var(--kind); background: var(--kind-bg); color: var(--kind-ink);
  font: 600 9px/1 var(--bn-font-mono); letter-spacing: .12em; text-transform: uppercase;
}
.grid-card-open-cat, .grid-card-cat {                                          /* P:569, 616 */
  display: inline-flex; align-items: center; gap: 6px; height: 23px; padding: 0 10px; border-radius: 999px;
  border: 1px solid var(--bn-border); font: 600 9.5px/1 var(--bn-font-mono); letter-spacing: .11em;
  text-transform: uppercase; color: var(--bn-text-2);
}
.grid-card-cat { gap: 7px; }                                                   /* P:616 */
.grid-card-open-cat-dot, .grid-card-cat-dot { width: 5px; height: 5px; border-radius: 999px; background: var(--beat); }   /* P:570, 617 */
.grid-card-open-date, .grid-card-date { font: 500 10px/1 var(--bn-font-mono); letter-spacing: .09em; color: var(--bn-text-3); }   /* P:572, 620 */
.grid-card-open-title { margin: 0; font: 700 27px/1.13 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.022em; text-wrap: pretty; }   /* P:574 */
.grid-card-open-dek { margin: 0; font: 400 16.5px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:575 */
.grid-card-open-text { columns: 2; column-gap: 30px; }                          /* P:576 */
.grid-card-open-text p { margin: 0 0 12px; font: 400 14.5px/1.6 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:577-578 */
.grid-card-open-text p:last-child { margin: 0; }                               /* P:579 */
.grid-card-open-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }   /* P:581 */
.grid-card-open-tag {                                                          /* P:583 */
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 5px;
  background: var(--bn-surface-2); border: 1px solid var(--bn-border-subtle);
  font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-2);
}
.grid-card-open-prov {                                                         /* P:586 */
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding-top: 13px;
  border-top: 1px solid var(--bn-border-subtle); font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-3);
}
.grid-card-open-prov a { color: var(--bn-link); }                              /* P:587 */
.grid-card-open-deck {                                                         /* P:589 */
  justify-self: start; display: inline-flex; align-items: center; gap: 8px; height: 38px; padding: 0 18px;
  border-radius: 999px; border: 0; background: var(--bn-accent-green); color: var(--bn-text-inverse);
  font: 600 11.5px/1 var(--bn-font-mono); cursor: pointer;
}
.grid-card-open-art { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: var(--bn-surface-2); order: -1; flex: 0 0 auto; }   /* P:593 */
.grid-card-open-art > img, .grid-card-art > img, .editorial-lead-art > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.grid-card-open-tools { position: absolute; top: 14px; right: 14px; display: flex; align-items: center; gap: 8px; }   /* P:594 */
.grid-card-open-save, .grid-card-open-close {                                  /* P:595, 598; ink P:1543 */
  display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--bn-stone-0) 30%, transparent);
  background: var(--bn-overlay);
  background: color-mix(in srgb, var(--bn-night-950) 55%, transparent);
  color: var(--bn-stone-0); cursor: pointer;
}
.grid-card.is-saved .grid-card-open-save, .grid-card-open-save[aria-pressed="true"] { color: var(--bn-accent-green); }
.grid-card-open-save svg { fill: none; }
.grid-card.is-saved .grid-card-open-save svg, .grid-card-open-save[aria-pressed="true"] svg { fill: currentColor; }

/* closed */
.grid-card-head { padding: 14px 16px 12px; display: grid; gap: 9px; }          /* P:614 */
.grid-card-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; }   /* P:615 */
.grid-card-side { display: inline-flex; align-items: center; gap: 8px; }       /* P:619 */
.grid-card-save {                                                              /* P:621, ink P:1533 */
  display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 999px;
  border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-3); cursor: pointer;
}
.grid-card.is-saved .grid-card-save, .grid-card-save[aria-pressed="true"] { color: var(--bn-accent-green); }
.grid-card-save svg { fill: none; }
.grid-card.is-saved .grid-card-save svg, .grid-card-save[aria-pressed="true"] svg { fill: currentColor; }
.grid-card-title { margin: 0; font: 700 19px/1.2 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.014em; text-wrap: pretty; }   /* P:626 */
.grid-card-art { position: relative; aspect-ratio: 16 / 9; background: var(--bn-surface-2); flex: 0 0 auto; opacity: 1; }   /* P:628 */
.grid-card.is-done .grid-card-art { opacity: .42; }                            /* P:1538: already read */
.grid-card-body { padding: 14px 16px 16px; display: grid; gap: 12px; }         /* P:637 */
.grid-card-dek { margin: 0; font: 400 14.5px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:638 */
.grid-card-tags { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }   /* P:639 */
.grid-card-tag {                                                               /* P:641 */
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px; border-radius: 5px;
  background: var(--bn-surface-2); border: 1px solid var(--bn-border-subtle);
  font: 500 10px/1 var(--bn-font-mono); color: var(--bn-text-2);
}
.grid-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-top: 11px; border-top: 1px solid var(--bn-border-subtle); }   /* P:644 */
.grid-card-source { font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:645 */
.grid-card-state { font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-link); }   /* P:646, ink P:1545 */
.grid-card.is-done .grid-card-state { color: var(--bn-text-3); }

/* ============================================================= 8. editorial */

.ed { width: 100%; max-width: 1080px; padding: 26px 0 14px; display: grid; gap: 22px; }   /* P:656 */
.ed-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding-bottom: 12px; border-bottom: 2px solid var(--bn-text); }   /* P:657 */
.ed-title { font: 700 23px/1 var(--bn-font-reading); letter-spacing: -.022em; color: var(--bn-text); }   /* P:658 */
.ed-count { font: 500 10.5px/1 var(--bn-font-mono); letter-spacing: .13em; color: var(--bn-text-3); }   /* P:659 */

.editorial-lead {                                                              /* P:663 */
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 30px; align-items: start;
  padding-bottom: 22px; border-bottom: 1px solid var(--bn-border); cursor: pointer;
}
.editorial-lead-text { display: grid; gap: 13px; }                              /* P:664 */
.editorial-lead-meta { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }   /* P:665 */
.editorial-lead-kind {                                                         /* P:666 */
  display: inline-flex; align-items: center; height: 24px; padding: 0 10px; border-radius: 5px;
  border: 1px solid var(--kind); background: var(--kind-bg); color: var(--kind-ink);
  font: 600 9.5px/1 var(--bn-font-mono); letter-spacing: .13em; text-transform: uppercase;
}
.editorial-lead-cat {                                                          /* P:667 */
  display: inline-flex; align-items: center; gap: 7px; height: 24px; padding: 0 11px; border-radius: 999px;
  border: 1px solid var(--bn-border); font: 600 9.5px/1 var(--bn-font-mono); letter-spacing: .11em;
  text-transform: uppercase; color: var(--bn-text-2);
}
.editorial-lead-cat-dot, .editorial-item-cat-dot { width: 5px; height: 5px; border-radius: 999px; background: var(--beat); }   /* P:668, 701 */
.editorial-lead-date { font: 500 10.5px/1 var(--bn-font-mono); letter-spacing: .09em; color: var(--bn-text-3); }   /* P:670 */
.editorial-lead-title { margin: 0; font: 700 40px/1.08 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.028em; text-wrap: pretty; }   /* P:672 */
.editorial-lead-dek { margin: 0; max-width: 52ch; font: 400 18px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:673 */
.editorial-lead-prov { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:674 */
.editorial-lead-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }   /* P:677 */
.editorial-lead-tag {                                                          /* P:679 */
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 5px;
  background: var(--bn-surface-2); border: 1px solid var(--bn-border-subtle);
  font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-2);
}
.editorial-lead-art { position: relative; aspect-ratio: 16 / 9; border-radius: 10px; overflow: hidden; background: var(--bn-surface-2); }   /* P:683 */

.ed-rest { display: grid; grid-template-columns: repeat(auto-fit, minmax(214px, 1fr)); gap: 0; }   /* P:695 */

/* NOT IN THE PROTOTYPE: the record and the edition's two lines. The prototype's
   editorial view ends at the seven items; the publication has a record under
   its leads and an opener and last line around them (design brief §5, §8). */
.editorial-lead-title a, .editorial-item-title a, .grid-card-open-title a { color: inherit; }
.editorial-lead-title a:hover, .editorial-item-title a:hover, .grid-card-open-title a:hover { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.ed-head--record { margin-top: 26px; }
.ed-record { list-style: none; margin: 0; padding: 0; display: grid; }
.ed-record-row {
  display: grid; grid-template-columns: 58px minmax(0, 1fr) auto; gap: 14px; align-items: baseline;
  padding: 11px 0; border-top: 1px solid var(--bn-border-subtle);
}
.ed-record-row:first-child { border-top: 0; }
.ed-record-date, .ed-record-side { font: 500 10.5px/1.3 var(--bn-font-mono); letter-spacing: .09em; color: var(--bn-text-3); }
.ed-record-side { text-align: right; white-space: nowrap; }
.ed-record-row a { font: 400 16.5px/1.35 var(--bn-font-reading); color: var(--bn-text); text-wrap: pretty; }
.ed-record-row a:hover { color: var(--bn-text); text-decoration: underline; text-underline-offset: 3px; }
.ed-last { margin: 8px 0 0; max-width: 52ch; font: 400 16.5px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }
.deck-spent-last { display: block; max-width: 30ch; text-align: center; font: 400 15px/1.45 var(--bn-font-reading); color: var(--bn-text-3); text-wrap: pretty; }
.editorial-item { display: grid; gap: 9px; align-content: start; padding: 0 18px; border-left: 1px solid var(--bn-border); cursor: pointer; }   /* P:697 */
.editorial-item-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }   /* P:698 */
.editorial-item-kind {                                                         /* P:699 */
  display: inline-flex; align-items: center; height: 21px; padding: 0 8px; border-radius: 4px;
  border: 1px solid var(--kind); background: var(--kind-bg); color: var(--kind-ink);
  font: 600 8.5px/1 var(--bn-font-mono); letter-spacing: .12em; text-transform: uppercase;
}
.editorial-item-cat { display: inline-flex; align-items: center; gap: 5px; font: 600 9px/1 var(--bn-font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--bn-text-2); }   /* P:700, no border */
.editorial-item-title { margin: 0; font: 700 19px/1.2 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.016em; text-wrap: pretty; }   /* P:704 */
.editorial-item-dek { margin: 0; font: 400 14px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:705 */
.editorial-item-line { font: 500 10px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:706 */

/* =============================================================== 9. my page */

.view-mine { width: 100%; max-width: 1040px; padding: 34px 0 120px; gap: 30px; }   /* P:339; display is the head's, under data-view */
.mine-head { display: grid; gap: 14px; padding-bottom: 22px; border-bottom: 2px solid var(--bn-text); }   /* P:340 */
.view-mine .mine-back {                                                        /* P:341; scoped past `.page a` (P:15), a link here */
  display: inline-flex; align-items: center; gap: 8px; justify-self: start; height: 30px; padding: 0 12px 0 9px;
  border-radius: 999px; border: 1px solid var(--bn-border); background: transparent;
  color: var(--bn-text-2); font: 500 11px/1 var(--bn-font-mono); cursor: pointer;
}
.view-mine a.mine-back:hover { color: var(--bn-text-2); }                       /* NOT IN THE PROTOTYPE: holds the ink against `.page a:hover` (P:16) */
.mine-title { margin: 0; font: 700 40px/1.06 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.03em; }   /* P:345 */
.mine-lead { margin: 0; max-width: 56ch; font: 400 16.5px/1.5 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:346 */

.mine-figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0; border: 1px solid var(--bn-border); border-radius: 9px; overflow: hidden; }   /* P:349 */
.mine-fig { display: grid; gap: 7px; padding: 20px 22px; border-right: 1px solid var(--bn-border-subtle); }   /* P:350 */
.mine-fig:last-child { border-right: 0; }                                      /* P:362 */
.mine-fig-label { font: 500 10px/1 var(--bn-font-mono); letter-spacing: .14em; color: var(--bn-text-3); }   /* P:351 */
.mine-fig-n { font: 700 30px/1 var(--bn-font-reading); color: var(--bn-text); }   /* P:352 */

.mine-saved, .mine-cols-section, .mine-digest { display: grid; gap: 15px; }   /* P:368, 405, 418 */
.mine-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }   /* P:369 */
.mine-section-label { font: 500 11px/1 var(--bn-font-mono); letter-spacing: .15em; color: var(--bn-text-3); }   /* P:370, 406, 419 */
.mine-clear { border: 0; background: transparent; font: 500 11px/1 var(--bn-font-mono); color: var(--bn-link); cursor: pointer; padding: 0; }   /* P:372; shown by the head under .has-saved */
.mine-rows { grid-template-columns: minmax(0, 1fr); }                          /* P:376; display is the head's, under .has-saved */
.mine-row-tpl { display: none; }                                               /* NOT IN THE PROTOTYPE: the row's <template>, which the script clones (P:378-393) and never renders */
.mine-row {                                                                    /* P:378 */
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 16px;
  padding: 15px 0; border-bottom: 1px solid var(--bn-border-subtle);
}
.cat-pill {                                                                    /* P:379; its dot is the head's .cat-dot (P:380) */
  display: inline-flex; align-items: center; gap: 7px; height: 24px; padding: 0 10px; border-radius: 999px;
  border: 1px solid var(--bn-border); font: 600 9.5px/1 var(--bn-font-mono); letter-spacing: .11em;
  text-transform: uppercase; color: var(--bn-text-2);
}
.cat-word { white-space: nowrap; }                                             /* P:381 */
.mine-row-text { display: grid; gap: 5px; min-width: 0; }                      /* P:382 */
.mine-row-title { font: 700 17px/1.26 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.012em; text-wrap: pretty; }   /* P:383 */
.mine-row-meta { font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:384 */
.mine-follow {                                                                 /* P:386, states P:1723-1726 */
  display: inline-flex; align-items: center; gap: 7px; height: 30px; padding: 0 12px; border-radius: 999px;
  border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-2);
  font: 500 10.5px/1 var(--bn-font-mono); cursor: pointer; flex: 0 0 auto;
}
.mine-follow.is-on { border-color: var(--bn-accent-green); background: var(--bn-green-100); color: var(--bn-green-800); }
.mine-follow svg { fill: none; }
.mine-follow.is-on svg { fill: currentColor; }
.mine-remove {                                                                 /* P:390 */
  display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 999px;
  border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-3); cursor: pointer; flex: 0 0 auto;
}
.mine-empty { display: grid; gap: 14px; justify-items: start; padding: 34px 26px; border: 1px dashed var(--bn-border-strong); border-radius: 9px; background: var(--bn-surface-2); }   /* P:398 */
.mine-empty-text { font: 400 17px/1.45 var(--bn-font-reading); color: var(--bn-text-2); max-width: 44ch; text-wrap: pretty; }   /* P:399 */
.mine-empty .mine-read {                                                       /* P:400; scoped past `.page a` (P:15), a link here */
  display: inline-flex; align-items: center; height: 36px; padding: 0 17px; border-radius: 999px;
  background: var(--bn-accent-green); border: 0; font: 600 11.5px/1 var(--bn-font-mono);
  color: var(--bn-text-inverse); cursor: pointer;
}
.mine-empty a.mine-read:hover { color: var(--bn-text-inverse); }               /* NOT IN THE PROTOTYPE: holds the ink against `.page a:hover` (P:16) */
.mine-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }   /* P:407 */
.mine-col { display: grid; gap: 10px; padding: 18px 20px; border: 1px solid var(--bn-border); border-radius: 9px; background: var(--bn-surface); }   /* P:409 */
.mine-col-name { font: 700 17px/1.2 var(--bn-font-reading); color: var(--bn-text); }   /* P:410 */
.mine-col-note { font: 400 14px/1.45 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }   /* P:411 */
.mine-col-count { font: 500 10.5px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:412 */
.mine-digest-opts { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }   /* P:420 */
.mine-digest-opt {                                                             /* P:422, states P:1737-1739 */
  display: inline-flex; align-items: center; height: 38px; padding: 0 18px; border-radius: 999px;
  border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-2);
  font: 500 12px/1 var(--bn-font-mono); cursor: pointer;
}
.mine-digest-opt.is-on { border-color: var(--bn-text); background: var(--bn-text); color: var(--bn-bg); }
.mine-digest-note { font: 400 14px/1.5 var(--bn-font-reading); color: var(--bn-text-3); max-width: 52ch; text-wrap: pretty; }   /* P:425; the on one shows, by the head */

/* ========================================================= 10. save popover */

/* Centred on the card, below the bookmark when that fits, above it when not,
   pinned to the card's top as a last resort; the height cap is the room left
   below the chosen top, never the viewport (P:1222-1239). The script sets the
   three properties; 292px is the measured panel height (P:844). Shown by the
   head under .pop.is-open. */
.pop {                                                                         /* P:714, defaults P:1753-1755 */
  --pop-x: 24px;
  --pop-y: 88px;
  --pop-h: 292px;
  position: fixed; left: var(--pop-x); top: var(--pop-y); z-index: 60; width: min(320px, 88vw);
  border-radius: 12px; border: 1px solid var(--bn-border-strong); background: var(--bn-surface);
  box-shadow: var(--bn-shadow-3); overflow: hidden auto; max-height: var(--pop-h);
}
.pop-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 15px 16px 12px; border-bottom: 1px solid var(--bn-border-subtle); }   /* P:715 */
.pop-titles { display: grid; gap: 5px; }                                       /* P:716 */
.pop-label { display: inline-flex; align-items: center; gap: 7px; font: 600 10px/1 var(--bn-font-mono); letter-spacing: .13em; color: var(--bn-accent-green); }   /* P:717 */
.pop-label svg { fill: currentColor; width: 12px; height: 12px; }              /* P:718 */
.pop-title { font: 700 14.5px/1.3 var(--bn-font-reading); color: var(--bn-text); text-wrap: pretty; }   /* P:721 */
.pop-close {                                                                   /* P:723 */
  display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 999px;
  border: 0; background: transparent; color: var(--bn-text-3); cursor: pointer; flex: 0 0 auto;
}
.pop-notify {                                                                  /* P:728 */
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 13px 16px;
  border: 0; border-bottom: 1px solid var(--bn-border-subtle); background: transparent; cursor: pointer; text-align: left;
}
.pop-notify-text { display: grid; gap: 4px; }                                  /* P:729 */
.pop-notify-title { font: 500 13px/1.3 var(--bn-font-ui); color: var(--bn-text); }   /* P:730 */
.pop-notify-note { font: 400 11.5px/1.35 var(--bn-font-reading); color: var(--bn-text-3); }   /* P:731; the on or off one shows, by the head */
.pop-toggle {                                                                  /* P:733, track P:1758 */
  display: inline-flex; align-items: center; width: 38px; height: 22px; padding: 2px; border-radius: 999px;
  background: var(--bn-border-strong); flex: 0 0 auto; transition: background .2s ease;
}
.pop-toggle-knob { width: 18px; height: 18px; border-radius: 999px; background: var(--bn-surface); box-shadow: var(--bn-shadow-1); transform: translateX(0); transition: transform .2s ease; }   /* P:734, knob P:1759 */
.pop-notify.is-on .pop-toggle { background: var(--bn-accent-green); }
.pop-notify.is-on .pop-toggle-knob { transform: translateX(16px); }
.pop-cols { display: grid; gap: 9px; padding: 13px 16px; border-bottom: 1px solid var(--bn-border-subtle); }   /* P:738 */
.pop-cols-label { font: 500 10px/1 var(--bn-font-mono); letter-spacing: .13em; color: var(--bn-text-3); }   /* P:739 */
.pop-col {                                                                     /* P:741, states P:1765-1767 */
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px; height: 34px; padding: 0 12px;
  border-radius: 7px; border: 1px solid var(--bn-border); background: transparent; color: var(--bn-text-2);
  font: 500 12px/1 var(--bn-font-ui); cursor: pointer; text-align: left;
}
.pop-col.is-on { border-color: var(--bn-accent-green); background: var(--bn-green-100); color: var(--bn-green-800); }
.pop-col-check { flex: 0 0 auto; }                                             /* P:743-745; shown when on, by the head */
.pop-mine {                                                                    /* P:750 */
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 13px 16px;
  border: 0; background: transparent; color: var(--bn-link); font: 500 12px/1 var(--bn-font-mono); cursor: pointer; text-align: left;
}

/* ============================================================ 11. bottom bar */

.bar {                                                                         /* P:757 */
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 40; display: grid;
  grid-template-columns: 1fr auto 1fr; align-items: end; gap: 16px; padding: 16px 28px 20px; pointer-events: none;
}
.bar-left { display: flex; align-items: center; justify-content: flex-end; pointer-events: auto; }   /* P:758 */
.fan-toggle {                                                                  /* P:760, states P:1698-1699; the deck view's only, by the head (P:759) */
  display: inline-flex; align-items: center; gap: 9px; height: 38px; padding: 0 17px; border-radius: 999px;
  border: 1px solid var(--bn-border-strong); background: transparent; color: var(--bn-text);
  font: 500 12px/1 var(--bn-font-mono); cursor: pointer;
}
.fan-toggle.is-on { background: var(--bn-text); color: var(--bn-bg); }
.bar-center { display: grid; gap: 9px; justify-items: center; pointer-events: auto; }   /* P:767 */
.counter { display: flex; align-items: center; gap: 13px; }                    /* P:768 */
.counter-read, .counter-of { font: 500 11.5px/1 var(--bn-font-mono); color: var(--bn-text-3); }   /* P:769, 771 */
.counter-n { font: 700 26px/1 var(--bn-font-reading); color: var(--bn-text); letter-spacing: -.02em; }   /* P:770 */
.modes { display: inline-flex; align-items: center; gap: 3px; padding: 3px; border-radius: 999px; border: 1px solid var(--bn-border); background: var(--bn-surface); }   /* P:773 */
.mode {                                                                        /* P:775, states P:1779-1780 */
  display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 14px; border-radius: 999px;
  border: 0; background: transparent; color: var(--bn-text-2); font: 500 11.5px/1 var(--bn-font-ui);
  cursor: pointer; transition: background .2s ease;
}
.mode.is-on { background: var(--bn-text); color: var(--bn-bg); }
.bar-right { display: flex; align-items: center; justify-content: flex-start; pointer-events: auto; padding-bottom: 13px; }   /* P:780 */
.hint { font: 500 11px/1 var(--bn-font-mono); letter-spacing: .07em; color: var(--bn-text-3); }   /* P:781; the seven wordings of P:1696, the on one shown by the head */
.hint-item { white-space: nowrap; }

/* ================================================= 12. left out of the port
   Rules the tail carried for markup the templates do not render, or for
   states nothing toggles; their citations kept here so the port stays
   traceable. The play cue and its badges (P:474, P:475, P:476, P:603, P:604,
   P:605, P:630, P:631, P:632, P:685, P:686, P:687) are no longer here: since
   23 September 2026 media.kind can be video, and the badge (.pic-play) and the
   "watch" cue (.dc-cue--watch) are styled in notis.css with the photographic
   frame they sit on. The reflow glide, .is-gliding
   (P:1179, P:1185), the dimmed fan, .is-dimmed
   (P:1415-1420), and the pile's overflow, .is-beyond (P:1436): the script
   writes those inline. The tick heights by hour (P:1564-1565): inline too,
   on .cal-tick. The skip link and the specimen banner are base.html's and
   notis.css already styles them (notis.css:85-86, 250). */

/* ======================================================= glue the macro asked for
 * Four rules the card macro cannot carry because they are colour or display.
 * Each cites the prototype line it stands in for.
 */

/* The kind chip's hue, keyed on data-chip. P:1454-1457: solid fill takes the hue
   with dark ink; outline keeps the surface and the secondary ink; the edge is
   always the hue. Ours are three facts the read model derives. */
.dc-kind, .grid-card-open-kind, .editorial-lead-kind, .editorial-item-kind {
  --kind: var(--bn-border); --kind-bg: transparent; --kind-ink: var(--bn-text-2);
}
[data-chip="corrected"] { --kind: var(--bn-accent-gold); --kind-bg: var(--bn-accent-gold); --kind-ink: var(--bn-night-925); }
[data-chip="narrowed"]  { --kind: var(--bn-chart-8); --kind-bg: transparent; --kind-ink: var(--bn-chart-8); }
[data-chip="secondary"] { --kind: var(--bn-text-3); --kind-bg: transparent; --kind-ink: var(--bn-text-3); }

/* The middle dot between facts. P:587, P:675. */
.grid-card-open-sep, .editorial-lead-sep { color: var(--bn-border-strong); }

/* LINK COPIED and the two share icons. P:448-457: the check while copied, the
   share glyph otherwise, and the label only while copied. */
.dc-copied, .dc-share-on { display: none; }
.dc.is-copied .dc-copied, .dc.is-copied .dc-share-on { display: inline-flex; }
.dc.is-copied .dc-share-off { display: none; }

/* The grid tile's two treatments. P:564-611 open, P:613-649 closed; .is-open
   spans it 2x2 (P:1541-1542) and shows the open face. `display: flex` on the
   open face would beat the hidden attribute, so the rule is explicit. */
.grid-card:not(.is-open) .grid-card-open { display: none; }
.grid-card.is-open > :not(.grid-card-open) { display: none; }


/* NOT IN THE PROTOTYPE (t-64, decision 0013). A lead is told in the same parts everywhere:
   three key points and "What it means for you", marked as analysis, on the back of the
   desktop card, as on the notice page. */
.dc-back-points { margin: 0; padding-left: 18px; display: grid; gap: 5px; }
.dc-back-points li { font: 600 14.5px/1.45 var(--bn-font-reading); color: var(--bn-text); text-wrap: pretty; }
.dc-back-means { padding: 10px 13px 12px; border-left: 3px solid var(--bn-accent-green); background: var(--bn-surface); border-radius: 0 8px 8px 0; display: grid; gap: 6px; }
.dc-back-body p.dc-back-means-h { font: 700 14px/1.2 var(--bn-font-ui); color: var(--bn-text); }
.dc-back-means-h span { margin-left: 6px; font: 500 10px/1 var(--bn-font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--bn-text-3); }
/* NOT IN THE PROTOTYPE (t-69, decision 0014): the three reactions on the back of the card,
   after "What it means for you" and before the tags (notis.css draws the buttons) */
.dc-react { gap: 6px; }
.dc-react .rx-btn { min-height: 32px; padding: 0 11px; font-size: 13.5px; background: var(--bn-surface); }

/* NOT IN THE PROTOTYPE (t-64): the back of a long card ran under the dock. While a card is
   flipped the deck is only as tall as the room between the fixed header and the dock
   (--top-h and --dock-h, which site.js measures; the fallbacks are their heights at
   1366x768), never taller than the card, and the script brings the card into that room
   (the scroll margins). The back's body is the back less its head and foot, never grows
   past it (min-height 0) and scrolls within its own height; a scroll that reaches its end
   stops there instead of moving the page under the dock. */
.deck:has(> .dc.is-flipped) {
  aspect-ratio: auto;
  height: min(calc(min(446px, 86vw) * 13 / 9), max(360px, calc(100dvh - var(--top-h, 137px) - var(--dock-h, 110px) - 24px)));
}
.dc { scroll-margin-top: calc(var(--top-h, 137px) + 12px); scroll-margin-bottom: calc(var(--dock-h, 110px) + 12px); }
.dc-back-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }

/* NOT IN THE PROTOTYPE (t-64, decision 0013): the news page opens with the edition's
   contents, the three leads as links and the read time; the record under it is "Quick
   hits", one line each. */
.ed-today { display: grid; gap: 10px; padding: 16px 20px 18px; border: 1px solid var(--bn-border); border-radius: 12px; background: var(--bn-surface); }
.ed-today-head { margin: 0; display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ed-today-title { font: 700 18px/1.2 var(--bn-font-reading); color: var(--bn-text); }
.ed-today-time { font: 500 10.5px/1.2 var(--bn-font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--bn-text-3); }
.ed-today-list { margin: 0; padding-left: 22px; display: grid; gap: 6px; }
.ed-today-list li { font: 400 16.5px/1.35 var(--bn-font-reading); color: var(--bn-text); }
.ed-today-list a { color: var(--bn-text); }
.ed-today-list a:hover { color: var(--bn-text); text-decoration: underline; text-underline-offset: 3px; }
.ed-quick .ed-record-row { grid-template-columns: minmax(0, 1fr); }


/* ================================================================ 13. phone
   NOT IN THE PROTOTYPE. The prototype is a desktop canvas: its one media query
   is reduced motion, and at 375px its fixed header wraps to 191px with a 487px
   nav under it. Everything below is the same elements re-flowed under one
   breakpoint. No element is new, no colour is set, and nothing here runs
   above 720px, so the desktop stays the prototype byte for byte. */

@media (max-width: 720px) {
  /* The header flows instead of floating. The masthead and the tools share its
     one row; the spine goes (the date control names the week); the links leave
     the header for a tab bar at the foot of the screen, the shape logg uses. */
  .top { position: relative; gap: 10px; padding: 12px 16px 10px; }
  .top-left { flex: 1 1 auto; min-width: 0; gap: 10px; }
  .top .spine { display: none; }
  .masthead-rule { width: 3px; height: 30px; border-radius: 2px; }
  .top .wordmark { font-size: 30px; letter-spacing: -.02em; }
  .top .masthead { grid-template-columns: auto auto auto auto; column-gap: 10px; }   /* one row: the area beside the wordmark, not under it */
  .masthead-ed { font-size: 18px; }
  .masthead-rule { grid-row: 1; }
  .top .masthead .area { grid-column: 4; grid-row: 1; }
  .area-toggle { font-size: 10px; letter-spacing: .2em; }
  .top-right { display: contents; }
  .top-tools { flex: 0 0 auto; gap: 8px; }
  .filter-toggle-label, .mine-pill-label { display: none; }                    /* icon pills */
  .filter-toggle, .mine-pill { width: 40px; padding: 0; justify-content: center; gap: 0; }
  /* t-39: 40px buttons as in Karl's design, each answering a 44px press */
  .filter-toggle, .mine-pill, .search-toggle { height: 40px; position: relative; color: var(--bn-text-2); }
  .search-toggle { width: 40px; }
  .filter-toggle::after, .mine-pill::after, .search-toggle::after { content: ""; position: absolute; inset: -2px; }
  .filter-toggle { position: relative; }
  .filter.is-active .filter-count { position: absolute; top: -5px; right: -5px; }
  .search-input { width: min(180px, 40vw); }

  /* the tab bar: the nav's four links, fixed to the foot, icon over word */
  /* Anchored to the dynamic viewport, not to bottom: 0. On Chrome for Android
     the layout viewport at load reaches under the URL bar, so a bar pinned to
     bottom: 0 sits below the screen until the first scroll collapses the bar;
     100dvh is what the reader can see at every moment. The vh line is the
     fallback for a browser without dvh, where bottom: 0 was never wrong. */
  .top .nav {
    --tabbar-h: calc(53px + env(safe-area-inset-bottom));
    position: fixed; left: 0; right: 0; bottom: auto; z-index: 65; width: auto;
    top: calc(100vh - var(--tabbar-h)); top: calc(100dvh - var(--tabbar-h));
    height: var(--tabbar-h); box-sizing: border-box;
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; max-width: 100%;
    background: var(--bn-surface); border-top: 1px solid var(--bn-border);
    padding: 0 0 env(safe-area-inset-bottom);
  }
  .nav-item { display: block; min-width: 0; }
  .top .nav-link {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    padding: 9px 4px 8px; font: 500 11px/1 var(--bn-font-ui); color: var(--bn-text-3);
  }
  .top .nav-link[aria-current="page"], .nav-item.is-here > .nav-link { color: var(--bn-action); }
  .nav-tab-icon { display: block; }
  .nav-chev, .nav-drop { display: none; }                                      /* the hover panels have no hover here; each tab is its page */

  /* the stage */
  .stage { padding: 4px 16px calc(96px + env(safe-area-inset-bottom)); }   /* room for the tab bar */
  .notice-line .wx-line { display: none; }                                   /* t-39: the weather is in the calendar panel now (site.js moves it); hidden here, never deleted */
  .notice-line .wx-line.is-kept { display: contents; }                        /* no calendar to move it into: it stays a chip on row two (site.js); with no script the noscript sheet shows it */
  .wx-panel .locate { width: 100%; justify-content: center; height: 32px; border-radius: 8px; }
  .wx-pill, .locate { height: 28px; padding: 0 10px; font-size: 10.5px; }
  .locate { white-space: nowrap; }
  /* row two (t-39): the Day|Week chip, the date chip and the view switch, one row */
  .notice-line { display: flex; flex-wrap: wrap; justify-content: flex-start; align-items: center; gap: 6px; align-self: stretch; padding-bottom: 10px; }
  .notice-label { display: none; }
  .span-switch {
    display: inline-flex; align-items: center; gap: 2px; height: 34px; padding: 2px; box-sizing: border-box;
    border-radius: 999px; border: 1px solid var(--bn-border);
  }
  .span-opt {
    position: relative; display: inline-flex; align-items: center; height: 28px; padding: 0 10px; border-radius: 999px;
    font: 500 10.5px/1 var(--bn-font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--bn-text-3);
  }
  .page a.span-opt { color: var(--bn-text-3); text-decoration: none; }
  .page a.span-opt:hover { color: var(--bn-text); }
  .span-opt.is-on { background: var(--bn-action-subtle); color: var(--bn-text); box-shadow: inset 0 0 0 1px var(--bn-accent-green); }
  .date-control { gap: 4px; }
  .date-control .date-prev, .date-control .date-next { width: 28px; height: 28px; }
  .date-toggle { position: relative; height: 34px; padding: 0 11px; gap: 6px; font-size: 11.5px; }
  .date-toggle > svg, .date-long { display: none; }                          /* the chip is the date alone, no year, as in Karl's design; the script writes the same short form */
  .date-short { display: inline; }
  .span-opt::after { content: ""; position: absolute; inset: -8px 0; }        /* a 44px press on a 28px option */
  .date-toggle::after { content: ""; position: absolute; inset: -5px 0; }     /* a 44px press on a 34px chip */
  /* row two: the date, the count and the weather share one row (Karl, 22 Sep). The
     arrows go (the calendar the chip opens has every week); the location button
     moves into the weather panel (site.js, at bind); the script shortens the date. */
  .date-control .date-prev, .date-control .date-next { display: none; }
  .date-sep, .clock { display: none; }                                       /* the time is the phone's own status bar */
  .stage-title { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }   /* the h1 stays for a screen reader */
  .cal-panel { width: min(324px, calc(100vw - 32px)); }
  .wx-panel { width: min(306px, calc(100vw - 32px)); }
  /* On a phone the chips share one centred row, so a panel centred on its own chip runs off
     the screen (Karl, 24 Sep: the calendar hung off the left edge). The row anchors both
     panels instead: centred under the row, which is the screen. */
  .notice-line { position: relative; }
  .notice-line .date-control, .notice-line .wx { position: static; }
  .notice-line .wx-drop { top: calc(100% + 2px); }

  /* the desktop's pile, a size down; hidden on the phone since t-39 (the story deck below) */
  .deck { width: min(446px, calc(100vw - 32px)); }
  .dc-head { padding: 16px 16px 12px; gap: 9px; }
  .dc-title { font-size: 23px; }
  .dc-body { padding: 14px 16px 16px; gap: 10px; }
  .dc-dek { font-size: 15.5px; line-height: 1.45; }
  .dc-row { padding: 5px 0; }
  .dc-val { font-size: 12.5px; }

  /* grid, editorial, my page: one column */
  .grid { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; gap: 14px; padding-top: 20px; }
  .grid-card.is-open, .grid-card[aria-expanded="true"] { grid-column: span 1; grid-row: span 1; }
  .grid-card-open-text { columns: 1; }
  .editorial-lead { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .editorial-lead-title { font-size: 30px; }
  .ed-rest { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .editorial-item { padding: 0; border-left: 0; }
  .ed-record-row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .ed-record-side { text-align: left; white-space: normal; }
  .mine-title { font-size: 30px; }
  .view-mine { padding: 24px 0 120px; }

  /* The bar goes: the view switch lives on row two (t-39), and the fan control and
     the hints assume a pointer. The count chip is hidden; the deck's progress counts. */
  .bar { display: none; }
  .counter--phone { display: none; }
  .stage .view { order: 2; }
  .view-deck { padding: 0; }
  /* ============================================================ t-39: the phone
     Karl's settled phone design (24 Sep, the design canvas, "A" and "Editorial 1").
     Three views in their own markup (index.html, _card.html ph*), shown here in
     place of the desktop's pile, tiles and news page. Colour is the theme's tokens,
     so day and night and the sky keep working; what is printed on a photograph is
     the one exception: light ink on its own dark chip or scrim, the same in both
     themes, from the palette's night, gold and green primitives (the --ph-* set). */
  .ph-deck, .ph-grid, .ph-front, .ph-front-head {
    --ph-chip-bg: color-mix(in srgb, var(--bn-night-950) 72%, transparent);
    --ph-chip-edge: color-mix(in srgb, var(--bn-night-50) 18%, transparent);
    --ph-chip-ink: var(--bn-night-50);
    --ph-chip-ink-2: var(--bn-night-200);
    --ph-badge: var(--bn-gold-300);
    --ph-scrim: var(--bn-night-950);
    --ph-check: var(--bn-green-300);
  }
  .ph-chip {
    display: inline-flex; align-items: center; gap: 7px; height: 26px; padding: 0 10px; box-sizing: border-box;
    border-radius: 999px; background: var(--ph-chip-bg); border: 1px solid var(--ph-chip-edge); color: var(--ph-chip-ink);
    font: 500 10.5px/1 var(--bn-font-mono); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap;
  }
  .ph-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--beat); flex: 0 0 auto; }   /* --beat is the beat's own token, set on the item as the desktop pill sets it (_card.html phbeat) */
  .ph-badge { height: 24px; padding: 0 9px; border-radius: 5px; border-color: var(--ph-badge); color: var(--ph-badge); font-size: 10px; letter-spacing: .12em; }
  /* The three kinds keep the desktop's distinction (the glue at site.css "kind chip's hue"):
     corrected is a solid gold fill with dark ink, narrowed a sand outline, secondary a quiet
     outline. Night palette values, because the chip is dark in both themes. */
  .ph-badge[data-chip="corrected"] { background: var(--ph-badge); color: var(--ph-scrim); }
  .ph-badge[data-chip="narrowed"] { --ph-badge: var(--bn-stone-300); }
  .ph-badge[data-chip="secondary"] { --ph-badge: var(--ph-chip-ink-2); }
  /* The credit is never cut on the phone (Mayor, for Karl): it wraps inside its chip. */
  .ph-credit {
    display: block; height: auto; min-width: 0; max-width: 100%; padding: 3px 7px; border: 0; border-radius: 4px;
    font-size: 10px; line-height: 1.3; letter-spacing: 0; text-transform: none; text-align: right;
    white-space: normal; overflow-wrap: anywhere; pointer-events: none;
  }
  /* The top of a picture: the video's link or the badge at the left, the credit at the
     right; a credit that does not fit beside them takes the row under. One flow, so
     nothing printed on a picture can be drawn over anything else. */
  .ph-top {
    position: absolute; top: 10px; left: 12px; right: 12px; z-index: 3;
    display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px 8px; pointer-events: none;
  }
  .ph-top > .ph-credit { flex: 0 1 auto; margin-left: auto; }
  .ph-top > .ph-watch, .ph-top > .ph-badge { flex: 0 0 auto; }
  .ph-img, .ph-art > .ev-frame, .ph-tile > .ev-frame, .ph-fp-art > .ev-frame {
    position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; display: block;
  }
  .ph-img.pic-whole { object-fit: contain; }                                   /* a vendor's image whole, never cropped */
  .ph-art .ev-surface, .ph-fp-art .ev-surface { fill: color-mix(in srgb, var(--beat, var(--bn-border-strong)) 22%, var(--bn-surface-2)); }

  /* ---- the deck: one story at a time, between the header and the tab bar */
  /* The deck page grows with its story, so the buttons always end above the tab bar
     and the page scrolls to them (Gatekeeper, run 83). Where the story can be made to
     fit by letting the picture give way, site.js adds is-fitted after measuring it
     (N.fitDeck), and only keeps it if the buttons then clear the tab bar. */
  .page[data-view="deck"] { min-height: 100vh; min-height: 100dvh; }
  .page[data-view="deck"].is-fitted { height: 100vh; height: 100dvh; min-height: 0; }
  .page[data-view="deck"] .stage { flex: 1 1 auto; min-height: 0; padding-bottom: calc(53px + env(safe-area-inset-bottom)); }
  .page[data-view="deck"] .view-deck { flex-direction: column; align-items: stretch; }
  .view-deck .deck { display: none; }
  .ph-deck { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; margin: 0 -16px; position: relative; }
  .ph-progress { display: flex; align-items: center; gap: 10px; padding: 0 16px 10px; flex: 0 0 auto; }
  .ph-segs { flex: 1 1 auto; display: flex; gap: 4px; }
  .ph-seg { flex: 1 1 0; height: 3px; border-radius: 2px; background: color-mix(in srgb, var(--bn-text) 20%, transparent); }
  .ph-seg.is-on { background: var(--bn-text); }
  .ph-count { font: 500 11px/1 var(--bn-font-mono); color: var(--bn-text-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
  .ph-story { display: none; flex-direction: column; flex: 1 1 auto; min-height: 0; }
  .ph-story.is-current { display: flex; }
  /* The picture takes what the text leaves, from about 292px at 390px wide down to 150px;
     the text never shrinks, so nothing can print over anything (the t-37 lesson). */
  .ph-art { position: relative; flex: 0 1 min(75vw, 320px); min-height: 150px; overflow: hidden; background: var(--bn-surface-2); }
  .ph-art--wash { background: linear-gradient(140deg, color-mix(in srgb, var(--beat) 34%, var(--bn-surface-2)), color-mix(in srgb, var(--beat) 12%, var(--bn-bg)) 72%); }
  .ph-facts { position: absolute; left: 16px; right: 16px; bottom: 14px; z-index: 2; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; pointer-events: none; }
  .ph-tap {
    position: absolute; top: 0; bottom: 0; z-index: 1; padding: 0; border: 0; background: transparent;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
  }
  .ph-tap--prev { left: 0; width: 38%; cursor: w-resize; }
  .ph-tap--next { right: 0; width: 62%; cursor: e-resize; }
  .ph-tap--zoom { left: 0; right: 0; cursor: zoom-in; }                   /* t-66: the picture opens large */
  .ph-tap:focus-visible { outline: 2px solid var(--bn-focus-ring); outline-offset: -4px; }
  .page a.ph-watch, .page a.ph-watch:hover { position: relative; height: 30px; color: var(--ph-chip-ink); text-transform: none; letter-spacing: .02em; pointer-events: auto; }
  .ph-watch::after { content: ""; position: absolute; inset: -7px 0; }          /* a 44px press on a 30px chip */
  .ph-body { flex: 1 0 auto; display: flex; flex-direction: column; gap: 12px; padding: 16px 20px 12px; }
  .ph-title { margin: 0; font: 700 27px/1.12 var(--bn-font-reading); letter-spacing: -.01em; color: var(--bn-text); text-wrap: pretty; }
  .ph-dek {
    margin: 0; max-width: none; font: 400 17px/1.45 var(--bn-font-reading); color: var(--bn-text-2);
    display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
  }
  .ph-fill { flex: 1 1 auto; }
  .ph-checked { margin: 0; max-width: none; display: flex; align-items: center; gap: 8px; font: 500 11px/1.3 var(--bn-font-mono); letter-spacing: .04em; color: var(--bn-text-3); }
  .ph-checked > span { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .ph-check { flex: 0 0 auto; color: var(--bn-accent-green); }
  .ph-actions { display: flex; align-items: center; gap: 8px; }
  .page a.ph-read, .page a.ph-read:hover {
    flex: 1 1 auto; display: flex; align-items: center; justify-content: center; gap: 8px; height: 46px; border-radius: 12px;
    background: var(--bn-text); color: var(--bn-bg); font: 700 15px/1 var(--bn-font-ui); text-decoration: none;
  }
  .ph-save, .ph-share {
    display: flex; align-items: center; justify-content: center; width: 46px; height: 46px; padding: 0; flex: 0 0 auto;
    border-radius: 12px; border: 1px solid var(--bn-border); color: var(--bn-text-2); cursor: pointer;
    background: color-mix(in srgb, var(--bn-surface) 70%, transparent);       /* reads as a button over the sky's ridge */
  }
  .ph-save svg { fill: none; }
  .ph-save.is-saved, .ph-share.is-copied { color: var(--bn-accent-green); }
  .ph-save.is-saved svg { fill: currentColor; }
  .ph-share-on, .ph-share.is-copied .ph-share-off { display: none; }
  .ph-share.is-copied .ph-share-on { display: block; }
  .ph-empty {
    display: none; flex-direction: column; align-items: center; justify-content: center; gap: 16px; margin: 16px; padding: 28px 20px;
    border: 1px dashed var(--bn-border-strong); border-radius: 12px; background: var(--bn-surface-2); text-align: center;
  }
  .ph-deck.is-empty .ph-empty { display: flex; }
  .ph-deck.is-empty .ph-progress { visibility: hidden; }
  .ph-empty-text { font: 400 17px/1.4 var(--bn-font-reading); color: var(--bn-text-2); max-width: 26ch; text-wrap: pretty; }
  .ph-empty-actions { display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; }
  .ph-clear { height: 44px; padding: 0 20px; border-radius: 999px; border: 0; background: var(--bn-accent-green); color: var(--bn-text-inverse); font: 600 12.5px/1 var(--bn-font-mono); cursor: pointer; }
  .page a.ph-archive { display: inline-flex; align-items: center; min-height: 44px; font: 500 12px/1 var(--bn-font-mono); }
  .ph-status { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  /* t-53: the next card arrives from the side the last one did not leave by, far enough to
     read as a card sliding in (a third of its width), not a nudge */
  @keyframes ph-in-next { from { opacity: .2; transform: translateX(34%) scale(.97); } }
  @keyframes ph-in-prev { from { opacity: .2; transform: translateX(-34%) scale(.97); } }
  .ph-story.is-in-next { animation: ph-in-next .32s cubic-bezier(.2,.8,.2,1); }
  .ph-story.is-in-prev { animation: ph-in-prev .32s cubic-bezier(.2,.8,.2,1); }
  .ph-story { touch-action: pan-y; will-change: transform; }                 /* sideways is ours, up and down is the page's */
  .ph-deck { overflow-x: clip; }                                             /* a card on its way out never widens the page */
  /* t-61 (Karl, 27 Sep): the card a swipe leads to waits under the current one, cut to its size,
     so dragging the top card away shows what comes next rather than the sky */
  .ph-story.is-under { display: flex; position: absolute; left: 0; right: 0; z-index: 0; pointer-events: none; transform-origin: 50% 30%; }
  @media (max-height: 700px) { .ph-dek { -webkit-line-clamp: 3; } .ph-title { font-size: 24px; } }

  /* ---- the grid: picture tiles edge to edge, 3px apart, the first across the width */
  .view-grid .grid { display: none; }
  .ph-grid { display: block; align-self: stretch; margin: 0 -16px; }
  .ph-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3px; }
  .ph-tile { position: relative; display: block; height: 236px; overflow: hidden; background: var(--bn-surface-2); text-decoration: none; }
  .ph-tile.is-lead { grid-column: 1 / -1; height: 300px; }
  .ph-tile--wash { background: linear-gradient(140deg, color-mix(in srgb, var(--beat) 42%, var(--bn-night-900)), var(--bn-night-950) 78%); }
  .page a.ph-tile, .page a.ph-tile:hover { color: var(--ph-chip-ink); }
  .ph-tile:focus-visible { outline: 2px solid var(--bn-focus-ring); outline-offset: -3px; }
  .ph-scrim { position: absolute; left: 0; right: 0; bottom: 0; height: 170px; pointer-events: none; background: linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--ph-scrim) 95%, transparent) 70%); }
  .ph-tile.is-lead .ph-scrim { height: 190px; background: linear-gradient(180deg, transparent 0%, color-mix(in srgb, var(--ph-scrim) 94%, transparent) 78%); }
  .ph-tile .ph-top { top: 8px; left: 8px; right: 8px; }
  .ph-tile .ph-credit { font-size: 9px; }
  .ph-tile-badge { height: 22px; padding: 0 8px; font-size: 9.5px; }
  .ph-tile-text { position: absolute; left: 12px; right: 12px; bottom: 12px; display: flex; flex-direction: column; gap: 6px; }
  .ph-tile.is-lead .ph-tile-text { left: 16px; right: 16px; bottom: 16px; gap: 8px; }
  .ph-tile-kicker { display: flex; align-items: center; gap: 6px; font: 500 9.5px/1.2 var(--bn-font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ph-chip-ink-2); }
  .ph-tile.is-lead .ph-tile-kicker { gap: 8px; font-size: 10.5px; color: var(--ph-chip-ink); }
  .ph-tile-title {
    font: 700 17px/1.15 var(--bn-font-reading); text-wrap: pretty;
    display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
  }
  .ph-tile.is-lead .ph-tile-title { font-size: 24px; line-height: 1.12; }
  .ph-tile-date, .ph-tile-checked { display: none; }
  .ph-tile.is-lead .ph-tile-date { display: inline; }
  .ph-tile.is-lead .ph-tile-checked { display: flex; align-items: center; gap: 6px; font: 500 10.5px/1.2 var(--bn-font-mono); color: var(--ph-chip-ink-2); }
  .ph-tile .ph-check { color: var(--ph-check); }
  .ph-grid-end {
    display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0; max-width: none;
    padding: 4px 16px; font: 500 11px/1.3 var(--bn-font-mono); color: var(--bn-text-3);
  }
  .ph-grid-end a { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; }

  /* ---- the editorial: the front page, in the desktop's order */
  .ed { padding: 4px 0 14px; gap: 0; }
  .ed > .ed-head:not(.ed-head--record), .ed > .editorial-lead, .ed > .ed-rest { display: none; }
  .ph-front-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 4px 0 12px; border-bottom: 2px solid var(--bn-text); }
  .ph-front-title { margin: 0; font: 700 24px/1 var(--bn-font-reading); letter-spacing: -.015em; color: var(--bn-text); }
  .ph-front-meta { font: 500 10.5px/1.2 var(--bn-font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--bn-text-3); white-space: nowrap; }
  .ph-front { display: block; list-style: none; margin: 0; padding: 0; }
  .ph-fp { display: flex; gap: 14px; padding: 18px 0; border-bottom: 1px solid var(--bn-border-subtle); }
  .ph-fp.is-lead { display: block; padding: 16px 0 18px; border-bottom-color: var(--bn-border); }
  .ph-fp-num { flex: 0 0 34px; font: 700 30px/.9 var(--bn-font-reading); color: var(--bn-accent-green); }
  .ph-fp.is-lead .ph-fp-num { display: none; }
  .ph-fp-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
  .ph-fp.is-lead .ph-fp-text { gap: 12px; }
  .ph-fp-kicker { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; font: 500 10px/1.2 var(--bn-font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--bn-text-2); }
  .ph-fp-badge { color: var(--kind); }
  .ph-fp-title { margin: 0; font: 700 21px/1.14 var(--bn-font-reading); letter-spacing: -.01em; color: var(--bn-text); text-wrap: pretty; }
  .ph-fp.is-lead .ph-fp-title { font-size: 31px; line-height: 1.08; letter-spacing: -.015em; }
  .page .ph-fp-title a { color: inherit; }
  .page .ph-fp-title a:hover { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
  .ph-fp-art { display: none; position: relative; height: 200px; margin: 2px -16px 0; overflow: hidden; background: var(--bn-surface-2); }
  .ph-fp.is-lead .ph-fp-art { display: block; }
  .ph-fp-art .ph-credit { position: absolute; bottom: 8px; right: 10px; z-index: 1; max-width: calc(100% - 20px); font-size: 9.5px; }
  .ph-fp-dek { margin: 0; max-width: none; font: 400 16px/1.45 var(--bn-font-reading); color: var(--bn-text-2); text-wrap: pretty; }
  .ph-fp.is-lead .ph-fp-dek { font-size: 18px; line-height: 1.5; color: color-mix(in srgb, var(--bn-text) 55%, var(--bn-text-2)); }
  .ph-fp-checked { margin: 0; max-width: none; display: flex; align-items: center; gap: 7px; font: 500 10.5px/1.3 var(--bn-font-mono); color: var(--bn-text-3); }
  .ph-fp-prov { flex: 1 1 auto; min-width: 0; }
  .page a.ph-fp-read { display: none; flex: 0 0 auto; align-items: center; gap: 6px; margin: -16px 0 -16px auto; padding: 16px 0 16px 12px; min-height: 44px; box-sizing: border-box; font: 500 11.5px/1 var(--bn-font-mono); white-space: nowrap; }   /* a 44px press, the row's look unchanged */
  .page .ph-fp.is-lead a.ph-fp-read { display: inline-flex; }
  .ed-head--record { margin-top: 26px; }
  .ed-record { margin-top: 4px; }
  .ed-last { margin: 20px 0 0; font-style: italic; font-size: 15.5px; line-height: 1.45; color: var(--bn-text-3); }

  /* ---- the view switch: cards, grid, front page (row two, at the right) */
  .viewswitch {
    display: inline-flex; align-items: center; gap: 2px; height: 34px; padding: 2px; margin-left: auto; box-sizing: border-box;
    border-radius: 999px; border: 1px solid var(--bn-border);
  }
  .page a.viewswitch-opt {
    position: relative; display: flex; align-items: center; justify-content: center; width: 38px; height: 28px;
    border-radius: 999px; color: var(--bn-text-3); text-decoration: none;
  }
  .page a.viewswitch-opt:hover { color: var(--bn-text); }
  .page a.viewswitch-opt[aria-current="page"] { background: var(--bn-action-subtle); box-shadow: inset 0 0 0 1px var(--bn-accent-green); color: var(--bn-text); }
  .viewswitch-opt::after { content: ""; position: absolute; inset: -8px -1px; } /* 40 x 44 each: three at 44 wide do not fit row two at 360px */

  /* ---- the weather, in the calendar panel (site.js moves it there on the phone) */
  .cal-panel { max-height: calc(100vh - 200px); max-height: calc(100dvh - 200px - env(safe-area-inset-bottom)); overflow: auto; }   /* above the tab bar */
  .cal-panel .wx { position: static; display: grid; gap: 10px; justify-items: start; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--bn-border-subtle); }
  .cal-panel .wx .wx-pill { height: 32px; }
  .cal-panel .wx .wx-drop { position: static; transform: none; padding-top: 0; width: 100%; }
  .cal-panel .wx .wx-panel { width: auto; padding: 0; border: 0; background: transparent; box-shadow: none; }
  /* ============================================================ t-50: the quiet deck
     Karl's design A (26 Sep, the design canvas "notis mobile layout"). One header row:
     the name, the date chip and a menu holding the day or week switch, the view switch
     and the tools (site.js moves them in, and back above 720px). The story is a solid
     card in the theme's colours: the sky, its hours and its weather, frames the card
     and never sits behind a word. The facts left the picture for a line over the
     headline, the check is a row that opens the sources, and a strip under the card
     names the next notice. Everything here is under .has-menu or inside the deck, so
     with no script the phone keeps its two rows. */
  .page.has-menu .top { flex-wrap: nowrap; align-items: center; gap: 8px; padding: 8px 12px 8px 16px; min-height: 60px; box-sizing: border-box; z-index: 70; }
  .page.has-menu .top-left { gap: 8px; }
  .page.has-menu .area { display: none; }                                    /* one area today: the switcher waits for a second */
  .page.has-menu .masthead-rule { height: 24px; }
  .page.has-menu .top .wordmark { font-size: 27px; }
  .page.has-menu .masthead-ed { font-size: 16px; }
  .page.has-menu .top .masthead { column-gap: 8px; }
  .page.has-menu .notice-line { padding-bottom: 0; }
  .page.has-menu .menu-date, .page.has-menu .menu { display: flex; align-items: center; flex: 0 0 auto; }
  .menu-date .date-control { position: static; }                             /* the calendar hangs from the header, centred under it */
  .menu-date .cal-panel { top: calc(100% + 4px); }
  .menu-date .date-toggle {
    height: 44px; padding: 0 14px; gap: 6px; border-radius: 22px; box-sizing: border-box;
    background: var(--bn-surface); border: 1px solid var(--bn-border); color: var(--bn-text);
    font: 500 15px/1 var(--bn-font-ui); letter-spacing: 0;
  }
  .menu-date .date-toggle::after { display: none; }
  /* t-51: Menu takes About's place on the tab bar and opens the menu above the bar */
  .page.has-menu .nav-link--about { display: none; }
  .page.has-menu .top .menu-tab { display: flex; width: 100%; height: 100%; border: 0; background: transparent; cursor: pointer; }
  .page.has-menu .top .menu-tab[aria-expanded="true"] { color: var(--bn-action); }
  .page.has-menu .menu { width: 0; }                                        /* the panel's holder takes no room in the header row */
  .menu-panel {
    display: none; position: fixed; left: 12px; right: 12px; z-index: 90;
    top: calc(100vh - 53px - env(safe-area-inset-bottom) - 8px); top: calc(100dvh - 53px - env(safe-area-inset-bottom) - 8px);
    transform: translateY(-100%);                                           /* its foot 8px above the tab bar, read off the visible screen as the bar is */
    flex-direction: column; gap: 16px; padding: 16px; border-radius: 16px; box-sizing: border-box;
    background: var(--bn-surface); border: 1px solid var(--bn-border); box-shadow: var(--bn-shadow-3);
  }
  .menu.is-open .menu-panel { display: flex; }
  .menu-group { display: flex; flex-direction: column; gap: 8px; }
  .menu-label { font: 700 12px/1 var(--bn-font-ui); letter-spacing: .08em; text-transform: uppercase; color: var(--bn-text-3); }
  .menu-slot { display: flex; }
  .menu-slot .viewswitch { margin-left: 0; }
  .menu-slot .top-tools { display: flex; flex-wrap: wrap; gap: 8px; }
  .menu-slot .filter-toggle-label, .menu-slot .mine-pill-label { display: inline; }   /* room for the words in the menu */
  .menu-slot .filter-toggle, .menu-slot .mine-pill { width: auto; height: 44px; padding: 0 14px; gap: 8px; }
  .menu-slot .search-toggle { width: 44px; height: 44px; }
  .menu-slot .filter-drop { left: 0; right: auto; top: auto; bottom: 100%; padding-top: 0; padding-bottom: 8px; }   /* opens upward, away from the tab bar */
  .menu-links { display: flex; flex-wrap: wrap; gap: 4px 18px; }
  .page .menu-links a { display: inline-flex; align-items: center; min-height: 44px; font: 500 15px/1 var(--bn-font-ui); color: var(--bn-text); text-decoration: none; }
  .page .menu-links a:hover { color: var(--bn-action); }

  /* the card */
  .ph-story { position: relative; z-index: 1; margin: 0 12px; border-radius: 20px; overflow: hidden; background: var(--bn-surface); border: 1px solid var(--bn-border-subtle); box-shadow: var(--bn-shadow-3); }
  .ph-art { flex: 0 1 auto; aspect-ratio: 16 / 9; min-height: 150px; }
  .ph-story.is-current { flex: 0 1 auto; }                                    /* the card ends with its words; the sky shows under it */
  .ph-story .ph-fill { display: none; }
  .ph-story .ph-top { top: auto; bottom: 8px; }                              /* the credit on the picture's corner */
  .ph-body { gap: 10px; padding: 16px 20px 20px; }
  .ph-kicker { margin: 0; max-width: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font: 700 12.5px/1.2 var(--bn-font-ui); letter-spacing: .08em; text-transform: uppercase; color: var(--bn-text-3); }
  .ph-kicker-date { font-weight: 500; letter-spacing: .02em; text-transform: none; margin-left: -4px; }
  .ph-kicker .ph-badge { height: 22px; background: transparent; border: 1px solid var(--bn-border-strong); color: var(--bn-text-2); font: 600 10.5px/1 var(--bn-font-ui); }
  .ph-kicker .ph-badge[data-chip="corrected"] { border-color: var(--bn-warning-border); color: var(--bn-warning-text); background: transparent; }
  .page a.ph-checked, .page a.ph-checked:hover {
    margin: 4px 0 0; min-height: 44px; padding: 0 12px; box-sizing: border-box; border-radius: 12px;
    display: flex; align-items: center; gap: 10px; background: var(--bn-inset); border: 1px solid var(--bn-border-subtle);
    font: 500 14.5px/1.3 var(--bn-font-ui); letter-spacing: 0; color: var(--bn-text-2); text-decoration: none;
  }
  .page a.ph-checked:hover { border-color: var(--bn-border); }
  .ph-actions { margin-top: 6px; }
  .page a.ph-read, .page a.ph-read:hover { height: 50px; border-radius: 14px; font-size: 16px; }
  .ph-save, .ph-share { width: 50px; height: 50px; border-radius: 14px; background: var(--bn-surface-2); color: var(--bn-text); }

  /* the next notice, tucked under the card */
  .ph-nextline {
    display: none; align-items: center; gap: 10px; margin: -14px 24px 0; padding: 24px 16px 12px; min-height: 56px; box-sizing: border-box;
    border-radius: 0 0 16px 16px; background: var(--bn-surface-2); border: 1px solid var(--bn-border-subtle); border-top: 0;
    font: 500 14px/1.3 var(--bn-font-ui); color: var(--bn-text-3); text-align: left; cursor: pointer; flex: 0 0 auto;
  }
  .ph-nextline.is-on { display: flex; }
  .ph-deck.is-empty .ph-nextline { display: none; }
  .ph-nextline-text { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .ph-nextline:focus-visible { outline: 2px solid var(--bn-focus-ring); outline-offset: 2px; }

  /* ---- t-64 (decision 0013): a lead's key points on the phone's card, under the standfirst,
     and the edition's contents on the front page, closer set */
  .ph-points { margin: 2px 0 0; padding-left: 18px; font: 400 14.5px/1.4 var(--bn-font-ui); color: var(--bn-text-2); }
  .ph-points li { margin: 3px 0; }
  /* ---- t-69 (decision 0014): the three reactions, one compact row under the key points,
     as Karl saw them: "Useful 12  Surprising 5  Doubtful 2". No pill and 28px tall, pulled
     4px into the gap above, so the card gives as little of its picture for it as it can
     (N.fitDeck); one line from 320px with two-digit counts, and past that it wraps, never
     overlaps. Each press is 44px tall through its ::after, which reaches into the gaps
     around the row and over nothing else. */
  .ph-react { justify-content: space-between; gap: 2px 4px; margin: -4px -2px 0; }
  .ph-react .rx-btn { position: relative; min-height: 28px; padding: 0 2px; gap: 4px; border: 0; border-radius: 8px; background: transparent; font-size: 13px; }
  .ph-react .rx-btn::after { content: ""; position: absolute; left: 0; right: 0; top: -8px; bottom: -8px; }
  .ph-react .rx-btn[aria-pressed="true"] { background: color-mix(in srgb, var(--bn-accent-green) 14%, transparent); }
  .ph-react .rx-icon { width: 14px; height: 14px; }
  .ed-today { margin: 0 0 14px; padding: 12px 14px; }
  .ed-today-list li { font-size: 16px; }
}

/* t-66: the desktop card's enlarge button, in the picture's top corner (NOT IN THE PROTOTYPE) */
.dc-art { position: relative; }
.dc-zoom { position: absolute; top: 10px; right: 10px; z-index: 2; width: 32px; height: 32px; display: inline-flex;
           align-items: center; justify-content: center; border-radius: 999px; border: 1px solid var(--bn-border);
           background: color-mix(in srgb, var(--bn-surface) 86%, transparent); color: var(--bn-text); cursor: zoom-in; }
.dc-zoom:focus-visible { outline: 2px solid var(--bn-focus-ring); outline-offset: 2px; }

