/* ==========================================================================
   Cadline Limited — visual layer
   Icons, infographics, illustrations and looping animations.
   Loads after styles.css. Every loop is disabled under prefers-reduced-motion
   (see the block at the foot of this file).
   ========================================================================== */

/* ---------- Chart palette --------------------------------------------------
   Validated for the light chart surface (#ffffff):
   worst adjacent CVD ΔE 9.1 · worst adjacent normal-vision ΔE 22.9.
   Two slots sit below 3:1 contrast, so the relief rule applies — every mark
   carries a visible direct value label, and the table below repeats the data.
   -------------------------------------------------------------------------- */
:root {
  --series-software: #c0272d;
  --series-training: #2a78d6;
  --series-works:    #1baf7a;
  --series-drawings: #eda100;
  --grid-ink: #e2e6ea;
}

/* ---------- Animated hero blueprint ---------- */
.hero-canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 0; opacity: .9; pointer-events: none;
}
.hero .wrap { position: relative; z-index: 2; }
/* the animated canvas carries its own grid — retire the static CSS one */
.hero--live::before { display: none; }

/* The blueprint draws itself ONCE on load and then holds its finished state —
   the grid sits still and the compass needle rests on north. The survey
   instrument is the only element that repeats. */
.align-draw {
  stroke-dasharray: 1600;
  stroke-dashoffset: 1600;
  animation: drawPath 2.8s ease-out forwards;
}
.align-draw.delay { animation-delay: .55s; }
@keyframes drawPath { to { stroke-dashoffset: 0; } }

.tick-fade { opacity: 0; animation: tickIn .8s ease-out 2.4s forwards; }
@keyframes tickIn { to { opacity: .85; } }

/* The one repeating element of the blueprint. Keyframes are sampled off the
   alignment cubic (M40 430 C240 430 300 250 520 190 S900 150 1160 96) at 16
   points spaced equally by ARC LENGTH, so the instrument holds a constant
   speed instead of surging where the curve is tight. Timing is linear for the
   same reason — any easing here is applied between every pair of keyframes,
   which is what makes a sampled path stutter. Starts once the line is down. */
.surveyor {
  opacity: 0;
  animation: surveyorRun 15s linear 3.2s infinite;
}
@keyframes surveyorRun {
  0%      { transform: translate(40px, 430px);   opacity: 0; }
  3%      { opacity: 1; }
  4.75%   { transform: translate(114px, 421px); }
  9.5%    { transform: translate(183px, 394px); }
  14.25%  { transform: translate(245px, 353px); }
  19%     { transform: translate(304px, 308px); }
  23.75%  { transform: translate(364px, 263px); }
  28.5%   { transform: translate(429px, 225px); }
  33.25%  { transform: translate(497px, 197px); }
  38%     { transform: translate(570px, 178px); }
  42.75%  { transform: translate(643px, 163px); }
  47.5%   { transform: translate(716px, 152px); }
  52.25%  { transform: translate(790px, 144px); }
  57%     { transform: translate(865px, 137px); }
  61.75%  { transform: translate(939px, 130px); }
  66.5%   { transform: translate(1013px, 121px); }
  71.25%  { transform: translate(1087px, 110px); }
  76%     { transform: translate(1160px, 96px);  opacity: 1; }
  84%     { transform: translate(1160px, 96px);  opacity: 0; }
  100%    { transform: translate(40px, 430px);   opacity: 0; }
}

/* Compass rose: continuous, constant-speed rotation. */
.sweep {
  animation: sweepSpin 12s linear infinite;
  transform-origin: center;
  transform-box: fill-box;
}
@keyframes sweepSpin { to { transform: rotate(360deg); } }

/* ---------- Figure wrapper ---------- */
.figure {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 30px 28px; box-shadow: var(--shadow-sm);
}
.figure-title { font-size: 1.05rem; font-weight: 700; color: var(--ink); margin: 0 0 4px; font-family: var(--ff-head); }
.figure-sub { font-size: .9rem; color: var(--muted); margin: 0 0 22px; }
.figure-note { font-size: .84rem; color: var(--muted); margin: 18px 0 0; }
.figure-note a { font-weight: 600; }

/* ---------- Horizontal bar chart ---------- */
.chart-row {
  display: grid; grid-template-columns: 200px 1fr 70px; align-items: center;
  gap: 16px; padding: 10px 0; border: 0; background: none; width: 100%;
  font-family: inherit; text-align: left; cursor: pointer;
}
.chart-row:hover .chart-track, .chart-row:focus-visible .chart-track { background: #eaeef2; }
.chart-row:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; border-radius: 6px; }
.chart-key { display: flex; align-items: center; gap: 10px; font-size: .93rem; color: var(--ink); font-weight: 600; }
.chart-swatch { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.chart-track { background: var(--bg-alt); border-radius: 4px; height: 22px; position: relative; overflow: hidden; }
.chart-fill {
  display: block;                    /* it is not a grid item — needs blockifying */
  height: 100%; width: 0; border-radius: 0 4px 4px 0;
  transition: width 1.1s cubic-bezier(.22,.75,.3,1);
}
.chart-value { font-size: 1.02rem; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.chart-value small { display: block; font-size: .74rem; font-weight: 600; color: var(--muted); }
.chart-axis {
  display: flex; justify-content: space-between; margin-top: 10px;
  padding-left: 216px; font-size: .76rem; color: var(--muted);
  border-top: 1px solid var(--grid-ink); padding-top: 8px;
}

/* ---------- Process pipeline with looping pulse ---------- */
.pipeline { position: relative; display: grid; grid-template-columns: repeat(5, 1fr); gap: 18px; }
.pipeline::before {
  content: ""; position: absolute; left: 10%; right: 10%; top: 33px; height: 3px;
  background: var(--line); border-radius: 2px;
}
.pipeline::after {
  content: ""; position: absolute; left: 10%; top: 33px; height: 3px; width: 80%;
  background: linear-gradient(90deg, rgba(192,39,45,0), var(--red), rgba(192,39,45,0));
  background-size: 30% 100%; background-repeat: no-repeat; border-radius: 2px;
  animation: pulseRun 4.5s linear infinite;
}
@keyframes pulseRun { 0% { background-position: -35% 0; } 100% { background-position: 135% 0; } }
.pipe-step { position: relative; text-align: center; z-index: 1; }
.pipe-ico {
  width: 68px; height: 68px; margin: 0 auto 16px; border-radius: 50%;
  background: #fff; border: 2px solid var(--line);
  display: grid; place-items: center; color: var(--red);
  transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
}
.pipe-step:hover .pipe-ico { border-color: var(--red); transform: translateY(-3px); box-shadow: var(--shadow-md); }
.pipe-ico svg { width: 28px; height: 28px; }
.pipe-num { display: block; font-size: .7rem; font-weight: 700; letter-spacing: .14em; color: var(--muted); margin-bottom: 6px; }
.pipe-step h3 { font-size: 1rem; margin-bottom: .35rem; }
.pipe-step p { font-size: .9rem; margin: 0; }

/* ---------- Looping client ticker ---------- */
.ticker {
  position: relative; overflow: hidden; padding: 7px 0;
  --fade-solid: #ffffff;             /* matches the section background */
  --fade-clear: rgba(255,255,255,0);
}
.ticker--alt { --fade-solid: #f5f7f9; --fade-clear: rgba(245,247,249,0); }
.ticker::before, .ticker::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 90px; z-index: 2; pointer-events: none;
}
.ticker::before { left: 0; background: linear-gradient(90deg, var(--fade-solid), var(--fade-clear)); }
.ticker::after { right: 0; background: linear-gradient(270deg, var(--fade-solid), var(--fade-clear)); }
.ticker-track { display: flex; width: max-content; animation: tickerRun 52s linear infinite; }
.ticker-track.reverse { animation-direction: reverse; animation-duration: 62s; }
.ticker:hover .ticker-track, .ticker:focus-within .ticker-track { animation-play-state: paused; }
@keyframes tickerRun { to { transform: translateX(-50%); } }
.ticker-item {
  flex: none; margin-right: 14px; padding: 14px 24px;
  background: #fff; border: 1px solid var(--line); border-radius: 8px;
  font-size: .92rem; font-weight: 600; color: var(--ink-soft); white-space: nowrap;
}
.ticker-item i { color: var(--red); margin-right: 9px; font-style: normal; }
.ticker-hint { text-align: center; font-size: .82rem; color: var(--muted); margin: 16px 0 0; }

/* ---------- Reach map ---------- */
.reachmap svg { width: 100%; height: auto; display: block; }
.arc { stroke-dasharray: 6 9; animation: arcFlow 2.6s linear infinite; }

/* Travelling dashes must shift by exactly one dash period per cycle, or the
   pattern jumps on every restart. Everything using dashTravel is authored with
   a 24-unit period (e.g. stroke-dasharray="14 10"), so the loop is seamless. */
.dash-flow { animation: dashTravel 2.4s linear infinite; }
@keyframes dashTravel { to { stroke-dashoffset: -24; } }
@keyframes arcFlow { to { stroke-dashoffset: -30; } }
.ping { transform-origin: center; transform-box: fill-box; animation: ping 2.8s ease-out infinite; }
.ping.d1 { animation-delay: .7s; }
.ping.d2 { animation-delay: 1.4s; }
.ping.d3 { animation-delay: 2.1s; }
@keyframes ping {
  0%   { transform: scale(.5); opacity: .85; }
  75%  { transform: scale(3); opacity: 0; }
  100% { transform: scale(3); opacity: 0; }
}
.reach-legend { display: flex; gap: 24px; flex-wrap: wrap; margin-top: 20px; font-size: .9rem; }
.reach-legend span { display: flex; align-items: center; gap: 9px; color: var(--body); }
.reach-legend i { width: 11px; height: 11px; border-radius: 50%; background: var(--red); display: block; flex: none; }
.reach-legend i.hub { background: #fff; box-shadow: 0 0 0 3px var(--red); }
.reach-legend i.line { width: 22px; height: 2px; border-radius: 0; background: #79a7d3; }

/* ---------- Before / after compare slider ---------- */
.compare {
  position: relative; border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line); background: #0f2237; touch-action: pan-y; --pos: 50%;
}
.compare > svg { display: block; width: 100%; height: auto; }
.compare-layer { position: absolute; inset: 0; }
.compare-layer.after { clip-path: inset(0 0 0 var(--pos)); }
.compare-layer svg { width: 100%; height: 100%; display: block; }
.compare-divider {
  position: absolute; top: 0; bottom: 0; left: var(--pos); width: 2px;
  background: #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.25); pointer-events: none; z-index: 4;
}
.compare-divider::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 42px; height: 42px; transform: translate(-50%, -50%);
  border-radius: 50%; background-color: #fff; box-shadow: var(--shadow-md);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23c0272d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6-5 6 5 6M15 6l5 6-5 6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center;
}
.compare-range {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; z-index: 5;
  opacity: 0; cursor: ew-resize; -webkit-appearance: none; appearance: none; background: none;
}
.compare-range:focus-visible ~ .compare-divider { box-shadow: 0 0 0 3px rgba(192,39,45,.75); }
.compare-tag {
  position: absolute; top: 14px; font-size: .7rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; padding: 5px 12px; border-radius: 999px; color: #fff;
  background: rgba(0,0,0,.55); pointer-events: none; z-index: 6;
}
.compare-tag.left { left: 14px; }
.compare-tag.right { right: 14px; background: rgba(192,39,45,.92); }

/* ---------- Cross-section illustration ---------- */
.crosssection svg { width: 100%; height: auto; display: block; border-radius: var(--radius); }
.flow { animation: dashTravel 2s linear infinite; }
.flow.slow { animation-duration: 3s; }
.droplet { animation: bob 3s ease-in-out infinite; }
.droplet.d2 { animation-delay: 1s; }
.droplet.d3 { animation-delay: 1.9s; }
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }

/* ---------- Product tiles ---------- */
.prodtiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.prodtile {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 24px 18px; text-align: center;
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.prodtile:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: #d4dae0; }
.prodtile svg { width: 46px; height: 46px; margin: 0 auto 14px; display: block; color: var(--red); }
.prodtile strong { display: block; color: var(--ink); font-size: .98rem; margin-bottom: 2px; }
.prodtile span { font-size: .82rem; color: var(--muted); }
.prodtile:hover .spin { animation: sweepSpin 2.6s linear infinite; }

/* ---------- Vertical step timeline ---------- */
.steps { list-style: none; margin: 0; padding: 0; position: relative; }
.steps::before { content: ""; position: absolute; left: 21px; top: 14px; bottom: 14px; width: 2px; background: var(--line); }
.steps li { position: relative; padding: 0 0 26px 64px; }
.steps li:last-child { padding-bottom: 0; }
.step-dot {
  position: absolute; left: 0; top: 0; width: 44px; height: 44px; border-radius: 50%;
  background: #fff; border: 2px solid var(--line); display: grid; place-items: center;
  color: var(--red); font-weight: 700; font-size: .9rem;
}
.step-dot svg { width: 20px; height: 20px; }
.steps li h4 { margin: 9px 0 4px; font-size: 1rem; color: var(--ink); font-family: var(--ff-head); }
.steps li p { margin: 0; font-size: .93rem; }

/* ---------- Chart tooltip ---------- */
.viz-tip {
  position: fixed; z-index: 300; pointer-events: none; opacity: 0;
  background: var(--ink); color: #fff; font-size: .84rem; line-height: 1.45;
  padding: 9px 13px; border-radius: 6px; box-shadow: var(--shadow-md);
  transition: opacity .12s ease; max-width: 250px;
}
.viz-tip.is-on { opacity: 1; }
.viz-tip b { display: block; font-size: .92rem; margin-bottom: 2px; }

/* ---------- Small icon helper ---------- */
.ico { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- Responsive ---------- */
@media (max-width: 980px) {
  .pipeline { grid-template-columns: repeat(2, 1fr); gap: 30px; }
  .pipeline::before, .pipeline::after { display: none; }
  .prodtiles { grid-template-columns: repeat(2, 1fr); }
  .chart-row { grid-template-columns: 150px 1fr 62px; gap: 12px; }
  .chart-axis { padding-left: 162px; }
}
@media (max-width: 640px) {
  .pipeline { grid-template-columns: 1fr; gap: 26px; }
  .chart-row { grid-template-columns: 1fr; gap: 6px; padding: 12px 0; }
  .chart-axis { display: none; }
  .figure { padding: 22px 18px; }
  .ticker::before, .ticker::after { width: 40px; }
  .compare-divider::after { width: 34px; height: 34px; }
}

/* ---------- Motion opt-out ---------- */
@media (prefers-reduced-motion: reduce) {
  .align-draw, .tick-fade, .surveyor, .sweep,
  .pipeline::after, .ticker-track, .arc, .ping, .dash-flow,
  .flow, .droplet, .prodtile:hover .spin {
    animation: none !important;
  }
  /* a frozen pulse would read as a progress bar — drop it instead */
  .pipeline::after { display: none; }
  .align-draw { stroke-dashoffset: 0; }
  .tick-fade { opacity: .85; }
  .surveyor { opacity: 0; }
  .chart-fill { transition: none; }
}
