/* ============================================================================
   onboarding.css — the first-run tour.

   Paired with static/js/bw-onboarding.js and templates/_onboarding.html. The
   template owns every string (it is the only place {{ _('...') }} works), the
   script owns sequencing, and this owns what the thing looks like.

   Loaded from templates/_app_ios.html alongside app-ios.css and
   app-states.css, for the reason that file documents: every page declares its
   CSS in an inline <style>, so a sheet linked from <head> loses every tie on
   source order. The rules here have to settle those ties against the
   page's own inline block without reaching for !important.

   ── The spotlight, and why there is no geometry in this file ──────────────

   Pointing at a real control the obvious way — measure it, punch a hole in a
   scrim over it — means getBoundingClientRect plus listeners on resize,
   scroll, orientationchange and the visual viewport, and it is still wrong
   the moment an iOS keyboard opens or the safe-area inset changes.

   So nothing is measured. The scrim covers the page; the nav bar is lifted
   above it by a class, which is enough to make it the only lit thing on the
   screen; and a second class dims the tabs that are not being talked about.
   Three z-indexes and an opacity. Correct at every viewport, in both
   orientations, with the keyboard up, forever.

   ── The stacking order it plugs into ─────────────────────────────────────

     .id-header .............   900   the top bar
     .bottom-nav ............  9999   the tab bar
     .bw-ob-scrim ...........  10000  over both — the page goes dark
     .bw-ob-lit .............  10001  the nav, pulled back out of the dark
     .bw-ob-card ............  10002  the caption, over everything
     account sheet ..........  10070  above the tour, and never open during it

   ── Motion ───────────────────────────────────────────────────────────────

   This is the first screen a new account sees, so it is the one place in the
   app that is allowed to show off a little — but only with the app's own
   motion vocabulary. Every duration and easing is from the spec in
   tools/drift_audit.py (150 / 200 / 350ms; standard
   cubic-bezier(0.4,0,0.2,1) or decelerate cubic-bezier(0.16,1,0.3,1)). The
   richness comes from *choreography* — each step's pieces rise in one after
   another on staggered animation-delays — not from long or looping effects.

   Nothing loops. An infinite animation needs a duration the spec does not
   have, and a throbbing thing beside a darkened screen reads as an alarm.

   Every keyframe below replays on its own each time a step is shown: a
   child of an element going from display:none to visible starts its CSS
   animations fresh, so the script needs no class juggling to re-trigger
   them, Back included.
   ========================================================================= */

/* ── Scroll lock ─────────────────────────────────────────────────────────
   Applied to <html> rather than <body> because the canvas is <html>'s here
   (app-ios.css §6). `overflow: hidden` only — `touch-action: none` up here
   would also forbid panning inside the card, which a short phone needs. */
html.bw-ob-open,
html.bw-ob-open body {
  overflow: hidden;
}

/* ── The scrim ─────────────────────────────────────────────────────────────
   A faint cyan bloom low on the screen, over the usual dark. It is what
   makes the lit nav bar on step 3 feel lit rather than merely uncovered. */
.bw-ob-scrim {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background:
    radial-gradient(120% 70% at 50% 110%, rgba(51, 204, 255, 0.14), transparent 60%),
    var(--scrim);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
  backdrop-filter: blur(8px) saturate(120%);
  opacity: 0;
  transition: opacity 350ms cubic-bezier(0.4, 0, 0.2, 1);
}
.bw-ob-scrim.is-in { opacity: 1; }

/* ── The lit navigation bar ──────────────────────────────────────────────
   The class is repeated four times, and this is not decoration.
   _fixed_chrome.html pins the tab bar with

     html body .bottom-nav.bottom-nav.bottom-nav { z-index: 9999 !important }

   at (0,3,2). A plain `.bw-ob-lit` loses to that, the bar stays under the
   scrim, and the spotlight silently lights nothing. Four repeats reach
   (0,4,2), which wins on specificity rather than on source order.

   Selecting on this file's own class — not on .bottom-nav — is what lets the
   same rule serve the desktop bar, which is a different element. */
html body .bw-ob-lit.bw-ob-lit.bw-ob-lit.bw-ob-lit {
  z-index: 10001 !important;
}

/* Dim the tabs that are not the subject of a step. `opacity` and nothing
   else: a filter would knock the bar's backdrop-blur out on WebKit. */
.bw-ob-lit[data-ob-focus] [data-tour] {
  opacity: 0.28;
  transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.bw-ob-lit[data-ob-focus="home"]   [data-tour="home"],
.bw-ob-lit[data-ob-focus="search"] [data-tour="search"],
.bw-ob-lit[data-ob-focus="picks"]  [data-tour="picks"],
.bw-ob-lit[data-ob-focus="live"]   [data-tour="live"],
.bw-ob-lit[data-ob-focus="bets"]   [data-tour="bets"] {
  opacity: 1;
}

/* The ring. `outline` rather than `box-shadow`: not clipped by the bar's
   overflow and takes no part in layout. */
.bw-ob-ring {
  outline: 2px solid var(--cyan);
  outline-offset: -2px;
  border-radius: var(--r-control);
}

/* ── The card ────────────────────────────────────────────────────────────
   One position for every step, so it reads as one guide still talking. On
   a phone it sits above the tab bar; on desktop it centres.

   The border is a gradient hairline: a padding-box fill over a border-box
   gradient, with a transparent border letting the second show through. One
   element, no pseudo, and it follows the radius for free. */
.bw-ob-card {
  position: fixed;
  z-index: 10002;
  left: var(--pad);
  right: var(--pad);
  bottom: calc(var(--bottom-h) + var(--safe-bottom) + var(--sp-4));
  margin: 0 auto;
  max-width: 420px;
  box-sizing: border-box;
  /* Capped against the tab bar below and the top bar above, so a tall step
     on a short phone scrolls inside rather than pushing its heading off the
     screen. dvh after vh: mobile Safari's vh is the largest viewport. */
  max-height: calc(100vh  - var(--bottom-h) - var(--safe-bottom)
                          - var(--id-h) - var(--safe-top) - var(--sp-6));
  max-height: calc(100dvh - var(--bottom-h) - var(--safe-bottom)
                          - var(--id-h) - var(--safe-top) - var(--sp-6));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: var(--sp-4) var(--sp-5) var(--sp-4);
  border: 1px solid transparent;
  border-radius: 24px;
  background:
    radial-gradient(140% 60% at 50% 0%, rgba(51, 204, 255, 0.10), transparent 70%) padding-box,
    linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(140deg, rgba(51, 204, 255, 0.65), rgba(255, 255, 255, 0.06) 38%,
                    rgba(255, 255, 255, 0.04) 62%, rgba(0, 255, 174, 0.55)) border-box;
  box-shadow:
    0 24px 60px -12px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(0, 0, 0, 0.12),
    0 0 48px -8px rgba(51, 204, 255, 0.22);
  font-family: 'DM Sans', sans-serif;
  opacity: 0;
  transform: translateY(18px) scale(0.97);
  transition: opacity 350ms cubic-bezier(0.4, 0, 0.2, 1),
              transform 350ms cubic-bezier(0.16, 1, 0.3, 1);
}
.bw-ob-card.is-in {
  opacity: 1;
  transform: translateY(0) scale(1);
}

@media (min-width: 600px) {
  .bw-ob-card {
    top: 50%;
    bottom: auto;
    transform: translateY(calc(-50% + 18px)) scale(0.97);
    max-height: calc(100vh  - var(--sp-8) - var(--sp-8));
    max-height: calc(100dvh - var(--sp-8) - var(--sp-8));
  }
  .bw-ob-card.is-in { transform: translateY(-50%) scale(1); }
}

/* ── The scrolling half ──────────────────────────────────────────────────
   Only the step scrolls; the progress bar above and the foot below stay put,
   because a reader who cannot see the way forward is stuck. `min-height: 0`
   lets the flex item shrink below its content. */
.bw-ob-step {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding-top: var(--sp-2);
}
.bw-ob-foot,
.bw-ob-dots { flex: 0 0 auto; }

/* ── Choreography ────────────────────────────────────────────────────────
   Each direct child of the step on screen rises into place, one after the
   other. `both` holds the first frame through the delay, so nothing flashes
   in at full opacity before its turn. */
@keyframes bw-ob-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes bw-ob-pop {
  from { opacity: 0; transform: scale(0.6) rotate(-8deg); }
  to   { opacity: 1; transform: none; }
}
@keyframes bw-ob-bloom {
  from { opacity: 0; transform: scale(0.4); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes bw-ob-sheen {
  from { background-position: 160% 0; }
  to   { background-position: -60% 0; }
}
@keyframes bw-ob-spark {
  0%   { opacity: 0; transform: rotate(var(--a)) translateY(0) scale(1); }
  30%  { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(-56px) scale(0.4); }
}

.bw-ob-step > * {
  animation: bw-ob-rise 350ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.bw-ob-step > :nth-child(1) { animation-name: bw-ob-pop; }
.bw-ob-step > :nth-child(2) { animation-delay: 90ms; }
.bw-ob-step > :nth-child(3) { animation-delay: 160ms; }
.bw-ob-step > :nth-child(4) { animation-delay: 230ms; }

/* ── Progress ────────────────────────────────────────────────────────────
   The dots are segments of one bar across the head of the card. Each fills
   left to right with the brand gradient as the reader reaches it. */
.bw-ob-dots {
  display: flex;
  gap: 6px;
  margin-bottom: var(--sp-3);
}
.bw-ob-dot {
  position: relative;
  flex: 1 1 0;
  height: 3px;
  border-radius: 3px;
  overflow: hidden;
  background: var(--glass-border2, rgba(255, 255, 255, 0.12));
}
.bw-ob-dot::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--grad, linear-gradient(135deg, #33ccff, #00ffae));
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 350ms cubic-bezier(0.16, 1, 0.3, 1);
}
.bw-ob-dot.is-done::after,
.bw-ob-dot.is-now::after { transform: scaleX(1); }

/* ── Hero steps (welcome, done) ──────────────────────────────────────────
   Centred, with a bigger mark: these are the two moments, not instructions. */
.bw-ob-step--hero {
  text-align: center;
  padding-top: 28px;  /* room for the halo and the spark burst above the mark */
}
.bw-ob-step--hero .bw-ob-title { font-size: var(--fs-title2, 22px); }

/* The app icon, with a soft halo that blooms out behind it and one sweep of
   light across its face. */
.bw-ob-brand {
  position: relative;
  width: 76px;
  height: 76px;
  margin: 0 auto var(--sp-4);
}
.bw-ob-halo {
  position: absolute;
  inset: -22px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(51, 204, 255, 0.38), rgba(0, 255, 174, 0.12) 60%, transparent);
  animation: bw-ob-bloom 350ms cubic-bezier(0.16, 1, 0.3, 1) 120ms both;
}
.bw-ob-brand-mark {
  position: relative;
  display: block;
  width: 76px;
  height: 76px;
  border-radius: 20px;
  box-shadow: 0 0 0 1px var(--cyan-line), 0 10px 28px rgba(0, 0, 0, 0.35);
}
.bw-ob-brand::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 20px;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, 0.55) 50%, transparent 65%)
              no-repeat;
  background-size: 250% 100%;
  background-position: 160% 0;
  pointer-events: none;
  animation: bw-ob-sheen 350ms cubic-bezier(0.4, 0, 0.2, 1) 420ms both;
}

/* ── Card head glyph ─────────────────────────────────────────────────────── */
.bw-ob-mark {
  position: relative;
  width: 44px;
  height: 44px;
  margin-bottom: var(--sp-3);
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    var(--grad, linear-gradient(135deg, #33ccff, #00ffae)) border-box;
  color: var(--cyan);
  font-size: var(--fs-headline);
  box-shadow: 0 6px 20px -6px rgba(51, 204, 255, 0.45);
}

/* The last step's mark: filled with the gradient, larger, with a burst of
   eight sparks thrown out from behind it once. */
.bw-ob-mark--done {
  width: 64px;
  height: 64px;
  margin: 0 auto var(--sp-4);
  border: 0;
  border-radius: 50%;
  background: var(--grad, linear-gradient(135deg, #33ccff, #00ffae));
  color: var(--on-accent, #04121a);
  font-size: 26px;
  box-shadow: 0 0 0 6px rgba(51, 204, 255, 0.12), 0 12px 32px -6px rgba(0, 255, 174, 0.5);
}
.bw-ob-sparks {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.bw-ob-sparks i {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: var(--cyan);
  opacity: 0;
  animation: bw-ob-spark 350ms cubic-bezier(0.16, 1, 0.3, 1) 200ms both;
}
.bw-ob-sparks i:nth-child(even) { background: #00ffae; width: 4px; height: 4px; margin: -2px 0 0 -2px; }
.bw-ob-sparks i:nth-child(1) { --a:   0deg; }
.bw-ob-sparks i:nth-child(2) { --a:  45deg; animation-delay: 240ms; }
.bw-ob-sparks i:nth-child(3) { --a:  90deg; }
.bw-ob-sparks i:nth-child(4) { --a: 135deg; animation-delay: 240ms; }
.bw-ob-sparks i:nth-child(5) { --a: 180deg; }
.bw-ob-sparks i:nth-child(6) { --a: 225deg; animation-delay: 240ms; }
.bw-ob-sparks i:nth-child(7) { --a: 270deg; }
.bw-ob-sparks i:nth-child(8) { --a: 315deg; animation-delay: 240ms; }

/* ── Type ────────────────────────────────────────────────────────────────── */
.bw-ob-title {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-title3);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--text-strong);
}

/* 15px: read on a dimmed screen, possibly at arm's length. */
.bw-ob-body {
  margin: 0;
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1.55;
  color: var(--text2);
}

/* ── The tab legend (step 3) ─────────────────────────────────────────────
   Each row rises in after the last. Icons repeat the marks in the bar, so
   the list and the thing it describes can be read against each other. */
.bw-ob-legend {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
}
.bw-ob-legend li {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-radius: 14px;
  background: var(--glass-bg2);
  border: var(--hairline, 1px) solid var(--glass-border);
  animation: bw-ob-rise 350ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.bw-ob-legend li:nth-child(1) { animation-delay: 160ms; }
.bw-ob-legend li:nth-child(2) { animation-delay: 220ms; }
.bw-ob-legend li:nth-child(3) { animation-delay: 280ms; }
.bw-ob-legend li:nth-child(4) { animation-delay: 340ms; }
.bw-ob-legend li > span:last-child {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.bw-ob-legend b {
  color: var(--text);
  font-size: var(--fs-subhead);
  font-weight: 700;
  line-height: 1.3;
}
.bw-ob-legend small {
  color: var(--muted2, var(--text2));
  font-size: var(--fs-caption);
  font-weight: 500;
  line-height: 1.35;
}
.bw-ob-legend .bw-ob-legend-icon {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--cyan-dim);
  border: 1px solid var(--cyan-line);
  color: var(--cyan);
  font-size: var(--fs-subhead);
}

/* ── The league picker (step 2) ──────────────────────────────────────────── */
.bw-ob-leagues {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}
.bw-ob-league {
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  border-radius: 14px;
  background: var(--glass-bg2);
  border: 1px solid var(--glass-border);
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: var(--fs-body);
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  animation: bw-ob-rise 350ms cubic-bezier(0.16, 1, 0.3, 1) both;
  transition: background 150ms cubic-bezier(0.4, 0, 0.2, 1),
              border-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1),
              transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
.bw-ob-league:nth-child(1) { animation-delay: 200ms; }
.bw-ob-league:nth-child(2) { animation-delay: 240ms; }
.bw-ob-league:nth-child(3) { animation-delay: 280ms; }
.bw-ob-league:nth-child(4) { animation-delay: 320ms; }
.bw-ob-league:nth-child(5) { animation-delay: 360ms; }
.bw-ob-league:nth-child(n+6) { animation-delay: 400ms; }
.bw-ob-league-logo {
  width: 20px;
  height: 20px;
}
.bw-ob-league:hover { border-color: var(--cyan-line); }
.bw-ob-league:active { transform: scale(0.97); }
.bw-ob-league[aria-pressed="true"] {
  background: var(--cyan-dim);
  border-color: var(--cyan);
  color: var(--cyan);
  box-shadow: 0 0 0 3px rgba(51, 204, 255, 0.15), 0 6px 18px -6px rgba(51, 204, 255, 0.5);
}

/* ── The exits on the last step ──────────────────────────────────────────── */
.bw-ob-exits {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}
.bw-ob-exit {
  min-height: var(--tap);
  padding: 0 var(--sp-4);
  border-radius: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  background: var(--glass-bg2);
  border: 1px solid var(--glass-border);
  color: var(--text);
  text-decoration: none;
  font-size: var(--fs-subhead);
  font-weight: 700;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
.bw-ob-exit:hover { border-color: var(--cyan-line); }
.bw-ob-exit.is-primary {
  background: var(--cyan-dim);
  border-color: var(--cyan-line);
  color: var(--cyan);
}
/* The guide is the quiet way out: a text link, not a third button competing
   with the two filled ones. */
.bw-ob-exit.is-link {
  min-height: 36px;
  background: none;
  border-color: transparent;
  color: var(--muted2, var(--text2));
  font-size: var(--fs-caption);
  font-weight: 600;
}
.bw-ob-exit.is-link:hover { color: var(--text); border-color: transparent; }

/* ── Foot: Skip on the left, Back / Next on the right ────────────────────── */
.bw-ob-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

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

.bw-ob-controls {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
}

/* Skip and Back are quiet; Next is the one filled thing on the card — the
   brand gradient, a soft glow, and a sheen that crosses it on hover. All
   three clear 44px. */
.bw-ob-quiet {
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--muted2);
  font-family: 'DM Sans', sans-serif;
  font-size: var(--fs-subhead);
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* The page's own button rules hand a bare <button> a minimum width, which
   floated "Skip" toward the middle of the foot. Sized to its word here, and
   pulled out by its own padding so the word lines up with the copy above. */
.bw-ob-foot .bw-ob-quiet {
  width: auto;
  min-width: 0;
  flex: 0 0 auto;
}
.bw-ob-foot > .bw-ob-quiet { margin-left: calc(-1 * var(--sp-3)); }
.bw-ob-quiet:hover { color: var(--text); }
.bw-ob-quiet[hidden] { display: none; }

.bw-ob-next {
  position: relative;
  overflow: hidden;
  min-height: var(--tap);
  min-width: 112px;
  padding: 0 var(--sp-5);
  border: 0;
  border-radius: 999px;
  background: var(--grad, linear-gradient(135deg, #33ccff, #00ffae));
  color: #04121a;
  font-family: 'DM Sans', sans-serif;
  font-size: var(--fs-body);
  font-weight: 800;
  letter-spacing: 0.01em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 8px 22px -8px rgba(51, 204, 255, 0.7);
  transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.bw-ob-next::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, 0.5) 50%, transparent 65%)
              no-repeat;
  background-size: 250% 100%;
  background-position: 160% 0;
  pointer-events: none;
}
.bw-ob-next:hover { box-shadow: 0 10px 28px -8px rgba(51, 204, 255, 0.9); }
.bw-ob-next:hover::after {
  animation: bw-ob-sheen 350ms cubic-bezier(0.4, 0, 0.2, 1) both;
}
.bw-ob-next:active { transform: scale(0.97); }
.bw-ob-next[hidden] { display: none; }

/* Focus is visible on everything here. A keyboard user is trapped inside this
   card by design; losing the caret inside a trap is a dead end. */
.bw-ob-card :focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
}

/* ── Steps ───────────────────────────────────────────────────────────────── */
.bw-ob-step[hidden] { display: none; }

/* ── `hidden` has to be re-stated ────────────────────────────────────────
   `.bw-ob-card { display: flex }` beats the UA sheet's `[hidden]` at equal
   specificity, so without this the closed card stayed in the layout —
   invisible at opacity 0 and still swallowing every tap across its
   footprint. Both elements listed so the scrim cannot reopen the hole. */
.bw-ob-card[hidden],
.bw-ob-scrim[hidden] { display: none; }

/* ── Reduced motion ──────────────────────────────────────────────────────
   Keep the fades, drop the travel, the bursts and the sheens. Something
   still has to mark the step changing, or the card looks frozen when the
   copy swaps underneath it. */
@media (prefers-reduced-motion: reduce) {
  .bw-ob-card {
    transform: none;
    transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .bw-ob-card.is-in { transform: none; }
  @media (min-width: 600px) {
    .bw-ob-card,
    .bw-ob-card.is-in { transform: translateY(-50%); }
  }
  /* `:nth-child(n)` matches everything, and is here only to reach the
     specificity of the stagger rules above — a plain `.bw-ob-step > *`
     loses to `.bw-ob-step > :nth-child(1)` whatever the source order. */
  .bw-ob-step > :nth-child(n),
  .bw-ob-legend li:nth-child(n),
  .bw-ob-league:nth-child(n),
  .bw-ob-halo {
    animation: bw-ob-fade 200ms cubic-bezier(0.4, 0, 0.2, 1) both;
    animation-delay: 0ms;
  }
  .bw-ob-brand::after,
  .bw-ob-next:hover::after,
  .bw-ob-sparks i { animation: none; }
  .bw-ob-sparks { display: none; }
  .bw-ob-dot::after { transition: none; }
  .bw-ob-next,
  .bw-ob-league { transition: background 150ms cubic-bezier(0.4, 0, 0.2, 1); }
  .bw-ob-next:active,
  .bw-ob-league:active { transform: none; }
}
@keyframes bw-ob-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
