/* /for-sales styles. Layers on top of base.css, which holds the shared
   design system (palette, type, container, buttons, header, footer,
   accent rule, centered close).

   The page is /for-marketing's sibling and is built from the same
   pieces (DESIGN.md, "The homepage concept's pieces" and "The marketing
   page's pieces"): full-bleed bands, white plates, one dot per account,
   the teal read line. Its frames below are /for-marketing's, copied with
   their class names (.mk-*) so the two audience pages are one system;
   they belong in a shared stylesheet once both pages settle.

   The first part sets the frames: hero, bands, the copy-beside-picture
   rows, the plate every picture sits on, the dark band, and the close.
   Then one labelled section per picture, in page order, holding what is
   drawn inside its plate, every selector scoped to [data-vis="<id>"].
   Section order matches src/views/for-sales.ejs. */

/* ── Header, on a phone ─────────────────────────────────────────── */

/* The homepage's hero carries a button and this one does not (Rex's
   copy has none), so on a phone this page keeps the header's "Meet with
   our team" beside the menu button, compact, rather than leaving the
   first way to book at the foot of the page. Below 360px there is no
   room, and the menu carries it. */
@media (max-width: 900px) {
  .bar .bar-cta {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-left: auto;
    margin-right: -6px;
    padding: 0 14px;
    font-size: 14px;
  }
  .bar-inner { gap: 12px; }
  /* The open menu carries its own button; never show two. */
  body.mobile-menu-open .bar .bar-cta { visibility: hidden; }
}
@media (max-width: 359px) {
  .bar .bar-cta { display: none; }
}

/* ── Hero ───────────────────────────────────────────────────────── */

/* Nearly the homepage hero's proportions, so the first viewports are
   the same shape: copy left, picture right. The copy side is wider than
   /for-marketing's (1fr, not 0.9fr) because this headline's longest
   line, "and every meeting.", is 8.2em to that page's 6.3em: at 1440 it
   gives the copy about 620px, enough to hold it at the full 72px, and
   costs the picture about 9% of its width. */
.mk-hero { padding: 72px 0 64px; }

.mk-hero-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
}
@media (max-width: 1040px) {
  .mk-hero-grid { grid-template-columns: 1fr; gap: 40px; }
}

/* One sentence on three lines at every width: "The right context" /
   "for every message" / "and every meeting." Line 1 is its own span;
   line 2's span wraps after "message" because the measure (8.6em) is
   wider than its longest piece (8.2em) and narrower than "for every
   message and" (9.6em). Display size, the homepage's own, wherever the
   copy column holds the longest line at that size (all of 1440 and up,
   and stacked at 1040 and below); between those the size steps down
   just enough to keep it there (12cqi is 8.3em of the column), rather
   than breaking the sentence into five lines. */
.mk-hero-copy { container-type: inline-size; }
.mk-hero h1 {
  max-width: 8.6em;
  font-size: min(clamp(38px, 5.6vw, 72px), 12cqi);
}
.mk-hero h1 .line { display: block; }
.mk-hero h1 .line + .line { margin-top: 0.1em; }

.mk-hero-sub {
  font-size: clamp(18px, 1.8vw, 22px);
  line-height: 1.52;
  color: var(--body);
  margin-top: 26px;
  max-width: 25em;
}

/* ── Sections ───────────────────────────────────────────────────── */

/* Grounds run Paper (hero), Tint, Paper, Tint, Ink, Paper (close): the
   Alternating Ground Rule, with the page's one Ink band in the same
   place in the sequence as the homepage's. */
.mk-sec { padding: 96px 0 104px; }
@media (max-width: 700px) {
  .mk-sec { padding: 68px 0 76px; }
}

.mk-head h2 { max-width: 19.5em; }

/* ── Rows: one point of copy beside its picture ─────────────────── */

.mk-rows {
  display: grid;
  gap: 88px;
  margin-top: 56px;
}
@media (max-width: 1040px) {
  .mk-rows { gap: 64px; margin-top: 44px; }
}

/* Copy 5 parts, picture 7: at 1440 the plate is about 674px wide. The
   picture side alternates row to row (.is-flip puts it on the left),
   and the alternation carries on across sections so the page zigzags
   from top to bottom. */
.mk-row {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 64px;
  align-items: center;
}
.mk-row.is-flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.mk-row.is-flip .mk-copy { order: 2; }
.mk-row.is-flip .vis { order: 1; }

/* Laptop widths, 1041 to 1290: a third for the copy, two thirds for the
   picture, so a plate is about 610 to 775px wide rather than 550 to
   670. This page's pictures carry more detail than /for-marketing's, and
   at 5 to 7 they drop to their stacked forms here and stand two or three
   times as tall as the one sentence beside them. */
@media (min-width: 1041px) and (max-width: 1290px) {
  .mk-row { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 48px; }
  .mk-row.is-flip { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
}

/* At 1040 and below, copy always sits above its picture. */
@media (max-width: 1040px) {
  .mk-row,
  .mk-row.is-flip { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .mk-row.is-flip .mk-copy,
  .mk-row.is-flip .vis { order: 0; }
}

/* The point itself, at lede size. Body colour on the light grounds,
   Dark Body on Ink (below). */
.mk-point {
  font-size: 19px;
  line-height: 1.6;
  color: var(--body);
  max-width: 26em;
}
@media (max-width: 700px) {
  .mk-point { font-size: 18px; }
}

/* ── The plate every picture sits on ────────────────────────────── */

/* The homepage's plate: Surface, 1px Rule, 14px radius, no shadow. Each
   picture sets its own shape and inner padding through three custom
   properties in its own section, so no picture has to out-specify
   this file or re-declare the phone breakpoint:

     [data-vis="filter"] {
       --vis-ratio: 1.55 / 1;       width / height above 520px
       --vis-ratio-phone: 0.9 / 1;  width / height at 520px and below
       --vis-pad: 26px;             inner padding above 520px
       --vis-pad-phone: 18px;       inner padding at 520px and below
     }

   Plate widths: about 674px at 1440, up to 680px when stacked between
   520 and 1040, and 335px on a 375px phone. At the defaults that is
   about 421px tall on desktop and 353px on a phone. */
.plate {
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 14px;
  overflow: hidden;
}

.vis {
  /* The homepage canvas's verdict fills and score ink, once for every
     picture: a dot is Teal for target now, Blue at 55% for monitor for
     timing signals, Grey at 45% for hold off; a score is Ink at 62% on
     Track. */
  --v-target: rgba(0, 168, 138, 0.95);
  --v-monitor: rgba(47, 99, 218, 0.55);
  --v-hold: rgba(118, 127, 137, 0.45);
  --score-ink: rgba(17, 22, 27, 0.62);
  position: relative;
  display: block;
  width: 100%;
  min-width: 0;
  aspect-ratio: var(--vis-ratio, 1.6 / 1);
  padding: var(--vis-pad, 26px);
  /* Everything drawn on a plate is instrument chrome or a figure, so
     the plate sets the body face; pictures set Mono where a figure has
     to align. */
  font-family: var(--text);
  color: var(--ink);
}
@media (max-width: 1040px) {
  .vis { max-width: 680px; }
}
@media (max-width: 520px) {
  .vis {
    aspect-ratio: var(--vis-ratio-phone, 0.95 / 1);
    padding: var(--vis-pad-phone, 18px);
  }
}

/* On Ink a white plate reads as a screen, which is what the two
   pictures in that band are. The hairline would be invisible there, so
   it goes. */
.blk.dark .vis { border-color: transparent; }

/* ── Before the player arms a picture ───────────────────────────── */

/* marketing-arm.js, shared with /for-marketing, marks <html> with
   .mk-arm before first paint (never
   under reduced motion or without script). Until the player has armed a
   picture (data-step) or let it rest (.is-done), what is drawn on it is
   hidden, so the finished frame never flashes before the first one. If
   the player never arrives, it shows anyway after 4s. */
html.mk-arm [data-vis]:not([data-step]):not(.is-done) > * {
  visibility: hidden;
  animation: mk-unarm 0s linear 4s forwards;
}
@keyframes mk-unarm { to { visibility: visible; } }

/* ── The player's reset between passes ──────────────────────────── */

/* sales.js fades a picture out before replaying it, snaps it back
   to its first frame with every transition inside it switched off, then
   fades it back in. Owned here, not by any picture. The pseudo-elements
   are included (a /for-sales addition; /for-marketing's copy of this
   rule lacks them), so nothing drawn as ::before or ::after visibly
   runs backwards at a reset. */
[data-vis] { transition: opacity 350ms ease; }
[data-vis].is-resetting { opacity: 0; }
[data-vis].is-snapping,
[data-vis].is-snapping *,
[data-vis].is-snapping *::before,
[data-vis].is-snapping *::after { transition: none !important; animation: none !important; }

/* On Ink a whole white plate blinking out to Ink and back is a flash, so
   there the plate stays lit and only what is drawn on it fades. */
.blk.dark [data-vis].is-resetting { opacity: 1; }
.blk.dark [data-vis] > * { transition: opacity 350ms ease; }
.blk.dark [data-vis].is-resetting > * { opacity: 0; }

/* ── Sales Enablement & Coaching (the Ink band) ─────────────────── */

/* Dark Body on Ink, as the homepage's compounding band sets its lede. */
.blk.dark .mk-point { color: var(--dark-body); }

/* Rex's paragraph under this section's heading, the one section lede on
   the page: it is about all three rows below it (the standard everything
   above runs on), so it sits under the heading rather than beside one
   picture. Lede size, a measure the headline sets. */
.mk-lede {
  margin-top: 26px;
  max-width: 28em;
  font-size: clamp(20px, 1.9vw, 25px);
  line-height: 1.5;
  color: var(--ink);
}
/* On Ink it is set in the band's own near-white, a step above the
   points beside the pictures (Dark Body, 19px), because it is the
   page's hinge: the paragraph that says why everything above can be
   trusted. The rows below it start further down than under a heading
   alone, so it reads as a statement of its own, not a caption. */
.blk.dark .mk-lede { color: #EEF1EE; }
.mk-head:has(.mk-lede) + .mk-rows { margin-top: 80px; }
@media (max-width: 1040px) {
  .mk-head:has(.mk-lede) + .mk-rows { margin-top: 60px; }
}

/* ── The close ──────────────────────────────────────────────────── */

/* The homepage's close, so the two pages end the same, with Rex's
   paragraph above the button as his copy has it: it is the offer, so it
   is set in Body rather than as a muted note. */
.mk-plan { padding: 104px 0 96px; }
.mk-plan .accent-rule { margin-left: auto; margin-right: auto; }
.mk-plan h2 { font-size: clamp(33px, 4.5vw, 57px); }
.mk-plan-body {
  margin: 22px auto 0;
  max-width: 31em;
  font-size: 16.5px;
  line-height: 1.58;
  color: var(--body);
}
.mk-plan .actions { margin-top: 30px; }

/* Two rows of unread accounts, hollow Slate rings, with the read line
   waiting at their edge in Ink at 35%. Drawn twice in the template, 32
   a row and 18 a row, and the width picks one, as on the homepage. */
.mk-unread {
  margin: 56px auto 0;
  max-width: 760px;
}
.mk-unread svg { display: block; width: 100%; height: auto; }
.mk-unread-narrow { display: none !important; }
@media (max-width: 520px) {
  .mk-unread-wide { display: none !important; }
  .mk-unread-narrow { display: block !important; }
}
.mk-unread-rings circle {
  fill: none;
  stroke: rgba(183, 190, 196, 0.95);
  stroke-width: 1.2;
}
.mk-unread-line {
  fill: none;
  stroke: rgba(17, 22, 27, 0.35);
  stroke-width: 1.6;
}


/* ════ PICTURE: Hero: one database, four sales programs [data-vis="hero"] ════ */

/* ════ PICTURE: Hero: one database, every sales program [data-vis="hero"] ════ */

/* The hero picture on /for-sales: one database, every sales program.
   The right-hand column of the hero (.mk-hero-grid in sales.css).
   /for-marketing's hero card (the hero section of marketing.css), built
   the same way so the two audience pages open alike; sales.css does not
   carry that section, so every rule the card needs is here.

   A card in the homepage hero chart's own build (Surface, 1px Rule, 14px
   radius, 20px 22px 22px padding) holding:
     .mk-hero-head   the grid's name and the homepage chart's color key
     .mk-hero-frame  the grid, on canvas, in an inset frame (1px Rule, 8px
                     radius, #FCFDFC); the canvas also draws the bar key
                     and, once read, the Ink outline round one rep's
                     territory with its name in the key's row
     .mk-hero-links  one strip cut into four programs, each a real link
                     to its section, each joined to the grid by a hairline

   The markup with NO data-step is the finished picture: grid read,
   territory outlined, every tile lit. Earlier frames are exceptions:
     step 0  the grid unread, every tile unlit
     step 1  the line reads the grid (canvas, the hero section of js/sales.js)
     step 2  the territory is outlined in the grid (canvas) as Account &
             Territory Planning, straight below it, lights: its six
             accounts are read in the grid's order, and they sort into
             rank
     step 3  Outbound Prospecting lights: the message's opening line
             types itself on the confirmed ground and its source drops
             in under it
     step 4  Meeting Prep lights: the first of three facts opens to its
             source and is ticked
     step 5  Sales Enablement & Coaching lights: the guide is ticked and
             reaches three people, and the picture holds

   Transitions are switched on only once step 1 is reached, so arming the
   picture at load (finished frame to step 0) snaps rather than fading
   every tile out in front of the reader. Nothing here sets transition
   on the [data-vis] root: sales.css owns that. */

[data-vis="hero"] {
  /* A lit hairline: Ink at 40% laid over Surface. */
  --hero-wire-on: #A0A2A4;
  --hero-drop: 20px;
  --glyph: #C3C9CE;                    /* Glyph Grey: a drawn line at rest */
  /* The plates' shared verdict fills and score ink (.vis in sales.css),
     declared here because the hero is not a .vis plate: the same values
     the grid's canvas fills with. */
  --v-target: rgba(0, 168, 138, 0.95);
  --v-monitor: rgba(47, 99, 218, 0.55);
  --v-hold: rgba(118, 127, 137, 0.45);
  --score-ink: rgba(17, 22, 27, 0.62);
  --ease-move: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-drop: cubic-bezier(0.2, 0.9, 0.3, 1.06);
  /* The picture lays itself out by its own width, not the viewport's:
     between 1040 and about 1300 the hero is two columns and this card
     is narrower than it is on a phone held sideways. */
  container-type: inline-size;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 14px;
  padding: 20px 22px 22px;
  min-width: 0;
}
@media (max-width: 1040px) {
  [data-vis="hero"] { max-width: 680px; }
}
@media (max-width: 520px) {
  [data-vis="hero"] { padding: 16px 16px 18px; }
}

/* ── The grid's name and key ────────────────────────────────────── */

/* The name as a plate title, the key as the homepage chart's key (9px
   swatches, 13px Muted); the swatches are marks, so plain Teal. */
[data-vis="hero"] .mk-hero-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 20px;
  margin: 0 2px 14px;
}
[data-vis="hero"] .mk-hero-name {
  margin: 0;
  font-family: var(--display);
  font-size: 15.5px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--ink);
}
[data-vis="hero"] .mk-hero-key {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
}
[data-vis="hero"] .mk-hero-key li {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--muted);
}
[data-vis="hero"] .mk-hero-key i {
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}
[data-vis="hero"] .mk-hero-key .k-good { background: var(--teal); }
[data-vis="hero"] .mk-hero-key .k-fit { background: var(--blue); }
[data-vis="hero"] .mk-hero-key .k-none { background: #767F89; }

/* ── The grid ───────────────────────────────────────────────────── */

[data-vis="hero"] .mk-hero-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 1.62 / 1;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: #FCFDFC;
  overflow: hidden;
}
[data-vis="hero"] .mk-hero-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}
@container (max-width: 519px) {
  [data-vis="hero"] .mk-hero-frame { aspect-ratio: 1.2 / 1; }
}
/* On a phone the territory's name takes a second key row above the
   grid (the hero section of js/sales.js), so the frame is square rather than
   /for-marketing's 1.08, and the cells keep their height. */
@container (max-width: 399px) {
  [data-vis="hero"] .mk-hero-frame { aspect-ratio: 1 / 1; }
  [data-vis="hero"] .mk-hero-head { margin-bottom: 12px; }
  [data-vis="hero"] .mk-hero-key { gap: 4px 14px; }
}

/* ── The four programs ──────────────────────────────────────────── */

/* One strip in the grid frame's own build (1px Rule, 8px radius,
   #FCFDFC), cut into four by hairlines, so the programs read as the
   instrument's outputs rather than as a row of feature cards. Each cell
   is a real link: the site's focus ring (base.css), a thumb-sized
   target, and the link color on hover. */
[data-vis="hero"] .mk-hero-links {
  position: relative;
  list-style: none;
  margin: var(--hero-drop) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: #FCFDFC;
}
[data-vis="hero"] .mk-hero-links li {
  position: relative;
  display: flex;
  min-width: 0;
}
[data-vis="hero"] .mk-hero-links li + li { border-left: 1px solid var(--rule); }

[data-vis="hero"] .mk-hero-links a {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 44px;
  padding: 16px 14px 15px;
  color: var(--ink);
  text-decoration: none;
  border-radius: 6px;
}
/* At rest each label ends in an arrow, so the tiles read as links. On
   hover the tile takes an Ink hairline and its label the link color. */
[data-vis="hero"] .mk-hero-links a:hover .lbl { color: var(--teal-deep); }
[data-vis="hero"] .mk-hero-links a:hover:not(:focus-visible) {
  outline: 1px solid var(--ink);
  outline-offset: -1px;
}
/* Inline, not inline-block, so the no-break space keeps the arrow on the
   last word's line instead of letting it wrap onto a line of its own. */
[data-vis="hero"] .go {
  position: relative;
  left: 0;
  font-family: var(--text);
  font-weight: 500;
  transition: left 200ms ease-out;
}
[data-vis="hero"] .mk-hero-links a:hover .go { left: 2px; }

[data-vis="hero"] .g {
  display: block;
  width: 100%;
  max-width: 104px;
  height: auto;
  overflow: visible;
}
[data-vis="hero"] .lbl {
  display: block;
  margin-top: 14px;
  font-family: var(--display);
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.005em;
  color: var(--ink);
}

/* The hairlines. In a card 520px wide and up: one straight drop from the
   grid's frame to the top of each program, each lit with its program. */
[data-vis="hero"] .mk-hero-links li::before,
[data-vis="hero"] .mk-hero-links::before {
  content: '';
  position: absolute;
  top: calc(-1 * var(--hero-drop) - 1px);
  width: 1px;
  height: var(--hero-drop);
  background: var(--hero-wire-on);
  pointer-events: none;
}
[data-vis="hero"] .mk-hero-links li::before { left: 50%; }
[data-vis="hero"] .mk-hero-links::before { display: none; left: 50%; }

/* Below 520px of card the programs sit two by two, and one drop from the
   grid lands on the strip's middle hairline, which carries it on down
   between them: the same one-to-four, folded. */
@container (max-width: 519px) {
  [data-vis="hero"] .mk-hero-links { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  [data-vis="hero"] .mk-hero-links li + li { border-left: 0; }
  [data-vis="hero"] .mk-hero-links li:nth-child(even) { border-left: 1px solid var(--rule); }
  [data-vis="hero"] .mk-hero-links li:nth-child(n+3) { border-top: 1px solid var(--rule); }
  [data-vis="hero"] .mk-hero-links li::before { display: none; }
  [data-vis="hero"] .mk-hero-links::before { display: block; left: calc(50% - 0.5px); }
  [data-vis="hero"] .mk-hero-links a { padding: 14px 12px 13px; }
  [data-vis="hero"] .lbl { margin-top: 12px; }
}

/* ── What each tile draws (finished) ────────────────────────────── */

/* The shared parts, at /for-marketing's glyph weight. A line of text is
   a 2 to 3 unit bar: Ink at 62% (the score ink, as the grid's bars)
   where it is the line that matters (a claim, a name, a title), Glyph
   Grey where it is the rest of the text. Teal only for what was
   checked: a sourced line's mark, a tick, a Target now account. No
   window frames: the one page drawn is the guide, which is a page. */
[data-vis="hero"] .g .ln { fill: var(--glyph); transform-box: fill-box; transform-origin: left center; }
[data-vis="hero"] .g .ln-k { fill: var(--score-ink); }
[data-vis="hero"] .g .mk { fill: var(--v-target); transform-box: fill-box; transform-origin: center top; }
[data-vis="hero"] .g .ck {
  fill: none;
  stroke: var(--v-target);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 0;
}

/* Account & Territory Planning: each account a dot in its verdict
   color, exactly as the grid fills a cell, beside its two bars, the
   score ink on Track. */
[data-vis="hero"] .g .trk { fill: var(--track); }
[data-vis="hero"] .g .val { fill: var(--score-ink); transform-box: fill-box; transform-origin: left center; }
[data-vis="hero"] .g .dot { stroke: rgba(183, 190, 196, 0); stroke-width: 1.1; }
[data-vis="hero"] .g .v-t { fill: var(--v-target); }
[data-vis="hero"] .g .v-m { fill: var(--v-monitor); }
[data-vis="hero"] .g .v-h { fill: var(--v-hold); }

/* Outbound Prospecting: the opening line on the confirmed pill ground,
   its source on the neutral one (the facts picture's chip), and the
   empty Track slot it is typed over, hidden once it is written. */
[data-vis="hero"] .g .band { fill: var(--pill-yes-bg); transform-box: fill-box; transform-origin: left center; }
[data-vis="hero"] .g .slot { fill: var(--track); opacity: 0; }
[data-vis="hero"] .g .chip-g { fill: var(--pill-none-bg); }
[data-vis="hero"] .g .chip-t { fill: var(--muted); }

/* Meeting Prep: the numerals are Muted, as the brief sets them; the
   source is the brief's inset record (Surface 2 on a hairline), its
   quote set off on a rule. */
[data-vis="hero"] .g .num { fill: var(--muted); }
[data-vis="hero"] .g .sbox { fill: var(--surface-2); stroke: var(--glyph); stroke-width: 1; }
[data-vis="hero"] .g .qr { fill: var(--glyph); }
[data-vis="hero"] .g .src { transform-box: fill-box; transform-origin: center top; }

/* Sales Enablement & Coaching: the guide is a Surface page on a Glyph
   Grey hairline; the wire is a lit hairline; each person is a rounded
   square on the neutral pill ground, its initials in Body, as the
   page's people are set. */
[data-vis="hero"] .g .pg { fill: var(--surface); stroke: var(--glyph); stroke-width: 1; }
[data-vis="hero"] .g .wire {
  fill: none;
  stroke: var(--hero-wire-on);
  stroke-width: 1;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 0;
}
[data-vis="hero"] .g .pp { fill: var(--pill-none-bg); }
[data-vis="hero"] .g .ini { fill: var(--body); }

/* ── Transitions, from step 1 on ────────────────────────────────── */

[data-vis="hero"][data-reached~="1"] .lbl { transition: color 400ms ease-out; }
[data-vis="hero"][data-reached~="1"] .mk-hero-links li::before,
[data-vis="hero"][data-reached~="1"] .mk-hero-links::before { transition: background-color 320ms ease-out; }
[data-vis="hero"][data-reached~="1"] .g circle,
[data-vis="hero"][data-reached~="1"] .g rect {
  transition: fill 380ms ease-out 160ms, stroke 380ms ease-out 160ms;
}

/* Territory: the six are read one by one (dot, then its bars), then
   they sort. */
[data-vis="hero"][data-reached~="1"] .t-ter .dot {
  transition: fill 340ms ease-out calc(240ms + var(--d, 0ms)), stroke 340ms ease-out calc(240ms + var(--d, 0ms));
}
[data-vis="hero"][data-reached~="1"] .t-ter .val {
  transition: transform 420ms var(--ease-out) calc(260ms + var(--d, 0ms));
}

/* Outbound: the message lights, the mark is set, the opening line types
   itself (in steps, as typing does), the confirmed ground sweeps in
   behind it, and its source drops in under it. */
[data-vis="hero"][data-reached~="1"] .t-out .ln {
  transition: fill 380ms ease-out calc(160ms + var(--d, 0ms));
}
[data-vis="hero"][data-reached~="1"] .t-out .mk { transition: transform 300ms var(--ease-out) 160ms; }
[data-vis="hero"][data-reached~="1"] .t-out .claim {
  transition: fill 200ms ease-out 260ms, transform 480ms steps(9, end) 280ms;
}
[data-vis="hero"][data-reached~="1"] .t-out .slot { transition: opacity 160ms ease-out 760ms; }
[data-vis="hero"][data-reached~="1"] .t-out .band { transition: transform 340ms var(--ease-out) 700ms; }
[data-vis="hero"][data-reached~="1"] .t-out .chip {
  transition: transform 400ms var(--ease-drop) 860ms, opacity 220ms ease-out 860ms;
}

/* Prep: the list lights, the two lines under the first slide down and
   its source opens in the room they leave, then the first is ticked.
   The source opens from its top on the same clock and curve as the
   lines move, so its foot stays clear above them the whole way. */
[data-vis="hero"][data-reached~="1"] .t-prep .f-rest { transition: transform 540ms var(--ease-move) 400ms; }
[data-vis="hero"][data-reached~="1"] .t-prep .src {
  transition: transform 540ms var(--ease-move) 400ms, opacity 200ms ease-out 400ms;
}
[data-vis="hero"][data-reached~="1"] .t-prep .ck { transition: stroke-dashoffset 320ms var(--ease-out) 900ms; }

/* Enablement: the page writes, its title is ticked, the hairline runs
   out and branches, and each person is reached in turn. */
[data-vis="hero"][data-reached~="1"] .t-enb .pg ~ .ln {
  transition: fill 300ms ease-out 160ms, transform 360ms var(--ease-out) calc(200ms + var(--d, 0ms));
}
[data-vis="hero"][data-reached~="1"] .t-enb .ck { transition: stroke-dashoffset 340ms var(--ease-out) 620ms; }
[data-vis="hero"][data-reached~="1"] .t-enb .w-stem { transition: stroke-dashoffset 220ms linear 900ms, stroke 200ms ease-out 900ms; }
[data-vis="hero"][data-reached~="1"] .t-enb .w-up,
[data-vis="hero"][data-reached~="1"] .t-enb .w-dn { transition: stroke-dashoffset 360ms var(--ease-out) 1120ms, stroke 200ms ease-out 1120ms; }
[data-vis="hero"][data-reached~="1"] .t-enb .w-mid { transition: stroke-dashoffset 240ms var(--ease-out) 1120ms, stroke 200ms ease-out 1120ms; }
[data-vis="hero"][data-reached~="1"] .t-enb .who .pp {
  transition: fill 300ms ease-out calc(1340ms + var(--d, 0ms));
}
[data-vis="hero"][data-reached~="1"] .t-enb .who .ini {
  transition: opacity 260ms ease-out calc(1400ms + var(--d, 0ms));
}
[data-vis="hero"][data-reached~="1"] .t-enb .who .ln {
  transition: fill 300ms ease-out calc(1400ms + var(--d, 0ms)), transform 380ms var(--ease-out) calc(1400ms + var(--d, 0ms));
}

/* The sort, only while the picture plays: the rows hold the grid's
   order while they are read, then move into rank. The two Monitor rows
   stepping down dim for the whole move (--o) so the Target now rows
   rising through them stay legible instead of piling over them; the
   Hold off rows are already in place. Keyframes rather than a
   transition, for that dip; at rest the static finished rows above take
   over at the same place. */
[data-vis="hero"][data-step][data-reached~="2"] .tr {
  animation: hero-ter-sort 1700ms both;
}
/* Held until the last row's bars have grown (930ms), then 750ms to
   move, done before Outbound lights at 1800ms. The dim is reached
   before any two rows meet and lifted only once they have parted. */
@keyframes hero-ter-sort {
  0%, 56% { transform: translateY(var(--dy)); opacity: 1; animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  64%, 88% { opacity: var(--o, 1); }
  100% { transform: translateY(0); opacity: 1; }
}

/* ── Unlit: a tile before its step ──────────────────────────────── */

/* The tile is there from the start, its drawing in Slate and Track and
   its name in Muted, so the four programs read as waiting on the
   database rather than appearing from nowhere. */
[data-vis="hero"][data-step]:not([data-reached~="2"]) .t-ter,
[data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out,
[data-vis="hero"][data-step]:not([data-reached~="4"]) .t-prep,
[data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb {
  --hero-wire-on: var(--rule);
}
[data-vis="hero"][data-step]:not([data-reached~="2"]) .mk-hero-links::before { background: var(--rule); }
:is(
  [data-vis="hero"][data-step]:not([data-reached~="2"]) .t-ter,
  [data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out,
  [data-vis="hero"][data-step]:not([data-reached~="4"]) .t-prep,
  [data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb
) .lbl { color: var(--muted); }

/* Every line of text waits as empty Track. */
:is(
  [data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out,
  [data-vis="hero"][data-step]:not([data-reached~="4"]) .t-prep,
  [data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb
) :is(.ln, .num) { fill: var(--track); }

/* Territory: the six accounts unread (Slate rings over empty tracks)
   and in the grid's order. */
[data-vis="hero"][data-step]:not([data-reached~="2"]) .t-ter .dot {
  fill: rgba(183, 190, 196, 0);
  stroke: var(--slate);
}
[data-vis="hero"][data-step]:not([data-reached~="2"]) .t-ter .val { transform: scaleX(0); }
[data-vis="hero"][data-step]:not([data-reached~="2"]) .tr { transform: translateY(var(--dy)); }

/* Outbound: an empty first line, no mark, no ground, no source yet. */
[data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out .slot { opacity: 1; }
[data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out .claim { transform: scaleX(0); }
[data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out .band { transform: scaleX(0); }
[data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out .mk { transform: scaleY(0); }
[data-vis="hero"][data-step]:not([data-reached~="3"]) .t-out .chip {
  opacity: 0;
  transform: translateY(-5px);
}

/* Prep: the source shut, the three lines together, no tick. */
[data-vis="hero"][data-step]:not([data-reached~="4"]) .t-prep .f-rest { transform: translateY(-15.6px); }
[data-vis="hero"][data-step]:not([data-reached~="4"]) .t-prep .src {
  opacity: 0;
  transform: scaleY(0);
}
[data-vis="hero"][data-step]:not([data-reached~="4"]) .t-prep .ck { stroke-dashoffset: 1; }

/* Enablement: an unwritten page on a Slate hairline, no tick, no wire,
   and three people waiting as empty Track squares (an outline here
   would read as a checkbox). */
[data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb .pg { stroke: var(--slate); }
[data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb .ln { transform: scaleX(0); }
[data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb .ck { stroke-dashoffset: 1; }
[data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb .wire { stroke-dashoffset: 1; }
[data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb .pp { fill: var(--track); }
[data-vis="hero"][data-step]:not([data-reached~="5"]) .t-enb .ini { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  [data-vis="hero"] * { animation: none !important; transition: none !important; }
}


/* ════ PICTURE: Account & Territory Planning 1: the territory, ranked with reasons [data-vis="rank"] ════ */

/* ════ PICTURE: Account & Territory Planning 1: the territory, ranked [data-vis="rank"] ════ */

/* The territory ranking picture on /for-sales.

   One rep's territory list turning from an arbitrary order into a
   ranking with a reason on every row. The reasons are the point of the
   copy beside it ("with the reasons attached"), so they carry the
   picture: each row is a quiet account on the left (rank, dot, name,
   and fit and timing as two separate bars under the name, never one
   score) and its reason on the right, the claim set large in Outfit
   over its source and date in Mono. Everything else is kept small and
   few: no Account or Why column labels, no verdict key (the hero
   carries it).

   Steps (the markup with no data-step is the finished picture):
     0  the six accounts A to Z: unread Slate rings, empty tracks, and
        each reason waiting as Track lines the length of its words, the
        sort label reading "A to Z".
     1  the read line passes down the list; each dot takes its verdict
        colour and its two bars fill as the line crosses it.
     2  the sort label changes, then the ranking is built from the top,
        each account pulled up into its place in turn (moved by
        the rank section of js/sales.js), and each rank appears as its row lands.
     3  the focal moment: each row's reason writes in over its waiting
        lines, one after another, claim then source and date. The Hold
        off rows are set exactly as the rest.

   The script times every step on the player's frames and marks each
   row as it goes (is-read, is-ranked, is-written); the rules under
   "Earlier steps" below draw a row that is not yet marked.

   Materials are the homepage's and /for-marketing's: a dot per account in the shared verdict fills, the grid's score bars
   (Ink at 62% on Track), the teal read line with its flat band, Plex
   Mono for counts, ranks and citations, the unknown slot as Track
   lines. The rep is a rounded square with initials, because on this
   page a circle is an account.

   Layout switches on the picture's own width (a container query), not
   the viewport's. The wide form holds down to 557px of content (a
   plate beside its copy at 1041); below 540px (a phone) each reason
   moves under its account and the bars move up beside the name.

   Do not set transition on the [data-vis] root: sales.css owns it for
   the fade between passes. */

[data-vis="rank"] {
  /* The plate is as tall as the list, so an edited reason that wraps
     grows the plate rather than being clipped. About 674 by 555 at
     1440. */
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  --vis-pad: 24px 26px 22px;
  --vis-pad-phone: 18px 16px 14px;
}

[data-vis="rank"] .rk {
  container-type: inline-size;
  /* How far the read line runs past the list on each side: to the
     plate's edge, so it reads as one line across the whole picture. */
  --rk-bleed: 26px;
}
@media (max-width: 520px) {
  [data-vis="rank"] .rk { --rk-bleed: 16px; }
}

/* One set of measures for the labels and the rows. Set on the
   picture's children, since a container query cannot restyle the
   container itself. */
[data-vis="rank"] .rk > * {
  --rk-rank: 16px;     /* the rank column */
  --rk-dot: 10px;      /* the dot column */
  --rk-gap: 12px;      /* between rank, dot and account */
  /* The account (its name, and its bars beneath), the bars, the gap to
     the reason and the reason's size grow with the plate, so a wide
     plate (775px at 1290) is not left empty on the right. */
  --rk-acct: clamp(172px, 29cqi, 214px);
  --rk-bw: clamp(64px, 11cqi, 80px);   /* one bar */
  --rk-bgap: 12px;                     /* between the fit and timing bars */
  --rk-mid: clamp(30px, 5.6cqi, 44px); /* between the account and its reason */
  /* The reason's size steps with the plate rather than sliding, so it is
     always a size on the type ramp: 22px (Title Card) on a wide plate,
     20px (Title) from 600px of content down, 17px on a phone. */
  --rk-claim: 22px;
  /* Where a 20px line beside the claim's first line sits: centred on it
     (the claim's line box is 1.2 of its size, 1px down). */
  --rk-line-at: calc(var(--rk-claim) * 0.6 - 9px);
}

/* ── Title row ──────────────────────────────────────────────────── */

[data-vis="rank"] .rk-head {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  column-gap: 12px;
  row-gap: 3px;
  align-items: baseline;
  margin-bottom: 20px;
}

/* The rep: initials on the neutral pill ground, as /for-marketing sets
   a person. */
[data-vis="rank"] .rk-rep {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 6px;
  background: var(--pill-none-bg);
  font-family: var(--text);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.02em;
  line-height: 1;
  color: var(--body);
}

[data-vis="rank"] .rk-title {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
  min-width: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
  line-height: 1.2;
  letter-spacing: -0.016em;
  color: var(--ink);
}

[data-vis="rank"] .rk-count {
  grid-column: 3;
  grid-row: 1;
  margin: 0;
  white-space: nowrap;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* The sort label: a small sort mark and the order the list is in. The
   two orders share one cell and cross-fade; the ranking is set in Ink
   because it is the order the read produced, the alphabet in Muted
   because it is no order at all. */
[data-vis="rank"] .rk-sort {
  grid-column: 2 / span 2;
  grid-row: 2;
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-size: 13px;
  line-height: 1.3;
  color: var(--muted);
}
[data-vis="rank"] .rk-sort-glyph {
  flex: none;
  width: 12px;
  height: 10px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
}
[data-vis="rank"] .rk-sort-labels { display: grid; }
[data-vis="rank"] .rk-sort-labels > span {
  grid-area: 1 / 1;
  white-space: nowrap;
  transition: opacity 320ms ease-out;
}
[data-vis="rank"] .rk-sort-before { opacity: 0; }
[data-vis="rank"] .rk-sort-after {
  font-weight: 500;
  color: var(--ink);
}

/* ── The two bar labels ─────────────────────────────────────────── */

/* Only the bars are labelled: an account and its reason need no column
   label. Outfit 600 12px Muted, as home.js draws Fit and Timing, each
   over its own bar. */
[data-vis="rank"] .rk-cols {
  display: flex;
  gap: var(--rk-bgap);
  padding: 0 0 8px calc(var(--rk-rank) + var(--rk-dot) + 2 * var(--rk-gap));
  border-bottom: 1px solid var(--rule);
}
[data-vis="rank"] .rk-col {
  flex: none;
  width: var(--rk-bw);
  font-family: var(--display);
  font-weight: 600;
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
  color: var(--muted);
}

/* ── Rows ───────────────────────────────────────────────────────── */

/* isolation keeps the rows' z-index during the sort inside the
   picture. */
[data-vis="rank"] .rk-body { position: relative; isolation: isolate; }

/* A grid column, so the script can place rows with the order
   property. */
[data-vis="rank"] .rk-list {
  display: grid;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Two lines a row. Left, the account: rank, dot and name on the first
   line, its two bars beneath the name. Right, its reason across both.
   No rule between rows: the reasons' own hairlines (below) mark each
   row, so the list reads as six cited reasons rather than a ruled
   table. Opaque, so a row passing another during the sort covers it
   cleanly. */
[data-vis="rank"] .rk-row {
  position: relative;
  display: grid;
  grid-template-columns:
    var(--rk-rank) var(--rk-dot) minmax(0, var(--rk-acct)) minmax(0, 1fr);
  grid-template-areas:
    "rank dot name why"
    ".    .   bars why";
  column-gap: var(--rk-gap);
  row-gap: 7px;
  align-items: start;
  padding: 10px 0;
  background: var(--surface);
}
[data-vis="rank"] .rk-list { padding-top: 6px; }

/* During the sort the row being pulled up passes over the others; it
   is edged above and below in Rule hairlines while it moves, so the row
   it covers reads as going under it rather than being sliced. */
[data-vis="rank"] .rk-row::before,
[data-vis="rank"] .rk-row::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--rule);
  opacity: 0;
  pointer-events: none;
}
[data-vis="rank"] .rk-row::before { top: 0; }
[data-vis="rank"] .rk-row::after { bottom: 0; }
[data-vis="rank"] .rk-row.is-climbing::before,
[data-vis="rank"] .rk-row.is-climbing::after { opacity: 1; }

[data-vis="rank"] .rk-rank {
  grid-area: rank;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  line-height: 20px;
  margin-top: var(--rk-line-at);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  transition: opacity 300ms ease-out;
}

/* One dot, one account: its verdict fill once read. Unread it is a
   Slate ring (the border), with nothing inside. */
[data-vis="rank"] .rk-dot {
  grid-area: dot;
  box-sizing: border-box;
  display: block;
  width: 10px;
  height: 10px;
  margin-top: calc(var(--rk-line-at) + 5px);
  border-radius: 50%;
  border: 1.25px solid transparent;
  background: var(--v-hold);
  /* The script marks the row read as the line crosses its middle. */
  transition: background-color 300ms ease-out, border-color 300ms ease-out;
}
[data-vis="rank"] .rk-target .rk-dot { background-color: var(--v-target); }
[data-vis="rank"] .rk-monitor .rk-dot { background-color: var(--v-monitor); }

/* The account's name: Body, regular, so its reason leads the row. */
[data-vis="rank"] .rk-name {
  grid-area: name;
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13.5px;
  line-height: 20px;
  /* Centred on the claim's first line, whatever its size. */
  margin-top: var(--rk-line-at);
  color: var(--body);
}

/* The grid's score bars, fit then timing, each over its label's width:
   Track for the whole 100, Ink at 62% for the score. */
[data-vis="rank"] .rk-bars {
  grid-area: bars;
  display: flex;
  gap: var(--rk-bgap);
}
[data-vis="rank"] .rk-bar {
  position: relative;
  display: block;
  flex: none;
  width: var(--rk-bw);
  height: 4px;
  border-radius: 2px;
  background: var(--track);
  overflow: hidden;
}
[data-vis="rank"] .rk-bar i {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  background: var(--score-ink);
  transform-origin: left center;
  transition: transform 480ms cubic-bezier(0.22, 1, 0.36, 1) 20ms;
}
[data-vis="rank"] .rk-bar-timing i { transition-delay: 100ms; }

/* The reason, the picture's focal point: the claim large in Outfit
   over its source and date on a 1px Rule hairline, the evidence row's
   shape as /for-marketing's ABM picture sets a cited fact (stacked, so
   the hairline is Rule, not a verdict color: the verdict is already the
   dot's). A Hold off reason is set exactly as a Target now one. */
[data-vis="rank"] .rk-why {
  grid-area: why;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-width: 0;
  margin-left: calc(var(--rk-mid) - var(--rk-gap));
  padding: 1px 0 2px 14px;
  border-left: 1px solid var(--rule);
}

/* Each line is as wide as its words, so the Track lines it waits on
   (::before) are the length of what will be written, and it writes in
   at the same pace whatever its length. The words (.rk-ink) are
   uncovered left to right while the Track line is cleared from the
   same edge, so the reason writes itself over its own slot. */
[data-vis="rank"] .rk-claim,
[data-vis="rank"] .rk-cite {
  position: relative;
  display: block;
  max-width: 100%;
}
[data-vis="rank"] .rk-claim::before,
[data-vis="rank"] .rk-cite::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  border-radius: 3px;
  background: var(--track);
  clip-path: inset(0 0 0 100%);
  transition: clip-path 560ms cubic-bezier(0.45, 0, 0.25, 1) 60ms;
}
[data-vis="rank"] .rk-claim::before { top: calc(50% - 4px); height: 8px; }
[data-vis="rank"] .rk-cite::before { top: 34%; height: 4px; border-radius: 2px; transition-delay: 300ms; }
[data-vis="rank"] .rk-ink {
  display: block;
  clip-path: inset(0 0 0 0);
  transition: clip-path 560ms cubic-bezier(0.45, 0, 0.25, 1) 60ms;
}
[data-vis="rank"] .rk-cite .rk-ink { transition-delay: 300ms; }

[data-vis="rank"] .rk-claim {
  font-family: var(--display);
  font-weight: 600;
  font-size: var(--rk-claim);
  line-height: 1.2;
  letter-spacing: -0.016em;
  text-wrap: balance;
  color: var(--ink);
}
[data-vis="rank"] .rk-cite {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
  white-space: nowrap;
  color: var(--muted);
}

/* ── The read line ──────────────────────────────────────────────── */

/* 1.6px Teal at 85% with a flat 38px band of Teal at 8% trailing it,
   running down the list from edge to edge of the plate. Shown only
   while it moves: the script sets its transform and opacity, 300ms a row. */
[data-vis="rank"] .rk-read {
  position: absolute;
  z-index: 5;
  left: calc(-1 * var(--rk-bleed));
  right: calc(-1 * var(--rk-bleed));
  top: 0;
  height: 38px;
  transform: translateY(-100%);
  background: rgba(0, 168, 138, 0.08);
  border-bottom: 1.6px solid rgba(0, 168, 138, 0.85);
  opacity: 0;
  pointer-events: none;
}

/* ── Earlier steps ──────────────────────────────────────────────── */

/* Until the line has crossed a row (step 1): an unread ring and two
   empty tracks. From step 2 every row is read whatever the script did. */
[data-vis="rank"][data-step]:not([data-reached~="2"]) .rk-row:not(.is-read) .rk-dot {
  background-color: transparent;
  border-color: var(--slate);
}
[data-vis="rank"][data-step]:not([data-reached~="2"]) .rk-row:not(.is-read) .rk-bar i {
  transform: scaleX(0);
}

/* Until the sort (step 2): the alphabet. */
[data-vis="rank"][data-step]:not([data-reached~="2"]) .rk-sort-before { opacity: 1; }
[data-vis="rank"][data-step]:not([data-reached~="2"]) .rk-sort-after { opacity: 0; }

/* Until a row has landed in its ranked place: no rank. */
[data-vis="rank"][data-step]:not([data-reached~="3"]) .rk-row:not(.is-ranked) .rk-rank { opacity: 0; }

/* Until its reason writes in (step 3): Track lines the length of its
   words, and no words. Reasons write in in rank order. */
[data-vis="rank"][data-step] .rk-row:not(.is-written) .rk-ink { clip-path: inset(0 100% 0 0); }
[data-vis="rank"][data-step] .rk-row:not(.is-written) .rk-claim::before,
[data-vis="rank"][data-step] .rk-row:not(.is-written) .rk-cite::before { clip-path: inset(0 0 0 0); }

/* ── Narrower plates ────────────────────────────────────────────── */

/* 541 to 600px of content (a plate beside its copy at 1041 to about
   1110, or a stacked plate just above phone width): the account column
   and the gaps give up a little and the reason steps down to 20px, so
   the longest reason keeps one line. */
@container (max-width: 600px) {
  [data-vis="rank"] .rk > * {
    --rk-acct: 160px;
    --rk-bw: 60px;
    --rk-bgap: 10px;
    --rk-mid: 24px;
    --rk-gap: 11px;
    --rk-claim: 20px;
  }
}

/* ── A phone: each reason under its account ─────────────────────── */

/* Below 540px of content the reason would squeeze onto three lines, so
   each row recomposes: rank, dot, name and the two bars on the first
   line, and the reason beneath the name, still the largest thing in the
   row. The bar labels move to the right, over the bars. */
@container (max-width: 539px) {
  [data-vis="rank"] .rk > * {
    --rk-rank: 14px;
    --rk-gap: 8px;
    --rk-bw: 46px;
    --rk-bgap: 8px;
    --rk-claim: 17px;
  }
  [data-vis="rank"] .rk-cols {
    justify-content: flex-end;
    padding-left: 0;
  }
  [data-vis="rank"] .rk-row {
    grid-template-columns: var(--rk-rank) var(--rk-dot) minmax(0, 1fr) auto;
    grid-template-areas:
      "rank dot name bars"
      ".    .   why  why";
    row-gap: 7px;
    padding: 9px 0 10px;
  }
  [data-vis="rank"] .rk-name,
  [data-vis="rank"] .rk-rank { margin-top: 0; }
  [data-vis="rank"] .rk-dot { margin-top: 5px; }
  [data-vis="rank"] .rk-bars { align-self: center; }
  [data-vis="rank"] .rk-why { margin-left: 0; gap: 3px; padding-left: 12px; }
}

/* A phone: the count drops under the title so the title keeps its
   room. */
@container (max-width: 400px) {
  [data-vis="rank"] .rk-head {
    grid-template-columns: 36px minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    row-gap: 2px;
    margin-bottom: 16px;
  }
  [data-vis="rank"] .rk-rep { grid-row: 1 / span 3; align-self: start; }
  [data-vis="rank"] .rk-title { font-size: 16.5px; }
  [data-vis="rank"] .rk-count { grid-column: 2; grid-row: 2; }
  [data-vis="rank"] .rk-sort { grid-column: 2; grid-row: 3; margin-top: 3px; }
}


/* ════ PICTURE: Account & Territory Planning 2: work now, watch, leave alone [data-vis="triage"] ════ */

/* ════ PICTURE: Account & Territory Planning 2: work now, watch, leave alone [data-vis="triage"] ════ */

/* The "triage" picture on /for-sales (Account & Territory Planning,
   point 2): one rep's territory sorted into three lanes, then one
   account crossing when the next monthly read finds its timing changed.

   In the homepage's materials: one dot is one account, in its verdict
   color (the shared --v-* tokens); an unread account is a Slate ring;
   the teal read line is the act of checking; a person is initials in a
   rounded square on the neutral pill ground, never a circle; the change
   ring is the color of the new standing, once, expanding and gone; a
   selection is ringed in Ink, because it claims no standing of its own.

   What it draws (the markup with no data-step is the finished picture):
     - the heading: Jordan M.'s initials, whose territory and its size,
       and the month it was read, in Mono at the right;
     - three lanes, Target now, Monitor for timing signals and Hold off,
       each a large count (as /for-marketing's intent picture sets its
       "25"), the verdict and Rex's words, over a hairline, then its
       accounts in a lattice twelve dots wide (24 when stacked), so the
       lanes compare as their counts do. The lane's dots are its key;
     - the focal moment: a card under the first two lanes (under Target
       now when stacked), tied by one upright hairline to the account
       that crossed (Target now's last dot, ringed in Ink): its name in
       Outfit, the teal pill saying what happened in the second lane's
       words, and the cited fact that moved it, claim over source and
       date in Mono on a hairline. A Surface card on a 1px Rule, as
       /for-marketing's persona card grows out of its list.

   Steps, as the player in sales.js sets them (timings in
   the triage section of js/sales.js):
     0  the 184 accounts as one block of unread rings: over the lanes'
        lattices side by side, in the card's room when stacked; the
        lanes wait faint (hairlines, names dimmed, no counts); the stamp
        reads last month
     1  the read line passes over the block; each ring it crosses takes
        its verdict color
     2  the dots gather into their lanes; the names come up and the
        counts count them in: 23, 41, 120
     3  the next month's read: the stamp turns to this month, the line
        passes over the lanes again and, as it crosses one blue account
        (the script sets .is-found), rings it in Ink; the card opens with
        its name and the fact, and a hairline reaches from the card to it
     4  the pill says "Timing changed"; it crosses into Target now along
        that hairline, which it takes in as it goes, leaving the tie; it
        turns teal and is ringed once (.is-landed), and the counts tick
        41 to 40 as it leaves and 23 to 24 as it lands
   The block, the read line, the hairline in step 4 and every move are
   the script's (transforms from each dot's finished place); every fade
   is here.

   Geometry: .tg is a size container, and the lattice cell is set from
   its width, so every lane's lattice is the same width and the picture
   recomposes by its own width, not the viewport's. Side by side from
   540px of content (tighter from 540 to 619, the plate beside its copy
   on a window of about 1041 to 1160); stacked under 540; a phone under
   381. The script reads --tg-cols and --tg-moved-slot from .tg-field,
   and the card's place from the layout, so it follows whatever this
   file lays out.

   Rules this file keeps: every selector is scoped under
   [data-vis="triage"]; no transition on the [data-vis] root (sales.css
   owns it for the fade between passes); no shadows, no gradients. */

/* The plate is as tall as the drawing, so a name edited in /admin that
   wraps grows the plate rather than clipping it. About 674 by 400 at
   1440, and 335 by about 540 on a phone. */
[data-vis="triage"] {
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  --vis-pad: 24px 26px 26px;
  --vis-pad-phone: 18px 18px 20px;
}

[data-vis="triage"] .tg {
  position: relative;
  container-type: inline-size;
  container-name: tg;
}

[data-vis="triage"] .tg-head,
[data-vis="triage"] .tg-field {
  /* Read by the script, from .tg-field: the lattice width in dots, and
     where in Monitor for timing signals the crossing account sits
     before it crosses (0-based; 36 is the first place of the fourth
     row, the nearest to Target now's empty end). The heading shares
     them for its width. */
  --tg-cols: 12;
  --tg-moved-slot: 36;
  --tg-gap: 28px;
  /* Three lanes of twelve cells, the gaps between them. */
  --tg-cell-raw: calc((100cqw - 2 * var(--tg-gap)) / 36);
  --tg-dot-max: 9.5px;
  --tg-cell: var(--tg-cell-raw);
  --tg-dot: min(calc(var(--tg-cell) * 0.58), var(--tg-dot-max));
  /* The Ink selection ring's gap to its dot: inside half the space
     between two dots, so it never touches a neighbor. */
  --tg-ring-g: calc((var(--tg-cell) - var(--tg-dot)) * 0.42);
  --tg-line: rgba(17, 22, 27, 0.34);
  /* The whole drawing's width: three lanes and their gaps, so the
     heading ends where the last lane does. */
  --tg-span: calc(3 * var(--tg-cols) * var(--tg-cell) + 2 * var(--tg-gap));
}
[data-vis="triage"] .tg-field { position: relative; }

/* Where round() is known, the cell is snapped to half a pixel and the
   dot to a whole one, so on a two-times screen every dot lands on the
   same device pixels and all 184 draw the same size. */
@supports (width: round(down, 10.3px, 0.5px)) {
  [data-vis="triage"] .tg-head,
  [data-vis="triage"] .tg-field {
    --tg-cell: round(down, var(--tg-cell-raw), 0.5px);
    --tg-dot: round(nearest, min(calc(var(--tg-cell) * 0.58), var(--tg-dot-max)), 1px);
  }
}

/* ── The heading ────────────────────────────────────────────────── */

/* The rep's square beside two lines, whose territory over its size, and
   the read stamp on the title's line at the right, as /for-marketing's
   dashboard shows "Read Oct". */
[data-vis="triage"] .tg-head {
  display: grid;
  width: var(--tg-span);
  grid-template-columns: 34px minmax(0, 1fr) auto;
  grid-template-areas:
    "rep title asof"
    "rep total .";
  align-items: baseline;
  column-gap: 12px;
  row-gap: 1px;
  margin-bottom: 24px;
}
/* A person: initials on the neutral pill ground, 6px radius. */
[data-vis="triage"] .tg-rep {
  grid-area: rep;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 6px;
  background: var(--pill-none-bg);
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--body);
}
[data-vis="triage"] .tg-title {
  grid-area: title;
  min-width: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
  line-height: 1.25;
  letter-spacing: -0.016em;
  color: var(--ink);
}
[data-vis="triage"] .tg-total,
[data-vis="triage"] .tg-asof {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  line-height: 1.35;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  white-space: nowrap;
}
[data-vis="triage"] .tg-total { grid-area: total; }
[data-vis="triage"] .tg-asof {
  grid-area: asof;
  justify-self: end;
}

/* ── The lanes ──────────────────────────────────────────────────── */

/* Each lane is exactly its lattice wide, so hairlines, counts and dots
   share one left and right edge. */
[data-vis="triage"] .tg-lanes {
  display: grid;
  grid-template-columns: repeat(3, calc(var(--tg-cols) * var(--tg-cell)));
  grid-template-rows: auto auto;
  column-gap: var(--tg-gap);
}
/* Each lane spans the two shared rows, so the three hairlines sit on
   one line however the names wrap. */
[data-vis="triage"] .tg-lane {
  display: grid;
  grid-row: span 2;
  grid-template-rows: subgrid;
  min-width: 0;
}

/* The count, large, over the verdict and Rex's words for it. */
[data-vis="triage"] .tg-lane-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "count" "name" "line";
  align-content: start;
  row-gap: 3px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}
[data-vis="triage"] .tg-count {
  grid-area: count;
  justify-self: start;
  margin-bottom: 7px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 28px;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
/* Each count in its lane's color set as text, so it reads with the dots
   under it and none outweighs the one the story is about: Teal Deep for
   the accounts confirmed to work now (as the intent picture's "25 Worth
   the budget"), Blue Deep for monitor for timing signals, Muted for
   leave alone. */
[data-vis="triage"] .tg-lane-target .tg-count { color: var(--teal-deep); }
[data-vis="triage"] .tg-lane-monitor .tg-count { color: var(--blue-deep); }
[data-vis="triage"] .tg-lane-hold .tg-count { color: var(--muted); }
/* The tick: as the crossing changes a count (and the next read changes
   the stamp), the new figure rises into place. The script sets
   .is-tick. */
[data-vis="triage"] .tg-count.is-tick,
[data-vis="triage"] .tg-asof.is-tick { animation: tg-tick 420ms cubic-bezier(0.2, 0.7, 0.3, 1) both; }
@keyframes tg-tick {
  0% { opacity: 0; transform: translateY(0.4em); }
  100% { opacity: 1; transform: none; }
}
[data-vis="triage"] .tg-name {
  grid-area: name;
  min-width: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: 14.5px;
  line-height: 18px;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: balance;
}
[data-vis="triage"] .tg-line {
  grid-area: line;
  font-size: 13px;
  line-height: 1.35;
  color: var(--body);
}

[data-vis="triage"] .tg-body {
  position: relative;
  padding-top: 12px;
}

/* One dot is one account. The lattice is exactly its columns wide, so
   the cell the script counts in is the cell CSS laid out. */
[data-vis="triage"] .tg-lattice {
  display: grid;
  grid-template-columns: repeat(var(--tg-cols), var(--tg-cell));
  grid-auto-rows: var(--tg-cell);
  width: calc(var(--tg-cols) * var(--tg-cell));
}
[data-vis="triage"] .tg-dot {
  position: relative;
  display: block;
  place-self: center;
  box-sizing: border-box;
  width: var(--tg-dot);
  height: var(--tg-dot);
  border-radius: 50%;
  /* The border is only ever drawn for an unread ring (.is-u, below). A
     read account is one flat disc, as /for-marketing draws them: its
     translucent fill runs under a transparent border, because a border
     in the same translucent color leaves a darker rim where the two
     antialiased edges meet. */
  border: 1.2px solid transparent;
  transition: background-color 260ms ease-out, border-color 260ms ease-out;
}
/* Only while it plays: at rest 184 dots need no layers of their own. */
[data-vis="triage"][data-step] .tg-dot { will-change: transform; }
[data-vis="triage"] .tg-lane-target .tg-dot { background: var(--v-target); }
[data-vis="triage"] .tg-lane-monitor .tg-dot { background: var(--v-monitor); }
[data-vis="triage"] .tg-lane-hold .tg-dot { background: var(--v-hold); }

/* ── The account that crossed ───────────────────────────────────── */

[data-vis="triage"] .tg-moved { z-index: 2; }

/* A selection, in Ink: which dot the card is about. */
[data-vis="triage"] .tg-moved::before {
  content: '';
  position: absolute;
  inset: calc(-1 * (var(--tg-ring-g) + 2.6px));
  border: 1.4px solid rgba(17, 22, 27, 0.7);
  border-radius: 50%;
}
/* Its transition only on arrival: the player's snap between passes
   switches every transition off, pseudo-elements included. */
[data-vis="triage"].is-found .tg-moved::before {
  transition: opacity 260ms ease-out, transform 380ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* The change ring: once, in the color of its new standing. */
[data-vis="triage"] .tg-moved::after {
  content: '';
  position: absolute;
  inset: -1.2px;
  border: 1.6px solid var(--teal);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}
/* It starts at the dot and ends well outside the Ink selection ring, so
   the two are never read as one. */
@keyframes tg-ring {
  0% { opacity: 1; transform: scale(1); }
  45% { opacity: 0.8; }
  100% { opacity: 0; transform: scale(3.8); }
}

/* The card's room. A block formatting context, so the card's margin
   stays inside it and the script can measure the card from it. Side by
   side it is only the card; stacked it also holds the unread block
   before the sort (below). */
[data-vis="triage"] .tg-room {
  position: relative;
  display: flow-root;
}

/* The card: under the first two lanes, its top a little below the
   second lane's fourth row, so the hairline from it rises straight to
   the crossing account (Target now's last place, the end of its second
   row) and, before the crossing, turns across to it in the fourth row
   of Monitor for timing signals. */
[data-vis="triage"] .tg-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, max-content) auto;
  grid-template-areas:
    "acct pill"
    "fact fact";
  justify-content: start;
  align-items: center;
  column-gap: 12px;
  width: calc(2 * var(--tg-cols) * var(--tg-cell) + var(--tg-gap));
  margin-top: calc(2 * var(--tg-cell) + 12px);
  padding: 15px 18px 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 12px;
  transition: opacity 380ms ease-out 220ms, transform 480ms cubic-bezier(0.22, 1, 0.36, 1) 220ms;
}
[data-vis="triage"] .tg-acct {
  grid-area: acct;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--display);
  font-weight: 600;
  font-size: 20px;
  line-height: 25px;
  letter-spacing: -0.018em;
  color: var(--ink);
}
/* What happened, in the second lane's own words: the confirmed pill,
   because the cited fact checked it, in the color of the account's new
   standing, as /for-marketing's "Up from 5th". */
[data-vis="triage"] .tg-pill {
  grid-area: pill;
  justify-self: start;
  padding: 4px 8px;
  border-radius: 5px;
  background: var(--pill-yes-bg);
  color: var(--teal-deep);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition: opacity 280ms ease-out, transform 360ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
/* The cited fact: claim over source and date, on a hairline. */
[data-vis="triage"] .tg-fact {
  grid-area: fact;
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 10px;
  padding: 1px 0 1px 12px;
  border-left: 1px solid var(--rule);
}
[data-vis="triage"] .tg-claim {
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
}
[data-vis="triage"] .tg-cite {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
  color: var(--muted);
}

/* The tie: one upright hairline from the card's top edge to the crossing
   account's Ink ring, over the empty end of Target now. It overlaps the
   card's border by its own pixel, so the two join. Side by side the
   dot's center is 1.5 cells below the lattice's top and the card's top
   4 cells and 12px below it. */
[data-vis="triage"] .tg-tie {
  position: absolute;
  bottom: 100%;
  left: calc((var(--tg-cols) - 0.5) * var(--tg-cell) - 1.5px);
  width: 1px;
  height: calc(2.5 * var(--tg-cell) + 13px - var(--tg-dot) / 2 - var(--tg-ring-g) - 1.4px);
  background: var(--tg-line);
}

/* ── The read line and the reach ────────────────────────────────── */

/* Shown only while it moves (step 1, and the next month's read in step
   3, .is-sweep); the script sets its place. */
[data-vis="triage"] .tg-read {
  position: absolute;
  left: 0;
  top: 0;
  width: 1.6px;
  height: 0;
  background: rgba(0, 168, 138, 0.85);
  opacity: 0;
  pointer-events: none;
  z-index: 3;
  transition: opacity 200ms ease-out;
}
[data-vis="triage"] .tg-read::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  right: 1.6px;
  width: 38px;
  background: rgba(0, 168, 138, 0.08);
}
[data-vis="triage"][data-step="1"] .tg-read,
[data-vis="triage"][data-step].is-sweep .tg-read { opacity: 1; }

/* Step 3's hairline from the card to the dot still in the second lane;
   the script draws its path, this draws it out and takes it back. */
[data-vis="triage"] .tg-reach {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
[data-vis="triage"] .tg-reach path {
  fill: none;
  stroke: var(--tg-line);
  stroke-width: 1;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 300ms ease-in;
}
[data-vis="triage"][data-step="3"].is-found .tg-reach path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 460ms ease-out 560ms;
}
/* In step 4 the script draws the hairline as what is left of it behind
   the travelling account; once it lands, the tie in the markup, drawn
   to the same points, takes over in the same frame. */
[data-vis="triage"][data-step].is-landed .tg-reach { opacity: 0; }

/* ── Compact: side by side on a narrower plate ──────────────────── */

/* Between 540 and 620px of content (a plate beside its copy on a window
   of about 1041 to 1160px) the lanes keep their places with a tighter
   gap and the verdict names a step down to Meta, so "Monitor for timing
   signals" still sets on one line in a lane of 162px (it takes about
   153px at 13.5px; at 14.5px it would take 164px and wrap). Rex's lines
   keep their 13px: the longest takes about 151px. The card keeps its
   full size: its name and pill take about 310px of the 344px the
   narrowest card has. */
@container tg (min-width: 540px) and (max-width: 619px) {
  [data-vis="triage"] .tg-head,
  [data-vis="triage"] .tg-field { --tg-gap: 20px; }
  [data-vis="triage"] .tg-name { font-size: 13.5px; }
  [data-vis="triage"] .tg-card { padding: 14px 16px 15px; }
  [data-vis="triage"] .tg-claim { font-size: 14.5px; }
}

/* ── Stacked: a narrow plate, and a phone ───────────────────────── */

@container tg (max-width: 539px) {
  [data-vis="triage"] .tg-head,
  [data-vis="triage"] .tg-field {
    /* Twenty-four across, so Target now is one row, Monitor for timing
       signals two and Hold off five; the crossing account is the last
       place of the second lane's second row. The unread block is laid
       at a pitch of at most 12.5px (the script's PITCH_MAX), so it fits
       the card's room. */
    --tg-cols: 24;
    --tg-moved-slot: 40;
    --tg-cell-raw: calc(100cqw / 24);
    --tg-dot-max: 9px;
    --tg-pitch: min(var(--tg-cell), 12.5px);
    --tg-span: calc(var(--tg-cols) * var(--tg-cell));
  }
  [data-vis="triage"] .tg-lanes {
    grid-template-columns: calc(var(--tg-cols) * var(--tg-cell));
    grid-template-rows: none;
    row-gap: 20px;
  }
  [data-vis="triage"] .tg-lane {
    display: block;
    grid-row: auto;
  }
  /* The count on the name's row, at the right, so the lanes stay short. */
  [data-vis="triage"] .tg-lane-head {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "name count"
      "line line";
    align-items: baseline;
    column-gap: 10px;
    row-gap: 2px;
    padding-bottom: 9px;
  }
  [data-vis="triage"] .tg-count { margin: 0; font-size: 22px; }
  [data-vis="triage"] .tg-body { padding-top: 10px; }

  /* The card's room, between Target now and the lanes below it: at
     least the unread block's eight rows at its pitch, so the faint lanes
     show round the block from the first frame and nothing moves when the
     card opens in it. The card is usually the taller, and sets it. */
  [data-vis="triage"] .tg-room { min-height: calc(8 * var(--tg-pitch) + 14px); }
  /* The card grows out of the lanes by 6px each side, so the tie lands
     on its straight top edge rather than its rounded corner. */
  [data-vis="triage"] .tg-card {
    width: calc(var(--tg-cols) * var(--tg-cell) + 12px);
    margin: 14px 0 4px -6px;
    padding: 13px 15px 14px;
  }
  [data-vis="triage"] .tg-claim { font-size: 14.5px; }
  /* Stacked, the dot's center is half a cell below the lattice's top and
     the card's top a cell and 14px below it; the card starts 6px left
     of the lattice. */
  [data-vis="triage"] .tg-tie {
    left: calc((var(--tg-cols) - 0.5) * var(--tg-cell) + 6px - 1.5px);
    height: calc(0.5 * var(--tg-cell) + 15px - var(--tg-dot) / 2 - var(--tg-ring-g) - 1.4px);
  }
}

/* A phone: the stamp joins the territory's size on the second line, and
   the pill goes under the fact, where the card has the width for it. */
@container tg (max-width: 380px) {
  [data-vis="triage"] .tg-head {
    grid-template-areas:
      "rep title title"
      "rep total asof";
    column-gap: 11px;
    margin-bottom: 22px;
  }
  [data-vis="triage"] .tg-title { font-size: 16.5px; }
  [data-vis="triage"] .tg-card {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "acct"
      "fact"
      "pill";
    padding: 12px 13px 13px;
  }
  [data-vis="triage"] .tg-acct { font-size: 17.5px; line-height: 22px; }
  [data-vis="triage"] .tg-fact { margin-top: 8px; padding-left: 10px; }
  [data-vis="triage"] .tg-pill { margin-top: 11px; }
}

/* ── Earlier steps, as exceptions to the finished picture ────────── */

/* 0 and 1: the lanes wait, faint: their hairlines, their names dimmed,
   no counts. At every width, so the plate is never mostly blank. */
[data-vis="triage"] .tg-name,
[data-vis="triage"] .tg-line { transition: opacity 420ms ease-out 260ms; }
/* A count comes up as its lane's first account lands, never as a 0. The
   script holds it back with .is-wait until then, so it follows the
   script's clock rather than a CSS delay that could run ahead of it. */
[data-vis="triage"] .tg-count { transition: opacity 200ms ease-out; }
[data-vis="triage"][data-step]:not([data-reached~="2"]) .tg-name,
[data-vis="triage"][data-step]:not([data-reached~="2"]) .tg-line { opacity: 0.38; }
[data-vis="triage"][data-step]:not([data-reached~="2"]) .tg-count,
[data-vis="triage"][data-step] .tg-count.is-wait { opacity: 0; }
/* Stacked, the block lies between the lanes, so the accounts bound for
   the lower two pass over the names: the names stay faint until the
   last have landed (the farthest leave at 620ms and take 760ms). */
@container tg (max-width: 539px) {
  [data-vis="triage"] .tg-name,
  [data-vis="triage"] .tg-line { transition: opacity 420ms ease-out 1150ms; }
}

/* Until the next read finds it (.is-found, step 3): no card, no
   selection. */
[data-vis="triage"][data-step]:not(.is-found) .tg-card {
  opacity: 0;
  transform: translateY(8px);
}
[data-vis="triage"][data-step]:not(.is-found) .tg-moved::before {
  opacity: 0;
  transform: scale(0.55);
}
/* Until 4: no pill; it comes as the reason the account is about to
   cross. */
[data-vis="triage"][data-step]:not([data-reached~="4"]) .tg-pill {
  opacity: 0;
  transform: translateY(3px) scale(0.92);
  transition: none;
}

/* Until it lands (the script sets .is-landed in step 4): the crossing
   account is still blue, monitor for timing signals, and the tie is the
   script's. As it lands it turns teal and is ringed once. */
[data-vis="triage"][data-step]:not(.is-landed) .tg-moved {
  background: var(--v-monitor);
}
[data-vis="triage"][data-step].is-landed .tg-moved {
  transition: background-color 320ms ease-out, border-color 320ms ease-out;
}
[data-vis="triage"][data-step]:not(.is-landed) .tg-tie { opacity: 0; }
[data-vis="triage"][data-step].is-landed .tg-moved::after {
  animation: tg-ring 1600ms cubic-bezier(0.25, 0.6, 0.35, 1) both;
}

/* An account not yet read is a Slate ring. The script sets .is-u while
   the picture plays; last, so it wins over every verdict color. */
[data-vis="triage"][data-step] .tg-dot.is-u {
  background: transparent;
  border-color: rgba(183, 190, 196, 0.95);
  border-width: 1.3px;
}


/* ════ PICTURE: Outbound Prospecting 1: facts true this month [data-vis="facts"] ════ */

/* ════ PICTURE: Outbound Prospecting 1: facts true this month [data-vis="facts"] ════ */

/* The "facts" picture on /for-sales: Outbound Prospecting, point 1.

   Two facts about Harborline Freight are checked this month. One
   stopped being true and is stamped with an Amber cross; one is still
   true and is stamped with a Teal check, and out of that check a Teal
   arrow runs into the email to Dana K., whose first line then writes
   itself from it. Markup: views/partials/sales/facts.ejs. Motion:
   the facts section of js/sales.js.

   The focal moment is the two stamps and the line they produce, so they
   are the filter picture's stamps (/for-marketing) at card size, the
   loudest marks on the plate, and everything else is kept quiet: the
   email is plain, its subject a gray bar, its unwritten lines gray bars.

   Drawn in two hands, as /for-marketing's filter picture is. The facts
   are ours: the evidence row's grammar, a claim over its source and date
   in Mono, on a Surface 2 card on a 1px hairline, as the filter
   picture's trait card. The verdict is carried by the stamp and the
   pill, never by a colored side border on the card. The email is any
   email app: a white window on hairlines. Nothing about the source is
   written inside the email; the arrow ties the line to the card that
   carries it.

   Steps (timings in the facts section of js/sales.js):
     0  both facts unread (their results empty pill-shaped slots); the
        email waits, its first line an unknown
     1  the read line moves down the facts (2000ms, linear, through
        step 2), leaving the first by the end of this step
     2  the first fact fails as the line leaves it: struck through in
        Amber, "No longer true" and when it stopped; the Amber cross
        drops on it
     3  the second is confirmed: "Still true", when it was checked; the
        Teal check drops on it
     4  its claim lights on the Teal 14% ground, the arrow draws out of
        the check into the email, a caret waits in the empty first line,
        which then writes itself word by word (the script), the fact lit
        on the same ground
     5  hold to read
   No data-step is the finished picture (also no-JS and reduced motion).

   Every selector is scoped under [data-vis="facts"]. The root's own
   transition belongs to sales.css (the fade between passes), and so does
   switching off transitions on pseudo-elements while snapping. */

/* The plate is as tall as the drawing, so a first line edited in /admin
   that runs long grows the plate instead of being clipped. The root is
   a size container, so the picture lays itself out by its own width:
   side by side from 540px of plate (every side-by-side page width, down
   to 1041px windows), stacked below that. */
[data-vis="facts"] {
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  --vis-pad: 26px;
  --vis-pad-phone: 18px;
  /* Named, because each card is a size container too, and an unnamed
     query from inside a card would measure the card. */
  container: fx / inline-size;
}

[data-vis="facts"] .fx {
  /* The geometry the stamps and the arrow are placed by. A claim's row
     and the email's first text row are both 24px, and both start 17px
     into their row of the grid (a 1px border and 16px of padding on the
     card, 17px of padding in the email), so the claim, its stamp, the
     arrow and the first line share one centre line, 29px into the row. */
  --fx-row: 24px;          /* a claim's line, and the email's */
  --fx-in: 16px;           /* a card's top padding */
  --fx-stamp: 64px;        /* the cross and the check */
  --fx-gut: 72px;          /* between the facts and the email */
  --fx-gap: 12px;          /* between the two facts */
  /* The facts never narrower than a claim beside half its stamp, and the
     email takes the rest, so its first line keeps to three rows. */
  --fx-facts-min: 240px;
  /* Amber at the pill grounds' strength, under Ink text (never white on
     Amber): the page's problem pill. The only Amber here is the fact
     that stopped being true. */
  --fx-amber-bg: rgba(206, 132, 9, 0.2);
  --fx-drop: cubic-bezier(0.2, 0.9, 0.3, 1.08);  /* the filter picture's stamp */
  --fx-ease: cubic-bezier(0.22, 0.8, 0.24, 1);

  /* Side by side: the facts, the gutter the stamps and the arrow sit in,
     the email. Three rows: the facts' label, then one row per fact. The
     email spans the two fact rows, and both columns share the rows
     (subgrid), so the email's head sits beside the first fact and its
     body beside the second. The fact rows are 1fr each, so the two
     cards are always the same height, the taller of what either row
     holds. */
  display: grid;
  grid-template-columns: minmax(var(--fx-facts-min), 0.95fr) var(--fx-gut) minmax(0, 1fr);
  grid-template-rows: auto 1fr 1fr;
  row-gap: var(--fx-gap);
}

/* ── The facts ──────────────────────────────────────────────────── */

[data-vis="facts"] .fx-facts {
  grid-column: 1;
  grid-row: 1 / 4;
  display: grid;
  grid-template-rows: subgrid;
  min-width: 0;
}
[data-vis="facts"] .fx-kicker {
  /* Micro, at the page's 12px floor, as /for-marketing sets its part
     labels. */
  grid-row: 1;
  align-self: end;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--muted);
}

[data-vis="facts"] .fx-cards {
  position: relative;
  grid-row: 2 / 4;
  display: grid;
  grid-template-rows: subgrid;
  min-width: 0;
}

/* A fact: a claim over its source and date, with what this month's
   check found at the foot of the card, so if the row is taller than the
   card's words the room goes between them, never under the verdict. A
   1px hairline all round, as the filter picture's trait card: the stamp
   and the pill say what the check found. */
[data-vis="facts"] .fx-card {
  /* A size container, so what it found lays itself out by the card's
     own width (below). */
  container: fx-card / inline-size;
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--fx-in) 14px 15px 17px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: 12px;
}
[data-vis="facts"] .fx-card-a { grid-row: 1; }
[data-vis="facts"] .fx-card-b { grid-row: 2; }

/* A claim, in Outfit as /for-marketing sets its trait. A few words on
   one line (the field labels say so), so the strike and the lit ground
   are each one band. */
[data-vis="facts"] .fx-claim {
  display: flex;
  margin: 0;
  /* Clear of the stamp's half on the card. */
  padding-right: calc(var(--fx-stamp) / 2 - 10px);
  font-family: var(--display);
  font-weight: 600;
  font-size: 18.5px;
  line-height: var(--fx-row);
  letter-spacing: -0.014em;
  color: var(--ink);
}
[data-vis="facts"] .fx-claim-text {
  position: relative;
  z-index: 0;
  white-space: nowrap;
  transition: color 300ms ease 160ms;
}
/* Struck through in Amber: the one fact that stopped being true. */
[data-vis="facts"] .fx-card-a .fx-claim-text { color: var(--muted); }
[data-vis="facts"] .fx-card-a .fx-claim-text::after {
  content: '';
  position: absolute;
  left: -1px;
  right: -1px;
  top: 54%;
  height: 2px;
  margin-top: -1px;
  border-radius: 2px;
  background: var(--amber);
  transform-origin: 0 50%;
  transition: transform 440ms var(--fx-ease) 90ms;
}
/* The fact the first line is written from, lit on the same Teal 14%
   ground as the words it became, so the two read as one. */
[data-vis="facts"] .fx-card-b .fx-claim-text::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: -4px;
  right: -4px;
  top: 1px;
  bottom: 0;
  border-radius: 3px;
  background: var(--pill-yes-bg);
  transform-origin: 0 50%;
  transition: transform 460ms var(--fx-ease);
}

[data-vis="facts"] .fx-cite,
[data-vis="facts"] .fx-found {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
  white-space: nowrap;
}
[data-vis="facts"] .fx-cite {
  display: block;
  margin-top: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--muted);
}

/* What this month's check found: a status pill, then what it found, in
   Mono, under a hairline. */
[data-vis="facts"] .fx-result {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 9px;
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}
/* The hairline keeps 12px from the source above it. */
[data-vis="facts"] .fx-cite { margin-bottom: 12px; }
[data-vis="facts"] .fx-pill {
  flex: none;
  padding: 4px 8px;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
  white-space: nowrap;
  transition: background-color 280ms ease, color 280ms ease;
}
[data-vis="facts"] .fx-card-a .fx-pill { background: var(--fx-amber-bg); color: var(--ink); }
[data-vis="facts"] .fx-card-b .fx-pill { background: var(--pill-yes-bg); color: var(--teal-deep); }
[data-vis="facts"] .fx-found {
  position: relative;
  color: var(--body);
  transition: color 280ms ease 90ms;
}
/* Unread, the found line is one Track bar the width of its words. */
[data-vis="facts"] .fx-found::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 2px;
  background: var(--track);
  opacity: 0;
  transition: opacity 200ms ease;
}

/* The stamps: the filter picture's cross and check (/for-marketing),
   the same paths and the same drop, at card size. Each sits on its
   card's right edge, centred on the claim, half on the card and half in
   the gutter, as the filter's check sits on its trait card's edge. */
[data-vis="facts"] .fx-stamp {
  position: absolute;
  z-index: 3;
  top: calc(var(--fx-in) + var(--fx-row) / 2 - var(--fx-stamp) / 2);
  right: calc(var(--fx-stamp) / -2 - 1px);
  width: var(--fx-stamp);
  height: var(--fx-stamp);
  fill: none;
  stroke-width: 11;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
  transform-origin: 50% 50%;
  transition: opacity 180ms ease 140ms, transform 420ms var(--fx-drop) 140ms;
}
[data-vis="facts"] .fx-x { stroke: var(--amber); }
[data-vis="facts"] .fx-check { stroke: var(--teal); }

/* The arrow: a Teal hairline out of the check, across the gutter, its
   open head just short of the email's edge, level with the first line.
   Drawn by a clip from the check outwards. */
[data-vis="facts"] .fx-link {
  position: absolute;
  z-index: 2;
  top: calc(var(--fx-in) + var(--fx-row) / 2 - 0.8px);
  left: calc(100% + 1px + var(--fx-stamp) / 2 + 3px);
  width: calc(var(--fx-gut) - var(--fx-stamp) / 2 - 6px);
  height: 1.6px;
  background: var(--teal);
  pointer-events: none;
  clip-path: inset(-6px -6px -6px -6px);
  transition: clip-path 380ms cubic-bezier(0.25, 0.7, 0.3, 1);
}
[data-vis="facts"] .fx-link::after {
  content: '';
  position: absolute;
  right: 1px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-top: 1.6px solid var(--teal);
  border-right: 1.6px solid var(--teal);
  transform: rotate(45deg);
}

/* The read line: a 1.6px Teal stroke at 85% with its flat 38px band
   trailing above it, moving down both facts. Shown only while it moves.
   The frame covers the two facts and clips the band to them, so the
   band grows out of the first fact's top edge rather than trailing up
   over the facts' label; the band moves by transform alone, in units of
   the frame's height (cqh). */
[data-vis="facts"] .fx-read {
  position: absolute;
  z-index: 2;
  left: -10px;
  right: -10px;
  top: 0;
  bottom: 0;
  overflow: hidden;
  container-type: size;
  pointer-events: none;
}
[data-vis="facts"] .fx-read i {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 38px;
  background: rgba(0, 168, 138, 0.08);
  border-bottom: 1.6px solid rgba(0, 168, 138, 0.85);
  opacity: 0;
  transform: translateY(-38px);
}

/* ── The email ──────────────────────────────────────────────────── */

[data-vis="facts"] .fx-mail {
  grid-column: 3;
  grid-row: 2 / 4;
  display: grid;
  grid-template-rows: subgrid;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 12px;
  overflow: hidden;
}
/* The head sits beside the first fact: To and Subject at its top, the
   greeting at its foot, so the greeting keeps one even gap above the
   first line whatever height the row takes. */
[data-vis="facts"] .fx-mail-head {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

[data-vis="facts"] .fx-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--rule);
}
[data-vis="facts"] .fx-row-label {
  flex: none;
  width: 54px;
  font-size: 13px;
  line-height: 1.3;
  color: var(--muted);
}
/* The recipient: a person is a rounded square with initials, on the
   neutral pill ground, never a circle (a circle is an account). */
[data-vis="facts"] .fx-who {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 13.5px;
  line-height: 1.3;
  white-space: nowrap;
}
[data-vis="facts"] .fx-av {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--pill-none-bg);
  color: var(--body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
}
[data-vis="facts"] .fx-who-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 600;
  color: var(--ink);
}

/* Written text that is not the point is drawn as gray bars, as the
   report picture on /for-marketing draws its sections. */
[data-vis="facts"] .fx-bar {
  display: block;
  height: 5px;
  border-radius: 2px;
  background: var(--track);
  width: var(--w, 100%);
}
[data-vis="facts"] .fx-bar-subject { flex: 0 1 56%; }

[data-vis="facts"] .fx-greet,
[data-vis="facts"] .fx-line {
  margin: 0;
  font-size: 15.5px;
  line-height: var(--fx-row);
  color: var(--ink);
}
[data-vis="facts"] .fx-greet { margin-top: auto; padding: 14px 16px 0; }

/* The body sits beside the Teal fact. Its first text row starts as far
   into the row as the claim does (17px), so the arrow meets it level.
   The rest of the message keeps to the foot of the row, level with the
   card's foot. */
[data-vis="facts"] .fx-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: calc(var(--fx-in) + 1px) 16px 14px;
}

/* The first line. Pretty wrapping, so it never ends on one word, but
   not balanced: an email's lines run to the width of the message, as
   the gray lines under it do. Safe while it is written: the script only
   shows and hides words that are already in place, so the text and its
   breaks never change. */
[data-vis="facts"] .fx-first { position: relative; }
[data-vis="facts"] .fx-line {
  position: relative;
  text-wrap: pretty;
}
/* One word, as the script splits the line: a plain span, nothing drawn
   on it. Anything drawn inside the line (a positioned caret, a border,
   padding) makes the browser drop the pretty wrapping, so the line
   would break one way while it is written and jump to the other at the
   end. */
[data-vis="facts"] .fx-w { transition: opacity 90ms ease; }
/* The caret, outside the line: at the start of the empty first row, and
   then 2px after the last word written, moved there by the script
   (--fx-cx, --fx-cy). Shown while data-caret is set. */
[data-vis="facts"] .fx-caret {
  position: absolute;
  left: 0;
  top: 2px;
  width: 1.5px;
  height: 20px;
  background: var(--ink);
  opacity: 0;
  pointer-events: none;
  transform: translate(var(--fx-cx, 0px), var(--fx-cy, 0px));
}
[data-vis="facts"][data-caret] .fx-caret { opacity: 1; }

/* The fact, lit: the read line's color at the confirmed pill's
   strength, swept on from the left behind the words, as the persona
   picture lights the words it read. Kept on one line so it is one band.
   The ground stops at the end of the fact's last letter plus a hair, and
   the fact keeps that hair as a margin, so the period after it ("...
   dispatchers.") sits just outside the ground rather than lit with it. */
[data-vis="facts"] .fx-hit {
  position: relative;
  z-index: 0;
  margin-right: 1.5px;
  white-space: nowrap;
}
[data-vis="facts"] .fx-hit::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: -3px;
  right: -1.5px;
  top: 1px;
  bottom: 0;
  border-radius: 3px;
  background: var(--pill-yes-bg);
  transform-origin: 0 50%;
  transition: transform 460ms var(--fx-ease);
}

/* The first line's unknown: two Track lines, the slot /for-marketing's
   cards wait with, on the line's first two text rows. */
[data-vis="facts"] .fx-skel {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: calc(var(--fx-row) - 6px);
  padding-top: calc(var(--fx-row) / 2 - 3px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease;
}
[data-vis="facts"] .fx-skel i {
  display: block;
  flex: none;
  height: 6px;
  width: 92%;
  border-radius: 2px;
  background: var(--track);
}
[data-vis="facts"] .fx-skel i + i { width: 58%; }

[data-vis="facts"] .fx-rest {
  display: grid;
  gap: 8px;
  margin-top: auto;
  padding-top: 10px;
}

/* ── Earlier steps, as exceptions to the finished picture ───────── */

/* 0-3: the first line is an unknown. */
[data-vis="facts"][data-step]:not([data-reached~="4"]) .fx-skel { opacity: 1; }
/* While playing, a word shows once the script has written it, and the
   fact is lit once its last word is down. */
[data-vis="facts"][data-step] .fx-w:not(.is-on) { opacity: 0; }
[data-vis="facts"][data-step] .fx-hit:not(.is-lit)::before { transform: scaleX(0); }

/* 1 and 2: the read line, started at step 1 and still running through
   step 2, so it leaves the first fact by the end of step 1 (the two
   cards are the same height) and crosses the second during step 2. */
[data-vis="facts"][data-reached~="1"] .fx-read i {
  animation: fx-read 2000ms linear 120ms both;
}
/* The stroke runs from the first fact's top edge to the second fact's
   foot at an even speed. */
@keyframes fx-read {
  0%   { transform: translateY(-38px);               opacity: 0; }
  5%   {                                             opacity: 1; }
  94%  {                                             opacity: 1; }
  100% { transform: translateY(calc(100cqh - 38px)); opacity: 0; }
}

/* 0-1: the first fact unread. */
[data-vis="facts"][data-step]:not([data-reached~="2"]) .fx-card-a .fx-claim-text { color: var(--ink); }
[data-vis="facts"][data-step]:not([data-reached~="2"]) .fx-card-a .fx-claim-text::after { transform: scaleX(0); }
[data-vis="facts"][data-step]:not([data-reached~="2"]) .fx-x {
  opacity: 0;
  transform: scale(1.4);
}

/* 0-2: the second fact unread. */
[data-vis="facts"][data-step]:not([data-reached~="3"]) .fx-check {
  opacity: 0;
  transform: scale(1.4);
}

/* 0-3: the second fact not yet used, and no arrow; at step 4 it lights
   and the arrow draws out of the check (after the light has started,
   and before the caret shows). */
[data-vis="facts"][data-step]:not([data-reached~="4"]) .fx-card-b .fx-claim-text::before { transform: scaleX(0); }
[data-vis="facts"][data-step]:not([data-reached~="4"]) .fx-link {
  clip-path: inset(-6px 100% -6px -6px);
}
[data-vis="facts"][data-step="4"] .fx-link { transition-delay: 160ms; }

/* An unread result is an empty pill-shaped slot and a Track bar. */
[data-vis="facts"][data-step]:not([data-reached~="2"]) .fx-card-a .fx-pill,
[data-vis="facts"][data-step]:not([data-reached~="3"]) .fx-card-b .fx-pill {
  background: var(--track);
  color: transparent;
}
[data-vis="facts"][data-step]:not([data-reached~="2"]) .fx-card-a .fx-found,
[data-vis="facts"][data-step]:not([data-reached~="3"]) .fx-card-b .fx-found { color: transparent; }
[data-vis="facts"][data-step]:not([data-reached~="2"]) .fx-card-a .fx-found::before,
[data-vis="facts"][data-step]:not([data-reached~="3"]) .fx-card-b .fx-found::before { opacity: 1; }

/* A card too narrow for the pill and what was found on one row (side
   by side at about 1041 to 1080px windows): the pill over what was
   found. Both cards are the same width, so both change together. */
@container fx-card (max-width: 221px) {
  [data-vis="facts"] .fx-result { flex-direction: column; align-items: flex-start; gap: 5px; padding-top: 9px; }
  [data-vis="facts"] .fx-cite { margin-bottom: 9px; }
}

/* 540 to 599px of plate (windows of about 1041 to 1130px, where the
   plate sits beside its copy at its narrowest): the gutter and stamps
   come in a little, the claims step down to 17.5px and the email's
   text to 14.5px (both on the type ramp), so the claims clear their
   stamps and the first line still opens on the whole fact. */
@container fx (min-width: 540px) and (max-width: 599px) {
  [data-vis="facts"] .fx { --fx-gut: 56px; --fx-stamp: 52px; --fx-facts-min: 236px; }
  [data-vis="facts"] .fx-row,
  [data-vis="facts"] .fx-greet { padding-left: 14px; padding-right: 14px; }
  [data-vis="facts"] .fx-body { padding-left: 14px; padding-right: 14px; }
  [data-vis="facts"] .fx-claim { font-size: 17.5px; }
  [data-vis="facts"] .fx-greet,
  [data-vis="facts"] .fx-line { font-size: 14.5px; }
}

/* ── A narrow plate: the facts, then the email ──────────────────── */

/* Under 540px of plate (windows of about 520 to 640px, and every
   phone) the email goes under the facts, so the picture still reads
   from cause to effect, top to bottom: the read line down the two
   facts, the check, the arrow down out of it into the email, the first
   line. The stamps come inside their cards' right edges, since the
   plate's margin is too narrow to take their outer half, and the arrow
   drops from under the check into the email's top edge. */
@container fx (max-width: 539px) {
  [data-vis="facts"] .fx {
    --fx-stamp: 50px;
    --fx-in: 15px;
    --fx-drop-h: 36px;     /* between the facts and the email */
    --fx-gap: 10px;
    display: block;
  }
  [data-vis="facts"] .fx-facts,
  [data-vis="facts"] .fx-mail { display: block; }
  [data-vis="facts"] .fx-kicker { display: block; margin-bottom: 10px; }
  [data-vis="facts"] .fx-cards {
    grid-template-rows: none;
    gap: var(--fx-gap);
  }
  [data-vis="facts"] .fx-card-a,
  [data-vis="facts"] .fx-card-b { grid-row: auto; }
  [data-vis="facts"] .fx-card { padding: var(--fx-in) 14px 13px 15px; }
  [data-vis="facts"] .fx-claim { padding-right: calc(var(--fx-stamp) + 10px); }
  [data-vis="facts"] .fx-result { margin-top: 0; padding-top: 10px; }
  [data-vis="facts"] .fx-cite { margin-bottom: 10px; }
  [data-vis="facts"] .fx-stamp { right: 10px; }
  [data-vis="facts"] .fx-link {
    top: calc(100% + 1px + 4px);
    left: auto;
    right: calc(10px + var(--fx-stamp) / 2 - 0.8px);
    width: 1.6px;
    height: calc(var(--fx-drop-h) - 9px);
  }
  [data-vis="facts"] .fx-link::after {
    right: auto;
    left: 50%;
    top: auto;
    bottom: 1px;
    margin: 0 0 0 -3.5px;
    transform: rotate(135deg);
  }
  [data-vis="facts"][data-step]:not([data-reached~="4"]) .fx-link {
    clip-path: inset(-6px -6px 100% -6px);
  }
  [data-vis="facts"] .fx-mail { margin-top: var(--fx-drop-h); }
  [data-vis="facts"] .fx-body { padding: 10px 16px 16px; }
  [data-vis="facts"] .fx-rest { margin-top: 0; padding-top: 14px; }
}

/* A phone: the email drops its Subject row (a gray bar, no words) and
   keeps the rest a little tighter; the first line stays at reading
   size. */
@container fx (max-width: 439px) {
  [data-vis="facts"] .fx { --fx-stamp: 46px; }
  [data-vis="facts"] .fx-row { gap: 8px; min-height: 42px; padding: 8px 14px; }
  [data-vis="facts"] .fx-row-subject { display: none; }
  [data-vis="facts"] .fx-row-label { width: auto; min-width: 22px; }
  [data-vis="facts"] .fx-who { font-size: 13px; gap: 7px; }
  [data-vis="facts"] .fx-av { width: 24px; height: 24px; }
  [data-vis="facts"] .fx-greet { padding: 13px 14px 0; }
  [data-vis="facts"] .fx-body { padding: 10px 14px 15px; }
}


/* ════ PICTURE: Outbound Prospecting 2: the buying committee, each with a reason [data-vis="committee"] ════ */

/* ════ PICTURE: Outbound Prospecting 2: the buying committee, tagged and sent [data-vis="committee"] ════ */

/* The "committee" picture on /for-sales (Outbound Prospecting, point 2):
   Harborline Freight's buying committee, every person tagged with why
   they are on the list, then each person sent into the team's tools.

   What it draws, top to bottom:
   - the account: its dot in its verdict color (Teal, target now) and its
     name as the plate's title. Nothing else, so it does not repeat
     /for-marketing's persona header.
   - the six people as a three by two grid of rounded squares (initials
     on the neutral pill ground in Body, 6px radius: on this page a
     circle is an account), each with one short title and a tag saying
     why they are on the list. Five tags are the confirmed pill (read off
     the account); person 5's is the neutral pill, because she joins at
     the contract stage, styled as fully as the others.
   - the two tools, side by side: each an Ink tile, because a tool is
     Ink on these pages (/for-marketing's intent picture draws its tool
     as an Ink app tile). Its glyph, its name and its count in Paper
     (the count Outfit 700 at 28px, as that picture and the triage
     picture set the counts their accounts arrive into), and under them
     a row of six places, one a person, in the committee's order. The
     people's squares land in them: the one focal moment, the light
     squares dropping into the two dark tiles. In Sales engagement,
     person 5's place stays empty, outlined in Slate with her initials
     in Slate, and a Slate hairline hangs from it to a neutral note
     under the tile.

   Steps (the committee script holds the timings):
     0  the account and its six people, each reason an unknown slot (a
        Track line the length of the tag it waits for); the tools'
        places empty outlines, the counts at 0
     1  the read line runs down the people; as it crosses each row the
        tags fill, left to right
     2  every person is sent into the CRM: one at a time a copy of each
        square leaves its person ringed in Ink (a selection, which
        travels with it), drops to the open lane under the people, runs
        along it and down into its place, and the count goes up as it
        lands
     3  the same into Sales engagement, except person 5: at her turn
        nothing leaves, her place is outlined and its note hangs from it
     4  it holds
   The markup with NO data-step is the finished picture, which is also
   what no-JS and reduced-motion readers see.

   Two layouts, chosen by the plate's own inner width (a container
   query), not the viewport's:
   - wide (540px and up inside): people in three columns; the tools
     side by side.
   - narrow (every phone, and a stacked plate up to about 590px wide):
     people in two columns; the tools one over the other, each the same
     tile, so a square bound for Sales engagement drops on through the
     CRM, over its own square there.

   Rules this file keeps: every selector is scoped under
   [data-vis="committee"]; the plate's shape and padding are set with
   the custom properties sales.css documents; no transition is set on
   the [data-vis] root itself (sales.css owns it for the fade between
   passes). No shadows, no gradients. Type only from DESIGN.md's ramp,
   radii only from its rounded scale. */

[data-vis="committee"] {
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  --vis-pad: 24px 26px 26px;
  --vis-pad-phone: 18px 16px 18px;
  container-type: inline-size;

  /* The plate's side padding, so the read line reaches its edges. */
  --cm-px: 26px;
  /* A person in the grid, and the same person in a tool. */
  --cm-av: 44px;
  --cm-sq: 34px;
  --cm-sq-gap: 6px;
  /* A tool tile's padding, and the note's distance under the tile,
     which the hairline from person 5's place spans. */
  --cm-tp: 14px;
  --cm-note-gap: 8px;
  --cm-ease: cubic-bezier(0.22, 0.8, 0.24, 1);
}
@media (max-width: 520px) {
  [data-vis="committee"] { --cm-px: 16px; }
}

[data-vis="committee"] .cm {
  position: relative;
  min-width: 0;
}

/* ── The account ───────────────────────────────────────────────── */

[data-vis="committee"] .cm-acct {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
[data-vis="committee"] .cm-dot {
  flex: none;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--v-target);
}
/* The plate's title: Outfit 600 at 17px. */
[data-vis="committee"] .cm-acct-name {
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
  line-height: 1.25;
  letter-spacing: -0.016em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* ── The people ────────────────────────────────────────────────── */

[data-vis="committee"] .cm-team {
  position: relative;
  margin-top: 16px;
}
[data-vis="committee"] .cm-people {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: 12px;
  row-gap: 18px;
}
[data-vis="committee"] .cm-p {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
  text-align: center;
}

[data-vis="committee"] .cm-av {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--cm-av);
  height: var(--cm-av);
  border-radius: 6px;  /* people are rounded squares; a circle is an account */
  background: var(--pill-none-bg);
  color: var(--body);
  font-weight: 600;
  font-size: 14.5px;
  letter-spacing: 0.02em;
  line-height: 1;
}

/* The short title, quieter than the reason, which is the point. */
[data-vis="committee"] .cm-role {
  margin-top: 7px;
  max-width: 100%;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── The reason, and the slot it fills ─────────────────────────── */

[data-vis="committee"] .cm-tag {
  position: relative;
  display: flex;
  justify-content: center;
  max-width: 100%;
  margin-top: 6px;
}

/* The unknown: a Track line where the tag's words will stand, as long
   as they are. The script measures each tag and sets the slot's left and
   width to its words exactly; the centered 60% is the fallback. Hidden
   in the finished picture. */
[data-vis="committee"] .cm-slot {
  position: absolute;
  left: 20%;
  top: 50%;
  width: 60%;
  height: 6px;
  margin-top: -3px;
  border-radius: 2px;
  background: var(--track);
  opacity: 0;
  transition: opacity 220ms ease-out;
}

/* The tag: the 12px status pill at 5px radius. Its ground is drawn
   behind the words (::before) so it can sweep on from the left as the
   line passes. --c is the person's column, so a row fills left to right. */
[data-vis="committee"] .cm-why {
  position: relative;
  z-index: 0;
  display: inline-block;
  max-width: 100%;
  padding: 4px 9px;
  border-radius: 5px;
  font-weight: 600;
  font-size: 12px;
  line-height: 1.35;
  color: var(--teal-deep);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color 280ms ease-out calc(110ms + var(--c, 0) * 90ms);
}
[data-vis="committee"] .cm-why::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 0;
  border-radius: 5px;
  background: var(--pill-yes-bg);
  transform-origin: 0 50%;
  transition: transform 440ms var(--cm-ease) calc(var(--c, 0) * 90ms);
}
/* Person 5: the neutral pill, styled as fully as the confirmed ones. */
[data-vis="committee"] .cm-p.is-later .cm-why { color: var(--muted); }
[data-vis="committee"] .cm-p.is-later .cm-why::before { background: var(--pill-none-bg); }

/* ── The read line ─────────────────────────────────────────────── */

/* 1.6px Teal at 85% with a flat 38px band of Teal at 8% trailing it,
   moving down the people (the script sets its place). Shown only while
   it moves, so it is invisible here and in the finished picture. */
[data-vis="committee"] .cm-read {
  position: absolute;
  z-index: 2;
  left: calc(var(--cm-px) * -1);
  right: calc(var(--cm-px) * -1);
  top: -38px;
  height: 38px;
  background: rgba(0, 168, 138, 0.08);
  border-bottom: 1.6px solid rgba(0, 168, 138, 0.85);
  opacity: 0;
  pointer-events: none;
}

/* ── The tools ─────────────────────────────────────────────────── */

/* Side by side, with an open lane above them that the squares run
   along. The note belongs to tool 2 (the one that holds person 5 back)
   and sits under its tile. */
[data-vis="committee"] .cm-tools {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 14px;
  margin-top: 30px;
}
[data-vis="committee"] .cm-tool { min-width: 0; }

/* A tool: an Ink tile at the lg radius. Glyph, name and count on one
   line, the six places under them. */
[data-vis="committee"] .cm-card {
  padding: var(--cm-tp);
  border-radius: 12px;
  background: var(--ink);
}
[data-vis="committee"] .cm-head {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  height: 28px;
}
/* The tool's own glyph in Paper strokes, no brand: a contact card for
   the CRM, an envelope for sales engagement. */
[data-vis="committee"] .cm-app {
  flex: none;
  display: inline-flex;
}
[data-vis="committee"] .cm-app svg {
  display: block;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: var(--bg);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
[data-vis="committee"] .cm-app .cm-app-fill { fill: var(--bg); stroke: none; }
[data-vis="committee"] .cm-tool-name {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--bg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The count, as /for-marketing's intent picture sets the counts its
   accounts arrive into (Outfit 700 at 28px). It counts up as each
   person lands; the row of squares under it says what it counts. */
[data-vis="committee"] .cm-n {
  flex: none;
  display: inline-block;
  font-family: var(--display);
  font-weight: 700;
  font-size: 28px;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--bg);
  transition: color 240ms ease-out;
}
[data-vis="committee"] .cm-tool.is-empty .cm-n { color: rgba(251, 251, 248, 0.32); }
/* Each time a tool receives a person its number drops in from 4px
   above (the script restarts this). */
[data-vis="committee"] .cm-n.is-bump { animation: cm-bump 300ms cubic-bezier(0.22, 0.8, 0.24, 1); }
@keyframes cm-bump {
  from { transform: translateY(-4px); opacity: 0.35; }
  to   { transform: none; opacity: 1; }
}

/* The six places, in the committee's order (left to right, top row
   then bottom row of the grid above). An empty place is a Rule Dark
   outline; a person's square covers it exactly when they land. */
[data-vis="committee"] .cm-places {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: flex;
  gap: var(--cm-sq-gap);
}
[data-vis="committee"] .cm-box {
  position: relative;
  flex: none;
  box-sizing: border-box;
  width: var(--cm-sq);
  height: var(--cm-sq);
  border: 1px solid var(--rule-dark);
  border-radius: 6px;
  transition: border-color 300ms ease-out;
}
[data-vis="committee"] .cm-sq,
[data-vis="committee"] .cm-ghost {
  position: absolute;
  inset: -1px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 1;
}
/* A person, as in the grid. z-index so a square in flight passes over
   the people and the tiles. */
[data-vis="committee"] .cm-sq {
  z-index: 3;
  background: var(--pill-none-bg);
  color: var(--body);
  transform-origin: 50% 50%;
  outline: 1.4px solid rgba(17, 22, 27, 0);
  outline-offset: 2px;
  transition: outline-color 200ms ease-out;
}
/* In flight it carries the person's Ink selection ring with it. */
[data-vis="committee"] .cm-sq.is-flying {
  outline-color: rgba(17, 22, 27, 0.7);
  transition-duration: 60ms;
}

/* Person 5's place in Sales engagement, held open: a Slate outline with
   her initials in Slate, and a Slate hairline down from it, out of the
   tile, to the note. */
[data-vis="committee"] .cm-box.is-held { border-color: var(--slate); }
[data-vis="committee"] .cm-ghost {
  color: var(--slate);
  transition: opacity 300ms ease-out;
}
[data-vis="committee"] .cm-box.is-held::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 100%;
  width: 1px;
  height: calc(var(--cm-tp) + 1px + var(--cm-note-gap));
  margin-left: -0.5px;
  background: var(--slate);
  transform-origin: 50% 0;
  transition: transform 300ms var(--cm-ease) 120ms;
}
/* The note, centered under person 5's place (--at is her place's
   index, rendered by the partial), so the hairline lands on its middle.
   The committee script nudges it left if a longer note would run past
   the tile. Centered with the translate property, so the steps can use
   transform. */
[data-vis="committee"] .cm-note {
  position: relative;
  height: 24px;
  margin-top: var(--cm-note-gap);
}
[data-vis="committee"] .cm-note-pill {
  position: absolute;
  top: 0;
  left: calc(var(--cm-tp) + var(--at, 0) * (var(--cm-sq) + var(--cm-sq-gap)) + var(--cm-sq) / 2);
  translate: -50% 0;
  display: inline-block;
  padding: 4px 10px;
  border-radius: 5px;
  background: var(--pill-none-bg);
  color: var(--muted);
  font-weight: 600;
  font-size: 12px;
  line-height: 1.35;
  white-space: nowrap;
  transition:
    opacity 320ms ease-out 260ms,
    transform 380ms var(--cm-ease) 260ms;
}

/* ── Earlier steps, as exceptions to the finished picture ──────── */

/* Steps 0 and 1: every reason an unknown slot until the line reaches
   its row (the script marks the row's people .is-read). */
[data-vis="committee"][data-step]:not([data-reached~="1"]) .cm-slot,
[data-vis="committee"][data-step="1"] .cm-p:not(.is-read) .cm-slot {
  opacity: 1;
}
[data-vis="committee"][data-step]:not([data-reached~="1"]) .cm-why,
[data-vis="committee"][data-step="1"] .cm-p:not(.is-read) .cm-why {
  color: transparent;
}
[data-vis="committee"][data-step]:not([data-reached~="1"]) .cm-why::before,
[data-vis="committee"][data-step="1"] .cm-p:not(.is-read) .cm-why::before {
  transform: scaleX(0);
}

/* Until person 5's turn in step 3 (the script marks the tool
   .is-noted): her place in Sales engagement is an ordinary empty
   place, with no initials, no hairline and no note. */
[data-vis="committee"][data-step]:not([data-reached~="4"]) .cm-tool:not(.is-noted) .cm-box.is-held {
  border-color: var(--rule-dark);
}
[data-vis="committee"][data-step]:not([data-reached~="4"]) .cm-tool:not(.is-noted) .cm-ghost {
  opacity: 0;
}
[data-vis="committee"][data-step]:not([data-reached~="4"]) .cm-tool:not(.is-noted) .cm-box.is-held::after {
  transform: scaleY(0);
}
[data-vis="committee"][data-step]:not([data-reached~="4"]) .cm-tool:not(.is-noted) .cm-note-pill {
  opacity: 0;
  transform: translateY(-4px);
}

/* The squares themselves are placed by the script while they travel
   (a transform from their place and an opacity), and are only ever
   hidden by it, so nothing here. */

/* ── Narrow: under 540px inside ────────────────────────────────── */

/* Every phone, and a stacked plate up to about 590px wide: the people
   in two columns, so every tag keeps the room to stay on one line where
   it can, and the tools one over the other, each tile as on a wide
   plate. A square bound for Sales engagement then drops on through the
   CRM, over its own square there: everyone passes through the CRM, and
   person 5 stops in it. */
@container (max-width: 539px) {
  /* A tile now has the plate's width, so its places can be larger. */
  [data-vis="committee"] .cm { --cm-sq: 38px; }
  [data-vis="committee"] .cm-people {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 18px;
  }
  [data-vis="committee"] .cm-tools {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 10px;
    margin-top: 28px;
  }
}

/* ── Phone ─────────────────────────────────────────────────────── */

@media (max-width: 520px) {
  [data-vis="committee"] {
    --cm-av: 40px;
    --cm-tp: 12px;
  }
  [data-vis="committee"] .cm-acct-name { font-size: 16.5px; }
  [data-vis="committee"] .cm-people { column-gap: 10px; row-gap: 16px; }
  [data-vis="committee"] .cm-tag { margin-top: 7px; }
  /* A long reason takes two balanced lines rather than being cut. */
  [data-vis="committee"] .cm-why {
    white-space: normal;
    text-wrap: balance;
    padding: 3px 8px;
  }
  [data-vis="committee"] .cm-places { margin-top: 10px; }
}


/* ════ PICTURE: Meeting Prep: the brief, one click from its source [data-vis="brief"] ════ */

/* ════ PICTURE: Meeting Prep: a brief where any fact opens to its source [data-vis="brief"] ════ */

/* The "brief" picture on /for-sales (Meeting Prep).

   The plate is the brief, built as the one on /what-we-build/briefing
   was (css/build.briefing.css, dropped 2026-10-05): a header on
   Surface 2 holding the account, its two bars, the meeting and the
   three tabs, then the open tab on Surface. Each fact is a claim over
   its kind of source, its date and a "Check it" link, the rows divided
   by hairlines (stacked rows take no colored side border). The real
   brief's "Leave alone" block is left out on purpose: the row's point
   is that every fact is dated and one click from its source, and a
   struck opening at the foot was a second message pulling against it.

   The one focal mark is fact 1's source, opened: a card standing proud
   of the list on a 1px Rule hairline, as /for-marketing's persona card
   does (no colored side border: that is a sourced line's mark, not a
   card's), the source's own words set large (28px on a laptop plate,
   nearly twice anything else on it) with the exact words the fact came
   from lit and set heavier, and beneath them where and when it was
   read: one sourced line in Mono behind the evidence row's 3px rule,
   Slate until the fact is checked, then Teal. When it opens, facts 2
   and 3 recede behind it (opacity only), as persona recedes its list
   behind its card.

   Steps (the markup with no data-step is the finished picture):
     0  the brief waits: header, tabs, "Open with" over three unknown
        fact slots (two Track lines each) and fact 1's source as an
        unknown slot (a faint Rule box inside the list's edges, a Track
        line under every line of words it will hold, the source line's
        rule Slate).
     1  the three facts arrive, each with its source and date.
     2  a drawn pointer travels to fact 1's "Check it" and clicks it.
     3  the source opens: the slot's box steps out to the card's edge
        (a transform), its words resolve out of their Track lines, the
        rest recedes, and the words the fact came from are lit on the
        Teal 14% ground, first in the source and then the same words in
        the claim, so the two are seen to match.
     4  fact 1 is marked Checked, and the source line's rule turns Teal.

   The card is laid out at its finished size on every step and only
   its box and words change, so the plate never changes height and no
   room waits empty anywhere on it.

   Teal only where something is checked: the account's dot (target
   now), the lit words, the Checked pill, the checked source line's
   rule, and the link that checks. No shadows, no gradients. The active
   tab is marked in Ink, not Teal, because a tab is not a confirmation.

   Type sizes are DESIGN.md's ramp: the quote 28px (the headline's
   floor) on plates 540px and up, 22px narrower, 19.5px on a phone,
   17.5px on the narrowest; claims 16.5px, the evidence row's claim.

   Do not set transition on the [data-vis] root: sales.css owns it for
   the fade between passes. */

[data-vis="brief"] {
  /* The plate is as tall as the brief. The header and the body carry
     their own padding, so the header's ground runs to the plate's edge
     as the real brief's does. */
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  --vis-pad: 0;
  --vis-pad-phone: 0;

  --brf-x: 26px;              /* side padding, header and body */
  --brf-proud: 14px;          /* how far the source card stands out of the list */
  --brf-slot: 0.956;          /* the slot's width as a share of the card's: inside the list's edges */
  --brf-q: 22px;              /* the quote's size (28px on plates 540px and up) */
  --brf-recede: 0.5;          /* the rest of the brief, behind the source */
  --brf-ease: cubic-bezier(0.22, 0.8, 0.24, 1);
}

[data-vis="brief"] .brf {
  position: relative;
  container-type: inline-size;
  min-width: 0;
}

/* ── The header ─────────────────────────────────────────────────── */

/* Account and bars on one line, the meeting under the name, the tabs
   along the foot. */
[data-vis="brief"] .brf-head {
  display: grid;
  grid-template-columns: 11px minmax(0, 1fr) auto;
  grid-template-areas:
    "dot  name scores"
    ".    meet meet"
    "tabs tabs tabs";
  column-gap: 11px;
  align-items: center;
  padding: 18px var(--brf-x) 0;
  background: var(--surface-2);
  border-bottom: 1px solid var(--rule);
}
[data-vis="brief"] .brf-dot {
  grid-area: dot;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--v-target);
}
[data-vis="brief"] .brf-name {
  grid-area: name;
  min-width: 0;
  font-family: var(--display);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.016em;
  line-height: 1.25;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
[data-vis="brief"] .brf-scores {
  grid-area: scores;
  display: flex;
  align-items: center;
  gap: 18px;
}
[data-vis="brief"] .brf-score {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
[data-vis="brief"] .brf-score-l {
  font-family: var(--display);
  font-weight: 600;
  font-size: 12px;
  color: var(--muted);
}
[data-vis="brief"] .brf-bar {
  position: relative;
  display: block;
  width: 52px;
  height: 5px;
  border-radius: 2px;
  background: var(--track);
  overflow: hidden;
}
[data-vis="brief"] .brf-bar i {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 2px;
  background: var(--score-ink);
}
[data-vis="brief"] .brf-meeting {
  grid-area: meet;
  margin-top: 3px;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
  color: var(--muted);
}

/* The tab strip. The first tab's word starts at the dot's edge; the
   open tab is Ink on an Ink rule that sits on the header's hairline. */
[data-vis="brief"] .brf-tabs {
  grid-area: tabs;
  display: flex;
  margin: 10px 0 0 -12px;
  min-width: 0;
}
[data-vis="brief"] .brf-tab {
  flex: none;
  padding: 9px 12px 10px;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font-family: var(--display);
  font-weight: 600;
  font-size: 13.5px;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--muted);
  white-space: nowrap;
}
[data-vis="brief"] .brf-tab.is-on {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

/* ── The open tab ───────────────────────────────────────────────── */

[data-vis="brief"] .brf-body {
  padding: 15px var(--brf-x) 12px;
}

/* Part labels: Micro, Muted. */
[data-vis="brief"] .brf-label {
  display: block;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--muted);
}

[data-vis="brief"] .brf-facts {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
}
[data-vis="brief"] .brf-fact {
  position: relative;
  padding: 10px 0 11px;
  border-top: 1px solid var(--rule);
}
[data-vis="brief"] .brf-fact:first-child { border-top: 0; padding-top: 6px; padding-bottom: 14px; }

/* Facts 2 and 3 recede behind the opened source. */
[data-vis="brief"] .brf-fact:not(:first-child) {
  opacity: var(--brf-recede);
  transition: opacity 480ms ease 160ms;
}

[data-vis="brief"] .brf-fact-text { position: relative; }

/* The claim, with the Checked pill hard right on fact 1. The line
   wraps, so on a narrow plate the pill drops under the claim rather
   than running into it. */
[data-vis="brief"] .brf-claim-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 5px 14px;
  min-height: 22px;
}
[data-vis="brief"] .brf-claim {
  min-width: 0;
  isolation: isolate;
  font-family: var(--display);
  font-weight: 500;
  font-size: 16.5px;
  letter-spacing: -0.012em;
  line-height: 1.3;
  color: var(--ink);
}

/* The Checked pill: the 12px status pill, confirmed, with a drawn
   check. */
[data-vis="brief"] .brf-checked {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 8px 4px 7px;
  border-radius: 5px;
  background: var(--pill-yes-bg);
  color: var(--teal-deep);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
}
[data-vis="brief"] .brf-checked svg { display: block; overflow: visible; }
[data-vis="brief"] .brf-checked path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}

/* Beneath the claim: the kind of source, its date in a Mono chip, and
   the link that opens it. */
[data-vis="brief"] .brf-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 9px;
  margin-top: 4px;
  font-size: 13px;
  line-height: 1.35;
}
[data-vis="brief"] .brf-src { color: var(--muted); }
[data-vis="brief"] .brf-date {
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--pill-none-bg);
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
  color: var(--body);
}
/* Drawn, not a real link: Teal Deep, as "Check it" is on the real
   brief. Padded into its own margin so the press ground has room
   without moving anything. */
[data-vis="brief"] .brf-check {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  margin: -2px -5px;
  padding: 2px 5px;
  border-radius: 5px;
  font-weight: 600;
  color: var(--teal-deep);
  white-space: nowrap;
}
[data-vis="brief"] .brf-arrow {
  display: inline-block;
  font-size: 12px;
  transition: transform 320ms var(--brf-ease);
}
/* The link that was used: underlined, and its arrow turned to point
   down into the source it opened. */
[data-vis="brief"] [data-fact="1"] .brf-check-t {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: currentColor;
  transition: text-decoration-color 220ms ease;
}
[data-vis="brief"] [data-fact="1"] .brf-arrow { transform: rotate(135deg); }

/* ── The source, opened: the focal mark ─────────────────────────── */

/* Laid out at its finished size on every step. Its card is drawn by
   ::before, so the box can step out to the card's edge as it opens (a
   horizontal scale, from inside the list's edges) without the words
   inside reflowing. A plain 1px Rule card, as persona's on
   /for-marketing: the checked state is carried by the source line's
   rule below and the Checked pill, never by a colored side of the
   card. */
[data-vis="brief"] .brf-source {
  position: relative;
  isolation: isolate;
  display: block;
  margin: 14px calc(var(--brf-proud) * -1) 0;
  padding: 20px 26px 20px 28px;
}
[data-vis="brief"] .brf-source::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 0;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--surface);
  transition: transform 560ms var(--brf-ease);
}

/* The source's own words. The opening quote mark hangs into the
   card's margin (set apart in the partial, out of the flow), so the
   words of every line start on one edge, and the slot's Track lines
   start there too. */
[data-vis="brief"] .brf-quote {
  position: relative;
  display: block;
  isolation: isolate;
  /* Balanced, so no word is left alone on the last line. */
  text-wrap: balance;
  font-family: var(--text);
  font-size: var(--brf-q);
  font-weight: 400;
  letter-spacing: -0.016em;
  line-height: 1.36;
  color: var(--body);
  /* The Track line each line of words sits on while the source is
     unknown (transparent once it is read). */
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 0.3em;
  text-underline-offset: -0.42em;
  text-decoration-skip-ink: none;
  transition:
    color 360ms ease 140ms,
    text-decoration-color 260ms ease;
}
[data-vis="brief"] .brf-qo {
  position: absolute;
  top: 0;
  right: 100%;
}
/* Where and when the source was read: one sourced line on a 1px
   hairline, as /for-marketing's abm picture sets its citations (Slate
   until the fact is checked, then Teal), its words indented behind it. */
[data-vis="brief"] .brf-cite {
  display: block;
  margin-top: 12px;
  padding-left: 13px;
  border-left: 1px solid var(--teal);
  font-family: var(--mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 4px;
  text-underline-offset: -0.5em;
  text-decoration-skip-ink: none;
  transition:
    color 320ms ease 300ms,
    text-decoration-color 260ms ease 160ms,
    border-color 360ms ease;
}

/* The exact words the fact came from, lit as /for-marketing's persona
   picture lights its keywords: Ink on the Teal 14% ground, first in the
   source and then the same words in fact 1's claim, so the two are seen
   to match. The ground overhangs by 2px, under a word space at these
   sizes, so the words either side keep their gap. */
[data-vis="brief"] .brf-mark {
  position: relative;
  white-space: nowrap;
  color: var(--ink);
  transition: color 300ms ease 700ms;
}
/* In the source the lit words are also set heavier: they are the
   picture's focal mark, and read from across the room. */
[data-vis="brief"] .brf-quote .brf-mark { font-weight: 600; }
[data-vis="brief"] .brf-mark::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: -3px;
  right: -3px;
  top: 0.08em;
  bottom: 0.02em;
  border-radius: 3px;
  background: var(--pill-yes-bg);
  transform-origin: 0 50%;
  transition: transform 520ms var(--brf-ease) 700ms;
}
[data-vis="brief"] .brf-mark-claim { color: inherit; transition: none; }
[data-vis="brief"] .brf-mark-claim::before {
  left: -2px;
  right: -2px;
  top: 0.1em;
  bottom: 0.04em;
  border-radius: 3px;
  transition-delay: 1150ms;
}

/* An unknown fact: Track lines where the words will be. Hidden on the
   finished picture. */
[data-vis="brief"] .brf-skel {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: 22px 1fr;
  align-items: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}
[data-vis="brief"] .brf-skel i {
  display: block;
  height: 5px;
  width: 44%;
  border-radius: 2px;
  background: var(--track);
}
[data-vis="brief"] .brf-skel i + i { width: 30%; height: 4px; }
[data-vis="brief"] [data-fact="2"] .brf-skel i { width: 62%; }
[data-vis="brief"] [data-fact="2"] .brf-skel i + i { width: 33%; }
[data-vis="brief"] [data-fact="3"] .brf-skel i { width: 56%; }
[data-vis="brief"] [data-fact="3"] .brf-skel i + i { width: 31%; }

/* ── The pointer ────────────────────────────────────────────────── */

/* A plain Ink arrow with a white edge so it reads over type. The
   script places and moves the outer span; the arrow fades and presses
   by CSS. Never on the finished picture. */
[data-vis="brief"] .brf-ptr {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 5;
  width: 16px;
  height: 22px;
  pointer-events: none;
}
[data-vis="brief"] .brf-ptr svg {
  display: block;
  overflow: visible;
  opacity: 0;
  transition: opacity 300ms ease 260ms;
}
[data-vis="brief"] .brf-ptr-shape {
  fill: var(--ink);
  stroke: var(--surface);
  stroke-width: 1.3;
  stroke-linejoin: round;
  transform-box: fill-box;
  transform-origin: 0 0;
}
[data-vis="brief"][data-reached~="2"]:not([data-reached~="3"]) .brf-ptr svg {
  opacity: 1;
  transition: opacity 220ms ease;
}

/* ── Earlier steps, as exceptions to the finished picture ───────── */

/* Before step 1: every fact unknown. */
[data-vis="brief"][data-step]:not([data-reached~="1"]) .brf-skel { opacity: 1; }
[data-vis="brief"][data-step]:not([data-reached~="1"]) .brf-claim-line,
[data-vis="brief"][data-step]:not([data-reached~="1"]) .brf-meta {
  opacity: 0;
  transform: translateX(-6px);
}

/* Step 1: the facts land one after another, each claim a beat ahead
   of its source and date. */
[data-vis="brief"] .brf-claim-line,
[data-vis="brief"] .brf-meta {
  transition: opacity 380ms ease, transform 420ms var(--brf-ease);
}
[data-vis="brief"][data-reached~="1"] [data-fact="1"] .brf-skel { transition-delay: 0ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="1"] .brf-claim-line { transition-delay: 40ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="1"] .brf-meta { transition-delay: 170ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="2"] .brf-skel { transition-delay: 300ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="2"] .brf-claim-line { transition-delay: 340ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="2"] .brf-meta { transition-delay: 470ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="3"] .brf-skel { transition-delay: 600ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="3"] .brf-claim-line { transition-delay: 640ms; }
[data-vis="brief"][data-reached~="1"] [data-fact="3"] .brf-meta { transition-delay: 770ms; }

/* Step 2: the click. The link takes the press ground as the arrow
   presses, then lets go. */
@keyframes brf-press {
  0% { transform: scale(1); }
  40% { transform: scale(0.84); }
  100% { transform: scale(1); }
}
@keyframes brf-link-press {
  0% { background-color: rgba(0, 168, 138, 0); }
  30%, 55% { background-color: var(--pill-yes-bg); }
  100% { background-color: rgba(0, 168, 138, 0); }
}
[data-vis="brief"][data-reached~="2"]:not([data-reached~="3"]) .brf-ptr-shape {
  animation: brf-press 240ms ease 940ms both;
}
[data-vis="brief"][data-reached~="2"]:not([data-reached~="3"]) [data-fact="1"] .brf-check {
  animation: brf-link-press 470ms ease 950ms both;
}

/* Before step 3: the link unused; the source an unknown slot, its box
   drawn in from the card's edges to the list's, a Track line under
   every line of the words it will hold (the words themselves clear),
   nothing lit; and nothing receded yet. */
[data-vis="brief"][data-step]:not([data-reached~="3"]) [data-fact="1"] .brf-check-t { text-decoration-color: transparent; }
[data-vis="brief"][data-step]:not([data-reached~="3"]) [data-fact="1"] .brf-arrow { transform: none; }
[data-vis="brief"][data-step]:not([data-reached~="3"]) .brf-source::before {
  transform: scaleX(var(--brf-slot));
}
[data-vis="brief"][data-step]:not([data-reached~="3"]) .brf-quote,
[data-vis="brief"][data-step]:not([data-reached~="3"]) .brf-cite,
[data-vis="brief"][data-step]:not([data-reached~="3"]) .brf-quote .brf-mark {
  color: transparent;
  text-decoration-color: var(--track);
  transition: none;
}
[data-vis="brief"][data-step]:not([data-reached~="3"]) .brf-mark::before { transform: scaleX(0); transition: none; }
/* As the source opens, the words to be lit arrive with the rest of the
   quote, in Body, and turn Ink as their ground sweeps in, so the quote
   never shows a gap where they will be. */
@keyframes brf-mark-in {
  0%, 14% { color: transparent; }
  50%, 70% { color: var(--body); }
  100% { color: var(--ink); }
}
[data-vis="brief"][data-step][data-reached~="3"] .brf-quote .brf-mark {
  animation: brf-mark-in 1000ms linear both;
}
[data-vis="brief"][data-step]:not([data-reached~="3"]) .brf-fact:not(:first-child) {
  opacity: 1;
  transition: opacity 300ms ease;
}

/* Before step 4: not yet checked. */
[data-vis="brief"] .brf-checked {
  transition: opacity 300ms ease, transform 420ms var(--brf-ease);
}
[data-vis="brief"] .brf-checked path { transition: stroke-dashoffset 380ms ease 240ms; }
[data-vis="brief"][data-step]:not([data-reached~="4"]) .brf-checked {
  opacity: 0;
  transform: translateX(-8px);
}
[data-vis="brief"][data-step]:not([data-reached~="4"]) .brf-checked path {
  stroke-dashoffset: 1;
  transition: none;
}
[data-vis="brief"][data-step]:not([data-reached~="4"]) .brf-cite { border-left-color: var(--slate); }

/* ── Wider and narrower plates ──────────────────────────────────── */

/* Every laptop and tablet plate (about 540 to 775px): the quote at its
   full size, still two balanced lines. Narrower plates (a stacked plate
   on a small tablet) keep the 22px default. */
@container (min-width: 540px) {
  [data-vis="brief"] .brf-body { --brf-q: 28px; }
}

/* A phone. The bars drop under the meeting line, the tabs set smaller
   so all three still fit, and the claims and the quote step down (the
   quote still the largest type on the plate). */
@container (max-width: 440px) {
  /* Set on the container's children: a container query cannot style
     the container itself. */
  [data-vis="brief"] .brf-head,
  [data-vis="brief"] .brf-body {
    --brf-x: 16px;
    --brf-proud: 8px;
    --brf-slot: 0.95;
    --brf-q: 19.5px;
  }
  [data-vis="brief"] .brf-head {
    grid-template-columns: 10px minmax(0, 1fr);
    grid-template-areas:
      "dot  name"
      ".    meet"
      ".    scores"
      "tabs tabs";
    column-gap: 10px;
    padding-top: 17px;
  }
  [data-vis="brief"] .brf-dot { width: 10px; height: 10px; }
  [data-vis="brief"] .brf-name { font-size: 16.5px; }
  [data-vis="brief"] .brf-scores { margin-top: 9px; gap: 16px; }
  [data-vis="brief"] .brf-bar { width: 48px; }
  [data-vis="brief"] .brf-tabs { margin: 10px 0 0 -9px; }
  [data-vis="brief"] .brf-tab { padding: 8px 9px 9px; font-size: 13px; }
  [data-vis="brief"] .brf-body { padding: 14px var(--brf-x) 10px; }
  [data-vis="brief"] .brf-claim { font-size: 15.5px; }
  [data-vis="brief"] .brf-meta { gap: 4px 8px; }
  [data-vis="brief"] .brf-source { margin-top: 12px; padding: 15px 15px 15px 19px; }
  [data-vis="brief"] .brf-quote { line-height: 1.4; }
  [data-vis="brief"] .brf-cite { margin-top: 9px; font-size: 12px; }
}

/* The narrowest phones (a plate under about 300px): the tabs close up
   so all three still sit on one line. */
@container (max-width: 300px) {
  [data-vis="brief"] .brf-head,
  [data-vis="brief"] .brf-body { --brf-x: 14px; --brf-slot: 0.94; }
  [data-vis="brief"] .brf-meeting { letter-spacing: 0; }
  [data-vis="brief"] .brf-tabs { margin-left: -7px; }
  [data-vis="brief"] .brf-tab { padding: 8px 7px 9px; font-size: 12px; letter-spacing: -0.015em; }
  [data-vis="brief"] .brf-quote { --brf-q: 17.5px; }
}


/* ════ PICTURE: Sales Enablement & Coaching 1: one standard, two guides [data-vis="standard"] ════ */

/* ════ PICTURE: Sales Enablement & Coaching 1: one standard [data-vis="standard"] ════ */

/* The standard picture on /for-sales (Sales Enablement & Coaching,
   point 1), the first picture on the Ink band, beside "Turn it into ICP
   and persona guides that reflect everyone's knowledge combined, backed
   by your real customers".

   Two tiers, cause above payoff:
   - the cause, across the top and drawn small: six people (rounded
     squares with initials, 6px radius, on the neutral pill ground, never
     circles: a circle is an account), each with their function as a
     Micro label, on the left; the customer data on the right, drawn as a
     small table so it is neither a person nor an account; and their
     hairlines meeting between them in one Surface 2 card, "Your
     standard", confirmed by the 12px status pill.
   - the payoff and the plate's one focal point, at full width and the
     largest type on the plate: the card dividing into the two guide
     pages, white on a hairline, each titled at Title Card size (Outfit
     700, 22px) and written out in full at Support size (15.5px). The
     ICP guide lists the four traits, each ticked in Teal once checked,
     so its column of ticks is the mark that reads from across the room;
     the Persona guide gives two personas and what each cares about. Nothing else on the plate is
     above 17px, and nothing is printed twice: the 212 customers are on
     the card's pill only.

   Wide plates (540px of content and up: every side-by-side plate, down
   to 557px at a 1041 viewport, and stacked plates from about 590px) set
   the top as one row, people, card, data, with the hairlines as two
   server-rendered SVGs at exact pixel coordinates (the row heights they
   rely on come from the custom properties the partial sets on .st).
   Narrower plates read the top
   downward: the people in a grid, the data under them, a bracket
   gathering both into the card. On a phone the two guides stack, joined
   to the card by one line down their left side.

   Steps (timings in the standard section of js/sales.js):
     0  the inputs present; the card and the guides faint, the guides'
        lines waiting as Track lines
     1  the hairlines draw from the people into the card
     2  the card's line reaches the ICP guide, and trait 1 is written in;
        the people it came from, their hairlines and the line through the
        card are ringed in Ink (a selection) while it lands
     3  trait 2, the same
     4  trait 3, the same
     5  trait 4, the same
     6  the customer data's hairline draws and it is ringed; the read line
        passes down the ICP guide, ticking each trait as it crosses it,
        then "Checked against 212 customers" lands on the card
     7  the card's line reaches the Persona guide, and its two personas
        are written in; hold
   No data-step is the finished picture (also no script and reduced
   motion). Every selector is scoped under [data-vis="standard"]; the
   root's own transition belongs to sales.css (the fade between passes,
   which on the Ink band fades only what is drawn here). */

[data-vis="standard"] {
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  container-type: inline-size;

  --st-wire: #C9CED2;                     /* a hairline at rest */
  --st-sel: rgba(17, 22, 27, 0.7);        /* a selection, Ink at 70% */
  --st-ease: cubic-bezier(0.22, 0.7, 0.3, 1);
  --st-gap: 12px;                         /* between the two guides */
  /* The ICP guide's share of the guides' width: its traits are the
     longest lines on the plate, so it is a little wider (1.13 to 1),
     enough at 1440 for every trait and persona to sit on one line.
     The fork's arms land on each guide's middle from these shares;
     the guides' grid repeats them as fr, so change the two together. */
  --st-icp: 1.13;
  --st-per: 1;
}

[data-vis="standard"] .st {
  display: flex;
  flex-direction: column;
}

/* Shared type: Micro part labels, Mono counts. */
[data-vis="standard"] .st-in-head,
[data-vis="standard"] .st-fn,
[data-vis="standard"] .st-data-l {
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  line-height: 16px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ── The cause, wide: people, card, data in one row ─────────────── */

/* The people and the data share the outer columns equally, so the card
   sits on the plate's centre line and the fork below it is symmetric.
   The label row is its own row, so the card is centred on the people's
   rows, where the hairlines meet. */
[data-vis="standard"] .st-top {
  display: grid;
  grid-template-columns:
    minmax(116px, 1fr) var(--st-fan) minmax(244px, 272px) var(--st-wire-w) minmax(116px, 1fr);
  grid-template-rows: var(--st-head) var(--st-rows);
}
[data-vis="standard"] .st-in-head {
  grid-column: 1;
  grid-row: 1;
  align-self: start;
  text-align: right;
}
[data-vis="standard"] .st-people {
  grid-column: 1;
  grid-row: 2;
  list-style: none;
  margin: 0;
  padding: 0;
}
[data-vis="standard"] .st-fan { grid-column: 2; grid-row: 2; }
[data-vis="standard"] .st-hubcol { grid-column: 3; grid-row: 2; }
[data-vis="standard"] .st-dwire { grid-column: 4; grid-row: 2; }
[data-vis="standard"] .st-data { grid-column: 5; grid-row: 2; }
[data-vis="standard"] .st-gather { display: none; }

/* Each person faces the card: label, then the square at the column's
   inner edge, where the hairline leaves it. */
[data-vis="standard"] .st-p {
  height: var(--st-row);
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-start;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
[data-vis="standard"] .st-fn {
  white-space: nowrap;
  transition: color 200ms ease;
}

/* People: initials on the neutral pill ground, 6px radius. A selection
   is ringed in Ink at 70%, 1.4px, as /for-marketing's chat rings one. */
[data-vis="standard"] .st-av {
  flex: none;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  background: var(--pill-none-bg);
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 1;
  color: var(--body);
  outline: 1.4px solid transparent;
  outline-offset: 2px;
  transition: outline-color 200ms ease;
}

/* The hairlines, wide. */
[data-vis="standard"] .st-wires {
  display: block;
  overflow: visible;
}
[data-vis="standard"] .st-w {
  fill: none;
  stroke: var(--st-wire);
  stroke-width: 1;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  transition:
    stroke 200ms ease,
    stroke-dashoffset 620ms var(--st-ease) calc(var(--n, 0) * 45ms);
}

/* The card's column: the card centred on the people's rows, and under
   it the start of the line down to the guides. */
[data-vis="standard"] .st-hubcol {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
[data-vis="standard"] .st-hubcol::before { content: ""; flex: 1; }
[data-vis="standard"] .st-stem {
  flex: 1;
  display: block;
  width: 1px;
  margin: 0 auto;
  background: var(--st-wire);
  transform-origin: top center;
  transition: transform 200ms ease-out, background-color 200ms ease;
}

/* ── The standard: one card ─────────────────────────────────────── */

[data-vis="standard"] .st-hub {
  box-sizing: border-box;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 14px 13px 15px;
  background: var(--surface-2);
  border: 1px solid var(--rule);
  border-radius: 12px;
  text-align: center;
  transition: opacity 420ms ease;
}
[data-vis="standard"] .st-title {
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
  line-height: 1.25;
  letter-spacing: -0.016em;
  color: var(--ink);
}
[data-vis="standard"] .st-ok {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 4px 10px 4px 8px;
  border-radius: 5px;
  background: var(--pill-yes-bg);
  color: var(--teal-deep);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
  text-align: left;
  transition: opacity 320ms ease 1620ms, transform 420ms var(--st-ease) 1620ms;
}
[data-vis="standard"] .st-ok svg {
  flex: none;
  width: 12px;
  height: 12px;
  fill: none;
  stroke: var(--teal-deep);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── The customer data ──────────────────────────────────────────── */

/* Wide: the table at the column's inner edge, on the card's centre line
   where its hairline meets it, with its label hanging under it so it
   does not move the table off that line. The count is not printed here:
   the card's pill says it, at the moment the data is checked. */
[data-vis="standard"] .st-data {
  position: relative;
  align-self: center;
  justify-self: start;
  display: block;
}
[data-vis="standard"] .st-data-g {
  display: block;
  overflow: visible;
  border-radius: 5px;
  outline: 1.4px solid transparent;
  outline-offset: 2px;
  transition: outline-color 200ms ease;
}
/* Drawn in the people's register, not heavier: a Muted frame, a header
   row and cells in Rule hairline gray. Neutral throughout, because Slate
   means ruled out or unread and this is neither. */
[data-vis="standard"] .st-tb-frame { fill: var(--surface); stroke: var(--muted); stroke-width: 1; }
[data-vis="standard"] .st-tb-head { fill: var(--rule); }
[data-vis="standard"] .st-tb-rule { fill: none; stroke: var(--rule); stroke-width: 1; }
[data-vis="standard"] .st-data-l {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  white-space: nowrap;
  transition: color 200ms ease;
}

/* ── The fork: the card dividing into the two guides ────────────── */

/* Three hairline pieces, a stem and two arms, so it draws in the flow's
   direction: down out of the card, then out to the middle of each
   guide. The arms turn just under the inputs and drop well clear of
   the guides' top edges (16px straight after the turn), so the fork
   reads as one line dividing in two, not as the edge of a card behind
   the guides. */
[data-vis="standard"] .st-split {
  position: relative;
  height: 32px;
}
[data-vis="standard"] .st-split i,
[data-vis="standard"] .st-gather i {
  position: absolute;
  display: block;
  box-sizing: border-box;
  border: 0 solid var(--st-wire);
}
[data-vis="standard"] .st-split .st-bs {
  left: calc(50% - 0.5px);
  top: 0;
  height: 7px;
  width: 1px;
  background: var(--st-wire);
  transform-origin: top center;
  transition: transform 100ms linear 180ms, background-color 200ms ease;
}
[data-vis="standard"] .st-split .st-bl,
[data-vis="standard"] .st-split .st-br {
  top: 6px;
  bottom: 0;
  border-top-width: 1px;
  clip-path: inset(0 0 0 0);
}
[data-vis="standard"] .st-split .st-bl {
  left: calc((100% - var(--st-gap)) * var(--st-icp) / (var(--st-icp) + var(--st-per)) / 2);
  right: 50%;
  border-left-width: 1px;
  border-top-left-radius: 8px;
  transition: clip-path 360ms var(--st-ease) 280ms, border-color 200ms ease;
}
[data-vis="standard"] .st-split .st-br {
  left: 50%;
  right: calc((100% - var(--st-gap)) * var(--st-per) / (var(--st-icp) + var(--st-per)) / 2);
  border-right-width: 1px;
  border-top-right-radius: 8px;
  transition: clip-path 380ms var(--st-ease), border-color 200ms ease;
}

/* ── The payoff: the two guides ─────────────────────────────────── */

[data-vis="standard"] .st-out {
  display: grid;
  /* 1.13 to 1: --st-icp and --st-per above (fr cannot be calculated). */
  grid-template-columns: minmax(0, 1.13fr) minmax(0, 1fr);
  column-gap: var(--st-gap);
  align-items: stretch;
}
[data-vis="standard"] .st-g {
  position: relative;
  box-sizing: border-box;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 12px;
  padding: var(--st-g-pad-t) var(--st-g-pad-x) var(--st-g-pad-b);
  transition: opacity 360ms ease;
}
/* The guides' measures, here so the medium and phone plates change them
   in one place. The read line's band runs to the page's edges, so it
   reads them too. */
[data-vis="standard"] .st {
  --st-g-pad-t: 19px;
  --st-g-pad-x: 18px;
  --st-g-pad-b: 21px;
  --st-g-title: 22px;
  --st-g-text: 15.5px;
  --st-g-lh: 22px;
  --st-g-box: 18px;
}
/* The title, at Title Card size (Outfit 700, 22px): the largest type on
   the plate, so the guides read first and still read when the plate is
   seen small. */
[data-vis="standard"] .st-g-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: var(--st-g-title);
  line-height: 1.1;
  letter-spacing: -0.022em;
  color: var(--ink);
}
[data-vis="standard"] .st-g-body {
  position: relative;
  margin-top: 15px;
}
[data-vis="standard"] .st-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 11px;
}

/* A line waiting to be written: a Track line about as long as its text,
   in the same cell, as the filter's trait card waits. */
[data-vis="standard"] .st-skel {
  grid-column: 2;
  grid-row: 1;
  align-self: center;
  display: grid;
  gap: 9px;
  opacity: 0;
  transition: opacity 200ms ease;
}
[data-vis="standard"] .st-skel i {
  display: block;
  width: var(--w);
  height: 6px;
  border-radius: 3px;
  background: var(--track);
}

/* The ICP guide: four traits, each with its box. */
[data-vis="standard"] .st-r {
  display: grid;
  grid-template-columns: var(--st-g-box) minmax(0, 1fr);
  column-gap: 10px;
  align-items: start;
}
[data-vis="standard"] .st-r-text {
  grid-column: 2;
  grid-row: 1;
  font-size: var(--st-g-text);
  font-weight: 500;
  line-height: var(--st-g-lh);
  color: var(--ink);
  text-wrap: pretty;
  transition: opacity 380ms ease 160ms, transform 460ms var(--st-ease) 160ms;
}

/* The box: ticked in Teal on a Teal 14% ground once checked. The check
   is a mark, not type, so it is plain Teal. */
[data-vis="standard"] .st-box {
  box-sizing: border-box;
  grid-column: 1;
  grid-row: 1;
  margin-top: calc((var(--st-g-lh) - var(--st-g-box)) / 2);
  width: var(--st-g-box);
  height: var(--st-g-box);
  border-radius: 5px;
  border: 1.3px solid transparent;
  background: var(--pill-yes-bg);
  display: grid;
  place-items: center;
  transition:
    opacity 320ms ease 160ms, transform 380ms var(--st-ease) 160ms,
    background-color 220ms ease calc(560ms + var(--k) * 295ms),
    border-color 220ms ease calc(560ms + var(--k) * 295ms);
}
[data-vis="standard"] .st-box svg {
  display: block;
  width: var(--st-g-box);
  height: var(--st-g-box);
  margin: -1.3px;
  fill: none;
  stroke: var(--teal);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
[data-vis="standard"] .st-box path {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 260ms ease-out calc(590ms + var(--k) * 295ms);
}

/* The read line: 1.6px Teal at 85% with its flat 38px band of Teal at
   8% trailing it, moving down the traits. Shown only while it moves. */
[data-vis="standard"] .st-read {
  position: absolute;
  left: calc(var(--st-g-pad-x) * -1);
  right: calc(var(--st-g-pad-x) * -1);
  top: 0;
  height: 38px;
  transform: translateY(-100%);
  background: rgba(0, 168, 138, 0.08);
  border-bottom: 1.6px solid rgba(0, 168, 138, 0.85);
  opacity: 0;
  pointer-events: none;
}

/* The Persona guide: two personas, each over what they care about. */
[data-vis="standard"] .st-g-per .st-rows { gap: 14px; }
[data-vis="standard"] .st-pr {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  transition: opacity 300ms ease;
}
[data-vis="standard"] .st-pr-text {
  grid-column: 1;
  grid-row: 1;
  display: grid;
  gap: 2px;
  transition: opacity 360ms ease calc(300ms + var(--j) * 240ms), transform 440ms var(--st-ease) calc(300ms + var(--j) * 240ms);
}
[data-vis="standard"] .st-pr-name {
  font-size: var(--st-g-text);
  font-weight: 600;
  line-height: var(--st-g-lh);
  color: var(--ink);
}
[data-vis="standard"] .st-pr-line {
  font-size: var(--st-g-text);
  font-weight: 400;
  line-height: var(--st-g-lh);
  color: var(--body);
  text-wrap: pretty;
}
[data-vis="standard"] .st-skel-2 {
  grid-column: 1;
  gap: 13px;
}

/* ── Narrower side-by-side guides: a size down ─────────────────── */

/* Under 620px of content (laptop plates from about 1041 to 1150, and
   every stacked plate under about 670px) the guides step down to Caption
   size (14.5px) on a 16px inset, which keeps every trait and persona on
   one line down to about 580px of content (1100). The phone sets its
   own measures below. */
@container (max-width: 619px) {
  [data-vis="standard"] .st {
    --st-g-pad-t: 16px;
    --st-g-pad-x: 16px;
    --st-g-pad-b: 18px;
    --st-g-text: 14.5px;
    --st-g-lh: 20px;
    --st-g-box: 16px;
  }
}

/* ── Medium: the top reads downward ─────────────────────────────── */

/* Under 540px of content (stacked plates under about 590px) the people,
   card and data no longer fit in one row. The people go into a grid, the
   data under them, and a bracket gathers both into the card, which
   still divides into the two guides side by side. */
@container (max-width: 539px) {
  [data-vis="standard"] .st-top {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }
  [data-vis="standard"] .st-in-head { order: 0; text-align: left; margin-bottom: 4px; }
  [data-vis="standard"] .st-people {
    order: 1;
    display: grid;
    grid-template-columns: repeat(3, max-content);
    justify-content: space-between;
    column-gap: 14px;
  }
  [data-vis="standard"] .st-p { flex-direction: row; height: 30px; }
  [data-vis="standard"] .st-data {
    order: 2;
    align-self: stretch;
    margin-top: 8px;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  [data-vis="standard"] .st-data-g { flex: none; }
  [data-vis="standard"] .st-data-l { position: static; }

  [data-vis="standard"] .st-gather { order: 3; }
  [data-vis="standard"] .st-hubcol { order: 4; }
  [data-vis="standard"] .st-wires,
  [data-vis="standard"] .st-stem,
  [data-vis="standard"] .st-hubcol::before { display: none; }

  [data-vis="standard"] .st-hub {
    align-self: center;
    width: 100%;
    max-width: 330px;
  }

  /* Gathering: arms from both ends of the inputs into the middle, then
     the stem down into the card. The left arm drops from under the
     middle of the customer data's table (13px in), so at step 6 it can
     carry the data into the card the way the data's own hairline does on
     a wide plate. */
  [data-vis="standard"] .st-gather {
    display: block;
    position: relative;
    height: 28px;
    margin-top: 10px;
  }
  [data-vis="standard"] .st-gather .st-bl,
  [data-vis="standard"] .st-gather .st-br {
    top: 0;
    height: 12px;
    width: calc(50% - 13px);
    border-bottom-width: 1px;
    clip-path: inset(0 0 0 0);
    transition: clip-path 420ms var(--st-ease), border-color 200ms ease;
  }
  [data-vis="standard"] .st-gather .st-bl {
    left: 13px;
    border-left-width: 1px;
    border-bottom-left-radius: 8px;
  }
  [data-vis="standard"] .st-gather .st-br {
    right: 13px;
    border-right-width: 1px;
    border-bottom-right-radius: 8px;
  }
  [data-vis="standard"] .st-gather .st-bs {
    left: calc(50% - 0.5px);
    top: 11px;
    bottom: 0;
    width: 1px;
    background: var(--st-wire);
    transform-origin: top center;
    transition: transform 260ms ease-out 360ms, background-color 200ms ease;
  }
}

/* ── Phone: the guides stack ─────────────────────────────────────── */

/* Under 430px of content (a phone) the guides would be too narrow side
   by side to hold their traits, so they stack at full width, set in
   from the left, and the card's line runs down their left side with a
   branch into each, so it still reads as one card dividing in two. The
   people go two to a row. The measures are set on .st, not on the
   picture's root: the root is the container this query measures, and a
   container query cannot style its own container. */
@container (max-width: 429px) {
  [data-vis="standard"] .st {
    --st-in: 16px;                       /* the guides' indent */
    --st-spine: 6px;                     /* where the line runs */
    --st-g-pad-t: 15px;
    --st-g-pad-x: 15px;
    --st-g-pad-b: 17px;
    --st-g-title: 22px;
    --st-g-text: 15.5px;
    --st-g-lh: 22px;
    --st-g-box: 17px;
    /* A branch meets a guide at its title's middle. */
    --st-branch: calc(var(--st-g-pad-t) + var(--st-g-title) * 0.55);
  }
  [data-vis="standard"] .st-people {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 12px;
  }
  [data-vis="standard"] .st-hub { max-width: none; }

  [data-vis="standard"] .st-out {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 12px;
    padding-left: var(--st-in);
  }

  /* The line out of the card: down from its middle, left to the spine,
     then down beside the guides. */
  [data-vis="standard"] .st-split { height: 20px; }
  [data-vis="standard"] .st-split .st-bs { display: none; }
  [data-vis="standard"] .st-split .st-bl {
    left: calc(var(--st-spine) + 9px);
    right: calc(50% - 0.5px);
    top: 0;
    bottom: auto;
    height: 10px;
    border-top-width: 0;
    border-left-width: 0;
    border-right-width: 1px;
    border-bottom-width: 1px;
    border-top-left-radius: 0;
    border-bottom-right-radius: 8px;
    transition: clip-path 240ms linear 120ms, border-color 200ms ease;
  }
  [data-vis="standard"] .st-split .st-br {
    left: var(--st-spine);
    right: auto;
    width: 10px;
    top: 9px;
    bottom: 0;
    border-right-width: 0;
    border-left-width: 1px;
    border-top-width: 1px;
    border-top-right-radius: 0;
    border-top-left-radius: 8px;
    transition: clip-path 140ms linear 360ms, border-color 200ms ease;
  }

  /* The spine beside the guides, and a branch into each, drawn on the
     guides themselves so they meet the pages wherever they end. */
  [data-vis="standard"] .st-g-icp::before,
  [data-vis="standard"] .st-g-icp::after,
  [data-vis="standard"] .st-g-per::before {
    content: "";
    position: absolute;
    box-sizing: border-box;
    border: 0 solid var(--st-wire);
    pointer-events: none;
  }
  /* Through the ICP guide's edge and on, past it, to the Persona guide. */
  [data-vis="standard"] .st-g-icp::before {
    left: calc(var(--st-spine) - var(--st-in) - 1px);
    top: -1px;
    bottom: -13px;
    width: 1px;
    border-left-width: 1px;
    clip-path: inset(0 0 0 0);
    transition: clip-path 260ms linear, border-color 200ms ease;
  }
  [data-vis="standard"] .st-g-icp::after {
    left: calc(var(--st-spine) - var(--st-in) - 1px);
    width: calc(var(--st-in) - var(--st-spine));
    top: var(--st-branch);
    height: 1px;
    border-top-width: 1px;
    clip-path: inset(0 0 0 0);
    transition: clip-path 120ms linear 620ms, border-color 200ms ease;
  }
  [data-vis="standard"] .st-g-per::before {
    left: calc(var(--st-spine) - var(--st-in) - 1px);
    width: calc(var(--st-in) - var(--st-spine) + 1px);
    top: -1px;
    height: calc(var(--st-branch) + 2px);
    border-left-width: 1px;
    border-bottom-width: 1px;
    border-bottom-left-radius: 8px;
    clip-path: inset(0 0 0 0);
    transition: clip-path 300ms linear 120ms, border-color 200ms ease;
  }
}

/* ── Earlier steps, as exceptions to the finished picture ───────── */

/* 0: the card and the guides wait, faint, before anything reaches them. */
[data-vis="standard"][data-step]:not([data-reached~="1"]) .st-hub { opacity: 0.45; }
[data-vis="standard"][data-step]:not([data-reached~="2"]) .st-g-icp { opacity: 0.45; }
[data-vis="standard"][data-step]:not([data-reached~="7"]) .st-g-per { opacity: 0.45; }

/* Before 1: no hairlines from the people. */
[data-vis="standard"][data-step]:not([data-reached~="1"]) .st-fan .st-w { stroke-dashoffset: 1; }
[data-vis="standard"][data-step]:not([data-reached~="1"]) .st-gather .st-bl { clip-path: inset(0 100% 0 0); }
[data-vis="standard"][data-step]:not([data-reached~="1"]) .st-gather .st-br { clip-path: inset(0 0 0 100%); }
[data-vis="standard"][data-step]:not([data-reached~="1"]) .st-gather .st-bs { transform: scaleY(0); }

/* Before 2: no line from the card to the ICP guide. */
[data-vis="standard"][data-step]:not([data-reached~="2"]) .st-stem { transform: scaleY(0); }
[data-vis="standard"][data-step]:not([data-reached~="2"]) .st-split .st-bs { transform: scaleY(0); }
[data-vis="standard"][data-step]:not([data-reached~="2"]) .st-split .st-bl { clip-path: inset(0 0 0 100%); }

/* Before each trait's step: its place waits as a Track line, and its
   text and box are out, a few px back toward the card. */
[data-vis="standard"][data-step]:not([data-reached~="2"]) .st-t1 .st-skel,
[data-vis="standard"][data-step]:not([data-reached~="3"]) .st-t2 .st-skel,
[data-vis="standard"][data-step]:not([data-reached~="4"]) .st-t3 .st-skel,
[data-vis="standard"][data-step]:not([data-reached~="5"]) .st-t4 .st-skel { opacity: 1; }

[data-vis="standard"][data-step]:not([data-reached~="2"]) .st-t1 :is(.st-r-text, .st-box),
[data-vis="standard"][data-step]:not([data-reached~="3"]) .st-t2 :is(.st-r-text, .st-box),
[data-vis="standard"][data-step]:not([data-reached~="4"]) .st-t3 :is(.st-r-text, .st-box),
[data-vis="standard"][data-step]:not([data-reached~="5"]) .st-t4 :is(.st-r-text, .st-box) {
  opacity: 0;
  transform: translateX(-8px);
}

/* While a trait is written in, the people it came from, their hairlines
   and the line through the card are ringed in Ink: where it came from,
   shown as it arrives. */
[data-vis="standard"][data-step="2"] .st-p.st-c1 .st-av,
[data-vis="standard"][data-step="3"] .st-p.st-c2 .st-av,
[data-vis="standard"][data-step="4"] .st-p.st-c3 .st-av,
[data-vis="standard"][data-step="5"] .st-p.st-c4 .st-av { outline-color: var(--st-sel); }
[data-vis="standard"][data-step="2"] .st-p.st-c1 .st-fn,
[data-vis="standard"][data-step="3"] .st-p.st-c2 .st-fn,
[data-vis="standard"][data-step="4"] .st-p.st-c3 .st-fn,
[data-vis="standard"][data-step="5"] .st-p.st-c4 .st-fn { color: var(--ink); }
[data-vis="standard"][data-step="2"] .st-w.st-c1,
[data-vis="standard"][data-step="3"] .st-w.st-c2,
[data-vis="standard"][data-step="4"] .st-w.st-c3,
[data-vis="standard"][data-step="5"] .st-w.st-c4 { stroke: var(--st-sel); }
[data-vis="standard"]:is([data-step="2"], [data-step="3"], [data-step="4"], [data-step="5"]) :is(.st-stem, .st-split .st-bs) {
  background-color: var(--st-sel);
}
[data-vis="standard"]:is([data-step="2"], [data-step="3"], [data-step="4"], [data-step="5"]) :is(.st-split .st-bl, .st-gather .st-bs) {
  border-color: var(--st-sel);
}
[data-vis="standard"]:is([data-step="2"], [data-step="3"], [data-step="4"], [data-step="5"]) .st-gather .st-bs {
  background-color: var(--st-sel);
}

/* Before 6: the customer data is not yet joined, and nothing is ticked.
   Each box is an empty Slate outline. */
[data-vis="standard"][data-step]:not([data-reached~="6"]) .st-w-data { stroke-dashoffset: 1; }
[data-vis="standard"][data-step]:not([data-reached~="6"]) .st-box {
  background-color: transparent;
  border-color: var(--slate);
}
[data-vis="standard"][data-step]:not([data-reached~="6"]) .st-box path { stroke-dashoffset: 1; }
[data-vis="standard"][data-step]:not([data-reached~="6"]) .st-ok {
  opacity: 0;
  transform: translateY(4px);
}

/* 6: the check. The data's hairline draws and it is ringed; the read
   line passes down the traits (450ms in, for 1100ms; each box's delay
   above is when the line crosses its row's middle), then the pill. */
[data-vis="standard"][data-step="6"] .st-w-data {
  stroke: var(--st-sel);
  transition: stroke 200ms ease, stroke-dashoffset 420ms var(--st-ease);
}
[data-vis="standard"][data-step="6"] .st-data-g { outline-color: var(--st-sel); }
[data-vis="standard"][data-step="6"] .st-data-l { color: var(--ink); }
[data-vis="standard"][data-step="6"] .st-read {
  animation: st-read 1100ms linear 450ms both;
}
@keyframes st-read {
  0%   { top: 0;    opacity: 0; }
  6%   {            opacity: 1; }
  92%  {            opacity: 1; }
  100% { top: 100%; opacity: 0; }
}
/* On a narrower plate the data has no hairline of its own: the gather's
   left arm and stem carry it into the card, ringed as its hairline is. */
@container (max-width: 539px) {
  [data-vis="standard"][data-step="6"] .st-gather .st-bl { border-color: var(--st-sel); }
  [data-vis="standard"][data-step="6"] .st-gather .st-bs { background-color: var(--st-sel); }
}

/* Before 7: no line to the Persona guide, and its personas wait. */
[data-vis="standard"][data-step]:not([data-reached~="7"]) .st-split .st-br { clip-path: inset(0 100% 0 0); }
[data-vis="standard"][data-step]:not([data-reached~="7"]) .st-pr .st-skel { opacity: 1; }
[data-vis="standard"][data-step]:not([data-reached~="7"]) .st-pr-text {
  opacity: 0;
  transform: translateX(-8px);
}

/* The phone's line: the turn out of the card and the branch into the
   ICP guide at 2 (the spine stops at that branch), the rest of the spine
   and the branch into the Persona guide at 7. */
@container (max-width: 429px) {
  [data-vis="standard"][data-step]:not([data-reached~="2"]) .st-split .st-bl { clip-path: inset(0 0 100% 0); }
  [data-vis="standard"][data-step]:not([data-reached~="2"]) .st-split .st-br { clip-path: inset(0 0 100% 0); }
  [data-vis="standard"][data-step]:not([data-reached~="2"]) .st-g-icp::before { clip-path: inset(0 0 100% 0); }
  [data-vis="standard"][data-step]:not([data-reached~="2"]) .st-g-icp::after { clip-path: inset(0 100% 0 0); }
  /* Only once the line has reached it (2): before that the rule above
     keeps the whole spine hidden. */
  [data-vis="standard"][data-step][data-reached~="2"]:not([data-reached~="7"]) .st-g-icp::before {
    clip-path: inset(0 0 calc(100% - var(--st-branch) - 2px) 0);
  }
  /* At 2 the spine waits for the turn out of the card (to 500ms), then
     runs to the branch, which follows it into the ICP guide (620ms). At
     7 it carries on at once, on its own transition. */
  [data-vis="standard"][data-step="2"] .st-g-icp::before {
    transition: clip-path 120ms linear 500ms, border-color 200ms ease;
  }
  [data-vis="standard"][data-step]:not([data-reached~="7"]) .st-g-per::before { clip-path: inset(0 0 100% 0); }
  /* Here the second piece of the split is part of the line to the ICP
     guide, so it draws at 2, not at 7 as the fork's right arm does. */
  [data-vis="standard"][data-step][data-reached~="2"] .st-split .st-br { clip-path: inset(0 0 0 0); }

  [data-vis="standard"]:is([data-step="2"], [data-step="3"], [data-step="4"], [data-step="5"]) .st-split .st-br,
  [data-vis="standard"]:is([data-step="2"], [data-step="3"], [data-step="4"], [data-step="5"]) .st-g-icp::before,
  [data-vis="standard"]:is([data-step="2"], [data-step="3"], [data-step="4"], [data-step="5"]) .st-g-icp::after {
    border-color: var(--st-sel);
  }
}


/* ════ PICTURE: Sales Enablement & Coaching 2: a trait taught by real examples [data-vis="examples"] ════ */

/* ════ PICTURE: Sales Enablement & Coaching 2: a trait, taught by real examples [data-vis="examples"] ════ */

/* The "examples" picture on /for-sales (Sales Enablement & Coaching,
   point 2), on the Ink band, where the plate is a white screen.

   One page of the ICP guide: the trait as its title, then one rep's
   territory read for it, then, under "Counts", three of its accounts
   drawn out as the guide's examples, and under "Doesn't count" one
   counter-example styled as carefully as they are.

   ONE FOCAL POINT. The three examples' evidence ("Hiring 40
   dispatchers") is the largest and heaviest type on the plate, Outfit
   700 at 22px, set as three columns of two lines each under the
   territory, so from across the room the page reads as a band of
   accounts over three statements of fact. Everything else steps down
   from it: the trait is a plate title (17.5px, 600), companies are
   14.5px, sources and dates are 12px Mono, and the column labels are gone
   (the copy beside the picture names company, evidence and date).

   In the homepage's materials: one dot is one account; the read line is
   the act of checking, a 1.6px Teal stroke at 85% on a flat 38px band
   of Teal at 8%; an account with the trait is ringed in Teal (hollow:
   the confirmed colour, claiming no standing, because on this page a
   solid Teal dot means Target now, as in the lanes picture), Glyph Grey
   read and not found, a Slate ring not yet read; a selection is ringed
   in Ink at 70%, 1.4px; counts, sources and dates are Plex Mono; people
   are rounded squares with initials; the two headings are the 12px
   status pill, confirmed and neutral.

   The markup with no data-step attribute is the finished picture (also
   no script and reduced motion). Steps, as the player in sales.js sets
   them (timings in the examples section of js/sales.js):
     0  the guide page with its trait; the territory unread, Slate rings;
        every piece of every example waiting as a Track line; neither
        heading yet
     1  the read line crosses the territory; each account it passes is
        ringed Teal (has the trait) or fills Glyph Grey (does not), and
        the territory's count lands
     2  three of the ringed accounts are drawn out in turn: each is
        ringed in Ink where it sits, a copy of its ring drops out of the
        territory into the head of its column, and the column writes in
        over its Track lines, company, then the evidence a line at a
        time, then source and date; "Counts" lands over the three
     3  the counter-example: a grey account is ringed and drawn out the
        same way, down the gap between two columns and along the rule
        to its place, and lands under "Doesn't count"
   The flights start from where each account sits in the territory,
   which the examples section of js/sales.js measures into custom properties on each
   card (they change with the layout). Every fade and move is here.

   Do not set transition on the [data-vis] root, or on .ex: sales.css
   owns both for the fade between passes (on the Ink band only the
   contents fade, so the white plate never blinks).

   Layout switches on the picture's own width (container queries on
   .ex), not the viewport's, because the plate is narrower beside its
   copy on a laptop than when stacked on a tablet:
     520px and over    the three examples as columns, evidence on two
                       lines; the counter-example on the same columns
     519px and under   each example a block, the evidence on one line,
                       the account's ring hanging in the margin
     469px and under   the territory goes from 46 a row (4 rows) to 23 a
                       row (8 rows), the rep's square beside two lines */

[data-vis="examples"] {
  /* As tall as what is drawn, so nothing can clip at any width. About
     674 by 480 at 1440. */
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  --vis-pad: 24px 28px 24px;
  --vis-pad-phone: 18px 18px 18px;

  --ex-glyph: #C3C9CE;                           /* Glyph Grey: read, trait not found */
  --ex-ring: rgba(17, 22, 27, 0.7);              /* a selection, in Ink */
  --ex-drop: cubic-bezier(0.2, 0.9, 0.3, 1.08);  /* quick ease-out, a hair of settle */
  --ex-write: cubic-bezier(0.3, 0.6, 0.25, 1);
}

[data-vis="examples"] .ex {
  container-type: inline-size;
  --ex-gap: 24px;        /* between the example columns */
  --ex-mark: 12px;       /* an example's ring */
  --ex-hang: 20px;       /* the ring and the space after it */
  --ex-has: 1.2;         /* an account with the trait, against an unread one */
}

/* ── The guide page's header ────────────────────────────────────── */

[data-vis="examples"] .ex-head {
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule);
}

/* Micro, the label inside a panel, at the page's 12px floor. */
[data-vis="examples"] .ex-kicker,
[data-vis="examples"] .ex-terr-label {
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  line-height: 1.3;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}
[data-vis="examples"] .ex-kicker { display: block; }

/* A plate title (DESIGN.md's Subtitle, 17.5px): the page's subject, a
   clear step under the evidence that is the picture's point. */
[data-vis="examples"] .ex-trait {
  margin: 6px 0 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: 17.5px;
  line-height: 1.25;
  letter-spacing: -0.016em;
  color: var(--ink);
}

/* Instrument: every count, source and date. */
[data-vis="examples"] .ex-terr-count,
[data-vis="examples"] .ex-src,
[data-vis="examples"] .ex-date {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  line-height: 16px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
[data-vis="examples"] .ex-terr-count,
[data-vis="examples"] .ex-src { color: var(--muted); }
[data-vis="examples"] .ex-date { color: var(--ink); }

/* ── The territory ──────────────────────────────────────────────── */

[data-vis="examples"] .ex-terr { margin-top: 14px; }

[data-vis="examples"] .ex-terr-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "rep label count";
  align-items: center;
  column-gap: 10px;
}
/* The rep: a person, so a rounded square with initials, never a
   circle (on this page a circle is an account). */
[data-vis="examples"] .ex-rep {
  grid-area: rep;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--pill-none-bg);
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--body);
}
[data-vis="examples"] .ex-terr-label { grid-area: label; }
[data-vis="examples"] .ex-terr-count {
  grid-area: count;
  transition: opacity 300ms ease;
}

/* The accounts, one dot each, on a square pitch at every width (the
   row height is the column width, from the picture's own width). */
[data-vis="examples"] .ex-lat-wrap {
  position: relative;
  margin-top: 9px;
  padding: 5px 0;
  overflow: hidden;
}
[data-vis="examples"] .ex-lat {
  /* A dot is about half its pitch, so the territory keeps one density
     at every width: 6.4px at 1440, never under 5.6px. Resolved on each
     dot, against .ex, the picture's own width. */
  --ex-dot: clamp(5.6px, calc(100cqw / 46 * 0.48), 6.6px);
  display: grid;
  grid-template-columns: repeat(46, minmax(0, 1fr));
  grid-auto-rows: calc(100cqw / 46);
  align-items: center;
  justify-items: center;
}
[data-vis="examples"] .ex-dot {
  position: relative;
  display: block;
  box-sizing: border-box;
  width: var(--ex-dot);
  height: var(--ex-dot);
  border-radius: 50%;
  border: 1.2px solid;
  transition:
    background-color 240ms ease, border-color 240ms ease, border-width 240ms ease,
    transform 240ms ease;
}
/* Has the trait: a Teal ring, a little larger and heavier than the
   unread Slate one (scaled by --ex-has, so a 1.5px border draws at
   1.8px), so it reads as found rather than waiting, and holds its own
   beside the solid grey dots. Scaled rather than resized, so the read
   moves no layout. */
[data-vis="examples"] .ex-dot.is-has {
  transform: scale(var(--ex-has));
  background-color: transparent;
  border-color: var(--teal);
  border-width: 1.5px;
}
[data-vis="examples"] .ex-dot.is-not { background-color: var(--ex-glyph); border-color: var(--ex-glyph); }

/* The four accounts drawn out keep an Ink ring where they sit, 2.4
   times the dot across, so it stays clear of its neighbours at every
   width. A real element rather than ::after, so the player's
   .is-snapping snaps it with everything else between passes. Inside a
   ringed account it is drawn smaller by the dot's own scale, so every
   selection is the same size and weight. */
[data-vis="examples"] .ex-ring {
  position: absolute;
  inset: calc(var(--ex-dot) * -0.72);
  border: 1.4px solid var(--ex-ring);
  border-radius: 50%;
  transition:
    opacity 220ms ease calc(140ms + var(--r, 0) * 620ms),
    transform 420ms var(--ex-drop) calc(140ms + var(--r, 0) * 620ms);
}
[data-vis="examples"] .ex-dot.is-has .ex-ring {
  inset: calc(var(--ex-dot) * -0.72 / var(--ex-has));
  border-width: calc(1.4px / var(--ex-has));
}

/* The read line, shown only while it moves. It runs from 4px before the
   territory to 4px after it; each dot's colour change is timed to the
   moment it crosses (the --c and --n delays below). */
[data-vis="examples"] .ex-line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -42px;
  width: 38px;
  background: rgba(0, 168, 138, 0.08);
  border-right: 1.6px solid rgba(0, 168, 138, 0.85);
  opacity: 0;
  pointer-events: none;
}

/* ── The two headings ───────────────────────────────────────────── */

/* The 12px status pill at 5px radius: confirmed over the three,
   neutral over the counter-example. Each lands once its group is
   written. */
[data-vis="examples"] .ex-pill {
  display: block;
  width: fit-content;
  font-family: var(--text);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
  padding: 3px 9px;
  border-radius: 5px;
  white-space: nowrap;
  transform-origin: 0 50%;
  transition:
    opacity 280ms ease var(--pill-at, 0ms),
    transform 380ms var(--ex-drop) var(--pill-at, 0ms);
}
[data-vis="examples"] .ex-pill.is-yes { background: var(--pill-yes-bg); color: var(--teal-deep); }
[data-vis="examples"] .ex-pill.is-none { background: var(--pill-none-bg); color: var(--muted); }

/* ── The examples ───────────────────────────────────────────────── */

[data-vis="examples"] .ex-yes {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--rule);
  /* After the third example's date is written. */
  --pill-at: 3640ms;
}
[data-vis="examples"] .ex-yes > .ex-pill { margin-bottom: 14px; }

/* Three columns, their rows shared (subgrid), so the evidence of all
   three starts on one line even if a company name wraps. */
[data-vis="examples"] .ex-cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: auto auto auto;
  column-gap: var(--ex-gap);
}
[data-vis="examples"] .ex-card {
  /* Each card's flight and writing run from its own start: the three
     one after another in step 2, the counter-example alone in step 3. */
  --base: calc(140ms + var(--r, 0) * 620ms);
  --fly: 1000ms;   /* the flight in from the territory */
  --wr: 980ms;     /* from the card's start to its first word */
  min-width: 0;
}
[data-vis="examples"] .ex-card.is-ex {
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
  row-gap: 0;
  align-content: start;
}

/* The account: its ring (a copy of the one in the territory) and its
   company, on one line. */
[data-vis="examples"] .ex-who {
  display: flex;
  align-items: center;
  gap: calc(var(--ex-hang) - var(--ex-mark));
  min-width: 0;
}
[data-vis="examples"] .ex-p-co .ex-w {
  font-size: 14.5px;
  font-weight: 600;
  line-height: 18px;
  color: var(--ink);
}

/* The mark. Two wrappers, one moving across and one down, so its
   flight in from the territory can take a route (the keyframes below)
   rather than a straight line. */
[data-vis="examples"] .ex-mark {
  flex: none;
  display: block;
  width: var(--ex-mark);
  height: var(--ex-mark);
}
[data-vis="examples"] .ex-fx,
[data-vis="examples"] .ex-rdot {
  display: block;
  width: 100%;
  height: 100%;
}
[data-vis="examples"] .ex-rdot {
  box-sizing: border-box;
  border-radius: 50%;
  border: 2px solid var(--teal);
  transition: opacity 0s linear calc(var(--base) + 160ms);
}
[data-vis="examples"] .ex-card.is-no .ex-rdot {
  background: var(--ex-glyph);
  border-color: var(--ex-glyph);
}

/* THE FOCAL POINT: the evidence. DESIGN.md's Title, card (Outfit 700,
   22px, -0.018em), the heaviest type on the plate, stepping down to
   Title's 20px only on the narrowest laptop plate, on two even lines. */
[data-vis="examples"] .ex-claim {
  display: block;
  margin-top: 10px;
  min-width: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(20px, 3.6cqw, 22px);
  line-height: 1.2;
  letter-spacing: -0.018em;
  color: var(--ink);
}
[data-vis="examples"] .ex-p-cite { margin-top: 10px; }
[data-vis="examples"] .ex-p-cite .ex-w {
  display: flex;
  flex-wrap: wrap;
  column-gap: 9px;
}

/* ── The counter-example ────────────────────────────────────────── */

[data-vis="examples"] .ex-no {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--rule);
  --pill-at: 2880ms;
}
[data-vis="examples"] .ex-no > .ex-pill { margin-bottom: 12px; }

/* On the examples' columns: the account and its date in the first,
   the evidence and the reason across the other two. */
[data-vis="examples"] .ex-card.is-no {
  --fly: 1300ms;
  --wr: 1300ms;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-areas:
    "who claim claim"
    "cite why why";
  column-gap: var(--ex-gap);
  row-gap: 4px;
  align-items: center;
}
[data-vis="examples"] .ex-card.is-no .ex-who { grid-area: who; }
[data-vis="examples"] .ex-card.is-no .ex-claim {
  grid-area: claim;
  margin-top: 0;
  font-family: var(--text);
  font-weight: 500;
  font-size: 16.5px;
  line-height: 21px;
  letter-spacing: 0;
  color: var(--body);
}
[data-vis="examples"] .ex-card.is-no .ex-p-why { grid-area: why; }
[data-vis="examples"] .ex-card.is-no .ex-p-cite { grid-area: cite; margin: 0; }
[data-vis="examples"] .ex-p-why .ex-w {
  font-size: 13.5px;
  line-height: 17px;
  color: var(--muted);
}
/* Its evidence runs on as one line here. */
[data-vis="examples"] .ex-card.is-no .ex-p-l1,
[data-vis="examples"] .ex-card.is-no .ex-p-l2 { display: inline-block; }

/* ── Writing in ─────────────────────────────────────────────────── */

/* A written piece: the words, and over them the Track line that waits
   where they will be. The piece is as wide as its words, so the line
   is exactly their length. As the words write in from the left, the
   line is taken away from the left on the same box, pace and curve,
   so the words replace it and never cross it (crossed words would read
   as struck out). The finished value is an inset() too (a few px proud
   of the box, so no glyph is ever trimmed), because clip-path cannot
   move between inset() and none. */
[data-vis="examples"] .ex-p {
  position: relative;
  display: block;
  width: fit-content;
  max-width: 100%;
  min-width: 0;
  --d: 0ms;
  --dur: 340ms;
}
[data-vis="examples"] .ex-p-l1 { --d: 260ms; --dur: 380ms; }
[data-vis="examples"] .ex-p-l2 { --d: 640ms; --dur: 380ms; }
[data-vis="examples"] .ex-p-why { --d: 900ms; }
[data-vis="examples"] .ex-p-cite { --d: 900ms; }
[data-vis="examples"] .ex-card.is-no .ex-p-cite { --d: 1080ms; }

[data-vis="examples"] .ex-w {
  display: block;
  clip-path: inset(-4px -6px -4px -4px);
  transition: clip-path var(--dur) var(--ex-write) calc(var(--base) + var(--wr) + var(--d));
}
[data-vis="examples"] .ex-sk {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  pointer-events: none;
  clip-path: inset(0 0 0 100%);
  transition: clip-path var(--dur) var(--ex-write) calc(var(--base) + var(--wr) + var(--d));
}
[data-vis="examples"] .ex-sk i {
  display: block;
  width: 100%;
  height: 6px;
  border-radius: 2px;
  background: var(--track);
}
[data-vis="examples"] .ex-claim .ex-sk i { height: 10px; border-radius: 3px; }
[data-vis="examples"] .ex-card.is-no .ex-claim .ex-sk i { height: 7px; }

/* ── Earlier steps, as exceptions to the finished picture ───────── */

/* 0: the territory unread, Slate rings, and no count yet. */
[data-vis="examples"][data-step]:not([data-reached~="1"]) .ex-dot {
  transform: none;
  background-color: transparent;
  border-color: var(--slate);
  border-width: 1.2px;
}
[data-vis="examples"][data-step]:not([data-reached~="1"]) .ex-terr-count { opacity: 0; }

/* 1: the read. The line crosses in 1200ms from 200ms in; each dot turns
   as it passes, and the count lands after it. */
[data-vis="examples"][data-step="1"] .ex-line {
  animation: ex-sweep 1200ms linear 200ms both;
}
[data-vis="examples"][data-step="1"] .ex-dot {
  transition-delay: calc(200ms + (var(--c) + 0.5) / 46 * 1200ms);
}
[data-vis="examples"][data-step="1"] .ex-terr-count { transition-delay: 1420ms; }
@keyframes ex-sweep {
  0%   { opacity: 0; left: -42px; }
  6%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { opacity: 0; left: calc(100% - 34px); }
}

/* 0-1: no example drawn out. Each one's mark waits as a copy of its
   account's ring, over that account (--fx, --fy, measured by the
   script), at the territory's dot size (--fs), unseen; nothing is
   written in its card, and there is no Ink ring in the territory. Step
   2 sends the three; step 3 the counter-example. */
[data-vis="examples"][data-step]:not([data-reached~="2"]) .ex-card.is-ex .ex-fx,
[data-vis="examples"][data-step]:not([data-reached~="3"]) .ex-card.is-no .ex-fx {
  transform: translateX(var(--fx, 0px));
}
[data-vis="examples"][data-step]:not([data-reached~="2"]) .ex-card.is-ex .ex-rdot,
[data-vis="examples"][data-step]:not([data-reached~="3"]) .ex-card.is-no .ex-rdot {
  opacity: 0;
  transform: translateY(var(--fy, 0px)) scale(var(--fs, 0.54));
}
[data-vis="examples"][data-step]:not([data-reached~="2"]) .ex-card.is-ex .ex-w,
[data-vis="examples"][data-step]:not([data-reached~="3"]) .ex-card.is-no .ex-w {
  clip-path: inset(-4px 100% -4px 0);
}
[data-vis="examples"][data-step]:not([data-reached~="2"]) .ex-card.is-ex .ex-sk,
[data-vis="examples"][data-step]:not([data-reached~="3"]) .ex-card.is-no .ex-sk {
  clip-path: inset(0 0 0 0);
}
[data-vis="examples"][data-step]:not([data-reached~="2"]) .ex-yes > .ex-pill,
[data-vis="examples"][data-step]:not([data-reached~="3"]) .ex-no > .ex-pill {
  opacity: 0;
  transform: scale(0.9);
}
[data-vis="examples"][data-step]:not([data-reached~="2"]) .ex-dot.is-pick:not(.is-pick-no) .ex-ring,
[data-vis="examples"][data-step]:not([data-reached~="3"]) .ex-dot.is-pick-no .ex-ring {
  opacity: 0;
  transform: scale(1.7);
}

/* The flight, when its step comes: a beat after the Ink ring, the copy
   drops out of the territory into the empty band under it (--gy),
   glides along it to its column, and drops into place, growing from
   the territory's dot size to its own. The two halves overlap, which
   rounds the corners. It only ever crosses empty space. */
[data-vis="examples"][data-step][data-reached~="2"] .ex-card.is-ex .ex-fx,
[data-vis="examples"][data-step][data-reached~="3"] .ex-card.is-no .ex-fx {
  animation: ex-fly-x var(--fly) linear calc(var(--base) + 160ms) both;
}
[data-vis="examples"][data-step][data-reached~="2"] .ex-card.is-ex .ex-rdot,
[data-vis="examples"][data-step][data-reached~="3"] .ex-card.is-no .ex-rdot {
  animation: ex-fly-y var(--fly) linear calc(var(--base) + 160ms) both;
}
@keyframes ex-fly-x {
  0%, 14% {
    transform: translateX(var(--fx, 0px));
    animation-timing-function: cubic-bezier(0.45, 0, 0.3, 1);
  }
  62%, 100% { transform: translateX(0); }
}
@keyframes ex-fly-y {
  0% {
    transform: translateY(var(--fy, 0px)) scale(var(--fs, 0.54));
    animation-timing-function: cubic-bezier(0.3, 0.6, 0.4, 1);
  }
  26% { transform: translateY(var(--gy, 0px)) scale(var(--fs, 0.54)); }
  52% {
    transform: translateY(var(--gy, 0px)) scale(var(--fs, 0.54));
    animation-timing-function: cubic-bezier(0.5, 0, 0.25, 1);
  }
  100% { transform: translateY(0) scale(1); }
}

/* The counter-example on columns has further to go, and the examples
   are written by then: it drops into the band, glides to the gap
   between two columns (--gx), drops down that gap to the rule over its
   heading (--gy2), glides along the rule to its own column, and drops
   into place. */
@keyframes ex-fly-x-no {
  0%, 12% {
    transform: translateX(var(--fx, 0px));
    animation-timing-function: cubic-bezier(0.45, 0, 0.3, 1);
  }
  28%, 52% {
    transform: translateX(var(--gx, 0px));
    animation-timing-function: cubic-bezier(0.45, 0, 0.3, 1);
  }
  80%, 100% { transform: translateX(0); }
}
@keyframes ex-fly-y-no {
  0% {
    transform: translateY(var(--fy, 0px)) scale(var(--fs, 0.54));
    animation-timing-function: cubic-bezier(0.3, 0.6, 0.4, 1);
  }
  16%, 26% {
    transform: translateY(var(--gy, 0px)) scale(var(--fs, 0.54));
    animation-timing-function: cubic-bezier(0.45, 0, 0.3, 1);
  }
  58%, 76% {
    transform: translateY(var(--gy2, 0px)) scale(var(--fs, 0.54));
    animation-timing-function: cubic-bezier(0.5, 0, 0.25, 1);
  }
  100% { transform: translateY(0) scale(1); }
}
@container (min-width: 520px) {
  [data-vis="examples"][data-step][data-reached~="3"] .ex-card.is-no .ex-fx { animation-name: ex-fly-x-no; }
  [data-vis="examples"][data-step][data-reached~="3"] .ex-card.is-no .ex-rdot { animation-name: ex-fly-y-no; }
}

/* ── Narrower plates ────────────────────────────────────────────── */

/* A small tablet, a phone: each example a block, one under another, its
   ring hanging in the margin beside the company, and the evidence on
   one line beneath. The headings sit on the text's edge, so the margin
   stays clear for the rings dropping in. */
@container (max-width: 519px) {
  [data-vis="examples"] .ex-cards {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    row-gap: 16px;
  }
  [data-vis="examples"] .ex-card.is-ex {
    grid-row: auto;
    display: block;
  }
  [data-vis="examples"] .ex-card.is-no {
    --fly: 1000ms;
    --wr: 980ms;
    display: block;
  }
  [data-vis="examples"] .ex-no { --pill-at: 2560ms; }
  [data-vis="examples"] .ex-pill,
  [data-vis="examples"] .ex-claim,
  [data-vis="examples"] .ex-card > .ex-p { margin-left: var(--ex-hang); }
  [data-vis="examples"] .ex-claim {
    margin-top: 5px;
    font-size: clamp(19.5px, 6.6cqw, 22px);
    line-height: 1.2;
  }
  [data-vis="examples"] .ex-p-l1,
  [data-vis="examples"] .ex-p-l2 { display: inline-block; vertical-align: top; }
  [data-vis="examples"] .ex-p-cite { margin-top: 5px; }
  [data-vis="examples"] .ex-card.is-no .ex-claim { margin-top: 5px; }
  [data-vis="examples"] .ex-card.is-no .ex-p-why { margin-top: 3px; }
  [data-vis="examples"] .ex-card.is-no .ex-p-cite { margin: 6px 0 0 var(--ex-hang); }
  [data-vis="examples"] .ex-yes > .ex-pill { margin-bottom: 12px; }
  [data-vis="examples"] .ex-no { margin-top: 16px; }
  [data-vis="examples"] .ex-no > .ex-pill { margin-bottom: 10px; }
}

/* A narrow plate: the territory in 23 a row, 8 rows, and the rep's
   square beside the label and the count, on two lines. */
@container (max-width: 469px) {
  [data-vis="examples"] .ex-lat {
    /* Capped, so a stacked mid-width plate keeps the phone's fine
       grain rather than turning to polka dots. */
    --ex-dot: clamp(6px, calc(100cqw / 23 * 0.45), 7.5px);
    grid-template-columns: repeat(23, minmax(0, 1fr));
    grid-auto-rows: calc(100cqw / 23);
  }
  [data-vis="examples"][data-step="1"] .ex-dot {
    transition-delay: calc(200ms + (var(--n) + 0.5) / 23 * 1200ms);
  }
  [data-vis="examples"] .ex-terr-head {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "rep label"
      "rep count";
    row-gap: 1px;
  }
  [data-vis="examples"] .ex-rep { width: 32px; height: 32px; }
  [data-vis="examples"] .ex-terr-count { justify-self: start; }
}

@media (max-width: 520px) {
  [data-vis="examples"] .ex-head { padding-bottom: 13px; }
  [data-vis="examples"] .ex-terr { margin-top: 13px; }
}


/* ════ PICTURE: Sales Enablement & Coaching 3: the meeting that went nowhere [data-vis="coach"] ════ */

/* ════ PICTURE: Sales Enablement & Coaching 3: coach the conversation [data-vis="coach"] ════ */

/* The coach picture on /for-sales (Sales Enablement & Coaching, point 3),
   on the Ink band, where the white plate reads as a screen.

   The sales leader's own review of the team's first meetings this
   month: only the brief chip is ours. Six meetings, in the materials of
   /for-marketing's persona and chat pictures: hairline rows, Plex Mono
   dates, people as rounded squares with initials, each account as its
   dot (Target now, all six) before its name, outcomes as the 12px status
   pill. Every row carries the same small brief chip.

   ONE FOCAL MOMENT. The meeting that went nowhere is ringed in Ink (a
   selection, never a verdict colour, as on the chat picture) and opens,
   as persona's card grows out of its row, while the other five compact
   to single lines and recede, all but their brief chips, which stay
   crisp so the sameness reads down the list. Inside, the leader's two
   conclusions, each a name with its mark beside it and no side rule
   (the pills carry the standing): Preparation, in Muted, "Ruled out"
   in the neutral pill, its reason under it; then The conversation, at
   38px in Ink, "Coach this" on Ink. From across the room: a column of
   identical chips, one amber mark, and a dark heading in a ring.

   The markup with no data-step attribute is the finished picture.
   Steps (timings in the coach section of js/sales.js):
     0  the six meetings at full height: date, rep, account; no briefs,
        no outcomes
     1  the read line passes down the list and leaves the same brief chip
        in each row as it crosses it
     2  the outcomes land, row by row
     3  the meeting that went nowhere is ringed in Ink
     4  it opens: the other rows compact and recede, the ring grows with
        it, every brief chip outlines once (the same in all six), and a
        beat later Preparation is ruled out
     5  The conversation grows to its full size in Ink, then "Coach
        this"; held to read
   The plate never changes height while it plays: the script measures
   the finished body and the steps hold it (--co-h).
   Do not set transition on the [data-vis] root or on .co, its only child:
   sales.css uses both for the fade between passes (on the Ink band only
   the contents fade). */

[data-vis="coach"] {
  /* As tall as the list and its open review: about 674 by 470 at 1440. */
  --vis-ratio: auto;
  --vis-ratio-phone: auto;
  --vis-pad: 26px 26px 24px;
  --vis-pad-phone: 18px 18px 16px;

  /* How far the read line's band bleeds past the list: the plate's own
     side padding, so it runs edge to edge as on the topics table. */
  --co-bleed: 26px;

  container-type: inline-size;
}
@media (max-width: 520px) {
  [data-vis="coach"] { --co-bleed: 18px; }
}

[data-vis="coach"] .co {
  --co-ease: cubic-bezier(0.22, 0.7, 0.3, 1);
  /* A meeting when finished (one compact line), before the review opens
     (a comfortable list), and the reviewed meeting at the top of its
     card. */
  --co-row-h: 34px;
  --co-row-open: 54px;
  --co-head-h: 46px;
  --co-gap: 14px;
  --co-rep: 24px;
  --co-chip-w: 56px;
  --co-out-w: 124px;
  /* date, rep, account, brief, outcome: one set of columns for the rows
     and the review's marks. */
  --co-cols: 76px var(--co-rep) minmax(0, 1fr) var(--co-chip-w) var(--co-out-w);
  /* The ring stands this far proud of the list on each side. */
  --co-proud: 12px;
  /* How far the other meetings recede once one is open (persona's list
     recedes to 0.6; these carry less, so a touch further). */
  --co-recede: 0.5;
  /* Amber at 20% under Ink type: the problem, named by the copy. The
     same ground as the facts picture's amber pill, so the page has one. */
  --co-amber-bg: rgba(206, 132, 9, 0.2);
  --co-sel-ink: rgba(17, 22, 27, 0.7);
  display: block;
  min-width: 0;
}

/* ── Title ──────────────────────────────────────────────────────── */

[data-vis="coach"] .co-head {
  padding-bottom: 13px;
  border-bottom: 1px solid var(--rule);
}
[data-vis="coach"] .co-title {
  display: block;
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
  line-height: 1.25;
  letter-spacing: -0.016em;
  color: var(--ink);
}

/* ── Rows ───────────────────────────────────────────────────────── */

/* isolation keeps the ring and the read line inside the picture, below
   the sticky header. */
[data-vis="coach"] .co-body { position: relative; isolation: isolate; }
/* While it plays, the body holds the finished picture's height. */
[data-vis="coach"][data-step] .co-body { height: var(--co-h, auto); }

[data-vis="coach"] .co-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Each meeting is one grid track tall, so the compacting at step 4 is a
   grid-template-rows change on its item (as the review's opening is),
   never a height or padding animation on the row itself. The reviewed
   meeting's item has a second track, its review. */
[data-vis="coach"] .co-list > li {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: var(--co-row-h);
  transition: grid-template-rows 560ms var(--co-ease);
}
[data-vis="coach"] .co-list > li.co-focus {
  grid-template-rows: var(--co-head-h) auto;
}

[data-vis="coach"] .co-row {
  box-sizing: border-box;
  display: grid;
  grid-template-columns: var(--co-cols);
  column-gap: var(--co-gap);
  align-items: center;
  min-height: 0;
  border-bottom: 1px solid var(--rule);
}
[data-vis="coach"] .co-list > li:last-child .co-row { border-bottom: 0; }

[data-vis="coach"] .co-date {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  white-space: nowrap;
}
[data-vis="coach"] .co-rep {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--co-rep);
  height: var(--co-rep);
  border-radius: 6px;  /* people are rounded squares; a circle is an account */
  background: var(--pill-none-bg);
  color: var(--body);
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 1;
}
[data-vis="coach"] .co-acct {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
}
/* One dot is one account, in its verdict colour: all six meetings were
   with accounts to target now. */
[data-vis="coach"] .co-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--v-target);
}
[data-vis="coach"] .co-name {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
[data-vis="coach"] .co-row.is-sel .co-acct { font-weight: 600; }

/* The brief chip: the same glyph and word in every row, the one thing on
   the plate that is ours. An outline chip, Surface on a Rule hairline
   (the persona picture's "Delivered to" chips), so it reads as a
   reference rather than a status, and the filled pills stay the only
   outcomes. */
[data-vis="coach"] .co-brief {
  box-sizing: border-box;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 18px;
  padding: 0 6px 0 5px;
  border: 1px solid var(--rule);
  border-radius: 5px;
  background: var(--surface);
  color: var(--muted);
  white-space: nowrap;
  transition:
    opacity 300ms ease-out calc(var(--i, 0) * 233ms + 250ms),
    transform 420ms var(--co-ease) calc(var(--i, 0) * 233ms + 250ms);
}
[data-vis="coach"] .co-glyph {
  flex: none;
  width: 9px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.1;
  stroke-linecap: round;
}
[data-vis="coach"] .co-glyph-head { stroke-width: 1.6; }
[data-vis="coach"] .co-brief-word {
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  line-height: 1;
  color: var(--body);
}

/* The 12px status pill at 5px radius. */
[data-vis="coach"] .co-out { min-width: 0; display: flex; }
[data-vis="coach"] .co-pill {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 9px;
  border-radius: 5px;
  font-family: var(--text);
  font-weight: 600;
  font-size: 12px;
  line-height: 1;
  white-space: nowrap;
}
[data-vis="coach"] .co-out .co-pill {
  transition:
    opacity 280ms ease-out calc(var(--i, 0) * 140ms + 120ms),
    transform 380ms var(--co-ease) calc(var(--i, 0) * 140ms + 120ms);
}
/* The outcomes are the leader's own record, not something we checked,
   so a booked next step takes the neutral ground, never the confirmed
   Teal: on this plate Teal is only ours (the read line, and each
   account's verdict dot). That also leaves the one Amber pill alone in
   its column. */
[data-vis="coach"] .co-pill-booked { background: var(--pill-none-bg); color: var(--body); }
/* Amber only because the copy names this as the problem; Ink type on it,
   never white. */
[data-vis="coach"] .co-pill-nowhere { background: var(--co-amber-bg); color: var(--ink); }
[data-vis="coach"] .co-pill-upcoming,
[data-vis="coach"] .co-pill-ruled { background: var(--pill-none-bg); color: var(--muted); }
/* The one thing left: Ink, the primary button's ground. */
[data-vis="coach"] .co-pill-coach { background: var(--ink); color: var(--bg); }

/* The other five meetings recede once one is open, everything but their
   brief chips. */
[data-vis="coach"] .co-item .co-date,
[data-vis="coach"] .co-item .co-rep,
[data-vis="coach"] .co-item .co-acct,
[data-vis="coach"] .co-item .co-out {
  opacity: var(--co-recede);
  transition: opacity 460ms ease-out;
}

/* ── The selection and the review ───────────────────────────────── */

[data-vis="coach"] .co-focus { position: relative; }

/* The Ink ring: a selection that claims no standing. It stands proud of
   the list on both sides, and as the review opens beneath the row it
   grows with it (it is pinned to the top and bottom of .co-focus). */
[data-vis="coach"] .co-sel {
  position: absolute;
  z-index: 2;
  left: calc(-1 * var(--co-proud));
  right: calc(-1 * var(--co-proud));
  top: -1px;
  bottom: 0;
  border: 1.4px solid var(--co-sel-ink);
  border-radius: 12px;  /* the card step: the ring holds a row and its review */
  pointer-events: none;
  transition: opacity 340ms ease-out, transform 460ms var(--co-ease);
}

/* The review opens by its own height (a grid row from 0fr to 1fr), so
   the rows below it move down as it grows. */
[data-vis="coach"] .co-review {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 560ms var(--co-ease);
}
[data-vis="coach"] .co-review-in { min-height: 0; overflow: hidden; }
[data-vis="coach"] .co-rvs {
  display: grid;
  row-gap: 20px;
  padding: 20px 0 24px;
}

/* Each conclusion is the name with its mark right beside it (so it reads
   as one note, the leader's, rather than a status in a column), and
   under Preparation its reason. No side rule: the pills carry the
   standing, and a coloured rule belongs only to a single sourced line. */
[data-vis="coach"] .co-rv {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "label mark" "detail detail";
  column-gap: 14px;
  row-gap: 5px;
  align-items: center;
  transition: opacity 300ms ease-out;
}
[data-vis="coach"] .co-rv-convo {
  grid-template-areas: "label mark";
  column-gap: 18px;
}
[data-vis="coach"] .co-rv-label {
  grid-area: label;
  display: block;
  min-width: 0;
  font-family: var(--display);
  letter-spacing: -0.02em;
  white-space: nowrap;
  transition: color 360ms ease-out;
}
/* Ruled out: preparation recedes to Muted. */
[data-vis="coach"] .co-rv-prep .co-rv-label {
  font-weight: 600;
  font-size: 20px;
  line-height: 1.2;
  color: var(--muted);
}
/* THE FOCAL MARK: the one thing left, in Ink at 38px (the Display and
   Figure sizes' floor: between the intent picture's 28px "25" and the
   report's 54px "1 in 4"). A phone steps it to 28px, the Headline's
   floor, with its mark beneath. */
[data-vis="coach"] .co-rv-convo .co-rv-label {
  --co-big: 38px;
  justify-self: start;
  font-weight: 700;
  font-size: var(--co-big);
  line-height: 1.08;
  letter-spacing: -0.035em;
  color: var(--ink);
  transform-origin: 0 50%;
  transition: color 360ms ease-out, transform 620ms var(--co-ease);
}
[data-vis="coach"] .co-rv-detail {
  grid-area: detail;
  min-width: 0;
  font-size: 14.5px;
  line-height: 1.4;
  color: var(--muted);
}
[data-vis="coach"] .co-rv-mark { grid-area: mark; display: flex; justify-self: start; }
[data-vis="coach"] .co-rv-mark .co-pill {
  transition: opacity 280ms ease-out, transform 380ms var(--co-ease);
}

/* ── The read line ──────────────────────────────────────────────── */

/* 1.6px Teal at 85% with a flat 38px band of Teal at 8% trailing it,
   moving down the six rows (by transform, so nothing is laid out again
   while it runs). Shown only while it moves. */
[data-vis="coach"] .co-read {
  position: absolute;
  z-index: 1;
  left: calc(-1 * var(--co-bleed));
  right: calc(-1 * var(--co-bleed));
  top: 0;
  height: 38px;
  transform: translateY(-100%);
  background: rgba(0, 168, 138, 0.08);
  border-bottom: 1.6px solid rgba(0, 168, 138, 0.85);
  opacity: 0;
  pointer-events: none;
}
[data-vis="coach"][data-step="1"] .co-read {
  animation: co-read 1400ms linear 120ms both;
}
@keyframes co-read {
  0%   { transform: translateY(-100%); opacity: 0; }
  6%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { transform: translateY(calc(6 * var(--co-row-open) - 100%)); opacity: 0; }
}

/* Step 4: every brief chip outlines in Ink once, top to bottom, as the
   review says the research was the same. */
[data-vis="coach"][data-step="4"] .co-brief {
  animation: co-same 1100ms ease-in-out calc(var(--i, 0) * 55ms + 380ms) both;
}
@keyframes co-same {
  0%   { border-color: var(--rule); color: var(--muted); }
  35%  { border-color: rgba(17, 22, 27, 0.62); color: var(--ink); }
  70%  { border-color: rgba(17, 22, 27, 0.62); color: var(--ink); }
  100% { border-color: var(--rule); color: var(--muted); }
}

/* ── Earlier steps, as exceptions to the finished picture ───────── */

/* Until step 1: no briefs. They land as the read line crosses. */
[data-vis="coach"][data-step]:not([data-reached~="1"]) .co-brief {
  opacity: 0;
  transform: translateY(-5px);
}

/* Until step 2: no outcomes. */
[data-vis="coach"][data-step]:not([data-reached~="2"]) .co-out .co-pill {
  opacity: 0;
  transform: translateY(4px);
}

/* Until step 3: nothing selected. */
[data-vis="coach"][data-step]:not([data-reached~="3"]) .co-sel {
  opacity: 0;
  transform: scale(1.012, 1.08);
}
[data-vis="coach"][data-step]:not([data-reached~="3"]) .co-row.is-sel .co-acct { font-weight: 500; }

/* Until step 4: one plain list. Every meeting at the same comfortable
   height and full strength, the review closed under its row. */
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-list > li { grid-template-rows: var(--co-row-open); }
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-list > li.co-focus { grid-template-rows: var(--co-row-open) auto; }
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-item .co-date,
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-item .co-rep,
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-item .co-acct,
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-item .co-out { opacity: 1; }
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-review { grid-template-rows: 0fr; }
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-rv { opacity: 0; }

/* Step 4, a beat after the review opens: Preparation is ruled out. Both
   lines start alike, in Body, the conversation drawn at Preparation's
   size. */
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-rv-prep .co-rv-label { color: var(--body); }
[data-vis="coach"][data-step]:not([data-reached~="4"]) .co-pill-ruled {
  opacity: 0;
  transform: translateX(-6px);
}
[data-vis="coach"][data-step="4"] .co-rv { transition-delay: 240ms; }
[data-vis="coach"][data-step="4"] .co-rv-prep .co-rv-label,
[data-vis="coach"][data-step="4"] .co-pill-ruled { transition-delay: 1350ms; }

/* Until step 5: the conversation is only named, at about Preparation's
   size (0.55 of 34 to 38px is 19 to 21px). Then it grows into the focal
   mark, in Ink, and "Coach this" lands beside it. The mark is laid out
   after the full-size name, so it lands where the grown name ends. */
[data-vis="coach"][data-step]:not([data-reached~="5"]) .co-rv-convo .co-rv-label {
  color: var(--body);
  transform: scale(0.55);
}
[data-vis="coach"][data-step]:not([data-reached~="5"]) .co-pill-coach {
  opacity: 0;
  transform: scale(0.9);
}
[data-vis="coach"][data-step="5"] .co-pill-coach { transition-delay: 520ms; }

/* ── Narrower plates, 440 to 529px inside (stacked, about 520 to 610
   wide): the dates go, so the account names keep their length ─────── */

@container (max-width: 529px) {
  [data-vis="coach"] .co {
    --co-cols: var(--co-rep) minmax(0, 1fr) var(--co-chip-w) var(--co-out-w);
  }
  [data-vis="coach"] .co-date { display: none; }
}

/* ── A phone, under 440px inside the plate ──────────────────────── */

/* Two lines a meeting: the rep's square beside the account and its
   date, then the brief chip and the outcome. Still compact once one is
   open, the chips still a column. In the review, Preparation keeps its
   mark beside it; the conversation steps down to 28px, still the
   largest thing on the plate by far, with "Coach this" beneath it. */
@container (max-width: 439px) {
  [data-vis="coach"] .co {
    --co-row-h: 52px;
    --co-row-open: 62px;
    --co-head-h: 60px;
    --co-gap: 10px;
    --co-proud: 8px;
  }
  [data-vis="coach"] .co-head { padding-bottom: 11px; }
  [data-vis="coach"] .co-title { font-size: 15.5px; }

  [data-vis="coach"] .co-row {
    grid-template-columns: var(--co-rep) minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    row-gap: 7px;
    align-content: center;
  }
  [data-vis="coach"] .co-rep { grid-column: 1; grid-row: 1 / span 2; align-self: center; }
  [data-vis="coach"] .co-acct { grid-column: 2; grid-row: 1; }
  [data-vis="coach"] .co-date { display: block; grid-column: 3; grid-row: 1; justify-self: end; }
  [data-vis="coach"] .co-brief { grid-column: 2; grid-row: 2; }
  /* The outcome shares the second line with the brief, right-aligned, so
     only the date sizes the last column and the names keep their room. */
  [data-vis="coach"] .co-out { grid-column: 2 / span 2; grid-row: 2; justify-self: end; }

  [data-vis="coach"] .co-rvs { row-gap: 15px; padding: 15px 0 18px; }
  [data-vis="coach"] .co-rv {
    column-gap: 10px;
    row-gap: 3px;
  }
  [data-vis="coach"] .co-rv-convo {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "label" "mark";
    row-gap: 9px;
  }
  [data-vis="coach"] .co-rv-prep .co-rv-label { font-size: 17.5px; }
  [data-vis="coach"] .co-rv-convo .co-rv-label { --co-big: 28px; }
  [data-vis="coach"][data-step]:not([data-reached~="5"]) .co-rv-convo .co-rv-label {
    transform: scale(0.625);  /* 17.5px of 28 */
  }
  [data-vis="coach"] .co-rv-detail { font-size: 13px; }
}

/* The smallest phones (about 340 wide and under): the date goes, so the
   account names keep their full length. */
@container (max-width: 279px) {
  [data-vis="coach"] .co-row .co-date { display: none; }
}
