  .story-feed { display:flex; flex-direction:column; gap:20px; }
  .story-card { display:flex; flex-direction:column; border:3px solid var(--ink);
    background:var(--paper); box-shadow:5px 5px 0 var(--ink); cursor:pointer;
    transition:transform var(--dur-hover) var(--ease), box-shadow var(--dur-hover) var(--ease); }
  .story-card[data-narrative-mode="consensus"] { box-shadow:5px 5px 0 var(--mustard); }
  .consensus-banner { display:flex; flex-direction:column; gap:5px; padding:11px 15px;
    border-bottom:3px solid var(--ink); background:var(--mustard); color:var(--ink); }
  .consensus-banner strong { font-family:var(--font-mono); font-size:9px; font-weight:800;
    letter-spacing:.16em; line-height:1.3; text-transform:uppercase; }
  .consensus-banner span { font-family:var(--font-sub); font-size:14px; font-weight:700;
    line-height:1.2; }
  .story-cover { position:relative; aspect-ratio:16/10; overflow:hidden;
    border-bottom:3px solid var(--ink); background:var(--paper-2); }
  .story-cover .cover-img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
  /* Spectrum duotone on feed thumbnails, tinted by the story's dominant lean
     (its heaviest coverage side), matching the coverage bar. A tie or no-lead
     story renders untinted grayscale (no side modifier class). */
  .story-cover--photo .cover-img { filter:grayscale(1) contrast(1.06) brightness(1.07); }
  .story-cover--photo::after { content:""; position:absolute; inset:0; z-index:1;
    mix-blend-mode:multiply; opacity:.82; pointer-events:none; }
  .story-cover--left::after { background:var(--spec-left); }
  .story-cover--center::after { background:var(--spec-center); }
  .story-cover--right::after { background:var(--spec-right); }
  .story-cover .topic-tag { z-index:3; }
  /* No-photo fallback: a "broke news" poster scene (ink + cream art) on a
     lean-tinted ground, so a photoless card still reads as news and stays
     colour-coded. Muted ground when the story has no clear lean. */
  .cover-fallback { position:absolute; inset:0; overflow:hidden; background:#8A7D66; }
  .cover-fallback svg { position:absolute; inset:0; width:100%; height:100%; display:block; }
  .cover-fallback::after { content:""; position:absolute; inset:0; background-image:var(--grain);
    background-size:150px 150px; mix-blend-mode:soft-light; opacity:.5; pointer-events:none; }
  .cover-fallback--left { background:var(--spec-left); }
  .cover-fallback--center { background:var(--spec-center); }
  .cover-fallback--right { background:var(--spec-right); }
  .topic-tag { position:absolute; z-index:2; top:11px; left:11px; padding:4px 7px;
    border:2px solid var(--ink); background:var(--paper); color:var(--ink);
    font-family:var(--font-mono); font-size:9px; font-weight:700; letter-spacing:.16em;
    line-height:1.3; text-transform:uppercase; }
  .story-meta { display:flex; justify-content:space-between; padding:13px 15px 6px;
    color:var(--smoke); font-family:var(--font-mono); font-size:9px; font-weight:700;
    letter-spacing:.14em; line-height:1.3; text-transform:uppercase; }
  .story-meta strong { color:var(--pumpkin-dark); }
  .story-title { padding:0 15px 4px; font-family:var(--font-sub); font-size:19px;
    font-weight:700; line-height:1.14; overflow-wrap:break-word; word-break:break-word; }
  .framing-lines { display:flex; flex-direction:column; gap:7px; padding:10px 15px 4px; }
  .framing-line { display:flex; align-items:baseline; gap:9px; font-size:12.5px; line-height:1.35;
    overflow-wrap:break-word; word-break:break-word; }
  .framing-line span:last-child { min-width:0; }
  .framing-line--silent span:last-child { color:var(--smoke); }
  .framing-bullet { width:8px; height:8px; flex:none; border:1.5px solid var(--ink);
    transform:translateY(1px); }
  .framing-line--left .framing-bullet { background:var(--spec-left); }
  .framing-line--center .framing-bullet { background:var(--spec-center); }
  .framing-line--right .framing-bullet { background:var(--spec-right); }
  /* Silent side: a struck-out eye (a blindspot) instead of the covered-line square.
     Sized ~20px to read at a glance; kept in the side's colour so the dark side is
     still identifiable, with an ink slash. Line is single-line, so centre the mark. */
  .framing-line--silent { align-items:center; }
  .framing-eye { flex:none; width:20px; height:14px; }
  .framing-line--left .framing-eye { color:var(--spec-left); }
  .framing-line--center .framing-eye { color:var(--spec-center); }
  .framing-line--right .framing-eye { color:var(--spec-right); }
  .framing-eye .eye-slash { stroke:var(--ink); }
  .card-coverage { padding:12px 15px 15px; }
  .coverage-bar { display:flex; flex:1; height:10px; gap:3px; margin-right:16px; }
  .coverage-segment--left { background:var(--spec-left); }
  .coverage-segment--center { background:var(--spec-center); }
  .coverage-segment--right { background:var(--spec-right); }
  .card-coverage .coverage-bar { height:7px; gap:2px; margin:0; }
  .empty-feed { padding:32px 0; color:var(--smoke); font-family:var(--font-mono);
    font-size:12px; text-align:center; }
  .story-card:active { transform:translate(5px, 5px); box-shadow:0 0 0 var(--ink); }
  .story-card:focus-visible { outline:3px solid var(--pumpkin); outline-offset:3px; }
  @media (hover:hover) {
    .story-card:hover { transform:translate(-3px, -3px); box-shadow:8px 8px 0 var(--ink); }
  }
