/* rail-kit — one rail, themed per brand.
 *
 * Every value below reads from a CSS custom property with a neutral fallback.
 * A brand adopts the rail by setting these once, wherever it already defines
 * its design tokens. Nothing here names a brand, a colour, or a typeface.
 *
 *   .my-brand {
 *     --rail-accent: #c8102e;
 *     --rail-card-bg: #141414;
 *     --rail-card-radius: 16px;
 *     --rail-media-aspect: 16 / 9;
 *   }
 *
 * Motion: every transition and animation sits inside
 * prefers-reduced-motion: no-preference, with a reduce block that switches all
 * of it off. Hover behaviour is additionally gated on a fine pointer so a tap
 * never leaves a card stuck in a hovered state.
 */

/* The private aliases must exist on every root the kit renders, not just the
   rail: the billboard and the chips use the same accent, border and text
   tokens, and without this their buttons fell back to `currentColor` and
   rendered white on white. */
/* The kit must not depend on the host's reset. Without this the padded
   overlay measured 266px inside a 230px card under content-box — invisible in
   a Tailwind site (preflight sets border-box) and broken everywhere else. */
.rail,
.rail-billboard,
.rail-drawpile,
.rail-drawpile__stack,
.rail-sparkle,
.rail-pack,
.rail-deck,
.rail-coverflow,
.rail-confetti,
.rail-playcard,
.rail-reactions,
.rail-boostercard,
.rail-tagpicker,
.rail-redeem,
.rail-stage,
.rail-score,
.rail-controls,
.rail-voice,
.rail-intro,
.rail-receipt,
.rail-statuschip,
.rail-statuslist,
.rail-finder,
.rail-finder__trigger,
.rail-note,
.rail-threadlist,
.rail-playbill,
.rail-brandcard,
.rail-filters,
.rail-frame,
.rail-versus,
.rail-list,
.rail-sheet,
.rail-faq,
.rail-player,
.rail-scene,
.rail-stickybar,
.rail-tabs,
.rail-bottomnav,
.rail-fab,
.rail-prompt,
.rail-embed,
.rail-nowplaying,
.rail-story,
.rail-tiles,
.rail-track,
.rail-merchant,
.rail-progress,
.rail-stats,
.rail-empty,
.rail-segmented,
.rail-cta,
.rail-disclosure,
.rail-figures,
.rail-options,
.rail-promo,
.rail-milestone,
.rail-presence,
.rail-live,
.rail-copy,
.rail-table,
.rail-poll,
.rail-ad,
.rail-pageheader,
.rail-price,
.rail-rating,
.rail-byline,
.rail-search,
.rail-coupons,
.rail-toast,
.rail-masonry,
.rail-storyring,
.rail-coachmark,
.rail-shortcuts,
.rail-offer,
.rail-folder,
.rail *,
.rail-billboard *,
.rail-drawpile *,
.rail-sparkle *,
.rail-pack *,
.rail-deck *,
.rail-coverflow *,
.rail-confetti *,
.rail-playcard *,
.rail-reactions *,
.rail-boostercard *,
.rail-filters *,
.rail-frame *,
.rail-versus *,
.rail-list *,
.rail-sheet *,
.rail-faq *,
.rail-player *,
.rail-scene *,
.rail-stickybar *,
.rail-tabs *,
.rail-bottomnav *,
.rail-fab *,
.rail-progress *,
.rail-stats *,
.rail-empty *,
.rail-segmented *,
.rail-cta *,
.rail-disclosure *,
.rail-figures *,
.rail-options *,
.rail-promo *,
.rail-milestone *,
.rail-presence *,
.rail-live *,
.rail-copy *,
.rail-table *,
.rail-poll *,
.rail-ad *,
.rail-pageheader *,
.rail-price *,
.rail-rating *,
.rail-byline *,
.rail-search *,
.rail-coupons *,
.rail-toast *,
.rail-masonry *,
.rail-storyring *,
.rail-coachmark *,
.rail-shortcuts *,
.rail-offer *,
.rail-folder *,
.rail-turntable *,
.rail-deck *,
.rail-masthead *,
.rail-evidence *,
.rail-cover *,
.rail-welcome * {
  box-sizing: border-box;
}

.rail,
.rail-billboard,
.rail-drawpile,
.rail-drawpile__stack,
.rail-sparkle,
.rail-pack,
.rail-deck,
.rail-coverflow,
.rail-confetti,
.rail-playcard,
.rail-reactions,
.rail-boostercard,
.rail-tagpicker,
.rail-redeem,
.rail-stage,
.rail-score,
.rail-controls,
.rail-voice,
.rail-intro,
.rail-receipt,
.rail-statuschip,
.rail-statuslist,
.rail-finder,
.rail-finder__trigger,
.rail-note,
.rail-threadlist,
.rail-playbill,
.rail-brandcard,
.rail-filters,
.rail-frame,
.rail-versus,
.rail-list,
.rail-sheet,
.rail-faq,
.rail-player,
.rail-scene,
.rail-stickybar,
.rail-tabs,
.rail-bottomnav,
.rail-fab,
.rail-prompt,
.rail-embed,
.rail-nowplaying,
.rail-story,
.rail-tiles,
.rail-track,
.rail-merchant,
.rail-progress,
.rail-stats,
.rail-empty,
.rail-segmented,
.rail-cta,
.rail-disclosure,
.rail-figures,
.rail-options,
.rail-promo,
.rail-milestone,
.rail-presence,
.rail-live,
.rail-copy,
.rail-table,
.rail-poll,
.rail-ad,
.rail-pageheader,
.rail-price,
.rail-rating,
.rail-byline,
.rail-search,
.rail-coupons,
.rail-toast,
.rail-masonry,
.rail-storyring,
.rail-coachmark,
.rail-shortcuts,
.rail-offer,
.rail-folder,
.rail-turntable,
.rail-deck,
.rail-masthead,
.rail-evidence,
.rail-cover,
.rail-welcome {
  --_gap: calc(var(--rail-gap, 20px) * var(--_space));
  --_width: var(--rail-card-width, 300px);
  --_accent: var(--rail-accent, currentColor);
  /* THE ACCENT AS TEXT IS A DIFFERENT COLOUR FROM THE ACCENT AS A FILL, and
     this alias is the only reason a brand does not have to know that fifteen
     times. An accent tuned for a filled button is routinely 3:1 or worse as
     13-15px text, which the axe gate has now caught on three separate
     components. A brand sets --rail-accent-text ONCE and every text use
     follows; leave it unset and nothing changes. */
  --_accent-text: var(--rail-accent-text, var(--_accent));
  --_radius: var(--rail-card-radius, 16px);
  --_bg: var(--rail-card-bg, rgba(255, 255, 255, 0.04));
  --_border: var(--rail-card-border, rgba(255, 255, 255, 0.12));
  --_text: var(--rail-text, inherit);
  --_muted: var(--rail-muted, rgba(255, 255, 255, 0.65));
  --_aspect: var(--rail-media-aspect, 4 / 3);
  --_shadow: var(--rail-card-shadow, 0 18px 40px -22px rgba(0, 0, 0, 0.9));

  /* ---- the three axes -------------------------------------------------
     Before this block a brand had to set ten separate sizes to look denser
     or calmer, and motion could not be themed at all: every duration and
     curve was a literal. Now a brand moves ONE number per axis and the kit
     follows.

     Every axis defaults to 1 and every step keeps the literal it already
     had, so a brand that sets nothing renders exactly what it rendered
     before. This is additive: the per-value tokens below still win when a
     brand sets them.

       .my-brand { --rail-density: 0.85; --rail-motion-scale: 0.7; }   */
  --_type: var(--rail-type-scale, 1);
  --_space: var(--rail-density, 1);
  --_motion: var(--rail-motion-scale, 1);

  --_text-2xs: calc(var(--rail-text-2xs, 11px) * var(--_type));
  --_text-xs: calc(var(--rail-text-xs, 13px) * var(--_type));
  --_text-sm: calc(var(--rail-text-sm, 13.5px) * var(--_type));
  --_text-md: calc(var(--rail-text-md, 14px) * var(--_type));

  --_space-2xs: calc(var(--rail-space-2xs, 4px) * var(--_space));
  --_space-xs: calc(var(--rail-space-xs, 6px) * var(--_space));
  --_space-sm: calc(var(--rail-space-sm, 10px) * var(--_space));
  --_space-md: calc(var(--rail-space-md, 12px) * var(--_space));
  --_space-lg: calc(var(--rail-space-lg, 16px) * var(--_space));
  --_space-s: calc(var(--rail-space-s, 8px) * var(--_space));
  --_space-3xs: calc(var(--rail-space-3xs, 2px) * var(--_space));
  --_space-xl: calc(var(--rail-space-xl, 18px) * var(--_space));
  --_space-2xl: calc(var(--rail-space-2xl, 20px) * var(--_space));
  --_space-3xl: calc(var(--rail-space-3xl, 22px) * var(--_space));
  /* Two steps the ramp was missing once 42 more components joined it. Added
     rather than snapping 14 to 16 and 24 to 22, because every axis so far has
     promised that a brand setting nothing renders exactly what it did. */
  --_space-mid: calc(var(--rail-space-mid, 14px) * var(--_space));
  --_space-4xl: calc(var(--rail-space-4xl, 24px) * var(--_space));
  --_text-lg: calc(var(--rail-text-lg, 14.5px) * var(--_type));
  --_text-xl: calc(var(--rail-text-xl, 17px) * var(--_type));
  --_track-wide: var(--rail-track-wide, 0.04em);
  --_track-wider: var(--rail-track-wider, 0.08em);
  --_pill: var(--rail-pill-radius, 999px);

  /* A control's tap target is the one value density must not be able to
     break: WCAG 2.2 AA wants 24px and this kit ships 44. max() means a
     brand can make the kit denser without configuring it below the floor. */
  --_control-min: max(24px, calc(var(--rail-control-min, 44px) * var(--_space)));
  --_control-min-sm: max(24px, calc(var(--rail-control-min-sm, 40px) * var(--_space)));

  /* Durations, not the number of passes: the sweep still runs three times
     and stops. A brand can slow it down; it cannot make it loop. */
  --_dur-fast: calc(var(--rail-motion-fast, 0.2s) * var(--_motion));
  --_dur-base: calc(var(--rail-motion-base, 0.28s) * var(--_motion));
  --_dur-slow: calc(var(--rail-motion-slow, 0.5s) * var(--_motion));
  --_dur-sweep: calc(var(--rail-motion-sweep, 2.6s) * var(--_motion));
  --_ease: var(--rail-motion-ease, cubic-bezier(0.2, 0.7, 0.2, 1));
  --_ease-soft: var(--rail-motion-ease-soft, ease);
  /* The AA tap floor. NOT scaled by density: a brand may make the kit denser,
     it may not configure itself below 24px. */
  --_tap-min: var(--rail-tap-min, 24px);
  --_ease-out: var(--rail-motion-ease-out, cubic-bezier(0.25, 0.46, 0.45, 0.94));
  color: var(--_text);
  container-type: inline-size;
}

.rail[data-rail-size="sm"] { --_width: var(--rail-card-width-sm, 240px); }
.rail[data-rail-size="lg"] { --_width: var(--rail-card-width-lg, 360px); }

.rail__header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--_space-lg);
}

.rail__eyebrow {
  font: var(--rail-eyebrow-font, inherit);
  letter-spacing: var(--rail-eyebrow-tracking, 0.14em);
  text-transform: var(--rail-eyebrow-transform, uppercase);
  /* Small text on a brand accent usually fails WCAG AA — the Geebs red is
     3.06:1 on its own background and the FLAS gold 3.02:1 on its own. Give
     these three their own tokens so a brand can lighten the accent for small
     text without touching buttons, where a large filled area passes. */
  color: var(--rail-eyebrow-color, var(--_accent-text));
  font-size: calc(var(--rail-eyebrow-size, 11px) * var(--_type));
}

.rail__heading {
  font: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-heading-size, clamp(22px, 3vw, 30px)) * var(--_type));
  line-height: 1.12;
  margin: var(--_space-s) 0 0;
}

.rail__subheading {
  margin: var(--_space-sm) 0 0;
  max-width: 60ch;
  color: var(--_muted);
  font-size: calc(var(--rail-subheading-size, 15px) * var(--_type));
  line-height: 1.6;
}

/* Sin nada que desplazar no hay flechas: un control que no hace nada es peor
   que ninguno. El contador sí se queda: "3 de 3" sigue diciendo algo. */
.rail__arrows[data-rail-scrollable="false"] .rail__arrow--move { display: none; }
.rail__arrow:disabled { opacity: 0.35; cursor: default; }

.rail__position {
  display: block;
  margin: 0 var(--_space-2xs) 0 auto;
  font-size: var(--_text-xs);
  color: var(--rail-meta-color, var(--_muted));
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rail__arrows { display: none; gap: var(--_space-s); flex-shrink: 0; }

@media (min-width: 768px) {
  .rail__arrows { display: flex; }
  .rail__scroller { align-items: stretch; }
}

.rail__arrow {
  width: 40px;
  height: 40px;
  border-radius: var(--_pill);
  border: 1px solid var(--_border);
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.rail__scroller {
  display: flex;
  /* On a phone you see one card at a time, so equal heights only buy a hole
     above the button. From tablet up several cards are visible side by side
     and their buttons should line up. */
  align-items: flex-start;
  gap: var(--_gap);
  overflow-x: auto;
  /* NO SNAP. This went `mandatory` -> `proximity` -> gone, and the last step
     is the one that fixes what people actually felt.

     The arithmetic is the whole story. A card is 420px and the gap 26, so a
     snap step is 446. One notch of a mouse wheel — or a small trackpad nudge —
     moves about 197px, 43% of a step. Snapping resolves to the NEAREST point,
     and 197 is closer to 0 than to 446, so the rail slides forward and then
     puts itself back where it started. Measured on a real wheel event: it
     reached 197 and walked home through 186, 141, 79, 26, 10, 0.

     `proximity` does not save you here. It loosens WHEN a snap happens, not
     WHERE it lands, and every short scroll is still short. The feeling is that
     the carousel is jammed, and it is not a feeling: every gentle scroll is
     undone.

     The affordance that snapping was supposed to buy — landing on a card
     instead of between two — is already in the arrows, which scroll by exactly
     one card and say so. Free scrolling never fights the hand. */
  scroll-snap-type: none;
  padding-bottom: var(--_space-lg);
  margin-top: var(--_space-4xl);
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}

/* Smooth scrolling is motion, and it was outside every reduce gate: a visitor
   who asked for less movement still got the arrows gliding the rail. The kit's
   own rule is that nothing animates without the query. */
@media (prefers-reduced-motion: no-preference) {
  .rail__scroller { scroll-behavior: smooth; }
}

@media (hover: hover) and (pointer: fine) {
  .rail__scroller { cursor: grab; }
  .rail__scroller[data-dragging="true"] {
    cursor: grabbing;
    scroll-behavior: auto;
    user-select: none;
  }
}

.rail__scroller::-webkit-scrollbar { display: none; }

/* Decorative edge fade — no layout change, nothing focusable hidden, both
   true ends still reachable. */
@supports (mask-image: linear-gradient(to right, transparent, black)) {
  @media (min-width: 768px) {
    .rail__scroller {
      mask-image: linear-gradient(to right, transparent 0, black 28px, black calc(100% - 56px), transparent 100%);
      -webkit-mask-image: linear-gradient(to right, transparent 0, black 28px, black calc(100% - 56px), transparent 100%);
    }
  }
}

.rail-card {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  width: min(var(--_width), 78vw);
  border: 1px solid var(--_border);
  border-radius: var(--_radius);
  background: var(--_bg);
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  transform: translateZ(0);
}

.rail-card[data-rail-highlighted="true"] { border-color: var(--_accent); }

.rail-card__figure {
  position: relative;
  display: block;
  aspect-ratio: var(--_aspect);
  background: var(--rail-figure-bg, rgba(255, 255, 255, 0.05));
  overflow: hidden;
}

.rail-card[data-rail-kind="text"] .rail-card__figure {
  aspect-ratio: var(--rail-text-aspect, 5 / 2);
  display: grid;
  place-items: center;
}

.rail-card__image { width: 100%; height: 100%; object-fit: cover; display: block; }

.rail-card__glyph {
  /* Its own token: this is large text, so it needs 3:1, and a brand accent
     tuned for a filled button routinely is not that on the card surface. */
  font: var(--rail-glyph-font, inherit);
  font-size: calc(var(--rail-glyph-size, 38px) * var(--_type));
  color: var(--rail-glyph-color, var(--_accent-text));
  letter-spacing: var(--_track-wide);
}

.rail-card__badge {
  position: absolute;
  top: 12px;
  left: 12px;
  padding: var(--_space-2xs) var(--_space-sm);
  border-radius: var(--_pill);
  font-size: var(--_text-2xs);
  letter-spacing: var(--_track-wider);
  text-transform: uppercase;
  background: var(--rail-badge-bg, rgba(0, 0, 0, 0.6));
  color: var(--rail-badge-color, #fff);
}

/* Icon chip + badge share one row above the title, so an icon-only card has a
   deliberate header instead of an empty picture frame. */
.rail-card__mark-row {
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
}

.rail-card__icon {
  display: inline-grid;
  place-items: center;
  width: var(--rail-icon-box, 36px);
  height: var(--rail-icon-box, 36px);
  border-radius: var(--rail-icon-radius, 12px);
  border: 1px solid var(--_border);
  background: var(--rail-icon-bg, rgba(255, 255, 255, 0.04));
  color: var(--_accent);
  flex: 0 0 auto;
}

.rail-card__icon > svg {
  width: var(--rail-icon-size, 20px);
  height: var(--rail-icon-size, 22px);
}

/* Inside the figure box the mark is bigger and unboxed — it is the picture. */
.rail-card__figure .rail-card__icon {
  width: auto;
  height: auto;
  border: 0;
  background: none;
}

/* Consumer media (an embed, a video, a framework image) fills the same box a
   plain <img> would, so a rail of embeds lines up with a rail of photos. */
.rail-card__figure > iframe,
.rail-card__figure > video,
.rail-card__figure > :is(span, div) > img {
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: cover;
  display: block;
}

.rail-card__figure .rail-card__icon > svg {
  width: var(--rail-figure-icon-size, 44px);
  height: var(--rail-figure-icon-size, 44px);
}

.rail-card[data-rail-kind="stat"] .rail-card__icon { margin: var(--_space-xl) var(--_space-xl) 0; }

/* With no figure, the badge sits in the body flow instead of over an image. */
.rail-card__badge--inline {
  position: static;
  align-self: flex-start;
  margin-bottom: var(--_space-3xs);
}

.rail-card__body { display: flex; flex-direction: column; gap: var(--_space-s); padding: var(--rail-card-padding, var(--_space-xl)); flex: 1; }
.rail-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--_space-sm); }
/* The headline carries the card. Netflix-scale by default — a rail is scanned
   at arm's length, and an 18px title made every card read like a list item. */
/* El titular puede ser un encabezado de verdad; que serlo no le cambie el
   tamaño ni el margen que trae el navegador. */
.rail-card__title { margin: 0; }
.rail-card__title {
  font-family: var(--rail-title-font, inherit);
  font-size: calc(var(--rail-title-size, clamp(20px, 1.6vw, 24px)) * var(--_type));
  font-weight: var(--rail-title-weight, 600);
  line-height: var(--rail-title-leading, 1.15);
  letter-spacing: var(--rail-title-tracking, normal);
  text-wrap: balance;
}
.rail-card__meta {
  font-family: var(--rail-meta-font, inherit);
  font-size: calc(var(--rail-meta-size, 14px) * var(--_type));
  font-weight: var(--rail-meta-weight, inherit);
  color: var(--rail-meta-color, var(--_accent-text));
  white-space: nowrap;
}

/* The value as the decision: its own line, its own scale. The note under it
   says what the number buys, so the number never has to. */
.rail-card__value { display: flex; flex-direction: column; gap: var(--_space-3xs); }
.rail-card__meta--block {
  font-size: calc(var(--rail-value-size, clamp(34px, 3.4vw, 46px)) * var(--_type));
  font-weight: var(--rail-value-weight, 800);
  line-height: var(--rail-value-leading, 1);
  letter-spacing: var(--rail-value-tracking, -0.045em);
  color: var(--rail-value-color, var(--_text));
}
.rail-card__meta--block small {
  font-size: calc(var(--rail-value-unit-size, 14px) * var(--_type));
  font-weight: var(--rail-weight-regular, 400);
  letter-spacing: normal;
  color: var(--_muted);
}
.rail-card__value-note {
  font-size: calc(var(--rail-value-note-size, 13px) * var(--_type));
  font-weight: var(--rail-value-note-weight, 700);
  color: var(--rail-value-note-color, var(--_text));
}
.rail-card__subtitle { font-size: calc(var(--rail-subtitle-size, 14px) * var(--_type)); color: var(--_muted); }
.rail-card__description { margin: 0; font-size: var(--_text-md); line-height: 1.6; color: var(--_muted); }
/* Opt-in line clamp — only inside a rail that asked for it. */
.rail[data-rail-clamp] .rail-card__description {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--rail-description-lines, 4);
  line-clamp: var(--rail-description-lines, 4);
  overflow: hidden;
}

.rail-card__bullets {
  margin: var(--_space-2xs) 0 0;
  padding-left: var(--rail-bullet-indent, var(--_space-xl));
  font-size: calc(var(--rail-bullet-size, 13.5px) * var(--_type));
  line-height: var(--rail-bullet-leading, 1.6);
  color: var(--rail-bullet-color, var(--_muted));
}
.rail-card__bullets > li + li { margin-top: var(--rail-bullet-gap, 0); }
/* Up to three actions; they stack on a phone and sit inline from tablet up. */
.rail-card__actions {
  display: flex;
  flex-direction: column;
  gap: var(--_space-s);
  margin-top: auto;
  padding-top: var(--_space-md);
}

@media (min-width: 768px) {
  .rail-card__actions {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
  }
}

.rail-card__title-link {
  color: inherit;
  text-decoration: none;
}

.rail-card__title-link:hover { text-decoration: underline; }

/* Dismiss controls. Visible on focus for keyboards, always visible on touch. */
.rail-card__dismiss,
.rail__dismiss {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 32px;
  height: 32px;
  display: inline-grid;
  place-items: center;
  border-radius: var(--_pill);
  border: 1px solid var(--_border);
  background: var(--rail-dismiss-bg, rgba(0, 0, 0, 0.45));
  color: inherit;
  font-size: var(--_text-xl);
  line-height: 1;
  cursor: pointer;
  z-index: 2;
}

.rail__dismiss {
  position: static;
  width: 40px;
  height: 40px;
}

.rail-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.rail-card__cta { font-size: var(--_text-sm); color: var(--rail-cta-link-color, var(--_accent-text)); text-decoration: none; }

/* Buttons, not <button>s — see RailCard — so they carry their own box. */
.rail-card__cta--primary,
.rail-card__cta--secondary {
  align-self: stretch;
  text-decoration: none;
  justify-content: center;
  margin-top: auto;
  padding: var(--rail-cta-padding, var(--_space-md) var(--_space-xl));
  border-radius: var(--rail-cta-radius, 10px);
  font-weight: var(--rail-cta-weight, 600);
  font-size: calc(var(--rail-cta-size, 14.5px) * var(--_type));
  /* WCAG AA tap target is 24px; 44 is the comfortable thumb size. */
  min-height: var(--_control-min);
  display: inline-flex;
  align-items: center;
  gap: var(--_space-xs);
  text-align: center;
}

/* Keeps the arrow beside the label when the label wraps, instead of pinned to
   the far edge of the button. */
.rail-card__cta-label { display: inline-block; }

.rail-card__cta--primary {
  background: var(--rail-cta-bg, var(--_accent));
  color: var(--rail-cta-color, #fff);
  border: 1px solid var(--rail-cta-bg, var(--_accent));
}

.rail-card__cta--secondary {
  background: var(--rail-cta-secondary-bg, transparent);
  color: var(--rail-cta-secondary-color, var(--rail-cta-link-color, var(--_accent-text)));
  border: 1px solid var(--rail-cta-secondary-border, var(--_accent));
}

/* From tablet up the button sits at its natural width — a full-width button
   on a 340px card reads as a form control rather than a choice. */
@media (min-width: 768px) {
  .rail-card__cta--primary,
  .rail-card__cta--secondary {
    align-self: flex-start;
    justify-content: flex-start;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .rail-card__cta--primary,
  .rail-card__cta--secondary {
    transition: filter var(--_dur-fast) var(--_ease-soft), background-color var(--_dur-fast) var(--_ease-soft), color var(--_dur-fast) var(--_ease-soft);
  }

  .rail-card:hover .rail-card__cta--primary { filter: brightness(1.1); }

  .rail-card:hover .rail-card__cta--secondary {
    background: var(--rail-cta-bg, var(--_accent));
    color: var(--rail-cta-color, #fff);
  }
}

.rail-card__stat-value { font: var(--rail-stat-font, inherit); font-size: calc(var(--rail-stat-size, clamp(40px, 3.4vw, 52px)) * var(--_type)); line-height: 1; padding: var(--_space-3xl) var(--_space-xl) 0; }
.rail-card__stat-label { font-size: var(--_text-md); color: var(--_muted); padding: var(--_space-sm) var(--_space-xl) 0; }
.rail-card[data-rail-kind="stat"] .rail-card__description { padding: var(--_space-sm) var(--_space-xl) var(--_space-2xl); }

.rail :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

/* ── Motion ─────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: no-preference) {
  .rail-card {
    transition:
      transform var(--_dur-base) var(--_ease),
      opacity var(--_dur-base) var(--_ease-soft),
      border-color var(--_dur-base) var(--_ease-soft),
      box-shadow var(--_dur-base) var(--_ease-soft);
  }

  .rail-card__image { transition: transform var(--_dur-slow) var(--_ease); }
  .rail__arrow { transition: transform var(--_dur-fast) var(--_ease-soft), border-color var(--_dur-fast) var(--_ease-soft); }
  .rail__arrow:hover { transform: scale(1.08); }

  @media (hover: hover) and (pointer: fine) {
    .rail__scroller:hover .rail-card { opacity: 0.62; }

    .rail-card:hover,
    .rail-card:focus-visible,
    .rail__scroller:hover .rail-card:focus-visible {
      opacity: 1;
      transform: translateY(-6px) scale(1.025);
      box-shadow: var(--_shadow);
    }

    .rail-card:hover .rail-card__image { transform: scale(1.06); }
  }

  /* Tactile press — the thing that makes an app feel responsive rather than
     a web page. */
  .rail-card:active { transform: translateY(-2px) scale(0.99); }

  /* Attention sweep on the one suggested card. Deliberately FINITE: three
     passes and it stops. An infinite pulse is a slot-machine pattern, and a
     card that never stops moving is a card nobody trusts. */
  .rail-card[data-rail-highlighted="true"]::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(
      100deg,
      transparent 35%,
      var(--rail-shimmer, rgba(255, 255, 255, 0.11)) 50%,
      transparent 65%
    );
    transform: translateX(-100%);
    animation: rail-shimmer var(--_dur-sweep) ease-in-out 3;
  }

  .rail-card { position: relative; }

  @keyframes rail-shimmer {
    to { transform: translateX(100%); }
  }
}

@media (prefers-reduced-motion: reduce) {
  .rail__scroller { scroll-behavior: auto; }
  .rail-card,
  .rail-card__image,
  .rail__arrow {
    transition: none !important;
    transform: none !important;
    animation: none !important;
  }

  .rail-card[data-rail-highlighted="true"]::after { display: none; }
}

/* ── Poster overlay, footer badge, header action ─────────────────────── */

/* A second label on the art. Netflix uses the bottom edge for status
   ("New Season", "Leaving Soon") and the top for provenance ("TOP 10"). */
.rail-card__badge--footer {
  top: auto;
  bottom: 12px;
  left: 12px;
  background: var(--rail-footer-badge-bg, var(--_accent));
  color: var(--rail-footer-badge-color, #fff);
}

/* Title drawn on the art, with a scrim heavy enough to keep it legible over
   any photograph — the whole point of a poster lockup. */
/* The overlay is positioned, not laid out: the image is a flex/grid item that
   fills the figure, so an in-flow overlay landed beside it, outside the card.
   Caught by comparing the two bounding boxes, not by looking at a screenshot. */

.rail-card__figure[data-rail-overlay]::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(
    --rail-overlay-scrim,
    linear-gradient(to top, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.45) 38%, rgba(0, 0, 0, 0) 68%)
  );
}

.rail-card__overlay {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--_space-2xs);
  padding: var(--rail-card-padding, var(--_space-xl));
  width: 100%;
  color: var(--rail-overlay-text, #fff);
}

.rail-card__overlay .rail-card__title { color: inherit; }
.rail-card__overlay .rail-card__meta { color: var(--rail-overlay-meta, #fff); }

.rail__header-action {
  display: inline-flex;
  align-items: center;
  gap: var(--_space-2xs);
  min-height: var(--_control-min-sm);
  padding: 0 var(--_space-2xs);
  color: var(--rail-cta-link-color, var(--_accent-text));
  font-size: var(--_text-lg);
  font-weight: var(--rail-weight-semibold, 600);
  text-decoration: none;
  white-space: nowrap;
}

.rail__header-action:hover { text-decoration: underline; }

/* ── Billboard ───────────────────────────────────────────────────────── */

.rail-billboard {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--rail-billboard-radius, var(--rail-card-radius, 16px));
  border: 1px solid var(--rail-card-border, rgba(255, 255, 255, 0.12));
  aspect-ratio: var(--rail-billboard-aspect, 3 / 4);
  color: var(--rail-overlay-text, #fff);
  isolation: isolate;
}

@media (min-width: 768px) {
  .rail-billboard { aspect-ratio: var(--rail-billboard-aspect-wide, 16 / 7); }
}

.rail-billboard__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -1;
}

.rail-billboard::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(
    --rail-overlay-scrim,
    linear-gradient(to top, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.45) 38%, rgba(0, 0, 0, 0) 68%)
  );
}

.rail-billboard__badge {
  position: absolute;
  top: 16px;
  left: 16px;
  padding: var(--_space-2xs) var(--_space-sm);
  border-radius: var(--_pill);
  font-size: var(--_text-2xs);
  letter-spacing: var(--_track-wider);
  text-transform: uppercase;
  background: var(--rail-badge-bg, rgba(0, 0, 0, 0.6));
  color: var(--rail-badge-color, #fff);
}

.rail-billboard__content {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--_space-md);
  padding: var(--rail-billboard-padding, var(--_space-4xl));
  text-align: center;
}

@media (min-width: 768px) {
  .rail-billboard__content {
    align-items: flex-start;
    text-align: left;
    max-width: 44ch;
  }
}

.rail-billboard__title {
  margin: 0;
  font-family: var(--rail-title-font, inherit);
  font-size: calc(var(--rail-billboard-title-size, clamp(28px, 4vw, 46px)) * var(--_type));
  font-weight: var(--rail-title-weight, 700);
  line-height: 1.03;
  letter-spacing: var(--rail-title-tracking, -0.02em);
  text-wrap: balance;
}

.rail-billboard__lockup img,
.rail-billboard__lockup svg {
  max-width: min(70vw, 420px);
  height: auto;
  display: block;
}

.rail-billboard__status {
  margin: 0;
  font-size: calc(var(--rail-billboard-status-size, 16px) * var(--_type));
  color: var(--rail-overlay-text, #fff);
}

.rail-billboard__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--_space-sm);
  width: 100%;
  justify-content: center;
}

@media (min-width: 768px) {
  .rail-billboard__actions { justify-content: flex-start; width: auto; }
}

.rail-billboard :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, #fff);
  outline-offset: 2px;
}

/* ── Filter chips ────────────────────────────────────────────────────── */

.rail-filters__list {
  display: flex;
  gap: var(--_space-s);
  list-style: none;
  margin: 0;
  padding: 0 0 var(--_space-2xs);
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  overscroll-behavior-x: contain;
}

.rail-filters__list::-webkit-scrollbar { display: none; }

.rail-filters__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--_space-xs);
  white-space: nowrap;
  /* WCAG AA tap target is 24px; 40 is comfortable for a thumb. */
  min-height: var(--_control-min-sm);
  padding: 0 var(--_space-lg);
  border-radius: var(--_pill);
  border: 1px solid var(--rail-card-border, rgba(255, 255, 255, 0.12));
  background: var(--rail-chip-bg, transparent);
  color: inherit;
  font-size: var(--_text-lg);
  font-weight: var(--rail-weight-medium, 500);
  text-decoration: none;
  cursor: pointer;
}

.rail-filters__chip[data-active] {
  background: var(--rail-chip-active-bg, var(--_accent));
  border-color: var(--rail-chip-active-bg, var(--_accent));
  color: var(--rail-chip-active-color, #fff);
}

/* Third instance of the same mistake in this stylesheet: opacity used to say
   "secondary" on something made of words. On the ACTIVE chip, which is filled
   with the brand accent, 0.7 put the count at 3.79:1. The count is already
   de-emphasised by being smaller and tabular; it does not need to be faded
   too. --rail-filters-count-color exists for a brand that wants to push it
   further, and it is that brand's job to keep it above 4.5. */
.rail-filters__count {
  color: var(--rail-filters-count-color, currentColor);
  font-variant-numeric: tabular-nums;
}

.rail-filters :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-filters__chip { transition: background-color var(--_dur-fast) var(--_ease-soft), border-color var(--_dur-fast) var(--_ease-soft), color var(--_dur-fast) var(--_ease-soft); }
}

/* ---------------------------------------------------------------------------
 * RailFrame — the band-and-border that marks one section as the week's thing.
 * ------------------------------------------------------------------------- */

.rail-frame {
  border-radius: var(--rail-frame-radius, calc(var(--_radius) + var(--_space-s)));
  padding: var(--rail-frame-inset, var(--_space-2xs));
  /* The frame is the only place the kit draws a filled accent area, so it
     takes its own token: a brand's button accent is often too loud at this
     size, and too quiet behind white type. */
  background: var(--rail-frame-bg, var(--_accent));
  color: var(--rail-frame-color, #fff);
  overflow: hidden;
}

.rail-frame__band {
  display: flex;
  align-items: baseline;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--_space-2xs) var(--_space-sm);
  margin: 0;
  padding: var(--rail-frame-band-padding, var(--_space-s) var(--_space-md) var(--_space-sm));
  text-align: center;
}

.rail-frame__label {
  font-family: var(--rail-frame-label-font, var(--rail-heading-font, inherit));
  font-size: calc(var(--rail-frame-label-size, 15px) * var(--_type));
  font-weight: var(--rail-frame-label-weight, 800);
  letter-spacing: var(--rail-frame-label-tracking, 0.02em);
  text-transform: var(--rail-frame-label-transform, uppercase);
}

.rail-frame__presenter {
  display: inline-flex;
  align-items: baseline;
  gap: var(--_space-xs);
  font-size: calc(var(--rail-frame-presenter-size, 14px) * var(--_type));
}

.rail-frame__presenter-prefix { opacity: 0.85; }
.rail-frame__presenter-mark { font-weight: 700; color: inherit; }
a.rail-frame__presenter-mark { text-decoration: none; }

.rail-frame__presenter-mark :is(img, svg) {
  display: block;
  max-height: var(--rail-frame-presenter-logo-height, 18px);
  width: auto;
}

.rail-frame__body {
  border-radius: var(--_radius);
  overflow: hidden;
  /* The body is the host's own surface again: the frame colours its edge, not
     what sits inside it. */
  background: var(--rail-frame-body-bg, var(--_bg));
  color: var(--_text);
}

.rail-frame :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * RailVersus — two competitors, in two layouts.
 * ------------------------------------------------------------------------- */

.rail-versus {
  display: flex;
  flex-direction: column;
  /* The card is sized by its slot, not the viewport — it sits in a frame, a
     sidebar, a grid cell. Its breakpoints have to ask the card's own width. */
  container-type: inline-size;
  border-radius: var(--_radius);
  background: var(--_bg);
  color: var(--_text);
  overflow: hidden;
}

/* Inside a frame the card has already been given its corner by the frame's
   body, and doubling the radius leaves a visible sliver of frame colour. */
.rail-frame__body > .rail-versus,
.rail-frame__body > .rail-list { border-radius: 0; }

.rail-versus__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-versus__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
  margin: 0;
  padding: var(--rail-versus-eyebrow-padding, var(--_space-md) var(--_space-mid));
  background: var(--rail-versus-eyebrow-bg, transparent);
  color: var(--rail-versus-eyebrow-color, inherit);
  font-size: calc(var(--rail-versus-eyebrow-size, 16px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  line-height: 1.25;
}

.rail-versus__eyebrow-icon {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
}

.rail-versus__eyebrow-icon :is(img, svg) {
  display: block;
  width: var(--rail-icon-size, 20px);
  height: var(--rail-icon-size, 20px);
}

.rail-versus__eyebrow-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail-versus__eyebrow-badge {
  flex-shrink: 0;
  padding: var(--_space-2xs) var(--_space-md);
  border-radius: var(--rail-versus-badge-radius, 6px);
  background: var(--rail-versus-badge-bg, rgba(128, 128, 128, 0.16));
  background: var(--rail-versus-badge-bg, color-mix(in srgb, currentColor 14%, transparent));
  color: var(--rail-versus-badge-color, inherit);
  font-size: calc(var(--rail-size-label, 13px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
}

.rail-versus__header {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  padding: var(--rail-versus-header-padding, var(--_space-md) var(--_space-mid));
}

.rail-versus__header-avatar {
  flex-shrink: 0;
  width: var(--rail-versus-avatar-size, 40px);
  height: var(--rail-versus-avatar-size, 40px);
  border-radius: var(--_pill);
  object-fit: cover;
}

.rail-versus__header-text { flex: 1; min-width: 0; }

.rail-versus__header-title {
  margin: 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  font-weight: var(--rail-weight-heavy, 800);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
  text-transform: uppercase;
}

.rail-versus__header-subtitle {
  margin: var(--_space-3xs) 0 0;
  font-size: calc(var(--rail-size-meta, 14.5px) * var(--_type));
  color: var(--_muted);
}

.rail-versus__header-value {
  flex-shrink: 0;
  margin: 0;
  text-align: right;
}

.rail-versus__header-value-figure {
  display: block;
  font-size: calc(var(--rail-versus-header-value-size, 22px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  font-variant-numeric: tabular-nums;
}

.rail-versus__header-value-label {
  display: block;
  font-size: calc(var(--rail-size-label, 13px) * var(--_type));
  color: var(--_muted);
}

.rail-versus__sides {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
}

.rail-versus__side { min-width: 0; }
.rail-versus__side > * { min-width: 0; }

/* --- scores layout: figures face each other over one surface -------------- */

.rail-versus[data-rail-layout="scores"] .rail-versus__side {
  display: flex;
  flex-direction: column;
  gap: var(--_space-s);
  padding: var(--rail-versus-side-padding, var(--_space-mid));
}

.rail-versus[data-rail-layout="scores"] .rail-versus__side[data-rail-side="right"] {
  text-align: right;
}

.rail-versus[data-rail-layout="scores"] .rail-versus__art {
  display: block;
  flex-shrink: 0;
  width: var(--rail-versus-crest-size, 58px);
  height: var(--rail-versus-crest-size, 58px);
  border-radius: var(--rail-versus-crest-radius, 8px);
  overflow: hidden;
}

.rail-versus[data-rail-layout="scores"] .rail-versus__body {
  display: flex;
  flex-direction: column;
  gap: var(--_space-2xs);
}

/* The crest and the score sit on one line, mirrored on the right-hand side so
   the two scores end up next to each other in the middle of the card — which
   is the comparison the visitor came for. */
.rail-versus[data-rail-layout="scores"] .rail-versus__side {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  grid-template-areas: "name name" "art body";
  align-items: center;
  column-gap: var(--_space-md);
}

.rail-versus[data-rail-layout="scores"] .rail-versus__side[data-rail-side="right"] {
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  grid-template-areas: "name name" "body art";
}

.rail-versus[data-rail-layout="scores"] .rail-versus__name {
  grid-area: name;
  margin-bottom: var(--_space-s);
}

/* Under ~330px of card the crest and the score cannot share a line without
   crushing the number, which is the one thing on this card nobody may
   misread. The crest goes above it instead. */
@container (max-width: 380px) {
  .rail-versus[data-rail-layout="scores"] .rail-versus__side,
  .rail-versus[data-rail-layout="scores"] .rail-versus__side[data-rail-side="right"] {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "name" "art" "body";
  }
  .rail-versus[data-rail-layout="scores"] .rail-versus__side[data-rail-side="right"] .rail-versus__art {
    margin-left: auto;
  }
}
.rail-versus[data-rail-layout="scores"] .rail-versus__art { grid-area: art; }
.rail-versus[data-rail-layout="scores"] .rail-versus__body { grid-area: body; }

/* --- panels layout: each side gets its own art panel --------------------- */

.rail-versus[data-rail-layout="panels"] .rail-versus__sides {
  gap: var(--rail-versus-panel-gap, 1px);
  background: var(--rail-versus-panel-divider, var(--_border));
}

.rail-versus[data-rail-layout="panels"] .rail-versus__side {
  display: flex;
  flex-direction: column;
  background: var(--_bg);
}

.rail-versus[data-rail-layout="panels"] .rail-versus__art {
  position: relative;
  display: block;
  aspect-ratio: var(--rail-versus-panel-aspect, 1 / 1);
  /* --_tint is the side's own background, set inline from `tint`. Without one
     the panel falls back to the card surface. */
  background: var(--_tint, var(--rail-versus-panel-bg, color-mix(in srgb, currentColor 6%, transparent)));
  overflow: hidden;
}

.rail-versus[data-rail-layout="panels"] .rail-versus__body {
  display: flex;
  flex-direction: column;
  gap: var(--_space-2xs);
  padding: var(--rail-versus-side-padding, var(--_space-mid));
}

.rail-versus[data-rail-layout="panels"]
  .rail-versus__side[data-rail-side="right"]
  .rail-versus__body {
  text-align: right;
}

.rail-versus__art-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.rail-versus__art :is(iframe, video) {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.rail-versus__chip {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: var(--rail-versus-chip-padding, calc(var(--_space-xs) / 2) var(--_space-s));
  border-radius: var(--rail-versus-chip-radius, 5px);
  background: var(--rail-versus-chip-bg, rgba(0, 0, 0, 0.55));
  color: var(--rail-versus-chip-color, #fff);
  font-size: calc(var(--rail-size-label, 12px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
}

.rail-versus__side[data-rail-side="right"] .rail-versus__chip {
  left: auto;
  right: 8px;
}

.rail-versus__name {
  margin: 0;
  /* A grid item's default min-width is auto, so a long team name pushed its
     column wider than the half it was given and overlapped the other side's
     name. Both halves have to be allowed to be narrower than their content. */
  min-width: 0;
  /* break-word, not anywhere: `anywhere` shattered "DADDY ALLEN SUGAR BABIES"
     into one syllable per line on a 375px phone. This breaks a word only when
     the word alone cannot fit. */
  overflow-wrap: break-word;
  font-family: var(--rail-versus-name-font, var(--rail-title-font, inherit));
  font-size: calc(var(--rail-versus-name-size, 15px) * var(--_type));
  font-weight: var(--rail-versus-name-weight, 800);
  line-height: 1.2;
  letter-spacing: var(--rail-tracking-wide, 0.01em);
  text-transform: var(--rail-versus-name-transform, uppercase);
}

.rail-versus__score { margin: 0; }

.rail-versus__score-figure {
  display: block;
  font-family: var(--rail-versus-score-font, var(--rail-stat-font, inherit));
  font-size: calc(var(--rail-versus-score-size, clamp(30px, 7vw, 44px)) * var(--_type));
  font-weight: var(--rail-versus-score-weight, 700);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--rail-tracking-tight, -0.02em);
}

.rail-versus__score-label {
  display: block;
  font-size: calc(var(--rail-size-label, 12px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-label, 0.08em);
  text-transform: uppercase;
  color: var(--_muted);
}

.rail-versus__stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--_space-3xs);
}

.rail-versus__stat {
  font-size: calc(var(--rail-versus-stat-size, 14px) * var(--_type));
  line-height: 1.35;
  color: var(--_muted);
}

.rail-versus__stat-label { margin-right: 4px; }

.rail-versus__stat[data-rail-tone="up"] .rail-versus__stat-value {
  color: var(--rail-tone-up, #46c266);
}

.rail-versus__stat[data-rail-tone="down"] .rail-versus__stat-value {
  color: var(--rail-tone-down, #e2585f);
}

.rail-versus__stat-value { font-variant-numeric: tabular-nums; }

/* --- the meter ----------------------------------------------------------- */

.rail-versus__meter {
  padding: var(--rail-versus-meter-padding, var(--_space-2xs) var(--_space-mid) var(--_space-lg));
}

.rail-versus__meter-label {
  margin: 0 0 var(--_space-xs);
  font-size: calc(var(--rail-size-label, 12px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  letter-spacing: var(--rail-tracking-label, 0.06em);
  text-transform: uppercase;
  color: var(--_muted);
}

.rail-versus__meter-row {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
}

.rail-versus__meter-value {
  flex-shrink: 0;
  font-size: calc(var(--rail-versus-meter-value-size, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  font-variant-numeric: tabular-nums;
  color: var(--_muted);
}

.rail-versus__meter-track {
  flex: 1;
  height: var(--rail-versus-meter-height, 9px);
  border-radius: var(--_pill);
  /* A white-on-dark fallback is invisible on a light brand — caught in the
     workbench, where the FLAS skin lost the unfilled half of the bar. */
  background: var(--rail-versus-meter-track-bg, rgba(128, 128, 128, 0.22));
  background: var(--rail-versus-meter-track-bg, color-mix(in srgb, currentColor 20%, transparent));
  overflow: hidden;
}

.rail-versus__meter-fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--rail-versus-meter-fill, var(--_accent));
}

.rail-versus__hint {
  margin: 0;
  padding: 0 var(--_space-mid) var(--_space-lg);
  text-align: center;
  font-size: calc(var(--rail-size-meta, 14.5px) * var(--_type));
  color: var(--_muted);
}

/* --- the footer ---------------------------------------------------------- */

.rail-versus__actions {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border-top: 1px solid var(--_border);
}

.rail-versus__action {
  display: flex;
  align-items: center;
  justify-content: center;
  /* WCAG AA tap target is 24px; 48 is the comfortable thumb size for a row
     that spans half the card. */
  min-height: var(--rail-versus-action-height, 48px);
  padding: var(--_space-s) var(--_space-md);
  color: inherit;
  font-size: calc(var(--rail-versus-action-size, 16px) * var(--_type));
  font-weight: var(--rail-weight-medium, 500);
  text-align: center;
  text-decoration: none;
}

.rail-versus__action + .rail-versus__action {
  border-left: 1px solid var(--_border);
}

.rail-versus :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: -2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-versus__meter-fill { transition: inline-size var(--_dur-slow) var(--_ease); }
  .rail-versus__action { transition: background-color var(--_dur-fast) var(--_ease-soft); }
}

@media (hover: hover) and (pointer: fine) {
  .rail-versus__action:hover {
    background: var(--rail-versus-action-hover-bg, color-mix(in srgb, currentColor 7%, transparent));
  }
}

/* ---------------------------------------------------------------------------
 * RailList — a vertical stack of one-line choices.
 * ------------------------------------------------------------------------- */

.rail-list {
  display: flex;
  flex-direction: column;
  gap: var(--_space-md);
}

.rail-list__header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--_space-lg);
}

.rail-list__eyebrow {
  margin: 0 0 var(--_space-2xs);
  font-size: calc(var(--rail-size-label, 12px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  letter-spacing: var(--rail-tracking-label, 0.1em);
  text-transform: uppercase;
  color: var(--rail-eyebrow-color, var(--_muted));
}

.rail-list__heading {
  margin: 0;
  font-family: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-heading-size, clamp(24px, 3vw, 34px)) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.1;
}

.rail-list__header-action {
  flex-shrink: 0;
  /* Measured at 55x18 by the brand check — under the 24px WCAG 2.2 AA floor.
     A text link is still a tap target. */
  display: inline-flex;
  align-items: center;
  min-height: var(--_tap-min);
  color: var(--rail-cta-link-color, var(--_accent-text));
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  text-decoration: none;
}

.rail-list__items {
  list-style: none;
  margin: 0;
  padding: 0;
  border-radius: var(--_radius);
  background: var(--rail-list-bg, var(--_bg));
  overflow: hidden;
}

.rail-list__item + .rail-list__item {
  border-top: 1px solid var(--_border);
}

.rail-list__row {
  display: flex;
  align-items: center;
  gap: var(--_space-mid);
  /* 56 clears the 24px AA tap target with room for two lines of text. */
  min-height: var(--rail-list-row-height, 56px);
  padding: var(--rail-list-row-padding, var(--_space-mid) var(--_space-lg));
  color: inherit;
  text-decoration: none;
}

.rail-list__icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-icon-box, 34px);
  height: var(--rail-icon-box, 34px);
  border-radius: var(--rail-icon-radius, 10px);
  background: var(--rail-icon-bg, transparent);
  color: var(--_accent);
}

.rail-list__icon :is(img, svg) {
  display: block;
  width: var(--rail-icon-size, 22px);
  height: var(--rail-icon-size, 22px);
}

.rail-list__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--_space-3xs);
}

.rail-list__title {
  font-family: var(--rail-title-font, inherit);
  font-size: calc(var(--rail-list-title-size, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.25;
}

.rail-list__title-link { color: inherit; text-decoration: none; }

.rail-list__description {
  font-size: calc(var(--rail-list-description-size, 14.5px) * var(--_type));
  line-height: 1.4;
  color: var(--_muted);
}

.rail-list__value {
  flex-shrink: 0;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  font-variant-numeric: tabular-nums;
}

.rail-list__action {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--rail-list-action-height, var(--_control-min-sm));
  padding: 0 var(--_space-xl);
  border-radius: var(--rail-cta-radius, var(--_pill));
  border: 1px solid var(--rail-cta-secondary-border, var(--_border));
  background: var(--rail-cta-secondary-bg, transparent);
  color: var(--rail-cta-secondary-color, var(--rail-cta-link-color, var(--_accent-text)));
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  text-decoration: none;
  white-space: nowrap;
}

.rail-list :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: -2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-list__row { transition: background-color var(--_dur-fast) var(--_ease-soft); }
}

@media (hover: hover) and (pointer: fine) {
  a.rail-list__row:hover {
    background: var(--rail-list-row-hover-bg, color-mix(in srgb, currentColor 6%, transparent));
  }
}

/* ---------------------------------------------------------------------------
 * Glass surface — opt in with data-rail-surface="glass" on any kit root.
 *
 * The material is in the EDGE, not the fill: a one-pixel gradient hairline
 * that catches more light at the top, the way the canto of a real sheet of
 * glass does. `saturate` is half the trick — without it the blur greys out
 * whatever is behind and the panel reads as dirty plastic.
 *
 * It needs something behind it to be worth anything. On a flat background a
 * glass card is just a slightly lighter card, which is why this is opt-in.
 * ------------------------------------------------------------------------- */

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  [data-rail-surface="glass"] :is(.rail-card, .rail-versus, .rail-list__items),
  .rail-versus[data-rail-surface="glass"],
  .rail-list[data-rail-surface="glass"] .rail-list__items {
    position: relative;
    background: var(--rail-glass-bg, rgba(255, 255, 255, 0.07));
    -webkit-backdrop-filter: blur(var(--rail-glass-blur, 18px))
      saturate(var(--rail-glass-saturate, 1.7));
    backdrop-filter: blur(var(--rail-glass-blur, 18px))
      saturate(var(--rail-glass-saturate, 1.7));
    box-shadow: var(--rail-glass-shadow, 0 24px 60px -28px rgba(0, 0, 0, 0.85));
  }

  /* The hairline is a ::before and not a `border`, because a border is the
     same colour on all four sides and a lit edge is not. */
  [data-rail-surface="glass"] :is(.rail-card, .rail-versus, .rail-list__items)::before,
  .rail-versus[data-rail-surface="glass"]::before,
  .rail-list[data-rail-surface="glass"] .rail-list__items::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;
    background: var(
      --rail-glass-edge,
      linear-gradient(
        to bottom,
        rgba(255, 255, 255, 0.55),
        rgba(255, 255, 255, 0.12) 38%,
        rgba(255, 255, 255, 0.06)
      )
    );
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
  }
}

/* ---------------------------------------------------------------------------
 * POSTER VARIANT — the catalogue language, promoted from danielzea-site's
 * `cartel.css`, where it had been a local override of this kit for months.
 *
 * The default card is EDITORIAL and brand-neutral on purpose: text first, a
 * hairline above it, the picture after. That is a magazine, and it is right
 * for a piece of writing.
 *
 * It is wrong for a catalogue. When the thing on the card is a thing you look
 * at — a car, a listing, a night, a film — the cover IS the product, so the
 * picture leads and the words sit on the panel under it.
 *
 * What is NOT promoted from danielzea: the hard-coded #101010 panel, the
 * cream #f3e4d6 label, the 4:5 aspect that came from measuring that site's
 * eight photographs, and the `--prensa` / `--noche` variants, which are that
 * site's content model. All of it arrives as tokens here.
 * ------------------------------------------------------------------------- */

/* One column, three rows. The picture takes the first; the title takes the
   second, the copy the third.
   The reason this is a grid and not `position: absolute`: in the kit's markup
   the title and the figure are SIBLINGS, so anchoring one to the other needs
   a made-up height for the caption — a magic number that breaks the day
   somebody writes one more line. With rows, the card grows and nothing can
   ever overlap. */
[data-rail-variant="poster"] .rail-card[data-rail-kind="media"],
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto auto auto;
  border-top: 0;
  border-radius: var(--_radius);
  overflow: hidden;
  background: var(--rail-poster-bg, var(--_bg));
  box-shadow: var(--_shadow);
  /* A POSTER CARD PAINTS ITS OWN PANEL, so it cannot take its text colour
     from the brand and hope. Caught in the workbench: a light brand with a
     dark --rail-poster-bg rendered dark text on it and the title disappeared
     entirely. `color: inherit` is invisible to the theme audit — it is not a
     literal — so this is the class of hole a regex cannot find and looking
     can. Any surface that sets its own background owes its own foreground. */
  color: var(--rail-poster-color, inherit);
}

[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] :is(.rail-card__subtitle, .rail-card__meta, .rail-card__description),
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] :is(.rail-card__subtitle, .rail-card__meta, .rail-card__description) {
  color: var(--rail-poster-muted, var(--_muted));
}

[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__figure,
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__figure {
  position: relative;
  grid-area: 1 / 1 / 2 / 2;
  z-index: 0;
  margin-top: 0;
  aspect-ratio: var(--rail-poster-aspect, var(--_aspect));
}

/* The picture takes ONLY the first row, and does not sit under the text.
   danielzea measured this the hard way: across eight event photographs the
   subject's face landed anywhere between 15% and 72% of the height, so any
   scrim over the copy covered a face in three of them. A catalogue cover is
   designed with its dead band at the bottom; a real photograph is not. */
[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__body,
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__body {
  grid-area: 2 / 1 / 3 / 2;
  z-index: 2;
  gap: var(--_space-xs);
  padding: var(--rail-poster-padding, 0 clamp(var(--_space-xl), 2vw, var(--_space-4xl)));
}

[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__description,
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__description {
  grid-area: 3 / 1 / 4 / 2;
  z-index: 2;
  display: block;
  margin: 0;
  padding: var(--_space-sm) clamp(var(--_space-xl), 2vw, var(--_space-4xl)) clamp(var(--_space-2xl), 2vw, var(--_space-4xl));
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  line-height: 1.5;
}

/* The seam between the photograph and the panel reads as two pieces glued
   together. Fading the last strip of the picture into the panel colour makes
   it one card — and 18% is below the lowest face danielzea measured, so it
   never covers a subject. Set --rail-poster-bg to a real colour for this to
   work: a transparent panel has nothing to fade INTO. */
[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__figure::after,
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__figure::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px 0;
  height: var(--rail-poster-fade-height, 18%);
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    color-mix(in srgb, var(--rail-poster-bg, var(--_bg)) 55%, transparent) 52%,
    var(--rail-poster-bg, var(--_bg)) 100%
  );
}

/* THE BADGE IS A GLASS BOOKMARK, NOT INK ON THE PHOTOGRAPH.
   A label over a picture cannot trust the picture's colour, because the
   picture changes on every card and at every crop. So it brings its own
   background — but an opaque rectangle reads as a patch stuck on top, so the
   background is glass: it lets the photograph through and still holds the
   letter. This is the sane exception to "no glass on a full-bleed card": the
   glass here is a 20px label, not the whole panel.
   The shape is a bookmark — square, with a V notch at the right, like the
   ribbon left between the pages of a book. `clip-path` cancels
   `border-radius`, so the left rounding lives inside the polygon itself. */
[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__badge,
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__badge,
[data-rail-variant="poster"] .rail-billboard__badge {
  /* The letter is NOT the brand accent, and that is arithmetic, not taste.
     Measured against the worst case — a WHITE photograph behind the glass,
     which in a real set exists: a lit ceiling, a pale studio wall. A mid
     copper at .62 veil gives 1.98:1. Reaching AA by darkening the veil to
     .85 stops being glass and becomes a black label, losing the one thing
     the glass was for. A warm cream at .66 gives 5.38:1 and keeps it. */
  color: var(--rail-poster-badge-color, #f3e4d6);
  padding: var(--_space-xs) var(--_space-2xl) var(--_space-xs) var(--_space-md);
  border-radius: 0;
  background: var(--rail-poster-badge-bg, rgba(8, 8, 8, 0.66));
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  /* the light on the edge: the material shows at the border, not in the fill */
  box-shadow: var(--rail-poster-badge-edge, inset 0 1px 0 rgba(255, 255, 255, 0.16));
  clip-path: polygon(
    3px 0,
    100% 0,
    calc(100% - 8px) 50%,
    100% 100%,
    3px 100%,
    0 calc(100% - 3px),
    0 3px
  );
  text-shadow: var(--rail-poster-badge-shadow, 0 1px 3px rgba(0, 0, 0, 0.55));
}

[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__badge,
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__badge {
  grid-area: 1 / 1 / 2 / 2;
  align-self: start;
  justify-self: start;
  z-index: 2;
  margin: clamp(var(--_space-lg), 1.8vw, var(--_space-3xl));
}

[data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__title,
.rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__title {
  font-size: calc(var(--rail-poster-title-size, clamp(22px, 2.2vw, 28px)) * var(--_type));
}

/* The catalogue gesture: the cover breathes under the cursor. Fine pointers
   only — on a phone there is no hover and a :hover there stays stuck. */
@media (prefers-reduced-motion: no-preference) {
  [data-rail-variant="poster"] .rail-card[data-rail-kind="media"] .rail-card__image,
  .rail-card[data-rail-variant="poster"][data-rail-kind="media"] .rail-card__image {
    transition: transform var(--_dur-slow) var(--_ease);
  }
}

@media (hover: hover) and (pointer: fine) {
  [data-rail-variant="poster"] .rail-card[data-rail-kind="media"]:hover .rail-card__image,
  .rail-card[data-rail-variant="poster"][data-rail-kind="media"]:hover .rail-card__image {
    transform: scale(var(--rail-poster-hover-scale, 1.045));
  }
}

/* ---------------------------------------------------------------------------
 * RailSheet — the card, opened. Promoted from danielzea-site's `ficha.css`.
 *
 * NEVER SET `display` ON THE <dialog>. This cost danielzea the only two bugs
 * the piece ever had, and both are silent:
 *
 *   · Closed, the panel stayed IN THE FLOW. The browser's own rule is
 *     `dialog:not([open]) { display: none }`, but ANY author `display` beats
 *     it — author styles win over UA styles regardless of specificity. So the
 *     panel existed at all times, invisible by colour but present to a screen
 *     reader.
 *   · Open, it flew 2,716px above the viewport. A modal dialog is centred by
 *     the browser with its own `position: fixed` and `margin: auto`; changing
 *     its `display` stops that machinery adding up.
 *
 * The grid goes on `.rail-sheet__in`, a wrapper inside. The dialog keeps the
 * display the browser wants and takes only box and colour.
 * ------------------------------------------------------------------------- */

.rail-sheet {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--rail-text, inherit);
  width: min(var(--rail-sheet-width, 1060px), 92vw);
  max-height: var(--rail-sheet-height, 88vh);
  overflow: hidden;
  border-radius: var(--rail-card-radius, 16px);
  /* A modal dialog is centred by the browser with `margin: auto`, and a CSS
     reset takes that away without meaning to: Tailwind's preflight zeroes the
     margin on every element, `dialog` included. The sheet then pins to the
     inset-0 corner and sits hard against the left edge with the whole gap on
     the right, which reads as a broken panel rather than a centred one.
     Restated here so the kit does not depend on what a consumer's reset does. */
  margin: auto;
}

.rail-sheet::backdrop {
  background: var(--rail-sheet-backdrop, rgba(4, 4, 4, 0.82));
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
}

.rail-sheet__in {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  max-height: var(--rail-sheet-height, 88vh);
  overflow: hidden;
  border-radius: var(--rail-card-radius, 16px);
  /* A MODAL PANEL HAS TO BE OPAQUE, and --rail-card-bg is not: the kit's card
     surface is deliberately translucent because a card sits ON the page and
     is meant to pick up what is behind it. Inheriting that here let the rail
     show straight through the open sheet.
     The first attempt used `Canvas`, and the workbench caught it: Canvas
     follows the OS colour scheme, not the brand, so a dark brand on a light
     machine got a WHITE panel under its white text. A system colour cannot
     know which way round the brand is.
     So the fallback is opaque dark, which is what the rest of this file
     already assumes — every neutral here is white-on-dark. A light brand
     overrides --rail-sheet-bg exactly as it already overrides --rail-card-bg
     and --rail-muted. The brand's own card tint is composited on top as an
     image layer, so the panel keeps the brand's colour either way. */
  background-color: var(--rail-sheet-bg, #111);
  background-image: linear-gradient(
    var(--rail-card-bg, transparent),
    var(--rail-card-bg, transparent)
  );
  box-shadow: var(--rail-card-shadow, 0 18px 40px -22px rgba(0, 0, 0, 0.9));
}

@media (min-width: 860px) {
  .rail-sheet__in {
    grid-template-columns:
      minmax(0, var(--rail-sheet-figure-width, 46%))
      minmax(0, 1fr);
  }
}

.rail-sheet__figure {
  margin: 0;
  min-height: 0;
  background: var(--rail-sheet-figure-bg, rgba(0, 0, 0, 0.35));
}

/* `contain`, not `cover`: the whole point of opening it is to see the
   photograph WHOLE. Cropping it again here would leave the panel with no
   reason to exist. On a wide screen the picture has a full column to itself,
   so it can fill it. */
.rail-sheet__image,
.rail-sheet__figure > :is(img, video, iframe) {
  display: block;
  width: 100%;
  height: 100%;
  max-height: var(--rail-sheet-figure-max, 44vh);
  object-fit: contain;
  border: 0;
}

@media (min-width: 860px) {
  .rail-sheet__image,
  .rail-sheet__figure > :is(img, video, iframe) {
    max-height: var(--rail-sheet-height, 88vh);
    object-fit: cover;
  }
}

.rail-sheet__text {
  display: flex;
  flex-direction: column;
  gap: var(--_space-mid);
  min-height: 0;
  padding: var(--rail-sheet-padding, clamp(var(--_space-4xl), 3.4vw, var(--_control-min)));
  overflow-y: auto;
}

.rail-sheet__badge {
  margin: 0;
  font-size: calc(var(--rail-sheet-badge-size, 12px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  letter-spacing: var(--rail-tracking-label, 0.1em);
  text-transform: uppercase;
  color: var(--rail-eyebrow-color, var(--rail-accent, currentColor));
}

.rail-sheet__title {
  margin: 0;
  font-family: var(--rail-sheet-title-font, var(--rail-heading-font, inherit));
  font-size: calc(var(--rail-sheet-title-size, clamp(30px, 4vw, 52px)) * var(--_type));
  font-weight: var(--rail-sheet-title-weight, 400);
  line-height: 1.06;
  letter-spacing: var(--rail-tracking-tight, -0.02em);
}

.rail-sheet__meta {
  margin: 0;
  font-size: calc(var(--rail-sheet-meta-size, 12px) * var(--_type));
  letter-spacing: var(--rail-tracking-label, 0.1em);
  text-transform: uppercase;
  color: var(--rail-muted, rgba(255, 255, 255, 0.65));
}

.rail-sheet__body {
  margin: var(--_space-xs) 0 0;
  /* Reading size and a reading measure. This is the room the sheet exists to
     give; setting it in a 44ch column is most of what makes it feel like a
     page rather than a bigger card. */
  font-size: calc(var(--rail-sheet-body-size, clamp(17px, 1.9vw, 21px)) * var(--_type));
  line-height: 1.6;
  max-width: var(--rail-sheet-measure, 44ch);
  color: var(--rail-sheet-body-color, inherit);
}

.rail-sheet__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--_space-sm);
  margin-top: auto;
  padding-top: var(--_space-md);
}

.rail-sheet__close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 3;
  display: grid;
  place-items: center;
  /* 46 is comfortable for a thumb and clears the 24px AA target. */
  width: var(--rail-sheet-close-size, 46px);
  height: var(--rail-sheet-close-size, 46px);
  border-radius: var(--_pill);
  border: 1px solid var(--rail-card-border, rgba(255, 255, 255, 0.12));
  background: var(--rail-sheet-close-bg, rgba(10, 10, 10, 0.55));
  color: inherit;
  font-size: calc(var(--rail-size-title, 26px) * var(--_type));
  line-height: 1;
  cursor: pointer;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.rail-sheet__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-sheet :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--rail-accent, currentColor));
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .rail-sheet__close:hover {
    background: var(--rail-sheet-close-hover-bg, rgba(10, 10, 10, 0.8));
    border-color: var(--rail-accent, currentColor);
  }
}

/* ---------------------------------------------------------------------------
 * RailFaq — questions and answers on <details>/<summary>.
 * Promoted from danielzea-site's `faq.css`.
 * ------------------------------------------------------------------------- */

.rail-faq { max-width: var(--rail-measure, 68ch); }

.rail-faq__heading {
  margin: 0 0 var(--_space-s);
  font-family: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-heading-size, clamp(24px, 3vw, 34px)) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.1;
}

.rail-faq details { border-top: 1px solid var(--_border); }
.rail-faq details[open] { border-color: var(--rail-faq-open-border, currentColor); }

.rail-faq summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--_space-4xl);
  /* 44 is the comfortable thumb target; AA's floor is 24. */
  min-height: var(--_control-min);
  padding: var(--rail-faq-padding, 28px 0);
  list-style: none;
  cursor: pointer;
}

/* Safari still paints its own marker without this. */
.rail-faq summary::-webkit-details-marker { display: none; }

.rail-faq__q {
  margin: 0;
  font-family: var(--rail-faq-q-font, var(--rail-title-font, inherit));
  font-size: calc(var(--rail-faq-q-size, clamp(20px, 2.8vw, 34px)) * var(--_type));
  font-weight: var(--rail-faq-q-weight, 400);
  line-height: 1.2;
  letter-spacing: var(--rail-tracking-tight, -0.018em);
}

.rail-faq__pm {
  flex-shrink: 0;
  font-size: calc(var(--rail-size-title, 24px) * var(--_type));
  line-height: 1;
  color: var(--_muted);
}

.rail-faq details[open] .rail-faq__pm { transform: rotate(45deg); }

.rail-faq__a {
  padding: var(--rail-faq-answer-padding, 0 0 calc(var(--_space-md) * 2.5));
  max-width: var(--rail-measure, 44rem);
  color: var(--_muted);
  font-size: calc(var(--rail-faq-a-size, 18px) * var(--_type));
  line-height: 1.62;
}

.rail-faq summary:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-faq__pm { transition: transform var(--_dur-base) var(--_ease); }
}

/* ---------------------------------------------------------------------------
 * RailPlayer — a video facade. Promoted from danielzea-site's `video.css`.
 * ------------------------------------------------------------------------- */

.rail-player {
  position: relative;
  display: block;
  width: 100%;
  padding: var(--rail-player-padding, 26px 0 0);
  border: 0;
  border-top: 1px solid var(--rail-player-rule, currentColor);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.rail-player[data-rail-playing] {
  padding: 0;
  border: 0;
  aspect-ratio: 16 / 9;
  background: var(--rail-player-stage-bg, #000);
  cursor: auto;
}

.rail-player iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.rail-player__shot {
  position: relative;
  display: block;
  margin-top: var(--_space-3xl);
  overflow: hidden;
}

.rail-player__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* THE PLAY DISC IS OPAQUE, and that is a contrast result rather than a style
   choice. As a white glyph on a black disc at 34% its real contrast depended
   on whichever frame sat underneath; against a pale mount it measured 1.06:1.
   A control whose legibility is decided by a photograph is not a control. */
.rail-player__mark {
  position: absolute;
  left: var(--rail-player-mark-inset, 22px);
  bottom: var(--rail-player-mark-inset, 22px);
  display: grid;
  place-items: center;
  width: var(--rail-player-mark-size, 56px);
  height: var(--rail-player-mark-size, 56px);
  padding-left: 3px;
  border-radius: var(--_pill);
  background: var(--rail-player-mark-bg, #faf8f6);
  color: var(--rail-player-mark-color, #141210);
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  box-shadow: var(--rail-player-mark-shadow, 0 2px 10px rgba(0, 0, 0, 0.45));
}

.rail-player__title {
  display: block;
  margin-top: var(--_space-lg);
  font-family: var(--rail-title-font, inherit);
  font-size: calc(var(--rail-player-title-size, clamp(20px, 2.6vw, 32px)) * var(--_type));
  font-weight: var(--rail-player-title-weight, 400);
  line-height: 1.16;
  letter-spacing: var(--rail-tracking-tight, -0.018em);
}

.rail-player__meta {
  display: block;
  margin-top: var(--_space-sm);
  font-size: calc(var(--rail-size-micro, 11.5px) * var(--_type));
  letter-spacing: var(--rail-tracking-label, 0.14em);
  text-transform: uppercase;
  color: var(--_muted);
}

.rail-player__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-player:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 3px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-player__mark {
    transition: background-color var(--_dur-slow) var(--_ease-soft), transform var(--_dur-slow) var(--_ease);
  }
  .rail-player__shot img {
    transition: transform var(--_dur-slow) var(--_ease);
  }
}

@media (hover: hover) and (pointer: fine) {
  .rail-player:hover .rail-player__mark { transform: scale(1.06); }
  .rail-player:hover .rail-player__shot img { transform: scale(1.03); }
}

/* ---------------------------------------------------------------------------
 * RailScene — a photograph and one sentence, overlapping.
 * Promoted from danielzea-site's `escena.css`.
 * ------------------------------------------------------------------------- */

.rail-scene {
  display: grid;
  gap: var(--rail-scene-gap, clamp(var(--_space-4xl), 4vw, calc(var(--_space-4xl) * 2.34)));
  align-items: center;
}

.rail-scene__figure {
  margin: 0;
  position: relative;
  overflow: hidden;
  /* The picture keeps its portrait shape. Cropping a portrait to a landscape
     band takes the top of somebody's head off. */
  aspect-ratio: var(--rail-scene-aspect, 4 / 5);
  outline: 1px solid var(--_border);
  outline-offset: -1px;
}

.rail-scene__figure > :is(img, video, iframe) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--rail-scene-focus, 50% 34%);
  display: block;
  border: 0;
}

.rail-scene__quote {
  margin: 0;
  font-family: var(--rail-scene-quote-font, var(--rail-heading-font, inherit));
  font-size: calc(var(--rail-scene-quote-size, clamp(24px, 3.6vw, 46px)) * var(--_type));
  font-weight: var(--rail-scene-quote-weight, 400);
  font-style: var(--rail-scene-quote-style, italic);
  line-height: 1.18;
  letter-spacing: var(--rail-tracking-tight, -0.02em);
  text-wrap: balance;
  max-width: 20ch;
}

.rail-scene__caption {
  margin: var(--rail-scene-caption-margin, clamp(var(--_space-2xl), 2.6vw, calc(var(--_space-md) * 2.5)) 0 0);
  font-size: calc(var(--rail-scene-caption-size, 12px) * var(--_type));
  letter-spacing: var(--rail-tracking-label, 0.1em);
  text-transform: uppercase;
  color: var(--_muted);
}

/* The accent rule marks the caption, not the quote: a hairline beside a large
   serif line competes with it. */
.rail-scene__caption::before {
  content: "";
  display: block;
  width: 52px;
  height: 1px;
  background: var(--_accent);
  margin: 0 0 var(--_space-lg);
}

@media (min-width: 860px) {
  .rail-scene {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    gap: 0;
  }

  /* THE PICTURE AND THE LINE TOUCH. Two columns with 84px of nothing between
     them read as two objects looking at each other. The line riding over the
     last third of the picture is what makes the page read like a cover. */
  .rail-scene__text {
    margin-left: clamp(-140px, -9vw, -60px);
    position: relative;
    z-index: 1;
  }

  /* The line sits on a photograph, so it carries its own legibility rather
     than trusting the frame underneath it. */
  .rail-scene__quote {
    text-shadow: var(
      --rail-scene-quote-shadow,
      0 2px 40px rgba(0, 0, 0, 0.85),
      0 1px 8px rgba(0, 0, 0, 0.6)
    );
  }

  .rail-scene[data-rail-flip] .rail-scene__figure { order: 2; }
  .rail-scene[data-rail-flip] .rail-scene__text {
    order: 1;
    margin-left: 0;
    margin-right: clamp(-140px, -9vw, -60px);
    text-align: right;
  }
  .rail-scene[data-rail-flip] .rail-scene__quote { margin-left: auto; }
  .rail-scene[data-rail-flip] .rail-scene__caption::before { margin-left: auto; }
}

/* ---------------------------------------------------------------------------
 * RailStickyBar — the bar that follows the reader down the page.
 * Promoted from danielzea-site's `contacto-fijo.css`.
 * ------------------------------------------------------------------------- */

.rail-stickybar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--rail-stickybar-z, 40);
  background: var(--rail-stickybar-bg, #0a0a0a);
  border-top: 1px solid var(--_border);
  transform: translateY(100%);
}

.rail-stickybar[data-rail-visible="true"] { transform: none; }

.rail-stickybar__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--_space-lg);
  flex-wrap: wrap;
  max-width: var(--rail-stickybar-max, 1200px);
  margin: 0 auto;
  padding: var(--rail-stickybar-padding, var(--_space-mid) var(--_space-lg));
}

.rail-stickybar__label {
  margin: 0;
  min-width: 0;
  font-size: calc(var(--rail-stickybar-label-size, 15px) * var(--_type));
  color: var(--_muted);
}

.rail-stickybar__actions {
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
  flex-shrink: 0;
}

.rail-stickybar__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--rail-stickybar-action-height, var(--_control-min));
  padding: 0 var(--_space-xl);
  border-radius: var(--rail-cta-radius, var(--_pill));
  border: 1px solid var(--_border);
  color: inherit;
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  text-decoration: none;
  white-space: nowrap;
}

.rail-stickybar__action[data-rail-primary] {
  background: var(--rail-cta-bg, var(--_accent));
  border-color: var(--rail-cta-bg, var(--_accent));
  color: var(--rail-cta-color, #fff);
}

.rail-stickybar :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-stickybar {
    transition: transform var(--_dur-slow) var(--_ease-out);
  }
}

/* ---------------------------------------------------------------------------
 * RailTabs — the sections across the top, active one underlined.
 * ------------------------------------------------------------------------- */

.rail-tabs { border-bottom: 1px solid var(--_border); }

.rail-tabs__list {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.rail-tabs__item { flex: 1; min-width: 0; }

.rail-tabs__tab {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--_space-s);
  width: 100%;
  /* 48 clears the 24px AA target with room for the underline below the text. */
  min-height: var(--rail-tabs-height, 48px);
  padding: var(--_space-md) var(--_space-s);
  border: 0;
  background: transparent;
  color: var(--_muted);
  font-family: inherit;
  font-size: calc(var(--rail-tabs-size, 17px) * var(--_type));
  font-weight: var(--rail-weight-medium, 500);
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  /* The underline is a border on the control, not a sliding element: one
     fewer thing to keep in sync with the active id. */
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
}

.rail-tabs__tab[aria-current] {
  color: var(--rail-tabs-active-color, var(--_accent-text));
  border-bottom-color: var(--rail-tabs-active-color, var(--_accent-text));
}

.rail-tabs__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rail-tabs__badge {
  flex-shrink: 0;
  min-width: 20px;
  padding: 0 var(--_space-xs);
  border-radius: var(--_pill);
  background: var(--rail-badge-bg, var(--_accent));
  color: var(--rail-badge-color, #fff);
  font-size: calc(var(--rail-size-label, 12px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: var(--rail-tabs-badge-line, var(--_space-2xl));
}

.rail-tabs :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: -2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-tabs__tab { transition: color var(--_dur-fast) var(--_ease-soft), border-color var(--_dur-fast) var(--_ease-soft); }
}

/* ---------------------------------------------------------------------------
 * RailBottomNav — the destinations under the thumb.
 * ------------------------------------------------------------------------- */

.rail-bottomnav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--rail-bottomnav-z, 45);
  background: var(--rail-bottomnav-bg, #0a0a0a);
  border-top: 1px solid var(--_border);
  /* The home indicator on a modern phone sits over the bottom of the screen. */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

.rail-bottomnav__list {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.rail-bottomnav__item { flex: 1; min-width: 0; }

.rail-bottomnav__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--_space-2xs);
  min-height: var(--rail-bottomnav-height, 56px);
  padding: var(--_space-s) var(--_space-2xs);
  color: var(--_muted);
  text-decoration: none;
  text-align: center;
}

.rail-bottomnav__link[aria-current="page"] {
  color: var(--rail-bottomnav-active-color, var(--_accent-text));
}

.rail-bottomnav__icon {
  position: relative;
  display: grid;
  place-items: center;
}

.rail-bottomnav__icon :is(svg, img) {
  width: var(--rail-icon-size, 22px);
  height: var(--rail-icon-size, 22px);
  display: block;
}

.rail-bottomnav__badge {
  position: absolute;
  top: -6px;
  left: 60%;
  min-width: 17px;
  padding: var(--rail-bottomnav-badge-padding, 0 calc(var(--_space-sm) / 2));
  border-radius: var(--_pill);
  background: var(--rail-badge-bg, var(--_accent));
  color: var(--rail-badge-color, #fff);
  font-size: calc(var(--rail-size-micro, 11px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: var(--rail-bottomnav-badge-line, calc(var(--_space-s) * 2.125));
  text-align: center;
}

.rail-bottomnav__label {
  font-size: calc(var(--rail-bottomnav-label-size, 11px) * var(--_type));
  letter-spacing: var(--rail-tracking-wide, 0.02em);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.rail-bottomnav a:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: -2px;
}

/* ---------------------------------------------------------------------------
 * RailFab — one persistent action, floating.
 * ------------------------------------------------------------------------- */

.rail-fab {
  position: fixed;
  right: var(--rail-fab-inset, 16px);
  bottom: var(--rail-fab-inset, 16px);
  z-index: var(--rail-fab-z, 50);
  display: grid;
  place-items: center;
  gap: var(--_space-3xs);
  width: var(--rail-fab-size, 68px);
  height: var(--rail-fab-size, 68px);
  border-radius: var(--_pill);
  border: 0;
  background: var(--rail-fab-bg, #fff);
  color: var(--rail-fab-color, #111);
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--rail-fab-shadow, 0 6px 20px -6px rgba(0, 0, 0, 0.6));
  /* Clears the home indicator when it sits at the very bottom. */
  margin-bottom: env(safe-area-inset-bottom, 0px);
}

.rail-fab__glyph {
  display: grid;
  place-items: center;
  font-size: calc(var(--rail-fab-glyph-size, 22px) * var(--_type));
  line-height: 1;
}

.rail-fab__glyph :is(svg, img) {
  width: var(--rail-fab-glyph-size, 22px);
  height: var(--rail-fab-glyph-size, 22px);
  display: block;
}

.rail-fab__label {
  font-size: calc(var(--rail-fab-label-size, 9.5px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-label, 0.08em);
  text-transform: uppercase;
}

.rail-fab:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 3px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-fab { transition: transform var(--_dur-fast) var(--_ease); }
}

@media (hover: hover) and (pointer: fine) {
  .rail-fab:hover { transform: scale(1.05); }
}

/* ---------------------------------------------------------------------------
 * RailProgress — progress towards one thing worth reaching.
 * ------------------------------------------------------------------------- */

.rail-progress {
  padding: var(--rail-progress-padding, var(--_space-mid) var(--_space-lg));
  border-radius: var(--_radius);
  background: var(--rail-progress-bg, var(--_bg));
}

.rail-progress__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--_space-md);
  margin-bottom: var(--_space-sm);
}

.rail-progress__label {
  font-size: calc(var(--rail-progress-label-size, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
}

.rail-progress__value {
  font-size: calc(var(--rail-progress-value-size, 16px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* <progress> is styled through vendor pseudo-elements and ignores most of
   what you set on the element itself, so appearance is reset first. */
.rail-progress__bar {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: var(--rail-progress-height, 10px);
  border: 0;
  border-radius: var(--_pill);
  overflow: hidden;
  background: var(--rail-progress-track, color-mix(in srgb, currentColor 20%, transparent));
  color: var(--rail-progress-fill, var(--_accent));
}

.rail-progress__bar::-webkit-progress-bar {
  background: var(--rail-progress-track, color-mix(in srgb, currentColor 20%, transparent));
  border-radius: var(--_pill);
}

.rail-progress__bar::-webkit-progress-value {
  background: var(--rail-progress-fill, var(--_accent));
  border-radius: var(--_pill);
}

.rail-progress__bar::-moz-progress-bar {
  background: var(--rail-progress-fill, var(--_accent));
  border-radius: var(--_pill);
}

.rail-progress__note {
  margin: var(--_space-s) 0 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

/* ---------------------------------------------------------------------------
 * RailStats — two to four figures, all visible at once.
 * ------------------------------------------------------------------------- */

.rail-stats {
  display: grid;
  gap: var(--rail-stats-gap, var(--_space-md));
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 640px) {
  .rail-stats[data-rail-columns="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .rail-stats[data-rail-columns="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.rail-stats__tile {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  min-width: 0;
  padding: var(--rail-stats-padding, var(--_space-lg));
  border-radius: var(--_radius);
  background: var(--rail-stats-bg, var(--_bg));
  color: inherit;
  text-decoration: none;
}

.rail-stats__icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
}

.rail-stats__icon :is(svg, img) {
  width: var(--rail-stats-icon-size, 34px);
  height: var(--rail-stats-icon-size, 34px);
  display: block;
}

.rail-stats__text { min-width: 0; }

.rail-stats__value {
  display: block;
  font-family: var(--rail-stat-font, inherit);
  font-size: calc(var(--rail-stats-value-size, clamp(24px, 5vw, 34px)) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--rail-tracking-tight, -0.02em);
}

.rail-stats__label {
  display: block;
  margin-top: var(--_space-3xs);
  font-size: calc(var(--rail-stats-label-size, 14px) * var(--_type));
  line-height: 1.25;
  color: var(--_muted);
}

.rail-stats :is(a):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * RailEmpty — the placeholder where something will be.
 * ------------------------------------------------------------------------- */

.rail-empty {
  display: flex;
  align-items: center;
  gap: var(--_space-mid);
  flex-wrap: wrap;
  padding: var(--rail-empty-padding, var(--_space-3xl));
  border-radius: var(--_radius);
  /* Dashed, because a solid box reads as a card that failed to fill and a
     bare line of grey text reads as a component that failed to load. Dashed
     says the space is reserved. */
  border: 1px dashed var(--rail-empty-border, var(--_border));
}

.rail-empty__icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  opacity: 0.55;
}

.rail-empty__icon :is(svg, img) {
  width: var(--rail-empty-icon-size, 34px);
  height: var(--rail-empty-icon-size, 34px);
  display: block;
}

.rail-empty__message {
  flex: 1;
  min-width: 12ch;
  margin: 0;
  font-size: calc(var(--rail-empty-size, 16px) * var(--_type));
  color: var(--_muted);
}

/* ---------------------------------------------------------------------------
 * RailList additions: a picture, a note line, a chevron.
 * ------------------------------------------------------------------------- */

.rail-list__image {
  flex-shrink: 0;
  display: block;
  width: var(--rail-list-image-width, 64px);
  aspect-ratio: var(--rail-list-image-aspect, 2 / 3);
  object-fit: cover;
  border-radius: var(--rail-list-image-radius, 6px);
}

.rail-list__note {
  font-size: calc(var(--rail-list-note-size, 14px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  line-height: 1.35;
  color: var(--rail-list-note-color, var(--_accent-text));
}

.rail-list__chevron {
  flex-shrink: 0;
  font-size: calc(var(--rail-size-title, 22px) * var(--_type));
  line-height: 1;
  color: var(--_muted);
}

/* ---------------------------------------------------------------------------
 * RailSegmented — two or three views of one section, in a pill.
 * ------------------------------------------------------------------------- */

.rail-segmented {
  display: inline-flex;
  gap: var(--_space-2xs);
  padding: var(--rail-segmented-inset, var(--_space-2xs));
  border-radius: var(--rail-segmented-radius, var(--_pill));
  background: var(--rail-segmented-bg, color-mix(in srgb, currentColor 8%, transparent));
}

.rail-segmented[data-rail-block] { display: flex; width: 100%; }
.rail-segmented[data-rail-block] .rail-segmented__segment { flex: 1; }

.rail-segmented__segment {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--_space-s);
  min-height: var(--rail-segmented-height, var(--_control-min-sm));
  padding: 0 var(--_space-xl);
  border: 0;
  border-radius: inherit;
  background: transparent;
  color: var(--_muted);
  font-family: inherit;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.rail-segmented__segment[data-active] {
  background: var(--rail-segmented-active-bg, color-mix(in srgb, currentColor 12%, transparent));
  color: var(--rail-segmented-active-color, var(--_accent-text));
}

.rail-segmented__icon { display: grid; place-items: center; }
.rail-segmented__icon :is(svg, img) {
  width: var(--rail-icon-size, 18px);
  height: var(--rail-icon-size, 18px);
  display: block;
}

.rail-segmented :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-segmented__segment { transition: background-color var(--_dur-fast) var(--_ease-soft), color var(--_dur-fast) var(--_ease-soft); }
}

/* ---------------------------------------------------------------------------
 * RailCta — one call to action, standing alone.
 * ------------------------------------------------------------------------- */

.rail-cta {
  display: inline-grid;
  justify-items: center;
  gap: var(--_space-3xs);
  min-height: var(--rail-cta-height, 48px);
  padding: var(--rail-cta-padding, var(--_space-sm) var(--_space-3xl));
  border: 1px solid transparent;
  border-radius: var(--rail-cta-radius, var(--_pill));
  font-family: inherit;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.rail-cta[data-rail-block] { display: grid; width: 100%; }
.rail-cta[data-rail-size="lg"] { min-height: var(--rail-cta-height-lg, 64px); }
/* A stacked CTA carries three registers, so it needs room to breathe. */
.rail-cta[data-rail-stacked] { padding: var(--rail-cta-padding-stacked, var(--_space-md) var(--_space-3xl)); }

.rail-cta[data-rail-variant="primary"] {
  background: var(--rail-cta-bg, var(--_accent));
  color: var(--rail-cta-color, #fff);
  border-color: var(--rail-cta-bg, var(--_accent));
}

.rail-cta[data-rail-variant="secondary"] {
  background: var(--rail-cta-secondary-bg, transparent);
  color: var(--rail-cta-secondary-color, inherit);
  border-color: var(--rail-cta-secondary-border, var(--_border));
}

.rail-cta[data-rail-variant="link"] {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--rail-cta-link-color, var(--_accent-text));
}

.rail-cta[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

.rail-cta__main {
  display: inline-flex;
  align-items: center;
  gap: var(--_space-sm);
  font-size: calc(var(--rail-size-body, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
}

.rail-cta[data-rail-size="lg"] .rail-cta__main {
  font-size: calc(var(--rail-cta-label-size-lg, 24px) * var(--_type));
  letter-spacing: var(--rail-tracking-wide, 0.02em);
}

.rail-cta__eyebrow,
.rail-cta__fineprint {
  font-size: calc(var(--rail-size-micro, 12px) * var(--_type));
  font-weight: var(--rail-weight-medium, 500);
  /* Not muted: on a filled button the "muted" token is tuned for the page, not
     for the accent, and it routinely fails contrast against it. Transparency
     of the button's own text colour cannot. */
  opacity: 0.85;
}

.rail-cta__icon { display: grid; place-items: center; }
.rail-cta__icon :is(svg, img) {
  width: var(--rail-icon-size, 22px);
  height: var(--rail-icon-size, 22px);
  display: block;
}

.rail-cta:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 3px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-cta { transition: filter var(--_dur-fast) var(--_ease-soft), background-color var(--_dur-fast) var(--_ease-soft); }
}

@media (hover: hover) and (pointer: fine) {
  .rail-cta:not([disabled]):hover { filter: brightness(1.08); }
}

/* ---------------------------------------------------------------------------
 * RailDisclosure — a section that folds away.
 * ------------------------------------------------------------------------- */

.rail-disclosure__head {
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
}

.rail-disclosure__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--_space-md);
  flex: 1;
  min-height: var(--_control-min);
  padding: var(--rail-disclosure-padding, var(--_space-sm) 0);
  border: 0;
  background: none;
  color: inherit;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.rail-disclosure[data-rail-tone="header"] .rail-disclosure__summary {
  flex: 1;
  font-family: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-disclosure-summary-size, 22px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
}

/* The footer tone is the full-width row under a card: centred, accent, quiet. */
.rail-disclosure[data-rail-tone="footer"] { border-top: 1px solid var(--_border); }
.rail-disclosure[data-rail-tone="footer"] .rail-disclosure__toggle {
  justify-content: center;
  padding: var(--rail-disclosure-footer-padding, var(--_space-mid) 0);
  color: var(--rail-cta-link-color, var(--_accent-text));
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
}

.rail-disclosure__chevron {
  flex-shrink: 0;
  font-size: calc(var(--rail-size-title, 18px) * var(--_type));
  line-height: 1;
  color: var(--_muted);
}

.rail-disclosure[data-rail-tone="footer"] .rail-disclosure__chevron {
  color: inherit;
  margin-left: var(--_space-s);
}

.rail-disclosure[data-rail-open] .rail-disclosure__chevron { transform: rotate(180deg); }

.rail-disclosure__badge {
  flex-shrink: 0;
  padding: var(--_space-2xs) var(--_space-sm);
  border-radius: var(--rail-disclosure-badge-radius, 6px);
  background: var(--rail-badge-bg, var(--_accent));
  color: var(--rail-badge-color, #fff);
  font-size: calc(var(--rail-size-micro, 12px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
}

.rail-disclosure__toggle:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-disclosure__chevron { transition: transform var(--_dur-base) var(--_ease); }
}

/* ---------------------------------------------------------------------------
 * RailFigures — labelled numbers inside a card.
 * ------------------------------------------------------------------------- */

.rail-figures {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--_space-md);
  margin: 0;
}

.rail-figures__pair { min-width: 0; }

.rail-figures__label {
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  color: var(--_muted);
}

.rail-figures__value {
  margin: var(--_space-3xs) 0 0;
  font-family: var(--rail-stat-font, inherit);
  font-size: calc(var(--rail-figures-size, clamp(24px, 5vw, 32px)) * var(--_type));
  font-weight: var(--rail-weight-regular, 400);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--rail-tracking-tight, -0.02em);
}

.rail-figures[data-rail-size="lg"] .rail-figures__value {
  font-size: calc(var(--rail-figures-size-lg, clamp(30px, 7vw, 44px)) * var(--_type));
}

.rail-figures__value[data-rail-tone="up"] { color: var(--rail-tone-up, #46c266); }
.rail-figures__value[data-rail-tone="down"] { color: var(--rail-tone-down, #e2585f); }

/* ---------------------------------------------------------------------------
 * RailOptions — two-line choices: terms on top, price underneath.
 * ------------------------------------------------------------------------- */

.rail-options {
  display: grid;
  grid-template-columns: repeat(var(--_cols, 3), minmax(0, 1fr));
  gap: var(--rail-options-gap, var(--_space-s));
}

.rail-options__option {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: var(--_space-3xs);
  /* 56 gives two lines of text a comfortable thumb target. */
  min-height: var(--rail-options-height, 56px);
  padding: var(--_space-s) var(--_space-sm);
  border: 1px solid var(--rail-options-border, transparent);
  border-radius: var(--rail-options-radius, var(--_radius));
  background: var(--rail-options-bg, color-mix(in srgb, currentColor 8%, transparent));
  color: inherit;
  font-family: inherit;
  cursor: pointer;
}

.rail-options__option[aria-checked="true"] {
  border-color: var(--rail-options-active-border, var(--_accent));
  background: var(--rail-options-active-bg, color-mix(in srgb, var(--_accent) 16%, transparent));
}

.rail-options__option[disabled] { opacity: 0.45; cursor: not-allowed; }

.rail-options__eyebrow {
  font-size: calc(var(--rail-size-micro, 11px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  letter-spacing: var(--rail-tracking-label, 0.1em);
  text-transform: uppercase;
  color: var(--_muted);
}

.rail-options__line {
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-variant-numeric: tabular-nums;
}

.rail-options__price {
  font-size: calc(var(--rail-size-body, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  font-variant-numeric: tabular-nums;
  color: var(--rail-options-price-color, var(--_accent-text));
}

.rail-options__option:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-options__option { transition: background-color var(--_dur-fast) var(--_ease-soft), border-color var(--_dur-fast) var(--_ease-soft); }
}

/* ---------------------------------------------------------------------------
 * RailPromo — the offer banner.
 * ------------------------------------------------------------------------- */

.rail-promo {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: var(--_radius);
  overflow: hidden;
  background: var(--rail-promo-bg, var(--_bg));
}

.rail-promo__art {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: var(--rail-promo-height, 150px);
  padding: var(--rail-promo-padding, var(--_space-xl));
}

.rail-promo__image,
.rail-promo__art > :is(video, iframe) {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 0;
}

/* The copy sits on artwork that changes per campaign, so OVER ARTWORK it
   brings its own floor rather than trusting whatever image lands behind it.
   With no artwork there is nothing to out-shout, and forcing white here put
   white text on a white panel for any brand whose promo surface is light. */
.rail-promo__copy {
  position: relative;
  z-index: 1;
  max-width: 34ch;
}

.rail-promo__art[data-rail-art] .rail-promo__copy {
  color: var(--rail-promo-color, #fff);
  text-shadow: var(--rail-promo-text-shadow, 0 2px 12px rgba(0, 0, 0, 0.75));
}

.rail-promo__title {
  margin: 0;
  font-family: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-promo-title-size, clamp(20px, 4vw, 28px)) * var(--_type));
  font-weight: var(--rail-weight-heavy, 800);
  line-height: 1.1;
}

.rail-promo__subtitle {
  margin: var(--_space-xs) 0 0;
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  line-height: 1.35;
}

.rail-promo__badge {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  padding: var(--_space-2xs) var(--_space-sm);
  border-radius: var(--rail-promo-badge-radius, 6px);
  background: var(--rail-badge-bg, var(--_accent));
  color: var(--rail-badge-color, #fff);
  font-size: calc(var(--rail-size-micro, 12px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
  text-transform: uppercase;
}

.rail-promo__dismiss {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: grid;
  place-items: center;
  /* 36 is over the 24px AA floor without the control competing with the art. */
  width: var(--rail-promo-dismiss-size, 36px);
  height: var(--rail-promo-dismiss-size, 36px);
  border-radius: var(--_pill);
  border: 0;
  background: var(--rail-promo-dismiss-bg, rgba(0, 0, 0, 0.55));
  color: var(--rail-promo-dismiss-color, #fff);
  font-size: calc(var(--rail-size-title, 18px) * var(--_type));
  line-height: 1;
  cursor: pointer;
}

/* The action is a full-width strip, not a button floating on the picture: a
   button over artwork has to fight whatever is behind it for contrast, and the
   artwork changes per campaign while this component does not. */
.rail-promo__action {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--_space-md);
  min-height: var(--rail-promo-action-height, var(--_control-min));
  padding: var(--_space-sm) var(--rail-promo-padding, var(--_space-xl));
  background: var(--rail-promo-action-bg, var(--_accent));
  color: var(--rail-promo-action-color, #fff);
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
  text-decoration: none;
  text-transform: uppercase;
}

.rail-promo__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-promo :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: -3px;
}

/* ---------------------------------------------------------------------------
 * RailMilestone — progress between two named rungs.
 * ------------------------------------------------------------------------- */

.rail-milestone {
  padding: var(--rail-milestone-padding, var(--_space-mid) var(--_space-lg));
  border-radius: var(--_radius);
  background: var(--rail-milestone-bg, var(--_bg));
}

.rail-milestone__count {
  margin: 0 0 var(--_space-sm);
  text-align: center;
  font-size: calc(var(--rail-milestone-count-size, 18px) * var(--_type));
  font-variant-numeric: tabular-nums;
}

.rail-milestone__value {
  font-weight: var(--rail-weight-bold, 700);
  color: var(--rail-milestone-value-color, var(--_accent-text));
}

.rail-milestone__target { color: var(--_muted); }

.rail-milestone__track-row {
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
}

.rail-milestone__node {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-milestone-node-size, 34px);
  height: var(--rail-milestone-node-size, 34px);
  border-radius: var(--rail-milestone-node-radius, 8px);
  background: var(--rail-milestone-node-bg, color-mix(in srgb, currentColor 14%, transparent));
  color: var(--_muted);
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
}

.rail-milestone__node[data-rail-reached] {
  background: var(--rail-milestone-node-reached-bg, var(--_accent));
  color: var(--rail-milestone-node-reached-color, #fff);
}

.rail-milestone__track {
  flex: 1;
  height: var(--rail-milestone-height, 8px);
  border-radius: var(--_pill);
  overflow: hidden;
  background: var(--rail-milestone-track, color-mix(in srgb, currentColor 18%, transparent));
}

.rail-milestone__fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--rail-milestone-fill, var(--_accent));
}

.rail-milestone__note {
  margin: var(--_space-s) 0 0;
  text-align: center;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

@media (prefers-reduced-motion: no-preference) {
  .rail-milestone__fill { transition: inline-size var(--_dur-slow) var(--_ease); }
}

/* ---------------------------------------------------------------------------
 * Tabs that scroll, and icons on tabs and chips.
 * ------------------------------------------------------------------------- */

.rail-tabs[data-rail-scroll] .rail-tabs__list {
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.rail-tabs[data-rail-scroll] .rail-tabs__list::-webkit-scrollbar { display: none; }
.rail-tabs[data-rail-scroll] .rail-tabs__item { flex: 0 0 auto; }
.rail-tabs[data-rail-scroll] .rail-tabs__tab { padding: var(--_space-md) var(--_space-lg); }

.rail-tabs__icon,
.rail-filters__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.rail-tabs__icon :is(svg, img),
.rail-filters__icon :is(svg, img) {
  width: var(--rail-icon-size, 20px);
  height: var(--rail-icon-size, 20px);
  display: block;
}

.rail-filters__chip { gap: var(--_space-s); }

/* The chip row scrolls, and a chip sliced by the viewport edge is the only
   thing telling anyone. The rail fades its own edge for this; so does this. */
@supports (mask-image: linear-gradient(to right, transparent, black)) {
  .rail-filters__list {
    mask-image: linear-gradient(
      to right,
      black 0,
      black calc(100% - var(--rail-filters-fade, 32px)),
      transparent 100%
    );
    -webkit-mask-image: linear-gradient(
      to right,
      black 0,
      black calc(100% - var(--rail-filters-fade, 32px)),
      transparent 100%
    );
  }
}

/* ---------------------------------------------------------------------------
 * TILE VARIANT — art only, for a library of things you recognise by their
 * cover: games, albums, films. The title lives IN the artwork, so the card
 * draws none, and a badge and an info control sit in the corners.
 * ------------------------------------------------------------------------- */

[data-rail-variant="tile"] .rail-card,
.rail-card[data-rail-variant="tile"] {
  position: relative;
  border: 0;
  border-top: 0;
  border-radius: var(--rail-tile-radius, 14px);
  overflow: hidden;
  background: var(--rail-tile-bg, var(--_bg));
  width: min(var(--rail-tile-size, 170px), 45vw);
}

[data-rail-variant="tile"] .rail-card .rail-card__figure,
.rail-card[data-rail-variant="tile"] .rail-card__figure {
  margin-top: 0;
  order: 0;
  aspect-ratio: var(--rail-tile-aspect, 1 / 1);
}

/* The body is present for a screen reader and gone for a sighted visitor: the
   artwork already carries the name, and repeating it under every tile turns a
   wall of covers into a wall of captions. */
[data-rail-variant="tile"] .rail-card .rail-card__body,
.rail-card[data-rail-variant="tile"] .rail-card__body {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

[data-rail-variant="tile"] .rail-card .rail-card__badge,
.rail-card[data-rail-variant="tile"] .rail-card__badge {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  margin: 0;
  padding: var(--rail-card-tile-badge-padding, calc(var(--_space-xs) / 2) calc(var(--_space-xl) / 2));
  border-radius: var(--rail-tile-badge-radius, 5px);
  background: var(--rail-badge-bg, var(--_accent));
  color: var(--rail-badge-color, #fff);
  font-size: calc(var(--rail-size-micro, 11px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
  text-transform: uppercase;
}

/* ---------------------------------------------------------------------------
 * RailPresence — a measured number of people, shown live.
 * ------------------------------------------------------------------------- */

.rail-presence {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 var(--_space-s);
  margin: 0;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  color: var(--_muted);
}

.rail-presence__glyph {
  align-self: center;
  display: grid;
  place-items: center;
  color: var(--rail-presence-color, var(--_accent-text));
}

.rail-presence__glyph :is(svg, img) {
  width: var(--rail-icon-size, 18px);
  height: var(--rail-icon-size, 18px);
  display: block;
}

.rail-presence__dot {
  display: block;
  width: var(--rail-presence-dot-size, 9px);
  height: var(--rail-presence-dot-size, 9px);
  border-radius: var(--_pill);
  background: currentColor;
}

.rail-presence__count {
  font-weight: var(--rail-weight-bold, 700);
  font-variant-numeric: tabular-nums;
  color: var(--_text);
}

.rail-presence__when { font-size: calc(var(--rail-size-meta, 14px) * var(--_type)); opacity: 0.8; }

/* The pulse is a halo on the dot, not the dot itself: a dot that changes size
   makes the whole line reflow every frame. */
@media (prefers-reduced-motion: no-preference) {
  .rail-presence:not([data-rail-still]) .rail-presence__dot {
    animation: rail-presence-pulse var(--_dur-sweep) ease-out infinite;
  }
}

@keyframes rail-presence-pulse {
  0% { box-shadow: 0 0 0 0 currentColor; opacity: 1; }
  70% { box-shadow: 0 0 0 7px transparent; opacity: 0.75; }
  100% { box-shadow: 0 0 0 0 transparent; opacity: 1; }
}

/* ---------------------------------------------------------------------------
 * RailLive — what is happening right now.
 * ------------------------------------------------------------------------- */

.rail-live {
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  color: var(--_muted);
}

.rail-live__mark {
  flex-shrink: 0;
  font-size: calc(var(--rail-size-label, 12px) * var(--_type));
  line-height: 1;
  color: var(--_muted);
}

.rail-live[data-rail-on] .rail-live__mark {
  color: var(--rail-live-color, var(--rail-tone-down, #e2585f));
}

.rail-live[data-rail-on] .rail-live__status {
  color: var(--rail-live-color, var(--rail-tone-down, #e2585f));
  font-weight: var(--rail-weight-semibold, 600);
}

.rail-live__slot {
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
  min-width: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-live[data-rail-on] .rail-live__mark {
    animation: rail-live-blink var(--_dur-sweep) ease-in-out infinite;
  }
}

@keyframes rail-live-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* ---------------------------------------------------------------------------
 * RailCopy — a value and one press to take it.
 * ------------------------------------------------------------------------- */

.rail-copy {
  display: flex;
  align-items: center;
  gap: var(--_space-s);
  min-width: 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

.rail-copy__label { flex-shrink: 0; }

.rail-copy__value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.rail-copy__button {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  /* 32 is over the 24px AA floor without the control out-weighing the value. */
  width: var(--rail-copy-button-size, 32px);
  height: var(--rail-copy-button-size, 32px);
  border: 0;
  border-radius: var(--rail-copy-button-radius, 6px);
  background: transparent;
  color: inherit;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  line-height: 1;
  cursor: pointer;
}

.rail-copy__button[data-rail-state="done"] { color: var(--rail-tone-up, #46c266); }
.rail-copy__button[data-rail-state="failed"] { color: var(--rail-tone-down, #e2585f); }

.rail-copy__button:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .rail-copy__button:hover {
    background: var(--rail-copy-button-hover-bg, color-mix(in srgb, currentColor 10%, transparent));
  }
}

.rail-copy__sr,
.rail-copy__status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------------------
 * RailTable — a standings table. A real <table>, so a screen reader can say
 * "row 3, Points for, 130.90" instead of nine unlabelled numbers in a line.
 * ------------------------------------------------------------------------- */

.rail-table__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--_space-lg);
  margin-bottom: var(--_space-sm);
}

.rail-table__heading {
  margin: 0;
  font-family: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-heading-size, clamp(24px, 3vw, 34px)) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.1;
}

.rail-table__header-action {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  min-height: var(--_tap-min);
  color: var(--rail-cta-link-color, var(--_accent-text));
  font-size: calc(var(--rail-size-body, 15px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  text-decoration: none;
}

/* A table has a natural minimum width; on a phone it scrolls rather than
   crushing the columns into unreadable stacks. */
.rail-table__scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.rail-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
}

.rail-table :is(th, td) {
  padding: var(--rail-table-cell-padding, var(--_space-md) var(--_space-sm));
  text-align: left;
  vertical-align: middle;
}

.rail-table thead th {
  font-size: calc(var(--rail-size-label, 13px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
  color: var(--_muted);
  border-bottom: 1px solid var(--_border);
  white-space: nowrap;
}

.rail-table tbody tr + tr :is(th, td) {
  border-top: 1px solid var(--rail-table-row-border, color-mix(in srgb, currentColor 8%, transparent));
}

.rail-table [data-rail-numeric] {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rail-table__rank,
.rail-table__rank-head {
  width: 1%;
  padding-right: var(--_space-2xs);
  color: var(--_muted);
  font-variant-numeric: tabular-nums;
}

.rail-table__name {
  font-weight: var(--rail-weight-semibold, 600);
}

.rail-table__name a { color: inherit; text-decoration: none; }

.rail-table__avatar {
  width: var(--rail-table-avatar-size, 30px);
  height: var(--rail-table-avatar-size, 30px);
  border-radius: var(--_pill);
  object-fit: cover;
  vertical-align: middle;
  margin-right: var(--_space-sm);
}

/* The reader's own row. The colour is the quick read; the marker in the
   accessible name is what makes it findable without seeing it. */
.rail-table tbody tr[data-rail-mine] :is(th, td) {
  background: var(--rail-table-mine-bg, color-mix(in srgb, currentColor 7%, transparent));
}

.rail-table__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-table :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * RailPoll — a two-way result, with every number stated.
 * ------------------------------------------------------------------------- */

.rail-poll__heads {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--_space-md);
  margin-bottom: var(--_space-sm);
}

.rail-poll__side { margin: 0; min-width: 0; }
.rail-poll__side[data-rail-side="right"] { text-align: right; }

.rail-poll__name {
  display: block;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.02em);
  text-transform: var(--rail-poll-name-transform, uppercase);
}

.rail-poll__votes,
.rail-poll__total {
  display: block;
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  color: var(--_muted);
  font-variant-numeric: tabular-nums;
}

.rail-poll__total { margin: 0; align-self: center; text-align: center; }

.rail-poll__bar {
  display: flex;
  min-height: var(--rail-poll-height, var(--_control-min-sm));
  border-radius: var(--rail-poll-radius, var(--_pill));
  overflow: hidden;
  background: var(--rail-poll-track, color-mix(in srgb, currentColor 14%, transparent));
}

.rail-poll__fill {
  display: flex;
  align-items: center;
  gap: var(--_space-s);
  min-width: 0;
  padding: 0 var(--_space-mid);
  background: var(--rail-poll-fill, color-mix(in srgb, currentColor 28%, transparent));
  font-size: calc(var(--rail-size-body, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  font-variant-numeric: tabular-nums;
}

.rail-poll__fill:last-child { justify-content: flex-end; }

/* The reader's OWN pick, not the winner: marking the winner would turn a
   majority into a verdict. */
.rail-poll__fill[data-rail-chosen] {
  background: var(--rail-poll-chosen-fill, var(--_accent));
  color: var(--rail-poll-chosen-color, #fff);
}

.rail-poll__pct { white-space: nowrap; }

.rail-poll__empty,
.rail-poll__sr {
  margin: 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

.rail-poll__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
 * RailAd — a paid placement that says so.
 * ------------------------------------------------------------------------- */

.rail-ad {
  display: flex;
  align-items: center;
  gap: var(--_space-s);
  padding: var(--rail-ad-padding, var(--_space-md));
  border: 1px solid var(--_border);
  border-radius: var(--_radius);
  background: var(--rail-ad-bg, transparent);
}

.rail-ad__link {
  display: flex;
  align-items: center;
  gap: var(--_space-mid);
  flex: 1;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.rail-ad__art {
  flex-shrink: 0;
  display: block;
  width: var(--rail-ad-art-size, 62px);
  aspect-ratio: var(--rail-ad-art-aspect, 1 / 1);
  border-radius: var(--rail-ad-art-radius, 8px);
  overflow: hidden;
}

.rail-ad__art > :is(img, video, iframe) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border: 0;
}

.rail-ad__text { min-width: 0; display: flex; flex-direction: column; gap: var(--_space-2xs); }

.rail-ad__title {
  font-size: calc(var(--rail-size-body, 17px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  line-height: 1.25;
}

/* Quiet, but never absent and never smaller than the kit's smallest readable
   step: this is the disclosure, and shrinking it is how sites pretend. */
.rail-ad__disclosure {
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

.rail-ad__menu {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-ad-menu-size, 34px);
  height: var(--rail-ad-menu-size, 34px);
  border: 0;
  border-radius: var(--_pill);
  background: transparent;
  color: var(--_muted);
  font-size: calc(var(--rail-size-title, 20px) * var(--_type));
  line-height: 1;
  cursor: pointer;
}

.rail-ad__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-ad :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * RailPageHeader — the top of a screen that is not the home screen.
 * ------------------------------------------------------------------------- */

.rail-pageheader__row {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  min-height: var(--rail-pageheader-height, 56px);
}

.rail-pageheader__back,
.rail-pageheader__action {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-pageheader-control-size, 44px);
  height: var(--rail-pageheader-control-size, 44px);
  border: 1px solid var(--rail-pageheader-control-border, transparent);
  border-radius: var(--_pill);
  background: var(--rail-pageheader-control-bg, transparent);
  color: inherit;
  font-size: calc(var(--rail-size-title, 20px) * var(--_type));
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}

.rail-pageheader__title {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
  margin: 0;
  font-family: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-pageheader-title-size, clamp(18px, 3vw, 22px)) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.2;
}

.rail-pageheader__mark { flex-shrink: 0; display: grid; place-items: center; }
.rail-pageheader__mark :is(svg, img) {
  width: var(--rail-pageheader-mark-size, 28px);
  height: var(--rail-pageheader-mark-size, 28px);
  display: block;
}

.rail-pageheader__expand {
  display: inline-flex;
  align-items: center;
  gap: var(--_space-s);
  min-width: 0;
  min-height: var(--_tap-min);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.rail-pageheader__chevron { flex-shrink: 0; font-size: calc(var(--rail-size-label, 14px) * var(--_type)); }
.rail-pageheader__expand[aria-expanded="true"] .rail-pageheader__chevron {
  transform: rotate(180deg);
}

.rail-pageheader__actions { display: flex; gap: var(--_space-xs); flex-shrink: 0; }

.rail-pageheader__meta {
  margin: var(--_space-3xs) 0 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

.rail-pageheader__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-pageheader :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-pageheader__chevron { transition: transform var(--_dur-base) var(--_ease); }
}

/* A wrapping chip set: a fixed menu you are meant to see all of. */
.rail-filters[data-rail-wrap] .rail-filters__list {
  flex-wrap: wrap;
  overflow: visible;
  mask-image: none;
  -webkit-mask-image: none;
}

/* ---------------------------------------------------------------------------
 * RailPrice — a price and everything that qualifies it.
 * ------------------------------------------------------------------------- */

.rail-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 var(--_space-s);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.rail-price__prefix,
.rail-price__was,
.rail-price__secondary {
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  color: var(--_muted);
}

.rail-price__now {
  display: inline-flex;
  align-items: baseline;
  color: var(--rail-price-color, inherit);
}

.rail-price__currency {
  font-size: calc(var(--rail-price-currency-size, 0.62em) * var(--_type));
  align-self: flex-start;
  padding-top: 0.22em;
}

/* Pounds big, pence small: the pounds are the decision, the pence the detail. */
.rail-price__whole {
  font-family: var(--rail-stat-font, inherit);
  font-size: calc(var(--rail-price-size, 26px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1;
  letter-spacing: var(--rail-tracking-tight, -0.02em);
}

.rail-price[data-rail-size="lg"] .rail-price__whole {
  font-size: calc(var(--rail-price-size-lg, 38px) * var(--_type));
}

.rail-price__cents {
  font-size: calc(var(--rail-price-cents-size, 0.62em) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
}

.rail-price__unit {
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  font-weight: var(--rail-weight-medium, 500);
  color: var(--_muted);
  margin-left: var(--_space-3xs);
}

.rail-price__off {
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  color: var(--rail-price-off-color, var(--rail-tone-down, #e2585f));
}

.rail-price__secondary { flex-basis: 100%; }

.rail-price__secondary-amount {
  font-weight: var(--rail-weight-bold, 700);
  color: var(--rail-price-secondary-color, var(--rail-tone-down, #e2585f));
}

/* ---------------------------------------------------------------------------
 * RailRating — an average, and the sample it came from.
 * ------------------------------------------------------------------------- */

.rail-rating {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 var(--_space-xs);
  margin: 0;
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  color: var(--_muted);
}

.rail-rating__value {
  font-weight: var(--rail-weight-semibold, 600);
  color: var(--_text);
  font-variant-numeric: tabular-nums;
}

/* One clipped row rather than N glyphs: a half star cannot be spoken. */
.rail-rating__stars {
  position: relative;
  display: inline-block;
  line-height: 1;
  font-size: calc(var(--rail-rating-star-size, 14px) * var(--_type));
  letter-spacing: var(--rail-rating-star-gap, 1px);
  color: var(--rail-rating-track, color-mix(in srgb, currentColor 30%, transparent));
}

.rail-rating__stars-fill {
  position: absolute;
  inset: 0;
  overflow: hidden;
  white-space: nowrap;
  color: var(--rail-rating-color, #f0b429);
}

.rail-rating__stars-track { visibility: visible; }

.rail-rating__count { font-variant-numeric: tabular-nums; }

.rail-rating__meta::before {
  content: "|";
  margin-right: var(--_space-xs);
  opacity: 0.45;
}

.rail-rating__sr,
.rail-byline__sr,
.rail-search__sr,
.rail-coupons__sr,
.rail-toast__sr,
.rail-storyring__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------------------
 * RailByline — who is behind the thing.
 * ------------------------------------------------------------------------- */

.rail-byline {
  display: inline-flex;
  align-items: center;
  gap: var(--_space-s);
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.rail-byline__avatar {
  flex-shrink: 0;
  display: block;
  width: var(--rail-byline-avatar-size, 28px);
  height: var(--rail-byline-avatar-size, 28px);
  border-radius: var(--_pill);
  overflow: hidden;
}

.rail-byline[data-rail-size="sm"] {
  --rail-byline-avatar-size: 22px;
}

.rail-byline__avatar > :is(img, video) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.rail-byline__text { min-width: 0; }

.rail-byline__line {
  display: flex;
  align-items: center;
  gap: var(--_space-xs);
  min-width: 0;
}

.rail-byline__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
}

.rail-byline__tick {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-byline-tick-size, 16px);
  height: var(--rail-byline-tick-size, 16px);
  border-radius: var(--_pill);
  background: var(--rail-byline-tick-bg, var(--_accent));
  color: var(--rail-byline-tick-color, #fff);
  font-size: calc(var(--rail-byline-tick-glyph-size, 10px) * var(--_type));
  line-height: 1;
}

.rail-byline__badge {
  flex-shrink: 0;
  padding: var(--rail-byline-badge-padding, var(--_space-3xs) calc(var(--_space-mid) / 2));
  border-radius: var(--rail-byline-badge-radius, 4px);
  background: var(--rail-byline-badge-bg, color-mix(in srgb, currentColor 14%, transparent));
  font-size: calc(var(--rail-size-micro, 11px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.04em);
  text-transform: uppercase;
}

.rail-byline__meta {
  display: block;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

/* ---------------------------------------------------------------------------
 * RailSearch — a real form, so Enter works and so does no-JS.
 * ------------------------------------------------------------------------- */

.rail-search {
  display: flex;
  align-items: center;
  gap: var(--_space-s);
  padding: var(--rail-search-padding, var(--_space-2xs) var(--_space-2xs) var(--_space-2xs) var(--_space-mid));
  border: 1px solid var(--rail-search-border, var(--_border));
  border-radius: var(--rail-search-radius, var(--_pill));
  background: var(--rail-search-bg, transparent);
}

.rail-search__glyph { flex-shrink: 0; font-size: calc(var(--rail-size-title, 18px) * var(--_type)); opacity: 0.7; }

.rail-search__input {
  flex: 1;
  min-width: 0;
  min-height: var(--rail-search-height, var(--_control-min-sm));
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  outline: none;
}

.rail-search__input::placeholder { color: var(--_muted); }
/* The browser's own clear button, which is not the brand's to restyle. */
.rail-search__input::-webkit-search-cancel-button { filter: invert(0.5); }

.rail-search__trailing {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-search-control-size, 36px);
  height: var(--rail-search-control-size, 36px);
  border: 0;
  border-radius: var(--_pill);
  background: transparent;
  color: inherit;
  font-size: calc(var(--rail-size-title, 18px) * var(--_type));
  cursor: pointer;
}

.rail-search__submit {
  flex-shrink: 0;
  min-height: var(--rail-search-height, var(--_control-min-sm));
  padding: 0 var(--_space-xl);
  border: 0;
  border-radius: var(--rail-search-radius, var(--_pill));
  background: var(--rail-cta-bg, var(--_accent));
  color: var(--rail-cta-color, #fff);
  font: inherit;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  cursor: pointer;
}

.rail-search:focus-within {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * RailCoupons — a book of tickets. The perforation says "separate things you
 * take", not "one block of text with three prices in it".
 * ------------------------------------------------------------------------- */

.rail-coupons {
  display: flex;
  flex-direction: column;
  gap: var(--_space-mid);
  padding: var(--rail-coupons-padding, var(--_space-2xl));
  border-radius: var(--rail-coupons-radius, var(--_radius));
  background: var(--rail-coupons-bg, var(--_bg));
}

.rail-coupons__heading {
  margin: 0;
  font-family: var(--rail-heading-font, inherit);
  font-size: calc(var(--rail-coupons-heading-size, clamp(24px, 5vw, 32px)) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.1;
}

.rail-coupons__sub { margin: var(--_space-2xs) 0 0; font-size: calc(var(--rail-size-body, 16px) * var(--_type)); }

.rail-coupons__list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-radius: var(--rail-coupons-ticket-radius, 12px);
  background: var(--rail-coupons-ticket-bg, #fff);
  color: var(--rail-coupons-ticket-color, #111);
  overflow: hidden;
}

.rail-coupons__coupon { padding: var(--rail-coupons-ticket-padding, var(--_space-xl)); }

/* The perforation. */
.rail-coupons__coupon + .rail-coupons__coupon {
  border-top: 1px dashed var(--rail-coupons-perforation, rgba(0, 0, 0, 0.22));
}

/* Same defect as the offer strip above, same fix: fade the ticket, not its
   words. */
.rail-coupons__coupon[data-rail-claimed] {
  background: var(--rail-coupons-claimed-bg, color-mix(in srgb, currentColor 4%, transparent));
}
.rail-coupons__coupon[data-rail-claimed] .rail-coupons__glyph {
  opacity: var(--rail-coupons-claimed-glyph-opacity, 0.55);
}

.rail-coupons__headline {
  margin: 0;
  font-size: calc(var(--rail-coupons-headline-size, clamp(26px, 6vw, 36px)) * var(--_type));
  font-weight: var(--rail-weight-heavy, 800);
  line-height: 1;
  /* NOT --_accent-text. The ticket paints its own light surface, so the value
     a brand tunes for text on the dark PAGE is wrong here — it measured
     2.76:1 on white. A token is tuned against a background, and this
     component brings its own. */
  color: var(--rail-coupons-headline-color, var(--_accent));
}

.rail-coupons__terms {
  margin: var(--_space-s) 0 0;
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
}

.rail-coupons__explain {
  /* Measured at 15x19 by the brand check. An inline glyph is still a tap
     target, and 24 is the WCAG 2.2 AA floor. */
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  vertical-align: middle;
  margin-left: var(--_space-3xs);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  opacity: 0.6;
  cursor: pointer;
}

.rail-coupons__validity {
  margin: var(--_space-2xs) 0 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  opacity: 0.7;
}

.rail-coupons__action {
  min-height: var(--rail-cta-height, 52px);
  border: 0;
  border-radius: var(--rail-cta-radius, var(--_pill));
  background: var(--rail-cta-bg, var(--_accent));
  color: var(--rail-cta-color, #fff);
  font: inherit;
  font-size: calc(var(--rail-size-body, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  cursor: pointer;
}

.rail-coupons :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * RailToast — tells you something without stopping you. Never takes focus.
 * ------------------------------------------------------------------------- */

.rail-toast {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  padding: var(--rail-toast-padding, var(--_space-md) var(--_space-mid));
  border-top: 1px solid var(--_border);
  background: var(--rail-toast-bg, var(--_bg));
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
}

.rail-toast[data-rail-tone="alert"] {
  border-top-color: var(--rail-tone-down, #e2585f);
}

.rail-toast__glyph { flex-shrink: 0; display: grid; place-items: center; }
.rail-toast__glyph :is(svg, img) {
  width: var(--rail-icon-size, 22px);
  height: var(--rail-icon-size, 22px);
  display: block;
}

.rail-toast__message { flex: 1; min-width: 0; margin: 0; }

.rail-toast__action {
  flex-shrink: 0;
  min-height: var(--_tap-min);
  padding: 0;
  border: 0;
  background: none;
  color: var(--rail-cta-link-color, var(--_accent-text));
  font: inherit;
  font-weight: var(--rail-weight-semibold, 600);
  text-decoration: none;
  cursor: pointer;
}

.rail-toast__dismiss {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-toast-dismiss-size, 32px);
  height: var(--rail-toast-dismiss-size, 32px);
  border: 0;
  border-radius: var(--_pill);
  background: transparent;
  color: var(--_muted);
  font-size: calc(var(--rail-size-title, 20px) * var(--_type));
  line-height: 1;
  cursor: pointer;
}

.rail-toast :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  /* A keyframe, not a class flipped from an effect: an animation runs once on
     mount and never again, which is exactly what that flag was faking. */
  .rail-toast { animation: rail-toast-in var(--_dur-base) var(--_ease-soft) both; }
}

/* ---------------------------------------------------------------------------
 * RailMasonry — a staggered grid. Reading order is DOWN each column.
 * ------------------------------------------------------------------------- */

.rail-masonry {
  column-count: 2;
  column-gap: var(--rail-masonry-gap, var(--_space-md));
}

@media (min-width: 720px) {
  .rail-masonry[data-rail-columns="3"] { column-count: 3; }
  .rail-masonry[data-rail-columns="4"] { column-count: 4; }
}

/* The rule everyone forgets: without it a card is sliced in half across a
   column boundary. */
.rail-masonry > * {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  margin-bottom: var(--rail-masonry-gap, var(--_space-md));
  display: block;
}

/* ---------------------------------------------------------------------------
 * RailStoryRing — a ring that says a word as well as a colour.
 * ------------------------------------------------------------------------- */

.rail-storyring {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--_space-s);
  max-width: var(--rail-storyring-size, 84px);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: none;
  cursor: pointer;
}

.rail-storyring[data-rail-size="sm"] { --rail-storyring-size: 62px; }
.rail-storyring[data-rail-size="lg"] { --rail-storyring-size: 104px; }

.rail-storyring__ring {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--rail-storyring-size, 84px);
  height: var(--rail-storyring-size, 84px);
  padding: var(--rail-storyring-width, 3px);
  border-radius: var(--_pill);
  background: var(--rail-storyring-idle, color-mix(in srgb, currentColor 22%, transparent));
}

.rail-storyring[data-rail-live] .rail-storyring__ring {
  background: var(--rail-storyring-live, var(--_accent));
}

.rail-storyring[data-rail-seen] .rail-storyring__ring { opacity: 0.45; }

.rail-storyring__avatar {
  width: 100%;
  height: 100%;
  border-radius: var(--_pill);
  overflow: hidden;
  background: var(--rail-storyring-avatar-bg, var(--_bg));
  border: var(--rail-storyring-gap, 2px) solid var(--rail-storyring-gap-color, transparent);
}

.rail-storyring__avatar > :is(img, video) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: var(--_pill);
}

.rail-storyring__badge {
  position: absolute;
  top: -2px;
  left: 50%;
  transform: translateX(-50%);
  padding: 1px var(--_space-s);
  border-radius: var(--rail-storyring-badge-radius, 4px);
  background: var(--rail-storyring-live, var(--_accent));
  color: var(--rail-storyring-badge-color, #fff);
  font-size: calc(var(--rail-size-micro, 10px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  letter-spacing: var(--rail-tracking-wide, 0.06em);
  text-transform: uppercase;
}

.rail-storyring__name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: calc(var(--rail-size-meta, 13px) * var(--_type));
}

.rail-storyring:focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 3px;
  border-radius: var(--rail-storyring-focus-radius, var(--_space-md));
}

/* A page-sized empty state looks deliberate rather than like a broken slot. */
.rail-empty[data-rail-tone="page"] {
  flex-direction: column;
  justify-content: center;
  text-align: center;
  gap: var(--_space-xl);
  padding: var(--rail-empty-page-padding, clamp(40px, 12vw, 88px) var(--_space-4xl));
  border: 0;
}

.rail-empty[data-rail-tone="page"] .rail-empty__icon {
  opacity: 0.35;
}

.rail-empty[data-rail-tone="page"] .rail-empty__icon :is(svg, img) {
  width: var(--rail-empty-page-icon-size, 120px);
  height: var(--rail-empty-page-icon-size, 120px);
}

.rail-empty[data-rail-tone="page"] .rail-empty__message {
  flex: none;
  font-size: calc(var(--rail-empty-page-size, clamp(20px, 5vw, 26px)) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  color: var(--_text);
}

/* ---------------------------------------------------------------------------
 * RailCoachmark — the bubble that points at something and explains it.
 * ------------------------------------------------------------------------- */

.rail-coachmark {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--_space-sm);
  max-width: var(--rail-coachmark-width, 34ch);
  padding: var(--rail-coachmark-padding, var(--_space-mid) var(--_space-mid) var(--_space-mid) var(--_space-lg));
  border-radius: var(--rail-coachmark-radius, 10px);
  background: var(--rail-coachmark-bg, #17171a);
  color: var(--rail-coachmark-color, #fff);
  box-shadow: var(--rail-coachmark-shadow, 0 12px 34px -14px rgba(0, 0, 0, 0.7));
}

/* The pointer is a rotated square on the bubble's own background, so it stays
   in step with any colour a brand sets rather than needing its own token. */
.rail-coachmark::before {
  content: "";
  position: absolute;
  width: var(--rail-coachmark-arrow, 12px);
  height: var(--rail-coachmark-arrow, 12px);
  background: inherit;
  transform: rotate(45deg);
}

.rail-coachmark[data-rail-side="top"]::before {
  top: calc(var(--rail-coachmark-arrow, 12px) / -2);
  left: var(--_offset, 16%);
}
.rail-coachmark[data-rail-side="bottom"]::before {
  bottom: calc(var(--rail-coachmark-arrow, 12px) / -2);
  left: var(--_offset, 16%);
}
.rail-coachmark[data-rail-side="left"]::before {
  left: calc(var(--rail-coachmark-arrow, 12px) / -2);
  top: var(--_offset, 16%);
}
.rail-coachmark[data-rail-side="right"]::before {
  right: calc(var(--rail-coachmark-arrow, 12px) / -2);
  top: var(--_offset, 16%);
}

.rail-coachmark__message {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  line-height: 1.35;
}

.rail-coachmark__action {
  flex-shrink: 0;
  min-height: var(--_tap-min);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: var(--rail-weight-bold, 700);
  text-decoration: underline;
  cursor: pointer;
}

.rail-coachmark__dismiss {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  /* 28 keeps the bubble compact while clearing the 24px AA floor. */
  width: var(--rail-coachmark-dismiss-size, 28px);
  height: var(--rail-coachmark-dismiss-size, 28px);
  border: 0;
  border-radius: var(--_pill);
  background: transparent;
  color: inherit;
  font-size: calc(var(--rail-size-title, 20px) * var(--_type));
  line-height: 1;
  cursor: pointer;
}

.rail-coachmark :is(a, button):focus-visible {
  outline: 2px solid var(--rail-coachmark-focus, currentColor);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * RailShortcuts — big marks, small words. You aim at the pizza, not the word.
 * ------------------------------------------------------------------------- */

.rail-shortcuts__list {
  display: flex;
  gap: var(--rail-shortcuts-gap, var(--_space-mid));
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.rail-shortcuts__list::-webkit-scrollbar { display: none; }

.rail-shortcuts[data-rail-wrap] .rail-shortcuts__list {
  flex-wrap: wrap;
  overflow: visible;
  justify-content: center;
}

.rail-shortcuts__item { flex: 0 0 auto; }

.rail-shortcuts__shortcut {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--_space-s);
  width: var(--rail-shortcuts-width, 76px);
  padding: var(--_space-2xs) 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: none;
  cursor: pointer;
}

.rail-shortcuts__glyph {
  display: grid;
  place-items: center;
  width: var(--rail-shortcuts-glyph-box, 56px);
  height: var(--rail-shortcuts-glyph-box, 56px);
  border-radius: var(--rail-shortcuts-glyph-radius, var(--_pill));
  background: var(--rail-shortcuts-glyph-bg, transparent);
  font-size: calc(var(--rail-shortcuts-glyph-size, 40px) * var(--_type));
  line-height: 1;
}

.rail-shortcuts__glyph :is(svg, img) {
  width: var(--rail-shortcuts-glyph-size, 40px);
  height: var(--rail-shortcuts-glyph-size, 40px);
  display: block;
}

/* Never hidden: an emoji has no reliable accessible name across platforms and
   an icon has none at all. */
.rail-shortcuts__label {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  text-align: center;
}

.rail-shortcuts :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 3px;
  border-radius: var(--rail-shortcuts-focus-radius, var(--_space-s));
}

/* ---------------------------------------------------------------------------
 * RailOffer — one offer, with the ticket's notch bitten out of its edge.
 *
 * The notch is two radial gradients in the background, not pseudo-elements:
 * a pseudo-element notch has to be painted in the PAGE's colour to look
 * punched, which means the strip only works on one background. A mask cuts a
 * real hole, so whatever is behind shows through.
 * ------------------------------------------------------------------------- */

.rail-offer {
  --_notch: var(--rail-offer-notch, 11px);
  --_notch-at: var(--rail-offer-notch-at, 76%);
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--_space-mid);
  padding: var(--rail-offer-padding, var(--_space-mid) var(--_space-xl));
  border-radius: var(--rail-offer-radius, 14px);
  background: var(--rail-offer-bg, color-mix(in srgb, var(--_accent) 14%, transparent));
  -webkit-mask:
    radial-gradient(var(--_notch) at var(--_notch-at) 0, transparent 99%, #000 100%) 0 0 / 100% 51% no-repeat,
    radial-gradient(var(--_notch) at var(--_notch-at) 100%, transparent 99%, #000 100%) 0 100% / 100% 51% no-repeat;
  mask:
    radial-gradient(var(--_notch) at var(--_notch-at) 0, transparent 99%, #000 100%) 0 0 / 100% 51% no-repeat,
    radial-gradient(var(--_notch) at var(--_notch-at) 100%, transparent 99%, #000 100%) 0 100% / 100% 51% no-repeat;
}

/* The dotted tear line between the stub and the rest. */
.rail-offer::after {
  content: "";
  position: absolute;
  top: var(--_notch);
  bottom: var(--_notch);
  left: var(--_notch-at);
  border-left: 1px dashed var(--rail-offer-perforation, color-mix(in srgb, currentColor 30%, transparent));
}

/* A claimed offer must read as TAKEN without becoming unreadable.
   `opacity: 0.6` on the whole strip did both: it dimmed the surface and every
   word on it, and the axe gate measured the result at 2.95:1 against 4.5.
   Opacity is the wrong instrument for "quieter" whenever there is text
   underneath it — it cannot tell the difference between a background it is
   fine to fade and a sentence somebody still has to read.
   The surface fades; the words do not. */
.rail-offer[data-rail-claimed] {
  background: var(--rail-offer-claimed-bg, color-mix(in srgb, var(--_accent) 6%, transparent));
}
.rail-offer[data-rail-claimed] .rail-offer__glyph {
  opacity: var(--rail-offer-claimed-glyph-opacity, 0.55);
}

.rail-offer__glyph {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-offer-glyph-box, 44px);
  height: var(--rail-offer-glyph-box, 44px);
  border-radius: var(--rail-offer-glyph-radius, var(--_space-md));
  background: var(--rail-offer-glyph-bg, var(--_accent));
  color: var(--rail-offer-glyph-color, #fff);
  font-size: calc(var(--rail-size-title, 22px) * var(--_type));
  line-height: 1;
}

.rail-offer__glyph :is(svg, img) {
  width: var(--rail-size-title, 22px);
  height: var(--rail-size-title, 22px);
  display: block;
}

.rail-offer__text { flex: 1; min-width: 0; }

.rail-offer__headline {
  margin: 0;
  font-size: calc(var(--rail-size-body, 17px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  line-height: 1.25;
}

.rail-offer__validity {
  display: flex;
  align-items: center;
  gap: var(--_space-3xs);
  margin: var(--_space-3xs) 0 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  /* Its own knob, not --_muted. The offer strip paints a tinted surface, so a
     muted value tuned against the page background can land under 4.5:1 on it
     (axe measured 3.04). A brand must be able to fix the offer without
     lifting muted text everywhere else. */
  color: var(--rail-offer-meta-color, var(--_muted));
}

.rail-offer__explain {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.rail-offer__action {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  min-height: var(--rail-offer-action-height, var(--_control-min-sm));
  padding: 0 var(--_space-xl);
  border: 0;
  border-radius: var(--rail-cta-radius, var(--_pill));
  background: var(--rail-offer-action-bg, var(--rail-cta-bg, var(--_accent)));
  color: var(--rail-offer-action-color, var(--rail-cta-color, #fff));
  font: inherit;
  font-size: calc(var(--rail-size-body, 15px) * var(--_type));
  font-weight: var(--rail-weight-bold, 700);
  text-decoration: none;
  cursor: pointer;
}

.rail-offer__claimed {
  flex-shrink: 0;
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  color: var(--rail-offer-meta-color, var(--_muted));
}

.rail-offer__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.rail-offer :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, var(--_accent));
  outline-offset: 2px;
}

@keyframes rail-toast-in {
  from { transform: translateY(var(--_space-s)); opacity: 0; }
  to { transform: none; opacity: 1; }
}

/* Toast gained a second line. */
.rail-toast__text { flex: 1; min-width: 0; }
.rail-toast__description {
  margin: var(--_space-3xs) 0 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}


/* -------------------------------------------------------------------------
 * RailPrompt — an opt-in ask with two answers the same size.
 *
 * The decline is a real button, not a grey link. Every token below that could
 * be used to shrink or fade it is deliberately absent: there is a knob for the
 * accept's colour and none for making the decline quieter, because the whole
 * argument of this component is that the two are equal.
 * ------------------------------------------------------------------------- */

.rail-prompt {
  display: flex;
  align-items: flex-start;
  gap: var(--_space-md);
  padding: var(--rail-prompt-padding, var(--_space-mid));
  border: 1px solid var(--rail-prompt-border, var(--_border));
  border-radius: var(--rail-prompt-radius, 14px);
  background: var(--rail-prompt-bg, transparent);
  color: var(--_text);
}

.rail-prompt__glyph {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-icon-size, 22px);
  height: var(--rail-icon-size, 22px);
}

.rail-prompt__text { min-width: 0; }

.rail-prompt__heading {
  margin: 0;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
}

.rail-prompt__body {
  margin: var(--_space-3xs) 0 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}

.rail-prompt__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--_space-md);
  margin-top: var(--_space-md);
}

/* Same padding, same font, same min-height. Only the colour differs. */
.rail-prompt__action {
  min-height: var(--_tap-min);
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: var(--rail-weight-semibold, 600);
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  text-decoration: none;
  cursor: pointer;
}

.rail-prompt__action--accept { color: var(--rail-prompt-accept-color, var(--_accent-text)); }
.rail-prompt__action--decline { color: var(--rail-prompt-decline-color, var(--_text)); }

.rail-prompt :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}

/* The extended FAB: a pill that follows its text instead of a fixed disc.
   Height stays put so it lines up with the disc form; only the width moves. */
.rail-fab[data-rail-extended] {
  grid-auto-flow: column;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: var(--rail-fab-size, 68px);
  height: var(--rail-fab-extended-height, 56px);
  padding: 0 var(--rail-fab-extended-padding, 22px);
  gap: var(--_space-xs);
}


/* -------------------------------------------------------------------------
 * RailEmbed — a third-party iframe that does not exist until it is asked for.
 * ------------------------------------------------------------------------- */

.rail-embed__frame {
  display: block;
  width: 100%;
  border: 0;
  border-radius: var(--rail-embed-radius, 12px);
}

.rail-embed__facade {
  display: flex;
  align-items: center;
  gap: var(--_space-mid);
  padding: var(--rail-embed-padding, var(--_space-mid));
  border: 1px solid var(--rail-embed-border, var(--_border));
  border-radius: var(--rail-embed-radius, 12px);
  background: var(--rail-embed-bg, transparent);
  color: var(--_text);
}

.rail-embed__image {
  flex-shrink: 0;
  width: var(--rail-embed-art, 96px);
  height: var(--rail-embed-art, 96px);
  object-fit: cover;
  border-radius: var(--rail-embed-art-radius, 8px);
}

.rail-embed__glyph {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--rail-embed-art, 96px);
  height: var(--rail-embed-art, 96px);
}

.rail-embed__text { min-width: 0; }
.rail-embed__heading {
  margin: 0;
  font-weight: var(--rail-weight-semibold, 600);
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
}
.rail-embed__body {
  margin: var(--_space-3xs) 0 0;
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}
.rail-embed__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--_space-md);
  margin-top: var(--_space-md);
}
.rail-embed__load,
.rail-embed__out {
  min-height: var(--_tap-min);
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: var(--rail-weight-semibold, 600);
  font-size: calc(var(--rail-size-meta, 15px) * var(--_type));
  cursor: pointer;
  text-decoration: none;
}
.rail-embed__load { color: var(--rail-embed-load-color, var(--_accent-text)); }
.rail-embed__out { color: var(--rail-embed-out-color, var(--_text)); }

.rail-embed :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}

/* -------------------------------------------------------------------------
 * RailMerchant — a directory of places, scanned rather than read.
 * ------------------------------------------------------------------------- */

.rail-merchant__heading {
  margin: 0 0 var(--_space-md);
  font-size: calc(var(--rail-heading-size, clamp(22px, 3vw, 30px)) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
}

.rail-merchant__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rail-merchant__row {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  border-bottom: 1px solid var(--rail-merchant-divider, var(--_border));
}
.rail-merchant__row:last-child { border-bottom: 0; }

.rail-merchant__link {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  padding: var(--rail-merchant-padding, var(--_space-md) 0);
  color: inherit;
  text-decoration: none;
}

.rail-merchant__logo {
  flex-shrink: 0;
  width: var(--rail-merchant-logo, 44px);
  height: var(--rail-merchant-logo, 44px);
  border-radius: var(--rail-merchant-logo-radius, 50%);
  object-fit: cover;
  display: grid;
  place-items: center;
}
.rail-merchant__logo--letter {
  background: var(--rail-merchant-logo-bg, color-mix(in srgb, currentColor 12%, transparent));
  font-weight: var(--rail-weight-semibold, 600);
}

.rail-merchant__text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--_space-3xs);
}
.rail-merchant__name { font-weight: var(--rail-weight-semibold, 600); }
.rail-merchant__meta {
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
}
.rail-merchant__offer {
  font-size: calc(var(--rail-size-meta, 13px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  color: var(--rail-merchant-offer-color, var(--_accent-text));
}
.rail-merchant__tags { display: flex; flex-wrap: wrap; gap: var(--_space-3xs); }
.rail-merchant__tag {
  font-size: calc(var(--rail-size-meta, 12px) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
  padding: 1px var(--_space-3xs);
  border: 1px solid var(--rail-merchant-tag-border, var(--_border));
  border-radius: var(--rail-merchant-tag-radius, 4px);
  color: var(--rail-merchant-tag-color, var(--_text));
}
.rail-merchant__unavailable {
  font-size: calc(var(--rail-size-meta, 13px) * var(--_type));
  color: var(--rail-merchant-unavailable-color, var(--_muted));
}

/* The row is quieter, and the TEXT keeps its contrast: the same rule the offer
   strip learned when opacity dimmed a sentence somebody still had to read. */
.rail-merchant__row[data-rail-unavailable] .rail-merchant__logo { opacity: 0.5; }

.rail-merchant__favourite {
  flex-shrink: 0;
  min-width: var(--_tap-min);
  min-height: var(--_tap-min);
  border: 0;
  background: none;
  color: var(--rail-merchant-favourite-color, var(--_text));
  font-size: calc(var(--rail-size-body, 18px) * var(--_type));
  cursor: pointer;
}

.rail-merchant :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}


/* -------------------------------------------------------------------------
 * RailNowPlaying — what is playing, on every screen.
 * ------------------------------------------------------------------------- */

.rail-nowplaying {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--rail-nowplaying-layer, 40);
  background: var(--rail-nowplaying-bg, var(--_bg));
  border-top: 1px solid var(--rail-nowplaying-border, var(--_border));
  color: var(--_text);
}
.rail-nowplaying__row {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  padding: var(--rail-nowplaying-padding, var(--_space-xs) var(--_space-md));
}
.rail-nowplaying__summary {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.rail-nowplaying__art {
  flex-shrink: 0;
  width: var(--rail-nowplaying-art, 44px);
  height: var(--rail-nowplaying-art, 44px);
  border-radius: var(--rail-nowplaying-art-radius, 6px);
  object-fit: cover;
}
.rail-nowplaying__text { min-width: 0; display: flex; flex-direction: column; }
.rail-nowplaying__title {
  font-weight: var(--rail-weight-semibold, 600);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-nowplaying__by { font-weight: 400; color: var(--_muted); }
.rail-nowplaying__device {
  display: flex;
  align-items: center;
  gap: var(--_space-3xs);
  font-size: calc(var(--rail-size-meta, 13px) * var(--_type));
  color: var(--rail-nowplaying-device-color, var(--_accent-text));
}
.rail-nowplaying__controls { display: flex; align-items: center; gap: var(--_space-xs); }
.rail-nowplaying__action,
.rail-nowplaying__transport {
  min-width: var(--_tap-min);
  min-height: var(--_tap-min);
  border: 0;
  background: none;
  color: inherit;
  font-size: calc(var(--rail-size-body, 18px) * var(--_type));
  cursor: pointer;
}
.rail-nowplaying__progress {
  display: flex;
  align-items: center;
  gap: var(--_space-xs);
  padding: 0 var(--_space-md) var(--_space-xs);
}
.rail-nowplaying__progress progress {
  flex: 1;
  height: var(--rail-nowplaying-bar, 3px);
  appearance: none;
  border: 0;
}
.rail-nowplaying__clock {
  font-size: calc(var(--rail-size-meta, 12px) * var(--_type));
  color: var(--_muted);
  font-variant-numeric: tabular-nums;
}
.rail-nowplaying :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}

/* -------------------------------------------------------------------------
 * RailStory — a short sequence with a segmented bar and a mandatory pause.
 * ------------------------------------------------------------------------- */

.rail-story {
  border: 1px solid var(--rail-story-border, var(--_border));
  border-radius: var(--rail-story-radius, 14px);
  background: var(--rail-story-bg, transparent);
  overflow: hidden;
}
.rail-story__chrome {
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  padding: var(--rail-story-padding, var(--_space-md));
}
.rail-story__bars { flex: 1; display: flex; gap: var(--_space-3xs); }
.rail-story__bar {
  flex: 1;
  height: var(--rail-story-bar, 3px);
  appearance: none;
  border: 0;
}
.rail-story__pause,
.rail-story__close {
  min-width: var(--_tap-min);
  min-height: var(--_tap-min);
  border: 0;
  background: none;
  color: inherit;
  font-size: calc(var(--rail-size-body, 16px) * var(--_type));
  cursor: pointer;
}
.rail-story__step { padding: 0 var(--rail-story-padding, var(--_space-md)) var(--rail-story-padding, var(--_space-md)); }
.rail-story :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}

/* -------------------------------------------------------------------------
 * RailTiles — a picture and a name, two across.
 * ------------------------------------------------------------------------- */

.rail-tiles__heading {
  margin: 0 0 var(--_space-md);
  font-size: calc(var(--rail-heading-size, clamp(22px, 3vw, 30px)) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
}
.rail-tiles__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--rail-tiles-gap, var(--_space-xs));
}
.rail-tiles[data-rail-columns="3"] .rail-tiles__grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.rail-tiles__tile {
  display: flex;
  align-items: center;
  gap: var(--_space-xs);
  min-height: var(--rail-tiles-height, 56px);
  border-radius: var(--rail-tiles-radius, 6px);
  background: var(--rail-tiles-bg, color-mix(in srgb, currentColor 8%, transparent));
  color: inherit;
  text-decoration: none;
  overflow: hidden;
}
.rail-tiles__art,
.rail-tiles__glyph {
  flex-shrink: 0;
  width: var(--rail-tiles-art, 56px);
  height: var(--rail-tiles-art, 56px);
  object-fit: cover;
  display: grid;
  place-items: center;
}
.rail-tiles__label {
  min-width: 0;
  padding-right: var(--_space-xs);
  font-weight: var(--rail-weight-semibold, 600);
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.rail-tiles__badge {
  margin-left: auto;
  padding-right: var(--_space-xs);
  color: var(--rail-tiles-badge-color, var(--_accent-text));
}
.rail-tiles a:focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}

/* -------------------------------------------------------------------------
 * RailTrack — many rows of the same kind of thing, where the state is the news.
 * ------------------------------------------------------------------------- */

.rail-track__heading {
  margin: 0 0 var(--_space-md);
  font-size: calc(var(--rail-heading-size, clamp(22px, 3vw, 30px)) * var(--_type));
  font-weight: var(--rail-weight-semibold, 600);
}
.rail-track__list { list-style: none; margin: 0; padding: 0; }
.rail-track__row { display: flex; align-items: center; gap: var(--_space-xs); }
.rail-track__link {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--_space-md);
  padding: var(--rail-track-padding, var(--_space-xs) 0);
  color: inherit;
  text-decoration: none;
}
.rail-track__art {
  flex-shrink: 0;
  width: var(--rail-track-art, 48px);
  height: var(--rail-track-art, 48px);
  border-radius: var(--rail-track-art-radius, 4px);
  object-fit: cover;
}
.rail-track__text { min-width: 0; display: flex; flex-direction: column; }
.rail-track__title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-track__row[data-rail-playing] .rail-track__title {
  color: var(--rail-track-playing-color, var(--_accent-text));
  font-weight: var(--rail-weight-semibold, 600);
}
.rail-track__by {
  display: flex;
  align-items: center;
  gap: var(--_space-3xs);
  font-size: calc(var(--rail-size-meta, 14px) * var(--_type));
  color: var(--_muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-track__mark { color: var(--rail-track-mark-color, var(--_accent-text)); }
.rail-track__saved { color: var(--rail-track-saved-color, var(--_accent-text)); }
.rail-track__menu {
  flex-shrink: 0;
  min-width: var(--_tap-min);
  min-height: var(--_tap-min);
  border: 0;
  background: none;
  color: inherit;
  font-size: calc(var(--rail-size-body, 18px) * var(--_type));
  cursor: pointer;
}
.rail-track :is(a, button):focus-visible {
  outline: 2px solid var(--rail-focus, currentColor);
  outline-offset: 2px;
}


/* ── RailFolder ──────────────────────────────────────────────────────────
   Folders in a drawer. The why is in RailFolder.tsx; this is the drawing.

   Every colour, radius and step comes from a token with a neutral fallback,
   like the rest of the kit: the folder has to look like manila in one brand
   and like a black lacquer box in another without either of them editing
   this file. */
.rail-folder {
  display: block;
  color: var(--_text, currentColor);
}

/* THE TABS OVERLAP THEIR SHEET. A row of tabs sitting ON a panel is what
   makes a drawer read as a drawer instead of as a segmented control, and the
   overlap is the whole trick: the open tab loses its bottom edge and becomes
   one shape with the sheet below it. */
.rail-folder__tabs {
  display: flex;
  align-items: flex-end;
  gap: var(--rail-folder-gap, 3px);
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding: 0 var(--rail-folder-inset, 10px);
  margin-bottom: -1px;
  position: relative;
  z-index: 1;
}
.rail-folder__tabs::-webkit-scrollbar { display: none; }

.rail-folder__tab {
  flex: 0 0 auto;
  display: inline-flex;
  /* LOS ROTULOS COMPARTEN LINEA DE BASE, Y ANTES BAILABAN. El escalon hace la
     pestana mas alta segun su indice -esa es la intencion: se cortan arriba-
     pero con el contenido centrado el TEXTO subia con la caja. Medido en el
     consumidor: cinco pestanas con la linea de base en y=46, 44, 42, 40, 46.
     Una fila de palabras a cinco alturas distintas se lee como desalineacion,
     que es justo lo que el escalon queria evitar.
     Anclado abajo, escalona el canto superior y no el texto. */
  align-items: flex-end;
  padding-bottom: var(--rail-folder-tab-pad-b, 11px);
  gap: var(--_space-s, 8px);
  min-height: var(--rail-folder-tab-height, 40px);
  padding: 0 var(--rail-folder-tab-pad, 15px);
  border: 1px solid var(--_border, currentColor);
  border-bottom-color: transparent;
  border-radius: var(--rail-folder-tab-radius, 9px) var(--rail-folder-tab-radius, 9px) 0 0;
  background: var(--rail-folder-tab-bg, transparent);
  color: inherit;
  font: inherit;
  font-size: var(--rail-folder-tab-size, 13px);
  cursor: pointer;
  /* THE STEP CHANGES THE TAB'S HEIGHT, NOT ITS BOTTOM EDGE, and the first
     version had it backwards. Stepping the bottom margin lifted the inactive
     tabs OFF the sheet: in a drawer they all rest on the same edge — what
     varies is where they are cut at the top, which is how you can read them
     all at once. Lifted instead, the row reads as a misalignment, and that is
     exactly how it looked in review. */
  padding-top: calc(var(--rail-folder-i, 0) * var(--rail-folder-step, 0px));
}
.rail-folder[data-rail-tone="drawer"] .rail-folder__tab {
  --rail-folder-step: 3px;
}
.rail-folder__tab[aria-selected="true"] {
  background: var(--rail-folder-sheet-bg, var(--_card-bg, transparent));
  border-color: var(--_accent, currentColor);
  border-bottom-color: transparent;
  color: var(--_accent-text, inherit);
}
.rail-folder__tab:focus-visible {
  outline: 2px solid var(--_accent, currentColor);
  outline-offset: 2px;
}
.rail-folder__badge {
  font-size: var(--rail-folder-badge-size, 11px);
  opacity: 0.75;
}

/* THE SHEET IS WHAT YOU PULLED OUT. Its top-left corner stays square where
   the tabs sit, so the tab and the sheet look cut from one piece of card. */
.rail-folder__sheet {
  border: 1px solid var(--_border, currentColor);
  border-radius: 0 var(--rail-folder-radius, 12px) var(--rail-folder-radius, 12px)
    var(--rail-folder-radius, 12px);
  background: var(--rail-folder-sheet-bg, var(--_card-bg, transparent));
  padding: var(--rail-folder-pad, 18px);
}
.rail-folder__sheet:focus-visible {
  outline: 2px solid var(--_accent, currentColor);
  outline-offset: -3px;
}

@media (prefers-reduced-motion: no-preference) {
  /* The sheet comes UP, like something lifted out of the drawer, and only a
     few pixels: a folder that slides across the screen is a carousel wearing
     a costume. */
  .rail-folder__sheet {
    animation: rail-folder-sale var(--rail-folder-speed, 0.26s) var(--_ease);
  }
  .rail-folder__tab {
    transition: background var(--rail-folder-speed, 0.26s) ease,
      border-color var(--rail-folder-speed, 0.26s) ease;
  }
}
@keyframes rail-folder-sale {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   RailPlaybill — el cartel que no se puede recortar.

   Dos marcas construyeron esto por separado y las dos chocaron con lo mismo:
   una obra con el titulo y los creditos impresos DENTRO de los pixeles no
   admite recorte. Cambiar `contain` por `cover` quita las bandas laterales y
   se come los creditos; volver a `contain` devuelve los creditos y las bandas.
   Ninguno de los dos es el arreglo.

   El arreglo es dejar de meter la obra en una caja fija: en modo `artwork` la
   imagen manda su propia proporcion, asi que no hay recorte NI bandas. El modo
   `photo` si recorta, anclado arriba, porque en un retrato la cara esta alta y
   lo que sobra esta abajo.
   --------------------------------------------------------------------------- */
.rail-playbill {
  display: flex;
  flex-direction: column;
  gap: var(--rail-playbill-gap, var(--_space-lg));
  background: var(--rail-playbill-bg, transparent);
  border-radius: var(--rail-playbill-radius, var(--rail-card-radius, 16px));
  overflow: hidden;
}

.rail-playbill__media {
  position: relative;
  width: 100%;
  overflow: hidden;
  border-radius: var(--rail-playbill-media-radius, inherit);
}

/* Modo artwork: la imagen impone su alto. Sin aspect-ratio, sin recorte. */
.rail-playbill--artwork .rail-playbill__image {
  display: block;
  width: 100%;
  height: auto;
}

/* Modo photo: caja con proporcion y recorte anclado arriba. */
.rail-playbill--photo .rail-playbill__media {
  aspect-ratio: var(--rail-playbill-aspect, 3 / 4);
}

.rail-playbill--photo .rail-playbill__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* El cuerpo va FUERA de la fotografia: ningun control cae sobre una cara. */
.rail-playbill__body {
  display: flex;
  flex-direction: column;
  gap: var(--rail-playbill-body-gap, var(--_space-sm));
  padding: var(--rail-playbill-padding, 0);
}

.rail-playbill__title {
  margin: 0;
  color: var(--rail-playbill-color, inherit);
  font-size: calc(var(--rail-playbill-title-size, 18px) * var(--_type));
  font-weight: var(--rail-playbill-title-weight, 600);
  line-height: var(--rail-playbill-title-leading, 1.25);
}

.rail-playbill__meta,
.rail-playbill__credit {
  margin: 0;
  color: var(--rail-playbill-muted, var(--_muted));
  font-size: calc(var(--rail-playbill-meta-size, 14px) * var(--_type));
  line-height: var(--rail-playbill-meta-leading, 1.4);
}

.rail-playbill__credit {
  font-size: calc(var(--rail-playbill-credit-size, 12px) * var(--_type));
}

.rail-playbill__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rail-playbill-actions-gap, var(--_space-sm));
  margin-block-start: var(--rail-playbill-actions-offset, var(--_space-xs));
}

/* ---------------------------------------------------------------------------
   RailBrandCard — la marca con su fotografia, y con su procedencia.

   Una foto ilustrativa junto al nombre de una marca se lee como prueba de que
   el trabajo ocurrio. Por eso la procedencia es parte del significado de la
   tarjeta, viene por defecto en el lado prudente (`editorial`) y se imprime
   como palabras visibles, nunca como un title.
   --------------------------------------------------------------------------- */
.rail-brandcard {
  display: flex;
  flex-direction: column;
  gap: var(--rail-brandcard-gap, var(--_space-md));
  color: inherit;
  text-decoration: none;
  background: var(--rail-brandcard-bg, transparent);
  border: var(--rail-brandcard-border, 1px solid var(--_border));
  border-radius: var(--rail-brandcard-radius, var(--rail-card-radius, 16px));
  padding: var(--rail-brandcard-padding, 0);
  overflow: hidden;
}

.rail-brandcard__media {
  width: 100%;
  aspect-ratio: var(--rail-brandcard-aspect, 4 / 3);
  overflow: hidden;
}

.rail-brandcard__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

.rail-brandcard__body {
  display: flex;
  flex-direction: column;
  gap: var(--rail-brandcard-body-gap, var(--_space-xs));
  padding: var(--rail-brandcard-body-padding, var(--_space-lg));
}

.rail-brandcard__category {
  margin: 0;
  /* El acento de una marca se elige para destacar, no para leerse a 12px: en
     el taller daba 3.05:1 sobre el papel oscuro, y AA pide 4.5:1 para texto
     normal. El defecto es el tono apagado, que si esta gestionado; una marca
     puede poner su acento cuando ese acento pase el contraste. */
  color: var(--rail-brandcard-category-color, var(--_muted));
  font-size: calc(var(--rail-brandcard-category-size, 12px) * var(--_type));
  letter-spacing: var(--rail-brandcard-category-tracking, 0.08em);
  text-transform: uppercase;
}

.rail-brandcard__name {
  margin: 0;
  font-size: calc(var(--rail-brandcard-name-size, 18px) * var(--_type));
  font-weight: var(--rail-brandcard-name-weight, 600);
  line-height: var(--rail-brandcard-name-leading, 1.25);
}

.rail-brandcard__phrase {
  margin: 0;
  color: var(--rail-brandcard-muted, var(--_muted));
  font-size: calc(var(--rail-brandcard-phrase-size, 14px) * var(--_type));
  line-height: var(--rail-brandcard-phrase-leading, 1.45);
}

/* La etiqueta de procedencia se LEE. No es un adorno ni un tooltip. */
.rail-brandcard__label,
.rail-brandcard__credit {
  margin: 0;
  color: var(--rail-brandcard-label-color, var(--_muted));
  font-size: calc(var(--rail-brandcard-label-size, 12px) * var(--_type));
  line-height: var(--rail-brandcard-label-leading, 1.4);
}

/* ---------------------------------------------------------------------------
   RailNote — las palabras van ENCIMA de la cara, nunca sobre ella.

   Un rotulo puesto sobre una fotografia acaba cayendo en la cara con algun
   tamano de texto, en algun idioma, en alguna pantalla. Encima del avatar no
   puede, en ninguno. El globo se corta a tres lineas: una nota es un
   pensamiento de paso, y una fila cuyas tarjetas crecen hasta la mas larga
   deja de ser una fila.
   --------------------------------------------------------------------------- */
.rail-note {
  display: flex;
  gap: var(--rail-note-gap, var(--_space-xl));
  margin: 0;
  padding: var(--rail-note-padding, var(--_space-md) var(--_space-lg));
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.rail-note::-webkit-scrollbar { display: none; }

/* El contenedor es flex con align-items:stretch, asi que cada item crece hasta
   el mas alto; dentro, el contenido se ancla abajo. Resultado: los avatares
   caen todos en la misma linea, tenga la nota una linea o tres, y la fila no
   queda dentada. Medido antes de esto: 140.3 / 140.3 / 123.4 / 113.6 px. */
.rail-note__item {
  display: flex;
  flex: 0 0 auto;
  scroll-snap-align: start;
}

.rail-note__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  gap: var(--rail-note-stack-gap, var(--_space-xs));
  width: var(--rail-note-width, calc(var(--_space-4xl) * 2.5));
  color: inherit;
  text-decoration: none;
}

.rail-note__bubble {
  position: relative;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-width: 100%;
  padding: var(--rail-note-bubble-padding, var(--_space-sm) var(--_space-md));
  border-radius: var(--rail-note-bubble-radius, calc(var(--_space-lg) * 1.25));
  background: var(--rail-note-bubble-bg, var(--_bg));
  color: var(--rail-note-bubble-color, inherit);
  font-size: calc(var(--rail-note-bubble-size, 13px) * var(--_type));
  line-height: var(--rail-note-bubble-leading, 1.3);
  text-align: center;
}

/* La cola. Dos circulos, como los globos de mensaje. */
.rail-note__bubble::after,
.rail-note__bubble::before {
  content: "";
  position: absolute;
  left: 50%;
  border-radius: 100%;
  background: inherit;
}

.rail-note__bubble::before {
  bottom: calc(var(--rail-note-tail, 8px) * -1);
  width: var(--rail-note-tail, 8px);
  height: var(--rail-note-tail, 8px);
  transform: translateX(-50%);
}

.rail-note__bubble::after {
  bottom: calc(var(--rail-note-tail, 8px) * -2);
  width: calc(var(--rail-note-tail, 8px) / 2);
  height: calc(var(--rail-note-tail, 8px) / 2);
  transform: translateX(-150%);
}

/* Sin nota, el hueco se reserva: la fila no salta de alto tarjeta a tarjeta. */
.rail-note__bubble--empty {
  background: transparent;
  min-height: var(--rail-note-bubble-min, calc(var(--_space-4xl)));
}

.rail-note__bubble--empty::before,
.rail-note__bubble--empty::after { display: none; }

.rail-note__avatar {
  display: block;
  width: var(--rail-note-avatar, calc(var(--_space-4xl) * 1.75));
  height: var(--rail-note-avatar, calc(var(--_space-4xl) * 1.75));
  border-radius: 100%;
  overflow: hidden;
  background: var(--rail-note-avatar-bg, var(--_bg));
}

.rail-note__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* La cara esta alta en un retrato: lo que sobra se recorta por abajo. */
  object-position: center top;
}

.rail-note__name {
  max-width: 100%;
  overflow: hidden;
  color: var(--rail-note-name-color, var(--_muted));
  font-size: calc(var(--rail-note-name-size, 12px) * var(--_type));
  line-height: var(--rail-note-name-leading, 1.3);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail-note__link--seen .rail-note__avatar {
  opacity: var(--rail-note-seen-opacity, 0.55);
}

/* ---------------------------------------------------------------------------
   RailThreadList — la bandeja.

   La marca de no leido lleva palabra ademas de punto. Un punto de color es el
   estado mas barato y el menos accesible: no existe para un lector de pantalla
   y es ambiguo para quien no separa ese tono del fondo.
   --------------------------------------------------------------------------- */
.rail-threadlist {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail-threadlist__link {
  display: flex;
  align-items: center;
  gap: var(--rail-threadlist-gap, var(--_space-lg));
  padding: var(--rail-threadlist-padding, var(--_space-md) var(--_space-lg));
  color: inherit;
  text-decoration: none;
}

.rail-threadlist__avatar {
  flex: 0 0 auto;
  width: var(--rail-threadlist-avatar, calc(var(--_space-4xl) * 1.5));
  height: var(--rail-threadlist-avatar, calc(var(--_space-4xl) * 1.5));
  border-radius: 100%;
  overflow: hidden;
  background: var(--rail-threadlist-avatar-bg, var(--_bg));
}

.rail-threadlist__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* min-width:0 o el texto no se deja recortar dentro de un flex. */
.rail-threadlist__body {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: var(--rail-threadlist-stack-gap, var(--_space-xs));
}

.rail-threadlist__name {
  overflow: hidden;
  font-size: calc(var(--rail-threadlist-name-size, 15px) * var(--_type));
  font-weight: var(--rail-threadlist-name-weight, 500);
  line-height: var(--rail-threadlist-name-leading, 1.3);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail-threadlist__item--unread .rail-threadlist__name {
  font-weight: var(--rail-threadlist-unread-weight, 700);
}

/* Una linea usa ellipsis; dos o mas necesitan line-clamp, que exige box.
   Con -webkit-line-clamp NO se pone white-space:nowrap: el nowrap gana y la
   segunda linea no llega a existir. */
.rail-threadlist__preview {
  display: -webkit-box;
  -webkit-line-clamp: var(--_borders, 1);
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--rail-threadlist-preview-color, var(--_muted));
  font-size: calc(var(--rail-threadlist-preview-size, 14px) * var(--_type));
  line-height: var(--rail-threadlist-preview-leading, 1.35);
}

.rail-threadlist__sender {
  color: var(--rail-threadlist-sender-color, inherit);
}

.rail-threadlist__receipt {
  margin-inline-end: var(--rail-threadlist-receipt-offset, var(--_space-xs));
}

/* La columna derecha: la hora arriba, las marcas debajo. */
.rail-threadlist__aside {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--rail-threadlist-aside-gap, var(--_space-xs));
  align-self: stretch;
}

.rail-threadlist__time {
  color: var(--rail-threadlist-time-color, var(--_muted));
  font-size: calc(var(--rail-threadlist-time-size, 12px) * var(--_type));
  white-space: nowrap;
}

.rail-threadlist__marks {
  display: inline-flex;
  align-items: center;
  gap: var(--rail-threadlist-marks-gap, var(--_space-xs));
  color: var(--rail-threadlist-marks-color, var(--_muted));
}

.rail-threadlist__muted {
  margin-inline-start: var(--rail-threadlist-muted-offset, var(--_space-xs));
}

.rail-threadlist__unread {
  flex: 0 0 auto;
}

.rail-threadlist__dot {
  display: block;
  width: var(--rail-threadlist-dot, var(--_space-md));
  height: var(--rail-threadlist-dot, var(--_space-md));
  border-radius: 100%;
  background: var(--rail-threadlist-dot-bg, var(--_accent));
}

/* ---------------------------------------------------------------------------
   RailBottomNav --floating — la barra se despega en una pastilla.

   Solo con fondo real: flotar significa que el contenido pasa por debajo, y
   una pastilla transparente pone texto en movimiento bajo los rotulos.
   --------------------------------------------------------------------------- */
.rail-bottomnav--floating {
  right: var(--rail-bottomnav-floating-inset, var(--_space-lg));
  left: var(--rail-bottomnav-floating-inset, var(--_space-lg));
  width: auto;
  margin-block-end: var(--rail-bottomnav-floating-lift, var(--_space-lg));
  border-radius: var(--rail-bottomnav-floating-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-bottomnav-floating-bg, var(--_bg));
  box-shadow: var(--rail-bottomnav-floating-shadow, none);
}

/* ---------------------------------------------------------------------------
   RailFinder — buscar todo el sitio desde cualquier sitio.

   El disparador es una barra pequena o un boton redondo; la hoja es RailSheet,
   asi que Escape cierra, el foco queda dentro mientras esta abierta y vuelve al
   disparador al cerrar. El alto es de la marca: --rail-sheet-height a 100vh
   para un buscador a pantalla completa.
   --------------------------------------------------------------------------- */
.rail-finder__trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--rail-finder-trigger-gap, var(--_space-sm));
  border: var(--rail-finder-trigger-border, 1px solid var(--_border));
  border-radius: var(--rail-finder-trigger-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-finder-trigger-bg, var(--_bg));
  color: var(--rail-finder-trigger-color, inherit);
  cursor: pointer;
  font: inherit;
  font-size: calc(var(--rail-finder-trigger-size, 14px) * var(--_type));
}

.rail-finder__trigger--bar {
  width: 100%;
  padding: var(--rail-finder-trigger-padding, var(--_space-md) var(--_space-lg));
}

/* Redondo, y con lado suficiente para un pulgar: AA pide 24px de objetivo. */
.rail-finder__trigger--icon {
  justify-content: center;
  width: var(--rail-finder-icon-size, calc(var(--_space-4xl) * 1.1));
  height: var(--rail-finder-icon-size, calc(var(--_space-4xl) * 1.1));
  padding: 0;
}

.rail-finder__glyph {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--rail-finder-glyph-color, var(--_muted));
}

.rail-finder__hint {
  overflow: hidden;
  color: var(--rail-finder-hint-color, var(--_muted));
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail-finder {
  display: flex;
  flex-direction: column;
  gap: var(--rail-finder-gap, var(--_space-lg));
  min-height: 0;
}

/* El campo se queda arriba y SOLO la lista se desplaza: si el campo se va con
   el scroll, afinar la busqueda obliga a volver a subir. */
.rail-finder__field {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--rail-finder-field-gap, var(--_space-sm));
  padding: var(--rail-finder-field-padding, var(--_space-md) var(--_space-lg));
  border-radius: var(--rail-finder-field-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-finder-field-bg, var(--_bg));
}

.rail-finder__input {
  width: 100%;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: calc(var(--rail-finder-input-size, 16px) * var(--_type));
  outline: none;
}

.rail-finder__results {
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}

.rail-finder__link {
  display: flex;
  align-items: center;
  gap: var(--rail-finder-thumb-gap, var(--_space-lg));
  padding: var(--rail-finder-result-padding, var(--_space-md) var(--_space-lg));
  border-radius: var(--rail-finder-result-radius, var(--rail-card-radius, 16px));
  color: inherit;
  text-decoration: none;
}

.rail-finder__thumb {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: var(--rail-finder-thumb, calc(var(--_space-4xl) * 1.35));
  height: var(--rail-finder-thumb, calc(var(--_space-4xl) * 1.35));
  border: var(--rail-finder-thumb-border, 1px solid var(--_border));
  border-radius: 100%;
  overflow: hidden;
  color: var(--rail-finder-glyph-color, var(--_muted));
}

.rail-finder__thumb-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* min-width:0 o el texto no se deja recortar dentro de un flex. */
.rail-finder__text {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: var(--rail-finder-result-gap, var(--_space-xs));
}

/* <mark> trae fondo amarillo del navegador. Se apaga y el enfasis pasa al
   peso, que es lo que hace el patron de autocompletar: la parte que coincide
   se distingue sin pintar la fila de otro color. */
.rail-finder__match {
  background: var(--rail-finder-match-bg, transparent);
  color: var(--rail-finder-match-color, inherit);
  font-weight: var(--rail-finder-match-weight, 700);
}

.rail-finder__badge {
  margin-inline-start: var(--rail-finder-badge-offset, var(--_space-xs));
}

.rail-finder__trailing {
  flex: 0 0 auto;
}

/* Cartas: cada resultado es un destino, no una sugerencia. */
.rail-finder__results--cards {
  display: grid;
  gap: var(--rail-finder-cards-gap, var(--_space-lg));
  grid-template-columns: repeat(auto-fill, minmax(var(--rail-finder-card-min, 240px), 1fr));
}

.rail-finder__results--cards .rail-finder__link {
  flex-direction: column;
  align-items: start;
  border: var(--rail-finder-card-border, 1px solid var(--_border));
}

.rail-finder__results--cards .rail-finder__thumb {
  width: 100%;
  height: auto;
  aspect-ratio: var(--rail-finder-card-aspect, 16 / 9);
  border-radius: var(--rail-finder-card-thumb-radius, var(--rail-card-radius, 16px));
}

.rail-finder__section {
  color: var(--rail-finder-section-color, var(--_muted));
  font-size: calc(var(--rail-finder-section-size, 12px) * var(--_type));
  letter-spacing: var(--rail-finder-section-tracking, 0.06em);
  text-transform: uppercase;
}

.rail-finder__title {
  font-size: calc(var(--rail-finder-title-size, 16px) * var(--_type));
  font-weight: var(--rail-finder-title-weight, 600);
  line-height: var(--rail-finder-title-leading, 1.3);
}

.rail-finder__summary {
  color: var(--rail-finder-summary-color, var(--_muted));
  font-size: calc(var(--rail-finder-summary-size, 14px) * var(--_type));
  line-height: var(--rail-finder-summary-leading, 1.4);
}

.rail-finder__empty {
  margin: 0;
  padding: var(--rail-finder-empty-padding, var(--_space-lg));
  color: var(--rail-finder-empty-color, var(--_muted));
  font-size: calc(var(--rail-finder-empty-size, 15px) * var(--_type));
}

.rail-finder__query {
  color: var(--rail-finder-query-color, inherit);
  font-weight: var(--rail-finder-query-weight, 600);
}

/* ---------------------------------------------------------------------------
   RailStatusChip — una cosa con nombre y si esta levantada.
   El punto es color y forma: no existe para un lector de pantalla. Por eso el
   estado viaja siempre en palabra, visible o para el lector.
   --------------------------------------------------------------------------- */
.rail-statuschip {
  display: inline-flex;
  align-items: center;
  gap: var(--rail-statuschip-gap, var(--_space-sm));
  padding: var(--rail-statuschip-padding, var(--_space-md) var(--_space-lg));
  border: var(--rail-statuschip-border, 1px solid var(--_border));
  border-radius: var(--rail-statuschip-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-statuschip-bg, transparent);
  color: inherit;
  font-size: calc(var(--rail-statuschip-size, 14px) * var(--_type));
  text-decoration: none;
}

.rail-statuschip__glyph {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--rail-statuschip-glyph-color, var(--_muted));
}

.rail-statuschip__dot {
  flex: 0 0 auto;
  width: var(--rail-statuschip-dot, var(--_space-sm));
  height: var(--rail-statuschip-dot, var(--_space-sm));
  border-radius: 100%;
  background: var(--rail-statuschip-dot-ok, #3fb950);
}

.rail-statuschip--busy .rail-statuschip__dot { background: var(--rail-statuschip-dot-busy, #d29922); }
.rail-statuschip--warn .rail-statuschip__dot { background: var(--rail-statuschip-dot-warn, #d1242f); }
.rail-statuschip--off .rail-statuschip__dot { background: var(--rail-statuschip-dot-off, #6e7681); }

.rail-statuschip__status {
  color: var(--rail-statuschip-status-color, var(--_muted));
}

.rail-statuschip__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   RailStatusList — el trabajo y lo que esta haciendo cada pieza.
   La marca de delante es un ESTADO, no una cara: se recorre la columna de
   marcas buscando la que te reclama. Por eso cada estado lleva su palabra.
   --------------------------------------------------------------------------- */
.rail-statuslist {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail-statuslist__link {
  display: flex;
  align-items: flex-start;
  gap: var(--rail-statuslist-gap, var(--_space-lg));
  padding: var(--rail-statuslist-padding, var(--_space-lg));
  color: inherit;
  text-decoration: none;
}

.rail-statuslist__mark {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: var(--rail-statuslist-mark, calc(var(--_space-4xl) * 0.9));
  height: var(--rail-statuslist-mark, calc(var(--_space-4xl) * 0.9));
  color: var(--rail-statuslist-mark-color, var(--_muted));
}

.rail-statuslist__item--attention .rail-statuslist__mark {
  color: var(--rail-statuslist-attention-color, var(--_accent));
}

.rail-statuslist__body {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: var(--rail-statuslist-stack-gap, var(--_space-xs));
}

.rail-statuslist__title {
  overflow: hidden;
  font-size: calc(var(--rail-statuslist-title-size, 17px) * var(--_type));
  font-weight: var(--rail-statuslist-title-weight, 500);
  line-height: var(--rail-statuslist-title-leading, 1.3);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail-statuslist__meta {
  overflow: hidden;
  color: var(--rail-statuslist-meta-color, var(--_muted));
  font-size: calc(var(--rail-statuslist-meta-size, 14px) * var(--_type));
  line-height: var(--rail-statuslist-meta-leading, 1.35);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   RailReceipt — que paso con el mensaje que mandaste.
   Un tick y dos ticks se diferencian en unos pixeles, y leido frente a
   entregado suele ser solo un color: ninguna de las dos cosas llega a un lector
   de pantalla ni sobrevive a un daltonismo. Por eso el estado lleva palabra.
   --------------------------------------------------------------------------- */
.rail-receipt {
  display: inline-flex;
  align-items: center;
  color: var(--rail-receipt-color, var(--_muted));
  vertical-align: -0.15em;
}

.rail-receipt--read { color: var(--rail-receipt-read, #53bdeb); }
.rail-receipt--failed { color: var(--rail-receipt-failed, #d1242f); }

/* ---------------------------------------------------------------------------
   RailIntro — la vuelta que se da la primera vez, y solo la primera.

   Panel abajo en el movil, tarjeta centrada en pantalla ancha. No tapa la
   pagina entera a proposito: el paso habla de algo que esta DETRAS, y un
   backdrop opaco esconde justo lo que se esta explicando.
   --------------------------------------------------------------------------- */
.rail-intro {
  position: fixed;
  z-index: var(--rail-intro-layer, 60);
  right: var(--rail-intro-inset, var(--_space-lg));
  bottom: var(--rail-intro-inset, var(--_space-lg));
  left: var(--rail-intro-inset, var(--_space-lg));
  display: flex;
  flex-direction: column;
  gap: var(--rail-intro-gap, var(--_space-md));
  max-height: var(--rail-intro-max-height, 76vh);
  overflow-y: auto;
  padding: var(--rail-intro-padding, var(--_space-xl));
  border: var(--rail-intro-border, 1px solid var(--_border));
  border-radius: var(--rail-intro-radius, calc(var(--_space-xl) * 1.25));
  background: var(--rail-intro-bg, var(--_bg));
  color: var(--rail-intro-color, inherit);
  box-shadow: var(--rail-intro-shadow, none);
  outline: none;
}

@media (min-width: 720px) {
  .rail-intro {
    right: auto;
    left: 50%;
    width: min(var(--rail-intro-width, 420px), 92vw);
    transform: translateX(-50%);
  }
}

.rail-intro__media {
  overflow: hidden;
  border-radius: var(--rail-intro-media-radius, var(--rail-card-radius, 16px));
}

.rail-intro__count {
  margin: 0;
  color: var(--rail-intro-count-color, var(--_muted));
  font-size: calc(var(--rail-intro-count-size, 12px) * var(--_type));
  letter-spacing: var(--rail-intro-count-tracking, 0.06em);
  text-transform: uppercase;
}

.rail-intro__title {
  margin: 0;
  font-size: calc(var(--rail-intro-title-size, 20px) * var(--_type));
  font-weight: var(--rail-intro-title-weight, 600);
  line-height: var(--rail-intro-title-leading, 1.25);
}

.rail-intro__body {
  margin: 0;
  color: var(--rail-intro-body-color, var(--_muted));
  font-size: calc(var(--rail-intro-body-size, 15px) * var(--_type));
  line-height: var(--rail-intro-body-leading, 1.5);
}

.rail-intro__dots {
  display: flex;
  gap: var(--rail-intro-dots-gap, var(--_space-xs));
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail-intro__dot {
  width: var(--rail-intro-dot, var(--_space-sm));
  height: var(--rail-intro-dot, var(--_space-sm));
  border-radius: 100%;
  background: var(--rail-intro-dot-bg, var(--_border));
}

.rail-intro__dot--at {
  background: var(--rail-intro-dot-at, var(--_accent));
}

.rail-intro__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rail-intro-actions-gap, var(--_space-md));
}

.rail-intro__move {
  display: flex;
  gap: var(--rail-intro-move-gap, var(--_space-sm));
}

/* Salir tiene que estar SIEMPRE a la vista, no escondido tras un aspa de 8px:
   quien mas quiere salir es quien ya sabe como funciona esto. */
.rail-intro__skip {
  padding: var(--rail-intro-skip-padding, var(--_space-sm) 0);
  border: 0;
  background: none;
  color: var(--rail-intro-skip-color, var(--_muted));
  cursor: pointer;
  font: inherit;
  font-size: calc(var(--rail-intro-skip-size, 14px) * var(--_type));
  text-decoration: underline;
}

/* El elemento del que habla el paso. Contorno, no relleno: rellenarlo taparia
   justo la cosa que se esta senalando. */
.rail-intro-anchor {
  outline: var(--rail-intro-anchor-outline, 2px solid var(--_accent));
  outline-offset: var(--rail-intro-anchor-offset, 3px);
  border-radius: var(--rail-intro-anchor-radius, var(--rail-card-radius, 16px));
}

/* ---------------------------------------------------------------------------
   RailVoice — decir lo que buscas.

   El microfono late mientras escucha, y late porque es el unico aviso de que
   hay un microfono abierto. Con prefers-reduced-motion el latido para y el
   estado lo lleva el color y el texto: nunca SOLO la animacion.
   --------------------------------------------------------------------------- */
.rail-voice {
  display: flex;
  flex-direction: column;
  gap: var(--rail-voice-gap, var(--_space-md));
}

.rail-voice__mic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: start;
  width: var(--rail-voice-mic, calc(var(--_space-4xl) * 1.35));
  height: var(--rail-voice-mic, calc(var(--_space-4xl) * 1.35));
  padding: 0;
  border: var(--rail-voice-mic-border, 1px solid var(--_border));
  border-radius: 100%;
  background: var(--rail-voice-mic-bg, var(--_bg));
  color: var(--rail-voice-mic-color, inherit);
  cursor: pointer;
}

.rail-voice__mic--on {
  border-color: var(--rail-voice-on-border, var(--_accent));
  background: var(--rail-voice-on-bg, var(--_bg));
  color: var(--rail-voice-on-color, var(--_accent));
  animation: rail-voice-pulse var(--rail-voice-pulse, 1.4s) ease-in-out infinite;
}

@keyframes rail-voice-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--rail-voice-ring, rgba(255, 255, 255, 0.22)); }
  50% { box-shadow: 0 0 0 var(--rail-voice-ring-size, 10px) transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .rail-voice__mic--on { animation: none; }
}

.rail-voice__status {
  margin: 0;
  min-height: var(--rail-voice-status-min, calc(var(--_space-xl) * 1.2));
  color: var(--rail-voice-status-color, var(--_muted));
  font-size: calc(var(--rail-voice-status-size, 15px) * var(--_type));
  line-height: var(--rail-voice-status-leading, 1.4);
}

.rail-voice__empty {
  margin: 0;
  color: var(--rail-voice-empty-color, var(--_muted));
  font-size: calc(var(--rail-voice-empty-size, 14px) * var(--_type));
}

.rail-voice__said {
  color: var(--rail-voice-said-color, inherit);
  font-weight: var(--rail-voice-said-weight, 600);
}

.rail-voice__unsupported {
  margin: 0;
  color: var(--rail-voice-unsupported-color, var(--_muted));
  font-size: calc(var(--rail-voice-unsupported-size, 14px) * var(--_type));
}

.rail-voice__results {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail-voice__link {
  display: flex;
  flex-direction: column;
  gap: var(--rail-voice-result-gap, var(--_space-xs));
  padding: var(--rail-voice-result-padding, var(--_space-md) var(--_space-lg));
  border-radius: var(--rail-voice-result-radius, var(--rail-card-radius, 16px));
  color: inherit;
  text-decoration: none;
}

.rail-voice__section {
  color: var(--rail-voice-section-color, var(--_muted));
  font-size: calc(var(--rail-voice-section-size, 12px) * var(--_type));
  letter-spacing: var(--rail-voice-section-tracking, 0.06em);
  text-transform: uppercase;
}

.rail-voice__title {
  font-size: calc(var(--rail-voice-title-size, 16px) * var(--_type));
  font-weight: var(--rail-voice-title-weight, 600);
  line-height: var(--rail-voice-title-leading, 1.3);
}

/* Glifo junto al titulo de seccion: a la altura del texto, no de la caja. */
.rail__heading-mark {
  display: inline-flex;
  align-items: center;
  margin-inline-end: var(--rail-heading-mark-gap, var(--_space-sm));
  vertical-align: -0.12em;
}

/* Chip de solo icono: un CIRCULO del alto de la fila.
   El lado no se deriva de --_space-4xl. Lo intente y sale una elipse: ese token
   vale 24px, asi que *1.1 daba 26.4 de ancho contra los 40 de alto que tienen
   los chips de texto. Medido en navegador; leyendo el CSS no se ve.
   `aspect-ratio` lo mantiene redondo aunque la marca cambie el alto de la fila,
   y `flex:0 0 auto` impide que encoja y deje de ser un circulo al apretarse la
   fila. 40px supera de sobra los 24 que pide AA como MINIMO de objetivo. */
.rail-filters__chip--icon {
  flex: 0 0 auto;
  justify-content: center;
  width: var(--rail-filters-icon-size, 40px);
  height: var(--rail-filters-icon-size, 40px);
  aspect-ratio: 1;
  padding: 0;
  border-radius: 100%;
}

/* ---------------------------------------------------------------------------
   RailStage / RailScore / RailControls — el suelo de un juego pequeno.
   --------------------------------------------------------------------------- */
.rail-stage {
  display: flex;
  flex-direction: column;
  gap: var(--rail-stage-gap, var(--_space-md));
}

.rail-stage__canvas {
  display: block;
  width: 100%;
  aspect-ratio: var(--rail-stage-aspect, 4 / 3);
  border-radius: var(--rail-stage-radius, var(--rail-card-radius, 16px));
  background: var(--rail-stage-bg, var(--_bg));
  touch-action: none;
}

.rail-stage__panel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rail-stage-panel-gap, var(--_space-md));
}

.rail-score {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rail-score-gap, var(--_space-lg));
  font-size: calc(var(--rail-score-size, 14px) * var(--_type));
}

.rail-score__part {
  display: inline-flex;
  align-items: baseline;
  gap: var(--rail-score-part-gap, var(--_space-xs));
}

.rail-score__label {
  color: var(--rail-score-label-color, var(--_muted));
}

.rail-score__value {
  font-variant-numeric: tabular-nums;
  font-weight: var(--rail-score-value-weight, 600);
}

/* El marcador actual manda sobre lo demas: es lo que se mira de reojo. */
.rail-score__part--now .rail-score__value {
  font-size: calc(var(--rail-score-now-size, 20px) * var(--_type));
}

.rail-score__part--extra .rail-score__value {
  color: var(--rail-score-extra-color, var(--_muted));
  font-weight: var(--rail-score-extra-weight, 500);
}

.rail-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rail-controls-gap, var(--_space-sm));
}

/* 40px de lado, no 24: AA pide 24 como MINIMO, y un control que se toca con el
   pulgar mientras pasa algo en pantalla necesita mas que el minimo. */
.rail-controls__button {
  display: inline-flex;
  align-items: center;
  gap: var(--rail-controls-button-gap, var(--_space-xs));
  min-height: var(--rail-controls-min, 40px);
  padding: var(--rail-controls-padding, var(--_space-sm) var(--_space-lg));
  border: var(--rail-controls-border, 1px solid var(--_border));
  border-radius: var(--rail-controls-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-controls-bg, transparent);
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: calc(var(--rail-controls-size, 14px) * var(--_type));
}

/* El estado "puesto" lo lleva el BORDE y el fondo, no el color del texto.
   Puse --_accent como color de rotulo y axe lo caza: 3.05:1 sobre papel oscuro
   con AA pidiendo 4.5:1 a 14px. Es la SEGUNDA vez hoy que cometo esto mismo
   (la categoria de RailBrandCard fue la primera): el acento de una marca se
   elige para destacar, nunca para leerse pequeno. */
.rail-controls__button[data-pressed] {
  border-color: var(--rail-controls-on-border, var(--_accent));
  background: var(--rail-controls-on-bg, var(--_bg));
  color: var(--rail-controls-on-color, inherit);
  font-weight: var(--rail-controls-on-weight, 600);
}

.rail-controls__button[disabled] {
  cursor: default;
  opacity: var(--rail-controls-off-opacity, 0.5);
}

.rail-controls__glyph {
  display: inline-flex;
}

/* ---------------------------------------------------------------------------
   RailRedeem — el catalogo de canje, leido contra lo que tienes.

   La marca de la izquierda cambia de color, SI, pero el color no lleva solo el
   dato: debajo del precio va la palabra. En la app de la que sale esto, poder
   pagarlo o no se distingue unicamente por el tono de un rombo — misma forma,
   mismo tamano. Eso no llega a un lector de pantalla y es una moneda al aire
   para quien no separa rojo de gris, justo en el unico dato que la pantalla
   existe para dar.
   --------------------------------------------------------------------------- */
.rail-redeem {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail-redeem__link {
  display: flex;
  align-items: center;
  gap: var(--rail-redeem-gap, var(--_space-lg));
  padding: var(--rail-redeem-padding, var(--_space-md) var(--_space-lg));
  color: inherit;
  text-decoration: none;
}

.rail-redeem__mark {
  flex: 0 0 auto;
  width: var(--rail-redeem-mark, var(--_space-md));
  height: var(--rail-redeem-mark, var(--_space-md));
  border-radius: 100%;
  background: var(--rail-redeem-mark-off, var(--_border));
}

.rail-redeem__mark[data-affordable] {
  background: var(--rail-redeem-mark-on, var(--_accent));
}

.rail-redeem__thumb {
  flex: 0 0 auto;
  width: var(--rail-redeem-thumb, calc(var(--_space-4xl) * 2));
  height: var(--rail-redeem-thumb, calc(var(--_space-4xl) * 2));
  border-radius: var(--rail-redeem-thumb-radius, var(--rail-card-radius, 16px));
  overflow: hidden;
  background: var(--rail-redeem-thumb-bg, var(--_bg));
}

.rail-redeem__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* min-width:0 o el nombre largo no se deja recortar dentro de un flex. */
.rail-redeem__text {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: var(--rail-redeem-stack-gap, var(--_space-xs));
}

.rail-redeem__badge {
  align-self: start;
  padding: var(--rail-redeem-badge-padding, 0 var(--_space-sm));
  border-radius: var(--rail-redeem-badge-radius, var(--_space-sm));
  background: var(--rail-redeem-badge-bg, var(--_bg));
  color: var(--rail-redeem-badge-color, var(--_muted));
  font-size: calc(var(--rail-redeem-badge-size, 11px) * var(--_type));
  letter-spacing: var(--rail-redeem-badge-tracking, 0.06em);
  text-transform: uppercase;
}

.rail-redeem__name {
  font-size: calc(var(--rail-redeem-name-size, 16px) * var(--_type));
  font-weight: var(--rail-redeem-name-weight, 600);
  line-height: var(--rail-redeem-name-leading, 1.3);
}

.rail-redeem__cost {
  color: var(--rail-redeem-cost-color, var(--_muted));
  font-size: calc(var(--rail-redeem-cost-size, 14px) * var(--_type));
  font-variant-numeric: tabular-nums;
}

.rail-redeem__status {
  color: var(--rail-redeem-status-color, var(--_muted));
  font-size: calc(var(--rail-redeem-status-size, 13px) * var(--_type));
}

.rail-redeem__status--yes {
  color: var(--rail-redeem-status-on-color, inherit);
  font-weight: var(--rail-redeem-status-on-weight, 600);
}

/* ---------------------------------------------------------------------------
   RailTagPicker — etiquetas que alguien elige sobre si mismo.

   Cada etiqueta es una casilla de verdad dentro de un <fieldset>: asi el
   conjunto se anuncia como "3 de 7 seleccionadas" y no como siete botones
   sueltos, y la barra espaciadora funciona sin que nadie la programe.
   --------------------------------------------------------------------------- */
.rail-tagpicker {
  display: flex;
  flex-direction: column;
  gap: var(--rail-tagpicker-gap, var(--_space-4xl));
}

.rail-tagpicker__group {
  margin: 0;
  padding: 0;
  border: 0;
}

.rail-tagpicker__legend {
  display: flex;
  align-items: center;
  gap: var(--rail-tagpicker-legend-gap, var(--_space-sm));
  padding: 0;
  margin-block-end: var(--rail-tagpicker-legend-space, var(--_space-md));
  color: var(--rail-tagpicker-legend-color, inherit);
  font-size: calc(var(--rail-tagpicker-legend-size, 17px) * var(--_type));
  font-weight: var(--rail-tagpicker-legend-weight, 600);
}

.rail-tagpicker__group--avoid .rail-tagpicker__legend {
  color: var(--rail-tagpicker-avoid-color, inherit);
}

.rail-tagpicker__glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--rail-tagpicker-glyph, calc(var(--_space-4xl) * 1.1));
  height: var(--rail-tagpicker-glyph, calc(var(--_space-4xl) * 1.1));
  border-radius: 100%;
  background: var(--rail-tagpicker-glyph-bg, var(--_bg));
}

.rail-tagpicker__note {
  margin: 0 0 var(--rail-tagpicker-note-space, var(--_space-md));
  color: var(--rail-tagpicker-note-color, var(--_muted));
  font-size: calc(var(--rail-tagpicker-note-size, 14px) * var(--_type));
  line-height: var(--rail-tagpicker-note-leading, 1.4);
}

.rail-tagpicker__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rail-tagpicker-tags-gap, var(--_space-md));
}

/* 40px de alto: AA pide 24 como MINIMO, y estas se tocan con el pulgar. */
.rail-tagpicker__tag {
  display: inline-flex;
  align-items: center;
  min-height: var(--rail-tagpicker-tag-min, 40px);
  padding: var(--rail-tagpicker-tag-padding, var(--_space-sm) var(--_space-xl));
  border: var(--rail-tagpicker-tag-border, 1px solid var(--_border));
  border-radius: var(--rail-tagpicker-tag-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-tagpicker-tag-bg, transparent);
  cursor: pointer;
  font-size: calc(var(--rail-tagpicker-tag-size, 14px) * var(--_type));
}

.rail-tagpicker__tag[data-selected] {
  border-color: var(--rail-tagpicker-on-border, var(--_accent));
  background: var(--rail-tagpicker-on-bg, var(--_bg));
  font-weight: var(--rail-tagpicker-on-weight, 600);
}

/* El anillo de foco va en la ETIQUETA, porque la casilla esta oculta para la
   vista. Sin esto, tabular por el grupo no se ve moverse por ningun sitio. */
.rail-tagpicker__tag:focus-within {
  outline: var(--rail-tagpicker-focus, 2px solid currentColor);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   RailBoosterCard — la carta de coleccion que se da la vuelta.

   El giro vive en __turner, y la inclinacion en __box, que es el que lleva
   data-rail-tilt. Separados a proposito: si el mismo elemento llevara las dos
   transformaciones, inclinarse a mitad de giro las multiplicaria y la carta
   saldria despedida en diagonal.
   --------------------------------------------------------------------------- */
.rail-boostercard {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--rail-boostercard-gap, var(--_space-xl));
  perspective: var(--rail-boostercard-perspective, 1400px);
}

.rail-boostercard__box {
  position: relative;
  width: 100%;
  max-width: var(--rail-boostercard-width, 340px);
  transform-style: preserve-3d;
}

.rail-boostercard__turner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-boostercard__turner {
    transition: transform var(--rail-boostercard-turn, 620ms)
      var(--rail-boostercard-ease, cubic-bezier(.2, .7, .2, 1));
  }
}

.rail-boostercard[data-facing="back"] .rail-boostercard__turner {
  transform: rotateY(180deg);
}

.rail-boostercard__face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* El canto. Sin un borde con color propio, una carta girada de canto
     desaparece: no tiene grosor que ensenar.
     El defecto NO puede ser --_border: mirando la captura, la carta flotaba sin
     forma porque ese tono esta pensado para separar filas, no para dibujar el
     borde de un objeto. Se mezcla con el texto actual, asi que se ve sobre
     papel claro y sobre papel oscuro sin que la marca toque nada. */
  /* Dos escalones a proposito: si el navegador no entiende color-mix, la
     declaracion entera es invalida y la carta se queda SIN canto. La primera
     linea es el suelo que siempre se aplica; la segunda la mejora donde se
     puede. */
  border: var(--rail-boostercard-edge, 1px solid currentColor);
  border-color: var(--rail-boostercard-edge-color,
    color-mix(in srgb, currentColor 38%, transparent));
  border-radius: var(--rail-boostercard-radius, calc(var(--_space-xl) * 1.1));
  background: var(--rail-boostercard-bg, var(--_bg));
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.rail-boostercard__face--back {
  transform: rotateY(180deg);
}

.rail-boostercard__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rail-boostercard-head-gap, var(--_space-md));
  padding: var(--rail-boostercard-head-padding, var(--_space-md) var(--_space-lg));
}

.rail-boostercard__rarity {
  padding: var(--rail-boostercard-rarity-padding, var(--_space-2xs) var(--_space-md));
  border-radius: var(--rail-boostercard-rarity-radius, var(--_space-xs));
  /* Mismo motivo que el canto: con --_border, "INMORTAL" salia como texto suelto
     y no como una chapa. */
  background: var(--rail-boostercard-rarity-bg, var(--_border));
  background: var(--rail-boostercard-rarity-bg,
    color-mix(in srgb, currentColor 16%, transparent));
  color: var(--rail-boostercard-rarity-color, inherit);
  font-size: calc(var(--rail-boostercard-rarity-size, 12px) * var(--_type));
  font-weight: var(--rail-boostercard-rarity-weight, 700);
  letter-spacing: var(--rail-boostercard-rarity-tracking, 0.08em);
  text-transform: uppercase;
}

.rail-boostercard__serial {
  color: var(--rail-boostercard-serial-color, var(--_muted));
  font-size: calc(var(--rail-boostercard-serial-size, 12px) * var(--_type));
  font-variant-numeric: tabular-nums;
}

.rail-boostercard__art {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.rail-boostercard__flip {
  min-height: var(--rail-boostercard-flip-min, 40px);
  padding: var(--rail-boostercard-flip-padding, var(--_space-sm) var(--_space-xl));
  border: var(--rail-boostercard-flip-border, 1px solid var(--_border));
  border-radius: var(--rail-boostercard-flip-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-boostercard-flip-bg, transparent);
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: calc(var(--rail-boostercard-flip-size, 14px) * var(--_type));
}

/* ---------------------------------------------------------------------------
   RailPlayCard — un momento, como tarjeta.

   El numero y las palabras traen la noticia. El tinte, el escudo de detras y el
   confeti son el VOLUMEN, y el volumen se puede bajar a cero sin perder una
   palabra. Esa es la prueba que deberia pasar todo efecto de celebracion.
   --------------------------------------------------------------------------- */
.rail-playcard {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--rail-playcard-gap, var(--_space-lg));
  overflow: hidden;
  padding: var(--rail-playcard-padding, var(--_space-md) var(--_space-lg));
  border-radius: var(--rail-playcard-radius, var(--rail-card-radius, 16px));
  background: var(--rail-playcard-bg, var(--_bg));
  color: var(--rail-playcard-color, inherit);
  text-decoration: none;
}

.rail-playcard__watermark {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  overflow: hidden;
  opacity: var(--rail-playcard-watermark-opacity, 0.16);
  pointer-events: none;
}

.rail-playcard__cutout {
  width: var(--rail-playcard-cutout, calc(var(--_space-4xl) * 2.2));
  height: var(--rail-playcard-cutout, calc(var(--_space-4xl) * 2.2));
  overflow: hidden;
  border-radius: var(--rail-playcard-cutout-radius, var(--_space-md));
}

.rail-playcard__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

.rail-playcard__body {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--rail-playcard-body-gap, var(--_space-3xs));
}

.rail-playcard__line {
  display: flex;
  align-items: baseline;
  gap: var(--rail-playcard-line-gap, var(--_space-xs));
}

.rail-playcard__who {
  font-size: calc(var(--rail-playcard-who-size, 19px) * var(--_type));
  font-weight: var(--rail-playcard-who-weight, 700);
  line-height: var(--rail-playcard-who-leading, 1.15);
}

.rail-playcard__role {
  color: var(--rail-playcard-role-color, var(--_muted));
  font-size: calc(var(--rail-playcard-role-size, 13px) * var(--_type));
  font-weight: var(--rail-playcard-role-weight, 600);
}

.rail-playcard__what {
  font-size: calc(var(--rail-playcard-what-size, 13px) * var(--_type));
  font-weight: var(--rail-playcard-what-weight, 700);
  letter-spacing: var(--rail-playcard-what-tracking, 0.02em);
  text-transform: uppercase;
}

.rail-playcard__score {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--rail-playcard-score-gap, var(--_space-3xs));
}

.rail-playcard__delta {
  font-size: calc(var(--rail-playcard-delta-size, 19px) * var(--_type));
  font-weight: var(--rail-playcard-delta-weight, 700);
  font-variant-numeric: tabular-nums;
}

.rail-playcard__total {
  color: var(--rail-playcard-total-color, var(--_muted));
  font-size: calc(var(--rail-playcard-total-size, 13px) * var(--_type));
  font-variant-numeric: tabular-nums;
}

.rail-playcard__foot {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  gap: var(--rail-playcard-foot-gap, var(--_space-md));
  color: var(--rail-playcard-foot-color, var(--_muted));
  font-size: calc(var(--rail-playcard-foot-size, 13px) * var(--_type));
}

/* El confeti. FINITO y sin pointer-events: cae una vez, no se puede tocar, y
   con motion reducido no existe ni una pieza. */
.rail-confetti {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.rail-confetti__piece {
  position: absolute;
  top: -12%;
  left: var(--_x, 50%);
  width: var(--rail-confetti-piece-w, 6px);
  height: var(--rail-confetti-piece-h, 10px);
  border-radius: 1px;
  background: var(--rail-confetti-piece-bg, currentColor);
  opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .rail-confetti__piece {
    animation: rail-confetti-fall var(--rail-confetti-fall, 1100ms)
      var(--rail-confetti-fall-ease, cubic-bezier(.25, .6, .4, 1)) var(--_delay, 0ms) 1 forwards;
  }
}

/* La CAIDA va en `top`, no en `transform`.
 *
 * Un porcentaje en translate se mide contra la ALTURA DE LA PROPIA PIEZA, no
 * contra la tarjeta: con piezas de 10px, `translateY(320%)` son 32px y el
 * confeti se queda pegado arriba. Medido antes de esto: la pieza bajaba de 58 a
 * 62 px en 450ms, cuatro pixeles, y a simple vista parecia que caia.
 *
 * Un porcentaje en `top` SI se resuelve contra el bloque contenedor, que es lo
 * que aqui significa "de arriba abajo de la tarjeta". El giro y la deriva se
 * quedan en transform, que es barato. */
@keyframes rail-confetti-fall {
  0% { opacity: 0; top: -12%; transform: translate3d(0, 0, 0) rotate(0deg); }
  12% { opacity: 1; }
  100% { opacity: 0; top: 112%; transform: translate3d(var(--_drift, 0), 0, 0) rotate(var(--_spin, 180deg)); }
}

/* ---------------------------------------------------------------------------
   RailReactions — lo que pensó la sala, en marcas con cuenta.
   --------------------------------------------------------------------------- */
.rail-reactions {
  display: flex;
  align-items: center;
  gap: var(--rail-reactions-gap, var(--_space-sm));
}

.rail-reactions__chip,
.rail-reactions__add {
  display: inline-flex;
  align-items: center;
  gap: var(--rail-reactions-chip-gap, var(--_space-xs));
  min-height: var(--rail-reactions-min, 36px);
  padding: var(--rail-reactions-padding, var(--_space-xs) var(--_space-md));
  border: var(--rail-reactions-border, 1px solid var(--_border));
  border-radius: var(--rail-reactions-radius, calc(var(--_space-4xl) * 1.25));
  background: var(--rail-reactions-bg, transparent);
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: calc(var(--rail-reactions-size, 14px) * var(--_type));
}

.rail-reactions__chip[data-mine] {
  border-color: var(--rail-reactions-mine-border, var(--_accent));
  background: var(--rail-reactions-mine-bg, var(--_bg));
  font-weight: var(--rail-reactions-mine-weight, 700);
}

.rail-reactions__add {
  justify-content: center;
  width: var(--rail-reactions-add, 36px);
  padding: 0;
}

.rail-reactions__count {
  font-variant-numeric: tabular-nums;
}

.rail-reactions__more {
  color: var(--rail-reactions-more-color, var(--_muted));
  font-size: calc(var(--rail-reactions-more-size, 13px) * var(--_type));
  white-space: nowrap;
}

/* Letra pequena dentro de una tarjeta de jugada. Se lee: si algo hay que decir
   en pequeno, se dice — no se insinua ni se quita. */
.rail-playcard__detail {
  grid-column: 1 / -1;
  color: var(--rail-playcard-detail-color, var(--_muted));
  font-size: calc(var(--rail-playcard-detail-size, 12px) * var(--_type));
  line-height: var(--rail-playcard-detail-leading, 1.4);
}

/* El pie de la carta de coleccion: fecha, marcador, sello. */
.rail-boostercard__footnote {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rail-boostercard-footnote-gap, var(--_space-md));
  padding: var(--rail-boostercard-footnote-padding, var(--_space-sm) var(--_space-lg));
  color: var(--rail-boostercard-footnote-color, var(--_muted));
  font-size: calc(var(--rail-boostercard-footnote-size, 11px) * var(--_type));
  line-height: var(--rail-boostercard-footnote-leading, 1.35);
}

/* ---------------------------------------------------------------------------
   El acabado holografico.

   Dos fondos y `background-clip`: el de dentro se recorta al padding-box y el
   degradado conico al border-box, asi que el "borde" ES el degradado. Sin
   pseudo-elementos — ::before y ::after ya tienen dueno en este kit.
   --------------------------------------------------------------------------- */
.rail-boostercard--holo .rail-boostercard__face {
  /* La capa de dentro tiene que TAPAR. El fondo por defecto del kit es
     translucido (rgba blanco al 4%), asi que sin esto el conico no se queda en
     el canto: se ve a traves de toda la cara y el contenido acaba sobre un
     arcoiris lavado. Visto en una captura, no leyendo el CSS.
     `--rail-boostercard-paper` es el papel opaco sobre el que se compone; una
     marca lo pone en su color y el conico vuelve a ser solo borde. */
  background-color: var(--rail-boostercard-paper, #0b0b0c);
  border-color: transparent;
  background-image:
    linear-gradient(var(--rail-boostercard-paper, #0b0b0c), var(--rail-boostercard-paper, #0b0b0c)),
    var(--rail-boostercard-holo,
      conic-gradient(from var(--rail-boostercard-holo-turn, 210deg),
        #9ad8ff, #c9a7ff, #ffd6a5, #a7ffd8, #9ad8ff));
  background-origin: border-box;
  background-clip: padding-box, border-box;
  border-width: var(--rail-boostercard-holo-width, 2px);
  border-style: solid;
}


/* =====================================================   RailPack — el sobre sin abrir, y el mazo que sale de el.

   Distinto de RailBoosterCard, que es UNA carta con dos caras que gira. Esto es
   lo de antes: el sobre CERRADO que eliges, que viaja al centro de la pantalla,
   se rasga, y reparte una PILA de cartas que se pasan una a una.

   Nace de gonzaloaguilar.tech, donde se construyo a mano y se corrigio contra
   un telefono de verdad. Lo que se aprendio alli y por lo que vive aqui:

   - EL NOMBRE VA EN UNA PLACA, no sobre el metal. Un degradado metalico barre
     del claro al oscuro y ninguna tinta aguanta todas sus paradas: seis de
     nueve metales dejaban el nombre por debajo de 4,5:1. Con la placa el par
     de colores es uno solo y deja de depender del metal.
   - LA ILUSTRACION VA EN MEDIO, anclada al 42% del alto y centrada sobre si
     misma. Pegada abajo se solapaba con la placa en cuanto el nombre crecia.
   - LA PISTA DE ABRIR ES UNA PASTILLA, no mas texto del mismo tamano. Subirle
     el cuerpo de 11 a 13 la IGUALO al nombre en vez de distinguirla.
   - EL SOBRE ELEGIDO SALE DEL ARBOL para crecer. Dentro de un carril con
     overflow se le cortaban 48px, y ni position:fixed ni un z-index alto lo
     arreglan cuando un ancestro crea contexto de apilamiento.

   Todo el color entra por variables: el kit no sabe de que marca es.
   ============================================================ */
.rail-pack {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  min-height: var(--rail-pack-min-height, 320px);
  padding: var(--rail-pack-padding, var(--_space-xl) var(--_space-sm) var(--_space-md));
  border: 1px solid var(--rail-pack-edge, currentColor);
  border-radius: var(--rail-pack-radius, var(--_space-xs));
  background: var(--rail-pack-bg, var(--_paper, #fff));
  color: var(--rail-pack-ink, var(--_ink, #111));
  box-shadow: var(--rail-pack-shadow, 0 12px 20px rgb(0 0 0 / 13%));
  cursor: pointer;
  touch-action: manipulation;
  overflow: hidden;
}

/* La ilustracion del tema, en la mitad del sobre. */
.rail-pack__art {
  position: absolute;
  left: 50%;
  top: var(--rail-pack-art-top, 42%);
  transform: translate(-50%, -50%);
  width: var(--rail-pack-art-size, 84px);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid currentColor;
  border-radius: 50%;
  opacity: 0.55;
}

.rail-pack__art > svg {
  display: block;
  width: 76%;
  height: 76%;
  overflow: visible;
}

/* LA PLACA DEL NOMBRE. Un par de colores fijo, no el del metal. */
.rail-pack__name {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--rail-pack-name-gap, var(--_space-2xs));
  min-height: var(--rail-pack-name-min, 66px);
  padding: var(--rail-pack-name-padding, var(--_space-sm) var(--_space-2xs) var(--_space-lg));
  background: var(--rail-pack-name-bg, rgb(9 15 27 / 58%));
  color: var(--rail-pack-name-ink, #fff);
  backdrop-filter: blur(16px) saturate(150%);
  text-align: center;
}

.rail-pack__hint {
  display: inline-flex;
  align-items: center;
  gap: var(--rail-pack-hint-gap, var(--_space-2xs));
  padding: var(--rail-pack-hint-padding, var(--_space-3xs) var(--_space-sm));
  border-radius: var(--rail-pack-hint-radius, 999px);
  background: var(--rail-pack-hint-bg, #fff);
  color: var(--rail-pack-hint-ink, #0c1421);
  font: 800 var(--rail-pack-hint-size, 13.5px) / 1 inherit;
}

.rail-pack__seal {
  position: absolute;
  left: var(--_space-sm);
  top: var(--_space-sm);
  opacity: 0.6;
  font: 700 var(--rail-pack-seal-size, 12px) / 1 inherit;
}

.rail-pack__foil {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* EL MAZO. Las cartas salen apiladas, no en lista: cada una es una sorpresa. */
.rail-deck {
  position: relative;
  min-height: var(--rail-deck-min-height, 320px);
}

.rail-deck__card {
  position: absolute;
  inset: 0;
  transform: translateY(calc(var(--d, 0) * var(--rail-deck-step, 10px)))
             scale(calc(1 - var(--d, 0) * 0.04));
  /* La duracion sale del token de movimiento del kit, asi que una marca que
     baja su ritmo -o lo apaga- lo baja tambien aqui sin tocar esta regla. */
  transition: transform var(--_dur-base) var(--rail-deck-ease, cubic-bezier(0.2, 0.8, 0.25, 1)),
              opacity var(--_dur-base);
}

/* Solo la de arriba se lee y se toca: si un lector de pantalla leyera las de
   debajo, contaria la sorpresa antes de tiempo. */
.rail-deck__card[aria-hidden="true"] {
  pointer-events: none;
}

.rail-deck__card--gone {
  opacity: 0;
}

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

/* ---------------------------------------------------------------------------
   RailCoverflow — la fila en perspectiva.

   Lo elegido de frente; lo demas gira hacia dentro y se aleja. El reflejo es un
   duplicado volteado con un desvanecido: no es un filtro, porque `filter` sobre
   una escena 3D fuerza un contexto de apilamiento nuevo y aplasta la
   perspectiva de los hijos.
   --------------------------------------------------------------------------- */
.rail-coverflow {
  --_step: var(--rail-coverflow-step, 62%);
  --_turn: var(--rail-coverflow-turn, 48deg);
  --_depth: var(--rail-coverflow-depth, 120px);
  position: relative;
  overflow: hidden;
  padding: var(--rail-coverflow-padding, var(--_space-xl) 0);
  perspective: var(--rail-coverflow-perspective, 1100px);
  outline: none;
}

.rail-coverflow__stage {
  position: relative;
  display: grid;
  place-items: center;
  height: var(--rail-coverflow-height, 300px);
  transform-style: preserve-3d;
}

.rail-coverflow__slot {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  transform-style: preserve-3d;
  /* Lo del centro va delante; lo de los lados, detras y en ese orden. */
  z-index: calc(10 - max(var(--_i, 0), calc(var(--_i, 0) * -1)));
}

@media (prefers-reduced-motion: no-preference) {
  .rail-coverflow__slot {
    transform:
      translateX(calc(var(--_i, 0) * var(--_step)))
      translateZ(calc(max(var(--_i, 0), calc(var(--_i, 0) * -1)) * var(--_depth) * -1))
      rotateY(calc(var(--_i, 0) * var(--_turn) * -1));
    transition: transform var(--rail-coverflow-glide, 420ms) var(--_ease-out, ease-out);
  }
}

/* Motion reducido: fila plana que se desliza. Una perspectiva congelada es un
   monton de rectangulos torcidos, y el sentido —"hay mas a los lados"— se
   pierde justo para quien pidio menos movimiento. */
.rail-coverflow--still .rail-coverflow__slot {
  transform: translateX(calc(var(--_i, 0) * var(--rail-coverflow-step-flat, 104%)));
}

.rail-coverflow__piece {
  display: block;
  cursor: pointer;
  /* Sin esto, una pieza que pasa de 90 grados ensena su REVERSO: el mismo
     dibujo con el texto al reves. Se vio en una captura — "Ambicion" escrito
     de derecha a izquierda en el sobre del extremo. Un carrusel no tiene
     dorso que ensenar, asi que se oculta. */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.rail-coverflow__art {
  display: block;
  width: var(--rail-coverflow-width, 180px);
}

.rail-coverflow__art > * {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--rail-coverflow-radius, var(--_space-md));
}

/* El reflejo: el mismo dibujo volteado, desvanecido hacia abajo. */
.rail-coverflow__mirror {
  display: block;
  width: var(--rail-coverflow-width, 180px);
  margin-block-start: var(--rail-coverflow-mirror-gap, var(--_space-xs));
  opacity: var(--rail-coverflow-mirror-opacity, 0.28);
  transform: scaleY(-1);
  -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 72%);
  mask-image: linear-gradient(to top, transparent 0%, #000 72%);
  pointer-events: none;
}

.rail-coverflow__mirror > * {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--rail-coverflow-radius, var(--_space-md));
}

.rail-coverflow__slot[data-current] .rail-coverflow__piece:focus-visible,
.rail-coverflow:focus-visible {
  outline: var(--rail-coverflow-focus, 2px solid currentColor);
  outline-offset: 3px;
}


/* ---------------------------------------------------------------------------
   El FOIL. El canto holografico dice "coleccionable"; el foil es lo que hace
   que una carta parezca una carta de verdad cuando la mueves.

   La referencia es un sobre de Pokemon: una lamina iridiscente que barre la
   cara y CAMBIA con el angulo. Por eso no es un degradado fijo — un degradado
   fijo se ve una vez y deja de existir. Sigue a `--hx`/`--hy`, que el sitio
   consumidor pone con el puntero o con la inclinacion del telefono.

   Va en un elemento REAL y no en ::before/::after, porque en este kit esos dos
   ya tienen dueno. Y se apaga entero con reduce: una lamina que persigue el
   dedo es movimiento, no decoracion.
   --------------------------------------------------------------------------- */
.rail-boostercard__foil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  border-radius: inherit;
  opacity: var(--rail-boostercard-foil-opacity, 0.55);
  mix-blend-mode: var(--rail-boostercard-foil-blend, color-dodge);
  background:
    /* El brillo que sigue al dedo. */
    radial-gradient(
      circle at var(--hx, 50%) var(--hy, 50%),
      rgb(255 255 255 / 55%) 0%,
      rgb(255 255 255 / 10%) 24%,
      transparent 52%
    ),
    /* La iridiscencia: el arcoiris se desplaza con el dedo, asi que dos
       posiciones distintas del puntero dan dos cartas distintas. El angulo lo
       pone el consumidor en `--rail-boostercard-foil-turn`; aqui no se calcula
       a partir de `--hx` porque un porcentaje no se convierte en grados en CSS,
       y una variable que nadie puede poner es configuracion muerta. */
    linear-gradient(
      var(--rail-boostercard-foil-turn, 104deg),
      transparent 14%,
      rgb(154 216 255 / 45%) 26%,
      rgb(201 167 255 / 45%) 38%,
      rgb(255 214 165 / 45%) 50%,
      rgb(167 255 216 / 45%) 62%,
      transparent 78%
    );
}

/* La trama fina que hace que el foil parezca impreso y no pintado. Sin ella la
   lamina se ve como un filtro de color; con ella, como una superficie. */
.rail-boostercard__foil::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  opacity: var(--rail-boostercard-foil-grain, 0.4);
  background-image: repeating-linear-gradient(
    115deg,
    rgb(255 255 255 / 12%) 0 1px,
    transparent 1px 4px
  );
}

@media (prefers-reduced-motion: reduce) {
  .rail-boostercard__foil {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
   RailSparkle — los destellos de lo raro.

   Cada brillo son DOS barras cruzadas, no una imagen: una estrella de cuatro
   puntas dibujada con pseudo-elementos pesa cero bytes y hereda el color, asi
   que una marca la tine sin sustituir ningun asset.

   `::before` y `::after` estan libres AQUI porque este elemento es propio del
   efecto y no lo comparte con nadie — que es justo lo que no pasaba con el
   canto del vidrio y el spotlight.
   --------------------------------------------------------------------------- */
.rail-sparkle {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.rail-sparkle__glint {
  position: absolute;
  left: var(--_x, 50%);
  top: var(--_y, 50%);
  width: var(--_size, 14px);
  height: var(--_size, 14px);
  margin: calc(var(--_size, 14px) / -2);
  color: var(--rail-sparkle-color, currentColor);
  opacity: 0;
  /* Un halo propio alrededor de cada punta.
     Sin esto, un destello claro sobre una carta clara no existe: la primera
     version se pinto en blanco sobre un degradado calido y en la captura no se
     distinguia del fondo. El bloom le da borde contra cualquier superficie, y
     va en `filter` sobre un span aislado —sin hijos en 3D— asi que el contexto
     de apilamiento que crea no aplasta ninguna perspectiva. */
  filter: drop-shadow(0 0 var(--rail-sparkle-bloom, 3px)
    var(--rail-sparkle-bloom-color, rgb(255 255 255 / 85%)));
}

.rail-sparkle__glint::before,
.rail-sparkle__glint::after {
  content: "";
  position: absolute;
  inset: 0;
  background: currentColor;
  /* La forma de estrella: una barra fina que se afila en las puntas. */
  clip-path: polygon(50% 0%, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0% 50%, 42% 42%);
}

.rail-sparkle__glint::after {
  transform: rotate(45deg) scale(var(--rail-sparkle-cross, 0.62));
}

@media (prefers-reduced-motion: no-preference) {
  .rail-sparkle__glint {
    animation: rail-sparkle-pop var(--rail-sparkle-life, 900ms)
      var(--rail-sparkle-ease, ease-out) var(--_delay, 0ms) 1 forwards;
  }

  .rail-sparkle--loop .rail-sparkle__glint {
    animation-iteration-count: infinite;
    animation-duration: var(--rail-sparkle-loop-life, 2.4s);
  }
}

@keyframes rail-sparkle-pop {
  0% { opacity: 0; transform: scale(0.2) rotate(0deg); }
  30% { opacity: 1; transform: scale(1) rotate(28deg); }
  100% { opacity: 0; transform: scale(0.35) rotate(56deg); }
}

/* El envoltorio del mazo: la pila, la cuenta y el boton de repartir. El #37
   dejo `.rail-deck` (la pila) pero no la caja que la sostiene. */
.rail-drawpile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--rail-drawpile-gap, var(--_space-lg));
}

.rail-drawpile__count {
  margin: 0;
  min-height: var(--rail-drawpile-count-min, var(--_space-xl));
  color: var(--rail-drawpile-count-color, var(--_muted));
  font-size: calc(var(--rail-drawpile-count-size, 14px) * var(--_type));
}

/* ---------------------------------------------------------------------------
   RailDrawPile — la pila de la que sale una carta cada vez.

   Nace de un choque de nombres: `RailDeck` ya existia en una rama sin mergear
   —un mazo de TRIAJE, con "me interesa" y "paso"— y es de un dia antes, ademas
   de ser dueno de todo el espacio .rail-deck__*. Dos mecanicas distintas no
   pueden compartir prefijo: la primera clase que coincidiera se pintaria con
   las reglas de la otra.
   --------------------------------------------------------------------------- */
.rail-drawpile__stack {
  position: relative;
  min-height: var(--rail-drawpile-min-height, 320px);
}

.rail-drawpile__card {
  position: absolute;
  inset: 0;
  transform: translateY(calc(var(--d, 0) * var(--rail-drawpile-step, 10px)))
             scale(calc(1 - var(--d, 0) * 0.04));
  transition: transform var(--_dur-base) var(--rail-drawpile-ease, cubic-bezier(0.2, 0.8, 0.25, 1)),
              opacity var(--_dur-base);
}

.rail-drawpile__card[aria-hidden="true"] {
  pointer-events: none;
}

.rail-drawpile__card--gone {
  opacity: 0;
}

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

/* ---------------------------------------------------------------------------
 * TURNTABLE — the sensory object on a magazine-format site.
 *
 * Promoted from the Christian Castiblanco build. The rotation and the arm
 * travel live in motion.css and only run when the root carries data-spinning,
 * which the component sets from the audio element's own events.
 */
.rail-turntable {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--_gap);
  align-items: center;
  color: var(--_text);
}
.rail-turntable__deck {
  position: relative;
  display: grid;
  justify-items: center;
  gap: var(--_gap);
  aspect-ratio: 1;
  padding: var(--_space-md);
  background: var(--rail-turntable-deck, rgba(255, 255, 255, 0.05));
  border-radius: var(--_radius);
  overflow: hidden;
}
.rail-turntable__record {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  max-width: var(--rail-turntable-size, 440px);
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--rail-turntable-vinyl, #111);
  cursor: pointer;
}
.rail-turntable__grooves {
  position: absolute;
  inset: 4%;
  border-radius: 50%;
  background: repeating-radial-gradient(circle,
    var(--rail-turntable-groove-dark, #131313) 0 2px,
    var(--rail-turntable-groove-light, #373737) 3px,
    var(--rail-turntable-groove-dark, #131313) 4px 5px);
  border: 1px solid var(--rail-turntable-groove-edge, #333);
}
.rail-turntable__label {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 35%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--rail-turntable-label-bg, #a43c2e);
  color: var(--rail-turntable-label-ink, #fff);
  text-align: center;
}
.rail-turntable__label b { font-size: var(--rail-turntable-mark, 3rem); line-height: 1; }
.rail-turntable__label small { font-size: var(--_text-xs); margin-top: .4em; }
.rail-turntable__label i {
  position: absolute;
  top: 49%; left: 49%;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--rail-turntable-spindle, #c9c5bb);
}
.rail-turntable__arm {
  position: absolute;
  top: 8%; right: 10%;
  width: 34%; height: 6px;
  padding: 0;
  border: 0;
  background: var(--rail-turntable-arm, #b9b3a7);
  cursor: pointer;
}
/* The arm is a 6px bar. The thing a finger has to hit is not. */
.rail-turntable__arm::before {
  content: "";
  position: absolute;
  inset: -19px -10px;
}
.rail-turntable__side { min-width: 0; display: flex; flex-direction: column; gap: var(--_space-xs); }
.rail-turntable__badge {
  align-self: start;
  font-size: var(--_text-xs);
  padding: var(--_space-xs) var(--_space-sm);
  border: 1px solid var(--_border);
  border-radius: var(--_radius);
  color: var(--_muted);
}
.rail-turntable__list { list-style: none; margin: 0; padding: 0; }
.rail-turntable__track {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--_space-sm);
  min-height: var(--_control-min);
  padding: var(--_space-xs) 0;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--_border);
  color: inherit;
  text-align: left;
  cursor: pointer;
}
/* La pista sonando se marca con PESO y con un filete, no con el acento como
   color de texto: axe lo midio en 3.05:1 sobre papel oscuro con AA pidiendo
   4.5:1 a 13px. Es la tercera vez hoy que aparece este mismo fallo en el kit
   —antes en la categoria de RailBrandCard y en el control pulsado—, siempre
   por la misma razon: el acento de una marca se elige para destacar, nunca
   para leerse pequeno. */
.rail-turntable__track[aria-pressed="true"] {
  font-weight: var(--rail-turntable-playing-weight, 700);
  box-shadow: inset 2px 0 0 var(--_accent);
}
.rail-turntable__number { font-variant-numeric: tabular-nums; color: var(--_muted); }
.rail-turntable__text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.rail-turntable__text small { color: var(--_muted); font-size: var(--_text-xs); }
.rail-turntable__state { margin: 0; color: var(--_muted); font-size: var(--_text-sm); min-height: var(--_text-md); }

@media (max-width: 720px) {
  .rail-turntable { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------------
 * DECK — cards you keep or pass.
 *
 * THE CARD IS SIZED BY THE CONSUMER, not by a constant in here. A viewport
 * budget written as `calc(100svh - bar - 190px)` shipped with its own caption
 * and both buttons under a fixed bar, because the 190px stood for chrome that
 * measured 357px. Set --rail-deck-card-h from measured boxes, or let it be the
 * default and give it room.
 */
.rail-deck { display: flex; flex-direction: column; gap: var(--_space-xs); color: var(--_text); }
.rail-deck__progress { margin: 0; font-size: var(--_text-xs); color: var(--_muted); }
.rail-deck__card {
  display: flex;
  flex-direction: column;
  height: var(--rail-deck-card-h, 440px);
  padding: var(--_space-md);
  background: var(--_bg);
  border: 1px solid var(--_border);
  border-radius: var(--_radius);
  box-shadow: var(--_shadow);
  /* Horizontal is ours; vertical stays the page's. */
  touch-action: pan-y;
  user-select: none;
  cursor: grab;
}
.rail-deck__card:active { cursor: grabbing; }
.rail-deck__media { position: relative; flex: 1 1 0; min-height: 0; overflow: hidden; border-radius: var(--_radius); }
.rail-deck__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rail-deck__tag {
  position: absolute;
  top: var(--_space-xs); left: var(--_space-xs);
  max-width: calc(100% - var(--_space-sm));
  width: max-content;
  padding: var(--_space-xs) var(--_space-sm);
  font-size: var(--_text-xs);
  background: var(--rail-deck-tag-bg, color-mix(in srgb, #000 60%, transparent));
  color: var(--rail-deck-tag-ink, #fff);
}
.rail-deck__stamp {
  display: none;
  position: absolute;
  top: 48%; left: 50%;
  transform: translate(-50%, -50%) rotate(-8deg);
  padding: var(--_space-xs) var(--_space-sm);
  border: 3px solid;
  border-radius: var(--_radius);
  font-weight: var(--rail-deck-stamp-weight, 700);
  white-space: nowrap;
  color: var(--rail-deck-stamp-ink, #fff);
}
.rail-decide.is-keeping .rail-deck__stamp--keep,
.rail-decide.is-passing .rail-deck__stamp--pass { display: block; }
.rail-deck__stamp--keep { background: var(--rail-deck-keep, #305e44); }
.rail-deck__stamp--pass { background: var(--rail-deck-pass, #7b352f); }
.rail-deck__body { flex: none; display: flex; flex-direction: column; padding-top: var(--_space-xs); }
.rail-deck__body small { color: var(--_muted); font-size: var(--_text-xs); }
.rail-deck__body a { min-height: var(--_tap-min); display: inline-flex; align-items: center; color: inherit; }
.rail-deck__actions { display: flex; gap: var(--_space-sm); }
.rail-deck__actions button {
  flex: 1;
  min-height: var(--_control-min);
  padding: var(--_space-xs);
  border: 1px solid var(--_border);
  border-radius: var(--_pill);
  background: var(--_bg);
  color: var(--_text);
  cursor: pointer;
}
.rail-deck__actions button:last-child {
  background: var(--rail-deck-go-bg, #253c30);
  color: var(--rail-deck-go-ink, #fff);
  border-color: var(--rail-deck-go-bg, #253c30);
}
.rail-deck__result { display: flex; flex-direction: column; gap: var(--_space-xs); }

/* ---------------------------------------------------------------------------
 * MASTHEAD — the editorial section header. Rule ABOVE, because a line under a
 * heading closes it and a line over one opens a section.
 */
.rail-masthead { color: var(--_text); }
.rail-masthead__top {
  display: flex;
  justify-content: space-between;
  gap: var(--_space-md);
  flex-wrap: wrap;
  margin: 0 0 var(--_space-lg);
  padding-top: var(--_space-md);
  border-top: 1px solid var(--_border);
  font-size: var(--_text-xs);
}
.rail-masthead__counter { color: var(--_muted); text-align: right; }
.rail-masthead__title {
  display: flex;
  justify-content: space-between;
  align-items: end;
  gap: var(--_space-lg);
}
.rail-masthead__title h2 {
  margin: 0;
  font-size: var(--rail-masthead-size, clamp(40px, 6.5vw, 86px));
  line-height: var(--rail-masthead-leading, .98);
  letter-spacing: var(--rail-masthead-tracking, -.045em);
  font-weight: var(--rail-masthead-weight, 400);
}
.rail-masthead__controls { flex: none; display: flex; gap: var(--_space-xs); }
.rail-masthead__lede { margin: var(--_space-md) 0 0; color: var(--_muted); font-size: var(--_text-md); }
@media (max-width: 720px) {
  .rail-masthead__title { display: block; }
  .rail-masthead__controls { margin-top: var(--_space-md); }
}

/* ---------------------------------------------------------------------------
 * EVIDENCE — a collaboration, and an honest label for the picture beside it.
 * The label sits ON the image because the body copy is what people skip.
 */
.rail-evidence { list-style: none; margin: 0; padding: 0; display: contents; }
.rail-evidence__item { min-width: 0; }
.rail-evidence__card {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--_bg);
  border: 1px solid var(--_border);
  border-radius: var(--_radius);
  overflow: hidden;
  color: var(--_text);
}
.rail-evidence__media { position: relative; display: block; }
.rail-evidence__media img {
  display: block;
  width: 100%;
  aspect-ratio: var(--rail-evidence-aspect, 3 / 4);
  object-fit: cover;
}
.rail-evidence__provenance {
  position: absolute;
  left: var(--_space-sm);
  bottom: var(--_space-sm);
  max-width: calc(100% - var(--_space-lg));
  width: max-content;
  padding: var(--_space-xs) var(--_space-sm);
  font-size: var(--_text-xs);
  background: var(--rail-evidence-provenance-bg, rgba(0, 0, 0, 0.72));
  color: var(--rail-evidence-provenance-ink, #fff);
  border-radius: var(--_radius);
}
.rail-evidence__body { flex: 1; display: flex; flex-direction: column; padding: var(--_space-md); }
.rail-evidence__kicker { margin: 0; font-size: var(--_text-xs); color: var(--_muted); }
.rail-evidence__body h3 { margin: var(--_space-xs) 0 0; font-size: var(--_text-xl); font-weight: var(--rail-evidence-name-weight, 400); }
.rail-evidence__note { margin: var(--_space-xs) 0 0; color: var(--_muted); font-size: var(--_text-sm); }
.rail-evidence__body a {
  margin-top: auto;
  padding-top: var(--_space-md);
  min-height: var(--_tap-min);
  display: inline-flex;
  align-items: center;
  font-size: var(--_text-sm);
  color: var(--_accent-text);
}

/* ---------------------------------------------------------------------------
 * COVER — the first screen. Photograph on top, words in a panel below it.
 * Never text over the face (E03): two zones cannot regress the way an overlay
 * does the moment the asset changes.
 */
.rail-cover { color: var(--_text); }
.rail-cover__masthead {
  display: flex;
  justify-content: space-between;
  gap: var(--_space-md);
  margin: 0 0 var(--_space-md);
  font-size: var(--_text-xs);
}
.rail-cover__edition { color: var(--_muted); }
.rail-cover__track {
  display: flex;
  gap: var(--_gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
  padding-bottom: var(--_space-sm);
}
.rail-cover__poster {
  flex: 0 0 var(--rail-cover-width, 78%);
  max-width: var(--rail-cover-max, 520px);
  display: flex;
  flex-direction: column;
  scroll-snap-align: center;
  background: var(--_bg);
  border: 1px solid var(--_border);
  border-radius: var(--_radius);
  overflow: hidden;
}
.rail-cover__media { position: relative; display: block; }
.rail-cover__media img {
  display: block;
  width: 100%;
  aspect-ratio: var(--rail-cover-aspect, 3 / 4);
  object-fit: cover;
}
/* Seats the photograph against the page. It is NOT there to make text legible:
   there is no text on the photograph. */
.rail-cover__shade {
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg,
    var(--rail-cover-shade, rgba(0, 0, 0, 0.35)), transparent 45%);
  pointer-events: none;
}
.rail-cover__label {
  position: absolute;
  top: var(--_space-sm);
  left: var(--_space-sm);
  display: flex;
  gap: var(--_space-sm);
  padding: var(--_space-xs) var(--_space-sm);
  font-size: var(--_text-xs);
  background: var(--rail-cover-label-bg, rgba(0, 0, 0, 0.6));
  color: var(--rail-cover-label-ink, #fff);
}
.rail-cover__copy { display: flex; flex-direction: column; padding: var(--_space-md); }
.rail-cover__copy h2 {
  margin: 0;
  font-size: var(--rail-cover-title-size, clamp(30px, 5vw, 52px));
  line-height: var(--rail-cover-title-leading, 1);
  letter-spacing: var(--rail-masthead-tracking, -.045em);
  font-weight: var(--rail-cover-title-weight, 400);
}
.rail-cover__copy p { margin: var(--_space-sm) 0 0; color: var(--_muted); font-size: var(--_text-sm); }
.rail-cover__copy a {
  margin-top: var(--_space-md);
  min-height: var(--_tap-min);
  display: inline-flex;
  align-items: center;
  font-size: var(--_text-sm);
  color: var(--_accent-text);
}

/* ---------------------------------------------------------------------------
 * WELCOME — the card that arrives before the form. E12 as a component.
 */
.rail-welcome { display: flex; flex-direction: column; gap: var(--_space-md); color: var(--_text); }
.rail-welcome__card {
  padding: var(--_space-lg);
  border: 1px solid var(--_border);
  border-radius: var(--_radius);
  background: linear-gradient(140deg,
    var(--rail-welcome-bg, rgba(255, 255, 255, 0.08)), transparent);
  transform: rotate(var(--rail-welcome-tilt, -1.5deg));
}
.rail-welcome__eyebrow { display: block; font-size: var(--_text-xs); color: var(--_muted); }
.rail-welcome__card strong {
  display: block;
  margin-top: var(--_space-lg);
  font-size: var(--rail-welcome-size, clamp(24px, 4.5vw, 34px));
  line-height: var(--rail-welcome-leading, 1.1);
  font-weight: var(--rail-welcome-weight, 400);
}
.rail-welcome__card strong span,
.rail-welcome__card strong em { display: block; }
.rail-welcome__note { margin: 0; color: var(--_muted); font-size: var(--_text-sm); }
.rail-welcome__open {
  min-height: var(--_control-min);
  padding: var(--_space-sm) var(--_space-lg);
  border: 1px solid var(--_border);
  border-radius: var(--_pill);
  background: var(--rail-welcome-action-bg, transparent);
  color: inherit;
  cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
  .rail-welcome__card { transform: none; }
}
