/* Split header: headline left, the steps photo right, baseline-locked per
   docs/design/photo-language.md. The grid, the align-items:end baseline lock and the
   1440px tightening all come from the shared .frame-split component; this file only
   carries the story-specific spacing and the near-miss clearance on the headline, plus
   the story's own stack point (700px, tighter than the shared 900px default). */
.story-head.frame-split {
  padding: 76px 0 56px;
}
.story-head-copy {
  max-width: 640px;
}
.story-head-copy h1 {
  font-size: clamp(2.75rem, 4.4vw, 4rem);
  max-width: 624px;
}

/* The conversation reads best at a measure narrower than the full 1248px wrap, per
   docs/design/astra-recommendations.md section 3 ("a readable measure"); .conversation's
   own card padding and type sizes are unchanged. */
.story-conversation-wrap {
  max-width: 720px;
  margin: 64px auto 0;
}
.story-conversation-wrap + .note {
  max-width: 720px;
  margin: 24px auto 0;
}
.note-action {
  margin-top: 14px;
}
/* The next action after the payoff. .note p paints its children muted, which left this link the
   exact same gray as the sentence above it and, with .text-link carrying no underline until hover,
   nothing at all marked it as a link. It takes the accent color the page's other inline links use. */
.note .note-action a {
  color: var(--accent);
}
.story-conversation-wrap .example-disclosure {
  margin: 20px 4px 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
}

/* ---------------------------------------------------------------------------------------------
   The convergence. This is the page's one authored moment: the beat where the answer visibly
   decomposes into the four sources it came from. Everything else on this page is deliberately quiet
   so this lands.

   It inverts to charcoal and bleeds to the edges of the conversation card. Dark with an orange
   thread is the site's established second mode, not a new visual language: .benefit-band is already
   background:var(--ink) with paper text, and --charcoal-scrim carries the mobile menu takeover and
   the photo overlays. Inverting exactly here, and nowhere else on the page, is what makes it the
   focal point rather than one more decorated block.

   Only opacity, transform and stroke-dashoffset animate, so nothing triggers layout and there is no
   CLS: every box is laid out at full size from first paint. The sequence is staged rather than
   simultaneous, and each individual transition stays inside the --dur-focal ceiling
   docs/design/motion.md sets.
   --------------------------------------------------------------------------------------------- */
.converge {
  --bleed: 40px;
  margin: 34px calc(var(--bleed) * -1) 10px;
  padding: 38px var(--bleed) 40px;
  background: var(--charcoal-scrim);
  color: var(--paper);
}
.message.assistant .converge-eyebrow {
  margin: 0 0 22px;
  font-size: 11px;
  line-height: 1.5;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

/* The four real tags, in a four-column grid so each column center is exactly 12.5%, 37.5%, 62.5%
   and 87.5% of the row, which is where the four threads below start. Monospace, because these are
   the literal contents of a stored field rather than prose, and nowrap so the longest tag can never
   break the row's rhythm by wrapping to a second line. */
.source-tags {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.source-tag {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 0;
  min-height: 44px;
  padding: 8px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 9px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  letter-spacing: -0.02em;
  white-space: nowrap;
  color: var(--paper);
}
/* The shipped tool marks are dark artwork made for a light page, so on charcoal they would vanish.
   Rendering all four icons as one white silhouette is both legible and more consistent than mixing
   a colored mark with a stroke icon; the mail icon already follows currentColor. */
.source-tag img {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: 0.85;
}
.source-tag .icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  opacity: 0.85;
}

/* The draw. The glow is a static paint filter, never animated, so it costs nothing per frame and
   gives the thread real presence on dark instead of reading as a hairline diagram. */
.converge svg {
  display: block;
  width: 100%;
  overflow: visible;
}
.converge path {
  fill: none;
  stroke: var(--orange);
  stroke-width: 2;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  filter: drop-shadow(0 0 5px rgba(253, 84, 10, 0.5));
}
.converge circle {
  fill: var(--orange);
  filter: drop-shadow(0 0 7px rgba(253, 84, 10, 0.7));
}
.converge-wide {
  height: 150px;
}
.converge-rail {
  display: none;
}

/* The threads have to land somewhere. The payoff sits directly under the convergence point so the
   graphic reads as one sentence: four sources, one node, one store. */
.message.assistant .converge-answer {
  margin: 2px 0 0;
  text-align: center;
  font-family: 'Sora', 'DM Sans', sans-serif;
  font-size: clamp(1.6rem, 3vw, 2.35rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--paper);
}
.converge-answer span {
  display: block;
  margin-top: 10px;
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.6);
}

/* Armed state. assets/experience.js adds converge-armed on load and converge-in-view on first
   intersection, the same shared observer every other thread on this site uses, so this needs no new
   JavaScript. Without JavaScript neither class is ever added, so the resting rules above apply and
   the panel renders complete and fully drawn. Under prefers-reduced-motion the observer is never
   constructed and the armed class is never added either, so this whole block is inert: the page is
   genuinely calm, and still looks finished rather than unstyled.

   The armed rules below carry NO transition, deliberately. Declaring the transition on the armed
   state instead means the pre-animation state is itself animated into when the class lands at load:
   an rAF timeline of an earlier revision showed the thread erasing itself backwards from 0 to 100
   before it ever came into view, and arriving mid-erase, so the draw was never actually seen. The
   transitions therefore live only on the in-view rules, and can only ever play forward.

   The order is authored, not uniform. Tags settle first, left to right on a 90ms step with a slight
   overshoot so they arrive with weight. The four threads then draw on an 80ms step, so the eye
   follows them inward rather than seeing four lines appear at once. The node and the payoff land
   last, together, as the threads meet. */
.converge.converge-armed .source-tag {
  opacity: 0;
  transform: translateY(10px) scale(0.97);
}
.converge.converge-armed path {
  stroke-dashoffset: 100;
}
.converge.converge-armed circle {
  opacity: 0;
  transform: scale(0.3);
  transform-origin: center;
  transform-box: fill-box;
}
.converge.converge-armed .converge-answer {
  opacity: 0;
  transform: translateY(8px);
}

.converge.converge-armed.converge-in-view .source-tag {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-layout) var(--ease),
    transform var(--dur-layout) cubic-bezier(0.34, 1.45, 0.64, 1);
  transition-delay: calc(90ms * var(--i, 0));
}
.converge.converge-armed.converge-in-view path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--dur-focal) var(--ease);
  transition-delay: calc(430ms + 80ms * var(--i, 0));
}
.converge.converge-armed.converge-in-view circle {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-state) var(--ease),
    transform var(--dur-state) cubic-bezier(0.34, 1.6, 0.64, 1);
  transition-delay: 1160ms;
}
.converge.converge-armed.converge-in-view .converge-answer {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-layout) var(--ease),
    transform var(--dur-layout) var(--ease);
  transition-delay: 1240ms;
}

/* Each claim beside the one source tag the assistant attributed it to. The tag repeats the exact
   string from the store, so a reader can match it against the four above without being told to. */
.claim-list {
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}
.claim {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  padding: 13px 0;
  border-top: 1px solid var(--line);
}
.message.assistant .claim p {
  margin: 0;
  flex: 1 1 16ch;
  font-size: 17px;
  line-height: 1.55;
}
.claim-tag {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  color: var(--accent);
  padding: 4px 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  white-space: nowrap;
  margin-left: auto;
}
.message.assistant .answer-closer {
  margin: 24px 0 0;
  font-size: 19px;
  line-height: 1.6;
  font-weight: 500;
  color: var(--ink);
}

/* Native summary controls need their own icon size; the shared sizing rule only
   covers links and buttons. State changes are instant, including reduced motion. */
.story-conversation-wrap .story-step {
  min-height: 44px;
}
.story-conversation-wrap .story-step > .icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  transform: rotate(90deg);
}
.story-conversation-wrap details[open] > .story-step > .icon {
  transform: rotate(-90deg);
}

@media (max-width: 900px) {
  .converge {
    --bleed: 28px;
  }
  .story-head.frame-split {
    grid-template-columns: 1.1fr 1fr;
    align-items: end;
    gap: 36px;
  }
  .story-head-copy h1 {
    font-size: clamp(2.1rem, 4vw, 2.3rem);
  }
}

@media (max-width: 700px) {
  .story-head.frame-split {
    grid-template-columns: 1fr;
    align-items: start;
    gap: 24px;
    padding: 56px 0 32px;
  }
  .story-head-copy {
    max-width: none;
  }
  .story-head-copy h1 {
    max-width: none;
  }
  .story-conversation-wrap {
    margin-top: 40px;
  }
  /* Narrow screens get their own composition, not a squeezed copy of the wide one: the tags become
     a single column and the thread runs down beside them, threading through all four before it
     reaches the answer. Same mechanism, same tokens, deliberately different shape. */
  .converge {
    --bleed: 22px;
    padding: 30px var(--bleed) 34px;
  }
  .converge-body {
    position: relative;
    padding-left: 30px;
  }
  .converge-rail {
    display: block;
    position: absolute;
    left: 4px;
    top: 0;
    bottom: 0;
    width: 12px;
  }
  .converge-rail svg {
    height: 100%;
  }
  .source-tags {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .source-tag {
    position: relative;
    justify-content: flex-start;
    font-size: 13px;
  }
  /* The dot sits on the rail at each tag's own vertical center, so it stays aligned whatever the
     tag's height ends up being. No magic percentages to drift out of sync with the text. */
  .source-tag::before {
    content: '';
    position: absolute;
    left: -24px;
    top: 50%;
    width: 9px;
    height: 9px;
    margin-top: -4.5px;
    border-radius: 50%;
    background: var(--orange);
    box-shadow: 0 0 7px rgba(253, 84, 10, 0.7);
  }
  .converge-rail {
    /* The rail carries on past the last tag and ends on the payoff, so the narrow composition
       finishes the same sentence the wide one does: four sources, one node, one store. */
    bottom: -36px;
  }
  .converge-draw {
    display: none;
  }
  .message.assistant .converge-answer {
    position: relative;
    margin-top: 22px;
    padding-left: 30px;
    text-align: left;
  }
  .message.assistant .converge-answer::before {
    content: '';
    position: absolute;
    left: 4px;
    top: 11px;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--orange);
    box-shadow: 0 0 9px rgba(253, 84, 10, 0.75);
  }
  .message.assistant .claim p {
    font-size: 16px;
  }
  .message.assistant .answer-closer {
    font-size: 17px;
  }
}
