/* ============================================================
   managed-growth: six engine cards, animations rebuilt 1:1 from
   the live page in the uplane agent-log design language.
   Warm paper panels on band-art stages; slow, layout-stable motion.
   ============================================================ */

/* Hero actions use one measured, page-specific system. The bottom padding is
   intentional: the shared hero motif measures this group and places its rule
   at the group edge, leaving the buttons clear of the line. */
.sub-hero-dark .sub-ctas {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: min(100%, 356px);
  gap: 10px;
  margin-top: 30px;
  padding-bottom: 18px;
}

@media (min-width: 901px) {
  .sub-hero-dark > .shd-inner > .sub-ctas {
    margin-top: 64px;
    padding-bottom: 0;
  }

  .sub-hero-dark > .shd-inner > .sub-ctas .btn {
    min-height: 44px;
  }
}
.sub-hero-dark .sub-ctas .btn {
  width: 100%;
  min-height: 42px;
  padding: 10px 18px;
  justify-content: center;
  border-radius: 8px;
  font-weight: 400;
  line-height: 1.2;
  box-shadow: none;
}
.sub-hero-dark .sub-ctas .mg-hero-primary {
  color: var(--ink);
  background: #fff;
  border-color: #fff;
}
.sub-hero-dark .sub-ctas .mg-hero-primary:hover {
  color: var(--ink);
  background: #f4f6ff;
  border-color: #f4f6ff;
}
.sub-hero-dark .sub-ctas .mg-hero-secondary {
  color: #fff;
  background: rgba(8, 18, 78, .18);
  border-color: rgba(255, 255, 255, .56);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.sub-hero-dark .sub-ctas .mg-hero-secondary:hover {
  color: #fff;
  background: rgba(255, 255, 255, .12);
  border-color: rgba(255, 255, 255, .8);
}
@media (max-width: 440px) {
  .sub-hero-dark .sub-ctas {
    width: 100%;
    grid-template-columns: 1fr;
  }
}

#team {
  /* the copy column's inset from the inner rail: the text box must not sit
     on the line, and the line must not run through the box (it is covered
     by .mg-cell's ground below). */
  --mg-gutter: clamp(20px, 2.2vw, 36px);
  --mg-line: rgba(47, 44, 43, .14);
  --mg-border: rgba(47, 44, 43, .09);
  --mg-paper: #F6F4F3;
  --mg-surface: #FCFAF9;
  --mg-enter: .7s;
  --mg-step: .9s;
}

.mg-grid {
  display: block;
  counter-reset: mg-step;
  margin-top: 56px;
  border-top: 1px solid rgba(10, 16, 60, .06);
}

.mg-cell {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
  grid-template-rows: auto auto auto auto auto 1fr;
  align-items: start;
  column-gap: 0;
  padding: 0;
  margin: 0;
  border-bottom: 1px solid rgba(10, 16, 60, .06);
  counter-increment: mg-step;
}

.mg-cell::before {
  content: counter(mg-step, decimal-leading-zero);
  grid-column: 1;
  grid-row: 1;
  display: block;
  padding-top: clamp(38px, 4vw, 60px);
  padding-right: clamp(28px, 4vw, 68px);
  padding-left: var(--mg-gutter);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: .13em;
  color: var(--blue);
}

.mg-cell > .mg-stage {
  grid-column: 2;
  grid-row: 1 / -1;
  align-self: stretch;
  /* flush with the .wrap content box, which is exactly where --rail-ir is
     measured, so the art lands on the inner line at every width. */
  margin-right: 0;
}

/* The alternation starts on the art: cell 01 puts the stage in column 1 and the
   copy in column 2, so ODD cells are the reversed ones and even cells fall back
   to the base rules above. */
.mg-cell:nth-child(odd)::before,
.mg-cell:nth-child(odd) > .mg-label,
.mg-cell:nth-child(odd) > h3,
.mg-cell:nth-child(odd) > p,
.mg-cell:nth-child(odd) > .mg-bullets {
  grid-column: 2;
  padding-right: var(--mg-gutter);
  padding-left: clamp(28px, 4vw, 68px);
}

.mg-cell:nth-child(odd) > .mg-stage {
  grid-column: 1;
  margin-right: 0;
  margin-left: 0;
}

.mg-cell .mg-label {
  grid-column: 1;
  grid-row: 2;
  display: block;
  margin-top: 14px;
  padding-right: clamp(28px, 4vw, 68px);
  font-family: var(--sans);
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--blue);
}
.mg-cell h3 {
  grid-column: 1;
  grid-row: 3;
  padding-right: clamp(28px, 4vw, 68px);
  padding-left: var(--mg-gutter);
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(21px, 1.9vw, 27px);
  letter-spacing: -.012em;
  line-height: 1.16;
  color: var(--ink);
  margin-top: 18px;
}
.mg-cell > p {
  grid-column: 1;
  grid-row: 4;
  padding-right: clamp(28px, 4vw, 68px);
  padding-left: var(--mg-gutter);
  margin-top: 14px;
  /* 14.5px was off the ladder and read a step under the rest of the site
     (home #how / #solutions / #security and why-us #situations all set body
     prose at 15px). This section carried 18 more sentences at 13.5px below. */
  font-size: 15px;
  line-height: 1.62;
  color: var(--muted);
  max-width: 56ch;
}
.mg-bullets {
  grid-column: 1;
  grid-row: 5;
  align-self: start;
  list-style: none;
  margin-top: 28px;
  padding: 0 clamp(28px, 4vw, 68px) clamp(38px, 4vw, 60px) var(--mg-gutter);
  display: flex;
  flex-direction: column;
  gap: 9px;
}

/* Collapse the two-column cell to one column.

   This block used to name `.mg-cell` and `.mg-cell:nth-child(even)` only. But
   the comment 60 lines up says it plainly: "cell 01 puts the stage in column 1
   and the copy in column 2, so ODD cells are the reversed ones and even cells
   fall back to the base rules above." Even was the case that never needed
   naming; odd was the one that did.

   `.mg-cell:nth-child(odd) > .mg-stage` is (0,3,0) against this block's
   (0,2,0), so on every odd cell the stage kept `grid-column: 2` in a grid that
   now has one explicit column. It landed in an implicit auto-width track and
   measured 0px wide, while `min-height: 390px` still reserved its full height:
   three ~400px holes of white down the page, one after each of cells 01, 03 and
   05, with their artwork invisible. The copy in those cells kept the desktop
   left padding for the same reason and sat on a different inset from the even
   cells. Naming odd here fixes both. */
@media (max-width: 900px) {
  .mg-cell,
  .mg-cell:nth-child(even),
  .mg-cell:nth-child(odd) {
    grid-template-columns: minmax(0, 1fr);
  }
  .mg-cell::before,
  .mg-cell:nth-child(even)::before,
  .mg-cell:nth-child(odd)::before,
  .mg-cell > .mg-label,
  .mg-cell:nth-child(even) > .mg-label,
  .mg-cell:nth-child(odd) > .mg-label,
  .mg-cell > h3,
  .mg-cell:nth-child(even) > h3,
  .mg-cell:nth-child(odd) > h3,
  .mg-cell > p,
  .mg-cell:nth-child(even) > p,
  .mg-cell:nth-child(odd) > p,
  .mg-cell > .mg-bullets,
  .mg-cell:nth-child(even) > .mg-bullets,
  .mg-cell:nth-child(odd) > .mg-bullets,
  .mg-cell > .mg-stage,
  .mg-cell:nth-child(even) > .mg-stage,
  .mg-cell:nth-child(odd) > .mg-stage {
    grid-column: 1;
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
  }
  .mg-cell::before,
  .mg-cell:nth-child(even)::before,
  .mg-cell:nth-child(odd)::before { grid-row: 1; }
  .mg-cell > .mg-label,
  .mg-cell:nth-child(even) > .mg-label,
  .mg-cell:nth-child(odd) > .mg-label { grid-row: 2; }
  .mg-cell > h3,
  .mg-cell:nth-child(even) > h3,
  .mg-cell:nth-child(odd) > h3 { grid-row: 3; }
  .mg-cell > p,
  .mg-cell:nth-child(even) > p,
  .mg-cell:nth-child(odd) > p { grid-row: 4; }
  .mg-cell > .mg-bullets,
  .mg-cell:nth-child(even) > .mg-bullets,
  .mg-cell:nth-child(odd) > .mg-bullets {
    grid-row: 5;
    padding-bottom: 32px;
  }
  .mg-cell > .mg-stage,
  .mg-cell:nth-child(even) > .mg-stage,
  .mg-cell:nth-child(odd) > .mg-stage {
    grid-row: 6;
    min-height: 390px;
  }

  /* The cell sits on the rails, so its COPY takes the same 16px inset off the
     line that the page's own text rail uses. The rule above zeroes the padding
     for every child, which is right for the artwork -- the stage is meant to
     reach the line -- and wrong for the text, which was left sitting on it.
     `--mg-gutter`'s own comment: "the text box must not sit on the line". */
  .mg-cell::before,
  .mg-cell:nth-child(even)::before,
  .mg-cell:nth-child(odd)::before,
  .mg-cell > .mg-label,
  .mg-cell:nth-child(even) > .mg-label,
  .mg-cell:nth-child(odd) > .mg-label,
  .mg-cell > h3,
  .mg-cell:nth-child(even) > h3,
  .mg-cell:nth-child(odd) > h3,
  .mg-cell > p,
  .mg-cell:nth-child(even) > p,
  .mg-cell:nth-child(odd) > p,
  .mg-cell > .mg-bullets,
  .mg-cell:nth-child(even) > .mg-bullets,
  .mg-cell:nth-child(odd) > .mg-bullets {
    padding-left: 16px;
    padding-right: 16px;
  }
}
/* full sentences, so they take the 14px secondary-body rung rather than the
   13.5px they had -- the smallest prose anywhere on the site */
.mg-bullets li { display: flex; gap: 10px; font-size: 14px; line-height: 1.55; color: var(--muted); }
.mg-bullets li b { font-weight: 500; color: var(--ink); }
.mg-bico {
  flex: none;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  background: #fff;
  border: 1px solid rgba(10, 10, 10, .12);
  border-radius: 7px;
  color: var(--ink);
}
.mg-bico svg { width: 13px; height: 13px; }

/* ---- the stage: squared band art + warm paper panel ---- */
.mg-stage {
  position: relative;
  border-radius: 0;
  overflow: hidden;
  isolation: isolate;
  display: grid;
  place-items: center;
  padding: clamp(18px, 2.4vw, 30px);
  /* fixed, not vw-derived: every stage must resolve to the same height so the
     six background squares line up across the grid. panel A is trimmed to fit
     inside 430 - 2*30 padding, so no panel can push its stage past this. */
  min-height: 430px;
}
.mg-stage > img.bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: -1;
}
.mg-panel {
  width: min(100%, 500px);
  container-type: inline-size;
  min-height: 330px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  background: var(--mg-paper);
  border-radius: 16px;
  box-shadow: 0 14px 34px rgba(6, 10, 40, .14);
  padding: 26px 22px 28px;
  color: #2F2C2B;
  font-family: var(--sans);
  overflow: hidden;
}

.mg-panel > .mg-anim {
  width: 100%;
}

/* The published six-part choreography, mounted inside the new brand stage. */
.mg-panel--rive {
  aspect-ratio: 574 / 365;
  padding: 0;
  background: #F6F4F3;
}

.mg-panel--rive > .mg-anim {
  display: none;
}

.mg-rive-wrap,
.mg-rive-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.mg-rive-wrap {
  position: relative;
  overflow: hidden;
  background: #F6F4F3;
}

.mg-rive-canvas {
  vertical-align: top;
}

.mg-rive-brand {
  position: absolute;
  z-index: 3;
  left: 23.7%;
  top: 7.2%;
  width: 7.4%;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 0 0 3px #fff, 0 0 0 4px rgba(26, 68, 255, .08);
  pointer-events: none;
}

.mg-rive-brand svg {
  display: block;
  width: 38%;
  height: 62%;
  fill: var(--blue);
}

@media (max-width: 560px) {
  .mg-stage {
    /* keep the 430px floor here too: at 375px the pill wraps and panel A grows
       to ~387, so a 330 floor let each stage size to its own panel and the
       squares came out unequal (399/362/373/371/384/362). */
    aspect-ratio: auto;
    padding: 16px;
  }
}

/* ---- shared atoms ---- */

/* CENTRING THE GLYPH IN A BADGE.
   The mark is 1389.5 x 1985.28, an aspect of 0.6999, so a box that fits it can
   never be even against its badge on both axes: every pairing in this file
   leaves a fractional half-space (14 - 5 = 4.5, 14 - 7 = 3.5, 34 - 12 = 11,
   34 - 17 = 8.5) and grid centring snaps that to a whole pixel. Worse, it
   snaps in a different direction per axis -- measured 4.5 -> 5 across and
   3.5 -> 3 down -- which put the mark 0.5px right and 0.5px high inside a 14px
   disc. That is 3.6% of the badge and plainly visible at these sizes.

   So the mark is centred by transform instead. translate(-50%, -50%) resolves
   on the compositor at subpixel precision and is never snapped, which holds at
   every badge size and every card aspect rather than only at the ones whose
   arithmetic happens to come out even. Verified from rendered pixels:
   tmp/glyphcenter.js. */
.mg-chip,
.mg-post-glyph { position: relative; }

.mg-chip > svg,
.mg-post-glyph > svg {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.mg-chip {
  width: 28px; height: 28px;
  flex: none;
  display: grid; place-items: center;
  background: #fff;
  border: 1px solid rgba(26, 68, 255, .18);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(6, 10, 40, .08);
}
.mg-chip svg { width: 12px; height: 17px; display: block; fill: var(--blue); }
.mg-chip.lg { width: 42px; height: 42px; border-radius: 11px; }
.mg-chip.lg svg { width: 16px; height: 23px; }

.mg-glow { position: relative; }
.mg-glow::after {
  content: none;
}
@keyframes mgBreath { 0%, 100% { opacity: .3; } 50% { opacity: .75; } }

/* One pointer for the whole page: plain black, no outline, and big enough
   to read at panel scale. It used to be brand blue with a white keyline,
   which made it compete with the blue the panels actually use for meaning. */
.mg-cursor {
  position: absolute;
  left: 0; top: 0;
  z-index: 6;
  width: 21px; height: 21px;
  filter: drop-shadow(0 1px 3px rgba(8, 12, 40, .22));
  transition: transform 1.15s var(--ease-in-out-quart);
  pointer-events: none;
}
.mg-cursor::after {
  content: "";
  position: absolute;
  left: -4px; top: -4px;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 2px solid rgba(10, 10, 10, .45);
  opacity: 0;
  transform: scale(.4);
}
.mg-cursor.click::after { animation: mgClick .7s var(--ease-out-quint); }
@keyframes mgClick { 0% { opacity: .8; transform: scale(.4); } 100% { opacity: 0; transform: scale(1.25); } }

/* ---- A: strategic architecture (static) ---- */
.mg-a { --sa-hair: rgba(47, 44, 43, .13); }

/* top pill: white card + solid blue uplane mark, soft brand halo */
.mg-a .mg-pill {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  width: max-content;
  max-width: 100%;
  margin: 0 auto;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .07);
  border-radius: 14px;
  padding: 10px 18px 9px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -.01em;
  color: var(--mg-ink, #2F2C2B);
  box-shadow:
    0 1px 3px rgba(6, 10, 40, .06),
    0 10px 24px rgba(26, 68, 255, .16),
    0 22px 48px rgba(26, 68, 255, .10);
}
.mg-a .mg-pill::before {
  content: "";
  position: absolute;
  inset: -9px -11px;
  z-index: -1;
  border-radius: 24px;
  background: rgba(26, 68, 255, .26);
  filter: blur(16px);
}
.mg-a .mg-chip {
  width: 34px; height: 34px;
  flex: none;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--blue);
  box-shadow: 0 0 0 5px rgba(26, 68, 255, .10), 0 6px 16px rgba(26, 68, 255, .30);
}
.mg-a .mg-chip svg { width: 12px; height: 17px; display: block; fill: #fff; }

/* connector tree: rounded elbows, matching the reference */
.mg-tree { position: relative; height: 24px; }
.mg-tree i { position: absolute; }
.mg-tree .t-v {
  left: 50%; top: 0;
  width: 1px; height: 8px;
  background: var(--sa-hair);
}
.mg-tree .t-bus {
  left: calc(16.6667% - 3.333px);
  right: calc(16.6667% - 3.333px);
  top: 8px;
  height: 16px;
  border: 1px solid var(--sa-hair);
  border-bottom: 0;
  border-radius: 13px 13px 0 0;
}
.mg-tree .t-d2 {
  left: 50%; top: 8px;
  width: 1px; height: 16px;
  background: var(--sa-hair);
}

.mg-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.mg-mini {
  min-width: 0;
  background: var(--mg-surface);
  border: 1px solid var(--mg-border);
  border-radius: 12px;
  padding: 10px 6px 12px;
  position: relative;
  display: flex;
  flex-direction: column;
}
.mg-mini > :last-child { margin-top: auto; margin-bottom: auto; }
/* Same rule as the source pills: every tag is its column's width, so the
   three read as one row of boxes rather than three different labels. */
.mg-tag {
  display: block;
  width: calc(100% - 4px);
  max-width: calc(100% - 4px);
  margin: -20px auto 10px;
  text-align: center;
  white-space: nowrap;
  background: #EFEDEB;
  border: 1px solid rgba(47, 44, 43, .07);
  border-radius: 8px;
  padding: 4px 11px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: -.005em;
  color: #4A4744;
  white-space: nowrap;
}

/* The third column's label has a phone-length twin in the markup, the same
   device .mg-btail and .lead--phone use: both strings live in the page and the
   width decides which one is shown, so neither is duplicated in CSS. */
.mg-tagshort { display: none; }

/* --- audiences --- */
/* No clip and no edge mask. The five rows fit exactly, so the window's top and
   bottom gutters are just the mini's auto margins (~8px), which now reads the
   same as the 9px left/right gutter — the old 20%/80% fade made the first and
   last row look pushed away from the card edge. Dropping overflow also lets the
   elevated row keep its shadow instead of being sliced at the border. */
.mg-audwin {
  padding: 0 3px;
}
.mg-audlist { display: flex; flex-direction: column; gap: 1px; }
.mg-audlist .row {
  display: flex;
  align-items: center;
  gap: 5px;
  height: 29px;
  padding: 0 4px 0 0;
  border-radius: 9px;
  opacity: .42;
}
.mg-audlist .row i {
  width: 3px; height: 15px;
  border-radius: 2px;
  background: rgba(47, 44, 43, .3);
  flex: none;
}
.mg-audlist .row span {
  font-size: 10px;
  line-height: 1.25;
  letter-spacing: -.005em;
  color: #2F2C2B;
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* the longest label, "Price sensitivity" at weight 500, needs 70.4px; this
     leaves it ~5px of slack inside the elevated row so it never ellipsises */
  padding-right: 2px;
}
.mg-audlist .row b {
  margin-left: auto; flex: none;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: rgba(47, 44, 43, .10);
  position: relative;
}
/* centred off the box's own middle rather than an asymmetric inset, and
   smaller: at inset 3px/2.6px the tick sat low and right of centre */
.mg-audlist .row b::after {
  content: "";
  position: absolute;
  left: 50%; top: 46%;
  width: 4.6px; height: 2.4px;
  border-left: 1.3px solid rgba(47, 44, 43, .38);
  border-bottom: 1.3px solid rgba(47, 44, 43, .38);
  transform: translate(-50%, -50%) rotate(-45deg);
}
.mg-audlist .row.done { opacity: .72; }
.mg-audlist .row.done i { background: #9FE0BE; }
.mg-audlist .row.done b { background: rgba(46, 158, 85, .14); }
.mg-audlist .row.done b::after { border-color: #5FBF87; }
/* The scanned row pops by widening out to the card's full content box rather
   than translating right — a translate pushed it past the clip edge, which is
   what sliced the pill and ellipsised its label. */
.mg-audlist .row.on {
  opacity: 1;
  background: #fff;
  margin: 0 -3px;
  padding-left: 9px;
  padding-right: 4px;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .06), 0 6px 18px rgba(6, 10, 40, .07);
}
.mg-audlist .row.on i {
  background: #12A150;
  margin-left: -3px;
}
.mg-audlist .row.on span { font-weight: 500; }
.mg-audlist .row.on b { background: rgba(46, 158, 85, .16); }
.mg-audlist .row.on b::after { border-color: #12A150; border-left-width: 1.6px; border-bottom-width: 1.6px; }

/* --- top ads --- */
/* 3 whole rows (3*46.5 + 2*5 = 149.5) so the grid ends on a tile edge instead
   of fading out mid-row. The 3px inline padding narrows the tiles to 49.5 and
   lifts the side gutter to 9px, which now matches the ~8px the mini's auto
   margins leave above and below — previously the sides were 6px against a
   fade that read as a much deeper top and bottom. */
.mg-adgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 46.5px;
  gap: 5px;
  width: 100%;
  height: 149.5px;
  padding: 0 3px;
  overflow: hidden;
  margin: 0 auto;
}
.mg-adtile {
  position: relative;
  display: block;
  min-width: 0;
  overflow: hidden;
  border-radius: 4px;
  background: #fff;
  opacity: .4;
  filter: grayscale(.55);
}
.mg-adtile img { display: block; width: 100%; height: 100%; object-fit: cover; }
.mg-adtile.hot {
  opacity: 1;
  filter: none;
  box-shadow: 0 2px 8px rgba(6, 10, 40, .16), 0 10px 22px rgba(6, 10, 40, .10);
  z-index: 2;
}

/* --- real-time trends --- */
.mg-ring {
  position: relative;
  width: 46px; height: 46px;
  margin: 12px auto 8px;
  border-radius: 50%;
  background: #fff;
  display: grid;
  place-items: center;
  box-shadow:
    0 0 0 5px #fff,
    0 0 0 6px rgba(26, 68, 255, .16),
    0 0 0 12px rgba(26, 68, 255, .05),
    0 4px 14px rgba(26, 68, 255, .10);
}
.mg-ring-mark svg { width: 15px; height: 21px; display: block; fill: var(--mg-ink, #2F2C2B); }
.mg-trendwin {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 26%, #000 74%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 26%, #000 74%, transparent 100%);
}
.mg-trendlist { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.mg-trendlist span {
  font-size: 10.5px;
  line-height: 1.2;
  padding: 5px 12px;
  border-radius: 8px;
  color: rgba(47, 44, 43, .55);
  white-space: nowrap;
  max-width: 100%;
}
.mg-trendlist span.on {
  background: #fff;
  color: #2F2C2B;
  font-weight: 600;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .06), 0 6px 18px rgba(6, 10, 40, .07);
}
.mg-trendlist span.fade { color: rgba(47, 44, 43, .3); }

/* ---- B: high-volume asset generation (static) ---- */
.mg-b { position: relative; display: flex; flex-direction: column; }
/* Three equal cells, not three shrink-to-fit pills. The labels are different
   lengths, so a flex row made three different boxes AND put their centres
   wherever the text happened to end -- which is why the connector legs, pinned
   at a hard 16.67%, came down beside the pills instead of out of them. With a
   3x1fr grid the centres are arithmetic: 1/6, 1/2 and 5/6 of the row once the
   gaps are taken out, and the connector below reads the same numbers. */
.mg-srcrow {
  --src-gap: 7px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--src-gap);
  width: 100%;
}
.mg-srcpill {
  display: grid;
  place-items: center;
  min-width: 0;
  background: #EDEBE9;
  border: 1px solid rgba(47, 44, 43, .06);
  border-radius: 8px;
  padding: 6px 7px;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: -.008em;
  color: #3C3936;
  text-align: center;
  white-space: nowrap;
}

/* Converging lines: two rounded elbows and a drop, all three landing ON the
   hub rather than stopping above it. The elbows' bottom rail runs at the hub's
   vertical centre, so they enter the circle from the left and the right dead
   centre; the drop stops at the hub's top edge, centred. --hub-r is half the
   circle, and is what the hub's own negative margin pulls back. */
.mg-conv {
  --src-gap: 7px;
  --hub-r: 21px;
  position: relative;
  height: 54px;
}
.mg-conv i { position: absolute; }
.mg-conv .c-bus {
  left: calc((100% - 2 * var(--src-gap)) / 6);
  right: calc((100% - 2 * var(--src-gap)) / 6);
  top: 0; bottom: 0;
  border: 1px solid var(--sa-hair, rgba(47, 44, 43, .13));
  border-top: 0;
  border-radius: 0 0 18px 18px;
}
.mg-conv .c-v {
  left: 50%; top: 0;
  width: 1px; height: calc(100% - var(--hub-r));
  background: var(--sa-hair, rgba(47, 44, 43, .13));
}

/* central hub: circular brand node */
.mg-hub {
  width: 42px; height: 42px;
  margin: -21px auto 0;
  position: relative;
  z-index: 2;
  border-radius: 50%;
  background: var(--blue);
  display: grid;
  place-items: center;
  box-shadow:
    0 0 0 5px #fff,
    0 0 0 6px rgba(26, 68, 255, .10),
    0 0 20px 7px rgba(26, 68, 255, .17),
    0 6px 20px rgba(26, 68, 255, .20);
}
.mg-hubmark svg { width: 13px; height: 18px; display: block; fill: #fff; }

/* publish stage */
.mg-stage-b {
  margin-top: 16px;
  background: #F1F0EE;
  border: 1px solid rgba(47, 44, 43, .05);
  border-radius: 12px;
  padding: 9px;
}
.mg-stream { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 7px; }
/* The post chrome is a frame around someone else's picture, so it should not
   be the brightest thing in the figure. At pure #fff the header and footer are
   26% of each card's height and they read as a white border drawn around the
   ad rather than as the surface the ad is sitting on -- the panel behind them
   is #F6F4F3, so #fff was the lightest tone anywhere in the section. #FBFAF9
   still sits ~6L above that panel, which the 1px hairline and the card's own
   shadow carry the rest of the way, and the ad becomes the brightest element
   in its own card. */
.mg-post {
  min-width: 0;
  background: #F8F6F5;
  border: 1px solid rgba(47, 44, 43, .07);
  border-radius: 9px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .05), 0 6px 16px rgba(6, 10, 40, .06);
}
.mg-post-h { display: flex; align-items: center; gap: 4px; padding: 5px 5px 4px; }
.mg-post-glyph {
  width: 14px; height: 14px;
  flex: none;
  border-radius: 50%;
  background: var(--blue);
  display: grid;
  place-items: center;
}
.mg-post-glyph svg { width: 5px; height: 7px; display: block; fill: #fff; }
.mg-post-meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.mg-post-meta b { font-size: 6.5px; font-weight: 700; color: #14120F; }
/* The handle's second line is a suggestive bar, not copy. At 5.5px (4px on
   the .ev cards) no string is legible, and what shipped here was the literal
   placeholder "Add some description" -- readable enough on a retina screen to
   be read as an unfinished page. A grey bar says "there is a caption here"
   without asserting one, and it is the wireframe language this page already
   speaks two cards to the left (.wf-line, .wf-copy i). */
.mg-post-meta i {
  display: block;
  width: 30px;
  height: 3px;
  margin-top: 3px;
  border-radius: 2px;
  background: rgba(47, 44, 43, .16);
}
.mg-post-media { position: relative; aspect-ratio: 1; background: #F3F1EF; }
.mg-post-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.mg-post-f { display: flex; align-items: center; gap: 5px; padding: 5px 5px 6px; }
.mg-post-f svg { width: 9px; height: 9px; display: block; }
.mg-post-f .i-heart { fill: #FF3040; }
.mg-post-f .i-line { fill: none; stroke: #14120F; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.mg-post-f .i-mark { fill: #14120F; margin-left: auto; }

@media (max-width: 900px) {
  .mg-srcpill { font-size: 9.5px; padding: 5px 5px; }
  .mg-post-meta i { display: none; }
}

/* ---- C: high-conversion ecosystem (static) ---- */
.mg-c { position: relative; display: flex; flex-direction: column; }

.mg-thumbstrip {
  width: max-content;
  max-width: 100%;
  margin: 0 auto;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .07);
  border-radius: 10px;
  padding: 5px;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .05), 0 8px 20px rgba(6, 10, 40, .07);
}
.mg-thumbrow { display: flex; gap: 4px; }
.mg-thumbrow img {
  width: 32px; height: 32px;
  object-fit: cover;
  border-radius: 6px;
  opacity: .42;
  filter: grayscale(.5);
}
.mg-thumbrow img.lead { opacity: 1; filter: none; }

.mg-ab { position: relative; height: 48px; }
.mg-ab .ab-lines {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  stroke: var(--sa-hair, rgba(47, 44, 43, .13));
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.mg-ab .ab-a,
.mg-ab .ab-b {
  position: absolute;
  bottom: -3px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .1);
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 600;
  color: #2F2C2B;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .06);
  z-index: 2;
}
.mg-ab .ab-a { left: calc(25% - 11px); }
.mg-ab .ab-b { left: calc(75% - 11px); }

.mg-pages { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: stretch; }
.mg-wf {
  min-width: 0;
  height: 100%;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .07);
  border-radius: 10px 10px 0 0;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .05), 0 10px 26px rgba(6, 10, 40, .07);
}
.wf-top {
  display: flex; align-items: center; gap: 4px;
  padding: 7px 8px;
  background: #FAF9F8;
  border-bottom: 1px solid rgba(47, 44, 43, .05);
}
.wf-dot { width: 12px; height: 6px; border-radius: 3px; background: rgba(47, 44, 43, .13); flex: none; }
.wf-url { flex: 1 1 auto; height: 5px; border-radius: 3px; background: rgba(47, 44, 43, .09); }
.wf-pill { width: 9px; height: 6px; border-radius: 3px; background: rgba(47, 44, 43, .11); flex: none; }

.wf-body { display: flex; gap: 8px; padding: 9px 8px; align-items: flex-start; }
.wf-body.col { flex-direction: column; align-items: stretch; }
.wf-copy { display: flex; flex-direction: column; gap: 5px; flex: 1 1 auto; min-width: 0; }
.wf-copy.center { align-items: center; }
.wf-copy.center .wf-row { justify-content: center; }
.wf-line, .wf-copy i { height: 5px; border-radius: 3px; background: rgba(47, 44, 43, .1); display: block; }
.wf-row { display: flex; gap: 4px; }
.w20 { width: 20px; } .w22 { width: 22px; } .w24 { width: 24px; } .w26 { width: 26px; }
.w28 { width: 28px; } .w30 { width: 30px; } .w34 { width: 34px; }
.w40 { width: 40%; } .w52 { width: 52%; }
.wf-cta { width: 26px; height: 9px; border-radius: 4px; background: rgba(47, 44, 43, .14); }
.wf-cta.ghost { background: rgba(47, 44, 43, .07); }
.wf-media {
  width: 62px;
  aspect-ratio: 1;
  flex: none;
  border-radius: 6px;
  background: #DFE3EC;
  display: grid;
  place-items: center;
}
.wf-media.wide { width: 100%; aspect-ratio: 16/9; }
.wf-media svg { width: 18px; height: 18px; display: block; }

.wf-foot { padding: 0 8px 10px; }
.wf-sep { display: block; height: 1px; background: rgba(47, 44, 43, .06); margin-bottom: 8px; }
.wf-chips { display: flex; gap: 4px; justify-content: center; }
.wf-chips i { width: 16px; height: 6px; border-radius: 3px; background: rgba(47, 44, 43, .08); }

.mg-dock {
  position: relative;
  z-index: 3;
  width: max-content;
  max-width: 100%;
  margin: -22px auto 0;
  display: flex;
  align-items: center;
  gap: 6px;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .06);
  border-radius: 999px;
  padding: 6px;
  box-shadow: 0 2px 8px rgba(6, 10, 40, .10), 0 14px 32px rgba(6, 10, 40, .14);
}
.mg-dock > span {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .07);
  display: grid;
  place-items: center;
  flex: none;
}
.mg-dock > span svg { display: block; }
.mg-dock .plus {
  font-size: 16px;
  font-weight: 500;
  line-height: 1;
  color: var(--blue);
  background: #F4F6FF;
  border-color: rgba(26, 68, 255, .12);
}
.mg-pointer {
  position: absolute;
  right: -4px; bottom: -9px;
  width: 21px; height: 21px;
  filter: drop-shadow(0 1px 3px rgba(8, 12, 40, .22));
}

@media (max-width: 900px) {
  .mg-thumbrow img { width: 26px; height: 26px; }
  .mg-dock > span { width: 26px; height: 26px; }
}

/* ---- D: high-frequency steering (static) ---- */
.mg-d { position: relative; display: flex; flex-direction: column; align-items: center; }
.mg-d .d-feed {
  width: 1px; height: 12px;
  background: var(--sa-hair, rgba(47, 44, 43, .18));
  display: block;
}
.mg-d .mg-hub { margin: 0 auto; width: 52px; height: 52px; }
.mg-d .mg-hubmark svg { width: 16px; height: 22px; }
.mg-d .d-stub {
  width: 1px; height: 17px;
  margin-top: 4px;
  background: var(--sa-hair, rgba(47, 44, 43, .18));
  display: block;
}
.mg-d .d-stub.s2 { height: 16px; margin-top: 0; position: relative; }
.mg-d .d-stub.s2::after {
  content: "";
  position: absolute;
  left: 50%; bottom: -2px;
  width: 5px; height: 5px;
  margin-left: -2.5px;
  border-radius: 50%;
  background: rgba(47, 44, 43, .18);
}

.mg-togglewrap {
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .06);
  border-radius: 999px;
  padding: 6px;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .05), 0 8px 22px rgba(6, 10, 40, .08);
}
.mg-toggles { display: flex; gap: 6px; }
.tg {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 999px;
  padding: 5px 11px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: -.008em;
  white-space: nowrap;
}
.tg i { width: 5px; height: 5px; border-radius: 50%; flex: none; }
/* The legend mirrors its series: Scaling is the Uplane blue curve, while
   the testing curves remain purple. */
.tg-b { background: var(--blue); color: #fff; }
.tg-b i { background: #fff; }
.tg-v { background: #F3EDFD; color: #6D4ABF; }
.tg-v i { background: #6D4ABF; }

.mg-chart {
  width: 100%;
  max-width: 308px;
  margin: 0 auto;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .07);
  border-radius: 12px;
  padding: 7px;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .05), 0 12px 30px rgba(6, 10, 40, .08);
}
.mg-chartinner {
  position: relative;
  border-radius: 9px;
  background: #FDFCFC;
  padding: 6px 6px 0;
}

/* The goal the steering is steering towards, and the point the winning line
   crosses it — without these the chart is three lines and no argument. */
.mg-chart .thr,
.mg-chart .mark {
  stroke: rgba(47, 44, 43, .34);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
}
.mg-target {
  position: absolute;
  top: 6%;
  left: 76%;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .09);
  border-radius: 7px;
  padding: 3px 7px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: -.015em;
  color: #14120F;
  box-shadow: 0 1px 3px rgba(6, 10, 40, .07);
}
.mg-target b { width: 3px; height: 11px; border-radius: 2px; background: #17B15E; flex: none; }
.mg-chart svg { display: block; width: 100%; height: 132px; }
.mg-chart .grid line { stroke: rgba(47, 44, 43, .07); stroke-width: 1; vector-effect: non-scaling-stroke; }
.mg-chart .ln { fill: none; stroke-width: 1.7; vector-effect: non-scaling-stroke; stroke-linecap: round; }
/* Scaling uses the Uplane blue across the curve, legend and area fill. */
.mg-chart .ln-blue { stroke: var(--blue); }
/* Three tests on their own tracks in purple tones, and the one line that
   scales carrying a wash under it so the winner is unmistakable. The tests
   used to sit flat along the bottom, where they read as grid artefacts. */
.mg-chart .ln-v { stroke-width: 1.3; }
.mg-chart .ln-v.v1 { stroke: #9E86D8; opacity: .8; }
.mg-chart .ln-v.v2 { stroke: #B7A4E4; opacity: .68; }
.mg-chart .ln-v.v3 { stroke: #8067C6; opacity: .72; }
.mg-chart .ln-blue { stroke-width: 2.1; }
.mg-chart .ar { stroke: none; }
.mg-chart .ar-blue { fill: url(#mgdFade); }
.mg-chart .dot { stroke: #fff; stroke-width: 1.2; }
.mg-chart .dot-blue { fill: var(--blue); }
.mg-chart .dot-v.v1 { fill: #9E86D8; }
.mg-chart .dot-v.v2 { fill: #B7A4E4; }
.mg-chart .dot-v.v3 { fill: #8067C6; }
.mg-axis { display: flex; gap: 4px; justify-content: space-between; padding: 7px 0 8px; }
.mg-axis i { flex: 1 1 0; height: 4px; border-radius: 3px; background: rgba(47, 44, 43, .06); }

.mg-d .mg-cursor {
  position: absolute;
  left: 87.6%; top: 30.6%;
  right: auto; bottom: auto;
  width: 21px; height: 21px;
  transition: none;
  filter: drop-shadow(0 1px 3px rgba(8, 12, 40, .22));
}
.mg-cursor svg { width: 100%; height: 100%; display: block; }

/* ---- E: optimization and learning engine (static) ---- */
.mg-e { position: relative; display: flex; }
/* The fan box is near-square, not landscape. At 348/300 the three variants had
   to overlap each other to fit their staircase; at 335/316 they clear with an
   even gap, which is what makes the A/B read as three separate tests.
   316 is the ceiling: stage 430 less its 2x30 padding less the panel's 54. */
.mg-fan {
  position: relative;
  width: 100%;
  max-width: 335px;
  margin: 0 auto;
  aspect-ratio: 335 / 316;
}
.mg-fanlines {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
}
.mg-fanlines path {
  fill: none;
  stroke: var(--sa-hair, rgba(47, 44, 43, .18));
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.mg-fanlines circle { fill: #fff; stroke: rgba(47, 44, 43, .18); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* the branch that won is the only filled terminal in the fan */
.mg-fanlines circle.win { fill: var(--blue); stroke: none; }

.fan-hero, .fan-v { position: absolute; }
.fan-hero { left: 0; top: 26.1%; width: 33.9%; }
.fan-v { width: 21.1%; }
.fan-v1 { left: 59.6%; top: 0; }
.fan-v2 { left: 65%; top: 35.5%; }
.fan-v3 { left: 79%; top: 70%; }
/* the poster's avatar is a squircle in the source art, not a disc */
.mg-e .mg-post-glyph { border-radius: 4px; }
.mg-e .mg-post.ev .mg-post-glyph { border-radius: 3px; }

.mg-e .mg-post { position: relative; }
.mg-e .mg-post.eh {
  box-shadow: 0 2px 6px rgba(6, 10, 40, .09), 0 16px 38px rgba(6, 10, 40, .16);
}
.mg-e .mg-post.ev { box-shadow: 0 1px 3px rgba(6, 10, 40, .05), 0 8px 20px rgba(6, 10, 40, .09); }
.mg-e .mg-post-h { padding: 5px 5px 4px; }
.mg-e .mg-post.ev .mg-post-h { padding: 3px 3px 2px; }
.mg-e .mg-post.ev .mg-post-glyph { width: 9px; height: 9px; }
.mg-e .mg-post.ev .mg-post-glyph svg { width: 3.2px; height: 4.5px; }
.mg-e .mg-post.ev .mg-post-meta b { font-size: 5px; }
/* the small cards carry the same bar, scaled with them */
.mg-e .mg-post.ev .mg-post-meta i { width: 21px; height: 2px; margin-top: 2px; }

.mg-post-ok {
  margin-left: auto;
  flex: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: #17B15E;
  display: grid;
  place-items: center;
}
.mg-post-ok svg { width: 9px; height: 9px; display: block; }
/* Size belongs to the card, colour belongs to .muted. These were one rule, so
   the tick could only be green at 14px: moving the green to a variant card
   drew a 14px disc inside a 3px-padded header and overflowed it. */
.mg-e .mg-post.ev .mg-post-ok { width: 9px; height: 9px; }
.mg-e .mg-post.ev .mg-post-ok svg { width: 6px; height: 6px; }
.mg-post-ok.muted { background: rgba(47, 44, 43, .22); }

.mg-e .mg-post-media { aspect-ratio: 1; }
.mg-e .mg-post-media .tint { transition: none; }
/* Real creatives, not one photo hue-rotated 165/22/78 degrees. Rotating the
   hue of a product shot that far turns the product an impossible colour,
   which is what made the A/B fan look broken. */
.mg-e .mg-post-f { padding: 4px 5px 5px; gap: 4px; }
.mg-e .mg-post.ev .mg-post-f { padding: 2px 3px 3px; gap: 3px; }
.mg-e .mg-post-f svg { width: 8px; height: 8px; }
.mg-e .mg-post.ev .mg-post-f svg { width: 5.5px; height: 5.5px; }

/* ---- F: reporting & insights (static) ---- */
/* Measured off the reference art, as shares of the artwork's width:
   card 72 | gap 9.3 | chips 18.7, with the bell 13.7 across, centred on the
   card's right edge and the stem tangent to the bell's right side. Held in
   cqw rather than px because the panel runs 391-500 wide depending on the
   viewport, and fixed pixels only landed these ratios at exactly 500. */
.mg-f {
  position: relative;
  display: block;
  padding-right: 28cqw;
  --mg-stub: 2.45cqw;
  /* The bell's diameter is declared here, not on .dash-bell, because the stem's
     head is derived from it (see .mg-notes::before). Two places used to carry
     the bell's size independently and the mobile pair drifted 48px apart. */
  --bell-w: 13.7cqw;
  /* .mg-notes' top and the stem's head are one number now. They were `37%` and
     a hard-coded `18.4cqw`, which only agree at one panel width: .mg-f's height
     is content-driven (the dashboard sets it) while the bell is sized in cqw,
     so the two drift as the panel's aspect changes and the stem's head leaves
     the bell. Both read this. */
  --notes-top: 18.4cqw;
  /* half a chip, so the stem stops on the last branch rather than past it */
  --stem-drop: 13px;
}

.mg-dash {
  display: flex;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .07);
  border-top: 2px solid rgba(26, 68, 255, .45);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 6px rgba(6, 10, 40, .06), 0 14px 34px rgba(6, 10, 40, .10);
}

.dash-side {
  width: 33%;
  max-width: 20.18cqw;
  flex: none;
  background: #FAFAF9;
  border-right: 1px solid rgba(47, 44, 43, .06);
  padding: 1.75cqw 1.54cqw;
  display: flex;
  flex-direction: column;
}
.dash-side .dl { display: flex; align-items: center; gap: 0.88cqw; margin-bottom: 1.97cqw; }
.dash-side .dl svg { width: 1.75cqw; height: 2.41cqw; display: block; fill: var(--blue); }
.dash-side .dl b { font-size: 8px; font-weight: 600; letter-spacing: -.02em; color: #14120F; }

/* Nav rows carry a disclosure caret on the sections that nest, and the live
   row a blue marker, so the rail reads as a product and not as six bars. */
.dash-nav { display: flex; flex-direction: column; gap: 1.32cqw; }
.dash-nav + .dash-nav { margin-top: 1.54cqw; }
.dn { display: flex; align-items: center; gap: 0.88cqw; }
.dn i { display: block; height: 1.1cqw; border-radius: 3px; background: rgba(47, 44, 43, .09); flex: 1 1 auto; }
.dn.w82 i { flex: 0 1 82%; }
.dn.w74 i { flex: 0 1 74%; }
.dn.w66 i { flex: 0 1 66%; }
.dn s {
  flex: none;
  width: 1.1cqw; height: 1.1cqw;
  margin-left: auto;
  text-decoration: none;
  background: rgba(47, 44, 43, .22);
  clip-path: polygon(0 34%, 50% 72%, 100% 34%, 100% 56%, 50% 94%, 0 56%);
}
.dn.on i { background: rgba(26, 68, 255, .3); }
.dn.on::before {
  content: "";
  flex: none;
  width: 0.66cqw; height: 0.66cqw;
  border-radius: 50%;
  background: var(--blue);
}
.dash-user { display: flex; align-items: center; gap: 0.88cqw; margin-top: auto; padding-top: 2.19cqw; }
.dash-user b { flex: none; width: 2.19cqw; height: 2.19cqw; border-radius: 50%; background: rgba(47, 44, 43, .11); }
.dash-user u { flex: 0 1 58%; height: 0.88cqw; border-radius: 2px; background: rgba(47, 44, 43, .08); text-decoration: none; }

.dash-main { flex: 1 1 auto; min-width: 0; padding: 2.19cqw 3.51cqw 2.19cqw 2.19cqw; background: #FCFBFB; }
/* Title over subtitle on the left, control pill on the right — a page header,
   where three bars on one line read as a toolbar. */
.dash-top { display: flex; align-items: flex-start; gap: 1.32cqw; margin-bottom: 1.97cqw; }
.dash-top .dt-t { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.88cqw; }
.dash-top .dt-l { display: block; width: 54%; height: 1.1cqw; border-radius: 3px; background: rgba(47, 44, 43, .11); }
.dash-top .dt-s { display: block; width: 34%; height: 0.88cqw; border-radius: 2px; background: rgba(47, 44, 43, .06); }
.dash-top .dt-p { width: 4.39cqw; height: 1.97cqw; border-radius: 5px; background: rgba(47, 44, 43, .1); flex: none; }

.dash-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.1cqw; margin-bottom: 1.97cqw; }
.dash-cards .kc {
  min-width: 0;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .06);
  border-radius: 6px;
  padding: 1.32cqw 1.1cqw;
  display: flex;
  flex-direction: column;
  gap: 0.88cqw;
}
.kc-h { display: flex; align-items: center; gap: 0.66cqw; }
.kc-h b { width: 1.75cqw; height: 1.75cqw; border-radius: 50%; background: none; border: 1px solid rgba(47, 44, 43, .16); flex: none; }
.kc-h u { flex: 1 1 auto; min-width: 0; height: 0.88cqw; border-radius: 2px; background: rgba(47, 44, 43, .1); text-decoration: none; }
/* the overflow affordance every real metric tile carries */
.kc-h s {
  flex: none;
  margin-left: 0.66cqw;
  width: 1.75cqw; height: 0.44cqw;
  text-decoration: none;
  background-image: radial-gradient(circle, rgba(47, 44, 43, .28) 45%, transparent 47%);
  background-size: 3px 2px;
  background-repeat: repeat-x;
}
.kc-l { display: block; height: 0.88cqw; border-radius: 2px; background: rgba(47, 44, 43, .08); }
.kc-l.w70 { width: 70%; } .kc-l.w45 { width: 45%; }
.kc-p { display: block; width: 3.07cqw; height: 1.32cqw; border-radius: 3px; background: rgba(47, 44, 43, .11); }

.dash-chart {
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .06);
  border-radius: 7px;
  padding: 1.54cqw;
}
.dash-chart .dch { display: block; width: 42%; height: 1.54cqw; border-radius: 3px; background: rgba(47, 44, 43, .11); margin-bottom: 1.1cqw; }
.dash-chart svg { display: block; width: 100%; height: 18.86cqw; }
.dash-chart .area { fill: url(#dashFade); }
.dash-chart .line { fill: none; stroke: var(--blue); stroke-width: 1.55; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round; }
.dash-chart .base { stroke: rgba(47, 44, 43, .1); stroke-width: 1; vector-effect: non-scaling-stroke; }
.dash-axis { display: flex; gap: 0.66cqw; margin-top: 1.1cqw; }
.dash-axis i { flex: 1 1 0; height: 0.88cqw; border-radius: 2px; background: rgba(47, 44, 43, .07); }

/* The bell is the loudest object in the frame on purpose: it is the moment the
   report leaves the product. At 38px it read as a UI button; it wants to sit
   across the card's corner at roughly a seventh of the artwork's width. */
.dash-bell {
  position: absolute;
  top: -1px;
  right: 21.15cqw;
  z-index: 3;
  width: var(--bell-w); aspect-ratio: 1;
  border-radius: 50%;
  background: #E4E3E4;
  border: 4px solid #F6F4F3;
  display: grid;
  place-items: center;
}
.dash-bell svg { width: 6cqw; height: 6cqw; display: block; }

.mg-notes {
  position: absolute;
  right: 0;
  top: var(--notes-top);
  width: 18.7cqw;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
/* The stem hangs off the bell's right edge and stops on the last branch, so it
   is never a line with a free end.

   Its head is the bell's vertical CENTRE, not the bell's bottom. The stem's x
   is the bell's right edge (chip width + stub, see the locked trio below), and
   a circle only reaches that x at one point: its centre height. Starting the
   head at the bell's bottom instead put it half a bell -- 26.6px at a 391px
   panel -- below the only point it could touch, so the branch tree read as
   floating beside the bell rather than leaving it.

   Both terms are cqw and share --notes-top with .mg-notes, so the head tracks
   the bell at every panel width instead of at one. */
.mg-notes::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--mg-stub));
  top: calc(var(--bell-w) / 2 - var(--notes-top) - 1px);
  bottom: var(--stem-drop);
  width: 1px;
  background: rgba(47, 44, 43, .18);
}
/* Destinations are chips, not cards: a flat grey fill with no rule and no lift,
   so the dashboard keeps the only shadow in the frame. */
.note {
  position: relative;
  display: flex;
  align-items: center;
  gap: 7px;
  background: #F0EEED;
  border-radius: 9px;
  padding: 6px 9px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: -.01em;
  color: #2F2C2B;
}
.note::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--mg-stub));
  top: 50%;
  width: var(--mg-stub);
  height: 1px;
  background: rgba(47, 44, 43, .18);
}
.note svg { width: 13px; height: 13px; display: block; flex: none; }

/* These sizes are locked to each other, not chosen independently: the
   bell's right offset must equal the chip width plus the branch stub, or the
   stem stops being tangent to the bell and starts floating beside it.
   88 = 80 + 8, and the desktop pair (98 = 86 + 12) obeys the same rule. */
/* Narrow screens give this artwork about 176px to work in, so every px the
   chips and bell take comes straight out of the dashboard. These four sizes
   are locked to each other, not chosen independently:
     padding-right = chip width + branch stub + half the bell
   which is what keeps the bell centred on the card's edge and the stem tangent
   to it. The desktop pair obeys the same rule (128 = 86 + 11 + 31).
   The dashboard still ends up narrow here; the standing fix is to drop the
   chips into a row under the card below 560px rather than beside it. */
@media (max-width: 900px) {
  /* --bell-w feeds both the bell and the stem's head, so they cannot drift.
     --stem-drop follows the smaller chip here (8px text + 8px padding), or the
     stem stops short of the last branch and leaves that stub hanging. */
  .mg-f { padding-right: 49cqw; --mg-stub: 4cqw; --bell-w: 17cqw; --stem-drop: 9px; }
  .mg-notes { width: 36cqw; }
  .note { font-size: 8px; padding: 4px 5px; gap: 4px; border-radius: 6px; }
  .note svg { width: 10px; height: 10px; }
  .dash-bell { right: 40cqw; border-width: 2.5px; }
  .dash-bell svg { width: 7.5cqw; height: 7.5cqw; }
}

/* ---- launch control timeline ---- */
/* overflow: hidden keeps the open card's shadow and the artwork inside the
   section frame. The section head is the split one in the process block
   below, so no centring rule belongs here. */
#timeline { overflow: hidden; }
.mg-launch {
  --launch-progress: 0%;
  position: relative;
  margin-top: 58px;
  border: 1px solid rgba(10, 16, 60, .11);
  background: #fff;
  overflow: hidden;
  overflow-anchor: none;
}
.mg-launch::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(rgba(10, 16, 60, .025) 1px, transparent 1px), linear-gradient(90deg, rgba(10, 16, 60, .025) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: linear-gradient(90deg, #000 0, transparent 38%, transparent 62%, #000 100%);
  mask-image: linear-gradient(90deg, #000 0, transparent 38%, transparent 62%, #000 100%);
}
.mg-launch-head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 54px;
  padding: 0 24px;
  border-bottom: 1px solid rgba(10, 16, 60, .09);
  background: rgba(255, 255, 255, .94);
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.mg-launch-live,
.mg-launch-target {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.mg-launch-live { color: var(--ink); }
.mg-launch-live > i {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: #48C486;
  box-shadow: 0 0 0 4px rgba(72, 196, 134, .11);
  animation: mgLaunchLive 2.8s var(--ease-micro) infinite;
}
@keyframes mgLaunchLive { 50% { opacity: .42; } }
.mg-launch-target { color: rgba(10, 16, 60, .48); }
.mg-launch-target b { color: var(--ink); font-weight: 500; }
.mg-launch-rail {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  padding: 22px 22px 20px;
  border-bottom: 1px solid rgba(10, 16, 60, .09);
  background: rgba(247, 248, 251, .82);
}
.mg-launch-track {
  position: absolute;
  left: calc(7.143% + 22px);
  right: calc(7.143% + 22px);
  top: 51px;
  height: 1px;
  background: rgba(10, 16, 60, .13);
  overflow: hidden;
}
.mg-launch-track > i {
  display: block;
  width: var(--launch-progress);
  height: 100%;
  background: var(--blue);
  box-shadow: 0 0 8px rgba(26, 68, 255, .28);
  transition: width 1s var(--ease-in-out-quart);
}
.mg-launch-rail button {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
  padding: 0 5px;
  border: 0;
  background: transparent;
  color: rgba(10, 16, 60, .42);
  cursor: pointer;
}
.mg-launch-rail button small {
  font-family: var(--sans);
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
}
.mg-launch-rail button b {
  margin-top: 26px;
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  transition: color .45s var(--ease-micro);
}
.mg-launch-rail button > i {
  position: absolute;
  top: 24px;
  left: 50%;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid rgba(10, 16, 60, .24);
  box-shadow: 0 0 0 4px #F7F8FB;
  transform: translateX(-50%);
  transition: background .45s, border-color .45s, box-shadow .45s;
}
.mg-launch-rail button.is-complete,
.mg-launch-rail button.is-active { color: var(--ink); }
.mg-launch-rail button.is-complete > i {
  background: #A9E8CB;
  border-color: #78D5AA;
}
.mg-launch-rail button.is-active { color: var(--blue); }
.mg-launch-rail button.is-active > i {
  background: var(--blue);
  border-color: var(--blue);
  box-shadow: 0 0 0 4px #F7F8FB, 0 0 0 7px rgba(26, 68, 255, .09);
}
.mg-launch-stage {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(340px, .92fr);
  gap: 18px;
  min-height: 438px;
  padding: 22px;
  background: rgba(255, 255, 255, .9);
  overflow-anchor: none;
}
.mg-launch-stage.is-changing > * {
  opacity: 0;
  transform: translateY(12px);
}
.mg-launch-brief,
.mg-launch-telemetry {
  min-width: 0;
  border-radius: 16px;
  transition: opacity .68s var(--ease-out-quint), transform .68s var(--ease-out-quint);
}
.mg-launch-brief {
  display: flex;
  flex-direction: column;
  padding: 26px 28px 24px;
  background: #F6F4F3;
  border: 1px solid rgba(47, 44, 43, .07);
  box-shadow: 0 18px 44px rgba(6, 10, 40, .09);
}
.mg-launch-briefhead {
  display: flex;
  align-items: center;
  gap: 12px;
}
.mg-launch-mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  flex: 0 0 36px;
}
.mg-launch-mark::before,
.mg-launch-mark::after,
.mg-launch-mark > i {
  content: "";
  position: absolute;
  border-radius: 50%;
}
.mg-launch-mark::before {
  inset: 2px;
  border: 1px solid rgba(26, 68, 255, .22);
  animation: mgLaunchOrbit 8s linear infinite;
}
.mg-launch-mark::after {
  width: 13px; height: 13px;
  border: 2px solid var(--blue);
  border-right-color: transparent;
  animation: mgLaunchSpin 1.1s steps(8) infinite;
}
.mg-launch-mark > i {
  width: 4px; height: 4px;
  top: 1px; left: 16px;
  background: var(--blue);
  box-shadow: 0 0 0 3px #F6F4F3;
}
@keyframes mgLaunchOrbit { to { transform: rotate(360deg); } }
@keyframes mgLaunchSpin { to { transform: rotate(360deg); } }
.mg-launch-briefhead > span:nth-child(2) {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 3px;
}
.mg-launch-briefhead small {
  font-family: var(--sans);
  font-size: 9px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(47, 44, 43, .48);
}
.mg-launch-briefhead b {
  font-size: 17px;
  font-weight: 550;
  line-height: 1.2;
  letter-spacing: -.015em;
}
.mg-launch-briefhead em {
  margin-left: auto;
  padding: 6px 9px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid rgba(47, 44, 43, .08);
  color: #2E9E55;
  font-family: var(--sans);
  font-size: 9px;
  font-style: normal;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.mg-launch-summary {
  max-width: 58ch;
  margin-top: 20px;
  color: #54504D;
  font-size: 13.5px;
  line-height: 1.55;
}
.mg-launch-ops {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 22px;
}
.mg-launch-op {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 43px;
  padding: 8px 11px;
  border-radius: 10px;
  background: #FCFAF9;
  border: 1px solid rgba(47, 44, 43, .055);
  opacity: .58;
  transform: translateY(7px);
  transition: opacity .65s var(--ease-out-quint), transform .65s var(--ease-out-quint);
}
.mg-launch:not(.is-paused) .mg-launch-op:nth-child(1) { transition-delay: .12s; }
.mg-launch:not(.is-paused) .mg-launch-op:nth-child(2) { transition-delay: .28s; }
.mg-launch:not(.is-paused) .mg-launch-op:nth-child(3) { transition-delay: .44s; }
.mg-launch-op.is-done,
.mg-launch-op.is-running { opacity: 1; transform: none; }
.mg-launch-op > i {
  position: relative;
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 1px dashed rgba(47, 44, 43, .32);
}
.mg-launch-op.is-done > i {
  background: #E7F7EF;
  border: 1px solid #B8E7D0;
}
.mg-launch-op.is-done > i::after {
  content: "";
  position: absolute;
  left: 3px; top: 2px;
  width: 6px; height: 3px;
  border-left: 1.5px solid #2E9E55;
  border-bottom: 1.5px solid #2E9E55;
  transform: rotate(-45deg);
}
.mg-launch-op.is-running > i {
  border: 2px solid rgba(26, 68, 255, .18);
  border-top-color: var(--blue);
  animation: mgLaunchSpin 1.05s steps(8) infinite;
}
.mg-launch-op span { font-size: 12.5px; color: #2F2C2B; }
.mg-launch-op small {
  font-family: var(--sans);
  font-size: 8.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(47, 44, 43, .46);
}
.mg-launch-op.is-done small { color: #2E9E55; }
.mg-launch-op.is-running small { color: var(--blue); }
.mg-launch-progress { margin-top: auto; padding-top: 22px; }
.mg-launch-progress > span {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  font-size: 11px;
}
.mg-launch-progress > span b { font-weight: 500; }
.mg-launch-progress > span small {
  font-family: var(--sans);
  font-size: 9px;
  color: rgba(47, 44, 43, .5);
}
.mg-launch-progress > i {
  display: block;
  height: 2px;
  margin-top: 9px;
  background: rgba(47, 44, 43, .1);
  overflow: hidden;
}
.mg-launch-progress > i > b {
  display: block;
  width: var(--stage-progress, 38%);
  height: 100%;
  background: var(--blue);
  transition: width 1.15s var(--ease-in-out-quart);
}
.mg-launch-telemetry {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 22px;
  background: #0A1242;
  color: #fff;
  box-shadow: 0 18px 44px rgba(6, 10, 40, .16);
}
.mg-launch-telemetry::before {
  content: "";
  position: absolute;
  inset: 0;
  opacity: .24;
  background-image: radial-gradient(rgba(255, 255, 255, .28) .7px, transparent .7px);
  background-size: 14px 14px;
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 72%);
  mask-image: linear-gradient(180deg, #000, transparent 72%);
}
.mg-launch-telemetry > * { position: relative; z-index: 1; }
.mg-launch-telemetry-head,
.mg-launch-chart-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.mg-launch-telemetry-head {
  font-family: var(--sans);
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .68);
}
.mg-launch-telemetry-head small {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #A9E8CB;
}
.mg-launch-telemetry-head small i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: #65D6A1;
}
.mg-launch-chart {
  display: flex;
  flex: 1;
  min-height: 180px;
  flex-direction: column;
  margin-top: 20px;
  padding: 17px;
  border: 1px solid rgba(255, 255, 255, .1);
  background: rgba(255, 255, 255, .045);
}
.mg-launch-chart-meta span {
  font-size: 11px;
  color: rgba(255, 255, 255, .66);
}
.mg-launch-chart-meta b {
  font-family: var(--serif);
  font-size: 24px;
  font-weight: 500;
  letter-spacing: -.02em;
}
.mg-launch-bars {
  display: flex;
  flex: 1;
  align-items: flex-end;
  gap: 6px;
  min-height: 100px;
  margin-top: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, .12);
  background: repeating-linear-gradient(to top, rgba(255, 255, 255, .065) 0 1px, transparent 1px 28px);
}
.mg-launch-bars i {
  position: relative;
  flex: 1;
  height: var(--v);
  min-height: 5px;
  background: linear-gradient(180deg, #65D6A1 0%, #39BBFF 52%, #4265FF 100%);
  opacity: .82;
  transform: scaleY(.12);
  transform-origin: bottom;
  transition: transform 1.15s var(--ease-out-quint);
}
.mg-launch-bars.is-ready i { transform: scaleY(1); }
.mg-launch-bars i::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, .5), transparent 22%);
}
.mg-launch-metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  margin-top: 14px;
  background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .1);
}
.mg-launch-metrics span {
  min-width: 0;
  padding: 11px;
  background: #0D174B;
}
.mg-launch-metrics small {
  display: block;
  overflow: hidden;
  color: rgba(255, 255, 255, .46);
  font-size: 8.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mg-launch-metrics b {
  display: block;
  margin-top: 5px;
  color: #fff;
  font-size: 15px;
  font-weight: 500;
}
.mg-launch-output {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 5px 14px;
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: 10px;
  background: #fff;
  color: #2F2C2B;
}
.mg-launch-output span {
  grid-column: 1 / -1;
  font-family: var(--sans);
  font-size: 8px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(47, 44, 43, .48);
}
.mg-launch-output strong {
  overflow: hidden;
  font-size: 11px;
  font-weight: 550;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mg-launch-output > i {
  color: #2E9E55;
  font-size: 9px;
  font-style: normal;
  white-space: nowrap;
}
.mg-launch-foot {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: auto minmax(80px, 1fr) auto;
  align-items: center;
  gap: 24px;
  min-height: 68px;
  padding: 10px 22px;
  border-top: 1px solid rgba(10, 16, 60, .09);
  background: #fff;
}
.mg-launch-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}
.mg-launch-controls button {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border: 1px solid rgba(10, 16, 60, .12);
  border-radius: 50%;
  background: #fff;
  color: var(--ink);
  font-size: 15px;
  cursor: pointer;
  transition: background .4s var(--ease-micro), color .4s var(--ease-micro), transform .4s var(--ease-micro);
}
.mg-launch-controls button:hover:not(:disabled) { background: var(--blue); color: #fff; transform: translateY(-1px); }
.mg-launch-controls button:disabled { opacity: .26; cursor: default; }
.mg-launch-controls span {
  min-width: 43px;
  font-family: var(--sans);
  font-size: 9px;
  letter-spacing: .1em;
  color: rgba(10, 16, 60, .42);
}
.mg-launch-controls span b { color: var(--ink); font-weight: 500; }
.mg-launch-auto {
  height: 2px;
  overflow: hidden;
  background: rgba(10, 16, 60, .08);
}
.mg-launch-auto i {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: left;
}
.mg-launch.is-auto .mg-launch-auto i { animation: mgLaunchAuto 7.2s linear forwards; }
.mg-launch.is-paused .mg-launch-auto i { animation-play-state: paused; }
@keyframes mgLaunchAuto { to { transform: scaleX(1); } }
.mg-launch-foot .btn { border-radius: 8px; }
@media (max-width: 900px) {
  .mg-launch-rail { overflow-x: auto; grid-template-columns: repeat(7, minmax(110px, 1fr)); scrollbar-width: none; }
  .mg-launch-rail::-webkit-scrollbar { display: none; }
  .mg-launch-track { left: 76px; right: 76px; min-width: 650px; }
  .mg-launch-stage { grid-template-columns: 1fr; }
  .mg-launch-telemetry { min-height: 360px; }
}
@media (max-width: 600px) {
  .mg-launch { margin-top: 42px; }
  .mg-launch-head { padding-inline: 16px; }
  .mg-launch-target { display: none; }
  .mg-launch-rail { padding-inline: 10px; }
  .mg-launch-stage { padding: 12px; }
  .mg-launch-brief { padding: 20px; }
  .mg-launch-briefhead { align-items: flex-start; }
  .mg-launch-briefhead em { display: none; }
  .mg-launch-op { grid-template-columns: 18px minmax(0, 1fr); }
  .mg-launch-op small { display: none; }
  .mg-launch-metrics { grid-template-columns: 1fr; }
  .mg-launch-foot { grid-template-columns: auto 1fr; gap: 14px; }
  .mg-launch-auto { display: none; }
}

/* ---- how we work: the process card row ----
   Rebuilt 2026-08-02 from the word-tab + stage split, which left the whole
   lower-left quadrant of the section empty once the tab list ran out of rows.
   The row component itself moved out to assets/process-cards.css on 2026-08-03
   when enterprise-software took it too -- read its header for the anatomy and
   the two hard constraints it holds. This file keeps the section frame and the
   head. */
#timeline {
  border-top: 1px solid rgba(10, 16, 60, .07);
  border-bottom: 1px solid rgba(10, 16, 60, .07);
  /* No section tint: the page canvas runs edge to edge here so the vertical
     rails stay continuous through the section instead of being painted over. */
  background: transparent;
}
#timeline.sub-section {
  padding-block: clamp(96px, 9vw, 140px);
}

/* ---- head: signpost and headline left, standfirst and CTA on the right ----
   The one section head on this page that is not centred. The process section
   owns the page's second CTA, and a centred head would have parked it under
   the cards where the previous build had it, 500px below the copy it belongs
   to. `align-items: end` sits the CTA on the headline's last baseline. */
/* 1.38 : .62 with a 44px gap is 720px for the headline at the 1088px text
   column. Measured: "live growth in two weeks." sets 652px at the 60px top of
   --fs-h2, so anything under ~680px breaks it after "two" and the headline
   runs to three lines. */
.pc-head {
  display: grid;
  grid-template-columns: minmax(0, 1.38fr) minmax(258px, .62fr);
  align-items: end;
  gap: clamp(22px, 2.9vw, 44px);
  margin-bottom: clamp(46px, 4.8vw, 68px);
}
.pc-head-main .h2 {
  margin-top: 16px;
}
/* The turn is its own line, the way the hero sets its h1: at 60px the two
   halves are 420px and 583px, and left to wrap they broke after "two". */
.pc-head-main .h2 .serif-i {
  display: block;
}
.pc-head-aside {
  padding-bottom: 6px;
}
/* Not a .lead: a lead sits under an h2 and runs the section width. This is a
   margin note beside the headline in a 340px column, so it takes --fs-body. */
.pc-standfirst {
  margin: 0;
  max-width: 46ch;
  font-size: 15px;
  line-height: 1.66;
  color: var(--muted);
}
.pc-cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 22px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
}
.pc-cta svg {
  transition: transform .2s var(--ease-micro);
}
.pc-cta:hover svg {
  transform: translateX(4px);
}

/* The row itself is assets/process-cards.css + assets/process-cards.js:
   enterprise-software runs the same component in its #implementation section
   (DESIGN-BOOK 25), so the anatomy, the fixed-height stage and the measured
   paint hides live in one file. What stays here is this page's business: the
   section frame above, the two-column head, and the head's own breakpoint. */
@media (max-width: 1080px) {
  .pc-head {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 22px;
  }
  .pc-head-main .h2 .serif-i {
    display: inline;
  }
  .pc-head-aside {
    padding-bottom: 0;
  }
  .pc-standfirst {
    max-width: 62ch;
  }
}


/* ---- platform comparison cards ---- */
#compare {
  background: transparent;
}
/* Centred like every other section head on the page, rather than anchored
   left on its own. The head carries .section-head.center too, so the shared
   treatment does the work; these only set the widths. */
#compare .mg-compare-head {
  max-width: 780px;
  margin-inline: auto;
  margin-bottom: 48px;
}
#compare .mg-compare-head .h2 {
  max-width: 18ch;
  margin-inline: auto;
}
#compare .mg-compare-head .lead {
  max-width: 620px;
  margin-inline: auto;
}
/* Built in the home page's "Two ways to work with us" card language
   (index.html #solutions): band-art media header with a serif word chip, an
   uppercase kicker with a blue index, the sans h3 scale, hairline rows, and a
   footer line. Same tokens throughout -- 16px radius, var(--line) frame,
   0 24px 54px shadow -- so the two sections read as one component family.
   The two differences from #solutions are content-driven: the rows here are
   dt/dd metric pairs rather than a tick list (there is nothing to tick on the
   agency side), and only the Uplane card carries a CTA, because only one of
   the two is an offer. */
.mg-compare-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  align-items: stretch;
  gap: clamp(14px, 1.6vw, 22px);
}
.mg-compare-card {
  position: relative;
  isolation: isolate;
  display: flex;
  min-width: 0;
  height: 100%;
  flex-direction: column;
  overflow: hidden;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--card, #fff);
  color: var(--ink);
  text-align: left;
  box-shadow: 0 19px 42px rgba(7, 16, 48, .085);
}

/* the outer rails belong to the page frame, not to the cards */
.mg-compare-card:first-child { border-left: 0; }
.mg-compare-card:last-child { border-right: 0; }

/* ---- media header ---- */
.mg-compare-media {
  position: relative;
  flex: 0 0 auto;
  min-height: clamp(240px, 24vw, 320px);
  overflow: hidden;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.mg-compare-card.is-agency .mg-compare-media {
  background-image: url('../assets/backgrounds/14.webp');
  /* The old way, drained of colour. Same band-art family as every other frame
     on the site, so the two cards are the same kind of object, but desaturated
     to near-grey: the contrast between the halves is carried by the artwork
     itself instead of by an arbitrary choice of two different photographs.

     Reviewed 2026-08-03: "shift it toward a brighter, more muted grey, using a
     subtle filter rather than a heavy one." saturate(.12) is a near-total kill
     that left the frame reading as a dark grey slab. .28 keeps a trace of the
     original blue so it still belongs to the band-art family, brightness goes
     1.02 -> 1.12 and contrast .95 -> .88 to open the midtones -- brighter and
     flatter, which is what "muted" asks for, rather than darker and duller.

     Reviewed 2026-08-04, superseding the trace of blue: fully black and white,
     and brighter again. saturate(.28) -> grayscale(1) kills the last of the
     chroma (measured max channel spread 68 -> 1), and brightness 1.12 -> 1.32
     with contrast .88 -> .84 lifts the mean composited luminance 103 -> 124
     without clipping the highlights (p95 lands at 151). Measured:
     tmp/mediatone.js. */
  filter: grayscale(1) contrast(.84) brightness(1.32);
}
.mg-compare-card.is-uplane .mg-compare-media {
  background-image: url('../assets/backgrounds/managed-growth-uplane-card.webp');
}
.mg-compare-media::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* No tint and no scrim, matching #solutions: the chip's own text-shadow is
   what keeps it legible, and the artwork gets to be artwork. */
.mg-compare-chip {
  position: absolute;
  left: clamp(26px, 3vw, 38px);
  bottom: 20px;
  z-index: 2;
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -.02em;
  color: #fff;
  text-shadow: 0 2px 12px rgba(3, 8, 35, .32);
}
/* The agency artwork is now brighter than it was (grayscale + brightness 1.32),
   which took this chip's composited contrast to 5.17:1 against the 5.7:1 floor
   in DESIGN-BOOK 16.3. A scrim is not available here -- the note above rules it
   out -- so the shadow carries it instead: a tight dark pass under the letter
   plus a wider soft one restores 6.10:1 without becoming an outline. Only the
   agency card: the Uplane artwork is unchanged and its chip still clears the
   floor on its own. Measured: tmp/chipcontrast.js. */
.mg-compare-card.is-agency .mg-compare-chip {
  text-shadow: 0 1px 3px rgba(3, 8, 35, .62), 0 2px 14px rgba(3, 8, 35, .5);
}

/* ---- copy ---- */
.mg-compare-copy {
  --mg-compare-pad: clamp(26px, 3vw, 38px);
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: var(--mg-compare-pad);
}
.mg-compare-kicker {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  font-family: var(--sans);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}
.mg-compare-card.is-uplane .mg-compare-kicker { color: var(--blue); }
/* #solutions makes both index numbers blue, because both of its cards are
   offers. Here blue carries the comparison, so the agency index stays grey and
   only Uplane's is blue -- otherwise the one spot of colour on a deliberately
   drained card is the wrong signal. */
.mg-compare-kicker .number {
  color: rgba(10, 16, 60, .42);
}
.mg-compare-card.is-uplane .mg-compare-kicker .number {
  color: var(--blue);
}
/* Serif at 500 on the card headline scale. It was sans 450 at 33px, which is
   exactly the mismatch #solutions fixed on the home page -- it made the card
   read as a different brand from every other card on the site. */
.mg-compare-card h3 {
  max-width: 15ch;
  margin: 18px 0 14px;
  font-family: var(--serif);
  font-size: clamp(21px, 2vw, 26px);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: -.01em;
  color: var(--ink);
}
.mg-compare-card > .mg-compare-copy > p {
  max-width: 440px;
  min-height: 75px;
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--muted);
}
/* DESIGN-BOOK 4.4 as the box rule 23.6 states it: no rule hangs in the air.
   These hairlines started and stopped on the copy column's own 38px inset and
   left a stub of card at each end. The list bleeds the padding out and re-adds
   it inside, so the rules reach the card while the type stays on the text
   column. Same fix as `#solutions .solution-card ul` on the home page, which
   runs the identical component. */
.mg-compare-card dl {
  margin: 26px calc(-1 * var(--mg-compare-pad, 0px)) 0;
  padding-inline: var(--mg-compare-pad, 0px);
  border-top: 1px solid var(--line);
}
.mg-compare-card dl > div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 52px;
  margin-inline: calc(-1 * var(--mg-compare-pad, 0px));
  padding-inline: var(--mg-compare-pad, 0px);
  border-bottom: 1px solid var(--line);
}
.mg-compare-card dt {
  color: var(--text);
  font-size: 14px;
  line-height: 1.55;
}
.mg-compare-card dd {
  margin: 0;
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  text-align: right;
}
.mg-compare-card.is-uplane dd {
  color: var(--blue);
}
.mg-compare-card.is-agency dd {
  color: var(--muted);
}

/* ---- footer ---- */
/* the CTA moved out to its own section, so the net-effect line is the only
   thing here and takes the full card width instead of half of it */
.mg-compare-footer {
  display: block;
  margin-top: auto;
  padding-top: 28px;
}
.mg-compare-fit {
  display: block;
  max-width: none;
  min-height: 62px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--muted);
}
.mg-compare-fit strong {
  display: block;
  margin-bottom: 3px;
  color: var(--ink);
  font-weight: 500;
}
/* no rule under the label: the arrow is the affordance (DESIGN-BOOK 14.3) */
.mg-compare-card .more {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex: none;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
}
.mg-compare-card .more svg {
  transition: transform .2s var(--ease-micro);
}
.mg-compare-card .more:hover svg {
  transform: translateX(3px);
}

@media (max-width: 760px) {
  #compare .mg-compare-head {
    margin-bottom: 34px;
  }
  .mg-compare-grid {
    grid-template-columns: 1fr;
  }
  .mg-compare-card > .mg-compare-copy > p {
    min-height: 0;
  }
  .mg-compare-fit {
    min-height: 0;
  }
  .mg-compare-media {
    min-height: clamp(180px, 42vw, 236px);
  }
}
@media (max-width: 440px) {
  /* The row outdents by --mg-compare-pad so its hairline reaches the card edge,
     then pads the content back by the same amount. Two things broke that pair
     here. The copy dropped to a flat 22px without telling the variable, which
     still read clamp(26px, 3vw, 38px) = 26px, and the row's `padding: 14px 0`
     shorthand zeroed the inline half of the compensation while the -26px margin
     stayed. Every spec row therefore hung 26px outside the card on both sides
     and was clipped by the viewport: "Output" read as "utput", "500+ ads per
     month" as "00+ ads per month", on all ten rows of both cards. The variable
     now carries the real pad and the row spends it. */
  .mg-compare-copy {
    --mg-compare-pad: 22px;
    padding: 22px;
  }
  .mg-compare-footer {
    align-items: flex-start;
    flex-direction: column;
    gap: 16px;
  }
  .mg-compare-card dl > div {
    align-items: flex-start;
    flex-direction: column;
    gap: 5px;
    padding: 14px var(--mg-compare-pad, 0px);
  }
  .mg-compare-card dd {
    text-align: left;
  }
}

/* No header/description reserve here: .mg-grid is display:block, so each cell
   is its own full-width row and has no horizontal neighbour to equalize with.
   A 2.4em/3-line reserve only opened a hole under the shorter blocks. */


/* ============================================================
   CTA closing band. Same frame as the home page closing section: squared,
   spanning the outer rails, artwork under a top-down gradient with the
   ken-burns breath, everything centred in .closing-inner. The quote takes
   the home page testimonial's treatment, in white since it sits on art.
   ============================================================ */
.cta-closing .cta-quote {
  margin: 0;
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(22px, 2.4vw, 32px);
  line-height: 1.4;
  letter-spacing: -.012em;
  color: #fff;
}
.cta-closing .cta-who { display: flex; align-items: center; justify-content: center; gap: 16px; margin: 0 0 28px; }
.cta-closing .cta-who > img { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; flex: none; }
.cta-closing .cta-who > span:not(.cta-org) { text-align: left; font-family: var(--sans); font-size: 14px; line-height: 1.45; color: rgba(255, 255, 255, .8); }
.cta-closing .cta-who strong { display: block; font-weight: 500; color: #fff; }
.cta-closing .cta-org { display: flex; align-items: center; min-height: 46px; padding-left: 18px; margin-left: 2px; border-left: 1px solid rgba(255, 255, 255, .3); }
.cta-closing .cta-org img { width: auto; height: 28px; max-width: 130px; object-fit: contain; filter: brightness(0) invert(1); }

/* `brightness(0) invert(1)` is the knockout for marks drawn in one flat ink: it
   maps every opaque pixel to black, then to white, so a colour logo lands on
   this art as a clean silhouette. A DUOTONE file is already dark-background
   artwork -- white wordmark, and an icon whose two tones are the mark -- so the
   same knockout flattens the icon into one white blob and throws away the only
   thing that makes it that icon. Those files pass through untouched, the way
   `.mgh-logo.is-alpecin img` does on the hero ticker for the same reason. */
.cta-closing .cta-org img.is-duotone { filter: none; }
.cta-closing .capture { margin-top: 30px; }

@media (max-width: 640px) {
  .cta-closing .cta-who { gap: 12px; margin-bottom: 22px; }
  .cta-closing .cta-who > img { width: 68px; height: 68px; }
  .cta-closing .cta-org { padding-left: 12px; }
  .cta-closing .cta-org img { height: 22px; max-width: 96px; }
}

/* ---- the "start scaling smarter" CTA ----
   This head used to carry a lone `.btn btn-blue` with an off-system 8px radius.
   It now takes the site's capture pill, same component as both closing bands, in
   its on-white `--light` tone. Outside a `.closing` the component is a
   full-width flex row with no centring, which is what `.closing .capture`
   supplies for the band variants, so the centred head restores it here. */
.section-head .capture {
  display: inline-flex;
  margin: 30px auto 0;
  text-align: left;
}


/* ---- HERO LOGO BANNER -------------------------------------------------
   The same client ticker the home page runs beneath its hero copy, brought
   onto this hero so the first screen of the Managed Growth page carries the
   proof the home page carries. Construction is copied from index.html rather
   than reinvented: two identical logo sets in a max-content track, translated
   -50% on a linear loop so the seam is never visible; the marks use their
   natural widths with one shared gap, just like the homepage strip; the mono
   set is knocked out white, and existing color artwork opts out as needed.

   Clipped on the measured inner rails, like the home page ticker, so it shares
   the page's margin geometry instead of floating on the hero's outer edge. */
.mgh-logos {
  --mgh-gap: 74px;
  position: absolute;
  left: calc(var(--rail-il, 48px) - var(--rail-o, 24px));
  right: calc(var(--rail-ir, 48px) - var(--rail-o, 24px));
  /* Center the 46px strip in the band beneath the CTA divider. */
  bottom: 52px;
  z-index: 3;
  height: 46px;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.mgh-logos-label {
  display: block;
  margin-bottom: 0;
}

.mgh-logos-track {
  /* Moved by assets/marquee.js (data-marquee on the track), the same measured
     loop as the home page ticker; see the note there. Speed in px/s. */
  --marquee-speed: 35;
  display: flex;
  align-items: center;
  width: max-content;
  height: 100%;
}

.mgh-logos-set {
  display: flex;
  align-items: center;
  flex: none;
  gap: var(--mgh-gap);
  padding-right: var(--mgh-gap);
}

.mgh-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: auto;
  height: 42px;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  box-sizing: border-box;
}

.mgh-logo img {
  display: block;
  width: auto;
  height: auto;
  max-width: 112px;
  max-height: 24px;
  object-fit: contain;
  /* single-colour silhouette art: brightness(0) flattens the mark, invert(1)
     lifts it to white */
  filter: brightness(0) saturate(100%) invert(1);
  opacity: 1;
}

/* Per-mark optical sizing, carried over from the home page ticker: a square
   plate, a stacked block and a long wordmark do not read equal at one cap. */
.mgh-logo.is-magic img { max-height: 27px; }
.mgh-logo.is-kalshi img { height: 24px; max-height: 24px; }
.mgh-logo.is-eharmony img { height: 20px; }
.mgh-logo.is-alpecin img { height: 31px; max-height: 31px; filter: none; opacity: 1; }
.mgh-logo.is-sunday img { width: auto; max-width: 138px; max-height: 38px; opacity: .96; }
.mgh-logo.is-misterspex img,
.mgh-logo.is-aonic img { max-height: 21px; }
.mgh-logo.is-enpal img { max-height: 24px; }
.mgh-logo.is-airup img { max-height: 28px; }

@keyframes mghScroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* Below 900px the hero copy grows and the ticker would collide with the CTA
   row, so it drops its fixed slots and rides a tighter, shorter band. */
@media (max-width: 900px) {
  .mgh-logos {
    --mgh-gap: 40px;
    bottom: 22px;
    height: 32px;
    left: var(--rail-i, 24px);
    right: var(--rail-i, 24px);
  }
  .mgh-logos-track { --marquee-speed: 45; }
  .mgh-logo { width: auto; height: 30px; }
  .mgh-logo img { max-height: 20px; }
  .mgh-logo.is-sunday img { width: 108px; max-width: 108px; max-height: 30px; }
  .mgh-logo.is-alpecin img { height: 25px; max-height: 25px; }
}

/* --------------------------------------------------------------------------
   PHONE. Two notes from the review, both on the hero.

   "Make the logo banner a little smaller on mobile": the ticker rides a 32px
   band with 20px marks under a headline, a lead, two CTAs and the badges. At
   26px / 16px it still reads as a client row and gives the copy above it back
   the ~10px it was pressing into.

   "Expert Strategy + latest AI technology": the hero lead runs three lines on a
   phone for a claim that is one. The long version stays in the markup for every
   width that has room; the phone shows the short one, the same swap the
   enterprise hero uses.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .mgh-logos {
    --mgh-gap: 30px;
    height: 26px;
    bottom: 18px;
  }
  .mgh-logos-track { --marquee-speed: 50; }

  .mgh-logo { height: 24px; }
  .mgh-logo img { max-height: 16px; }
  .mgh-logo.is-sunday img { width: 88px; max-width: 88px; max-height: 24px; }
  .mgh-logo.is-alpecin img { height: 20px; max-height: 20px; }
  .mgh-logo.is-aonic img,
  .mgh-logo.is-misterspex img { max-height: 15px; }

  /* Reviewed again as "this logo park Kalshi is a little large". The 16px cap
     above is `.mgh-logo img`, one class deep, so every mark that carries its own
     optical size at `.mgh-logo.is-x img` -- two classes -- outranked it and kept
     its desktop height: Kalshi and Enpal stayed at 24px, Magic Mind at 27 and
     air up at 28, against a 16px row. Each one is restated here at the same
     two-class specificity, scaled by the 16/24 the default cap takes, so the
     row keeps its optical balance at the smaller size instead of flattening. */
  .mgh-logo.is-kalshi img { height: 16px; max-height: 16px; }
  .mgh-logo.is-enpal img { max-height: 16px; }
  .mgh-logo.is-magic img { max-height: 18px; }
  .mgh-logo.is-airup img { max-height: 19px; }
  .mgh-logo.is-eharmony img { height: 13px; }

  body .sub-hero-dark .lead:not(.lead--phone) { display: none; }
  body .sub-hero-dark .lead--phone { display: block; }
}

/* PHONE: the closing band goes to the edges.
   Reviewed as "forget the margins to the left and the right for the image in the
   background, this can go to the edges". The band is a photograph with copy on
   it, and a 24px white margin around it on a 390px screen reads as a mistake
   rather than as a frame. It outdents by the wrap's own inset.
   Scoped per surface rather than shared: the enterprise page's closing already
   sits on a full-bleed wrap, and the same rule there pushed it 24px past the
   viewport on both sides. */
@media (max-width: 640px) {
  .closing {
    margin-inline: -24px;
  }

  /* Reviewed as "there is too much white space above here" on the apply band.
     Measured from the pager under the comparison cards to this band's eyebrow:
     150px of nothing -- the dots' own 20px, the section above closing on 44,
     and then the band opening with another 56 of its own. The band's top inset
     is the one of the three that is only decoration, so it takes the cut; its
     foot keeps 56 because what follows it is the footer photograph. */
  .closing--quiet {
    padding-top: 24px;
  }
}

/* --------------------------------------------------------------------------
   PHONE: the two long card rows become swipe tracks, like the enterprise page.

   "I want swipeable cards from right to left with the dots underneath, the
   animations compressed into smaller cards that fit onto half of the screen"
   (#team, six capabilities at 716-766px each = 4500px of column) and "a slider
   so that you get that this is a comparison between traditional agency and
   uplane" (#capabilities, two 848px cards).

   Both rows carry data-m-swipe, so the shared track and its dots come from
   assets/site.css and assets/site.js. What is page-specific is the compression:
   the animation stage goes 399px -> 200px and its type comes down with it, and
   the bullet list keeps only the first three items. Half a screen, as asked.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  /* THE CARD IS FRAMED ON ALL FOUR SIDES.
     Reviewed as "left border missing" on the first card and "right border
     missing" on the last. The shared track draws `> * + *` a top and left edge
     (assets/site.css), which is the rule for a COLLAPSED column where each card
     borrows its neighbour's line -- but these cards sit 12px apart, so the
     first had nothing on its left and the last nothing on its right, and every
     card was missing its bottom. Each one draws its own frame here. */
  body .mg-cell {
    border: 1px solid var(--line);
    padding: 0 0 4px;
  }

  /* THE ARTWORK LEADS.
     Reviewed as "please place these cards above the text in those swipeable
     cards, for all of the cards". The desktop cell alternates artwork left and
     copy right; stacked, that had become numeral, heading, paragraph, bullets
     and THEN the screen, so a swipe through six cards showed six blocks of
     grey type and you only met the picture at the bottom of each one. The
     stage takes the first row and everything else steps down one.

     Row 6 stays declared (`auto ... 1fr` on .mg-cell) and simply resolves to
     zero: the rows are content-sized and every card is the same height, so
     nothing collects there. */
  body .mg-cell > .mg-stage,
  body .mg-cell:nth-child(even) > .mg-stage,
  body .mg-cell:nth-child(odd) > .mg-stage {
    grid-row: 1;
  }

  body .mg-cell::before,
  body .mg-cell:nth-child(even)::before,
  body .mg-cell:nth-child(odd)::before {
    grid-row: 2;
    /* the numeral's desktop top inset was the card's own breathing room at the
       top of the column; under the artwork it only has to clear it */
    padding-top: 18px;
  }

  body .mg-cell > .mg-label,
  body .mg-cell:nth-child(even) > .mg-label,
  body .mg-cell:nth-child(odd) > .mg-label { grid-row: 3; }

  body .mg-cell > h3,
  body .mg-cell:nth-child(even) > h3,
  body .mg-cell:nth-child(odd) > h3 { grid-row: 4; }

  body .mg-cell > p,
  body .mg-cell:nth-child(even) > p,
  body .mg-cell:nth-child(odd) > p { grid-row: 5; }

  body .mg-cell > .mg-bullets,
  body .mg-cell:nth-child(even) > .mg-bullets,
  body .mg-cell:nth-child(odd) > .mg-bullets { grid-row: 6; }

  /* THE SCREEN INSIDE THE CARD.
     Reviewed as "make all cards the same exact height so that when scrolling
     through them they look very aligned. Each background image should be the
     same height at the start and end. Each graphical element can have a
     different size but they should be in a size where you can actually read
     what is going on there. They should always have some distance to the border
     of the card."

     Three numbers do all of it, and they are derived from each other rather
     than picked one at a time:

       --mg-m-stage  the artwork box, FIXED, so the six photographs start and
                     end on the same line however long the copy above them runs
       --mg-m-inset  the panel's distance to the card edge on all four sides.
                     The photograph still bleeds to the edge (it is positioned
                     against the stage, not padded by it); it is the SCREEN that
                     is inset, which is what the note asks for.
       --mg-m-zoom   the panel's scale.

     The panel is a FLUID box (width: min(100%, 500px)), not a fixed 500px one,
     so the inset costs no type size: the panel keeps its 0.6 scale and simply
     lays out on a narrower canvas. That is why "distance to the border" and
     "big enough to read" are not in tension here.

     The panel's height is the stage's inner box divided by the zoom, so every
     screen is exactly as tall as the space it is given -- no panel sizes itself
     to its own content, which is what made the six boxes unequal before. */
  body .mg-cell {
    --mg-m-stage: 262px;
    --mg-m-inset: 12px;
    --mg-m-zoom: .63;
  }

  /* The stage's height is set by `.mg-cell > .mg-stage,
     .mg-cell:nth-child(even) > .mg-stage, .mg-cell:nth-child(odd) > .mg-stage`
     at (0,3,1) with a 390px floor, so a two-class rule here could not reach it.
     Matched selector for selector, plus the body prefix. */
  body .mg-cell > .mg-stage,
  body .mg-cell:nth-child(even) > .mg-stage,
  body .mg-cell:nth-child(odd) > .mg-stage {
    height: var(--mg-m-stage);
    min-height: 0;
    padding: var(--mg-m-inset);
  }

  /* `zoom`, not `transform: scale()`. The panel is a static box ~367px tall
     inside the stage: a transform scales the PAINT and leaves the layout box,
     so the panel still occupied 367px, sat 86px down the stage and ran out of
     the bottom of it. zoom scales the box as well, so the stage can centre what
     is left. */
  body .mg-cell .mg-panel {
    zoom: var(--mg-m-zoom);
    transform: none;
    /* px inside a zoomed box are zoomed px, so this resolves to exactly the
       stage's inner height on screen. Fixed on both ends: a min-height alone
       let the two densest panels (A at 370 design px, E at 368) grow past it
       and the others sit short. */
    height: calc((var(--mg-m-stage) - 2 * var(--mg-m-inset)) / var(--mg-m-zoom));
    min-height: 0;
  }

  /* Reviewed as "please shorten the text". Each bullet was a bold label plus a
     25-word gloss, and three of them ran 330px of grey type above a 200px
     screen -- the card was a page of body copy with a thumbnail under it. The
     labels carry the scan on a phone; the gloss is wrapped in .mg-btail in the
     markup purely so it can come off here, and every width above 640px still
     gets the full sentence. */
  body .mg-cell .mg-bullets .mg-btail {
    display: none;
  }

  body .mg-cell .mg-bullets li b {
    font-weight: 500;
    color: var(--ink);
  }

  /* THE COPY ROWS ARE FIXED, so the artwork below them starts on the same line
     in every card. The cards were already equal in overall height (the swipe
     track stretches them), but their INSIDES were not: the paragraph runs three
     lines on "Complete funnels" and five on "Strategy that moves with the
     market", so the photograph began at y=266 on one card and y=305 on the
     next and the short cards carried the difference as dead space at the
     bottom. Two lines of heading and four of body copy, everywhere.

     The heading is a floor, not a cap -- no title on this page runs past two
     lines at 16px, and a title that did would push the row rather than lose a
     word. The paragraph is a cap: it is a gloss on the heading, the bullets
     under it carry the detail, and a fifth line only exists on two of the six
     cards. */
  body .mg-cell h3 {
    margin-top: 14px;
    min-height: 40px;
    font-size: 16px;
    line-height: 1.25;
  }

  body .mg-cell > p {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    overflow: hidden;
    margin-top: 8px;
    height: 78px;
    font-size: 13px;
    line-height: 1.5;
  }

  /* On a 320px screen the same sentences run five and six lines, so a flat
     four-line box would cut four of the six cards. The box takes a fifth line
     there and the cards stay equal to each other, which is what the alignment
     asks for; only the one 6-line paragraph is still trimmed. */
  @media (max-width: 360px) {
    body .mg-cell > p {
      -webkit-line-clamp: 5;
      height: 97.5px;
    }
  }

  body .mg-cell > .mg-bullets,
  body .mg-cell:nth-child(even) > .mg-bullets,
  body .mg-cell:nth-child(odd) > .mg-bullets {
    margin-top: 10px;
    gap: 6px;
    padding-bottom: 0;
  }

  body .mg-cell .mg-bullets li {
    font-size: 12.5px;
    line-height: 1.4;
  }

  /* three of five: the first three name the capability, the last two are
     examples of it, and the card has to fit a screen */
  body .mg-cell .mg-bullets li:nth-child(n+4) {
    display: none;
  }

  /* ------------------------------------------------------------------
     THE ARTWORK, SIMPLIFIED FOR A PHONE.

     Six notes from one pass over the panels, all of them the same problem
     seen six times: the panels are drawn at ~390 design px and shown at
     .63, so anything the desktop sets in single-digit px arrives on a
     phone as a smudge, and anything sized to a desktop column arrives too
     narrow for its own label.
     ------------------------------------------------------------------ */

  /* THE LIST STANDS OFF THE CARD'S FOOT.
     Reviewed as "fix the distances from here to the background, it looks a
     little messy": the copy above steps 8px from heading to paragraph and
     10px from paragraph to bullets, and then the last bullet's box ended
     exactly on the photograph -- 0px, measured on all six cards. 16px is the
     next step in that ladder. With the artwork now at the top of the card,
     the same 16px is what keeps the last bullet off the card's bottom edge. */
  body .mg-cell > .mg-bullets,
  body .mg-cell:nth-child(even) > .mg-bullets,
  body .mg-cell:nth-child(odd) > .mg-bullets {
    padding-bottom: 16px;
  }

  /* THREE ADS, NOT NINE.
     Reviewed as "for mobile we can just have three ads in here so they are
     bigger". The grid is 2 x 5 at 46.5px a row, which on a phone is a
     21px-wide thumbnail: nine of them, none legible. Three stacked squares
     use the same 208 design px of column and are 62px each, three times
     the area. Square, not the column's full width: the creatives are
     portrait and a full-width row would be a 1.6:1 letterbox of them.
     The first three include both `hot` tiles, so the highlight the
     animation plays still has something to land on. */
  body .mg-cell .mg-adgrid {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: auto;
    justify-items: center;
    gap: 6px;
    height: auto;
  }

  body .mg-cell .mg-adgrid .mg-adtile {
    width: min(100%, 62px);
    aspect-ratio: 1;
  }

  body .mg-cell .mg-adgrid .mg-adtile:nth-child(n+4) {
    display: none;
  }

  /* THE FUNNEL CARD'S THUMBNAIL STRIP, BIG ENOUGH TO BE AN AD.
     Reviewed as "please replace those ads with the latest Aonic ads, also make
     it a little bigger so we can see them actually. On mobile change size, but
     replace ads also on desktop."

     The strip is the row of creatives the two landing pages under it are built
     from, and at 26px against the panel's .63 scale it arrived 16px wide: four
     grey stamps. 52px design is 33px on screen, four times the area, and the
     row still sits inside the strip's own white plate.

     The four sources are swapped in the markup, so desktop takes them too:
     assets/cases/aonic/aonic-ad-0*.webp, the current set, in place of four
     older cdn hashes. */
  body .mg-cell .mg-thumbrow img {
    width: 52px;
    height: 52px;
    border-radius: 8px;
  }

  body .mg-cell .mg-thumbrow {
    gap: 6px;
  }

  /* THE COLUMN TAGS FIT THEIR COLUMNS.
     Reviewed as "make sure that real-time trends fits into this box". The
     tag is `white-space: nowrap` at its column's width, so the longest of
     the three simply ran out through its own rounded box: measured 93px of
     text in a 73px tag at 320px, and 103 in 106 at 390px -- fitting by
     3px, which is why it looked wrong at every size. The type comes down
     half a point and the side padding from 11px to 8px, and the third
     label swaps to its short twin in the markup, so it reads "Trends". All three then clear their column at 320px with room over, and
     the trio still reads as one row of boxes. */
  body .mg-cell .mg-tag {
    padding: 3px 8px;
    font-size: 10.5px;
  }

  body .mg-cell .mg-tagfull {
    display: none;
  }

  body .mg-cell .mg-tagshort {
    display: inline;
  }

  /* THE DESTINATIONS ARE LOGOS, AND THE LOGOS ARE THE POINT.
     Reviewed as "for mobile just have the logos here", and then as "these
     logos are way too small, please redesign so that they are way larger,
     maybe make a 2x2 matrix here where we see the logo is way bigger in the
     cards".

     The word goes first: Slack, Teams, WhatsApp and Email set at 8px arrive at
     5px on screen, so each chip was a legible logo beside an illegible one.
     That left four 141x22 chips carrying a 10px mark -- 89px of chip and 6px
     of logo once the panel's .63 scale is applied.

     Two by two is what buys the size. The column's own width splits into two
     66px cells, the chip grows to 46 and the mark to 22 -- three and a half
     times the area it had -- and the block still ends inside the panel (162 +
     101 against 378 of panel).

     The stem was dropped with the column on the grounds that a vertical line
     branching into each chip is a true drawing of a stacked list and a false
     one of a grid. Reviewed since as "check that there's still a connection
     from the bell to these four buttons, just like on desktop", which is
     right: proximity is not a connection, and the bell then fed nothing.

     The desktop drawing holds for a grid with one change -- each row is a RUN
     rather than a stop. The trunk still hangs off the bell's right edge and
     still ends on the last branch, one stub still enters every chip, and the
     right column's stub bridges the column gap from the chip beside it. So
     the picture is two rows of two stops on one bus, which is what a 2x2
     actually is, and all four chips sit on the line.

     That only works if the gap the right-hand stub has to cross IS the stub:
     the column gap is --mg-stub here, not 9px. The other three numbers are
     unchanged and still locked to each other -- the bell's right offset is
     the block width plus the stub (40 = 36 + 4), so the trunk lands tangent
     to the bell without being told where the bell is. */
  body .mg-cell .mg-notes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--mg-stub);
    row-gap: 9px;
    /* half a chip: 22px of mark and 12px of padding either side, so the trunk
       stops on the bottom row's branch instead of running past it */
    --stem-drop: 23px;
  }

  body .mg-cell .mg-notes .note {
    justify-content: center;
    gap: 0;
    padding: 12px 6px;
    font-size: 0;
  }

  body .mg-cell .mg-notes .note svg {
    width: 22px;
    height: 22px;
  }

  /* THE PRODUCT RAIL KEEPS ITS MARK.
     Reviewed as "for mobile just have the icon here for uplane". Same 8px
     -> 5px: the glyph reads, the wordmark beside it does not. */
  body .mg-cell .dash-side .dl b {
    display: none;
  }

  body .mg-cell .dash-side .dl {
    justify-content: center;
    gap: 0;
  }

  /* AND THE HANDLE ON EVERY AD BECOMES A MARK.
     Reviewed as "reduce complexity, small text should be just a black
     line, like the uplane writing in the ads". "Uplane" is set at 6.5px in
     the feed cards and 5px in the fan, which is 4px and 3px on a phone --
     under the size at which a string is a string. The second line of that
     handle is already a bar for exactly this reason (see .mg-post-meta i);
     the first line becomes one too, at the width the word occupied and a
     step darker, so the pair still reads as a name over a caption. */
  body .mg-cell .mg-post-meta b {
    display: block;
    width: 22px;
    height: 4px;
    border-radius: 2px;
    background: rgba(20, 18, 15, .55);
    font-size: 0;
    overflow: hidden;
  }

  /* The fan's three variant cards set the same handle at 5px through a
     three-class rule, which outranks the one above; they get the mark at
     their own scale, sized against their own caption bar (21 x 2). */
  body .mg-cell .mg-e .mg-post.ev .mg-post-meta b {
    width: 15px;
    height: 3px;
    font-size: 0;
  }

  /* the comparison pair */

  /* This row keeps its own gap -- the desktop `clamp(14px, 1.6vw, 22px)` sits
     later in the cascade than the shared track's, and resolves to 14px down
     here. The shared trailing spacer sizes itself as `6% - --m-swipe-gap`
     (assets/site.css), so it has to be told that number or the last card comes
     to rest 2px off centre. Same value, declared rather than assumed. */
  .mg-compare-grid {
    --m-swipe-gap: 14px;
  }

  body .mg-compare-card {
    border: 1px solid var(--line);
    /* `height: auto`, overriding the base `height: 100%`.
       Reviewed as "please have same height and same length as for the one on
       the right". The 100% is for the desktop grid, whose row is
       `grid-auto-rows: 1fr`; in the phone swipe track the row's height is
       content-driven, so the percentage resolved against an indefinite height
       -- and a card whose cross size is not `auto` is exempt from the row's
       `align-items: stretch`. So each card sized to its own copy and the
       Uplane card, whose net-effect line runs one line longer, came out taller:
       measured 591.3 against 610.9 at 364px and 611.4 against 667.7 at 320px.
       With auto, stretch applies and the pair shares the row's height at every
       width. */
    height: auto;
  }

  body .mg-compare-media {
    height: 132px;
    min-height: 0;
  }

  body .mg-compare-copy {
    /* The row outdents by --mg-compare-pad so its hairline reaches the card
       edge and pads the content back by the same amount, so the variable has to
       agree with the padding actually set here or every spec row hangs outside
       the card. The 440px block above sets 22px; this one is later and narrower
       and was setting 16px without telling the variable. */
    --mg-compare-pad: 16px;
    padding: 16px 16px 18px;
  }

  /* Reviewed as "here is a lot of space wasted, please make it a little tighter
     to keep it easier to overview, the height of it should be smaller, the
     width is good".

     The spec rows were the whole of it. Below 440px they break the term over
     its value in a column, which costs 71px a row against a 300px-wide card
     that holds `Optimization` beside `Algorithmic and real time` on one line
     with 27px to spare. They go back to one line, the padding comes in, and the
     steps around the list come down with them. Measured 776px a card before,
     585px after, with nothing dropped. */
  body .mg-compare-card dl > div {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: 0;
    padding: 10px var(--mg-compare-pad, 16px);
  }

  body .mg-compare-card dd {
    text-align: right;
  }

  body .mg-compare-card dl {
    margin-top: 16px;
  }

  body .mg-compare-card h3 {
    margin: 12px 0 10px;
  }

  /* THE NET EFFECT STARTS ON ONE LINE IN BOTH CARDS.
     Reviewed as "please have this at the same height as the text in the right
     card so that the net effect is at the same height and the text starts at
     the same height while the entire panel stays the same size".

     Two things were pulling it apart, and only one of them was the footer.
     The intro paragraph runs three lines on the agency card and two on the
     Uplane one, which starts the spec list 20px lower on the left; and the
     footer is bottom-anchored (`margin-top: auto`), so its own text -- four
     lines against three -- starts wherever the taller of the two lands. The
     two cards are the same height throughout; it was the insides that
     disagreed. Measured before: the net effect began at y=508 and y=488.

     So the paragraph takes a three-line floor, which puts the spec list on one
     line in both, and the footer stops being bottom-anchored and simply takes
     the room that is left. Nothing changes size: the track already gives the
     two cards one height, and the footer was already filling that space -- it
     was just filling it above its text rather than below it. */
  body .mg-compare-card > .mg-compare-copy > p,
  body .mg-compare-card p {
    min-height: 62px;
    min-height: 3lh;
  }

  body .mg-compare-footer {
    flex: 1 1 auto;
    margin-top: 0;
  }

  body .mg-compare-footer {
    padding-top: 16px;
  }

  body .mg-compare-copy h3 { font-size: 16px; line-height: 1.25; }
  body .mg-compare-copy p { font-size: 13px; line-height: 1.5; }
  body .mg-compare-copy li { font-size: 12.5px; line-height: 1.4; }

  /* The 388px block in the middle of each card is a definition list of six
     rows. Four of them carry the comparison; the last two repeat it with
     examples, and the point of the slider is that you can hold both cards in
     your head at once. */
  body .mg-compare-copy dl { font-size: 12.5px; }
  body .mg-compare-copy dt { font-size: 12.5px; }
  body .mg-compare-copy dd { font-size: 12.5px; line-height: 1.4; }
  body .mg-compare-copy dl > *:nth-child(n+9) { display: none; }
}

/* --------------------------------------------------------------------------
   PHONE: the launch process becomes a stack of clickable bars.

   "Put this section into a drop down where each of the images becomes a small
   bar that is like a quarter of the size of the first one. The headlines, like
   Book a Demo and Strategy Call, are written in those and you can drop down to
   see the text. It becomes more like a flow chart that is clickable."

   1928px of column, five steps each with a 200px photograph and its copy, for a
   section whose job is to say "these are the five steps". So the photograph
   becomes a 58px band -- roughly the quarter asked for -- with the step's own
   headline set on it, and the copy under it opens and closes.

   The headline moves onto the band by being lifted out of the flow (absolute,
   over the artwork) rather than by moving markup: it lives inside .pc-body,
   which is the part that collapses, and it has to stay visible when the panel is
   shut. The component's own click handler already toggles `.on`, so nothing new
   drives it.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  /* Reviewed as "please move this section under the four points" and "put this
     under the drop down of the four": the standfirst and the strategy-call link
     are a margin note beside a headline in the desktop two-column head, and
     stacked they became 120px of grey text between the headline and the thing
     the section is actually about. They read as a closing note under the four
     steps instead.

     .pc-head is a sibling of .pc-row, not a parent, so order alone cannot do
     it. `display: contents` dissolves the head and hands its two halves to the
     section wrap, which orders all three. The head's own bottom margin goes
     with it, so the headline carries the gap itself. */
  body #timeline .wrap {
    display: flex;
    flex-direction: column;
  }

  body #timeline .pc-head {
    display: contents;
  }

  body #timeline .pc-head-main {
    order: 1;
    margin-bottom: 34px;
  }

  body #timeline .pc-row {
    order: 2;
  }

  body #timeline .pc-head-aside {
    order: 3;
    margin-top: 28px;
    padding-bottom: 0;
  }

  body #timeline .pc-row {
    display: grid;
    grid-template-columns: 1fr;
    align-items: start;
    gap: 8px;
    height: auto;
  }

  body #timeline .pc-card,
  body #timeline .pc-card.on,
  body #timeline .pc-card:not(.on):hover {
    position: relative;
    height: auto;
    overflow: hidden;
    cursor: pointer;
    background: #fff;
  }

  body #timeline .pc-card { --pc-media-h: 58px; }

  body #timeline .pc-media,
  body #timeline .pc-card.on .pc-media {
    height: 58px;
    opacity: 1;
  }

  /* CALM BANDS.
     Reviewed as "please, for mobile, select images that are much less busy in
     the background so it looks much cleaner". Two things were making these read
     as busy, and only one of them was the choice of picture.

     The band is 58px of a 1400px-tall photograph, so WHICH 58px matters more
     than which photograph: `object-position: center top` is the desktop art
     direction, chosen for a 200px frame, and at 58px it landed the crop on the
     hard diagonal each image carries. Measured as luminance spread across the
     rendered band (tmp/bandcrop.mjs), the four bars scored sd 21.4 / 30.6 /
     24.5 / 6.0 -- the launch bar had a black streak straight through its label.

     So each bar now takes the calmest band its own picture holds, and three of
     the four also swap to a picture whose calm band is calmer still and keeps
     the blue-blue-red-red progression (the <picture> sources are phone-only, so
     the desktop composition is untouched). After: sd 2.8 / 6.1 / 2.2 / 2.1,
     with mean luminance 25 / 70 / 84 / 94 -- every one of them clears 6:1
     against the white label. */
  body #timeline .pc-card:nth-child(1) .pc-media img { object-position: 50% 65%; }
  body #timeline .pc-card:nth-child(2) .pc-media img { object-position: 50% 25%; }
  body #timeline .pc-card:nth-child(3) .pc-media img { object-position: 50% 70%; }
  body #timeline .pc-card:nth-child(4) .pc-media img { object-position: 50% 70%; }

  /* the headline, on the band.
     `margin: 0` is the fix for "the book demo strategy call line is misaligned
     in this box": the base component gives .pc-title a 12px top margin, which
     an absolutely positioned box still honours on top of `top: 0`, so every
     label sat 12px low in a 58px band -- its centre at 41px against the band's
     29px. Measured on all four cards before and after. */
  body #timeline .pc-title,
  body #timeline .pc-card.on .pc-title {
    position: absolute;
    top: 0;
    left: 52px;
    right: 46px;
    z-index: 3;
    display: flex;
    align-items: center;
    height: 58px;
    min-height: 0;
    margin: 0;
    padding: 0;
    overflow: visible;
    text-shadow: 0 2px 10px rgba(3, 8, 35, .4);
  }

  /* Reviewed as "input pick numbers 1, 2, 3, 4 across the next steps". The
     step number is already in the markup for the desktop composition and was
     simply hidden here; on the band it goes where the label used to start, and
     the label moves right by its column. Same 01-04 tokens the section uses at
     every other width rather than bare digits, so the two read as one set. */
  body #timeline .pc-index {
    display: flex;
    position: absolute;
    top: 0;
    left: 16px;
    z-index: 3;
    align-items: center;
    height: 58px;
    margin: 0;
    padding: 0;
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .06em;
    color: rgba(255, 255, 255, .74);
    text-shadow: 0 2px 10px rgba(3, 8, 35, .4);
  }

  body #timeline .pc-title > span { position: static; }
  body #timeline .pc-title .pc-w { display: none; }

  body #timeline .pc-title .pc-c {
    font-family: var(--sans);
    font-weight: 500;
    font-size: 14px;
    line-height: 1.25;
    color: #fff;
  }

  /* the affordance, drawn on the band */
  body #timeline .pc-card::after {
    content: "";
    position: absolute;
    top: 24px;
    right: 20px;
    z-index: 3;
    width: 9px;
    height: 9px;
    border-right: 2px solid rgba(255, 255, 255, .9);
    border-bottom: 2px solid rgba(255, 255, 255, .9);
    transform: rotate(45deg);
    transition: transform .24s var(--ease-micro), top .24s var(--ease-micro);
  }

  body #timeline .pc-card.on::after {
    top: 28px;
    transform: rotate(-135deg);
  }

  /* The panel collapses INSIDE the body, not the body itself. Clipping the body
     clipped the headline with it -- the title is absolutely positioned but still
     a descendant, and `overflow: hidden` on an ancestor clips out-of-flow
     children too, so every shut bar lost its label. The body keeps its box and
     the kicker plus the description are what open and close. */
  body #timeline .pc-body,
  body #timeline .pc-card.on .pc-body {
    padding: 0;
    overflow: visible;
    max-height: none;
  }

  /* OPEN AND CLOSE ARE THE SAME MOVE, RUN IN OPPOSITE DIRECTIONS.
     Reviewed as "when I open a new one, this opens first and then the other
     one closes; it should happen exactly simultaneously so it feels like one
     smooth transition".

     The class swap was already simultaneous -- show() toggles every card in one
     pass -- and both panels already ran .34s. What was not simultaneous was
     what those .34s were spent ON. The panel opened and closed by animating
     `max-height` between 0 and 700px against ~62px of actual content, so 90% of
     the declared travel was invisible: opening, the panel reached its real
     height in the first ~9% of the curve and then sat there; closing, nothing
     moved for the first ~90% and it dropped at the end. Sampled per frame
     (tmp, 390px): at 66ms the opening card had done 63% of its travel and the
     closing one 3%; at 216ms it was 97% against 27%. That IS the "opens first,
     then the other closes" -- one clock, two different mappings onto it.

     `grid-template-rows: 0fr -> 1fr` animates the row to the content's OWN
     height, so a card's progress and its height are the same number and the
     two panels are mirror images at every frame. It is the mechanism the same
     component already uses above 1080px (.pc-more), and .pc-more > * carries
     the `min-height: 0; overflow: hidden` it needs.

     The kicker is one 17px line of text, so it has no element child to collapse
     and stays on max-height -- capped at 20px rather than 700, which is the
     same 1:1 mapping to within three pixels. */
  body #timeline .pc-kicker,
  body #timeline .pc-card.on .pc-kicker {
    display: block;
    max-height: 20px;
    overflow: hidden;
    transition: max-height .34s var(--ease-micro),
                opacity .24s ease,
                margin .34s var(--ease-micro);
  }

  body #timeline .pc-more,
  body #timeline .pc-card.on .pc-more {
    display: grid;
    grid-template-rows: 1fr;
    max-height: none;
    overflow: hidden;
    transition: grid-template-rows .34s var(--ease-micro),
                opacity .24s ease,
                margin .34s var(--ease-micro);
  }

  body #timeline .pc-card.on .pc-kicker { margin: 14px 16px 0; }
  body #timeline .pc-card.on .pc-more { margin: 4px 16px 18px; }

  body #timeline .pc-card:not(.on) .pc-kicker {
    max-height: 0;
    margin: 0 16px;
    opacity: 0;
  }

  body #timeline .pc-card:not(.on) .pc-more {
    grid-template-rows: 0fr;
    margin: 0 16px;
    opacity: 0;
  }

  body #timeline .pc-bar { display: none; }

  @media (prefers-reduced-motion: reduce) {
    body #timeline .pc-body,
    body #timeline .pc-card::after { transition: none; }
  }
}
