/*
  cards.css: the belt's card types beyond the designer's Constitution card,
  drawn in her system (sanctum.css): the same frame, type, colours and dark
  decision panel. Signal keeps its own grammar (verified badge, strength
  dials, established vs not established, commit before reveal) inside it.

  Also the rail additions: ten dots, the counting note, the list form.
*/

/* ------------------------------------------------------------ the rail */

.dots-progress { gap: 5px; }
.dots-progress i { flex: 1; width: auto; max-width: 28px; }
.rail-record { display: inline-block; margin-top: 12px; font-size: 14px; color: #246ac5; }
.stats-note { margin-top: 14px; font-size: 12px; line-height: 1.45; color: #737873; }
.stats-note a { color: #246ac5; }

.rail-list { border-top: 1px solid var(--line); padding: 20px 0; }
.rail-list .eyebrow { font-size: 10px; color: #6c706b; }
.rail-list p:not(.eyebrow) { margin: 8px 0 12px; font-size: 13px; line-height: 1.45; color: #4f544e; }
.rail-list div { display: flex; gap: 6px; }
.rail-list input[type="email"] { flex: 1; min-width: 0; padding: 10px; font-size: 13px; }
.rail-list button { flex: none; padding: 10px 14px; border-radius: 7px; background: #191919; color: #fff; font-size: 13px; }
.rail-list small { display: block; min-height: 17px; margin-top: 7px; font-size: 11px; color: #6d726d; }
.rail-list.is-done small { color: #1f7a3a; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }


.optional-details { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line); font-size: 14px; }
.optional-details summary { cursor: pointer; color: #444; }
.record-signup { display: inline-flex; margin-top: 18px; }

/* ------------------------------------------------------------ Signal card */

.signal-card { --accent: #191919; }
.sg-species i { background: #191919; border-radius: 50%; }
.sg-badge { padding: 3px 9px; border-radius: 999px; font-size: 11px; letter-spacing: .2px; }
.sg-verified { background: #dcf5df; color: #1f7a3a; }
.sg-reported { background: #fff4d6; color: #7a5a12; }
.signal-card .story-age { margin-left: auto; }
.signal-card .meta .sg-badge { order: 3; }
.sg-note { margin-top: 12px; font-size: 13px; line-height: 1.5; color: #7a5a12; }

.sg-strength { margin-top: 18px; }
.sg-overall { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: center; font-size: 13px; color: #191919; }
.sg-track { position: relative; display: block; height: 6px; border-radius: 6px; background: #ececec; overflow: hidden; }
.sg-track > span { position: absolute; inset: 0 auto 0 0; background: #438ff4; border-radius: 6px; }
.sg-track-wide { height: 8px; }
.sg-dial { display: grid; gap: 5px; cursor: help; }
.sg-dial-k { font-size: 11px; color: #777; }
.sg-dial .sg-track > span { background: #8fb7f6; }

.sg-shift { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 20px 0 0; }
.sg-shift div { padding: 12px 14px; border-radius: 10px; background: #f6f6f4; }
.sg-shift div + div { background: #edf4ff; }
.sg-shift dt { font-size: 11px; letter-spacing: 1px; text-transform: uppercase; color: #777; }
.sg-shift dd { margin: 6px 0 0; font-size: 14px; line-height: 1.5; color: #333; }

.signal-card .context-more.sg-sec { margin-top: 16px; padding-top: 0; }
.signal-card .context-more.sg-sec:first-of-type { margin-top: auto; padding-top: 24px; }
.sg-sec p { color: #555; font-size: 14px; }
.sg-trail { margin: 14px 0 0; padding: 0; list-style: none; border-left: 2px solid #e5e5e5; }
.sg-trail li { position: relative; padding: 0 0 12px 16px; }
.sg-trail li::before { content: ""; position: absolute; left: -5px; top: 6px; width: 8px; height: 8px; border-radius: 50%; background: #bbb; }
.sg-trail li.sg-reacts::before { background: #438ff4; }
.sg-trail span { font-size: 11px; letter-spacing: .6px; text-transform: uppercase; color: #888; }
.sg-trail p { margin-top: 3px !important; }
.sg-gloss { margin: 14px 0 0; display: grid; gap: 8px; }
.sg-gloss dt { font-size: 13px; color: #191919; }
.sg-gloss dd { margin: 2px 0 0; font-size: 13px; color: #666; line-height: 1.5; }
.sg-bounds { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 14px; }
.sg-bounds h4 { margin: 0 0 6px; font-size: 12px; font-weight: 500; letter-spacing: .6px; text-transform: uppercase; color: #1f7a3a; }
.sg-bounds div + div h4 { color: #9a4a16; }
.sg-bounds ul { margin: 0; padding-left: 16px; font-size: 13px; line-height: 1.5; color: #555; }
.sg-bounds li + li { margin-top: 4px; }
.sg-rationale { margin-top: 12px !important; font-size: 13px !important; color: #777 !important; }

.sg-options { gap: 8px; }
.sg-options .choice { --bar-color: #438ff4; padding: 12px 14px; }
.sg-options .choice-heading { margin-bottom: 3px; }
.sg-options .choice-body { font-size: 12px; color: #cfcfcf; }
.sg-options .sg-too-early { --bar-color: #9a9a9a; border-style: dashed; }
.sg-options .choice:disabled { cursor: default; opacity: 1; }
.sg-options .choice:disabled:not(.selected) { opacity: .55; }
.sg-options .choice.selected { border-color: #75acfa; background: #1f2a3a; }

.sg-reveal .insight-top strong { font-size: 15px; }
.sg-crowd { display: grid; gap: 7px; margin-top: 16px; }
.sg-bar { position: relative; display: grid; grid-template-columns: 1fr auto; gap: 4px 10px; padding: 9px 12px; border: 1px solid #444; border-radius: 8px; background: #222; overflow: hidden; isolation: isolate; font-size: 13px; color: #e6e6e6; }
.sg-bar-track { position: absolute; inset: 0; z-index: -1; }
.sg-bar-track span { position: absolute; inset: 0 auto 0 0; background: #438ff4; opacity: .22; animation: sg-grow .65s ease-out; transform-origin: left; }
.sg-bar.sg-yours { border-color: #75acfa; }
.sg-bar.sg-yours .sg-bar-track span { opacity: .45; }
.sg-bar-label b { font-weight: 500; color: #9cc4ff; }
.sg-bar-num { font-variant-numeric: tabular-nums; color: #fff; }
.sg-crowd-n { margin-top: 6px; font-size: 12px; color: #bdbdbd; }
.sg-watch { margin-top: 16px; padding: 16px 18px; border-radius: 12px; background: #f6f6f4; color: #191919; }
.sg-watch { background: #f6f6f4; }
.sg-watch > span { font-size: 11px; letter-spacing: 1px; text-transform: uppercase; color: #666; }
.sg-watch > span { color: #666; }
.sg-watch ul { margin: 8px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; font-size: 13px; line-height: 1.5; color: #444; }
.sg-watch b { display: inline-block; min-width: 18px; margin-right: 4px; font-weight: 500; color: #246ac5; }
@keyframes sg-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.signal-card .card-foot { flex-wrap: wrap; }
.sg-sources a, .sg-links a { color: #515c49; text-decoration: underline; text-decoration-color: #ccc; text-underline-offset: 3px; }

@media (max-width: 700px) {
  .sg-shift, .sg-bounds { grid-template-columns: 1fr; }
}

/* Signal hooks are sentences, not headlines: a size that fits them. */
.signal-card .story-title { font-size: clamp(22px, 1.75vw, 28px); line-height: 1.25; margin: 22px 0 16px; }
.signal-card .bluf { font-size: 15px; }
.sg-source-list { margin: 14px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.6; }
.sg-source-list a { color: #246ac5; text-decoration: underline; text-underline-offset: 3px; }
.sg-sources { color: #858980; }

/* ------------------------------------------------------------ one card per screen

   Every card fills the space under the header and snaps into place, at every
   screen size, so there is never half of one card and half of the next. The
   header height is measured by sanctum.js (--belt-top). Long cards scroll
   inside themselves; at their end, the page moves on to the next card. */

/* Proximity, not mandatory.

   Mandatory snap traps a reader on any card taller than the screen: the page
   must come to rest on a snap point, so the bottom of that card is unreachable
   and the next one will not arrive. Measured at 390x844, five of the nine cards
   were taller than the usable height, and four wheel gestures moved the page
   thirty-four pixels and then nothing. A card grows when it is answered, so
   guaranteeing every card fits every phone is not something this layout can
   promise.
   
   Proximity still settles on a card edge when the reader stops near one, which
   is the feel that was asked for, and it can never refuse to move. */
html:has(body.page-sanctum) { scroll-snap-type: y proximity; scroll-padding-top: calc(var(--belt-top, 76px) + var(--belt-gap)); }
/* The gap lives on the root, not on the body. The page's scroll-padding is set
   on the html element, and a variable declared on body does not reach it: the
   padding silently fell back to 18px while the cards used 10, so every card
   came to rest eight pixels out on a phone. */
html:has(body.page-sanctum), html:has(body.page-signal) { --belt-gap: 18px; }
body.page-sanctum { --card-h: calc(100vh - var(--belt-top, 76px) - 2 * var(--belt-gap)); }
@supports (height: 100dvh) { body.page-sanctum { --card-h: calc(100dvh - var(--belt-top, 76px) - 2 * var(--belt-gap)); } }
.page-sanctum .layout { padding-top: var(--belt-gap); }
.page-sanctum .right-rail { top: calc(var(--belt-top, 76px) + var(--belt-gap)); max-height: var(--card-h); }
.page-sanctum #stories > .story-card {
  height: var(--card-h); min-height: 0;
  /* Wide enough that the card above is fully gone, even under the see-through header. */
  margin-bottom: calc(var(--belt-top, 76px) + 2 * var(--belt-gap));
  /* The page's scroll-padding already holds the card clear of the header. This
     used to repeat it, and only worked because --belt-gap was not readable on
     the html element, which made the padding invalid and left the margin to do
     the job alone. Once the variable resolved, the two added up and every card
     came to rest a header's height too low. */
  scroll-snap-align: start; scroll-margin-top: 0;
}
.page-sanctum #stories > .story-card .story-top,
.page-sanctum #stories > .story-card .decision { overflow-y: auto; overscroll-behavior-y: auto; scrollbar-width: thin; scrollbar-color: #aaa transparent; }

@media (max-width: 950px) {
  /* One column: the card itself scrolls. */
  .page-sanctum #stories > .story-card { grid-template-rows: auto auto auto; overflow-y: auto; overscroll-behavior-y: auto; }
  .page-sanctum #stories > .story-card .story-top,
  .page-sanctum #stories > .story-card .decision { overflow: visible; }
}
@media (max-width: 700px) {
  html:has(body.page-sanctum), html:has(body.page-signal) { --belt-gap: 10px; }
  .page-sanctum .layout { padding: var(--belt-gap) 12px 0; }
  .page-sanctum #stories > .story-card { border-radius: 16px; }
  /* On phones the rail would sit below the last card, where a snapping page
     cannot rest. Its parts live elsewhere: progress in the chip below, the
     next steps in the closing card, the list in every page's footer. */
  .page-sanctum .right-rail { display: none; }
}

/* A small progress chip on phones, where the rail is out of sight. */
.belt-progress { display: none; }
@media (max-width: 700px) {
  .belt-progress { position: fixed; right: 64px; top: 19px; z-index: 31; display: inline-flex; align-items: baseline; gap: 2px; padding: 6px 12px; border-radius: 999px; background: rgba(25, 25, 25, .88); color: #fff; font-size: 14px; backdrop-filter: blur(10px); }
  .belt-progress b { font-weight: 600; font-size: 15px; }
  /* Out of the way while the menu is open. */
  body:has(.site-header.menu-open) .belt-progress { display: none; }
  .belt-progress span { margin-left: 6px; color: #c8c8c8; font-size: 12px; }
}

/* ------------------------------------------------------------ the framing cards */

.frame-card { --accent: #438ff4; }
.frame-title { font-size: clamp(30px, 2.8vw, 44px) !important; line-height: 1.1 !important; letter-spacing: -.01em; }
.frame-facts { display: flex; flex-wrap: wrap; gap: 10px; margin: 28px 0 0; padding: 0; list-style: none; }
.frame-facts li { padding: 9px 14px; border: 1px solid #e3e3e3; border-radius: 999px; font-size: 14px; color: #444; }
.frame-facts b { font-weight: 600; color: #191919; }
.frame-decision { display: flex; flex-direction: column; }
.frame-decision h3 { margin-top: 24px; }
.frame-steps { display: grid; gap: 16px; margin: 28px 0 30px; padding: 0; list-style: none; }
/* On a tall screen the three steps used to sit in a clump at the top of the dark
   panel with a field of black under them. They share the height instead: the
   space between them grows, the panel stays one block of type. */
@media (min-width: 950px) {
  .frame-decision .frame-steps { flex: 1; display: flex; flex-direction: column; justify-content: space-evenly; gap: 20px; margin-block: 24px; }
  .frame-decision .frame-steps li { align-items: center; }
}
.frame-steps li { display: grid; grid-template-columns: 34px 1fr; gap: 14px; align-items: start; }
.frame-steps li > span { display: grid; place-items: center; width: 34px; height: 34px; border: 1px solid #555; border-radius: 50%; color: #9cc4ff; font-size: 14px; }
.frame-steps b { display: block; color: #fff; font-size: 16px; font-weight: 500; }
.frame-steps p { margin-top: 3px; color: #c4c4c4; font-size: 14px; line-height: 1.5; }
.frame-copy { color: #d0d0d0; font-size: 15px; line-height: 1.6; }
.frame-go { display: inline-flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: auto; padding: 16px 20px; border-radius: 12px; background: #438ff4; color: #fff; font-size: 16px; transition: background .2s, transform .2s; }
.frame-go:hover { background: #2f7de8; transform: translateY(-1px); }
.frame-go-light { margin-top: 28px; align-self: flex-start; background: #191919; }
.frame-go-light:hover { background: #333; }
.frame-link { margin-top: 14px; color: #c4c4c4; font-size: 14px; }
.frame-link:hover { color: #fff; }
.finale-card[data-complete="true"] .finale-open,
.finale-card[data-complete="false"] .finale-done { display: none; }
@media (max-width: 950px) { .frame-go { margin-top: 12px; } }
/* Three ways in, on the first screen: answer, read a Signal, read the
   Constitution. The button sits under what the site promises about an answer,
   so nobody is asked before they are told. */
.frame-promise { margin-top: 14px; font-size: 13.5px; line-height: 1.55; color: #5f635c; }
.frame-paths { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; margin-top: 20px; }
.frame-paths .frame-go { margin-top: 0; align-self: stretch; }
.frame-path { color: #246ac5; font-size: 14px; }
.frame-path:hover { text-decoration: underline; text-underline-offset: 3px; }
.frame-decision { display: flex; flex-direction: column; }
.frame-articles { display: flex; flex-wrap: wrap; gap: 6px; margin: auto 0 0; padding: 20px 0 0; list-style: none; }
.frame-articles li { padding: 5px 11px; border: 1px solid var(--line); border-radius: 999px; color: #5f635c; font-size: 12.5px; }
.frame-articles li.done { border-color: #1f7a3a; color: #1f7a3a; }
.frame-back { margin-top: auto; padding-top: 16px; border-top: 1px solid #333; color: #c4c4c4; font-size: 13px; line-height: 1.5; }
@media (max-width: 700px) { .intro-card .frame-facts { margin-top: 18px; } }

@media (max-width: 700px) {
  .context-fold .context { margin-top: 12px; }
  /* The robot steps back a little on phones, so it never covers an answer. */
  .page-sanctum .companion-button { width: 72px; height: 72px; }
  .page-sanctum .sanctity-companion { bottom: 12px; right: 6px; }
  .page-sanctum .companion-message { margin-right: 52px; }
}

/* Illustrative scenarios say so, above the story, on every card. */
.scenario-note { display: inline-block; align-self: flex-start; margin: -8px 0 16px; padding: 4px 10px; border-radius: 999px; background: #f3f3f1; color: #4a4a47; font-size: 12px; }

/* An answer picked on the home page's preview, waiting to be confirmed here. */
.choice.is-picked { border-color: var(--bar-color); box-shadow: 0 0 0 2px var(--bar-color); animation: picked 1.4s ease-in-out 3; }
@keyframes picked { 50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--bar-color) 45%, transparent); } }

/* ------------------------------------------------------------ contrast (WCAG AA, checked with axe)
   The designer's faint greys and the light blue buttons fell below 4.5:1. */
.page-sanctum .card-foot { color: #5f635c; }
.frame-go, .page-sanctum .lab-teaser { background: #1f66d1; }
.frame-go:hover { background: #1a57b3; }
.page-sanctum .lab-teaser .lab-link { color: #fff; }
.sg-shift dt { color: #555; }
.sg-sources { color: #5f635c; }
.stats-note a { text-decoration: underline; text-underline-offset: 2px; }
.page-sanctum .context-more summary { color: #5f635c; }
.sg-dial-k { color: #555; }

/* ------------------------------------------------------------ four positions and "Not sure" */
.choices { gap: 10px; }
.choice-not-sure { justify-self: start; align-self: flex-start; width: auto; margin-top: 6px; padding: 8px 16px; border: 1px dashed #8a8a86; border-radius: 999px; background: transparent; color: #d6d6d2; font: inherit; font-size: 14px; cursor: pointer; }
.choice-not-sure:hover { border-style: solid; color: #fff; }
.choice-not-sure.selected { border-style: solid; border-color: #d6d6d2; background: rgba(255, 255, 255, .1); color: #fff; }
.choice-not-sure:disabled { opacity: .6; }
.choice .choice-insight b { font-weight: 600; }
/* Once a question has formed, every position shows its share as a faint bar; yours stays strongest. */
.decision .choice::before { width: var(--share, 0); opacity: .13; }
.decision .choice.selected::before { opacity: .26; }
.idle-nudge { border: 1px solid rgba(255, 255, 255, .28); }

/* Typography polish on the Sanctum and Signal pages too. */
h1, h2, h3, h4, .story-title, .choice-heading { text-wrap: balance; }
p, li, dd, .choice-body, .bluf { text-wrap: pretty; }

/* Tablets: the side rail was squeezed into a narrow column. From 900px down it
   sits below the cards, as on phones, and the progress chip moves to the header. */
@media (max-width: 900px) and (min-width: 701px) {
  .layout { display: block; padding: 22px 24px; }
  .feed { max-width: none; }
  .right-rail { position: static; display: block; margin-top: 30px; border: 1px solid var(--line); border-radius: 16px; padding: 24px; max-height: none; overflow: visible; }
  .belt-progress { position: fixed; right: 64px; top: 19px; z-index: 31; display: inline-flex; align-items: baseline; gap: 2px; padding: 6px 12px; border-radius: 999px; background: rgba(25, 25, 25, .88); color: #fff; font-size: 14px; }
  .belt-progress b { font-weight: 600; font-size: 15px; }
  .belt-progress span { margin-left: 6px; color: #c8c8c8; font-size: 12px; }
  body:has(.site-header.menu-open) .belt-progress { display: none; }
}

/* The Signal card's evidence brief: what it rests on, before the call. */
/* The report on the face: sections, not a brief above a poll. */
.sg-lead-rest { margin: 10px 0 0; font-size: 15px; line-height: 1.6; color: #44443f; }
.sg-h { margin: 0 0 10px; font-size: 11px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: #6b6b66; }
.sg-h em { font-style: normal; text-transform: none; letter-spacing: 0; color: #5f635c; font-size: 11.5px; }
.sg-h em::before { content: "· "; }
.sg-evidence, .sg-read { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line); }
.sg-observed { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 12px; margin: 0; font-size: 14px; line-height: 1.55; color: #3f3f3b; }
.sg-observed > span { padding-top: 2px; color: #6b6b66; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; }
.sg-read p { margin: 0; max-width: 68ch; font-size: 14.5px; line-height: 1.6; color: #333; }
.sg-more { margin-top: 10px; }
.sg-more > summary { font-size: 12.5px; color: #6b6b66; cursor: pointer; }
.sg-more > summary:hover { color: #191919; }
.sg-more p { margin: 10px 0 0; padding-left: 108px; font-size: 13px; line-height: 1.55; color: #5f635c; }
@media (max-width: 700px) { .sg-more p { padding-left: 0; } }
.sg-read .sg-watch { margin-top: 14px; }
.sg-weight { margin-top: 12px; }
.sg-weight > summary { font-size: 12px; color: #6b6b66; cursor: pointer; }
.sg-weight > summary:hover { color: #191919; }
.sg-weight[open] > summary { margin-bottom: 12px; }
.sg-weight .sg-dial { display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 12px; align-items: center; margin-top: 8px; }
.sg-rationale { margin: 12px 0 0; font-size: 12.5px; line-height: 1.5; color: #5f635c; }
/* The call is the quiet end of a card, not its subject. */
.sg-decision .decision-label span:first-child { letter-spacing: .12em; }
.sg-decision .guide { font-size: 12.5px; line-height: 1.5; }
@media (max-width: 700px) { .sg-observed { grid-template-columns: 1fr; gap: 2px; } }

/* ------------------------------------------------------------ a Signal card is a read

   The Constitution belt is a reel: one short question, one screen, snap to the
   next. A Signal card is a piece of writing, so on its deck and on its own page
   it takes the height its report needs, full width, with the call as a quiet
   band underneath instead of a dark half shouting alongside. Nothing snaps
   while someone is reading.
*/
/* Signal snaps, card to card, on a phone and on a desktop. It used not to,
   because a Signal card was a full report and a snapping page full of reports
   taller than the screen is a trap. The deck is briefs now, so each one can fit
   and the page can move a card at a time like the Sanctum does.

   A single card on its own page still does not snap: there is nothing to snap
   to, and the report there is meant to be read at length. */
html:has(body.page-signal) { scroll-snap-type: y proximity; scroll-padding-top: calc(var(--belt-top, 76px) + var(--belt-gap, 18px)); }
html:has(body.page-card) { scroll-snap-type: none; }
.page-signal #stories > .story-card, .page-card #stories > .story-card {
  height: auto; min-height: 0; grid-template-columns: 1fr; grid-template-rows: auto auto auto;
  overflow: hidden;
  margin-bottom: 28px;
}
/* A single card on its own page has nothing to snap to and is meant to be read
   at length, so only that page opts out. This used to be written into the rule
   above, which both pages share, and it silently cancelled the snap on the deck
   as well: the deck was left with exactly one snap target, the hero, and a
   mandatory-snap page with one target cannot be scrolled at all. Four wheel
   gestures moved it nowhere. */
.page-card #stories > .story-card { scroll-snap-align: none; scroll-snap-stop: normal; }
/* The offset comes from the page's scroll-padding alone. Setting it here as
   well adds the two together, and the card came to rest a header's height too
   far down, with that much white above it. */
.page-signal #stories > .story-card { scroll-snap-align: start; scroll-margin-top: 0; }
.page-signal #stories > .story-card .story-top, .page-card #stories > .story-card .story-top,
.page-signal #stories > .story-card .decision, .page-card #stories > .story-card .decision { overflow: visible; }
.page-signal .right-rail, .page-card .right-rail { max-height: none; }
.story-card.signal-card .story-top { max-width: 78ch; padding: 34px 38px 30px; }
/* On a wide card the report used to leave a column of dead white down the right.
   The section labels move into that space, where a magazine would put them, and
   the text keeps its reading measure. */
@media (min-width: 1200px) {
  .story-card.signal-card .story-top { max-width: none; padding-right: 56px; }
  .story-card.signal-card .story-top > .meta,
  .story-card.signal-card .story-top > .story-title,
  .story-card.signal-card .story-top > .bluf,
  .story-card.signal-card .story-top > .sg-lead-rest,
  .story-card.signal-card .story-top > .sg-shift,
  .story-card.signal-card .story-top > .sg-sec { max-width: 68ch; margin-left: 178px; }
  .story-card.signal-card .story-top > .story-title { margin-left: 178px; }
  .signal-card .sg-evidence, .signal-card .sg-read { display: grid; grid-template-columns: 150px minmax(0, 68ch); gap: 0 28px; }
  .signal-card .sg-evidence > .sg-h, .signal-card .sg-read > .sg-h { grid-column: 1; grid-row: 1; margin: 0; line-height: 1.5; }
  .signal-card .sg-evidence > *:not(.sg-h), .signal-card .sg-read > *:not(.sg-h) { grid-column: 2; }
  /* The rail already says which section this is, so the line inside it does not repeat a column. */
  .signal-card .sg-observed { grid-template-columns: 1fr; gap: 4px; }
  .signal-card .sg-more p { padding-left: 0; }
  .signal-card .sg-h em { display: block; }
  .signal-card .sg-h em::before { content: ""; }
}
.story-card.signal-card .sg-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 10px; align-items: start; }
.story-card.signal-card .decision h3 { max-width: 34ch; }
.story-card.signal-card .sg-reveal { max-width: 720px; }
@media (max-width: 900px) { .story-card.signal-card .story-top { padding: 24px; } }

/* ------------------------------------------------------------ what does this mean?

   Next to the question, on the dark side, because that is where a reader
   hesitates. Shut by default: the question has to stand on its own words.
*/
.story-help { margin: 14px 0 4px; }
.story-help > summary { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border: 1px solid #3a3a3a; border-radius: 999px; color: #d8d8d8; font-size: 13px; cursor: pointer; list-style: none; }
.story-help > summary::-webkit-details-marker { display: none; }
.story-help > summary::after { content: "+"; color: #9a9a9a; }
.story-help[open] > summary::after { content: "\2212"; }
.story-help > summary:hover { border-color: #5d5d5d; color: #fff; }
.story-help dl { margin: 14px 0 0; display: grid; gap: 8px; }
.story-help dt { color: #fff; font-size: 13px; }
.story-help dd { margin: 2px 0 0; color: #bdbdbd; font-size: 13px; line-height: 1.5; }
.story-help-eg { margin: 14px 0 0; color: #bdbdbd; font-size: 13px; line-height: 1.55; }
.story-help-eg span { display: block; margin-bottom: 4px; color: #8f8f8f; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; }

/* ------------------------------------------------------------ a deck of briefs

   Every card on /signal is a brief: what happened, what changed, how much it
   weighs, and the way to the report. The report itself is on the card's own
   page, where it has room to be read.
*/
.story-card.signal-brief { grid-template-rows: auto auto; }
.signal-brief .story-top { padding: 26px 30px 22px; max-width: 74ch; }
.signal-brief .story-title { font-size: clamp(1.4rem, 2.1vw, 1.9rem); }
.signal-brief .story-title a { display: block; }
.signal-brief .story-title a:hover { text-decoration: underline; text-underline-offset: 4px; }
.signal-brief .bluf { margin-top: 10px; }
.sg-brief-shift { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 12px; margin: 14px 0 0; font-size: 14px; line-height: 1.5; color: #44443f; }
.sg-brief-shift > span { padding-top: 2px; color: #6b6b66; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; }
.sg-brief-strength { margin-top: 16px; max-width: 420px; }
.sg-open { color: #246ac5; }
.sg-open:hover { text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 700px) { .signal-brief .story-top { padding: 22px; } }

/* ------------------------------------------------ the values card, rebuilt

   Set at the Product and Marketing meeting on 21 September 2026, after a
   first-time reader walked the site cold and could not tell what to do.

   Three rules, in order of how much they matter:

   1. The black pane answers on its own. Title, a complete question, four
      labels. Nobody has to read the left pane to take a position, so the
      left pane is background rather than homework.
   2. A values card never scrolls. Its text is short and fixed, so the card
      is the same height every time. Signal may scroll; this may not.
   3. One panel open at a time. Opening "who it affects" closes "why it
      matters", so an open panel can never push the question off the screen. */

/* 1. No scrolling regions on a values card, at any width. This overrides both
      the earlier rule here and the one in the designer stylesheet, which each
      let a pane scroll when its contents outgrew it. Nothing outgrows it now,
      and a card that cannot scroll is a card that cannot hide its own end. */
.page-sanctum #stories > .story-card[data-kind="constitution"] .story-top,
.page-sanctum #stories > .story-card[data-kind="constitution"] .decision {
  overflow: visible;
}
.page-sanctum #stories > .story-card[data-kind="constitution"] { overflow: hidden; }

/* 2. Background, closed until asked for. */
.page-sanctum .context { display: block; border-top: 1px solid var(--line); margin-top: auto; padding-top: 8px; }
.ctx-open {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; padding: 14px 0; background: transparent; border: 0;
  border-bottom: 1px solid var(--line); text-align: left;
  font-size: 15px; color: #191919;
}
.ctx-open i { flex: none; width: 11px; height: 11px; border-right: 1.6px solid #8a8a8a; border-bottom: 1.6px solid #8a8a8a; transform: rotate(45deg) translate(-2px, -2px); transition: transform .18s ease; }
.ctx-open[aria-expanded="true"] i { transform: rotate(-135deg) translate(-3px, -3px); border-color: #191919; }
.ctx-open:hover { color: #000; }
.ctx-panel { padding: 4px 0 16px; font-size: 15px; line-height: 1.6; color: #666; border-bottom: 1px solid var(--line); }
.ctx-panel p { margin: 0; }
.ctx-panel dl { margin: 0; display: grid; gap: 10px; }
.ctx-panel dt { font-size: 14px; color: #191919; }
.ctx-panel dd { margin: 2px 0 0; font-size: 14px; line-height: 1.5; color: #666; }

/* 3. Four labels in a row, hardest no on the left to hardest yes on the right.
      A reader who has seen one card knows how to read every other card. */
.page-sanctum .choices[data-row] { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; align-items: stretch; }
.page-sanctum .choices[data-row] .choice {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 14px 12px 12px; min-height: 96px; text-align: left; grid-template-columns: none;
}
/* The ends of the ladder, because the row does not always run the same way.
   Half of readers get the four positions reversed, so that eight questions in
   a row cannot teach a hand where to reach before the eyes have read anything.
   Whichever way it runs, the two ends say which way it runs.

   The 1 to 4 that used to sit on each tile are gone: a rank printed on a
   position turns a set of views into a scale, and a scale invites the middle
   one. */
.page-sanctum .choice-ends { display: flex; justify-content: space-between; margin: 0 2px 7px; font-size: 11px; letter-spacing: .6px; text-transform: uppercase; color: #9a9a9a; }
.page-sanctum .choice-heading { margin: 0; font-size: 14px; line-height: 1.25; }
/* The sentence that says what a position means is on the tile, always.
   
   It used to appear on hover, and that was two faults in one. The tile grew
   when a pointer crossed it, so the row, the pane and the whole card changed
   height under the reader's hand, four times per card. And the browser drew
   its own tooltip with the same sentence in it, so the text arrived twice at
   once in two different places.
   
   Reserving the space and revealing it on hover would fix the first and not
   the second, and would still leave a person who is not hovering unable to
   read what they are choosing between. So it is simply there: nothing to
   discover, nothing that moves, and no control needed to ask for it. */
.page-sanctum .choice-body { display: block; font-size: 12px; line-height: 1.4; color: #c4c4c4; }
.page-sanctum .choice:hover .choice-body, .page-sanctum .choice:focus-visible .choice-body { color: #e8e8e8; }
.choice-share { display: none; margin-top: auto; width: 100%; height: 4px; border-radius: 4px; background: #3a3a3a; overflow: hidden; }
.choice-share i { display: block; height: 100%; width: var(--share, 0%); background: var(--bar-color); transition: width .6s ease; }

.choice-extras { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 12px; }
.page-sanctum .choice-not-sure { margin: 0; }

@media (max-width: 1150px) {
  .page-sanctum .choices[data-row] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 4. Wherever the two panes cannot sit side by side they become two tabs, with
      the question in front, so a reader never has to get past the background to
      reach the question.

      This used to start at 700px, which left the band from 701 to 950 with the
      panes stacked and the background on top: a tablet reader met "who it
      affects" and "why it matters" before they met the question, which is the
      one thing the 21 September meeting said must not happen. The card stops
      being two columns at 950, so that is where the tabs now start. */
.card-tabs { display: none; }
@media (max-width: 950px) {
  .page-sanctum #stories > .story-card[data-kind="constitution"] { display: block; }
  .card-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 0; background: #fff; border-bottom: 1px solid var(--line); }
  .card-tabs .tab { padding: 14px 8px; background: transparent; border: 0; border-bottom: 2px solid transparent; color: #666; font-size: 14px; }
  .card-tabs .tab.on { color: #191919; border-bottom-color: #191919; }
  .page-sanctum .choices[data-row] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .page-sanctum .choices[data-row] .choice { min-height: 84px; }
}

/* 5. A short card is a short card. The card used to be locked to the height of
      the window, which was right when it carried a scenario and three scrolling
      regions. With the text cut, that lock left half a screen of empty white on
      the left and half a screen of empty black on the right: the same dead space
      complaint as before, arriving from the opposite direction. The card now
      takes the height its content needs, so eight questions pass under the
      reader faster, which is the whole point of the rebuild.

      That holds on a phone, where the card scrolls inside itself and the page
      is a column. On a wide screen it is undone below, because a card shorter
      than the screen is what put a third of a screen of nothing between one
      card and the next. */
.page-sanctum #stories > .story-card[data-kind="constitution"] { height: auto; min-height: 0; }

/* 5b. One card is one screen, and the screen is the card.

      The version before this one put the air between the cards instead of
      inside them: each card kept its content height and the script opened a
      gap under it until the next card began exactly one screen down. The
      arithmetic was right and the page was wrong. Measured at 1440x900, a
      values card was 527 tall in an 806 tall opening, so a reader saw the card
      and then three hundred and sixty five pixels of nothing, and a scroll
      that stopped anywhere in that nothing was too far from either card for
      proximity to pull it in. Empty page, no snap, which is exactly what it
      was reported as: too much gap, and the snap gone.

      So the card is the screen again. The gap under it is the header plus the
      two margins, which is the distance that puts the next card just below the
      fold, and the pitch is a screen because the card is a screen. The reason
      it was made short was dead space inside the card, and that is a layout
      problem inside the card, solved below where it lives: the dark pane
      spreads its prompt and its four positions over the height it is given,
      and the white pane sets its background against the foot.

      Except that it does not, and this is the third time the answer has been
      "stretch the card" and the third time it was wrong. Locked to the window
      it cut 119 pixels off the dark pane the moment a card was answered, which
      is the reader's own result. Told to spread its content instead, it put a
      two hundred pixel hole above the positions and another under them at
      1920x1080, and stood the four tiles up as boxes two thirds empty.

      Two full cards or one, never one and a half. Two was measured and does
      not fit: two cards and a gap inside an 806 pixel opening is 383 pixels
      each, and the card is 527 of real content, so it would be cut. So it is
      one, filling the opening.

      Which means the card has to earn the height rather than be padded out to
      it, and that is what the two attempts before this got wrong: they kept
      the type the size it is in a 527 pixel card and let the spare pixels fall
      into gaps. On a card that is the whole screen the question is the largest
      thing on it and the four positions are panels, not chips. The size of the
      type is set from the height of the card below, so a taller window gets a
      bigger card rather than more air. */
@media (min-width: 951px) {
  .page-sanctum #stories > .story-card[data-kind="constitution"] { height: auto; min-height: var(--card-h); }
}
.page-sanctum #stories > .story-card[data-kind="constitution"] .decision { display: flex; flex-direction: column; }
.page-sanctum #stories > .story-card[data-kind="constitution"] .story-top { min-height: 0; }
/* The background sits at the foot of its pane. When an answer opens, the black
   pane grows and the grid makes both columns match, so anchoring it to the
   bottom puts the extra space between the title and the background, where it
   reads as composition, instead of leaving a hole under the last line. */
.page-sanctum #stories > .story-card[data-kind="constitution"] .story-top { display: flex; flex-direction: column; }
.page-sanctum #stories > .story-card[data-kind="constitution"] .context { margin-top: auto; padding-top: 28px; border-top: 0; }

/* The accordion label is a label, not the old uppercase micro-caption: that
   style belongs to the two-column context block this replaced. */
.page-sanctum .ctx-open > span { font-size: 15px; letter-spacing: 0; text-transform: none; color: inherit; }
.page-sanctum .ctx-panel > p { font-size: 15px; line-height: 1.6; color: #666; }

/* 6. The answer landing. The row of labels turns into the graph in place: the
      chosen one lights up, each one grows a bar of its share, and the numbers
      appear under the labels. Nothing moves and nothing scrolls, so a person
      sees their answer register without hunting for the confirmation. */
.page-sanctum .story-card.answered .choice-share { display: block; }
.page-sanctum .choice-insight { display: block; margin-top: 6px; font-size: 12px; line-height: 1.2; color: #cfd8e6; }
.page-sanctum .choice.selected .choice-insight { color: #fff; }
.page-sanctum .choice.selected { border-color: var(--bar-color); }
.page-sanctum .story-card.answered .choice:not(.selected) { opacity: .72; }
.page-sanctum .story-card.answered .choice-body { display: none; }

/* ------------------------------------------------------ the Sanctum hero

   What a first-time reader meets at sanctity.ai. It replaces the card of
   instructions that used to hold the first slot: a reader who is handed a page
   of instructions leaves before answering anything, and an answer is the one
   thing this site wants from them.

   It shows once. The first question scrolls up over it and it stays behind,
   so the reader moves from "what is this" to "here is a question" in one
   gesture and never meets the hero again on that visit. */

.sanctum-hero {
  /* A snap target of its own. The page snaps with `y mandatory`, so anything
     that is not a snap target is skipped over on load: without this line the
     browser rested on the first question and the hero was never seen, which is
     the whole reason it exists. */
  scroll-snap-align: start; scroll-snap-stop: always;
  scroll-margin-top: calc(var(--belt-top, 76px) + var(--belt-gap, 18px));
  /* Not sticky, and this is the second thing the snapping page has taken away.
     The meeting asked for the first card to rise over a hero that stays behind
     it. Built with `position: sticky`, that works going down and locks going
     up: the page snaps by `y mandatory`, a sticky element's snap position
     travels with it, and the browser then refuses to rest at the top at all.
     Measured: scrolling back to the top landed at 386px at 768, and at 560px
     at 1024 and 1440, so a reader who wanted to re-read what this site is
     could not get back to it. Only the phone, where the hero was already
     static, could return.

     A hero nobody can go back to is worse than a hero that does not slide, so
     the effect goes and the hero stays reachable. If the takeover matters more
     than going back, it needs a different mechanism than sticky. */
  z-index: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 28px; align-items: center;
  min-height: min(560px, calc(100dvh - var(--belt-top, 76px) - 120px));
  padding: 8px 4px 56px;
}
.sanctum-hero .eyebrow { font-size: 12px; letter-spacing: 1.6px; color: #6b6b6b; }
.sanctum-hero h1 { margin: 18px 0 0; font-size: clamp(34px, 4.2vw, 58px); line-height: 1.08; letter-spacing: -.3px; color: #191919; text-wrap: balance; }
.sanctum-hero-intro { margin: 20px 0 0; max-width: 46ch; font-size: 17px; line-height: 1.6; color: #575757; }
.sanctum-hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 22px; margin-top: 30px; }
.sanctum-hero-link { font-size: 15px; color: #2368c2; }
/* The drawing that replaced three post-it notes.

   The notes said three of the eight values on three coloured rectangles, and
   they were hidden below 950px, which is where most people are: on a phone the
   hero said nothing at all about what the eight Articles are. The plant says
   it at both sizes and says something the notes could not, which is that the
   named things are underneath and everything above the line stands on them.

   Colours, type and the wide/deep swap are in grown.css, because the same
   drawing set is used on three pages. */
.sanctum-hero .grown-roots { min-width: 0; }

/* The cards ride over it. Each carries its own background, so the hero is
   covered rather than showing through. */
.page-sanctum #stories { position: relative; z-index: 1; }
.page-sanctum #stories > .story-card { background: #fff; }

@media (max-width: 950px) {
  .sanctum-hero { grid-template-columns: 1fr; gap: 20px; min-height: 0; padding-bottom: 40px; }
}
@media (max-width: 700px) {
  .sanctum-hero { padding: 4px 0 28px; }
  .sanctum-hero h1 { font-size: clamp(30px, 8vw, 40px); }
  .sanctum-hero-intro { font-size: 16px; }
}

/* 7. The companion speaks inside the card, not over the page.

      It used to say the same congratulation after every one of the eight, in a
      bubble that floated above the page and landed on whatever was underneath,
      including the Share control. A first-time reader read it as boilerplate,
      and she was right. It now sits under the row, looks like the robot talking
      rather than like the site's own copy, and says what was recorded and how
      many Articles are left. */
.bot-line { display: flex; align-items: center; gap: 12px; margin: 0 0 18px; padding: 12px 14px; border: 1px solid #3f3f3f; border-radius: 12px; background: #232323; color: #e9e9e9; font-size: 14px; line-height: 1.45; }
.bot-mark { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px; background: #191919; }
.bot-mark img { display: block; width: 30px; height: 30px; object-fit: contain; }

/* Which pane a tab shows. Last in the file on purpose: these carry the same
   weight as the layout rules above, so whichever comes last wins, and what a
   tab says must beat what the layout would otherwise do. Written higher up,
   they lost, the tabs drew, and the tab said "Question" while the background
   sat under it. */
@media (max-width: 950px) {
  /* The Question tab keeps the card's name and its Article. Hiding the whole
     left pane took those with it, and a question with no title is not the
     self-sufficient face the card is supposed to have: it is the question
     alone, with nothing saying which of the eight it belongs to. Only the
     background folds away. */
  .page-sanctum #stories > .story-card[data-tab="decision"] .context { display: none; }
  .page-sanctum #stories > .story-card[data-tab="decision"] .story-top { padding-bottom: 18px; }
  .page-sanctum #stories > .story-card[data-tab="decision"] .story-title { margin-bottom: 0; }
  .page-sanctum #stories > .story-card[data-tab="story-top"] .decision { display: none; }

  /* On the Background tab the three sections are already the whole card, so
     folding them costs a row of chrome each to save nothing. Three closed
     accordion rows took about a hundred and fifty pixels of a phone screen to
     hold six lines of text. Open, labelled, no buttons. */
  .page-sanctum #stories > .story-card[data-tab="story-top"] .ctx-open { display: none; }
  .page-sanctum #stories > .story-card[data-tab="story-top"] .ctx-panel { display: block; padding: 0 0 18px; border-bottom: 0; }
  .page-sanctum #stories > .story-card[data-tab="story-top"] .ctx-panel::before {
    content: attr(data-label); display: block; margin-bottom: 6px;
    font-size: 13px; letter-spacing: .4px; color: #8a8a8a;
  }
  .page-sanctum #stories > .story-card[data-tab="story-top"] .context { border-top: 0; margin-top: 8px; }
}

/* The "Now" line on a Signal brief ran to 96 characters at tablet width, which
   is past the point where the eye loses the start of the next line. Capping the
   measure rather than the box keeps the card's width and shortens the line. */
.signal-brief .sg-brief-shift { max-width: 62ch; }

/* 8. The answer landing, made impossible to miss.

      A first-time reader tapped a position and could not tell anything had
      happened: the chosen tile gained a thin outline and three words of grey
      text, and everything else was below the fold on a phone. The tile now
      fills, carries a tick, and a line appears directly under the row saying
      the answer is recorded and what the numbers beside it are. All of it
      within a thumb's reach of where the tap landed, with nothing to scroll. */
.page-sanctum .story-card.answered .choice.selected {
  background: #f3f5ef; color: #1a1d18; border-color: #f3f5ef;
}
.page-sanctum .story-card.answered .choice.selected .choice-heading { color: #1a1d18; }
.page-sanctum .story-card.answered .choice.selected .choice-share { background: #d6dccb; }
.page-sanctum .choice-insight { display: flex; align-items: baseline; gap: 6px; margin-top: 8px; font-size: 13px; line-height: 1.2; color: #cfd8e6; }
.page-sanctum .choice-insight b { font-size: 17px; font-weight: 600; }
.page-sanctum .choice-insight em { font-style: normal; font-size: 12px; letter-spacing: .3px; color: #6a6f63; }
.page-sanctum .choice.selected .choice-insight { color: #1a1d18; }

.answer-landed {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 0 0; padding: 10px 12px;
  border-radius: 10px; background: #232a20; color: #dde6d4;
  font-size: 14px; line-height: 1.45;
  animation: arrive .35s ease;
}
.answer-landed .tick {
  flex: none; width: 20px; height: 20px; margin-top: 1px; border-radius: 50%;
  background: #cfe4ac; position: relative;
}
.answer-landed .tick::after {
  content: ""; position: absolute; left: 6px; top: 5px; width: 6px; height: 10px;
  border: solid #26301c; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
@media (prefers-reduced-motion: reduce) { .answer-landed { animation: none; } }

/* The old share wash. Before the row carried bars, each tile shaded itself
   left-to-right by its share. Now that every tile has an explicit bar and a
   number, the wash says the same thing a second time and muddies the tile a
   reader has just chosen. */
.page-sanctum .choices[data-row] .choice::before { display: none; }

/* A brief that fits the screen.

   Snapping only works if a card fits: a card taller than the window leaves its
   own foot unreachable, because the next snap point pulls the page past it.
   Measured at 390x844 the briefs ran from 554 to 986 pixels, four of the
   thirty-four taller than the screen.

   So the parts that vary are given a limit in lines. Nothing is lost: the whole
   report is one tap away on every card, which is what the brief is for. */
.signal-brief .story-title { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; line-clamp: 4; overflow: hidden; }
.signal-brief .bluf { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.signal-brief .sg-brief-shift { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
@media (max-width: 700px) {
  .signal-brief .story-title { -webkit-line-clamp: 3; line-clamp: 3; }
  .signal-brief .bluf { -webkit-line-clamp: 3; line-clamp: 3; }
}

/* Signal's hero borrows the Sanctum's, minus the paper notes. */
.signal-hero .sanctum-hero-copy { grid-column: 1 / -1; }
.signal-hero { grid-template-columns: 1fr; min-height: 0; padding-bottom: 40px; }
.signal-how { margin-top: 26px; padding: 22px 24px; border: 1px solid var(--line); border-radius: 14px; background: #fbfbfa; }
.signal-how .frame-steps { display: grid; gap: 18px; margin: 0; padding: 0; list-style: none; }
.signal-how .frame-steps li { display: grid; grid-template-columns: 30px 1fr; gap: 14px; }
.signal-how .frame-steps li > span { display: grid; place-items: center; width: 30px; height: 30px; border: 1px solid var(--line); border-radius: 50%; font-size: 13px; color: #555; }
/* These steps were written for the black pane, where their headings are light
   on dark. On this panel they were near-white on near-white. */
.signal-how .frame-steps b { display: block; margin-bottom: 4px; font-size: 16px; color: #191919; font-weight: 500; }
.signal-how .frame-steps li > span { color: #4a4a4a; background: #fff; }
.signal-how .frame-steps p { margin: 0; font-size: 14px; line-height: 1.5; color: #5d5d5d; max-width: 62ch; }
.signal-how-foot { margin: 18px 0 0; padding-top: 16px; border-top: 1px solid var(--line); font-size: 14px; color: #5d5d5d; }
/* A link inside a sentence has to be findable by something other than its
   colour: this blue against the grey around it is 1.2:1, which a reader who
   does not see colour the usual way cannot pick out at all. */
.signal-how-foot a { color: #2368c2; text-decoration: underline; text-underline-offset: 3px; }
button.sanctum-hero-link { background: transparent; border: 0; padding: 0; font: inherit; color: #2368c2; cursor: pointer; text-align: left; }

/* ------------------------------------------------------------ Signal's rail

   Signal used to borrow the Sanctum's rail: the eight Articles' progress
   dots, the Constitution's contribution totals and a Lab teaser, on a page
   about none of those. A reader on Signal was shown how far through a
   different product they were.

   The line under the heading is the one that earns its place. "How the world
   moved this week" reads like a news digest, and the whole claim of Signal is
   that it is not one. */

.rail-what { margin-top: 12px; font-size: 13px; line-height: 1.55; color: #5c615b; }
.rail-block { padding: 18px 0; border-top: 1px solid var(--line); }
.rail-block .eyebrow { display: block; font-size: 10px; letter-spacing: 1.5px; color: #6c706b; }
.rail-figure { display: block; margin: 8px 0 6px; font-size: 22px; font-weight: 500; letter-spacing: -.01em; color: #191919; }
.rail-block small { display: block; margin-top: 8px; font-size: 12px; line-height: 1.5; color: #6d726d; }
.rail-block .dots-progress { display: flex; gap: 3px; }
.rail-block .dots-progress i { flex: 1; height: 4px; max-width: 14px; border-radius: 2px; background: #dcdcd8; }
.rail-block .dots-progress i.done { background: #438ff4; }
.rail-watch p { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: #35382f; }
.rail-watch a { color: #246ac5; }

/* ---------------------------------------------- the values card, rebalanced

   MC's list, 22 September: the same Article named four times on one card, half
   the card spent on three folded rows that each opened to one sentence, four
   positions crammed into tall thin slabs, too much white and not enough black,
   and a gap between cards that made the deck look unfinished.

   The identity is said once now, as a link, and the foot that repeated it is
   gone. The background is simply written out, because three controls and three
   taps to read fifteen words is not a saving. The positions are a two by two
   matrix instead of four columns, so a heading gets a line and its sentence
   gets two rather than six. And the dark side takes more of the card, because
   the dark side is where the reading and the answering both happen. */

@media (min-width: 951px) {
  .page-sanctum #stories > .story-card[data-kind="constitution"] { grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr); }
}

.page-sanctum .story-card[data-kind="constitution"] .meta { align-items: baseline; gap: 12px; }
.story-article { font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: #6a6e67; }
.story-article:hover { color: #191919; text-decoration: underline; text-underline-offset: 3px; }

/* The background, open. */
.page-sanctum .context { display: grid; gap: 18px; margin-top: 26px; }
.page-sanctum .ctx-block h3 { margin: 0 0 6px; font-size: 11.5px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: #6a6e67; }
.page-sanctum .ctx-block p { margin: 0; font-size: 14px; line-height: 1.6; color: #4b4f4a; }
.page-sanctum .ctx-block dl { margin: 0; display: grid; gap: 8px; }
.page-sanctum .ctx-block dt { font-size: 13px; color: #191919; }
.page-sanctum .ctx-block dd { margin: 2px 0 0; font-size: 13px; line-height: 1.55; color: #5c605a; }

/* Two by two. Four columns gave each heading a word per line and each sentence
   six lines; two columns give the heading a line and the sentence two. */
.page-sanctum .choices[data-row] { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.page-sanctum .choices[data-row] .choice { min-height: 104px; padding: 15px 16px 14px; }
.page-sanctum .choice-heading { font-size: 15px; }
.page-sanctum .choice-body { font-size: 12.5px; line-height: 1.45; }
@media (max-width: 1150px) { .page-sanctum .choices[data-row] { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* The snap is back.
   
   It was taken out when a card was 580px of content in a 900px window and the
   nearest snap point was still the card you were on, so a small scroll undid
   itself. The gap is measured now and the distance from one card to the next
   is exactly one screen, so proximity has a real target to settle on and
   nothing to drag a reader backwards to.

   And on a screen with a real pointer, snapping hands over entirely. It picks
   the nearest point, so with the points a screen apart a wheel notch was
   nearer to where it started and the page did not move: zero pixels for a 120
   pixel gesture, zero for 250. sanctum.js reads the gesture instead and moves
   one card per gesture, which is the thing that was asked for and the thing
   snapping cannot be configured into. Leaving snap on underneath would only
   fight it. The phone keeps it: there a card is often taller than the screen,
   the scroll is a finger, and settling on an edge still earns its place. */
@media (min-width: 951px) and (pointer: fine) {
  html:has(body.page-sanctum[data-mode="belt"]) { scroll-snap-type: none; }
}

/* The card is set on the page, not stretched to it.

   The background runs under the Article's line at a fixed distance rather than
   being dropped at the foot of the column, so the white pane is a block of
   type and not a title with a field under it. */
/* Written with #stories because the rules these replace are, and an id beats
   three classes however far down the file the newer rule sits. That exact
   mistake has been made here three times. */
@media (min-width: 951px) {
  /* The dark pane, set to the card. The question leads, the positions are
     panels under it, the hint sits at the foot. Every size is drawn from the
     height of the window as well as its width, so the card grows into a tall
     screen instead of opening a hole in one. */
  .page-sanctum #stories > .story-card[data-kind="constitution"] .decision { gap: 0; }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .decision h3 {
    margin: clamp(16px, 2.2vh, 30px) 0 0;
    font-size: clamp(27px, 1.5vw + 1.5vh, 44px); line-height: 1.16; letter-spacing: -.015em;
  }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .choice-ends { margin: clamp(16px, 2.4vh, 32px) 0 clamp(10px, 1.4vh, 18px); }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .choices[data-row] { gap: clamp(10px, 1.3vh, 16px); }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .choices[data-row] .choice {
    min-height: clamp(104px, 17.5vh, 200px);
    padding: clamp(15px, 2vh, 24px) clamp(16px, 1.4vw, 24px);
  }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .choice-heading { font-size: clamp(15px, .5vw + .9vh, 20px); }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .choice-body { font-size: clamp(12.5px, .35vw + .7vh, 15px); }
  /* A position is a panel, so its two lines sit on the middle of it rather
     than clinging to the top edge of an otherwise empty box. */
  .page-sanctum #stories > .story-card[data-kind="constitution"] .choices[data-row] .choice {
    display: flex; flex-direction: column; justify-content: center;
  }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .choice-extras { margin-top: clamp(10px, 1.4vh, 18px); }
  /* The hint follows the positions. Pinning it to the foot of the pane put a
     hundred and fifty pixels of black between the two, which is the hole this
     whole rebuild is about. What is left over is a margin at the bottom of the
     card, where a margin belongs. */
  .page-sanctum #stories > .story-card[data-kind="constitution"] .guide { margin-top: clamp(16px, 2.4vh, 30px); margin-bottom: 0; }

  /* The white pane. The background follows the Article's line rather than
     being dropped at the foot of the column, which left four hundred pixels of
     white between the two. */
  .page-sanctum #stories > .story-card[data-kind="constitution"] .context { margin-top: clamp(26px, 3.4vh, 46px); gap: clamp(16px, 2.2vh, 30px); }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .ctx-block p,
  .page-sanctum #stories > .story-card[data-kind="constitution"] .ctx-block dd { font-size: clamp(14px, .3vw + .65vh, 16px); }
  .page-sanctum #stories > .story-card[data-kind="constitution"] .story-title { font-size: clamp(28px, 1.3vw + 1.4vh, 44px); }
}

/* The rail's title is not the page's title.
   
   Both belt pages had two h1 elements: the hero's and the rail's. A page has
   one main heading, and a screen reader lists both as though the page were two
   pages. The rail's is an h2 now, sized as the h1 was. The Signal rail has no
   title at all any more, because the one it had repeated the hero's. */
.rail-intro .rail-title { font-size: 32px; line-height: 1.18; letter-spacing: .2px; margin: 19px 0; font-weight: 500; }
@media (max-width: 1150px) { .rail-intro .rail-title { font-size: 28px; } }
@media (max-width: 950px) { .rail-intro .rail-title { font-size: 25px; } }
@media (max-width: 700px) { .rail-intro .rail-title { font-size: 32px; } }
.page-signal .rail-intro .rail-what { margin-top: 12px; font-size: 15px; line-height: 1.6; color: #4f544e; }

/* ==================================================================
   An answer lands in one line, and the card does not grow
   ==================================================================

   MC, 23 September: answering added "Recorded. Shares appear once 20 people
   have answered." and "Recorded: Article II at "It warns you". 3 Articles
   left." under the row, and a block of reasons, buttons and a Next row under
   that, so the card grew and had to be scrolled. Feedback, he said, without so
   many words and without the card growing.

   The hint line under the row becomes the confirmation, in the same place and
   at the same height: a tick, "Recorded. 3 to go.", and two small controls.
   The reasons, share and sign open over the dark pane, not under it. */
.page-sanctum .story-card[data-kind="constitution"] .guide.answer-landed {
  display: flex; align-items: center; gap: 10px; flex-wrap: nowrap;
  margin-left: 0; margin-right: 0; padding: 0; border-radius: 0; background: none;
  font-size: 14px; line-height: 1.4; color: #dde6d4;
}
.page-sanctum .story-card[data-kind="constitution"] .guide.answer-landed .tick { width: 18px; height: 18px; margin-top: 0; }
.page-sanctum .story-card[data-kind="constitution"] .guide.answer-landed .tick::after { left: 6px; top: 4px; width: 5px; height: 9px; }
.landed-words { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.landed-words b { font-weight: 500; color: #fff; }
.landed-actions { display: flex; gap: 6px; margin-left: auto; flex: none; }
.landed-actions button {
  padding: 5px 12px; border: 1px solid #4a4f47; border-radius: 999px; background: transparent;
  color: #e9ece6; font-size: 13px; line-height: 1.3; cursor: pointer;
}
.landed-actions button:hover, .landed-actions button:focus-visible { border-color: #cfe4ac; color: #fff; }
@media (max-width: 700px) {
  .landed-actions button { min-height: 44px; padding: 0 14px; }
}

/* The panel that used to push the card down now sits over the dark pane. */
.page-sanctum .story-card[data-kind="constitution"] .decision { position: relative; }
.page-sanctum .story-card[data-kind="constitution"] .insights.insights-over {
  position: absolute; inset: 0; z-index: 3; margin: 0; padding: clamp(20px, 2.4vw, 32px);
  border-top: 0; background: #191919; overflow-y: auto; overscroll-behavior: contain;
  animation: arrive .25s ease;
}
.insights-over .over-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 4px; font-size: 14px; color: #dde6d4; }
.insights-over .over-done { padding: 6px 14px; border: 1px solid #5a5f57; border-radius: 999px; background: transparent; color: #fff; font-size: 13px; cursor: pointer; }
@media (max-width: 700px) { .insights-over .over-done { min-height: 44px; } }
@media (prefers-reduced-motion: reduce) { .insights-over { animation: none; } }
