/* ================================================================
   HELIXID — illustrations.css
   Inline SVG scenes for the "How it works" steps, drawn in the logo's
   hairline style. Each scene plays once when its section gets .in
   (main.js). Transform + opacity only; transforms sit on <g> wrappers
   with transform-box: fill-box (AGENTS.md). Static under reduced motion.
   ================================================================ */

.ill { display: block; width: 100%; height: auto; overflow: visible; }

/* Palette (mirrors main.css tokens; SVG presentation attributes can't read var() in all browsers) */
.ill .ink      { stroke: #0B1220; }
.ill .f-ink    { fill: #0B1220; }
.ill .f-white  { fill: #FFFFFF; }
.ill .f-soft   { fill: #E6FBF9; }
.ill .f-soft2  { fill: #F3FBFC; }
/* Accent fills are a soft teal tint and outlines a muted teal, so the scenes don't
   compete with the logo; full-strength brand teal is kept for the logo mark itself. */
.ill .f-teal   { fill: #A8E4DE; }
.ill .f-cyan   { fill: #BDEEF4; }
.ill .s-teal   { stroke: #4DBFB6; }
.ill .s-tealdk { stroke: #0A7C77; }
.ill .s-muted  { stroke: #A9B6C2; }
.ill .f-red    { fill: #DC2626; }
.ill .s-red    { stroke: #DC2626; }
.ill .f-redbg  { fill: #FEF2F2; }
.ill .f-green  { fill: #16A34A; }
.ill .s-green  { stroke: #16A34A; }
.ill .f-tealdk { fill: #0A7C77; }
.ill .f-navy   { fill: #1E3A8A; }
.ill .f-muted  { fill: #5B6B7A; }
.ill .f-bush   { fill: #2F3B52; opacity: .85; }
.ill .f-blue50 { fill: #EEF4FF; }
.ill .f-blue   { fill: #2563EB; }
.ill .s-blue   { stroke: #2563EB; }
.ill .f-green50{ fill: #ECFDF3; }
.ill .f-violet50 { fill: #F3EFFF; }
.ill .s-violet { stroke: #7C3AED; }
.ill .f-violet { fill: #7C3AED; }
.ill .f-red50  { fill: #FEF2F2; }
.ill .s-navy   { stroke: #1E3A8A; }
/* Secondary palette — soft tints that give the scenes variety without competing
   with the brand teal: foliage, sky, road and building tones. */
.ill .f-leaf   { fill: #E4F5EA; }
.ill .s-leaf   { stroke: #63B48A; }
.ill .s-leafdk { stroke: #3F8F67; }
.ill .f-sky    { fill: #F2F8FE; }
.ill .s-sky    { stroke: #9CC0E2; }
.ill .s-road   { stroke: #F1F4F8; }
.ill .s-roadeg { stroke: #D6DEE8; }
.ill .s-roadln { stroke: #B6C3D1; }
.ill .f-sand   { fill: #FBF4E6; }
.ill .s-wood   { stroke: #9A7B5A; }

.ill .line     { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.ill .hair     { fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* Default weights only where the element doesn't set its own stroke-width
   (CSS would otherwise override the SVG attribute). */
.ill .line:not([stroke-width]) { stroke-width: 2; }
.ill .hair:not([stroke-width]) { stroke-width: 1.4; }
.ill .dash     { stroke-dasharray: 6 6; }

.ill text      { font-family: 'Plus Jakarta Sans', 'Segoe UI', Helvetica, Arial, sans-serif; fill: #0B1220; }
.ill .t-label  { font-size: 13px; font-weight: 700; }
.ill .t-title  { font-size: 15px; font-weight: 800; letter-spacing: .04em; }
.ill .t-mono   { font-family: 'Source Code Pro', monospace; font-size: 11px; font-weight: 500; }
.ill .t-hand   { font-family: 'Caveat', 'Comic Sans MS', cursive; font-size: 19px; font-weight: 600; fill: #1E3A8A; }
.ill .t-small  { font-size: 10.5px; font-weight: 800; letter-spacing: .03em; }
.ill .t-xs     { font-size: 9.5px; font-weight: 600; }
.ill .t-body   { font-size: 12px; font-weight: 600; }
.ill .t-big    { font-size: 18px; font-weight: 800; }
.ill .t-q      { font-size: 34px; font-weight: 800; fill: #0FB5AE; }

/* ── Animation primitives ─────────────────────────────────────────
   Put one class on a <g>; delay with style="--d: .4s". */
.ill [class*="a-"] { transform-box: fill-box; transform-origin: center; }
.ill .o-top    { transform-origin: top center; }
.ill .o-bottom { transform-origin: bottom center; }
.ill .o-left   { transform-origin: left center; }

/* Hidden until the section is revealed (only when JS runs) */
.js [data-animate]:not(.in) .ill :is(.a-pop, .a-rise, .a-drop, .a-fade, .a-grow-y, .a-grow-x, .a-slide-l, .a-slide-r, .a-stamp, .a-stack, .a-fly, .a-print, .a-walk-in, .a-walk-on) { opacity: 0; }
.ill :is(.a-travel, .a-route, .a-bounce, .a-flash) { opacity: 0; }

@keyframes ill-pop     { 0% { opacity: 0; transform: scale(.3); } 65% { opacity: 1; transform: scale(1.12); } 100% { opacity: 1; transform: none; } }
@keyframes ill-rise    { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes ill-drop    { from { opacity: 0; transform: translateY(-16px); } to { opacity: 1; transform: none; } }
@keyframes ill-fade    { from { opacity: 0; } to { opacity: 1; } }
@keyframes ill-grow-y  { from { opacity: 0; transform: scaleY(0); } to { opacity: 1; transform: none; } }
@keyframes ill-grow-x  { from { opacity: 0; transform: scaleX(0); } to { opacity: 1; transform: none; } }
@keyframes ill-slide-l { from { opacity: 0; transform: translateX(-24px); } to { opacity: 1; transform: none; } }
@keyframes ill-slide-r { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes ill-lift    { from { transform: none; } to { transform: rotate(-32deg); } }
@keyframes ill-advance { from { transform: none; } to { transform: translateX(var(--ax, 40px)); } }
@keyframes ill-spin    { from { transform: rotate(0); } to { transform: rotate(360deg); } }
@keyframes ill-wobble  { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-12deg); } 75% { transform: rotate(10deg); } }
@keyframes ill-bob     { 0%, 100% { transform: none; } 50% { transform: translateY(-4px); } }
@keyframes ill-pulse   { 0% { opacity: 0; transform: none; } 12% { opacity: .9; transform: none; } 100% { opacity: 0; transform: scale(1.16); } }
/* Travel from the element's own position by (--dx, --dy), then fade out */
@keyframes ill-travel  {
  0%   { opacity: 0; transform: translate(0, 0) scale(.6); }
  15%  { opacity: 1; transform: translate(0, 0) scale(1); }
  85%  { opacity: 1; transform: translate(var(--dx, 0), var(--dy, 0)) scale(1); }
  100% { opacity: 0; transform: translate(var(--dx, 0), var(--dy, 0)) scale(.8); }
}

.in .ill .a-pop     { animation: ill-pop     .55s cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-rise    { animation: ill-rise    .6s  cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-drop    { animation: ill-drop    .6s  cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-fade    { animation: ill-fade    .6s  ease                      var(--d, 0s) backwards; }
.in .ill .a-grow-y  { animation: ill-grow-y  .55s cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-grow-x  { animation: ill-grow-x  .55s cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-slide-l { animation: ill-slide-l .6s  cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-slide-r { animation: ill-slide-r .6s  cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.ill .barrier-arm { transform: rotate(-32deg); }
/* ShipCo's door check pops when the scene says so (--gc on the <svg>) */
.ill .gate-check { transform-box: fill-box; transform-origin: center; }
.js [data-animate]:not(.in) .ill .gate-check { opacity: 0; }
.in .ill .gate-check { animation: ill-pop .55s cubic-bezier(.22,1,.36,1) var(--gc, .6s) backwards; }
.ill .advanced    { transform: translateX(var(--ax, 40px)); }
.in .ill .a-advance { animation: ill-advance 1s cubic-bezier(.45,0,.2,1) var(--d, 0s) backwards; }
.in .ill .a-lift    { animation: ill-lift    .9s  cubic-bezier(.34,1.3,.5,1) var(--d, 0s) backwards; }
/* One-shot accents — all finish well inside 5 s, so no pause control is needed */
.in .ill .a-spin    { animation: ill-spin    1.4s cubic-bezier(.45,0,.2,1) var(--d, 0s) 1 both; }
.in .ill .a-wobble  { animation: ill-wobble  .7s  ease-in-out var(--d, 0s) 3 both; }
.in .ill .a-bob     { animation: ill-bob     1.2s ease-in-out var(--d, 0s) 2 both; }
.in .ill .a-pulse   { animation: ill-pulse   1.1s ease-out    var(--d, 0s) 2 both; }
.in .ill .a-travel  { animation: ill-travel  1.3s cubic-bezier(.45,0,.2,1) var(--d, 0s) 1 both; }

/* Story motions (steps 5–11) — transform and opacity only, all one-shot.
   a-route  : a token follows up to three hops (--x1/--y1 … --x3/--y3) over --t, then fades
   a-bounce : a token heads for (--dx, --dy), is refused and falls back
   a-stamp  : slams down from large and settles (VERIFIED)
   a-stack  : drops onto a pile with a small squash (needs .o-bottom)
   a-fly    : flies in from (--fx, --fy) turned by --fr and settles
   a-print  : slides out of a slot (clip it in the scene)
   a-walk-in: comes in from the left with a bouncing gait
   a-flash  : a highlight that blinks once and goes
   a-beat   : one heartbeat on an element that is already visible
   a-push   : two small shoves to the right
   a-tick   : a stopwatch hand that barely moves */
@keyframes ill-route {
  0%   { opacity: 0; transform: translate(0, 0) scale(.5); }
  8%   { opacity: 1; transform: translate(0, 0) scale(1); }
  36%  { transform: translate(var(--x1, 0), var(--y1, 0)); }
  66%  { transform: translate(var(--x2, var(--x1, 0)), var(--y2, var(--y1, 0))); }
  90%  { opacity: 1; transform: translate(var(--x3, var(--x2, var(--x1, 0))), var(--y3, var(--y2, var(--y1, 0)))) scale(1); }
  100% { opacity: 0; transform: translate(var(--x3, var(--x2, var(--x1, 0))), var(--y3, var(--y2, var(--y1, 0)))) scale(.6); }
}
@keyframes ill-bounce {
  0%   { opacity: 0; transform: translate(0, 0) scale(.5); }
  12%  { opacity: 1; transform: translate(0, 0) scale(1); }
  55%  { opacity: 1; transform: translate(var(--dx, 0), var(--dy, 0)); }
  70%  { opacity: 1; transform: translate(calc(var(--dx, 0px) * .7), calc(var(--dy, 0px) * .7)) rotate(-14deg); }
  100% { opacity: 0; transform: translate(calc(var(--dx, 0px) * .6), calc(var(--dy, 0px) * .6 + 14px)) rotate(-30deg); }
}
@keyframes ill-stamp  { 0% { opacity: 0; transform: scale(1.9) rotate(-10deg); } 55% { opacity: 1; transform: scale(.94) rotate(1deg); } 75% { transform: scale(1.04); } 100% { opacity: 1; transform: none; } }
@keyframes ill-stack  { 0% { opacity: 0; transform: translateY(-70px); } 55% { opacity: 1; transform: translateY(0) scaleY(.88); } 75% { transform: translateY(-4px) scaleY(1.03); } 100% { opacity: 1; transform: none; } }
@keyframes ill-fly    { 0% { opacity: 0; transform: translate(var(--fx, 0), var(--fy, 0)) rotate(var(--fr, 0deg)) scale(.7); } 70% { opacity: 1; transform: translate(0, 0) rotate(calc(var(--fr, 0deg) * -.08)) scale(1.03); } 100% { opacity: 1; transform: none; } }
@keyframes ill-print  { from { opacity: 0; transform: translateY(-100%); } 15% { opacity: 1; } to { opacity: 1; transform: none; } }
@keyframes ill-walk-in {
  0%   { opacity: 0; transform: translate(-80px, 0); }
  10%  { opacity: 1; transform: translate(-72px, -3px); }
  25%  { transform: translate(-56px, 0); }
  40%  { transform: translate(-40px, -3px); }
  55%  { transform: translate(-24px, 0); }
  70%  { transform: translate(-10px, -3px); }
  85%  { transform: translate(0, 0); }
  100% { opacity: 1; transform: none; }
}
@keyframes ill-flash  { 0% { opacity: 0; } 30% { opacity: 1; } 100% { opacity: 0; } }
@keyframes ill-beat   { 0%, 100% { transform: none; } 40% { transform: scale(1.18); } }
@keyframes ill-tick   { 0% { transform: none; } 60% { transform: rotate(28deg); } 80% { transform: rotate(22deg); } 100% { transform: rotate(24deg); } }
@keyframes ill-push   { 0%, 100% { transform: none; } 25%, 75% { transform: translateX(5px); } 50% { transform: none; } }
/* First-load entrance (hero, phones / no traveller): the agent walks on from the left along
   the road, bobbing with each step and slowing as it arrives. With the traveller the same walk
   is driven by main.js so it can come in from the edge of the screen. */
@keyframes ill-walk-on {
  0%   { opacity: 1; transform: translate(-520px, 0); animation-timing-function: linear; }
  10%  { transform: translate(-462px, -6px); }
  20%  { transform: translate(-404px, 0); }
  30%  { transform: translate(-346px, -6px); }
  40%  { transform: translate(-288px, 0); }
  50%  { transform: translate(-232px, -6px); }
  60%  { transform: translate(-178px, 0); }
  70%  { transform: translate(-126px, -5px); }
  80%  { transform: translate(-78px, 0); }
  90%  { transform: translate(-32px, -3px); animation-timing-function: ease-out; }
  100% { opacity: 1; transform: none; }
}
.in .ill .a-walk-on { animation: ill-walk-on 1.2s linear var(--d, 0s) backwards; }
.in .ill .a-route   { animation: ill-route   var(--t, 1.6s) cubic-bezier(.45,0,.25,1) var(--d, 0s) 1 both; }
.in .ill .a-bounce  { animation: ill-bounce  1.3s cubic-bezier(.45,0,.25,1) var(--d, 0s) 1 both; }
.in .ill .a-stamp   { animation: ill-stamp   .6s  cubic-bezier(.3,0,.3,1)   var(--d, 0s) backwards; }
.in .ill .a-stack   { animation: ill-stack   .7s  cubic-bezier(.3,0,.3,1)   var(--d, 0s) backwards; }
.in .ill .a-fly     { animation: ill-fly     .9s  cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-print   { animation: ill-print   1.1s cubic-bezier(.22,1,.36,1) var(--d, 0s) backwards; }
.in .ill .a-walk-in { animation: ill-walk-in 1.2s linear                    var(--d, 0s) backwards; }
.in .ill .a-flash   { animation: ill-flash   .9s  ease-out                  var(--d, 0s) 1 both; }
.in .ill .a-beat    { animation: ill-beat    .45s ease-in-out               var(--d, 0s) 1; }
.in .ill .a-tick    { animation: ill-tick    .5s  cubic-bezier(.3,0,.3,1)   var(--d, 0s) 1 both; }
.in .ill .a-push    { animation: ill-push    .8s  ease-in-out               var(--d, 0s) 2; }

/* Agent character: one blink, a short walk cycle and a wave — all one-shot, transform only */
.ill .r-blink { transform-box: fill-box; transform-origin: center; }
.ill .r-leg   { transform-box: fill-box; transform-origin: 50% 0; }
.ill .r-arm-l, .ill .r-wave { transform-box: fill-box; transform-origin: 100% 0; }
.ill .r-wave  { transform-origin: 0 100%; }
@keyframes r-blink  { 0%, 100% { transform: none; } 50% { transform: scaleY(.12); } }
@keyframes r-step-a { 0%, 100% { transform: none; } 25% { transform: rotate(16deg); } 75% { transform: rotate(-16deg); } }
@keyframes r-step-b { 0%, 100% { transform: none; } 25% { transform: rotate(-16deg); } 75% { transform: rotate(16deg); } }
@keyframes r-wave   { 0%, 100% { transform: none; } 25%, 75% { transform: rotate(14deg); } 50% { transform: rotate(-8deg); } }
.in .ill .r-blink            { animation: r-blink .22s ease-in-out var(--bd, 1s) 2; }
.in .ill .r-leg-l.walking    { animation: r-step-a .5s ease-in-out var(--wd, .3s) 3; }
.in .ill .r-leg-r.walking    { animation: r-step-b .5s ease-in-out var(--wd, .3s) 3; }
.in .ill .r-arm-l.walking    { animation: r-step-b .5s ease-in-out var(--wd, .3s) 3; }
.in .ill .r-wave             { animation: r-wave .9s ease-in-out var(--wd, 1s) 2; }
.ill:hover .r-blink { animation: r-blink .22s ease-in-out 1; }

/* Agent glances toward the pointer (main.js sets --lx / --ly in the agent's own units,
   only while the scene is on screen and only for a fine pointer) */
.ill .r-look-eyes  { transform: translate(var(--lx, 0px), var(--ly, 0px)); transition: transform .35s cubic-bezier(.22,1,.36,1); }
.ill .r-eyes-open  { opacity: 0; transition: opacity .18s ease; }
.ill .r-eyes-happy { transition: opacity .18s ease; }
.agents-looking .ill .r-eyes-open  { opacity: 1; }
.agents-looking .ill .r-eyes-happy { opacity: 0; }
.ill .r-look-mouth { transform: translate(calc(var(--lx, 0px) * .5), calc(var(--ly, 0px) * .5)); transition: transform .45s cubic-bezier(.22,1,.36,1); }

/* Step 7: a stack layer and its question card highlight each other */
.ill .layer { transform-box: fill-box; transition: transform .25s cubic-bezier(.22,1,.36,1); }
.ill .layer.is-hot { transform: translateX(-10px); }
.qa-card.is-hot { transform: translateX(6px); border-color: #0FB5AE; }

/* A scene's drawn sequence waits at its first frame until it is properly in view — or,
   with the travelling agent, until the agent arrives (main.js removes .ill-wait). Only the
   drawing inside is held; the image's own scroll-linked motion keeps running. */
.ill.ill-wait * { animation-play-state: paused !important; }

/* Travelling agent (desktop). main.js adds .has-traveller to <html> when it runs; then the
   scenes' own agents are hidden (the traveller lands exactly on their spots in their pose),
   except a second character marked data-agent-keep. */
.traveller { display: none; position: fixed; left: 0; top: 0; z-index: 45; pointer-events: none; }
.has-traveller .traveller { display: block; }
.traveller-body { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; }
.traveller-svg { position: absolute; left: -90px; top: -150px; width: 180px; height: 160px; overflow: visible; }
.has-traveller svg.ill:not(.traveller-svg) [data-agent]:not([data-agent-keep]) { visibility: hidden; }
.traveller .r-leg-l, .traveller .r-leg-r, .traveller .r-arm-l { animation: none !important; }
/* Steps 1–3 fold holds still while the traveller walks across it (main.js sets the
   extra track height and the sticky offset) */
.has-traveller .overview-pin { height: var(--pin-h, auto); }
.has-traveller .overview-pin > .overview { position: sticky; top: var(--pin-top, 80px); }
.traveller-measure .overview-pin > .overview { position: static; }
/* Every fold from step 4 on holds briefly, Apple-style: the section sticks for an extra
   stretch of native scrolling (main.js sets the track height and where it pins) */
.has-traveller .fold-pin { height: var(--pin-h, auto); }
.has-traveller .fold-pin > section {
  position: sticky; top: var(--pin-top, 80px);
  /* while held, a fold fills the screen under the nav (content centred) — no seams above or below */
  min-height: calc(100vh - var(--nav-h, 68px)); display: flex; flex-direction: column; justify-content: center;
}
.traveller-measure .fold-pin > section { position: static; }
.has-traveller .fold-pin.no-hold > section { position: static; }
/* Hand-held props (passport, visa, cards) stay put away until the traveller stands in
   that scene, then pop into its hands */
.has-traveller svg.ill [data-held] {
  opacity: 0; transform: translateY(12px) scale(.55); transform-box: fill-box; transform-origin: 50% 100%;
  transition: opacity .25s ease, transform .45s cubic-bezier(.34,1.45,.5,1);
}
.has-traveller svg.ill[data-traveller-here] [data-held] { opacity: 1; transform: none; }
/* With the traveller, main.js walks the traveller itself in (the hero's own agent is hidden);
   the hero card comes out when it arrives, like every held prop */
.has-traveller .hero .hero-walker.a-walk-on { animation: none; }
.traveller-overlay { position: absolute; inset: 0; pointer-events: none; overflow: visible; z-index: 3; }
/* The route is kept for the agent to follow but not drawn: with the folds holding still, a
   trail drawn on the page would slide past the held scenes */
.traveller-path { position: absolute; left: 0; top: 0; z-index: 3; pointer-events: none; overflow: visible; visibility: hidden; }
.traveller-path path { fill: none; stroke: #4DBFB6; stroke-width: 2.8; stroke-linecap: round; stroke-dasharray: .1 10; opacity: .5; }
.traveller-path .trail { stroke: #0FB5AE; opacity: .85; }

/* Replay button on each detail illustration (main.js swaps in a fresh copy of the SVG) */
.step-media { position: relative; }
.ill-replay {
  position: absolute; top: 0; right: 0; z-index: 2; min-height: 32px; padding: 6px 12px;
  display: inline-flex; align-items: center; gap: 6px; border-radius: 999px;
  font-family: inherit; font-size: 12.5px; font-weight: 600; line-height: 1; color: #0A7C77;
  background: #fff; border: 1px solid #CDEFEC; cursor: pointer;
  opacity: 0; transition: opacity .2s ease, background-color .2s ease, border-color .2s ease;
  touch-action: manipulation;
}
.step-media:hover .ill-replay, .ill-replay:focus-visible { opacity: 1; }
.ill-replay:hover { background: #E6FBF9; border-color: #0FB5AE; }
.ill-replay:focus-visible { outline: 2px solid #0FB5AE; outline-offset: 2px; }
.ill-replay svg { transition: transform .4s cubic-bezier(.22,1,.36,1); }
.ill-replay:hover svg { transform: rotate(-200deg); }
@media (hover: none), (pointer: coarse) { .ill-replay { opacity: 1; min-height: 44px; padding: 0 14px; } }

/* Hover: replay a small accent so the scene feels alive (transform only) */
.ill:hover .h-wobble { animation: ill-wobble .7s ease-in-out 1; }
.ill:hover .h-bob    { animation: ill-bob 1s ease-in-out 1; }

@media (prefers-reduced-motion: reduce) {
  .ill-replay { display: none; }
  .ill :is(.r-look-eyes, .r-look-mouth) { transform: none !important; transition: none; }
  .ill *, .ill *::before, .ill *::after { animation: none !important; }
  .js [data-animate]:not(.in) .ill * { opacity: 1; }
  .ill :is(.a-travel, .a-pulse, .a-route, .a-bounce, .a-flash) { opacity: 0 !important; }
}
