/*
 * RAKT motion layer: scroll reveals and the animated diagrams.
 *
 * Two rules govern everything here.
 *
 * First, nothing is hidden unless JavaScript is running. Every hiding selector
 * is scoped to `html.rakt-motion`, a class motion.js sets on itself before the
 * first paint. If the script is blocked, fails to parse, or the browser has no
 * IntersectionObserver, no element ever receives an opacity of 0 and the page
 * reads exactly as it does today. Reveal-on-scroll implemented the other way
 * round, with the hidden state in the stylesheet and JS responsible for undoing
 * it, is the single most common way a marketing site ships a blank page.
 *
 * Second, motion is opt-out at the OS level. The reduced-motion block at the
 * foot neutralises transitions and animations rather than merely shortening
 * them, and it is written last so it wins on order alone.
 */

/* ─────────────────────────────────────────────────────────────
   Scroll reveal
   ───────────────────────────────────────────────────────────── */

html.rakt-motion .rakt-reveal {
  opacity: 0;
  transform: translateY(16px);
}

html.rakt-motion .rakt-reveal.is-in {
  opacity: 1;
  transform: none;
  /* Opacity and transform only. Both are compositor-driven, so a long list of
     revealing cards does not force layout on each frame. */
  transition:
    opacity 620ms cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 620ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Staggered children. `--i` is set by motion.js on each child of a marked
   group; the cap keeps a twelve-card grid from taking a second and a half to
   finish, which reads as a slow page rather than a considered one. */
html.rakt-motion .rakt-reveal.is-in {
  transition-delay: calc(min(var(--i, 0), 6) * 70ms);
}

/* ─────────────────────────────────────────────────────────────
   Diagrams
   ───────────────────────────────────────────────────────────── */

.rakt-dgm {
  --dgm-ink: var(--rakt-ink, #0B1220);
  --dgm-body: var(--rakt-body, #475569);
  --dgm-muted: var(--rakt-muted, #64748B);
  --dgm-line: var(--rakt-line, #E3E8EF);
  --dgm-primary: var(--rakt-primary, #D0243C);
  --dgm-surface: var(--rakt-surface, #F7F9FC);
  --dgm-check: var(--rakt-check, #0F7B4F);
  --dgm-warn: var(--rakt-warning, #F4A623);

  width: 100%;
  margin: 0;
}

.rakt-dgm svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.rakt-dgm__cap {
  margin: 14px 0 0;
  font-family: var(--rakt-font-primary, sans-serif);
  font-size: 0.84375rem;
  line-height: 1.5;
  color: var(--dgm-muted);
}

/* Typography inside the SVG.
 *
 * Set here rather than as presentation attributes so the diagram inherits the
 * site's font stack and honours a user font override.
 *
 * Painted with `currentColor` against an explicit `color`, never with a `fill`
 * of its own. Two reasons, and the second is the load-bearing one. It keeps the
 * diagram to colours the page already uses. And `fill` is invisible to anything
 * reading computed styles, so SVG text with a bare `fill` reports whatever
 * `color` it happened to inherit: the body grey, which is 30 RGB units from the
 * builder's ink and is not a colour these pages otherwise paint text in. That
 * showed up as a near-duplicate colour pair on every page carrying a diagram,
 * and the pair did not exist on screen.
 *
 * Sizes are viewBox units, not pixels. See the note on the mobile rule below for
 * what they resolve to. */
.rakt-dgm text {
  font-family: var(--rakt-font-primary, sans-serif);
  color: var(--dgm-ink);
  fill: currentColor;
}
.rakt-dgm .t-node   { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.rakt-dgm .t-sub    { font-size: 12.5px; font-weight: 500; color: var(--dgm-muted); }
.rakt-dgm .t-step   { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; color: var(--dgm-primary); }
.rakt-dgm .t-day    { font-size: 12.5px; font-weight: 700; letter-spacing: 0.06em; color: var(--dgm-primary); }
.rakt-dgm .t-refuse { font-size: 14px; font-weight: 600; color: #9B1C2E; }

.rakt-dgm .n-box {
  fill: #FFFFFF;
  stroke: var(--dgm-line);
  stroke-width: 1;
}
.rakt-dgm .n-box--tint  { fill: var(--dgm-surface); }
.rakt-dgm .n-box--gate  { fill: #FDF2F4; stroke: #F3C6CE; }
.rakt-dgm .n-box--done  { fill: #F1F8F4; stroke: #C6E3D2; }

.rakt-dgm .n-link {
  fill: none;
  stroke: var(--dgm-line);
  stroke-width: 1.5;
  stroke-linecap: round;
}
.rakt-dgm .n-link--live { stroke: var(--dgm-primary); }
.rakt-dgm .n-link--dash { stroke-dasharray: 4 4; }

.rakt-dgm .n-dot { fill: var(--dgm-primary); }
.rakt-dgm .n-ico { fill: none; stroke: var(--dgm-primary); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* ── Animation: nodes ─────────────────────────────────────────
   Each animated part carries `--i`, its position in the sequence, and the
   diagram only starts once it is on screen. */

html.rakt-motion .rakt-dgm .a-node {
  opacity: 0;
  transform: translateY(8px) scale(0.985);
  transform-box: fill-box;
  transform-origin: center;
}
html.rakt-motion .rakt-dgm.is-in .a-node {
  animation: rakt-dgm-in 520ms cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
  animation-delay: calc(var(--i, 0) * 150ms);
}

@keyframes rakt-dgm-in {
  from { opacity: 0; transform: translateY(8px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

/* ── Animation: connectors draw ───────────────────────────────
   `pathLength="1"` is set on the markup, so the dash figures are fractions of
   the path and one rule covers paths of any real length. */

html.rakt-motion .rakt-dgm .a-draw {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
html.rakt-motion .rakt-dgm.is-in .a-draw {
  animation: rakt-dgm-draw 420ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
  animation-delay: calc(var(--i, 0) * 150ms + 260ms);
}

@keyframes rakt-dgm-draw {
  to { stroke-dashoffset: 0; }
}

/* ── Animation: the travelling segment ───────────────────────
   A short dash running the length of the flow once the chain has drawn, which
   is what makes a row of boxes read as a sequence with a direction.

   Done as a dash travelling along an overlaid copy of the connector rather than
   a dot on an `offset-path`: dash geometry is understood by every browser that
   renders SVG at all, where `offset-path: path()` would leave the dot parked at
   the origin wherever it is unsupported. */

html.rakt-motion .rakt-dgm .a-flow {
  opacity: 0;
  stroke-dasharray: 0.06 0.94;
  stroke-dashoffset: 1;
}
html.rakt-motion .rakt-dgm.is-in .a-flow {
  opacity: 1;
  animation: rakt-dgm-flow 2800ms linear var(--flow-delay, 1100ms) infinite;
}

@keyframes rakt-dgm-flow {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}

/* ── Animation: the gate stamp ───────────────────────────────
   The refusal cross lands slightly late and with no bounce. A gate that springs
   playfully into place undercuts the thing it is illustrating. */

html.rakt-motion .rakt-dgm .a-stamp {
  opacity: 0;
  transform: scale(0.9);
  transform-box: fill-box;
  transform-origin: center;
}
html.rakt-motion .rakt-dgm.is-in .a-stamp {
  animation: rakt-dgm-stamp 340ms cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
  animation-delay: calc(var(--i, 0) * 150ms + 340ms);
}

@keyframes rakt-dgm-stamp {
  to { opacity: 1; transform: none; }
}

/* Legibility floor, expressed as a width rather than a breakpoint.
 *
 * These are laid out in a 1000-unit viewBox and scale with the container, so a
 * font-size above is a fraction of the diagram's width and not a pixel
 * measurement. The label that goes illegible first is the 12-unit step eyebrow,
 * and the site holds text to 13.5px, so the diagram must never render narrower
 * than 13.5 / 12 x 1000, which is 1125px.
 *
 * `min-width` against the `width: 100%` above does that with no media query and
 * no magic breakpoint: above 1125px of container the diagram fills the space,
 * below it the figure scrolls instead of shrinking. Choosing a breakpoint
 * instead would have left every width between the phone and the desktop
 * rendering 8px labels, which is what a `max-width: 600px` version of this rule
 * actually did.
 *
 * Horizontal scroll is the honest trade. A seven-step flow chart cannot be read
 * on a 360px screen at any font size, and the figcaption underneath carries the
 * same explanation in prose, so a reader who never swipes still gets the point. */
.rakt-dgm--wide {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}
.rakt-dgm--wide > svg {
  min-width: 1125px;
}

/* ─────────────────────────────────────────────────────────────
   Reduced motion. Last, so it wins on order.
   ───────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html.rakt-motion .rakt-reveal,
  html.rakt-motion .rakt-reveal.is-in,
  html.rakt-motion .rakt-dgm .a-node,
  html.rakt-motion .rakt-dgm .a-draw,
  html.rakt-motion .rakt-dgm .a-stamp {
    opacity: 1;
    transform: none;
    stroke-dashoffset: 0;
    transition: none;
    animation: none;
  }
  /* The travelling segment is decorative and loops forever, so it is removed
     rather than stilled: a stopped dash mid-path just looks like a mistake. */
  html.rakt-motion .rakt-dgm .a-flow {
    display: none;
  }
}
