/* Smart Web Labs: diagrams, and the contact page's map.
   Loaded only by pages that have one, from a <link> placed just before the
   first, so the page above it paints without waiting for this file.
   site.css holds everything else, including the rule that pauses loops off
   screen. */

/* ---------- Diagrams ----------
   Instrument-style figures drawn with HTML, CSS and inline SVG, in the
   page's one accent. Without scripts, or with reduced motion, each one is
   complete and still. Where motion is welcome it draws itself in when it is
   revealed (.is-in), and its loop runs once site.js marks the panel
   .is-live; like every loop, it pauses off screen. Labels inside a drawing
   sit in a role="img" or aria-hidden part and are left out of the word
   count; the caption is read out and counted. */

.dg { margin: 0 0 clamp(2.25rem, 4.5vw, 3.5rem); }
.dg__panel {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(1rem, 2.6vw, 2rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background:
    radial-gradient(80% 60% at 50% 0%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 72%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
    #0A0A0E;
}
/* An accent hairline along the top, and crop marks in the corners. */
.dg__panel::before {
  content: "";
  position: absolute;
  top: 0; left: var(--radius); right: var(--radius);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent) 25%, var(--accent) 75%, transparent);
  opacity: 0.5;
  pointer-events: none;
}
.dg__panel::after {
  --m: rgba(255, 255, 255, 0.2);
  content: "";
  position: absolute;
  inset: 9px;
  z-index: -1;
  background:
    linear-gradient(var(--m), var(--m)) 0 0 / 9px 1px,
    linear-gradient(var(--m), var(--m)) 0 0 / 1px 9px,
    linear-gradient(var(--m), var(--m)) 100% 0 / 9px 1px,
    linear-gradient(var(--m), var(--m)) 100% 0 / 1px 9px,
    linear-gradient(var(--m), var(--m)) 0 100% / 9px 1px,
    linear-gradient(var(--m), var(--m)) 0 100% / 1px 9px,
    linear-gradient(var(--m), var(--m)) 100% 100% / 9px 1px,
    linear-gradient(var(--m), var(--m)) 100% 100% / 1px 9px;
  background-repeat: no-repeat;
  pointer-events: none;
}
.dg__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 1.25rem;
  margin-bottom: clamp(1.1rem, 2.4vw, 1.75rem);
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--line);
}
.dg__bar > .lab:first-child { color: var(--accent); }
.dg__status { display: inline-flex; align-items: center; gap: 0.55rem; }
.dg__status::before {
  content: "";
  width: 6px; height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.dg svg { overflow: visible; }
.dg__caption { max-width: 68ch; margin-top: 1rem; color: var(--text-3); font-size: var(--fs-small); line-height: 1.6; }
.dg__caption .lab { display: inline; margin-right: 0.6rem; color: var(--accent); }
.dg__legend { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin-top: clamp(1.1rem, 2.6vw, 1.75rem); padding-top: 1rem; border-top: 1px solid var(--line); list-style: none; }
.dg__key { display: inline-flex; align-items: center; gap: 0.55rem; }
.dg__key::before { content: ""; flex: none; width: 18px; height: 6px; border-radius: 3px; background: var(--sw, var(--accent)); }
.dg__key--fair { --sw: color-mix(in srgb, var(--accent) 36%, transparent); }
.dg__key--poor { --sw: rgba(255, 255, 255, 0.14); }
.dg__key--window { --sw: repeating-linear-gradient(-45deg, var(--accent) 0 2px, transparent 2px 4px); }
.dg__key--soft { --sw: color-mix(in srgb, var(--accent) 30%, transparent); }
.dg__key--night { --sw: rgba(0, 0, 0, 0.6); }
.dg__key--night::before { outline: 1px solid var(--line-strong); }
.dg__key--now::before { width: 2px; height: 14px; border-radius: 1px; background: #fff; box-shadow: 0 0 8px rgba(255, 255, 255, 0.6); }
.dg__key--person::before { width: 10px; height: 10px; border-radius: 50%; background: var(--text-1); }
.dg__key--biz::before { width: 9px; height: 9px; border-radius: 2px; background: none; border: 1.5px solid rgba(255, 255, 255, 0.4); }
.dg__key--hit::before { width: 9px; height: 9px; border-radius: 2px; box-shadow: 0 0 0 3px #0A0A0E, 0 0 0 4.5px var(--accent); }
@media (scripting: none) { .dg__key--now { display: none; } }

/* Home: the path from stranger to customer. A light runs along the line,
   and each stage lights in the colour of the service that moved the
   visitor there. */
.journey__frame { position: relative; }
.journey__track > :nth-child(2) { --k: 1; }
.journey__track > :nth-child(3) { --k: 2; --n: var(--gold-500); --at: 1.07s; }
.journey__track > :nth-child(4) { --k: 3; }
.journey__track > :nth-child(5) { --k: 4; --n: var(--cyan); --at: 1.97s; }
.journey__track > :nth-child(6) { --k: 5; }
.journey__track > :nth-child(7) { --k: 6; --n: var(--lavender); --at: 3s; }
.journey__node { position: relative; background: radial-gradient(circle, var(--n, var(--text-1)) 0 2.5px, #0A0A0E 3px); box-shadow: 0 0 0 4px #0A0A0E, 0 0 16px -2px var(--n, rgba(255, 255, 255, 0.5)); }
.journey__stage:nth-child(n + 3) .journey__node { border-color: var(--n); }
.journey__move::before { box-shadow: 0 0 10px -1px var(--c); }
.journey__node::after { content: ""; position: absolute; inset: -1.5px; border: 1px solid var(--n, var(--text-1)); border-radius: 50%; opacity: 0; }
.journey__beam { position: absolute; top: 9px; bottom: 9px; left: 0; width: 14px; overflow: hidden; pointer-events: none; }
.journey__beam::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0;
  background:
    radial-gradient(circle at 50% 100%, #fff 0 1.5px, rgba(255, 255, 255, 0.45) 2.5px, transparent 7px),
    linear-gradient(180deg, transparent 62%, rgba(255, 255, 255, 0.85)) 50% 0 / 2px 100% no-repeat;
}
@media (min-width: 900px) {
  .journey__beam { top: 0; bottom: auto; left: 7px; right: 7px; width: auto; height: 14px; }
  .journey__beam::after {
    background:
      radial-gradient(circle at 100% 50%, #fff 0 1.5px, rgba(255, 255, 255, 0.45) 2.5px, transparent 7px),
      linear-gradient(90deg, transparent 62%, rgba(255, 255, 255, 0.85)) 0 50% / 100% 2px no-repeat;
  }
  /* A soft glow under the spectrum line. */
  .journey__track::after { content: ""; position: absolute; left: 7px; right: 7px; top: 3px; height: 8px; border-radius: 8px; background: var(--spectrum); opacity: 0.3; filter: blur(7px); pointer-events: none; }
}

/* Web design: Core Web Vitals dials, on Google's published scales. */
.gauges__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(0.75rem, 3vw, 2.5rem); }
.gauge { display: grid; justify-items: center; align-content: start; gap: 0.3rem; text-align: center; }
.gauge:nth-child(2) { --g: 1; }
.gauge:nth-child(3) { --g: 2; }
.gauge__dial { width: 100%; max-width: 13.5rem; height: auto; margin-bottom: 0.35rem; }
.gauge__track, .gauge__zone, .gauge__glow, .gauge__scan, .gauge__ticks, .gauge__marks { fill: none; }
.gauge__track { stroke: rgba(255, 255, 255, 0.05); stroke-width: 12; }
.gauge__zone { stroke-width: 12; }
.gauge__zone--good { stroke: var(--accent); }
.gauge__zone--fair { stroke: color-mix(in srgb, var(--accent) 36%, transparent); }
.gauge__zone--poor { stroke: rgba(255, 255, 255, 0.14); }
.gauge__glow { stroke: var(--accent); stroke-width: 26; stroke-opacity: 0.1; }
.gauge__ticks { stroke: rgba(255, 255, 255, 0.24); stroke-width: 1.2; stroke-linecap: round; }
.gauge__marks { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.gauge__scan { stroke: #fff; stroke-width: 3; stroke-linecap: round; stroke-dasharray: 2 200; stroke-dashoffset: 6; opacity: 0; }
.gauge__needle { transform: rotate(var(--rest)); transform-origin: 100px 96px; }
.gauge__needle path { fill: var(--text-1); }
.gauge__hub { fill: #0A0A0E; stroke: var(--accent); stroke-width: 2.5; }
.gauge__pin { fill: var(--accent); }
.gauge--lcp { --rest: -60deg; }
.gauge--inp, .gauge--cls { --rest: -86.4deg; }
.gauge--lcp :is(.gauge__zone--good, .gauge__glow) { stroke-dasharray: 41.1 100; }
.gauge--lcp .gauge__zone--fair { stroke-dasharray: 0 42.3 23.8 100; }
.gauge--lcp .gauge__zone--poor { stroke-dasharray: 0 67.3 100; }
:is(.gauge--inp, .gauge--cls) :is(.gauge__zone--good, .gauge__glow) { stroke-dasharray: 24.4 100; }
:is(.gauge--inp, .gauge--cls) .gauge__zone--fair { stroke-dasharray: 0 25.6 36.3 100; }
:is(.gauge--inp, .gauge--cls) .gauge__zone--poor { stroke-dasharray: 0 63.1 100; }
.gauge .lab { color: var(--accent); }
.gauge__value { color: var(--text-1); font-family: var(--font-display); font-size: clamp(1.2rem, 0.95rem + 1.3vw, 2rem); font-weight: 650; letter-spacing: -0.02em; line-height: 1.05; white-space: nowrap; }
.gauge__name { max-width: 16ch; color: var(--text-2); font-size: 0.8125rem; line-height: 1.4; }
.gauges .dg__legend { justify-content: center; }
@media (min-width: 760px) { .gauge__name { font-size: var(--fs-small); } }

/* Performance marketing: the funnel from impression to sale. Particles
   flow through it, and the narrowing walls stop most of them. */
.funnel { display: grid; gap: 1.25rem; }
.funnel__shape {
  position: relative;
  height: clamp(8.5rem, 15vw, 12rem);
  clip-path: polygon(0 0, 100% 30%, 100% 70%, 0 100%);
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 5%, transparent), color-mix(in srgb, var(--accent) 24%, transparent));
}
.funnel__edges { position: absolute; inset: 0; width: 100%; height: 100%; }
.funnel__edges path { fill: none; stroke: var(--accent); stroke-opacity: 0.65; stroke-width: 2; vector-effect: non-scaling-stroke; }
.funnel__edges .funnel__div { stroke: #fff; stroke-opacity: 0.16; stroke-width: 1; }
.funnel__edges--y { display: none; }
.funnel__flow { position: absolute; inset: 0; }
.funnel__flow i { position: absolute; left: 0; right: 0; top: calc(var(--p) * 100%); height: 0; opacity: 0; }
.funnel__flow i::before { content: ""; position: absolute; right: 100%; top: -1.5px; width: 20px; height: 3px; border-radius: 3px; background: linear-gradient(90deg, transparent, var(--accent)); }
.funnel__flow i:nth-child(3n)::before { background: linear-gradient(90deg, transparent, #fff); }
.funnel__flow i:nth-child(1) { --p: 0.08; --t: 3.9s; --d: -0.2s; }
.funnel__flow i:nth-child(2) { --p: 0.2; --t: 4.6s; --d: -2.9s; }
.funnel__flow i:nth-child(3) { --p: 0.33; --t: 4.2s; --d: -1.4s; }
.funnel__flow i:nth-child(4) { --p: 0.42; --t: 5s; --d: -3.8s; }
.funnel__flow i:nth-child(5) { --p: 0.5; --t: 4.4s; --d: -0.9s; }
.funnel__flow i:nth-child(6) { --p: 0.57; --t: 4.8s; --d: -2.2s; }
.funnel__flow i:nth-child(7) { --p: 0.66; --t: 4.1s; --d: -3.3s; }
.funnel__flow i:nth-child(8) { --p: 0.79; --t: 4.7s; --d: -1.7s; }
.funnel__flow i:nth-child(9) { --p: 0.91; --t: 4s; --d: -0.5s; }
.funnel__flow i:nth-child(10) { --p: 0.14; --t: 5.2s; --d: -4.4s; }
.funnel__flow i:nth-child(11) { --p: 0.46; --t: 3.8s; --d: -2.6s; }
.funnel__flow i:nth-child(12) { --p: 0.54; --t: 5.1s; --d: -4.8s; }
.funnel__flow i:nth-child(13) { --p: 0.72; --t: 4.3s; --d: -3.9s; }
.funnel__flow i:nth-child(14) { --p: 0.86; --t: 4.9s; --d: -1.1s; }
.funnel__spark { position: absolute; right: -16px; top: 50%; width: 32px; height: 32px; margin-top: -16px; border-radius: 50%; background: radial-gradient(circle, var(--accent), transparent 70%); opacity: 0.55; }
.funnel__stages { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); list-style: none; }
.funnel__stages li { display: grid; align-content: start; gap: 0.2rem; padding: 0 0.85rem; border-left: 1px solid var(--line); }
.funnel__stages li:first-child { padding-left: 0; border-left: 0; }
.funnel__stages li:nth-child(2) { --i: 1; }
.funnel__stages li:nth-child(3) { --i: 2; }
.funnel__stages li:nth-child(4) { --i: 3; }
.funnel__stages strong { color: var(--text-1); font-size: 1rem; font-weight: 600; line-height: 1.3; }
.funnel__stages span:last-child { color: var(--text-3); font-size: 0.875rem; line-height: 1.45; }
.funnel__stages .is-key strong { color: var(--accent); }
@media (max-width: 759.98px) {
  .funnel { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: 1rem; }
  .funnel__shape {
    height: auto;
    min-height: 19rem;
    clip-path: polygon(0 0, 100% 0, 70% 100%, 30% 100%);
    background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 5%, transparent), color-mix(in srgb, var(--accent) 24%, transparent));
  }
  .funnel__edges--x { display: none; }
  .funnel__edges--y { display: block; }
  .funnel__flow i { top: 0; bottom: 0; left: calc(var(--p) * 100%); right: auto; width: 0; height: auto; }
  .funnel__flow i::before { right: auto; top: auto; bottom: 100%; left: -1.5px; width: 3px; height: 20px; background: linear-gradient(180deg, transparent, var(--accent)); }
  .funnel__flow i:nth-child(3n)::before { background: linear-gradient(180deg, transparent, #fff); }
  .funnel__spark { right: auto; top: auto; left: 50%; bottom: -16px; margin: 0 0 0 -16px; }
  .funnel__stages { grid-template-columns: minmax(0, 1fr); grid-template-rows: repeat(4, minmax(0, 1fr)); }
  .funnel__stages li { align-content: center; padding: 0.5rem 0 0.5rem 0.25rem; border-left: 0; border-top: 1px solid var(--line); }
  .funnel__stages li:first-child { padding-left: 0.25rem; border-top: 0; }
}

/* AI automation: one enquiry, start to finish. Phones and tablets get a
   rail with a light running down it; desktops get the full map with
   pulses travelling along every wire. */
.flowmap { position: relative; display: grid; gap: 0.6rem; padding-left: 2.25rem; }
.flowmap__group { display: grid; gap: 0.6rem; list-style: none; }
.flowmap__chip {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  min-height: 3.25rem;
  padding: 0.55rem 0.9rem;
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-1);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.25;
}
.flowmap__chip .icon { color: var(--accent); }
.flowmap__node {
  position: relative;
  display: grid;
  gap: 0.3rem;
  padding: 1rem 1.1rem;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: var(--radius);
  background:
    radial-gradient(120% 100% at 0% 0%, color-mix(in srgb, var(--accent) 13%, transparent), transparent 70%),
    rgba(255, 255, 255, 0.025);
}
.flowmap__node--hub { grid-template-columns: auto minmax(0, 1fr); column-gap: 0.9rem; }
.flowmap__node--hub > :not(.flowmap__core) { grid-column: 2; }
.flowmap__node .lab { color: var(--accent); }
.flowmap__title { color: var(--text-1); font-family: var(--font-display); font-size: 1.25rem; font-weight: 650; letter-spacing: -0.02em; line-height: 1.1; }
.flowmap__text { color: var(--text-2); font-size: 0.875rem; line-height: 1.45; }
.flowmap__core {
  position: relative;
  grid-row: 1 / span 3;
  align-self: start;
  width: 2.75rem; height: 2.75rem;
  border-radius: 50%;
  background: radial-gradient(circle, var(--accent) 0 20%, color-mix(in srgb, var(--accent) 30%, transparent) 22% 44%, transparent 46%);
}
.flowmap__core::before { content: ""; position: absolute; inset: 0; border: 1px dashed color-mix(in srgb, var(--accent) 75%, transparent); border-radius: 50%; }
.flowmap__core::after { content: ""; position: absolute; inset: 0; border: 1px solid var(--accent); border-radius: 50%; opacity: 0; }
.flowmap__rail { position: absolute; left: 0.75rem; top: 1.625rem; bottom: 1.625rem; width: 2px; border-radius: 2px; background: var(--line-strong); overflow: hidden; }
.flowmap__rail::after { content: ""; position: absolute; inset: 0; opacity: 0; background: linear-gradient(180deg, transparent 62%, var(--accent) 94%, #fff); }
.flowmap__chip::before, .flowmap__node::before {
  content: "";
  position: absolute;
  left: calc(-1.5rem - 3px); top: 50%;
  width: 8px; height: 8px;
  margin-top: -4px;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  background: #0A0A0E;
}
.flowmap__node::before { background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent); }
.flowmap__chip::after, .flowmap__node::after { content: ""; position: absolute; inset: -1px; border-radius: inherit; box-shadow: 0 0 0 1px var(--accent), 0 0 20px -4px var(--accent); opacity: 0; pointer-events: none; }
/* Light timing on desktops, in step with the pulses (a 6 s loop). */
.flowmap__group:first-of-type .flowmap__chip:nth-child(2) { --at: 0.15s; }
.flowmap__group:first-of-type .flowmap__chip:nth-child(3) { --at: 0.3s; }
.flowmap__node--hub { --at: 1.45s; }
.flowmap__node--crm { --at: 2.3s; }
.flowmap__group:last-of-type .flowmap__chip:nth-child(1) { --at: 3.6s; }
.flowmap__group:last-of-type .flowmap__chip:nth-child(2) { --at: 3.75s; }
.flowmap__group:last-of-type .flowmap__chip:nth-child(3) { --at: 3.9s; }
.flowmap > :nth-child(4) { --i: 3; }
.flowmap > :nth-child(6) { --i: 5; }
.flowmap__group:last-of-type { --i: 7; }
.flowmap__fan, .flowmap__link { display: none; }
.flowmap__wire { fill: none; stroke: var(--line-strong); stroke-width: 1.5; }
.flowmap__pulse { fill: none; stroke: var(--accent); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 18 200; stroke-dashoffset: 25; }
@media (min-width: 1024px) {
  .flowmap {
    grid-template-columns: minmax(0, 1fr) 3.5rem minmax(0, 1.2fr) 2.75rem minmax(0, 0.95fr) 3.5rem minmax(0, 1fr);
    align-items: center;
    gap: 0;
    padding-left: 0;
  }
  .flowmap__rail, .flowmap__chip::before, .flowmap__node::before { display: none; }
  .flowmap__group { gap: 0.75rem; }
  .flowmap__chip { height: 3.25rem; min-height: 0; white-space: nowrap; }
  .flowmap__fan { display: block; width: 3.5rem; height: 11.25rem; filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent) 55%, transparent)); }
  .flowmap__link { display: block; position: relative; height: 2px; background: var(--line-strong); overflow: hidden; }
  .flowmap__link::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, var(--accent) 70%, #fff); transform: translateX(-100%); }
}

/* Guwahati SEO: two searches from opposite ends of the city. Schematic,
   not to scale; the map is drawn, not traced. */
.seo-map__view { position: relative; }
.seo-map__art { display: block; width: 100%; height: auto; color: var(--accent); }
.seo-map__contour { fill: none; stroke: rgba(255, 255, 255, 0.07); stroke-width: 1; }
.seo-map__river { fill: none; stroke: var(--accent); stroke-opacity: 0.1; stroke-width: 46; stroke-linecap: round; }
.seo-map__water { fill: none; stroke: var(--accent); stroke-opacity: 0.4; stroke-width: 1.5; stroke-dasharray: 2 14; }
.seo-map__road { fill: none; stroke: rgba(255, 255, 255, 0.1); stroke-width: 3; stroke-linecap: round; }
.seo-map__biz { fill: #0A0A0E; stroke: rgba(255, 255, 255, 0.36); stroke-width: 1.5; }
.seo-map__hit { fill: var(--accent); }
.seo-map__halo { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-opacity: 0.65; }
.seo-map__ring { fill: color-mix(in srgb, var(--accent) 5%, transparent); stroke: var(--accent); stroke-opacity: 0.45; stroke-width: 1.25; stroke-dasharray: 4 6; }
.seo-map__ping { fill: none; stroke: var(--accent); stroke-width: 2; opacity: 0; transform-box: fill-box; transform-origin: center; }
.seo-map__pin { fill: var(--text-1); }
.seo-map__pin-dot { fill: var(--bg-0); }
.seo-map__shadow { fill: rgba(0, 0, 0, 0.5); }
.seo-map__label { position: absolute; display: grid; justify-items: center; color: var(--text-1); font-size: 0.875rem; font-weight: 600; line-height: 1.25; text-align: center; white-space: nowrap; transform: translateX(-50%); }
.seo-map__label .lab { color: var(--accent); }
.seo-map__label--a { left: 25%; top: 53.5%; }
.seo-map__label--b { left: 72%; top: 68%; }
.seo-map__river-name { position: absolute; left: 31%; top: 13%; color: color-mix(in srgb, var(--accent) 80%, transparent); font-style: italic; }
.seo-map__axis { display: flex; align-items: center; gap: 0.75rem; margin-top: 0.85rem; }
.seo-map__axis::after { content: ""; order: 1; flex: 1; height: 1px; background: linear-gradient(90deg, var(--line-strong), transparent 18%, transparent 82%, var(--line-strong)); }
.seo-map__axis .lab { white-space: nowrap; }
.seo-map__axis .lab:last-child { order: 2; }
@media (max-width: 639.98px) { .seo-map__river-name, .seo-map__label .lab { display: none; } }
@media (max-width: 419.98px) { .seo-map__compass { display: none; } }

/* UK and USA: time-zone timelines. Hours run left to right in India time,
   and each band is a 9-to-5 working day placed where it falls in ours. */
.tz { --name: 8.5rem; --gap: 1rem; position: relative; display: grid; gap: 0.55rem; }
.tz__nowrow { display: none; height: 1.4rem; }
.tz__scale, .tz__nowrow { position: relative; margin-left: calc(var(--name) + var(--gap)); }
.tz__scale { height: 1.15rem; color: var(--text-3); font-family: var(--font-mono); font-size: var(--fs-lab); line-height: 1.15rem; }
.tz__scale span { position: absolute; top: 0; left: calc(var(--k, 0) / 8 * 100%); transform: translateX(-50%); }
.tz__scale > span:first-child { transform: none; }
.tz__scale > span:last-child { transform: translateX(-100%); }
.tz__scale span:nth-child(2) { --k: 1; }
.tz__scale span:nth-child(3) { --k: 2; }
.tz__scale span:nth-child(4) { --k: 3; }
.tz__scale span:nth-child(5) { --k: 4; }
.tz__scale span:nth-child(6) { --k: 5; }
.tz__scale span:nth-child(7) { --k: 6; }
.tz__scale span:nth-child(8) { --k: 7; }
.tz__scale span:nth-child(9) { --k: 8; }
.tz__row { display: grid; grid-template-columns: var(--name) minmax(0, 1fr); align-items: center; gap: var(--gap); }
.tz__row + .tz__row { --i: 1; }
.tz__row + .tz__row + .tz__row { --i: 2; }
.tz__row + .tz__row + .tz__row + .tz__row { --i: 3; }
.tz__row + .tz__row + .tz__row + .tz__row + .tz__row { --i: 4; }
.tz__row + .tz__row + .tz__row + .tz__row + .tz__row + .tz__row { --i: 5; }
.tz__name { color: var(--text-1); font-size: 0.9375rem; font-weight: 500; line-height: 1.25; }
.tz__name .lab { display: block; margin-bottom: 0.1rem; }
.tz__track {
  position: relative;
  height: 2.25rem;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.055) 0 1px, transparent 1px calc(100% / 24)), rgba(255, 255, 255, 0.015);
}
.tz__night { position: absolute; top: 0; bottom: 0; left: calc(var(--from) / 24 * 100%); width: calc(var(--len) / 24 * 100%); display: flex; align-items: center; padding-left: 0.5rem; background: rgba(0, 0, 0, 0.5); }
.tz__band {
  position: absolute;
  top: 4px; bottom: 4px; left: 0;
  width: calc(8 / 24 * 100%);
  display: flex;
  align-items: center;
  padding: 0 0.6rem;
  border-radius: 6px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 34%, transparent), color-mix(in srgb, var(--accent) 14%, transparent));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 60%, transparent);
  color: var(--text-1);
  font-size: 0.8125rem;
  font-weight: 600;
  white-space: nowrap;
  transform: translateX(calc(var(--at) / 8 * 100%));
}
.tz__band > span { position: relative; }
.tz__band::after { content: ""; position: absolute; inset: -1px; border-radius: inherit; box-shadow: 0 0 0 1px var(--accent), 0 0 18px -2px var(--accent); opacity: 0; }
.tz.is-now .tz__band.is-open::after { opacity: 0.9; }
/* London: the morning, best for calls, is the brighter first part. */
.tz__band--london::before { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 37.5%; border-radius: 6px 0 0 6px; background: color-mix(in srgb, var(--accent) 34%, transparent); }
.tz--uk .tz__night--1 { --from: 0; --len: 6; }
.tz--uk .tz__night--2 { --from: 22; --len: 2; }
.tz--us .tz__night { --from: 10; --len: 8; }
.tz[data-season="summer"] .tz__band--london { --at: 13.5; }
.tz[data-season="winter"] .tz__band--london { --at: 14.5; }
.tz[data-season="summer"] .tz__band--et { --at: 6.5; }
.tz[data-season="winter"] .tz__band--et { --at: 7.5; }
.tz[data-season="summer"] .tz__band--ct { --at: 7.5; }
.tz[data-season="winter"] .tz__band--ct { --at: 8.5; }
.tz[data-season="summer"] .tz__band--mt { --at: 8.5; }
.tz[data-season="winter"] .tz__band--mt { --at: 9.5; }
.tz .tz__band--az { --at: 9.5; }
.tz[data-season="summer"] .tz__band--pt { --at: 9.5; }
.tz[data-season="winter"] .tz__band--pt { --at: 10.5; }
/* London's own hours, under its track, slide with the clocks. */
.tz__scale--local { overflow: hidden; }
.tz__slide { position: absolute; inset: 0 auto 0 0; width: 125%; }
.tz[data-season="summer"] .tz__slide { transform: translateX(-5%); }
.tz[data-season="winter"] .tz__slide { transform: translateX(-1.6667%); }
.tz__slide span { left: calc(var(--k, 0) * 10%); }
.tz__slide span:nth-child(10) { --k: 9; }
.tz__slide span:nth-child(11) { --k: 10; }
.tz__slide > span:first-child, .tz__slide > span:last-child { transform: translateX(-50%); }
/* Now: a line at the current time, drawn only for the clocks in force. */
.tz__overlay { position: absolute; top: 0; bottom: 0; left: calc(var(--name) + var(--gap)); right: 0; display: none; pointer-events: none; }
.tz.is-now .tz__overlay { display: block; }
.tz__needle { position: absolute; inset: 0; transform: translateX(calc(var(--now, 0) * 100%)); }
.tz__needle::before { content: ""; position: absolute; left: -1px; top: 1.55rem; bottom: 0; width: 2px; border-radius: 2px; background: linear-gradient(180deg, #fff, rgba(255, 255, 255, 0.2)); box-shadow: 0 0 10px rgba(255, 255, 255, 0.45); }
.tz__needle::after { content: ""; position: absolute; left: -4px; top: calc(1.55rem - 4px); width: 8px; height: 8px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.16); }
.tz__nowlabel { position: absolute; top: 0; left: 0; color: var(--text-1); white-space: nowrap; transform: translateX(var(--shift, -50%)); }
.tz-switch { display: inline-flex; padding: 3px; border: 1px solid var(--line-strong); border-radius: 999px; background: rgba(255, 255, 255, 0.02); }
.tz-switch__btn {
  min-height: 44px;
  padding: 0 1rem;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: var(--fs-lab);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}
.tz-switch__btn:hover { color: var(--text-1); }
.tz-switch__btn[aria-pressed="true"] { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--text-1); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent); }
.tz-switch__btn:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 2px; }
@media (scripting: enabled) {
  .tz__nowrow { display: block; }
  .tz-static { display: none; }
}
@media (scripting: none) { .tz-switch { display: none; } }
@media (max-width: 699.98px) {
  .tz { --name: 0px; --gap: 0px; }
  .tz__row { grid-template-columns: minmax(0, 1fr); gap: 0.35rem; }
  .tz__name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.6rem; }
  .tz__band > span { display: none; }
  .tz__nowlabel .tz__there { display: none; }
}

/* How we work: typical time from approval to launch, in weeks. */
.gantt { --name: 11rem; --gap: 1.25rem; position: relative; display: grid; gap: 0.45rem; }
.gantt__scale { position: relative; height: 1.25rem; margin: 0 6px 0 calc(var(--name) + var(--gap)); color: var(--text-3); font-family: var(--font-mono); font-size: var(--fs-lab); line-height: 1.25rem; }
.gantt__scale span { position: absolute; top: 0; left: calc(var(--k, 0) / 6 * 100%); transform: translateX(-50%); }
.gantt__scale span:first-child { transform: none; }
.gantt__scale span:last-child { transform: translateX(-100%); }
.gantt__scale span:nth-child(2) { --k: 1; }
.gantt__scale span:nth-child(3) { --k: 2; }
.gantt__scale span:nth-child(4) { --k: 3; }
.gantt__scale span:nth-child(5) { --k: 4; }
.gantt__scale span:nth-child(6) { --k: 5; }
.gantt__scale span:nth-child(7) { --k: 6; }
.gantt__rows { display: grid; gap: 0.55rem; list-style: none; }
.gantt__row { display: grid; grid-template-columns: var(--name) minmax(0, 1fr); align-items: center; gap: var(--gap); }
.gantt__row:nth-child(2) { --i: 1; }
.gantt__row:nth-child(3) { --i: 2; }
.gantt__row:nth-child(4) { --i: 3; }
.gantt__row:nth-child(5) { --i: 4; }
.gantt__row:nth-child(6) { --i: 5; }
.gantt__name { color: var(--text-1); font-size: 0.9375rem; font-weight: 500; line-height: 1.25; }
.gantt__name .lab { display: block; margin-top: 0.2rem; }
.gantt__lane { position: relative; height: 1.75rem; margin-right: 6px; border-radius: 6px; background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.07) 0 1px, transparent 1px calc(100% / 12)), rgba(255, 255, 255, 0.015); }
.gantt__work, .gantt__window { position: absolute; top: 50%; height: 0.5rem; margin-top: -0.25rem; }
.gantt__work { left: 0; width: calc(var(--from) / 12 * 100%); border-radius: 99px 0 0 99px; background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 30%, transparent), var(--accent)); box-shadow: 0 0 12px -3px var(--accent); transform-origin: 0 50%; }
.gantt__window { left: calc(var(--from) / 12 * 100%); width: calc((var(--to) - var(--from)) / 12 * 100%); border-radius: 0 99px 99px 0; background: repeating-linear-gradient(-45deg, color-mix(in srgb, var(--accent) 65%, transparent) 0 2px, color-mix(in srgb, var(--accent) 12%, transparent) 2px 5px); }
.gantt__window::after { content: ""; position: absolute; right: -4px; top: 50%; width: 8px; height: 8px; margin-top: -4px; border-radius: 2px; background: var(--accent); box-shadow: 0 0 0 3px #0A0A0E, 0 0 12px var(--accent); transform: rotate(45deg); }
.gantt__row--landing { --from: 1; --to: 2; }
.gantt__row--site { --from: 3; --to: 8; }
.gantt__row--store { --from: 6; --to: 12; }
.gantt__row--ads, .gantt__row--auto { --from: 1; --to: 3; }
.gantt__row--seo { --from: 1.5; --to: 12; }
.gantt__row--seo .gantt__window { border-radius: 0; background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 60%, transparent), transparent); }
.gantt__row--seo .gantt__window::after { content: none; }
.gantt__playhead { position: absolute; top: 1.7rem; bottom: 0; left: calc(var(--name) + var(--gap)); right: 6px; opacity: 0; pointer-events: none; }
.gantt__playhead::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 1px; background: linear-gradient(180deg, transparent, var(--accent) 12%, var(--accent) 88%, transparent); box-shadow: 0 0 8px var(--accent); }
@media (max-width: 699.98px) {
  .gantt { --name: 0px; --gap: 0px; }
  .gantt__rows { gap: 0.9rem; }
  .gantt__row { grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
  .gantt__name { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.2rem 0.75rem; }
  .gantt__name .lab { margin-top: 0; }
}

/* About: the lab loop. A light circles the ring and each step lights as
   it passes. */
.cycle { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); grid-template-areas: "n n n" "w ring e" "s s s"; align-items: center; gap: 0.75rem clamp(0.6rem, 2.5vw, 2rem); }
.cycle__ring { grid-area: ring; position: relative; width: clamp(7.25rem, 30vw, 18.5rem); aspect-ratio: 1; }
.cycle__ring > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.cycle__halo { fill: none; stroke: rgba(255, 255, 255, 0.07); stroke-width: 1; }
.cycle__ticks { fill: none; stroke: rgba(255, 255, 255, 0.22); stroke-width: 1.2; stroke-linecap: round; }
.cycle__track { fill: none; stroke: color-mix(in srgb, var(--accent) 45%, transparent); stroke-width: 1.5; }
.cycle__chev { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.cycle__node { fill: #0A0A0E; stroke: var(--accent); stroke-width: 2; }
.cycle__ping { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: 0; transform-box: fill-box; transform-origin: center; }
.cycle__orbit { position: absolute; inset: 0; opacity: 0; }
.cycle__orbit::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 240deg, color-mix(in srgb, var(--accent) 80%, transparent) 350deg, #fff 360deg);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(80% - 2px), #000 calc(80% - 1.5px) calc(80% + 1.5px), transparent calc(80% + 2px));
  mask: radial-gradient(farthest-side, transparent calc(80% - 2px), #000 calc(80% - 1.5px) calc(80% + 1.5px), transparent calc(80% + 2px));
}
.cycle__orbit::after { content: ""; position: absolute; left: 50%; top: 10%; width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent), 0 0 14px var(--accent); }
.cycle__core { position: absolute; inset: 31%; display: grid; place-items: center; border: 1px solid var(--line-strong); border-radius: 50%; background: radial-gradient(circle, color-mix(in srgb, var(--accent) 16%, transparent), transparent 70%); color: var(--accent); }
.cycle__step { display: grid; gap: 0.2rem; }
.cycle__step > * { display: block; }
.cycle__step .lab { color: var(--accent); }
.cycle__step strong { color: var(--text-1); font-family: var(--font-display); font-size: clamp(0.9375rem, 0.85rem + 0.6vw, 1.375rem); font-weight: 650; letter-spacing: -0.02em; line-height: 1.1; }
.cycle__step span:not(.lab) { display: none; max-width: 22ch; color: var(--text-2); font-size: var(--fs-small); line-height: 1.45; }
.cycle__step--n { grid-area: n; justify-items: center; text-align: center; }
.cycle__step--e { grid-area: e; justify-items: start; --at: 2s; }
.cycle__step--s { grid-area: s; justify-items: center; text-align: center; --at: 4s; }
.cycle__step--w { grid-area: w; justify-items: end; text-align: right; --at: 6s; }
.cycle__ping--e { --at: 2s; }
.cycle__ping--s { --at: 4s; }
.cycle__ping--w { --at: 6s; }
@media (min-width: 700px) { .cycle__step span:not(.lab) { display: block; } }

/* India: a first visit to this site, slowed down, and its size budget. */
.fall { --name: 5.5rem; --gap: 1rem; display: grid; gap: clamp(1.25rem, 3vw, 2rem); }
.fall__chart { position: relative; padding-top: 1.6rem; }
.fall__rows { display: grid; gap: 0.55rem; list-style: none; }
.fall__row { display: grid; grid-template-columns: var(--name) minmax(0, 1fr); align-items: center; gap: var(--gap); }
.fall__row:nth-child(2) { --i: 1; }
.fall__row:nth-child(3) { --i: 2; }
.fall__row:nth-child(4) { --i: 3; }
.fall__row:nth-child(5) { --i: 4; }
.fall__name { color: var(--text-2); }
.fall__lane { position: relative; height: 1.5rem; background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.06) 0 1px, transparent 1px 10%); }
.fall__bar {
  position: absolute;
  top: 50%;
  left: calc(var(--a) * 100%);
  width: calc((var(--c) - var(--a)) * 100%);
  height: 0.625rem;
  margin-top: -0.3125rem;
  border-radius: 2px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 28%, transparent) 0 var(--w), var(--accent) var(--w));
  box-shadow: 0 0 10px -2px color-mix(in srgb, var(--accent) 60%, transparent);
  transform-origin: 0 50%;
}
.fall__row--html { --a: 0; --c: 0.2; --w: 35%; --fall: fall-html; }
.fall__row--css { --a: 0.17; --c: 0.33; --w: 25%; --fall: fall-css; }
.fall__row--font { --a: 0.17; --c: 0.42; --w: 20%; --fall: fall-font; }
.fall__row--js { --a: 0.19; --c: 0.4; --w: 30%; --fall: fall-js; }
.fall__row--img { --a: 0.5; --c: 0.84; --w: 18%; --fall: fall-img; }
.fall__overlay { position: absolute; top: 0; bottom: 0; left: calc(var(--name) + var(--gap)); right: 0; pointer-events: none; }
.fall__mark { position: absolute; top: 1.35rem; bottom: 0; left: 36%; border-left: 1px dashed color-mix(in srgb, var(--accent) 75%, transparent); }
.fall__mark .lab { position: absolute; bottom: calc(100% + 0.2rem); left: 0; color: var(--accent); white-space: nowrap; transform: translateX(-50%); }
.fall__cursor { position: absolute; top: 1.6rem; bottom: 0; left: 0; right: 0; opacity: 0; }
.fall__cursor::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 1px; background: #fff; box-shadow: 0 0 8px rgba(255, 255, 255, 0.7); }
.fall__budget { display: grid; gap: 0.55rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.fall__budget > .lab { color: var(--text-2); }
.fall__meter { position: relative; height: 0.75rem; border-radius: 99px; background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.08) 0 1px, transparent 1px 5%), rgba(255, 255, 255, 0.04); }
/* The heaviest page's first load from tools/budgets.mjs, on a 0-200 KB scale
   with the 150 KB budget at 75%. budgets.mjs warns when this drifts. */
.fall__fill { position: absolute; top: 0; bottom: 0; left: 0; width: 65%; border-radius: inherit; background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 35%, transparent), var(--accent)); box-shadow: 0 0 14px -2px var(--accent); transform-origin: 0 50%; }
.fall__limit { position: absolute; top: -0.4rem; bottom: -0.4rem; left: 75%; width: 2px; border-radius: 2px; background: var(--text-1); }
.fall__limit-label { position: relative; height: 1.2rem; }
.fall__limit-label .lab { position: absolute; top: 0; left: 75%; color: var(--text-1); white-space: nowrap; transform: translateX(-50%); }
@media (max-width: 699.98px) { .fall { --name: 4.25rem; --gap: 0.6rem; } }

/* Contact and thank-you: the three next steps, joined by a line that a
   light runs down. */
.next-steps li:nth-child(2) { --i: 1; }
.next-steps li:nth-child(3) { --i: 2; }
.next-steps li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0.6rem; top: 1.55rem; bottom: -0.75rem;
  width: 1px;
  background:
    linear-gradient(180deg, transparent, var(--accent), transparent) 0 -150% / 100% 60% no-repeat,
    linear-gradient(180deg, color-mix(in srgb, var(--accent) 55%, transparent), var(--line));
}

/* Location cards: a slow radar sweep and pings from the pin. */
.instrument .radar { opacity: 0; transform-origin: 160px 110px; }
.instrument .radar-ping { fill: none; stroke: currentColor; stroke-width: 1; opacity: 0; transform-origin: 160px 110px; }
.mapcard .radar { opacity: 0; transform-origin: 200px 150px; }
.mapcard .radar-ping { fill: none; stroke: currentColor; stroke-width: 1; opacity: 0; transform-origin: 200px 150px; }

/* Contact: the location map. A drawing until the visitor asks for the live
   map, so nothing reaches Google before that click. Then Google's embed
   loads in place, is revealed from the pin, and is darkened to sit on the
   page. Without scripts, the card links out to Google Maps instead. */
.mapcard { position: relative; isolation: isolate; display: grid; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius); background: #0A0A0E; box-shadow: 0 32px 80px -44px rgba(0, 0, 0, 0.95); }
.mapcard::before { content: ""; position: absolute; top: 0; left: var(--radius); right: var(--radius); z-index: 2; height: 1px; background: linear-gradient(90deg, transparent, var(--accent) 25%, var(--accent) 75%, transparent); opacity: 0.55; pointer-events: none; }
.mapcard__bar { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.5rem 1rem; padding: 0.95rem 1.15rem; border-bottom: 1px solid var(--line); }
.mapcard__bar .lab:first-child { color: var(--accent); white-space: pre; }
.mapcard__state { display: inline-flex; align-items: center; gap: 0.5rem; }
.mapcard__state::before { content: ""; width: 6px; height: 6px; flex: none; border-radius: 50%; background: var(--text-3); }
.mapcard.is-map .mapcard__state::before { background: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 24%, transparent); }
.mapcard__view { position: relative; aspect-ratio: 4 / 3; overflow: hidden; }
.mapcard__art { position: absolute; inset: 0; width: 100%; height: 100%; color: var(--accent); --sw: 1.1; --sw-faint: 0.8; }
.mapcard__veil { position: absolute; inset: auto 0 0; display: grid; justify-items: center; gap: 0.6rem; padding: 3rem 1.25rem 1.35rem; background: linear-gradient(180deg, transparent, rgba(10, 10, 14, 0.94) 52%); text-align: center; }
.mapcard__load { background: rgba(14, 14, 19, 0.92); }
.mapcard__load:disabled { cursor: progress; }
.mapcard__note { max-width: 36ch; color: var(--text-3); font-size: 0.8125rem; line-height: 1.45; }
.mapcard__out { display: none; background: rgba(14, 14, 19, 0.92); }
.mapcard.is-failed .mapcard__out { display: inline-flex; }
.mapcard__frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; opacity: 0; filter: invert(93%) hue-rotate(182deg) saturate(0.45) brightness(0.86) contrast(1.08); }
.mapcard.is-map .mapcard__frame { opacity: 1; }
.mapcard.is-map :is(.mapcard__art, .mapcard__veil) { visibility: hidden; opacity: 0; }
/* While Google answers, the button shows a turning ring. */
.mapcard.is-loading .mapcard__load::after { content: ""; width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; }
@media (max-width: 599.98px) { .mapcard__view { aspect-ratio: 1; } }
/* Phones: full-width buttons, like every other call to action there. */
@media (max-width: 767.98px) { .mapcard__load, .mapcard__out { width: 100%; min-height: 48px; } }
@media (scripting: none) {
  .mapcard__load, .mapcard__note { display: none; }
  .mapcard__out { display: inline-flex; }
}

/* Diagrams: entrances, then loops that start from the still drawing. */
@keyframes dg-pop { from { opacity: 0; transform: scale(0.4); } to { opacity: 1; transform: none; } }
@keyframes dg-lift { from { opacity: 0; transform: translateY(10px) scale(0.97); } to { opacity: 1; transform: none; } }
@keyframes dg-grow { from { scale: 0 1; } to { scale: 1 1; } }
@keyframes dg-grow-y { from { scale: 1 0; } to { scale: 1 1; } }
@keyframes dg-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes dg-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes dg-wipe { from { clip-path: inset(0 100% 0 0 round 6px); } to { clip-path: inset(0 0 0 0 round 6px); } }
@keyframes dg-ring { 0% { transform: scale(0.7); opacity: 0.9; } 18%, 100% { transform: scale(2.1); opacity: 0; } }
@keyframes journey-ping { 0% { transform: scale(1); opacity: 0.9; } 18%, 100% { transform: scale(2.7); opacity: 0; } }
@keyframes dg-spin { to { transform: rotate(360deg); } }
@keyframes dg-flash { 0% { opacity: 0; } 4% { opacity: 1; } 18%, 100% { opacity: 0; } }
@keyframes dg-breathe { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }
@keyframes beam-x { 0% { transform: translateX(-100%); opacity: 1; } 60% { transform: translateX(40%); opacity: 1; } 60.1%, 100% { transform: translateX(40%); opacity: 0; } }
@keyframes beam-y { 0% { transform: translateY(-100%); opacity: 1; } 60% { transform: translateY(40%); opacity: 1; } 60.1%, 100% { transform: translateY(40%); opacity: 0; } }
@keyframes needle-in { from { transform: rotate(-120deg); } 70% { transform: rotate(calc(var(--rest) + 7deg)); } to { transform: rotate(var(--rest)); } }
@keyframes needle-idle { 0%, 100% { transform: rotate(var(--rest)); } 50% { transform: rotate(calc(var(--rest) + 2.5deg)); } }
@keyframes gauge-scan { 0% { stroke-dashoffset: 6; opacity: 1; } 55% { stroke-dashoffset: -100; opacity: 1; } 55.1%, 100% { stroke-dashoffset: -100; opacity: 0; } }
@keyframes funnel-x { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 1; } }
@keyframes funnel-y { from { transform: translateY(0); opacity: 1; } to { transform: translateY(100%); opacity: 1; } }
@keyframes spark { 0%, 100% { transform: scale(0.75); opacity: 0.35; } 50% { transform: scale(1.3); opacity: 0.85; } }
@keyframes fm-dash { 0% { stroke-dashoffset: 25; } 20%, 100% { stroke-dashoffset: -105; } }
@keyframes fm-sweep { 0% { transform: translateX(-100%); } 10%, 100% { transform: translateX(100%); } }
@keyframes river { to { stroke-dashoffset: 160; } }
@keyframes seo-ping { 0% { transform: scale(0.12); opacity: 0; } 3% { opacity: 0.8; } 22% { transform: scale(1); opacity: 0; } 25% { transform: scale(0.12); opacity: 0; } 28% { opacity: 0.8; } 47%, 100% { transform: scale(1); opacity: 0; } }
@keyframes seo-set { 0%, 46% { opacity: 1; } 52%, 96% { opacity: 0.25; } 100% { opacity: 1; } }
@keyframes open-glow { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }
@keyframes playhead { 0% { transform: translateX(0); opacity: 0; } 4% { opacity: 1; } 76% { transform: translateX(100%); opacity: 1; } 80%, 100% { transform: translateX(100%); opacity: 0; } }
@keyframes step-lit { 0%, 14% { color: var(--accent); } 24%, 100% { color: var(--text-1); } }
@keyframes fall-html { 0% { scale: 1 1; opacity: 1; } 5% { scale: 1 1; opacity: 0; } 6% { scale: 0 1; opacity: 0; } 7%, 10% { scale: 0 1; opacity: 1; } 22%, 100% { scale: 1 1; opacity: 1; } }
@keyframes fall-css { 0% { scale: 1 1; opacity: 1; } 5% { scale: 1 1; opacity: 0; } 6% { scale: 0 1; opacity: 0; } 7%, 20.2% { scale: 0 1; opacity: 1; } 29.8%, 100% { scale: 1 1; opacity: 1; } }
@keyframes fall-font { 0% { scale: 1 1; opacity: 1; } 5% { scale: 1 1; opacity: 0; } 6% { scale: 0 1; opacity: 0; } 7%, 20.2% { scale: 0 1; opacity: 1; } 35.2%, 100% { scale: 1 1; opacity: 1; } }
@keyframes fall-js { 0% { scale: 1 1; opacity: 1; } 5% { scale: 1 1; opacity: 0; } 6% { scale: 0 1; opacity: 0; } 7%, 21.4% { scale: 0 1; opacity: 1; } 34%, 100% { scale: 1 1; opacity: 1; } }
@keyframes fall-img { 0% { scale: 1 1; opacity: 1; } 5% { scale: 1 1; opacity: 0; } 6% { scale: 0 1; opacity: 0; } 7%, 40% { scale: 0 1; opacity: 1; } 60.4%, 100% { scale: 1 1; opacity: 1; } }
@keyframes fall-mark { 0% { opacity: 1; } 5%, 31% { opacity: 0.2; } 33%, 100% { opacity: 1; } }
@keyframes fall-cursor { 0%, 10% { transform: translateX(0); opacity: 0; } 11% { opacity: 1; } 70% { transform: translateX(100%); opacity: 1; } 73%, 100% { transform: translateX(100%); opacity: 0; } }
@keyframes next-glow { 0% { background-position: 0 -150%, 0 0; } 45%, 100% { background-position: 0 250%, 0 0; } }
@keyframes radar-ping { from { transform: scale(0.15); opacity: 0.7; } to { transform: scale(1); opacity: 0; } }

/* Motion: only when the visitor has not asked for reduced motion, in
   their settings or with the footer switch (see site.css). */
@media (prefers-reduced-motion: no-preference) {
  :root:not([data-motion="reduce"]) {
    /* Diagrams. Each draws itself in once when revealed; its loop runs
       while the panel is live. The time-zone bands and London's hours
       slide when the season switch changes the clocks. */
    & .journey.is-in .journey__node { animation: dg-pop 420ms var(--ease-out) both; animation-delay: calc(var(--k, 0) * 80ms + 120ms); }
    & .journey.is-in .journey__move { animation: reveal 520ms var(--ease-out) both; animation-delay: calc(var(--k, 0) * 80ms + 160ms); }
    & .journey.is-in .journey__move::before { transform-origin: 50% 0; animation: line-draw-y 520ms var(--ease-out) both; animation-delay: calc(var(--k, 0) * 80ms + 120ms); }
    & .journey .is-live .journey__beam::after { animation: beam-y 7s linear infinite; }
    & .journey .is-live .journey__node::after { animation: journey-ping 7s var(--ease-out) infinite; animation-delay: var(--at, 0s); }
    @media (min-width: 900px) {
      & .journey.is-in .journey__track::before { transform-origin: 0 50%; animation: line-draw-x 700ms var(--ease-out) 80ms both; }
      & .journey .is-live .journey__beam::after { animation-name: beam-x; }
    }

    & .dg.is-in .gauge :is(.gauge__zone, .gauge__glow, .gauge__marks) { animation: dg-fade 500ms var(--ease-out) both; animation-delay: calc(var(--g, 0) * 90ms); }
    & .dg.is-in .gauge__needle { animation: needle-in 700ms cubic-bezier(0.34, 1.3, 0.64, 1) both; animation-delay: calc(var(--g, 0) * 90ms + 150ms); }
    & .is-live .gauge__needle { animation: needle-idle 4.5s ease-in-out infinite; animation-delay: calc(var(--g, 0) * -1.4s); }
    & .dg.is-in .is-live .gauge__needle { animation: needle-in 700ms cubic-bezier(0.34, 1.3, 0.64, 1) calc(var(--g, 0) * 90ms + 150ms) both, needle-idle 4.5s ease-in-out calc(var(--g, 0) * 90ms + 900ms) infinite; }
    & .is-live .gauge__scan { animation: gauge-scan 3.6s var(--ease-out) infinite; animation-delay: calc(var(--g, 0) * 0.45s + 0.8s); }

    & .dg.is-in .funnel__shape { transform-origin: 0 50%; animation: dg-grow 700ms var(--ease-out) both; }
    & .dg.is-in .funnel__stages li { animation: reveal 520ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * 70ms + 260ms); }
    & .is-live .funnel__flow i { animation: funnel-x var(--t, 4.5s) linear var(--d, 0s) infinite; }
    & .is-live .funnel__spark { animation: spark 2.2s ease-in-out infinite; }
    @media (max-width: 759.98px) {
      & .dg.is-in .funnel__shape { transform-origin: 50% 0; animation-name: dg-grow-y; }
      & .is-live .funnel__flow i { animation-name: funnel-y; }
    }

    & .dg.is-in :is(.flowmap__chip, .flowmap__node) { animation: dg-lift 480ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * 70ms + 80ms); }
    & .is-live .flowmap__rail::after { animation: beam-y 6s linear infinite; }
    & .is-live .flowmap__core::before { animation: dg-spin 14s linear infinite; }
    @media (min-width: 1024px) {
      & .is-live .flowmap__pulse { animation: fm-dash 6s linear infinite; }
      & .is-live .flowmap__pulse:nth-of-type(2) { animation-delay: 0.1s; }
      & .is-live .flowmap__pulse:nth-of-type(3) { animation-delay: 0.25s; }
      & .is-live .flowmap__pulse:nth-of-type(4) { animation-delay: 0.4s; }
      & .is-live .flowmap__fan--out .flowmap__pulse:nth-of-type(2) { animation-delay: 2.45s; }
      & .is-live .flowmap__fan--out .flowmap__pulse:nth-of-type(3) { animation-delay: 2.6s; }
      & .is-live .flowmap__fan--out .flowmap__pulse:nth-of-type(4) { animation-delay: 2.75s; }
      & .is-live .flowmap__link::after { animation: fm-sweep 6s linear 1.7s infinite; }
      & .is-live :is(.flowmap__chip, .flowmap__node)::after { animation: dg-flash 6s ease-out infinite; animation-delay: var(--at, 0s); }
      & .is-live .flowmap__core::after { animation: dg-ring 6s var(--ease-out) 1.45s infinite; }
    }

    & .dg.is-in .seo-map__ring { transform-box: fill-box; transform-origin: center; animation: dg-pop 640ms var(--ease-out) both; }
    & .dg.is-in .seo-map__ring--b { animation-delay: 140ms; }
    & .is-live .seo-map__water { animation: river 7s linear infinite; }
    & .is-live .seo-map__ping { animation: seo-ping 8s var(--ease-out) infinite; }
    & .is-live .seo-map__ping--b { animation-delay: -4s; }
    & .is-live .seo-set--a { animation: seo-set 8s ease-in-out infinite; }
    & .is-live .seo-set--b { animation: seo-set 8s ease-in-out -4s infinite; }

    & :is(.tz__band, .tz__slide) { transition: transform 700ms var(--ease-out); }
    & .dg.is-in .tz__band { animation: dg-wipe 600ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * 70ms + 120ms); }
    & .is-live .tz.is-now .tz__band.is-open::after { animation: open-glow 2.4s ease-in-out infinite; }
    & .is-live .tz__needle::after { animation: dg-breathe 2s ease-in-out infinite; }

    & .dg.is-in .gantt__work { animation: dg-grow 650ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * 70ms + 120ms); }
    & .dg.is-in .gantt__window { animation: dg-fade 450ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * 70ms + 560ms); }
    & .is-live .gantt__playhead { animation: playhead 9s cubic-bezier(0.45, 0, 0.55, 1) 1.2s infinite; }

    & .dg.is-in .cycle__track { stroke-dasharray: 1; animation: dg-draw 700ms var(--ease-out) both; }
    & .dg.is-in .cycle__node { transform-box: fill-box; transform-origin: center; animation: dg-pop 420ms var(--ease-out) 320ms both; }
    & .is-live .cycle__orbit { opacity: 1; animation: dg-spin 8s linear infinite; }
    & .is-live .cycle__ping { animation: dg-ring 8s var(--ease-out) infinite; animation-delay: var(--at, 0s); }
    & .is-live .cycle__step strong { animation: step-lit 8s ease-out infinite; animation-delay: var(--at, 0s); }

    & .dg.is-in .fall__bar { animation: dg-grow 600ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * 90ms + 100ms); }
    & .dg.is-in .fall__fill { animation: dg-grow 900ms var(--ease-out) 300ms both; }
    & .is-live .fall__bar, & .dg.is-in .is-live .fall__bar { animation: var(--fall) 7s linear infinite; }
    & .is-live .fall__mark { animation: fall-mark 7s linear infinite; }
    & .is-live .fall__cursor { animation: fall-cursor 7s linear infinite; }

    & .next-steps.is-live li:not(:last-child)::after { animation: next-glow 4.5s ease-in-out infinite; animation-delay: calc(var(--i, 0) * 1.5s); }

    & :is(.instrument, .mapcard:not(.is-map)).is-live .radar { opacity: 1; animation: dg-spin 6s linear infinite; }
    & :is(.instrument, .mapcard:not(.is-map)).is-live .radar-ping { animation: radar-ping 3.2s var(--ease-out) infinite; }
    & :is(.instrument, .mapcard:not(.is-map)).is-live .radar-ping--2 { animation-delay: 1.6s; }

    /* The map: the radar quickens while Google answers, then the live map
       opens out from the pin as the drawing and button fade away. */
    & .mapcard.is-loading.is-live .radar { animation-duration: 1.4s; }
    & .mapcard.is-loading .mapcard__load::after { animation: dg-spin 800ms linear infinite; }
    & .mapcard__frame { clip-path: circle(0% at 50% 50%); transition: clip-path 1000ms var(--ease-out), opacity 240ms var(--ease-out); }
    & .mapcard.is-map .mapcard__frame { clip-path: circle(75% at 50% 50%); }
    & .mapcard__veil { transition: opacity 280ms var(--ease-out), visibility 0s linear 280ms; }
    & .mapcard__art { transition: opacity 400ms var(--ease-out) 600ms, visibility 0s linear 1000ms; }
  }
}

@media (forced-colors: active) {
  /* Diagrams keep their own colours: they are drawings, described in text. */
  .dg__panel, .instrument .art { forced-color-adjust: none; }
  .mapcard__frame { filter: none; }
}

@media print {
  .dg__panel { display: none !important; }
}
