/* =========================================================================
   Wyre News homepage
   Palette: red / black / white. Modern newspaper.
   ========================================================================= */

:root {
  /* This design is light-only. Saying so stops Chrome and Android auto-dark
     from inverting it, which they do unevenly: explicitly-set backgrounds
     survive while inherited text colours flip, and headlines end up white on
     a white card. A real dark mode would be a deliberate second palette, not
     an automatic inversion of this one. */
  color-scheme: only light;

  /* ink & paper */
  --paper:       #ffffff;
  --paper-warm:  #f7f5f2;
  --paper-deep:  #efece7;
  --ink:         #0c0c0c;
  --ink-soft:    #1c1c1c;
  --ink-muted:   #6a6a6a;
  --rule:        #d9d5cf;
  --rule-strong: #0c0c0c;

  /* brand red, sampled from the mark */
  --red:         #e10600;
  --red-deep:    #a60400;
  --red-bright:  #ff2f26;   /* legible on black */

  /* Type. Newsreader is a variable serif drawn for reading news on screen,
     with real italics and optical sizing, so it carries both the headlines
     and the body copy. Libre Franklin stays for the letterspaced caps only
     (nav, kickers, tags, buttons): that sans-against-serif contrast is what
     makes the labels read as furniture rather than as text.
     Newsreader tops out at 800, so nothing here asks for 900. */
  --display: "Newsreader", "Times New Roman", Times, serif;
  --serif:   "Newsreader", "Times New Roman", Times, serif;
  --sans:    "Libre Franklin", "Helvetica Neue", Arial, sans-serif;
  --mono:    ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* metrics */
  --wrap:    1240px;
  --gutter:  clamp(18px, 4vw, 40px);
}

/* ------------------------------------------------------------------ base */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }

a { color: inherit; }

h1, h2, h3 { margin: 0; font-weight: 800; line-height: 1.06; letter-spacing: -0.015em; }

p { margin: 0; }

ul { margin: 0; padding: 0; list-style: none; }

code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: var(--paper-deep);
  padding: 0.1em 0.4em;
  border-radius: 2px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--red);
  color: #fff;
  padding: 12px 20px;
  font-weight: 700;
  text-decoration: none;
}
.skip:focus { left: 0; }

:where(a, button):focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 3px;
}

/* shared: small caps label */
.kicker {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin: 0 0 18px;
  color: var(--ink-muted);
}
.kicker--red { color: var(--red); }

/* --------------------------------------------------------- paywall stamp */

/* Marks a link that dead-ends at a subscription wall. Wyre sends readers to
   publishers, so that is worth saying BEFORE the click. Drawn as a rubber
   stamp - double rule, letterspaced caps, a few degrees off square - so it
   reads as something pressed onto the page rather than as part of the
   headline beside it.

   The second rule is an OUTLINE, not an inset shadow, so the gap between the
   rules shows whatever is actually behind the stamp. That is what lets one
   rule serve white cards, the black wire and both of their hover states
   without a background colour per context. */
.stamp {
  display: inline-block;
  vertical-align: middle;
  padding: 3px 6px 2px;
  border: 1.5px solid var(--red);
  outline: 1px solid var(--red);
  outline-offset: 1.5px;
  font-family: var(--sans);
  font-size: 9px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: 0.18em;
  text-indent: 0.18em;   /* re-centres the word against its own trailing letterspace */
  text-transform: uppercase;
  color: var(--red);
  white-space: nowrap;
  transform: rotate(-4deg);
}

/* On the black wire the deep red goes muddy; --red-bright is the palette's
   answer for exactly this (see :root). */
.wire .stamp {
  border-color: var(--red-bright);
  outline-color: var(--red-bright);
  color: var(--red-bright);
}

/* Inline after the headline text, so it needs its own space; in the flex meta
   rows on a desk page the row gap already provides it. */
.wire__title .stamp { margin-inline-start: 10px; }


/* Furniture stays on the sans. Body copy now defaults to the serif, so every
   letterspaced-caps label, nav item and button has to opt out explicitly
   rather than inherit it from body as it did before. */
.topbar__inner,
.masthead__tagline,
.nav__list a,
.nav__cta,
.btn,
.panel__head,
.stat dt,
.section-head__sub,
.tags li,
.deskpanel__kicker,
.deskpanel__go,
.node__name,
.wire__desk,
.wire__source,
.wire__empty-links a,
.footer__col h2,
.footer__col a,
.footer__base {
  font-family: var(--sans);
}

/* --------------------------------------------------------------- topbar */

.topbar {
  background: var(--ink);
  color: #efefef;
  border-bottom: 3px solid var(--red);
}

.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 38px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.topbar__mid {
  font-family: var(--display);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.3em;
  color: #fff;
}

.topbar__status { display: inline-flex; align-items: center; gap: 9px; color: #bdbdbd; }

.pip {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--red-bright);
  box-shadow: 0 0 0 0 rgba(255, 47, 38, 0.65);
  animation: pip 2.4s ease-out infinite;
}
@keyframes pip {
  0%   { box-shadow: 0 0 0 0 rgba(255, 47, 38, 0.6); }
  70%  { box-shadow: 0 0 0 7px rgba(255, 47, 38, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 47, 38, 0); }
}

@media (max-width: 780px) {
  .topbar__mid { display: none; }
  .topbar__inner { justify-content: space-between; letter-spacing: 0.1em; }
}
@media (max-width: 460px) {
  .topbar__status span { display: none; }
}

/* ------------------------------------------------------------- masthead */

.masthead {
  padding: clamp(26px, 4vw, 46px) 0 clamp(18px, 2.4vw, 26px);
  background: var(--paper);
  text-align: center;
}

.masthead__rule--top {
  height: 0;
  border-top: 1px solid var(--rule);
  margin-bottom: clamp(22px, 3.2vw, 38px);
}

.masthead__logo {
  display: block;
  text-decoration: none;
}
.masthead__logo img {
  width: clamp(230px, 42vw, 430px);
  height: auto;
  margin-inline: auto;
}

.masthead__rule--bottom {
  margin-top: clamp(20px, 3vw, 34px);
  border-top: 4px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  height: 5px;
  position: relative;
}
/* red tick centred on the heavy rule */
.masthead__rule--bottom::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -4px;
  width: 86px;
  height: 4px;
  background: var(--red);
  transform: translateX(-50%);
}

.masthead__tagline {
  margin-top: 14px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* ------------------------------------------------------------------ nav */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--ink);
  color: #fff;
  border-bottom: 1px solid #2a2a2a;
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 56px;
}

.nav__brand {
  display: none;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  font-family: var(--display);
  font-weight: 800;
  font-size: 18px;
  letter-spacing: 0.04em;
}
.nav__brand img { width: 24px; height: 24px; }

.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(14px, 3vw, 40px);
  margin-inline: auto;
  flex-wrap: wrap;
  justify-content: center;
}

.nav__list a {
  position: relative;
  display: inline-block;
  padding: 6px 0;
  text-decoration: none;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #e8e8e8;
  transition: color 0.18s ease;
}
.nav__list a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  height: 2px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.22s ease;
}
.nav__list a:hover { color: #fff; }
.nav__list a:hover::after { transform: scaleX(1); }

.nav__cta {
  flex: none;
  padding: 9px 18px;
  background: var(--red);
  color: #fff;
  text-decoration: none;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  transition: background 0.18s ease;
}
.nav__cta:hover { background: var(--red-deep); }

/* the sticky bar shows a compact brand once the masthead scrolls away */
.nav.is-stuck .nav__brand { display: inline-flex; }
.nav.is-stuck .nav__list { margin-inline: auto; }

@media (max-width: 820px) {
  .nav__inner { min-height: 52px; padding-block: 8px; }
  .nav__cta { display: none; }
  .nav.is-stuck .nav__brand { display: none; }
  .nav__list { gap: 16px; }
  .nav__list a { font-size: 11px; letter-spacing: 0.12em; }
}
/* Six desks on the homepage, seven links on a desk page. The list wraps
   rather than overflowing, but tightening keeps it to one line on most
   handsets. */
@media (max-width: 560px) {
  .nav__inner { padding-inline: 12px; }
  .nav__list { gap: 9px; }
  .nav__list a { font-size: 10px; letter-spacing: 0.04em; }
}
@media (max-width: 430px) {
  .nav__list { gap: 7px; }
  .nav__list a { font-size: 9.5px; letter-spacing: 0.02em; }
}

/* ----------------------------------------------------------------- lede */

.lede {
  padding: clamp(46px, 6vw, 84px) 0 clamp(40px, 5vw, 70px);
  border-bottom: 1px solid var(--rule);
  background:
    linear-gradient(var(--paper), var(--paper));
}

.lede__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: clamp(30px, 5vw, 76px);
  align-items: start;
}

.lede__head {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(46px, 8.2vw, 108px);
  line-height: 0.92;
  letter-spacing: -0.03em;
}
.lede__head em {
  font-style: italic;
  font-weight: 700;
  color: var(--red);
}

.lede__deck {
  margin-top: clamp(22px, 2.6vw, 30px);
  max-width: 60ch;
  font-size: clamp(17px, 1.35vw, 19px);
  line-height: 1.68;
  color: #2e2e2e;
}
.lede__deck::first-letter {
  float: left;
  font-family: var(--display);
  font-weight: 800;
  font-size: 3.4em;
  line-height: 0.78;
  padding: 0.08em 0.1em 0 0;
  color: var(--red);
}

.lede__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 34px;
}

.btn {
  display: inline-block;
  padding: 14px 26px;
  text-decoration: none;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  border: 2px solid var(--ink);
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.btn--solid { background: var(--ink); color: #fff; }
.btn--solid:hover { background: var(--red); border-color: var(--red); }
.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: #fff; }

/* at-a-glance panel */
.lede__aside {
  position: relative;
  overflow: hidden;
  padding: clamp(26px, 3vw, 36px);
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  border-top: 5px solid var(--red);
}

.panel__head {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule);
}

.stats { margin: 0; }
.stat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 15px 0;
  border-bottom: 1px solid var(--rule);
}
.stat dt {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.stat dd {
  margin: 0;
  font-family: var(--display);
  font-weight: 800;
  font-size: 26px;
  letter-spacing: -0.01em;
}

.panel__note {
  position: relative;
  z-index: 1;
  margin-top: 20px;
  font-size: 14.5px;
  line-height: 1.6;
  color: #444;
}

.panel__mark {
  position: absolute;
  right: -58px;
  bottom: -48px;
  width: 240px;
  opacity: 0.055;
  pointer-events: none;
}

@media (max-width: 900px) {
  .lede__grid { grid-template-columns: 1fr; }
  .lede__aside { max-width: 560px; }
}

/* --------------------------------------------------------- section head */

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding-bottom: 16px;
  margin-bottom: clamp(28px, 3.4vw, 44px);
  border-bottom: 3px solid var(--ink);
}

.section-head__title {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(30px, 4.4vw, 52px);
  letter-spacing: -0.022em;
}

.section-head__sub {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.section-head--invert { border-bottom-color: var(--red); }
.section-head--invert .section-head__title { color: #fff; }
.section-head--invert .section-head__sub { color: #9d9d9d; }

/* ---------------------------------------------------------------- desks */

.desks { padding: clamp(50px, 6vw, 88px) 0; }

/* The desk dial: one hub, seven spokes, seven nodes.
 *
 * Seven is prime, so no equal-column grid can ever fill its last row: three
 * across leaves two holes, two across leaves one. A radial escapes the
 * problem instead of patching it, because a ring divides by any number.
 * 360/7 is 51.4286 degrees, and every node and spoke coordinate below is
 * that step measured from the top and rounded to two places.
 *
 * The whole control is seven radio inputs. No JavaScript is involved: the
 * active node, the lit spoke and the visible panel are all sibling selectors
 * hanging off :checked, which is also why the inputs come first in source
 * order. Arrow keys move through the group for free.
 *
 * This block is written mobile-first, unlike the rest of this sheet. The
 * base rules are the stacked list, and the ring only switches on at the
 * width where it has room for its labels. That way the small screen needs no
 * overrides to fight the :checked rules, which carry high specificity and
 * would otherwise need !important to beat.
 */

.dial__radio {
  /* Off-screen but still focusable, so the group keeps its keyboard
     behaviour. display:none would take it out of the tab order. */
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.dial__stage { display: none; }

/* -- the stacked list: small screens, and the no-CSS-grid fallback -------- */

.deskpanel {
  position: relative;
  padding: 30px 0;
  border-top: 1px solid var(--rule);
}
.deskpanel:first-child { border-top: 2px solid var(--rule-strong); }

.deskpanel__ghost {
  position: absolute;
  top: 12px;
  right: 0;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(72px, 16vw, 150px);
  line-height: 0.8;
  letter-spacing: -0.04em;
  color: var(--paper-deep);
  user-select: none;
  pointer-events: none;
}

.deskpanel__kicker,
.deskpanel__name,
.deskpanel__domain,
.deskpanel__desc,
.deskpanel .tags,
.deskpanel__go { position: relative; }

.deskpanel__kicker {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--red);
}

.deskpanel__name {
  margin-top: 10px;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(34px, 5.4vw, 54px);
  line-height: 1.02;
  letter-spacing: -0.03em;
}

.deskpanel__domain {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.02em;
  color: var(--red);
}

.deskpanel__desc {
  margin-top: 16px;
  max-width: 52ch;
  font-size: 16px;
  line-height: 1.62;
  color: #3a3a3a;
}

.deskpanel__go {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 24px;
  padding-bottom: 3px;
  border-bottom: 2px solid var(--ink);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  transition: color 0.24s ease, border-color 0.24s ease;
}
.deskpanel__go i { font-style: normal; transition: transform 0.24s ease; }
.deskpanel__go:hover,
.deskpanel__go:focus-visible { color: var(--red); border-color: var(--red); }
.deskpanel__go:hover i,
.deskpanel__go:focus-visible i { transform: translateX(6px); }

/* -- the ring: only once there is room for it ---------------------------- */

@media (min-width: 760px) {

  .dial {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
    align-items: center;
    gap: clamp(30px, 4.6vw, 76px);
  }

  .dial__stage { display: block; }

  .dial__ring {
    position: relative;
    width: 100%;
    max-width: 540px;
    margin: 0 auto;
    aspect-ratio: 1;
  }

  .dial__wires {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
  }

  .dial__orbit {
    fill: none;
    stroke: var(--rule);
    stroke-width: 0.35;
    stroke-dasharray: 1.4 2.2;
  }

  .spoke {
    stroke: var(--rule);
    stroke-width: 0.55;
    transition: stroke 0.3s ease, stroke-width 0.3s ease;
  }

  .dial__hub  { fill: var(--ink); }
  .dial__hubring {
    fill: none;
    stroke: var(--ink);
    stroke-width: 0.4;
    stroke-dasharray: 0.9 1.9;
  }
  .dial__hubtext {
    fill: #fff;
    font-family: var(--sans);
    font-size: 5.2px;
    font-weight: 800;
    letter-spacing: 0.22em;
    text-anchor: middle;
    dominant-baseline: central;
    /* letter-spacing pushes the last letter past centre; pull it back */
    transform: translateX(0.55px);
  }

  /* the signal leaving the hub, once every four seconds */
  .dial__pulse {
    fill: none;
    stroke: var(--red);
    stroke-width: 0.5;
    transform-origin: 50% 50%;
    animation: dial-pulse 4s ease-out infinite;
  }
  @keyframes dial-pulse {
    0%   { transform: scale(1);    opacity: 0.55; }
    70%  { transform: scale(2.32); opacity: 0;    }
    100% { transform: scale(2.32); opacity: 0;    }
  }

  /* Nodes. Positions are 36% of the box from centre, stepped by 360/7.  */
  .node {
    position: absolute;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    width: 124px;
    cursor: pointer;
    text-align: center;
  }
  .node--1 { left: 50.00%; top: 14.00%; }
  .node--2 { left: 78.15%; top: 27.55%; }
  .node--3 { left: 85.10%; top: 58.01%; }
  .node--4 { left: 65.62%; top: 82.44%; }
  .node--5 { left: 34.38%; top: 82.44%; }
  .node--6 { left: 14.90%; top: 58.01%; }
  .node--7 { left: 21.85%; top: 27.55%; }

  .node__dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    border: 1.5px solid var(--ink);
    border-radius: 50%;
    background: var(--paper);
    color: var(--ink);
    transition: background 0.28s ease, color 0.28s ease,
                border-color 0.28s ease, transform 0.28s ease;
  }
  .node__dot svg { width: 26px; height: 26px; }

  .node__name {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.17em;
    text-transform: uppercase;
    color: var(--ink-muted);
    transition: color 0.28s ease;
  }

  .node:hover .node__dot { transform: scale(1.07); border-color: var(--red); }
  .node:hover .node__name { color: var(--ink); }

  /* -- active states ----------------------------------------------------
     One selector per desk, because :checked has to reach across to a
     specific node, spoke and panel. Grouped so the declarations stay in
     one place. */

  .dial__radio:nth-of-type(1):checked ~ .dial__stage .node--1 .node__dot,
  .dial__radio:nth-of-type(2):checked ~ .dial__stage .node--2 .node__dot,
  .dial__radio:nth-of-type(3):checked ~ .dial__stage .node--3 .node__dot,
  .dial__radio:nth-of-type(4):checked ~ .dial__stage .node--4 .node__dot,
  .dial__radio:nth-of-type(5):checked ~ .dial__stage .node--5 .node__dot,
  .dial__radio:nth-of-type(6):checked ~ .dial__stage .node--6 .node__dot,
  .dial__radio:nth-of-type(7):checked ~ .dial__stage .node--7 .node__dot {
    background: var(--ink);
    border-color: var(--ink);
    color: #fff;
    transform: scale(1.16);
  }

  .dial__radio:nth-of-type(1):checked ~ .dial__stage .node--1 .node__name,
  .dial__radio:nth-of-type(2):checked ~ .dial__stage .node--2 .node__name,
  .dial__radio:nth-of-type(3):checked ~ .dial__stage .node--3 .node__name,
  .dial__radio:nth-of-type(4):checked ~ .dial__stage .node--4 .node__name,
  .dial__radio:nth-of-type(5):checked ~ .dial__stage .node--5 .node__name,
  .dial__radio:nth-of-type(6):checked ~ .dial__stage .node--6 .node__name,
  .dial__radio:nth-of-type(7):checked ~ .dial__stage .node--7 .node__name {
    color: var(--red);
  }

  .dial__radio:nth-of-type(1):checked ~ .dial__stage .spoke--1,
  .dial__radio:nth-of-type(2):checked ~ .dial__stage .spoke--2,
  .dial__radio:nth-of-type(3):checked ~ .dial__stage .spoke--3,
  .dial__radio:nth-of-type(4):checked ~ .dial__stage .spoke--4,
  .dial__radio:nth-of-type(5):checked ~ .dial__stage .spoke--5,
  .dial__radio:nth-of-type(6):checked ~ .dial__stage .spoke--6,
  .dial__radio:nth-of-type(7):checked ~ .dial__stage .spoke--7 {
    stroke: var(--red);
    stroke-width: 1.05;
  }

  /* Keyboard focus has to be drawn on the label, since the real input is
     off-screen. */
  .dial__radio:nth-of-type(1):focus-visible ~ .dial__stage .node--1 .node__dot,
  .dial__radio:nth-of-type(2):focus-visible ~ .dial__stage .node--2 .node__dot,
  .dial__radio:nth-of-type(3):focus-visible ~ .dial__stage .node--3 .node__dot,
  .dial__radio:nth-of-type(4):focus-visible ~ .dial__stage .node--4 .node__dot,
  .dial__radio:nth-of-type(5):focus-visible ~ .dial__stage .node--5 .node__dot,
  .dial__radio:nth-of-type(6):focus-visible ~ .dial__stage .node--6 .node__dot,
  .dial__radio:nth-of-type(7):focus-visible ~ .dial__stage .node--7 .node__dot {
    outline: 2px solid var(--red);
    outline-offset: 4px;
  }

  /* -- panels ------------------------------------------------------------
     All seven stack in the same grid cell, so the column is as tall as the
     longest one and nothing jumps as you move around the ring. */

  .dial__panels { display: grid; }

  .deskpanel {
    grid-area: 1 / 1;
    padding: 0;
    border: 0;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(12px);
    transition: opacity 0.34s ease, transform 0.34s ease, visibility 0.34s;
  }
  .deskpanel:first-child { border: 0; }

  .dial__radio:nth-of-type(1):checked ~ .dial__panels .deskpanel--1,
  .dial__radio:nth-of-type(2):checked ~ .dial__panels .deskpanel--2,
  .dial__radio:nth-of-type(3):checked ~ .dial__panels .deskpanel--3,
  .dial__radio:nth-of-type(4):checked ~ .dial__panels .deskpanel--4,
  .dial__radio:nth-of-type(5):checked ~ .dial__panels .deskpanel--5,
  .dial__radio:nth-of-type(6):checked ~ .dial__panels .deskpanel--6,
  .dial__radio:nth-of-type(7):checked ~ .dial__panels .deskpanel--7 {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: none;
  }

  .deskpanel__ghost {
    top: -26px;
    right: 4px;
    font-size: clamp(120px, 13vw, 190px);
  }
}

/* The ring wants more room than the copy does, so it gets the wider half
   back once there is room to spare. */
@media (min-width: 1080px) {
  .dial { grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr); }
}

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 20px;
}
.tags li {
  padding: 4px 10px;
  border: 1px solid var(--rule);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* ----------------------------------------------------------------- wire */

.wire {
  padding: clamp(50px, 6vw, 88px) 0;
  background: var(--ink);
  color: #fff;
}

.wire__list { border-top: 1px solid #2b2b2b; }

.wire__item {
  display: grid;
  grid-template-columns: 108px 128px minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 22px;
  padding: 20px 4px;
  border-bottom: 1px solid #2b2b2b;
  text-decoration: none;
  transition: background 0.2s ease, padding 0.2s ease;
}
.wire__item:hover { background: #161616; padding-inline: 14px 4px; }

.wire__time {
  font-family: var(--mono);
  font-size: 12px;
  color: #8a8a8a;
  white-space: nowrap;
}

.wire__desk {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--red-bright);
  white-space: nowrap;
}

.wire__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(17px, 1.7vw, 21px);
  line-height: 1.32;
  letter-spacing: -0.01em;
  color: #fff;
}
.wire__item:hover .wire__title { text-decoration: underline; text-underline-offset: 4px; }

.wire__source {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #7d7d7d;
  white-space: nowrap;
}

@media (max-width: 860px) {
  .wire__item {
    grid-template-columns: auto 1fr;
    gap: 6px 16px;
    padding-block: 18px;
  }
  .wire__time  { grid-row: 1; }
  .wire__desk  { grid-row: 1; }
  .wire__title { grid-column: 1 / -1; grid-row: 2; }
  .wire__source{ grid-column: 1 / -1; grid-row: 3; }
}

/* placeholder shown until a feed is connected */
.wire__empty {
  padding: clamp(34px, 5vw, 62px) clamp(26px, 4vw, 54px);
  border: 1px solid #2e2e2e;
  border-left: 5px solid var(--red);
  background: #131313;
  text-align: center;
}
.wire__empty-head {
  font-family: var(--display);
  font-weight: 700;
  font-style: italic;
  font-size: clamp(24px, 3vw, 34px);
  color: #fff;
}
.wire__empty-note {
  margin: 14px auto 0;
  max-width: 52ch;
  font-size: 15.5px;
  color: #a4a4a4;
}
.wire__empty-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 28px;
}
.wire__empty-links a {
  padding: 9px 16px;
  border: 1px solid #3a3a3a;
  text-decoration: none;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #e6e6e6;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.wire__empty-links a:hover { background: var(--red); border-color: var(--red); color: #fff; }

/* ------------------------------------------------------------- colophon */

.colophon {
  padding: clamp(50px, 6vw, 84px) 0;
  background: var(--paper-warm);
  border-bottom: 1px solid var(--rule);
}

.colophon__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 60px);
}
.colophon__grid article {
  padding-top: 20px;
  border-top: 3px solid var(--ink);
}
.colophon__grid p {
  margin-top: 14px;
  font-size: 15.5px;
  line-height: 1.66;
  color: #3d3d3d;
}

.colophon__head {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(21px, 2.2vw, 27px);
  letter-spacing: -0.018em;
}

.feedlist { margin-top: 16px; }
.feedlist a {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--ink);
  transition: color 0.16s ease;
}
.feedlist a span { color: var(--ink-muted); }
.feedlist a:hover { color: var(--red); }
.feedlist a:hover span { color: var(--red); }

@media (max-width: 880px) {
  .colophon__grid { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------- footer */

.footer {
  background: var(--ink);
  color: #d4d4d4;
  padding: clamp(46px, 5vw, 72px) 0 28px;
  border-top: 5px solid var(--red);
}

.footer__grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: clamp(28px, 4vw, 56px);
}

.footer__brand img { width: 176px; }
.footer__brand p {
  margin-top: 16px;
  font-family: var(--display);
  font-style: italic;
  font-size: 17px;
  color: #9d9d9d;
}

.footer__col h2 {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #fff;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid #2e2e2e;
}
.footer__col li { margin-bottom: 9px; }
.footer__credit {
  font-family: var(--display);
  font-weight: 700;
  font-size: 17px;
  color: #fff;
  line-height: 1.25;
  margin-bottom: 14px !important;
}
.footer__credit span {
  display: block;
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--red-bright);
  margin-top: 4px;
}
.footer__col a {
  text-decoration: none;
  font-size: 14.5px;
  color: #b6b6b6;
  transition: color 0.16s ease;
}
.footer__col a:hover { color: var(--red-bright); }

.footer__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 10px;
  margin-top: clamp(34px, 4vw, 56px);
  padding-top: 20px;
  border-top: 1px solid #2a2a2a;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: #7b7b7b;
}
/* The owner credit is the only link in the legal line. It keeps its underline,
   which is the clearest signal in a line of running text, but lifts out of the
   muted grey so it does not read as more small print. */
.footer__base a {
  color: #b6b6b6;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color 0.16s ease;
}
.footer__base a:hover { color: var(--red-bright); }

@media (max-width: 880px) {
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .footer__grid { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------- preferences */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

@media print {
  .nav, .wire, .topbar .pip { display: none; }
  body { font-size: 12pt; }
  /* The ring is a control, not content, so it does not print. Paper then
     needs every desk laid out at once: undo the grid-stacking the ring
     layout uses, since six of the seven are hidden on screen. These sit
     after the ring's media query and match its specificity, so they win
     without reaching for !important. */
  .dial__stage, .dial__radio { display: none; }
  .dial { display: block; }
  .dial__panels { display: block; }
  .deskpanel {
    display: block;
    opacity: 1;
    visibility: visible;
    transform: none;
    break-inside: avoid;
    padding: 18pt 0;
    border-top: 1px solid #999;
  }
  .deskpanel__ghost { display: none; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
}
