/*
 * Thought map — the objects, their connections, the guide and the traveler.
 *
 * Shared by the lab and by production. Nothing here knows which surface is
 * showing it: the container is named by the page, and the only hook this
 * stylesheet needs from it is .thought-map, plus .is-found when a map has
 * converged and .is-reduce when motion is off.
 */

/*
 * The five tones, defined once.
 *
 * A sphere is drawn at two sizes now -- full size on an open map, 16px in the
 * collapsed strip -- and the collapsed one has to be recognisably the same
 * object, so both read the fill from here. Writing the gradients twice would
 * have let the two drift apart, and a strip whose colours disagree with the
 * map is worse than no strip.
 */
:root {
  --sphere-gold: radial-gradient(circle at 34% 30%, #fffaf0 0%, #f3dcab 28%, #d4b06a 70%, #c49a4e 100%);
  --sphere-lavender: radial-gradient(circle at 34% 30%, #faf5ff 0%, #ccbae8 30%, #8f6fbe 74%, #6d5a96 100%);
  --sphere-sage: radial-gradient(circle at 34% 30%, #f4faf8 0%, #c3ded7 30%, #7fa9a0 74%, #648b83 100%);
  --sphere-cool: radial-gradient(circle at 34% 30%, #f2f6fd 0%, #b9caea 30%, #7089c4 74%, #5a6fa8 100%);
  --sphere-rose: radial-gradient(circle at 34% 30%, #fff6f6 0%, #f2c9cf 30%, #d590a0 74%, #c07a8e 100%);
}

* { box-sizing: border-box; }

.portrait {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: 30px;
  background:
    radial-gradient(88% 78% at 6% 0%, rgba(255, 226, 164, 0.58), transparent 56%),
    radial-gradient(78% 68% at 100% 10%, rgba(186, 160, 220, 0.42), transparent 58%),
    radial-gradient(70% 48% at 50% 100%, rgba(255, 248, 236, 0.5), transparent 62%),
    linear-gradient(180deg, rgba(255, 250, 242, 0.97), rgba(247, 239, 228, 0.94));
  box-shadow:
    0 18px 44px rgba(90, 68, 48, 0.07),
    0 0 0 1px rgba(255, 255, 255, 0.82) inset,
    0 0 64px rgba(240, 215, 168, 0.28);
}

.map-space {
  position: absolute;
  inset: 0;
}

.field {
  position: absolute;
  inset: 48px 16px 64px;
  z-index: 0;
  border-radius: 48%;
  background: radial-gradient(circle at 50% 46%, rgba(255, 248, 236, 0.55), transparent 68%);
  filter: blur(8px);
  pointer-events: none;
}

.warmth {
  position: absolute;
  z-index: 1;
  width: 140px;
  height: 140px;
  margin: -70px 0 0 -70px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(240, 215, 168, 0.46), rgba(196, 178, 226, 0.12) 46%, transparent 72%);
  filter: blur(16px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 280ms ease;
}

.unknown-field {
  position: absolute;
  z-index: 1;
  width: 150px;
  height: 150px;
  margin: -40px 0 0 -40px;
  border-radius: 50%;
  background: radial-gradient(circle at 52% 42%, rgba(196, 178, 226, 0.2), rgba(244, 238, 230, 0.02) 58%, transparent 74%);
  filter: blur(18px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 700ms ease;
}

.world {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/*
 * Relationships are drawn behind the thoughts, not beside them.
 *
 * They were nearly as loud as the spheres, so a map with a hub and a line
 * running back across it read as tangle first and thoughts second. Thinner and
 * softer, they still say what connects to what while the objects and their
 * labels stay the thing being looked at. Crossings are much rarer now that
 * rows reorder to avoid them, and the ones that remain are quieter.
 */
.conn {
  fill: none;
  stroke: url(#map-link);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  /* No opacity here: applyClock sets it inline every frame, so a value in this
   * rule is overwritten before it is ever seen. It lives in render.js. */
}

.conn.is-loop { stroke-width: 1.4; }
/*
 * Every relationship is drawn the same way.
 *
 * The "open" kind used to draw a fine dashed line, which put four line styles
 * on one map -- two dashed, two solid -- and read as something half-rendered
 * rather than as a distinction. A relationship either exists on this map or it
 * does not, and it exists.
 *
 * What is lost: "open" meant the model was not certain the link holds. That
 * distinction was worth almost nothing to look at and it survives in the claim
 * record, where anything that wants it can read it. What it cost on screen was
 * a map that looked broken.
 */
.conn.is-open {
  stroke: rgba(139, 122, 168, 0.5);
  stroke-width: 1.25;
}

.thought-map.is-found .conn.is-loop,
.thought-map.is-found .conn.is-link {
  stroke-width: 2.05;
}

/*
 * Convergence: what carried the discovery gets weight, what stayed unresolved
 * recedes without disappearing, and the sentence at the top is what the eye
 * should land on. Colour and weight only -- no camera move, so reduced motion
 * gets the same composition standing still.
 */
.thought-map.is-found .conn.is-open {
  opacity: 0.42;
}

.thought-map.is-found .thought:not(.is-unresolved) .sphere {
  filter: saturate(1.06);
}

.thought-map.is-found .thought.is-unresolved {
  opacity: 0.76;
}


.thought-map.is-found .conn,
.thought-map.is-found .thought {
  transition:
    opacity 520ms ease,
    stroke-width 520ms ease,
    filter 520ms ease;
}

.is-reduce .thought-map.is-found .conn,
.is-reduce .thought-map.is-found .thought {
  transition: none;
}

.beads {
  fill: none;
  stroke: rgba(255, 248, 234, 0.0);
  stroke-width: 0;
  pointer-events: none;
}

/*
 * The guide's motion path. Never painted; it exists to be measured and
 * sampled with getPointAtLength.
 */
.travel-path {
  fill: none;
  stroke: none;
  pointer-events: none;
}

/*
 * The traveler is a point of light, not the character. It carries a
 * connection's meaning from one thought to the other and then it is gone.
 * Hidden by default: applyClock is the only thing that raises its opacity, so
 * a static render and reduced motion both show a settled line and no light.
 */
.traveler {
  opacity: 0;
}

.traveler-halo {
  fill: rgba(240, 215, 168, 0.42);
}

.traveler-core {
  fill: #fff8ea;
}

.traveler-tail {
  fill: rgba(196, 178, 226, 0.85);
}

.thought {
  position: absolute;
  z-index: 3;
  /* Set by the layout from the column pitch. The fallback is the old constant,
   * for anything that renders a map without one. */
  width: var(--thought-w, 122px);
  margin-left: calc(var(--thought-w, 122px) / -2);
  text-align: center;
  transform: translate(-0%, 0);
  opacity: var(--appear, 1);
  pointer-events: none;
}

.thought .name {
  display: block;
  color: var(--ink);
  font-size: 0.78rem;
  font-weight: 500;
  line-height: 1.22;
  opacity: 0;
}

.thought.is-labeled .name { opacity: 1; }

.thought.is-remembered {
  filter: saturate(0.86);
}

.thought.is-remembered .sphere {
  transform: scale(0.92);
}

.thought.is-newest .sphere {
  transform: scale(1.04);
}

.sphere {
  display: block;
  position: relative;
  width: 44px;
  height: 44px;
  margin: 0 auto 7px;
  border-radius: 50%;
  transform-origin: 50% 50%;
}

.thought.is-gold .sphere {
  background: var(--sphere-gold);
  box-shadow:
    0 0 16px 5px rgba(240, 215, 168, 0.48),
    0 0 36px 10px rgba(223, 192, 137, 0.22),
    inset 0 -8px 14px rgba(160, 110, 40, 0.1);
}

.thought.is-lavender .sphere {
  background: var(--sphere-lavender);
  box-shadow:
    0 0 16px 5px rgba(196, 178, 226, 0.44),
    0 0 36px 12px rgba(143, 111, 190, 0.22),
    inset 0 -8px 14px rgba(70, 50, 110, 0.14);
}

/*
 * Shades within a tone.
 *
 * Tone says what kind of thought this is; the shade only separates two of the
 * same kind so the map never shows one idea apparently drawn twice. Kept small
 * on purpose -- far enough apart to tell two spheres from each other, close
 * enough that they still read as the same family.
 */
/* Context: the situation a thought sits in. Quieter than the three feeling
 * tones on purpose, and drawn from the connection mark's middle stop. */
.thought.is-sage .sphere {
  background: var(--sphere-sage);
  box-shadow:
    0 0 16px 5px rgba(183, 207, 201, 0.42),
    0 0 36px 12px rgba(127, 169, 160, 0.2),
    inset 0 -8px 14px rgba(40, 80, 72, 0.12);
}

/* The fifth tone. Cooler and bluer than lavender so the two never read as
 * the same colour side by side. */
.thought.is-cool .sphere {
  background: var(--sphere-cool);
  box-shadow:
    0 0 16px 5px rgba(160, 185, 230, 0.42),
    0 0 36px 12px rgba(112, 137, 196, 0.2),
    inset 0 -8px 14px rgba(36, 52, 96, 0.12);
}

/*
 * Not settled yet. A dashed halo around a sphere that is otherwise as solid as
 * any other, because the previous treatment -- a near-transparent ring instead
 * of a sphere -- left the object reading as an empty slot with a label under
 * it. Unsettled is a state of a thought, not the absence of one.
 */
.thought .sphere.is-possible {
  box-shadow:
    0 0 0 2px rgba(255, 252, 247, 0.9),
    0 0 0 3.5px rgba(143, 111, 190, 0.34),
    0 0 18px 6px rgba(196, 178, 226, 0.3);
}

.thought .sphere.is-possible::after {
  position: absolute;
  inset: -7px;
  border: 1.7px dashed rgba(143, 111, 190, 0.72);
  border-radius: 50%;
  content: "";
}

/*
 * What is still open, made a little easier to find.
 *
 * The old Finding card carried "Not yet known" as one of its two orbs, and
 * that job does not disappear because the map replaced the card: preserving
 * unresolved uncertainty is a rule in its own right. The map already draws it
 * as a dashed halo, so this raises that halo rather than adding a second
 * signal, and stops the name reading lighter than its neighbours.
 *
 * Deliberately small. An unresolved thought competing with the map would make
 * the open question the subject of every turn, which is the pull the two-orb
 * card was being moved away from.
 */
.thought.is-unresolved .sphere.is-possible {
  box-shadow:
    0 0 0 2px rgba(255, 252, 247, 0.9),
    0 0 0 3.5px rgba(143, 111, 190, 0.46),
    0 0 20px 7px rgba(196, 178, 226, 0.38);
}

.thought.is-gravity .sphere {
  width: 58px;
  height: 58px;
  box-shadow:
    0 0 22px 8px rgba(240, 215, 168, 0.55),
    0 0 48px 16px rgba(223, 192, 137, 0.28),
    inset 0 -8px 14px rgba(160, 110, 40, 0.1);
}

.thought.is-forming .sphere {
  animation: form-bloom 900ms ease both;
}

.possibility {
  display: block;
  position: relative;
  width: 62px;
  height: 62px;
  margin: 0 auto 8px;
}

.possibility-haze {
  position: absolute;
  inset: 12px;
  border-radius: 50%;
  background: radial-gradient(circle at 42% 36%, rgba(250, 245, 255, 0.2) 0%, rgba(196, 178, 226, 0.1) 46%, transparent 76%);
  filter: blur(5px);
}

.possibility-rim {
  position: absolute;
  inset: 1px;
  border-radius: 50%;
  background: conic-gradient(
    from 198deg,
    rgba(186, 160, 220, 0) 0deg,
    rgba(201, 184, 226, 0.62) 32deg,
    rgba(186, 160, 220, 0.22) 86deg,
    rgba(186, 160, 220, 0) 128deg,
    rgba(186, 160, 220, 0) 232deg,
    rgba(196, 178, 226, 0.42) 278deg,
    rgba(186, 160, 220, 0) 328deg
  );
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 1.55px), #000 calc(100% - 1.35px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 1.55px), #000 calc(100% - 1.35px));
}

.thought.is-unresolved .name {
  color: #5d5468;
  font-weight: 450;
}

.clarity-glint {
  position: absolute;
  z-index: 6;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  background: #fff8ea;
  opacity: 0;
  clip-path: polygon(50% 0, 61% 38%, 100% 50%, 61% 62%, 50% 100%, 39% 62%, 0 50%, 39% 38%);
  filter: drop-shadow(0 0 10px rgba(255, 248, 234, 1)) drop-shadow(0 0 16px rgba(240, 215, 168, 1));
  pointer-events: none;
}

.clarity-glint.is-on {
  animation: clarity-glint 420ms ease 1 both;
}

.guide {
  position: absolute;
  /*
   * Below .thought (3) and above the connections. Avoidance should keep the
   * guide off every label, but if it ever cannot, the thought is what stays
   * visible. The character is not the protagonist.
   */
  z-index: 2;
  left: 0;
  top: 0;
  /* Width is set inline by guideWidthFor. This is only a floor for a first
   * paint before the clock runs. */
  width: 52px;
  /*
   * Anchor the sprite's feet on the slot rather than its box corner: half its
   * width left, most of its height up. Percentages so they track the inline
   * width instead of pinning to the old 58px.
   */
  margin: 0;
  translate: -50% -86%;
  transform: translate(-999px, -999px);
  pointer-events: none;
  will-change: transform;
}

.guide-scale {
  width: 100%;
  transform-origin: 50% 80%;
}

.guide-bob {
  position: relative;
}

.guide-glow {
  position: absolute;
  left: 50%;
  bottom: 6%;
  z-index: 0;
  width: 72%;
  height: 18%;
  margin-left: -36%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(196, 178, 226, 0.45), rgba(240, 215, 168, 0.18) 46%, transparent 72%);
  filter: blur(3px);
  pointer-events: none;
}

.guide-sprite {
  display: block;
  position: relative;
  z-index: 1;
  width: 100%;
  /*
   * The sprites are square, and saying so keeps the guide's box from
   * collapsing to zero height between innerHTML replacing the <img> and the
   * decode finishing. Measured at 0px on the frame after every step, which
   * also made the panel-offset measurement taken in that frame wrong.
   */
  aspect-ratio: 1;
  height: auto;
  filter: drop-shadow(0 8px 12px rgba(90, 70, 48, 0.12));
}

.guide-sprite.is-walk { display: none; }

.guide[data-pose="travel"] .guide-sprite.is-idle { display: none; }
.guide[data-pose="travel"] .guide-sprite.is-walk { display: block; }

.guide.is-flip .guide-scale { transform: scaleX(-1); }

.guide[data-pose="idle"] .guide-bob {
  animation: guide-breathe 6.8s ease-in-out infinite;
}

.guide[data-pose="idle"] .guide-glow {
  animation: cape-glow 7.4s ease-in-out infinite;
}

.guide[data-pose="notice"] .guide-lean {
  transform-origin: 50% 70%;
  animation: head-notice 700ms ease both;
}

.guide[data-pose="travel"] .guide-bob {
  animation: guide-glide 1.15s ease-in-out infinite;
}

.guide.is-look .guide-lean {
  transform-origin: 50% 70%;
  transform: rotate(6deg);
}

/*
 * Reduced motion: the guide is present and still.
 *
 * The class lands on the lab root that applyClock is handed, not on <html> and
 * not on .lab-shell -- the pass-one rules here named both and matched neither,
 * which went unnoticed because the guide was display:none at the time. A plain
 * descendant selector matches wherever the class sits.
 */
.is-reduce .guide,
.is-reduce .guide * {
  animation: none !important;
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .guide-bob,
  .guide-lean,
  .guide-glow,
  .thought.is-forming .sphere,
  .clarity-glint {
    animation: none !important;
  }
}

@keyframes guide-breathe {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-1.6px); }
}

@keyframes guide-glide {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-2.2px); }
}

@keyframes cape-glow {
  0%, 100% { opacity: 0.7; transform: scaleX(1); }
  50% { opacity: 1; transform: scaleX(1.08); }
}

@keyframes head-notice {
  0% { transform: rotate(0deg); }
  40% { transform: rotate(14deg); }
  100% { transform: rotate(8deg); }
}

@keyframes form-bloom {
  0% { opacity: 0.2; transform: scale(0.42); filter: blur(8px); }
  42% { opacity: 0.8; transform: scale(1.08); filter: blur(1px); }
  100% { opacity: 1; transform: scale(1); filter: blur(0); }
}

@keyframes clarity-glint {
  0% { opacity: 0; transform: scale(0.4) rotate(0deg); }
  35% { opacity: 1; transform: scale(1.15) rotate(18deg); }
  100% { opacity: 0; transform: scale(0.7) rotate(36deg); }
}

@media (min-width: 720px) {
  .lab-shell { width: 430px; }
}

/* ── pass one additions ─────────────────────────────────────────────── */

/* Tone encoding lifted from the approved reference: gold = what the user
   wants, lavender = belief, rose = behaviour, open = unresolved. */
.thought.is-rose .sphere {
  background: var(--sphere-rose);
  box-shadow:
    0 0 16px 5px rgba(231, 184, 196, 0.44),
    0 0 36px 12px rgba(201, 122, 142, 0.2),
    inset 0 -8px 14px rgba(120, 50, 70, 0.12);
}

/* A cycle reads dashed, exactly as the reference legend defines it:
   "the cycle that keeps going". */
.conn.is-cycle {
  stroke: rgba(168, 138, 196, 0.66);
  stroke-width: 1.45;
  stroke-dasharray: 0.018 0.022;
}

.conn.is-counterforce {
  stroke: rgba(201, 165, 106, 0.62);
  stroke-width: 1.45;
}

/*
 * Part A renders the guide. Size is set from JS by guideWidthFor so one
 * function owns it; the old fixed 58px and its .is-complex override, on a class
 * nothing ever set, are gone.
 */

/* Emergence: haze → concentrated light → object → label → glow settles. */
.thought.is-hazing .sphere {
  filter: blur(9px);
  opacity: 0.45;
  transform: scale(0.72);
}

.thought.is-lighting .sphere {
  filter: blur(3px) brightness(1.25);
  opacity: 0.8;
  transform: scale(0.88);
}

/* ── lab chrome. Never ships. ───────────────────────────────────────── */

/*
 * The disclosure around the map.
 *
 * The map is shown on turns that gained a relationship and collapsed on the
 * rest, so this line is the whole of it on an ordinary turn. It has to read as
 * a way back to something, not as a panel that failed to load.
 */
.map-reveal {
  margin: 0;
}

/*
 * The stage the ceremony plays on.
 *
 * Nothing here appears until Finish Entry, so this is chrome for one moment
 * rather than for a conversation: a way out while it runs, and the closing
 * keyword when it stops.
 */
.map-stage {
  position: relative;
}

/*
 * A way past thirteen seconds for someone who does not want them. Quiet
 * enough not to compete with the map, and gone once the map is at rest --
 * there is nothing left to skip, and a dead control is worse than none.
 */
.map-skip {
  position: absolute;
  top: 2px;
  right: 2px;
  z-index: 8;
  padding: 5px 11px;
  border: 0;
  border-radius: 999px;
  opacity: 0.55;
  background: rgba(255, 252, 247, 0.82);
  color: rgba(43, 38, 31, 0.9);
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: opacity 160ms ease;
}

.map-skip:hover,
.map-skip:focus-visible {
  opacity: 1;
}

/*
 * The last balloon: one keyword for the whole conversation.
 *
 * Arrives after the objects have settled, and is given weight the labels do
 * not have, because it is not another thought -- it is what the thoughts came
 * to. It fades up rather than being drawn, so it reads as a conclusion rather
 * than as an eighth arrival.
 */
.map-closing {
  margin: 18px 0 0;
  opacity: 0;
  text-align: center;
  transform: translateY(6px);
  transition:
    opacity 700ms ease,
    transform 700ms ease;
}

.map-closing.is-in {
  opacity: 1;
  transform: none;
}

.map-closing span {
  display: inline-block;
  padding: 9px 20px;
  border-radius: 999px;
  background: radial-gradient(circle at 34% 30%, #fffaf0 0%, #f6e6c4 46%, #eed9a8 100%);
  box-shadow:
    0 0 22px 8px rgba(240, 215, 168, 0.42),
    0 1px 2px rgba(120, 92, 40, 0.14);
  color: #4a3c22;
  font-size: 15px;
  letter-spacing: 0.01em;
}

@media (prefers-reduced-motion: reduce) {
  .map-closing {
    transition: none;
  }

  .map-skip {
    transition: none;
  }
}


/*
 * The guide this conversation earned.
 *
 * Last thing on the stage, after the map has settled and the closing keyword
 * has arrived. The line under the name says what earned it, because a guide
 * that turns up without saying why is a badge, and a badge is what this was
 * designed not to be.
 *
 * The art is per character and may not exist yet: guide.js falls back to the
 * original companion sprite on error, so a missing file shows the guide we
 * already have rather than a broken image.
 */
.guide-earned {
  display: grid;
  justify-items: center;
  margin: 22px 0 4px;
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 900ms ease,
    transform 900ms ease;
}

.guide-earned.is-in {
  opacity: 1;
  transform: none;
}

.guide-earned-art {
  width: 84px;
  height: 84px;
  object-fit: contain;
}

.guide-earned-name {
  margin: 10px 0 0;
  color: var(--ink, #2b261f);
  font-size: 17px;
  letter-spacing: 0.01em;
}

.guide-earned-name span {
  opacity: 0.5;
  font-size: 13px;
}

/*
 * Two lines under the name, one each, and neither wraps.
 *
 * They ran to four wrapped lines before, which is a paragraph -- read once and
 * not kept. The copy is written to fit and the width is set to hold it, so the
 * card stays the size of something someone would screenshot.
 *
 * Longest line in the set is 41 characters; 42ch leaves room without letting a
 * longer one silently wrap in future. If a new line does not fit, shorten the
 * line rather than widening this.
 *
 * The evidence line leads and the description follows, which is the reverse of
 * how this started. The description is the same sentence whoever earns the
 * guide, so giving it the weight put a line that fits any conversation above a
 * line that only fits this one. The name is still the largest thing on the
 * card: it is what someone collects, and that has not changed.
 */
.guide-earned-earned {
  max-width: 42ch;
  margin: 8px 0 0;
  color: var(--ink, #2b261f);
  font-size: 14px;
  line-height: 1.4;
  text-align: center;
  text-wrap: nowrap;
}

/* Who that makes you. Quieter, and under, so the card is not a horoscope. */
.guide-earned-blurb {
  max-width: 42ch;
  margin: 5px 0 0;
  opacity: 0.5;
  font-size: 12px;
  line-height: 1.4;
  text-align: center;
  text-wrap: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .guide-earned {
    transition: none;
  }
}


/*
 * A thought that has been here before.
 *
 * This is the one mark on the map that a new app cannot make on its first
 * day: it needs a history to be true. The person said this in an earlier
 * conversation, stopped saying it, and said it again.
 *
 * Drawn as an echo -- a fainter copy of the same sphere, behind and slightly
 * off -- rather than as a badge or a brighter colour. It has come back, not
 * been promoted, and a thought that keeps returning is not necessarily good
 * news. An echo says "again" without saying "well done".
 *
 * Deliberately not the dashed ring, which already means unresolved. A thought
 * can be both, and the two have to stay legible together.
 */
.thought.is-returning .sphere::before {
  position: absolute;
  z-index: -1;
  inset: 0;
  transform: translate(-7px, -5px) scale(0.92);
  border-radius: 50%;
  opacity: 0.34;
  background: inherit;
  content: "";
  filter: blur(0.4px);
}

.thought.is-returning .name {
  position: relative;
}

/* A small mark before the name, so the echo is not the only carrier: at a
 * glance the spheres blur together, and the label is where someone reads. */
.thought.is-returning .name::before {
  margin-right: 4px;
  opacity: 0.6;
  content: "↺";
  font-size: 0.88em;
}

/*
 * The line that says when. Under the map, quiet, and only when something
 * actually came back -- a heading that appears every time would stop meaning
 * anything the second time it is read.
 */
.map-returning {
  margin: 14px 0 0;
  color: color-mix(in srgb, currentColor 72%, transparent);
  font-size: 13px;
  text-align: center;
  text-wrap: balance;
}

.map-returning b {
  font-weight: 600;
}


/*
 * The sequence line. One kind, because there is only one kind now: this arrow
 * says "and then", and nothing else.
 */
.conn.is-flow {
  stroke: rgba(120, 104, 150, 0.5);
  stroke-width: 1.35;
}


/*
 * The guide card does not close a paid discovery.
 *
 * It is a good component and it is in the wrong place. Someone has just been
 * told something specific about their own problem -- that the question is not
 * whether they want to leave but how much better an opportunity would have to
 * be -- and the last thing on the screen then says "You do not stop at the
 * first why", which is about the kind of person they are. Whatever it adds,
 * it is more general than what it follows, and the ending should leave the
 * finding standing rather than a sentence that would fit anyone.
 *
 * Suppressed here rather than removed. characters.js, guide.js, the scoring
 * and `npm run characters` are untouched and still correct; the card is built
 * and revealed exactly as before and simply is not painted in the production
 * conversation. Scoped to .discovery-panel because map.css is shared with
 * living-map-lab.html and map.html, which are not this decision.
 *
 * Done in CSS because the alternative is panel.js, and the map's internals are
 * a locked decision. One rule, and deleting it brings the card back.
 *
 * Not locked: the design ledger names the guide only inside FINAL THOUGHT MAP
 * / INNER WORLD = NOT YET LOCKED, and section 11 of the consumer constitution
 * lists achievement badges among the things to avoid.
 *
 * Nothing replaces it. The ending is the map, the closing word, and quiet.
 */
.discovery-panel .guide-earned {
  display: none;
}
