/* rx-block: rx-compare */

/* ==========================================================================
   Comparison table — Figma 3111:6339, heading 3111:6335
   --------------------------------------------------------------------------
   THE ROWS ARE INDEPENDENT GRIDS, not one grid with display: contents on the
   rows. Both give aligned columns; only this one lets the row keep a box, and
   the row needs a box because the rules are drawn per row and because
   role="row" on an element with no box is a bet on how each browser maps
   display: contents into the accessibility tree. Every row shares one template
   held in --rx-compare-cols, so the columns cannot drift.

   THE CARD IS ABSOLUTE, and that is not a shortcut. Figma runs it 78 above the
   header rule and past the last row (3111:6342, 1428.22 -> 2097.22 against a
   table of 1506.22 -> 1943.74), so it deliberately overhangs the table at both
   ends. A grid item cannot do that, and `grid-row: 1 / -1` cannot span rows
   that are all implicit — -1 resolves to the end of the EXPLICIT grid, which
   here is line 1, and the card collapses to nothing.

   Measured at the 1512 frame, taking the RULES as the column edges (the rules
   are what a reader sees as the column; the text inside them is inset):
     col 1   134.02 -> 502.18   368.16
     col 2   520.52 -> 907.02   386.50
     col 3   924.02 -> 1406.02  482.00   <- the card
   Gaps 18.34 and 17.00; call it 17.5 either side. Cells total 1236.66, which
   is --rx-container-max (1240) to within 3px, so this is an ordinary
   container and not a fourth width in the theme.
   ========================================================================== */

.rx-compare {
  --rx-compare-gap: 17.5px;

  /* The three columns, in their measured proportions. fr not %, so the gap
     comes out of the track sizes rather than out of the total. */
  --rx-compare-cols: 368.16fr 386.5fr 482fr;

  /* Column 3's share of the space left after the gaps — the card's width, and
     the only place the proportion above has to be restated. Derived from the
     same numbers so retuning the columns moves the card with them. */
  --rx-compare-card-w: calc(
    (100% - var(--rx-compare-gap) * 2) * 482 / 1236.66
  );

  /* How far the card overhangs the table, top and bottom.

     MEASURED AGAINST THE TEXT, not against the rules. The card runs 1428.22 to
     2097.22 (3111:6342); the header text starts at 1469.85 and the last row's
     copy ends about 2014. So it stands 41.6 proud at the top and 83 at the
     bottom.

     It was 78 / 153 — the distances to the header RULE and to the last rule
     drawn. Both are real numbers and both are the wrong ones: our table's box
     starts at the header text and ends at the last row's floor, not at those
     rules, so measuring to the rules put the card 38 too high and left 70 of
     empty white under the last answer. */
  --rx-compare-card-top: 41.6px;
  --rx-compare-card-bottom: 83px;

  /* Text inset inside a cell. Columns 1 and 2 sit 13 in from their rule; the
     card's copy sits 52.5 in from the card's edge, because there the inset is
     the card's padding rather than a hanging indent. */
  --rx-compare-cell-x: 13px;
  --rx-compare-card-x: 52.5px;

  /* Row rhythm. Figma leaves ~30 between a rule and the next row's cap top
     and the rows are set by their content below that. */
  --rx-compare-row-y: 30px;

  /* 40/1.17 measured (3111:6335). Not a step on the type scale — held local,
     the same call cta-band makes for its 54 and feature-card for its 48.
     Adding a token for one heading is how a scale stops being a scale. */
  --rx-compare-heading: 2.5rem;
}

/* --- Intro ---------------------------------------------------------------
   A repeater, so the order and the mix are the editor's. The gap between two
   blocks belongs to the LOWER one's top margin, which is the only arrangement
   that survives reordering — a bottom margin on the heading is wrong the
   moment the heading is last. */
.rx-compare__intro { margin-block-end: var(--rx-space-9); }
.rx-compare__intro > * { margin-block: 0; }
.rx-compare__intro > * + * { margin-block-start: var(--rx-space-4); }
.rx-compare__intro > .rx-compare__heading + * { margin-block-start: var(--rx-space-5); }
.rx-compare__intro > .rx-compare__cta { margin-block-start: var(--rx-space-6); }

/* Centring is text-align plus an auto margin on the measures: a measure that
   stays flush left inside a centred column reads as a mistake rather than as
   an alignment. */
.rx-compare__intro--center {
  text-align: center;
}

.rx-compare__intro--center .rx-compare__heading,
.rx-compare__intro--center .rx-compare__copy {
  margin-inline: auto;
}

.rx-compare__intro--center .rx-compare__cta { justify-content: center; }

.rx-compare__copy {
  max-width: 34em;
  font-size: var(--rx-text-base);
  line-height: var(--rx-leading-normal);
}

.rx-compare__heading {
  /* THE LINE BREAK IS THE EDITOR'S, not the measure's. Figma breaks after
     "wait." (3111:6335 carries an explicit break, not a wrap), and a max-width
     tuned to reproduce that break is a width that only works for one string —
     change the copy and the break lands somewhere else. pre-line honours the
     newline in the field instead, so what the editor types is what breaks.

     The measure is then only a backstop for a line with no break in it. 25em
     clears the longest drawn line (44 characters at 40px) without forcing a
     wrap the editor did not ask for. */
  white-space: pre-line;
  max-width: 25em;
  font-size: var(--rx-compare-heading);
  font-weight: 400;
  line-height: 1.17; /* measured 3111:6335 */

  /* INHERIT, not --rx-heading. .rx-text--light sets a colour on the section
     for a dark background; a hard-coded heading colour beat it and left the
     heading invisible on the "Dark (inverse)" choice. Same reason the body
     cells inherit below. */
  color: inherit;
}

/* Four sizes. The drawn 40 is `md` and the default; the others exist because
   this heading is sometimes the page's own h1 and sometimes a label over a
   table further down. Held here rather than added to the type scale — one
   block's heading is not a scale step (the same call cta-band makes for 54). */
.rx-compare__heading--sm { --rx-compare-heading: var(--rx-text-2xl); }
.rx-compare__heading--md { --rx-compare-heading: 2.5rem; }
.rx-compare__heading--lg { --rx-compare-heading: var(--rx-text-3xl); }
.rx-compare__heading--xl { --rx-compare-heading: var(--rx-text-5xl); }

/* The card is out of flow, so the table has to hold its overhang itself —
   without this the card's 153px tail hangs over whatever block comes next,
   which on this page was the logo bar. Bottom only: the top overhang lands in
   the gap the heading's own margin already leaves. */
.rx-compare__table {
  position: relative;
  margin-block-end: var(--rx-compare-card-bottom);
}

/* --- The card ------------------------------------------------------------
   Right-aligned because column 3 is the last column and the table fills the
   container — so the card's right edge and the table's are the same edge, and
   there is nothing to compute. Painted under the cells; the cells are in flow
   and therefore later in paint order, so no z-index is needed on them.

   The shadow is the deep one (Figma 3111:6341 draws it as a second white
   rectangle behind the card with a 58px blur — a shadow modelled as a shape).

   NOT BUILT: 3111:6343, a fill-less 499x134.8 node over the card's first row,
   17 proud of the card on each side. It carries a shadow and no fill, so it
   reads as a slight lift under the first answer. The row is already set a step
   up and in semibold, which is the same emphasis said once instead of twice —
   if the lift is wanted it is a box-shadow on .rx-compare__row--first. */
.rx-compare__card {
  position: absolute;
  top: calc(var(--rx-compare-card-top) * -1);
  bottom: calc(var(--rx-compare-card-bottom) * -1);
  right: 0;
  width: var(--rx-compare-card-w);
  border-radius: var(--rx-radius-card);
  background-color: var(--rx-surface);
  box-shadow:
    0 var(--rx-shadow-deep-y) var(--rx-shadow-deep-blur)
    rgba(var(--rx-shadow-deep-rgb), var(--rx-shadow-deep-alpha));
}

/* --- Rows and cells ------------------------------------------------------ */

/* STRETCH, not start. The rule under a row is drawn on each CELL, so a cell
   only as tall as its own text puts its rule at its own height — and with
   three columns of unequal copy that meant three rules at three different
   heights in every row. Figma draws one line across all three columns at one y
   (3111:6356-6358 share a y, as do each row's triple below it).

   Stretching the cells to the row's height puts every rule on the row's floor.
   The text still sits at the top of the cell, because the padding above it is
   fixed and there is nothing centring it. */
.rx-compare__row {
  display: grid;
  grid-template-columns: var(--rx-compare-cols);
  column-gap: var(--rx-compare-gap);
  align-items: stretch;
}

.rx-compare__cell {
  position: relative;
  padding: var(--rx-compare-row-y) var(--rx-compare-cell-x);
  font-size: var(--rx-text-base); /* 16 Regular, measured 3111:6349 */
  line-height: 1.3; /* measured 3111:6349 */

  /* INHERIT. This was --rx-heading, which is dark, and it beat .rx-text--light
     — so on the "Dark (inverse)" background the stage and status-quo columns
     rendered dark-on-dark and read as EMPTY, with the rules still drawn. The
     card column below re-asserts a dark colour, because that one is on a white
     surface at every width and does not follow the section. */
  color: inherit;

  /* The rule under the row. On the CELL and not the row, because Figma draws
     three separate lines of three different widths — they are the columns'
     edges, not one line across the table. */
  border-bottom: 1px solid var(--rx-gold-t1);
}

/* Last row has no rule under it in any column (3111:6363 is the last one
   drawn, and it sits above row 4). */
.rx-compare__row:last-of-type .rx-compare__cell { border-bottom: 0; }

/* The stage name. 17 SemiBold, measured 3111:6352. The design sets row 4 at 18
   Medium instead, which is drift in the file rather than a fifth style — one
   label in a column of four does not change weight on purpose. */
.rx-compare__cell--stage {
  font-size: var(--rx-text-lg);
  font-weight: 600;
  line-height: var(--rx-leading-normal);
}

/* Column 3's cells sit on the card, so their inset is the card's padding. The
   rule inside the card is the neutral one — a gold rule reads as a divider
   between surfaces, and inside a single white card it is a hairline in it. */
.rx-compare__cell--ours {
  padding-inline: var(--rx-compare-card-x);
  border-bottom-color: var(--rx-rule);

  /* THE WHOLE COLUMN IS SET UP AND IN SEMIBOLD — 17/1.3, measured on both
     3111:6345 (row 1) and 3111:6351 (row 4). It used to be row 1 only, on the
     reading that the design leaned on the first answer and let the rest run at
     body weight. Re-measured on 3208:47: every row is the same style, and the
     weight is the argument the card is making. With it on row 1 alone, rows
     2-4 were typographically identical to the status quo beside them. */
  font-size: var(--rx-text-lg);
  font-weight: 600;
  line-height: 1.3; /* measured 3111:6351 */

  /* Always on the white card, at every width and under every background
     choice, so this colour is a property of the surface and not of the
     section — it must not follow .rx-text--light. */
  color: var(--rx-heading);
}

/* --- Column headings (3111:6370 / 6371) ----------------------------------
   16/1.5 SemiBold, measured on 3111:6371 — NOT 12. The 12 came from the text
   node's box HEIGHT in the layer metadata, which for a cap-trimmed single line
   is the cap height and not the font size. Rendered, they sit level with the
   body copy and only the weight separates them.

   The stage column has no heading drawn — its header cell is empty on screen
   and carries a visually-hidden name so the table still announces three
   columns. */
.rx-compare__row--head .rx-compare__cell {
  padding-block: 0 var(--rx-space-5);
  font-size: var(--rx-text-base);
  font-weight: 600;
  line-height: 1.5; /* measured 3111:6371 */
  border-bottom-color: var(--rx-rule);
}

/* The head cell in column 3 inherits --ours above, which is a step larger. The
   two column headings are drawn at the SAME size (3111:6370 and 6371 both
   measure 16), so it is put back here — the emphasis in that column is the
   card and the answers, not its label. */
.rx-compare__row--head .rx-compare__cell--ours {
  font-size: var(--rx-text-base);
  line-height: 1.5;
}

/* Stacked only. Hidden here: the column heading above already names the
   column, and repeating it in every cell would be the same word four times. */
.rx-compare__label { display: none; }

/* --- Rings (Figma 3208:47) -----------------------------------------------
   Four concentric circles on ONE centre, and that centre is the card's
   top-right corner (1403.93, 1428.22 against a card of 924.02..1406.02 /
   1428.22 — 2px, i.e. the corner). So the anchor is placed by the card's own
   two edges and there is no measured offset to keep in agreement with the
   column proportions above: retune the columns and the rings follow.

   The layer is inset to .rx-compare__table, which is already position:
   relative for the card. 100% is therefore the table's right edge, which IS
   the card's right edge (the card is right-aligned and the table fills the
   container), and the card's top is one --rx-compare-card-top above the box.

   TWO LAYERS, because the cluster straddles the card: rendered, the two large
   circles are cut by the white surface and the two small ones carry across it.
   An element cannot be on both sides of a sibling from one layer — the same
   split solution-cta makes for the same reason.

   The host section must not clip, and it does not: .rx-compare paints no
   surface and sets no overflow. */
.rx-compare__ring-point {
  inset-inline-start: 100%;
  inset-block-start: calc(var(--rx-compare-card-top) * -1);
}

/* _rings.css pins the layer at z-index: -1, which is right for the pair the
   card cuts and wrong for the pair that crosses it. Overridden on this block's
   own class rather than on .rx-rings, which is shared. */
.rx-compare__rings--front { z-index: 1; }

/* --- The pulse -----------------------------------------------------------
   The same motion resources-section draws, ported rather than reinvented: a
   SEPARATE, additional ring born small at the shared centre, travelling out
   through the static set and dissolving at the rim, a new one arriving as the
   last fades. The four drawn circles are the subject; this is the thing
   passing through them.

   Two, half a cycle apart, so one is always somewhere in the travel.

   IN THE BACK LAYER ONLY, which is what keeps it quiet. The card is opaque and
   sits above that layer, so the pulse is cut at the card's edge exactly like
   the two large drawn rings are. It reads in the margin to the right of the
   table and never crosses the answers.

   Animates `inline-size`, NOT `scale`. A scaled ring scales its own border, so
   across this range a 1px hairline would render at ~0.11px at the centre and
   thicken as it travelled — backwards for something dissipating. It also
   leaves `transform` to the reveal system, so _rings.css's entrance underneath
   is untouched.

   Scroll, not time: on a view() timeline the scroll IS the progress, so it
   moves when the reader moves. Where view() is unsupported the pulse never
   runs and the block is the static design, which is the right fallback — hence
   opacity 0 at rest rather than a stray extra circle.

   Travels between the drawn set's own bounds, 72.15 to 651.78, in --rx-u, so
   it damps with the rings instead of drifting out of register above 1512. */
.rx-compare__pulse {
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0;
  inline-size: calc(var(--rx-u) * 72.15);
  aspect-ratio: 1 / 1;
  border: 1px solid var(--rx-gold-base);
  border-radius: 50%;
  translate: -50% -50%;
  opacity: 0;
}

.rx-compare__pulse--b {
  --rx-compare-pulse-start: entry 18%;

  border-color: var(--rx-green-base);
}

@keyframes rx-compare-pulse {
  0% { inline-size: calc(var(--rx-u) * 72.15); opacity: 0; }
  15% { opacity: 0.55; }
  70% { opacity: 0.35; }
  100% { inline-size: calc(var(--rx-u) * 651.78); opacity: 0; }
}

@supports (animation-timeline: view()) {
  .rx-compare__pulse {
    animation: rx-compare-pulse linear 3 both;
    animation-timeline: view();
    animation-range: var(--rx-compare-pulse-start, entry 0%) exit 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rx-compare__pulse { animation: none; opacity: 0; }
}

/* --- Entrance ------------------------------------------------------------
   One trigger on the section, rows stepping down it. Fade only for the type:
   these are lines of text on a rule, and a zoom on a rule is the rule going
   soft. The rings keep _rings.css's outward expansion. */
.rx-compare__intro > *,
.rx-compare__row {
  --rx-reveal-from: 1;
}

/* Counted with nth-of-type, not nth-child: the ring layers are <span>s among
   the table's <div>s, so nth-child would renumber every row the moment the
   rings were switched on. Of the divs, the card is 1, the head row 2 and the
   first data row 3. Anything past the fifth data row shares a delay — past
   that the stagger is only holding up something already off the bottom of the
   screen. */
.rx-compare__intro > :nth-child(2) { --rx-reveal-delay: 60ms; }
.rx-compare__intro > :nth-child(n+3) { --rx-reveal-delay: 100ms; }
.rx-compare__row--head { --rx-reveal-delay: 100ms; }
.rx-compare__row:nth-of-type(3) { --rx-reveal-delay: 160ms; }
.rx-compare__row:nth-of-type(4) { --rx-reveal-delay: 220ms; }
.rx-compare__row:nth-of-type(5) { --rx-reveal-delay: 280ms; }
.rx-compare__row:nth-of-type(6) { --rx-reveal-delay: 340ms; }
.rx-compare__row:nth-of-type(n+7) { --rx-reveal-delay: 400ms; }

/* --- Responsive ----------------------------------------------------------
   Three columns of prose stop working long before the viewport does: at 1024
   column 2 is under 200px, which is three or four words a line. So the table
   becomes a list of rows, each one a stage with its two answers stacked, and
   each answer labelled — the column heading is off the top of the screen by
   then, so the cell has to say which side it is.

   The card cannot span rows any more, so the surface moves onto the cells that
   were sitting on it. Same contrast, no floating rectangle behind a stack. */
@media (max-width: 1024px) {
  .rx-compare__card { display: none; }
  .rx-compare__row--head { display: none; }

  .rx-compare__row {
    display: block;
    padding-block: var(--rx-space-5);
    border-bottom: 1px solid var(--rx-gold-t1);
  }

  .rx-compare__row:last-of-type { border-bottom: 0; }

  .rx-compare__cell {
    display: block;
    padding: 0;
    border-bottom: 0;
  }

  .rx-compare__cell--stage { margin-bottom: var(--rx-space-4); }

  .rx-compare__row .rx-compare__cell + .rx-compare__cell {
    margin-top: var(--rx-space-4);
  }

  /* The weight and the step up STAY when stacked. Without the card spanning
     the column there is nothing else left distinguishing the two answers, so
     dropping to body weight here made the block argue nothing on a phone —
     which is where the reflow does the most damage. Only the padding and the
     surface change. */
  .rx-compare__cell--ours {
    padding: var(--rx-space-5);
    border-radius: var(--rx-radius-card);
    background-color: var(--rx-surface);
    box-shadow: var(--rx-shadow-card);
  }

  .rx-compare__label {
    display: block;
    margin-bottom: var(--rx-space-2);
    font-size: var(--rx-text-xs);
    font-weight: 600;
    color: var(--rx-text-muted);
  }
}

@media (max-width: 767px) {
  /* On the HEADING, not on .rx-compare. The size modifier is a class on the
     heading element itself, and a custom property set on an ancestor loses to
     one set on the element — so a phone override declared on the section was
     silently dead the moment the sizes became a field. Only `md` is pinned:
     the tokens the other three read already shrink at this width in
     _tokens.css, and shrinking them twice is how a heading ends up smaller
     than its own copy. */
  .rx-compare__heading--md { --rx-compare-heading: 1.75rem; }
  .rx-compare__intro { margin-block-end: var(--rx-space-7); }
}
