/* =============================================================
   LABS ON CALL, Story graphics
   No monospace. Motion explains; it never decorates.

   Animation technique note: everything here uses either CSS
   `transform` on an SVG <g> or `stroke-dashoffset`. Both are
   universally supported. `offset-path` was removed, mobile
   Safari's support is patchy and it silently failed on phones.
   ============================================================= */

/* Screen-tier graphic swap */
.gfx-m { display: block; }
.gfx-d { display: none; }
@media (min-width: 768px) {
  .gfx-m { display: none; }
  .gfx-d { display: block; }
}

/* -------------------------------------------------------------
   1. COMPLETION PATH, the thesis graphic
   Three orders set out on each lane. On the unsupported lane one
   of the three drops out; on ours all three arrive.
   ------------------------------------------------------------- */

.cpath { width: 100%; height: auto; overflow: visible; }

.cpath .lane-broken {
  fill: none;
  stroke: rgba(253,254,251,.34);
  stroke-width: 2;
  stroke-dasharray: 5 7;
  stroke-linecap: round;
}
.cpath .lane-live {
  fill: none;
  stroke: var(--teal);
  stroke-width: 3;
  stroke-linecap: round;
}

.cpath .node-ring { fill: none; stroke: rgba(253,254,251,.36); stroke-width: 2; }
.cpath .node-ring--live { stroke: var(--teal); }
.cpath .node-ic { fill: none; stroke: rgba(253,254,251,.78); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.cpath .node-ic--live { stroke: var(--teal-300); }

/* Label sizes are set per-composition because the two viewBoxes differ
   in width, the same value would render at very different scales. */
.cpath .lbl {
  font-family: var(--f-display);
  font-style: italic;
  fill: rgba(253,254,251,.86);
}
/* Sized so the rendered result lands around 16-17px on desktop and 15px on
   phones: comfortably readable at any age without shouting. Because these are
   viewBox units they scale with the graphic, so they stay proportional on
   every screen rather than needing separate breakpoints. */
.cpath.gfx-d .lbl { font-size: 17px; }
.cpath.gfx-m .lbl { font-size: 15px; }
.cpath .lbl--live { fill: var(--teal-300); font-style: normal; font-weight: 700; }
.cpath .lbl--warn { fill: #EFB295; }

/* Drop-out gate: dashed line down to an X where the lost orders fall out */
.cpath .gate-dash { stroke: #EFB295; stroke-width: 2; stroke-dasharray: 4 5; opacity: .7; }
.cpath .drop-x path {
  stroke: #EFB295; stroke-width: 3; stroke-linecap: round; fill: none;
}

/* Travelling orders */
.cpath .pip { transform-box: view-box; transform-origin: 0 0; opacity: 0; }
/* Radius lives on the r="5.5" attribute in the markup, not here. `r` as a CSS
   property is an SVG2 geometry property that WebKit does not implement, so
   setting it in CSS left these circles at the attribute default of r=0 on
   every iOS browser: zero-radius, invisible, whether or not the animation
   ran. The coverage map never had the bug because its circles always carried
   the attribute. Do not move geometry back into CSS. */
.cpath .pip--muted circle { fill: rgba(253,254,251,.66); }
.cpath .pip--lost circle { fill: #E0A184; }
.cpath .pip--live circle { fill: var(--teal); }

/* Line draw-in */
.cpath .lane-live { stroke-dasharray: var(--len, 500); stroke-dashoffset: var(--len, 500); }
.cpath.in .lane-live { animation: drawLine 1000ms var(--ease) 400ms forwards; }
@keyframes drawLine { to { stroke-dashoffset: 0; } }

/* ---- Mobile choreography (viewBox 0 0 340 280) ----
   x0 = 56, x1 = 284, broken y = 72, live y = 240, gate x = 170, drop to y = 104 */
@keyframes m-pass-broken {
  0%   { transform: translate(56px, 72px); opacity: 0; }
  8%   { opacity: 1; }
  88%  { transform: translate(284px, 72px); opacity: 1; }
  100% { transform: translate(284px, 72px); opacity: 0; }
}
@keyframes m-lost-broken {
  0%   { transform: translate(56px, 72px); opacity: 0; }
  8%   { opacity: 1; }
  48%  { transform: translate(170px, 72px); opacity: 1; }
  74%  { transform: translate(170px, 104px); opacity: 0; }
  100% { transform: translate(170px, 104px); opacity: 0; }
}
@keyframes m-pass-live {
  0%   { transform: translate(56px, 240px); opacity: 0; }
  8%   { opacity: 1; }
  88%  { transform: translate(284px, 240px); opacity: 1; }
  100% { transform: translate(284px, 240px); opacity: 0; }
}

/* Two of the three drop out; the third completes */
.cpath.gfx-m.in .pip--b1 { animation: m-lost-broken 3600ms var(--ease) 200ms infinite; }
.cpath.gfx-m.in .pip--b2 { animation: m-lost-broken 3600ms var(--ease) 700ms infinite; }
.cpath.gfx-m.in .pip--b3 { animation: m-pass-broken 3600ms var(--ease) 1200ms infinite; }
.cpath.gfx-m.in .pip--l1 { animation: m-pass-live 3600ms var(--ease) 1400ms infinite; }
.cpath.gfx-m.in .pip--l2 { animation: m-pass-live 3600ms var(--ease) 1900ms infinite; }
.cpath.gfx-m.in .pip--l3 { animation: m-pass-live 3600ms var(--ease) 2400ms infinite; }

/* ---- Desktop choreography (viewBox 0 0 620 290) ----
   x0 = 78, x1 = 540, broken y = 82, live y = 262, gate x = 321, drop to y = 118 */
@keyframes d-pass-broken {
  0%   { transform: translate(78px, 82px); opacity: 0; }
  8%   { opacity: 1; }
  88%  { transform: translate(540px, 82px); opacity: 1; }
  100% { transform: translate(540px, 82px); opacity: 0; }
}
@keyframes d-lost-broken {
  0%   { transform: translate(78px, 82px); opacity: 0; }
  8%   { opacity: 1; }
  48%  { transform: translate(321px, 82px); opacity: 1; }
  74%  { transform: translate(321px, 118px); opacity: 0; }
  100% { transform: translate(321px, 118px); opacity: 0; }
}
@keyframes d-pass-live {
  0%   { transform: translate(78px, 262px); opacity: 0; }
  8%   { opacity: 1; }
  88%  { transform: translate(540px, 262px); opacity: 1; }
  100% { transform: translate(540px, 262px); opacity: 0; }
}

.cpath.gfx-d.in .pip--b1 { animation: d-lost-broken 3600ms var(--ease) 200ms infinite; }
.cpath.gfx-d.in .pip--b2 { animation: d-lost-broken 3600ms var(--ease) 700ms infinite; }
.cpath.gfx-d.in .pip--b3 { animation: d-pass-broken 3600ms var(--ease) 1200ms infinite; }
.cpath.gfx-d.in .pip--l1 { animation: d-pass-live 3600ms var(--ease) 1400ms infinite; }
.cpath.gfx-d.in .pip--l2 { animation: d-pass-live 3600ms var(--ease) 1900ms infinite; }
.cpath.gfx-d.in .pip--l3 { animation: d-pass-live 3600ms var(--ease) 2400ms infinite; }

@media (prefers-reduced-motion: reduce) {
  .cpath .lane-live { stroke-dashoffset: 0 !important; }
  .cpath.in * { animation: none !important; }

  /* The pips are the argument, not decoration: two of the three orders stop
     at the gate and the third gets through, and with us all three do. They
     used to be display:none here, which honoured the motion preference by
     deleting the point of the graphic. Placed statically at the positions
     the animation resolves to instead, so the story still reads with
     nothing moving. Coordinates match the keyframe end states above. */
  .cpath .pip { opacity: 1; }

  .cpath.gfx-d .pip--b1 { transform: translate(305px, 118px); }
  .cpath.gfx-d .pip--b2 { transform: translate(337px, 118px); }
  .cpath.gfx-d .pip--b3 { transform: translate(540px, 82px); }
  .cpath.gfx-d .pip--l1 { transform: translate(210px, 262px); }
  .cpath.gfx-d .pip--l2 { transform: translate(375px, 262px); }
  .cpath.gfx-d .pip--l3 { transform: translate(540px, 262px); }

  .cpath.gfx-m .pip--b1 { transform: translate(156px, 104px); }
  .cpath.gfx-m .pip--b2 { transform: translate(184px, 104px); }
  .cpath.gfx-m .pip--b3 { transform: translate(284px, 72px); }
  .cpath.gfx-m .pip--l1 { transform: translate(130px, 240px); }
  .cpath.gfx-m .pip--l2 { transform: translate(207px, 240px); }
  .cpath.gfx-m .pip--l3 { transform: translate(284px, 240px); }
}

/* -------------------------------------------------------------
   2. PROCESS RAIL, the spine draws itself as you scroll in
   ------------------------------------------------------------- */

.jrny__rail { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-8); position: relative; }

/* Faint full-length track so the route is legible before it fills */
.jrny__rail::after {
  content: "";
  position: absolute;
  left: 15px; top: 8px; bottom: 8px; width: 3px;
  border-radius: 3px;
  background: var(--teal); opacity: .14;
}
/* The fill that travels along it. Was a 2px hairline at .22 opacity,
   which was effectively invisible, hence "no animation". */
.jrny__rail::before {
  content: "";
  position: absolute;
  z-index: 1;
  left: 15px; top: 8px; bottom: 8px; width: 3px;
  border-radius: 3px;
  background: var(--teal); opacity: .85;
  transform: scaleY(0); transform-origin: top;
  transition: transform 1600ms var(--ease) 120ms;
}
.jrny__rail.in::before { transform: scaleY(1); }

/* Dots light up in sequence rather than all at once */
.jrny__rail .jstep:nth-child(1) .jstep__dot,
.jrny__rail .jstep:nth-child(1) .jstep__dot i { transition-delay: 260ms; }
.jrny__rail .jstep:nth-child(2) .jstep__dot,
.jrny__rail .jstep:nth-child(2) .jstep__dot i { transition-delay: 620ms; }
.jrny__rail .jstep:nth-child(3) .jstep__dot,
.jrny__rail .jstep:nth-child(3) .jstep__dot i { transition-delay: 980ms; }
.jrny__rail .jstep:nth-child(4) .jstep__dot,
.jrny__rail .jstep:nth-child(4) .jstep__dot i { transition-delay: 1340ms; }
.jrny__rail .jstep:nth-child(5) .jstep__dot,
.jrny__rail .jstep:nth-child(5) .jstep__dot i { transition-delay: 1700ms; }

.jstep { position: relative; display: grid; grid-template-columns: 32px 1fr; gap: var(--s-4); align-items: start; }
.jstep__dot {
  position: relative; z-index: 1;
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--paper); border: 2px solid var(--mist-200);
  display: flex; align-items: center; justify-content: center; flex: none;
  transition: border-color var(--d-slow) var(--ease), transform var(--d-slow) var(--ease);
}
.section--deep .jstep__dot { background: var(--navy); border-color: rgba(253,254,251,.28); }
.jstep__dot i {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--slate-300);
  transition: background var(--d-slow) var(--ease), transform var(--d-slow) var(--ease);
}
.jstep.in .jstep__dot { border-color: var(--teal); transform: scale(1.06); }
.jstep.in .jstep__dot i { background: var(--teal); transform: scale(1.14); }

.jstep__t {
  font-family: var(--f-display); font-style: italic;
  font-size: .95rem; color: var(--teal-700); margin-bottom: var(--s-2);
}
.section--deep .jstep__t { color: var(--teal-300); }
.jstep__h {
  font-family: var(--f-body); font-size: 1.04rem; font-weight: 650;
  color: var(--navy); margin: 0 0 .25em; letter-spacing: -.006em;
}
.section--deep .jstep__h { color: var(--paper); }
.jstep p { font-size: var(--t-sm); color: var(--text-muted); margin: 0; }
.section--deep .jstep p { color: var(--text-on-deep-muted); }

@media (min-width: 900px) {
  .jrny__rail { grid-template-columns: repeat(var(--steps, 4), 1fr); gap: var(--s-6); }
  .jrny__rail::after {
    left: 16px; right: 16px; top: 15px; bottom: auto;
    width: auto; height: 3px;
  }
  .jrny__rail::before {
    left: 16px; right: 16px; top: 15px; bottom: auto;
    width: auto; height: 3px;
    transform: scaleX(0); transform-origin: left;
  }
  .jrny__rail.in::before { transform: scaleX(1); }
  .jstep { grid-template-columns: 1fr; gap: var(--s-6); }
  .jstep p { max-width: 32ch; }
}

@media (prefers-reduced-motion: reduce) {
  .jrny__rail::before { transform: none !important; transition: none; }
}

/* -------------------------------------------------------------
   3. COVERAGE MAP, recognisable continental US
   ------------------------------------------------------------- */

.cov { position: relative; width: 100%; }
.cov__svg { width: 100%; height: auto; overflow: visible; }

/* Supplied outline, recoloured to sit on the navy section */
.cov .map {
  fill: rgba(253, 254, 251, .07);
  stroke: rgba(253, 254, 251, .30);
  stroke-width: 1.1;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* Smaller regions */
.cov .dot-sm {
  fill: var(--teal);
  opacity: 0;
  transform-box: fill-box; transform-origin: center;
}
.cov.in .dot-sm { animation: dotIn 620ms var(--ease) forwards; }
@keyframes dotIn {
  0%   { opacity: 0; transform: scale(0); }
  70%  { opacity: .78; transform: scale(1.25); }
  100% { opacity: .62; transform: scale(1); }
}

/* Major metros use the Labs On Call location mark: the Drop brandmark turned
   on its point, so the marker is the brand rather than a generic dot. The tip
   sits exactly on the city, so the pin scales up from the tip rather than from
   its middle, which is why transform-origin is bottom rather than center. */
.cov .pin {
  fill: var(--teal-300);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 50% 100%;
}
.cov.in .pin { animation: pinDrop 700ms var(--ease) forwards; }
@keyframes pinDrop {
  0%   { opacity: 0; transform: translateY(-9px) scale(.4); }
  62%  { opacity: 1; transform: translateY(0) scale(1.16); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* Headquarters.
   Everything here is sized in viewBox units, so it shrinks with the map. On a
   phone the map renders at roughly half its coordinate space, which would put
   the label at about 5px. `--hq-s` scales the mark and the label back up at
   narrow widths rather than letting them dissolve. */
.cov { --hq-s: 1; --hq-lbl: 13px; }
@media (max-width: 1023px) { .cov { --hq-s: 1.12; --hq-lbl: 15px; } }
@media (max-width: 767px)  { .cov { --hq-s: 1.3;  --hq-lbl: 19px; } }

.cov .hq {
  fill: var(--paper);
  opacity: 0;
  transform-box: fill-box; transform-origin: center;
  transform: scale(var(--hq-s));
}
.cov.in .hq { animation: hqIn 760ms var(--ease) 1700ms forwards; }
@keyframes hqIn {
  0%   { opacity: 0; transform: scale(0) rotate(-70deg); }
  70%  { opacity: 1; transform: scale(calc(var(--hq-s) * 1.3)) rotate(8deg); }
  100% { opacity: 1; transform: scale(var(--hq-s)) rotate(0); }
}
.cov .hq-ring {
  fill: none; stroke: var(--paper); stroke-width: 1.4;
  opacity: 0;
  transform-box: fill-box; transform-origin: center;
}
.cov.in .hq-ring { animation: hqRing 3200ms var(--ease) 2100ms infinite; }
@keyframes hqRing {
  0%   { opacity: .6; transform: scale(calc(var(--hq-s) * .6)); }
  70%  { opacity: 0;  transform: scale(calc(var(--hq-s) * 1.9)); }
  100% { opacity: 0;  transform: scale(calc(var(--hq-s) * 1.9)); }
}
.cov .hq-lbl {
  font-family: var(--f-body);
  font-size: var(--hq-lbl); font-weight: 650;
  letter-spacing: .04em;
  fill: var(--paper);
  opacity: 0;
  /* Hold the gap to the star constant as the star scales up on small screens */
  transform: translateX(calc((var(--hq-s) - 1) * 11px));
}
.cov.in .hq-lbl { animation: fadeIn 600ms var(--ease) 2200ms forwards; }
@keyframes fadeIn { to { opacity: .92; } }

@keyframes ringPulse {
  0%   { opacity: .75; transform: scale(.5); }
  70%  { opacity: 0; transform: scale(2.6); }
  100% { opacity: 0; transform: scale(2.6); }
}

/* Staggered so the map fills in rather than snapping on all at once */
.cov .d0 { animation-delay: 300ms; }  .cov .d1 { animation-delay: 400ms; }
.cov .d2 { animation-delay: 500ms; }  .cov .d3 { animation-delay: 600ms; }
.cov .d4 { animation-delay: 700ms; }  .cov .d5 { animation-delay: 800ms; }
.cov .d6 { animation-delay: 900ms; }  .cov .d7 { animation-delay: 1000ms; }

.cov .m0 { animation-delay: 900ms; }  .cov .m1 { animation-delay: 1020ms; }
.cov .m2 { animation-delay: 1140ms; } .cov .m3 { animation-delay: 1260ms; }
.cov .m4 { animation-delay: 1380ms; } .cov .m5 { animation-delay: 1500ms; }


@media (prefers-reduced-motion: reduce) {
  .cov .dot-sm { opacity: .62; animation: none; }
  .cov .pin, .cov .hq { opacity: 1; animation: none; }
  .cov .hq-lbl { opacity: .92; animation: none; }
  .cov .hq-ring { display: none; }
}

/* -------------------------------------------------------------
   6. ROUTE OPTION CARDS
   ------------------------------------------------------------- */

.routes { display: grid; gap: var(--s-4); }
@media (min-width: 900px) { .routes { grid-template-columns: repeat(3, 1fr); gap: var(--s-6); } }

/* Border stays a uniform hairline, matching the service cards. A heavier top
   edge against 1px sides tapers unevenly through a 20px corner radius and
   the wedge is visible at both top corners. The accent is already carried by
   .route__tag, which opens the card the same way every other label on the
   site does. */
.route {
  position: relative;
  padding: var(--s-8) var(--s-6) var(--s-6);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.route__ic { display: block; width: 30px; height: 30px; margin-bottom: var(--s-4); color: var(--teal-700); }
.route__ic svg { width: 100%; height: 100%; }
.route h4 { font-family: var(--f-body); font-size: 1.02rem; font-weight: 650; color: var(--navy); margin: 0 0 .3em; }
.route p { font-size: var(--t-sm); color: var(--text-muted); margin: 0; }
.route__tag { font-family: var(--f-display); font-style: italic; font-size: .95rem; color: var(--teal-700); display: block; margin-bottom: var(--s-3); }

/* -------------------------------------------------------------
   7. TRUST INDICATORS
   ------------------------------------------------------------- */

.tind { display: grid; gap: var(--s-6); }
@media (min-width: 640px) { .tind { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .tind { grid-template-columns: repeat(4, 1fr); gap: var(--s-8); } }

.tind__i { display: grid; grid-template-columns: 40px 1fr; gap: var(--s-4); align-items: start; }
.tind__i svg { width: 40px; height: 40px; color: var(--teal-600); flex: none; }
.section--deep .tind__i svg { color: var(--teal-300); }
.tind__i b { display: block; font-size: 1rem; font-weight: 650; color: var(--navy); margin-bottom: .16em; letter-spacing: -.006em; }
.section--deep .tind__i b { color: var(--paper); }
.tind__i span { display: block; font-size: var(--t-sm); line-height: 1.5; color: var(--text-muted); }
.section--deep .tind__i span { color: var(--text-on-deep-muted); }

/* -------------------------------------------------------------
   8. IMAGE PLACEHOLDERS
   Replace the whole <div class="ph">…</div> with:
   <img src="Assets/Images/file.webp" alt="…" width="W" height="H" loading="lazy">
   ------------------------------------------------------------- */

.ph {
  position: relative;
  display: flex; flex-direction: column; justify-content: center;
  width: 100%;
  padding: clamp(1.25rem, 1rem + 1.5vw, 2rem);
  border: 2px dashed rgba(29,45,80,.26);
  border-radius: var(--r-lg);
  background:
    repeating-linear-gradient(135deg, rgba(29,45,80,.028) 0 10px, transparent 10px 20px),
    var(--mist);
  color: var(--navy);
  overflow: hidden;
}
.section--deep .ph {
  border-color: rgba(253,254,251,.32);
  background:
    repeating-linear-gradient(135deg, rgba(253,254,251,.045) 0 10px, transparent 10px 20px),
    var(--navy-800);
  color: var(--paper);
}


.ph[data-ratio] { aspect-ratio: var(--ratio, 16 / 9); }

.ph__tag {
  display: inline-flex; align-items: center; gap: .5em; align-self: flex-start;
  font-family: var(--f-body); font-size: .72rem; font-weight: 700; letter-spacing: .01em;
  /* --warn on --warn-100 measured 3.75:1 at 11.5px, under the 4.5:1 AA floor */
  color: #8A4220; padding: .35em .75em; border-radius: var(--r-pill);
  background: var(--warn-100); margin-bottom: var(--s-4);
}
.section--deep .ph__tag { background: rgba(224,161,132,.22); color: #F0C4AC; }

.ph__title { font-family: var(--f-body); font-size: .99rem; font-weight: 650; line-height: 1.35; margin: 0 0 .4em; color: inherit; }
.ph__desc { font-size: var(--t-sm); line-height: 1.5; color: var(--text-muted); margin: 0 0 var(--s-4); max-width: 54ch; }
.section--deep .ph__desc { color: rgba(253,254,251,.72); }

.ph__spec {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
  padding-top: var(--s-3); border-top: 1px solid rgba(29,45,80,.14);
  font-size: .74rem; color: var(--slate);
}
.section--deep .ph__spec { border-top-color: rgba(253,254,251,.18); color: rgba(253,254,251,.55); }
.ph__spec b { color: var(--navy); font-weight: 650; }
.section--deep .ph__spec b { color: var(--paper); }

/* Device frames */
.frame-lap {
  position: relative;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--navy-900); padding: 30px 10px 10px;
  box-shadow: var(--shadow-lg);
}
.frame-lap::before {
  content: ""; position: absolute; top: 11px; left: 14px;
  width: 8px; height: 8px; border-radius: 50%;
  background: rgba(253,254,251,.3);
  box-shadow: 14px 0 0 rgba(253,254,251,.3), 28px 0 0 rgba(253,254,251,.3);
}
.frame-lap .ph, .frame-lap img { border-radius: var(--r-sm); }

.frame-phone {
  position: relative; max-width: 262px; margin-inline: auto;
  border: 8px solid var(--navy-900); border-radius: 30px;
  background: var(--navy-900); box-shadow: var(--shadow-lg); overflow: hidden;
}
.frame-phone .ph, .frame-phone img { border-radius: 20px; border-width: 1px; }
@media (min-width: 900px) { .frame-phone { margin-inline: 0; } }
