/*
 * The looping explainer icons.
 *
 * Four icons, four loops, each acting out the word underneath it. Timings are
 * deliberately slow and staggered by a fraction of a second so the four tiles
 * never pulse in unison — a row of icons all firing together reads as a glitch
 * rather than as motion.
 *
 * Every animation is a transform or a dash offset, so none of them trigger
 * layout, and all of them stop under prefers-reduced-motion.
 */

.ai {
  overflow: visible;
}

/* ---------------- erase ---------------- */
/* A head sweeps across the medium and the three lines of data vanish behind
   it, one after another, then come back so the loop can run again. */

.ai-erase .ai-head {
  animation: ai-sweep 4s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.ai-erase .ai-data path {
  transform-origin: 6px center;
}
.ai-erase .ai-data-1 {
  animation: ai-wipe 4s linear infinite;
  animation-delay: 0.55s;
}
.ai-erase .ai-data-2 {
  animation: ai-wipe 4s linear infinite;
  animation-delay: 0.95s;
}
.ai-erase .ai-data-3 {
  animation: ai-wipe 4s linear infinite;
  animation-delay: 1.35s;
}

@keyframes ai-sweep {
  0% {
    transform: translateX(0);
  }
  45% {
    transform: translateX(16.5px);
  }
  60% {
    transform: translateX(16.5px);
    opacity: 1;
  }
  70% {
    opacity: 0;
  }
  71% {
    transform: translateX(0);
    opacity: 0;
  }
  85% {
    opacity: 1;
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

@keyframes ai-wipe {
  0%,
  4% {
    opacity: 1;
    transform: scaleX(1);
  }
  14%,
  70% {
    opacity: 0;
    transform: scaleX(0);
  }
  85%,
  100% {
    opacity: 1;
    transform: scaleX(1);
  }
}

/* ---------------- verify ---------------- */
/* The check draws itself inside the shield, holds long enough to be read, then
   clears and draws again. */

.ai-verify .ai-check {
  stroke-dasharray: 1;
  animation: ai-draw 3.2s ease-in-out infinite;
}

@keyframes ai-draw {
  0% {
    stroke-dashoffset: 1;
  }
  30%,
  72% {
    stroke-dashoffset: 0;
  }
  88%,
  100% {
    stroke-dashoffset: 1;
  }
}

/* ---------------- diagnose ---------------- */
/* A short segment of the trace travels the whole path, the way a reading
   crosses a monitor. */

.ai-diagnose .ai-pulse {
  stroke-dasharray: 0.34 0.66;
  animation: ai-trace 2.6s linear infinite;
}

@keyframes ai-trace {
  0% {
    stroke-dashoffset: 1;
  }
  100% {
    stroke-dashoffset: -0.34;
  }
}

/* ---------------- certify ---------------- */
/* The seal ring turns continuously; the mark inside is stamped on, held, and
   lifted off. */

.ai-certify .ai-ring {
  transform-origin: 12px 9.5px;
  animation: ai-turn 9s linear infinite;
}
.ai-certify .ai-stamp {
  transform-origin: 12px 9.5px;
  animation: ai-stamp 3.6s ease-in-out infinite;
}

@keyframes ai-turn {
  to {
    transform: rotate(360deg);
  }
}

@keyframes ai-stamp {
  0%,
  8% {
    opacity: 0;
    transform: scale(0.4);
  }
  20% {
    opacity: 1;
    transform: scale(1.12);
  }
  28%,
  74% {
    opacity: 1;
    transform: scale(1);
  }
  88%,
  100% {
    opacity: 0;
    transform: scale(0.4);
  }
}

/* ================================================================== */
/* platform diagram                                                    */
/* ================================================================== */

.ds-dia-lead {
  max-width: 78ch;
  margin: -22px 0 34px;
  font-size: 17px;
  line-height: 1.7;
  color: var(--ds-muted);
}
.ds-diagram {
  margin-top: 8px;
}
@media (max-width: 767px) {
  .ds-dia-lead {
    margin: -14px 0 26px;
    font-size: 16px;
  }
}
.ds-dia-wide {
  display: block;
  width: 100%;
  height: auto;
}
.ds-dia-tall {
  display: none;
}

/* ---- the six input cards ---- */
.ds-dia-node rect {
  fill: #fff;
  stroke: var(--ds-line);
  stroke-width: 1;
}
.ds-dia-node text {
  font-family: inherit;
  font-size: 18px;
  font-weight: 600;
  fill: var(--ds-ink);
}
.ds-dia-sub {
  font-size: 14.5px !important;
  font-weight: 500 !important;
  fill: var(--ds-muted) !important;
}

/* ---- the glyphs ----
   Drawn from the same 24-grid geometry as the rest of the icon set, so the
   diagram is not a second, slightly different drawing style sitting inside the
   page. Stroke width is set on the group in the component, because a transform
   scales the stroke with the path. */
.ds-dia-glyph {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The tiles are <rect>s inside .ds-dia-node / .ds-dia-hub / .ds-dia-outcard,
   so each one has to out-specify that group's own rect fill. */
.ds-dia-node .ds-dia-tile {
  /* Not --ds-teal-wash: the band this diagram sits on is already that colour,
     so the tile disappeared into both the card and the ground behind it. */
  fill: rgba(0, 150, 136, 0.1);
  stroke: none;
}
.ds-dia-node .ds-dia-glyph {
  stroke: var(--ds-teal);
}
.ds-dia-hub .ds-dia-tile-onDark {
  fill: rgba(255, 255, 255, 0.18);
  stroke: none;
}
.ds-dia-hub .ds-dia-glyph {
  stroke: #fff;
}
.ds-dia-outcard .ds-dia-tile-onInk {
  fill: rgba(255, 255, 255, 0.12);
  stroke: none;
}
.ds-dia-outcard .ds-dia-glyph {
  stroke: #4fd6c7;
}
/* Each card lifts as the pulse behind it reaches the hub, one after another. */
.ds-dia-node {
  animation: dia-node 4.4s ease-in-out infinite;
}
/* The dip is shallow on purpose. Taken much below this the card stops reading
   as "waiting its turn" and starts reading as "disabled". */
@keyframes dia-node {
  0%,
  10% {
    opacity: 0.86;
  }
  18%,
  30% {
    opacity: 1;
  }
  46%,
  100% {
    opacity: 0.92;
  }
}

/* ---- connectors ---- */
.ds-dia-links {
  stroke: var(--ds-teal);
}
/* The always-there rail. */
.ds-dia-rail {
  stroke-width: 1.5;
  opacity: 0.28;
}
/* The travelling pulse, brighter and thicker than the rail it runs on. */
.ds-dia-pulse {
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 0.16 0.84;
  animation: dia-flow 4.4s linear infinite;
}
/* The hub-to-certificate leg runs on its own beat, after the inputs. */
.ds-dia-out {
  animation-delay: 1.5s;
}
@keyframes dia-flow {
  0% {
    stroke-dashoffset: 1;
  }
  60%,
  100% {
    stroke-dashoffset: -0.16;
  }
}

/* ---- the hub ---- */
.ds-dia-hub rect {
  fill: var(--ds-teal);
}
.ds-dia-hub-halo {
  fill: var(--ds-teal);
  opacity: 0.14;
  animation: dia-halo 4.4s ease-in-out infinite;
}
@keyframes dia-halo {
  0%,
  40% {
    opacity: 0.1;
    transform: scale(1);
  }
  55% {
    opacity: 0.26;
  }
  75%,
  100% {
    opacity: 0.1;
    transform: scale(1);
  }
}
.ds-dia-hub-halo {
  transform-box: fill-box;
  transform-origin: center;
}
.ds-dia-hub text {
  font-family: inherit;
  font-size: 26px;
  font-weight: 600;
  fill: #fff;
}
.ds-dia-hubsub {
  font-size: 15px !important;
  font-weight: 500 !important;
  fill: rgba(255, 255, 255, 0.72) !important;
}

/* ---- the rings, the joint and the ports ---- */

/* Three dashed rings behind the hub, breathing very slowly. Without them the
   six curves appear to stop in empty space just short of the panel. */
.ds-dia-rings circle {
  stroke: var(--ds-teal);
  stroke-width: 1;
  stroke-dasharray: 2 10;
  opacity: 0.16;
  animation: dia-ring 6.6s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}
@keyframes dia-ring {
  0%,
  100% {
    opacity: 0.1;
    transform: scale(0.985);
  }
  50% {
    opacity: 0.26;
    transform: scale(1);
  }
}

/* The point every connector arrives at. */
.ds-dia-joint {
  fill: var(--ds-teal);
  animation: dia-joint 4.4s ease-in-out infinite;
}
@keyframes dia-joint {
  0%,
  35% {
    opacity: 0.45;
  }
  50% {
    opacity: 1;
  }
  70%,
  100% {
    opacity: 0.55;
  }
}

/* Where a line leaves its card. Filled white with a teal ring so it reads as a
   socket on the card rather than a blob on the line. */
.ds-dia-port {
  fill: #fff;
  stroke: var(--ds-teal);
  stroke-width: 2;
}

/* ---- inside the hub ---- */

.ds-dia-rule {
  stroke: rgba(255, 255, 255, 0.28);
  stroke-width: 1;
}
.ds-dia-ruledot {
  fill: rgba(255, 255, 255, 0.55);
}

/* ---- the output card ---- */
.ds-dia-outcard rect {
  fill: var(--ds-ink);
}
.ds-dia-outcard text {
  font-family: inherit;
  font-size: 19px;
  font-weight: 600;
  fill: #fff;
}
.ds-dia-outtitle {
  font-size: 19px !important;
  letter-spacing: 0.01em;
}
/* One ticked line per thing the document carries. The disc is drawn rather
   than borrowed from the icon set because at 18px across it needs its own,
   heavier tick to stay readable. */
.ds-dia-check circle {
  fill: rgba(79, 214, 199, 0.16);
}
.ds-dia-tick {
  fill: none;
  stroke: #4fd6c7;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ds-dia-check text {
  font-size: 15.5px !important;
  font-weight: 500 !important;
  fill: rgba(255, 255, 255, 0.82) !important;
}
.ds-dia-outcard .ds-dia-sub {
  fill: rgba(255, 255, 255, 0.66) !important;
}
/* Stamped on once the flow has reached it, then held. */
.ds-dia-outcard {
  animation: dia-out 4.4s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: left center;
}
/* Same reasoning as the input cards: at 0.4 the ink card washed out to grey
   and looked broken rather than pending. It only needs to lift, not appear. */
@keyframes dia-out {
  0%,
  52% {
    opacity: 0.88;
    transform: scale(0.985);
  }
  64% {
    opacity: 1;
    transform: scale(1.02);
  }
  72%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* ---- the capability strip ---- */

/* Five things that are true of every run, sitting under the drawing rather
   than inside it: they are equal and unrelated to each other, so the SVG would
   only take away their ability to wrap. */
.ds-dia-caps {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 16px;
  margin: 48px 0 0;
  padding: 0;
  list-style: none;
  background: transparent;
  border: none;
}
.ds-dia-caps li {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  justify-content: flex-start;
  gap: 14px;
  padding: 24px 16px 22px;
  background: #ffffff;
  border: 1px solid var(--ds-line);
  border-radius: 18px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.02);
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.ds-dia-caps li:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(0, 150, 136, 0.08);
  border-color: rgba(0, 150, 136, 0.3);
}
.ds-dia-caps-ico {
  position: relative;
  display: block;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: rgba(0, 150, 136, 0.08);
  color: var(--ds-teal);
  flex-shrink: 0;
  margin: 0 auto;
  transition: background-color 0.25s ease, color 0.25s ease;
}
.ds-dia-caps li:hover .ds-dia-caps-ico {
  background: var(--ds-teal);
  color: #ffffff;
}
.ds-dia-caps-ico svg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 24px;
  height: 24px;
  margin: 0 !important;
  padding: 0 !important;
  display: block;
}
.ds-dia-caps strong {
  display: block;
  margin-bottom: 4px;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--ds-ink);
  letter-spacing: -0.01em;
}
.ds-dia-caps span {
  display: block;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--ds-muted);
}

/* Responsive grid */
@media (max-width: 1199px) {
  .ds-dia-caps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
  }
}
@media (max-width: 767px) {
  .ds-dia-caps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-top: 32px;
    gap: 12px;
  }
  .ds-dia-caps li {
    padding: 18px 12px;
  }
}
@media (max-width: 479px) {
  .ds-dia-caps {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- narrow: the same nodes, stacked ---- */
@media (max-width: 767px) {
  .ds-dia-wide {
    display: none;
  }
  .ds-dia-tall {
    display: block;
  }
  .ds-dia-tall-inputs {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .ds-dia-tall-inputs li {
    padding: 14px;
    border: 1px solid var(--ds-line);
    border-radius: 14px;
    background: #fff;
  }
  .ds-dia-tall-inputs strong {
    display: block;
    font-size: 14.5px;
    font-weight: 600;
    color: var(--ds-ink);
  }
  .ds-dia-tall-sub {
    font-size: 12.5px;
    color: var(--ds-muted);
  }
  /* The same tile as the wide drawing, at the size a 2-up card can carry. */
  .ds-dia-tall-ico {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    margin-bottom: 10px;
    border-radius: 10px;
    background: rgba(0, 150, 136, 0.1);
    color: var(--ds-teal);
  }
  .ds-dia-tall-arrow {
    display: grid;
    place-items: center;
    height: 34px;
  }
  .ds-dia-tall-arrow span {
    width: 2px;
    height: 100%;
    background: linear-gradient(var(--ds-teal), transparent);
    animation: dia-drip 1.8s linear infinite;
  }
  @keyframes dia-drip {
    0% {
      opacity: 0.25;
      transform: scaleY(0.2);
      transform-origin: top;
    }
    60% {
      opacity: 1;
      transform: scaleY(1);
      transform-origin: top;
    }
    100% {
      opacity: 0.25;
      transform: scaleY(1);
      transform-origin: bottom;
    }
  }
  .ds-dia-tall-hub,
  .ds-dia-tall-out {
    padding: 18px;
    border-radius: 16px;
    text-align: center;
  }
  .ds-dia-tall-hub {
    background: var(--ds-teal);
  }
  .ds-dia-tall-out {
    background: var(--ds-ink);
  }
  .ds-dia-tall-hub strong,
  .ds-dia-tall-out strong {
    display: block;
    font-size: 17px;
    font-weight: 600;
    color: #fff;
  }
  /* The same four lines the wide card ticks off. */
  .ds-dia-tall-checks {
    margin: 12px 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 7px;
    text-align: left;
  }
  .ds-dia-tall-checks li {
    position: relative;
    padding-left: 22px;
    font-size: 13px;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.72);
  }
  .ds-dia-tall-checks li::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 6px;
    width: 8px;
    height: 5px;
    border-left: 2px solid #4fd6c7;
    border-bottom: 2px solid #4fd6c7;
    transform: rotate(-45deg);
  }
  .ds-dia-tall-hub .ds-dia-tall-sub,
  .ds-dia-tall-out .ds-dia-tall-sub {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.72);
  }
  /* Centred rather than left-aligned: these two blocks are centred already. */
  .ds-dia-tall-hub .ds-dia-tall-ico,
  .ds-dia-tall-out .ds-dia-tall-ico {
    margin: 0 auto 10px;
    background: rgba(255, 255, 255, 0.16);
    color: #fff;
  }
  .ds-dia-tall-out .ds-dia-tall-ico {
    background: rgba(255, 255, 255, 0.12);
    color: #4fd6c7;
  }
}

/* ------------------------------------------------------------------ */
/* stillness on request                                                */
/* ------------------------------------------------------------------ */

/* Nothing here carries meaning that the still frame does not, so a reader who
   has asked the OS for no animation loses nothing by getting the end state. */
@media (prefers-reduced-motion: reduce) {
  .ai *,
  .ai,
  .ds-diagram *,
  .ds-diagram {
    animation: none !important;
  }
  /* The diagram's still frame is its finished state: everything present, the
     travelling pulse resolved into a solid line along its rail. */
  .ds-dia-pulse {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    stroke-width: 2;
    opacity: 0.55;
  }
  .ds-dia-node,
  .ds-dia-outcard {
    opacity: 1;
    transform: none;
  }
  .ai-verify .ai-check,
  .ai-diagnose .ai-pulse {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }
  .ai-certify .ai-stamp {
    opacity: 1;
    transform: none;
  }
}
