/* rx-block: rx-thero */
/* ==========================================================================
   Hero (text only) — block rx-thero
   --------------------------------------------------------------------------
   One column of type. Every editor control on this module resolves to a class
   owned somewhere else — _utilities.css for the width, space, surface and the
   frame's travel, _rings.css for the rings, partials/atoms.html for the
   content itself — so what is left here is the column, the hero type scale,
   the centred variant and the header tuck.

   NOTHING IN THIS FILE STYLES ANOTHER BLOCK. The frame, container, ring and
   button classes the module emits are all consumed as-is.
   ========================================================================== */

.rx-thero {
  /* How far the page scrolls before a tucked card finishes its travel. Same
     760 feature-plate settled on: long enough to read as a movement, short
     enough to be over before the hero leaves the screen. */
  --rx-thero-open-range: 760px;

  /* The section must NOT clip. The rings are drawn larger than the block on
     purpose and run into the neighbours above and below; a clip here cuts them
     at the section's own box, which reads as a seam. The frame does the
     clipping, and it is an inner element. */
  position: relative;
}

/* --- The card surface -----------------------------------------------------
   .rx-frame supplies the clip, the travel and the overshoot that keeps the
   open state's corners off-screen. This adds only what a card made of type
   needs: a floor under it and air around it.

   NOTHING HERE PAINTS THE SURFACE. The card's fill is its own editor field and
   the section's Background is another, and both emit the same shared .rx-bg--*
   utility — the card carries one on itself. So there is no second colour ramp
   in this file, and no `background-color` that a module stylesheet (which
   loads after main.css) would silently win with.

   Background used to ride the frame when the surface was a card, which made
   one field mean two different things depending on the value of another. */
.rx-thero__frame {
  padding-block: var(--rx-frame-pad);
}

/* --- The static card ------------------------------------------------------
   A card that does not travel is NOT a .rx-frame. The frame draws its width by
   clipping, and clip-path cuts the box-shadow off with everything else outside
   the edge — so the shadow this block declared was computed and invisible from
   the day it was written. A static card takes an ordinary container width and
   an ordinary radius instead, and can be given a real shadow.

   The widths are the same four tokens the container utilities use, so a static
   card and a travelling one settle at the same place. */
.rx-thero__frame--static {
  inline-size: min(100% - var(--rx-gutter) * 2, var(--rx-container-max));
  margin-inline: auto;
  padding-inline: var(--rx-frame-pad);
  border-radius: var(--rx-radius-card);
}

.rx-thero__frame--w-narrow { inline-size: min(100% - var(--rx-gutter) * 2, var(--rx-container-narrow)); }
.rx-thero__frame--w-indented { inline-size: min(100% - var(--rx-gutter) * 2, var(--rx-container-indented)); }
.rx-thero__frame--w-wide { inline-size: min(100% - var(--rx-gutter) * 2, var(--rx-container-wide)); }
.rx-thero__frame--w-snug { inline-size: calc(100% - var(--rx-frame-x-snug) * 2); }

/* Full bleed has no corners to round: a radius at the screen edge reads as a
   cut rather than as a card, which is the same call .rx-frame--w-full makes. */
.rx-thero__frame--w-full {
  inline-size: 100%;
  border-radius: 0;
}

.rx-thero__frame--shadow {
  box-shadow: var(--rx-shadow-card);
}

/* Inside a static card the container has no frame rule sizing it, so it fills
   the padding box. The content measures below are what hold the line length. */
.rx-thero__frame--static .rx-thero__inner {
  inline-size: 100%;
}

/* --- The header tuck ------------------------------------------------------
   THE PILL SITS INSIDE THE SURFACE, the way the blog and solution pages draw
   it. The header is sticky rather than fixed, so it takes --rx-header-height
   of FLOW before this block starts; cancelling that height with a negative top
   margin pulls the surface up under it. The header carries z-index 50, so it
   stays over the card rather than under it. Same construction as post-hero and
   solution-hero — and the same constraint: THIS IS ONLY VALID AS THE FIRST
   BLOCK ON THE PAGE. Anywhere else it hauls the card up over whatever is above
   it by the header's full height, with nothing in the editor to explain why,
   which is why the field is opt-in and off by default.

   ON THE FRAME, AND THE SECTION'S OWN TOP SPACE GOES TO NONE (module.html
   emits --pt-none when tucked). A tucked card is inset from the top of the
   SCREEN by its own small margin, the way solution-hero's panel and the blog's
   are — 24px, its own value rather than the section's spacing choice, which is
   a gap between two blocks and there is no block above this one. Left to
   space_top the card sat a section's padding down the page and read as a
   narrow panel floating mid-screen rather than as the top of the page.

   If the header ever becomes position: fixed, this comes out — there would be
   no flow height left to cancel.

   The type then owes its clearance to the PILL rather than to the card's top
   edge, which is what --rx-header-top + --rx-header-height measures. Tied to
   the header tokens rather than transcribed, so it stays correct if the pill
   moves. Without the tuck the header sits above the block in the ordinary way
   and this padding would be a screenful of empty surface. */
.rx-thero--first .rx-thero__frame {
  margin-block-start: calc(var(--rx-space-5) - var(--rx-header-height));
  /* The frame's own top padding is REPLACED, not added to. Left in place the
     card was charged twice — --rx-frame-pad plus the whole header clearance
     below — which put ~150 of white above the eyebrow against 96 under the
     buttons, so the type sat visibly low in its own card. */
  padding-block-start: 0;
}

/* THE GAP UNDER THE PILL IS THE CARD'S OWN PADDING, derived rather than
   picked: the pill's bottom sits (--rx-header-top + --rx-header-height) below
   the top of the SCREEN, and the card's top edge is --rx-space-5 below it, so
   the pill clears the card's top by the difference. Adding --rx-frame-pad to
   that puts the eyebrow exactly as far under the pill as the buttons are above
   the card's floor, which is what "centred in the card" means when the thing
   at the top is the nav rather than the card's own edge. */
.rx-thero--first .rx-thero__inner {
  padding-block-start: calc(
    var(--rx-header-top) + var(--rx-header-height) - var(--rx-space-5) +
    var(--rx-frame-pad)
  );
}

/* --- Travel, at the top of the page ---------------------------------------
   A TUCKED CARD CANNOT USE view(). _utilities.css drives .rx-frame from
   `animation-timeline: view()` over `entry`, and an entry range is measured
   against the element arriving in the viewport — a block at the TOP of the
   page has already arrived at scroll zero, so the travel is over before the
   reader can see any of it and the card renders settled. Exactly the trap
   CLAUDE.md records for stacked-hero and feature-plate, both of which answer
   it the same way: drive the same keyframes from `scroll(root block)` over a
   distance from the top of the document instead.

   Gated on --once like feature-plate's, rather than left to be harmless
   because a static card has no animation to consume the timeline. */
@supports (animation-timeline: scroll(root block)) {
  .rx-thero--first .rx-thero__frame.rx-frame--once {
    animation-timeline: scroll(root block);
    animation-range: 0px var(--rx-thero-open-range);
  }
}

/* --- The column -----------------------------------------------------------
   z-index lifts the type over the ring layer, which sits at -1 inside this
   section's stacking context (every .rx-section carries `isolation: isolate`,
   _buttons.css). Without it a ring drawn across the block runs over the
   headline rather than behind it. */
.rx-thero__inner {
  position: relative;
  z-index: 1;
}

.rx-thero--center .rx-thero__inner {
  text-align: center;
}

/* --- Type -----------------------------------------------------------------
   The theme's hero display size and leading (--rx-text-5xl / --rx-leading-hero,
   both measured on the home hero's h1) as the DEFAULT, behind --rx-h-size /
   --rx-h-lh so an editor's "Heading size" choice wins. Same shape .rx-tm__
   heading uses for the same reason.

   The two measures are RATIOS taken from the centred hero already in the theme
   — stacked-hero draws its heading 771 wide at 56 (13.77em) and its lead 578
   at 17 (34em), Figma 3111:5983 / 5992. Carried as em so each holds its line
   count as the type grows, per the "a drawn width is in em, not ch" rule in
   CLAUDE.md. This block has no Figma frame of its own; when it gets one, these
   are the two numbers to re-measure.

   `margin-inline: auto` on the measures rather than on the column: the column
   is the container and is already centred, and a centred hero needs its
   SHORTER lines centred inside it, not the box moved. Left-set, auto resolves
   to 0 on the start side and the measures sit where the column starts. */
.rx-thero__heading {
  margin: 0;
  max-width: var(--rx-thero-heading-measure, 13.77em);
  font-size: var(--rx-h-size, var(--rx-text-5xl));
  font-weight: 400;
  line-height: var(--rx-h-lh, var(--rx-leading-hero));
  color: var(--rx-heading);
}

/* THE HEADING HAS TO OPT BACK IN TO THE INVERSE. .rx-text--light and
   .rx-bg--dark set `color` on their own element and rely on inheritance, and a
   module stylesheet loads after main.css — so the `color: var(--rx-heading)`
   above silently beat both and the headline rendered dark brown on a dark
   fill. Measured: on a dark card the headline was invisible while the eyebrow
   and lead beside it inverted correctly, which reads as missing copy rather
   than as a colour bug. Any block that names its own heading colour owes these
   two rules. */
.rx-text--light .rx-thero__heading,
.rx-bg--dark .rx-thero__heading {
  color: var(--rx-inverse-text);
}

.rx-thero__lead {
  margin: var(--rx-space-5) 0 0;
  max-width: var(--rx-thero-copy-measure, 34em);
}

.rx-thero__copy {
  margin: var(--rx-space-5) 0 0;
  max-width: var(--rx-thero-copy-measure, 34em);
  /* Stated rather than inherited, so the Copy size choice has something to
     multiply. --rx-text-base IS what body sets, so with no class this computes
     to the 16 it already inherited. */
  font-size: calc(var(--rx-text-base) * var(--rx-copy-scale, 1));
}

/* --- Content width --------------------------------------------------------
   SEPARATE FROM THE BLOCK'S WIDTH, and it has to be: the type's line length
   and the card's width are different questions, and inside a .rx-frame they
   were being answered by two caps that have nothing to do with either. The
   frame's own `.rx-frame .rx-container` rule holds the column to
   (--rx-container-max - --rx-frame-pad * 2) — 1048 at 1512 — however wide the
   card is, and the heading's measure then held it to 13.77em (~826 at the
   display size) inside that. So a 1460-wide card carried an 826-wide heading
   and read as narrow type in a big empty panel.

   Both measures are in em, so each holds its LINE COUNT as the type grows
   rather than a pixel width. "Full" removes them and lets the type run the
   width of the column it is in. */
.rx-thero__inner--c-narrow {
  --rx-thero-heading-measure: 10em;
  --rx-thero-copy-measure: 26em;
}

.rx-thero__inner--c-wide {
  --rx-thero-heading-measure: 18em;
  --rx-thero-copy-measure: 42em;
}

.rx-thero__inner--c-full {
  --rx-thero-heading-measure: none;
  --rx-thero-copy-measure: none;
}

/* Full also gives the column back the width the frame rule took: inside a
   travelling card the container is capped at the content column less the
   frame's padding, which is narrower than the card itself at every width past
   Default. Later in the cascade than _utilities.css, so this wins. */
.rx-thero__inner--c-full {
  inline-size: 100%;
}

.rx-thero__eyebrow {
  margin: 0 0 var(--rx-space-4);
}

.rx-thero__actions {
  margin-top: var(--rx-space-6);
}

/* The atoms macro emits the pieces in the editor's order, so the first one is
   whatever they put first — it must not carry a top margin it inherited from
   being second somewhere else. */
.rx-thero__inner > :first-child {
  margin-top: 0;
}

.rx-thero--center .rx-thero__heading,
.rx-thero--center .rx-thero__lead,
.rx-thero--center .rx-thero__copy {
  margin-inline: auto;
}

/* --- Entrance -------------------------------------------------------------
   One group trigger on the section, so the hero arrives as one event and
   cannot re-run when it is scrolled back to. The stagger runs down the
   column; the frame is not in it — its own travel is the scroll-linked one,
   and a scale on top of a clip is two gestures arguing. */
.rx-thero__eyebrow,
.rx-thero__heading,
.rx-thero__lead,
.rx-thero__copy,
.rx-thero__actions {
  --rx-reveal-from: 0.94;
}

.rx-thero__heading { --rx-reveal-delay: 60ms; }
.rx-thero__lead    { --rx-reveal-delay: 120ms; }
.rx-thero__copy    { --rx-reveal-delay: 120ms; }
.rx-thero__actions { --rx-reveal-delay: 180ms; }
