/* ==========================================================================
   Digital Signage page — digital-signage.php
   Built from the client PSD "Rusk Creative 2 Digital signage". Loaded after
   custom.min.css and responsive.css, so equal-specificity rules here win.
   Breakpoints match responsive.css (575.98 / 767.98 / 991.98 / 1199.98), plus
   1500px, where .container widens from 1140px to 1600px.
   The packages section reuses the site's .section-5 package styles as-is.
   ========================================================================== */

/* --- Banner ----------------------------------------------------------------
   Height, ratio and the heading's scale all come from the shared .inner-banner
   rules in responsive.css; background-image rather than the shorthand so those
   rules survive. The photo's bottom edge is the curve into the page, so anchor
   the bottom: on very wide screens the banner is capped at 70vh, and the crop
   should come off the top rather than the curve. */
.digital-signage-banner {
  background-image: url(../images/digital-signage-banner.webp);
  background-position: center bottom;
}

/* --- Section headings ------------------------------------------------------ */
.ds-heading {
  text-align: center;
  margin-bottom: 3.5rem;
}

.ds-heading h2 {
  font-size: 3.4375rem; /* 55px, the services page heading size */
  line-height: 1.1;
  text-wrap: balance;
}

.ds-eyebrow {
  font-family: var(--font-heading);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--secondary);
  margin-bottom: 0.5rem;
}

.ds-heading-sub {
  font-family: var(--font-heading);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.3;
  margin-top: 0.75rem;
}

.ds-heading-text {
  font-size: 1.125rem;
  line-height: 1.65;
  color: #333;
  margin: 1rem auto 0;
  text-wrap: balance;
}

/* --- Intro ----------------------------------------------------------------- */
.ds-intro-media {
  margin: 0;
}

.ds-intro-media img,
.ds-process-figure img {
  display: block;
  width: 100%;
  height: auto;
}

.ds-intro-content {
  max-width: 36rem;
}

.ds-intro-content h2 {
  font-size: 4rem;
  line-height: 1.05;
}

.ds-intro-tagline {
  font-family: var(--font-heading);
  font-size: 1.625rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--black);
  margin: 0.75rem 0 1.25rem;
}

.ds-copy,
.ds-card p,
.ds-step p {
  font-size: 1.125rem;
  line-height: 1.67;
  color: #333;
}

.ds-copy + .ds-copy {
  margin-top: 1.75rem;
}

/* --- Video Showcase --------------------------------------------------------
   Pictures only for now. The category tabs are drawn as in the PSD but aren't
   wired up (no filtering until there are pictures for every category), so they
   are plain list items with no pointer or hover state. */
.ds-showcase .ds-heading {
  margin-bottom: 2.75rem;
}

/* The pill itself comes from .ul-tab in custom.min.css -- the same component
   index.php and portfolio.php use, so every page's tabs look identical. Only
   spacing is set here: this row carries five items, one of them as long as
   "Digital Outdoor Billboards", so unlike the other pages' it has to wrap. */
.ds-tabs {
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  margin: 1.75rem 0 0;
}

/* Hidden by the tab filter. Scoped to the showcase so it can never take out
   anything else, and only ever applied once .js-tabs is present. */
.ds-showcase [hidden] {
  display: none;
}

/* One row that scrolls sideways: three pictures in view, the rest a swipe,
   trackpad scroll or arrow press away. Native overflow with scroll-snap rather
   than a carousel library, so touch and keyboard work without any script. */
.ds-showcase-grid {
  display: flex;
  flex-wrap: nowrap;
  gap: 2.5rem;
  overflow-x: auto;
  /* overflow-x:auto alone computes overflow-y to auto as well, and the tab
     animation's 26px rise would then flash a vertical scrollbar */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.ds-showcase-grid::-webkit-scrollbar {
  display: none;
}

.ds-showcase-item {
  flex: 0 0 calc((100% - 2 * 2.5rem) / 3);
  margin: 0;
  scroll-snap-align: start;
}

.ds-showcase-nav {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 1.75rem;
}

.ds-showcase-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--secondary);
  color: #fff;
  cursor: pointer;
  transition: background 0.25s ease, opacity 0.25s ease;
}

.ds-showcase-arrow svg {
  width: 16px;
  height: 16px;
  fill: currentColor;
}

.ds-showcase-arrow:hover:not(:disabled) {
  background: var(--primary);
}

.ds-showcase-arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

.ds-showcase-item img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 530 / 397;
  object-fit: cover;
  border-radius: 24px;
}

@media (max-width: 1499.98px) {
  .ds-showcase-grid {
    gap: 1.5rem;
  }

  .ds-showcase-item {
    flex-basis: calc((100% - 2 * 1.5rem) / 3);
  }
}

@media (max-width: 991.98px) {
  .ds-showcase-item {
    flex-basis: calc((100% - 1.5rem) / 2);
  }
}

@media (max-width: 767.98px) {
  .ds-tabs {
    gap: 0.5rem;
    margin-top: 1.25rem;
  }

  /* The phone sizing the site gives its tabs, which custom.min.css scopes to
     .section-4. Five pills at the desktop 14px/30px would be unreadable here. */
  .ds-tabs li button {
    padding: 12px 18px;
    font-size: 15px;
  }
}

/* Short of full width, so the edge of the next picture shows and the row
   reads as scrollable. */
@media (max-width: 575.98px) {
  .ds-showcase-item {
    flex-basis: 86%;
  }
}

/* --- What We Create --------------------------------------------------------
   Icon beside the copy, as drawn, while the 1600px container gives each card
   the PSD's ~500px. Narrower than that, the icon moves above the copy (see the
   1499.98px query) rather than wrapping titles like "Promotional Screens". */
.ds-heading--shape {
  position: relative;
}

.ds-shape {
  position: absolute;
  top: -1.5rem;
  right: 0;
  width: 151px;
  height: auto;
}

.ds-create-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2.125rem 2.5rem;
}

.ds-card {
  display: flex;
  align-items: flex-start;
  gap: 1.25rem;
  height: 100%;
  padding: 3rem 2rem 3rem 2.5rem;
  background: var(--white);
  border-radius: 24px;
}

/* No width/height here: each icon renders at the size the PSD draws it, which
   the markup's width/height attributes carry (the files are 2x). */
.ds-card-icon {
  flex: none;
}

/* Title drops level with the icon's lower half, as in the PSD. */
.ds-card-body {
  padding-top: 2.4rem;
}

.ds-card h3 {
  font-size: 1.625rem;
  line-height: 1.25;
  margin-bottom: 0.625rem;
}

/* --- Our Process -----------------------------------------------------------
   Stacked by default: the stand on top, then the four steps in reading order.
   From 1200px it becomes the PSD's diagram, with steps 01/03 left and 02/04
   right, each tied to the stand by a dotted leader. min-width queries here
   because the diagram is the exception, not the base. */
.ds-process-map {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2.5rem 2rem;
  text-align: center;
}

.ds-process-figure {
  grid-column: 1 / -1;
  justify-self: center;
  width: 100%;
  max-width: 380px;
  margin: 0;
}

.ds-step-num {
  display: inline-block;
  font-family: var(--font-heading);
  font-size: 3rem;
  font-weight: 700;
  line-height: 1;
  background: linear-gradient(90deg, #1e08c4, #21c7f7);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.ds-step h3 {
  font-size: 1.75rem;
  line-height: 1.2;
  margin: 0.25rem 0 0.625rem;
}

.ds-step p {
  font-size: 1rem;
  line-height: 1.5;
}

@media (min-width: 1200px) {
  /* Every horizontal length in the diagram is the PSD's pixel value times --s,
     so the leaders still land on the stand's frame when the diagram is scaled
     down for the 1140px container.

     The vertical rhythm is tighter than the PSD at this scale. The copy wraps
     to more lines in the narrower columns, and at the PSD's spacing the lower
     two leaders ran past the bottom of the frame onto the stand's legs. */
  .ds-process-map {
    --s: 0.75;
    --gap: 80px; /* copy edge to the stand image's box */
    --frame-l: 168px; /* image box to the frame, left side (PSD px) */
    --frame-r: 159px; /* image box to the frame, right side (PSD px) */
    --top: 0px; /* first row's drop below the top of the stand */
    --row-gap: 20px;
    --stagger: 24px; /* how much lower the right-hand steps sit */
    grid-template-columns: minmax(0, 1fr) calc(585px * var(--s)) minmax(0, 1fr);
    grid-template-rows: auto auto 1fr;
    gap: var(--row-gap) 0;
    text-align: left;
  }

  .ds-process-figure {
    grid-column: 2;
    grid-row: 1 / -1;
    max-width: none;
  }

  .ds-step {
    position: relative;
    z-index: 1; /* leaders draw over the stand's translucent backdrop */
    max-width: calc(270px + var(--gap));
  }

  .ds-step--1,
  .ds-step--3 {
    grid-column: 1;
    justify-self: end;
    padding-right: var(--gap);
    text-align: right;
  }

  .ds-step--2,
  .ds-step--4 {
    grid-column: 3;
    justify-self: start;
    padding-left: var(--gap);
    /* transform rather than margin, so the offset doesn't also stretch the
       rows the left-hand steps sit in. */
    transform: translateY(var(--stagger));
  }

  .ds-step--1,
  .ds-step--2 {
    grid-row: 1;
    margin-top: var(--top);
  }

  .ds-step--3,
  .ds-step--4 {
    grid-row: 2;
  }

  .ds-step-num {
    font-size: 2.75rem;
  }

  .ds-step h3 {
    position: relative;
    font-size: 1.625rem;
  }

  .ds-step p {
    font-size: 0.9375rem;
    line-height: 1.45;
  }

  /* ::before is the dot beside the title, ::after the leader to the frame. */
  .ds-step h3::before,
  .ds-step h3::after {
    content: "";
    position: absolute;
    top: 50%;
    pointer-events: none;
  }

  .ds-step h3::before {
    width: 13px;
    height: 13px;
    margin-top: -6.5px;
    border-radius: 50%;
    background: var(--black);
  }

  .ds-step h3::after {
    height: 5px;
    margin-top: -2.5px;
    /* Round dots in every browser; a dotted border renders square in Safari. */
    background: radial-gradient(circle, var(--black) 1.6px, transparent 2.1px)
      left center / 9px 5px repeat-x;
  }

  .ds-step--1 h3::before,
  .ds-step--3 h3::before {
    left: calc(100% + 20px);
  }

  .ds-step--2 h3::before,
  .ds-step--4 h3::before {
    right: calc(100% + 20px);
  }

  /* Leader = the rest of the gap + the run into the image as far as the frame,
     times 1/cos(10deg) for the slope. */
  .ds-step--1 h3::after,
  .ds-step--3 h3::after {
    left: calc(100% + 26px);
    width: calc((var(--gap) - 26px + var(--frame-l) * var(--s)) * 1.016);
    transform-origin: left center;
    transform: rotate(10deg);
  }

  .ds-step--2 h3::after,
  .ds-step--4 h3::after {
    right: calc(100% + 26px);
    width: calc((var(--gap) - 26px + var(--frame-r) * var(--s)) * 1.016);
    transform-origin: right center;
    transform: rotate(-10deg);
  }
}

@media (min-width: 1500px) {
  /* Full size, at the PSD's spacing. The row gap is the PSD's 77px less the
     extra height the web type adds to each step, so the leaders land where the
     PSD draws them. */
  .ds-process-map {
    --s: 1;
    --gap: 110px;
    --top: 32px;
    --row-gap: 60px;
    --stagger: 64px;
  }

  .ds-step {
    max-width: calc(360px + var(--gap));
  }

  .ds-step-num {
    font-size: 3.5rem;
  }

  .ds-step h3 {
    font-size: 1.875rem;
  }

  .ds-step p {
    font-size: 1rem;
    line-height: 1.5;
  }
}

/* --- Packages --------------------------------------------------------------
   The site's .section-5 package styles, as on pricing.php. This section shows a
   single category, so it has no tab row -- and on pricing that row is what
   spaces the heading from the cards on phones. */
.ds-packages .ser-pkg > .row {
  justify-content: center; /* two across, the third card centres beneath */
}

/* On phones responsive.css makes .heading-sec `display: contents`, so it has no
   box to carry a margin; its h2 is the flex item that sits above the cards. */
@media (max-width: 767.98px) {
  .ds-packages .heading-sec h2 {
    margin-bottom: 30px; /* the gap the tab row leaves on phones */
  }
}

/* --- Narrower screens ------------------------------------------------------ */
@media (max-width: 1499.98px) {
  .ds-intro-content h2 {
    font-size: 3.4375rem;
  }

  .ds-create-grid {
    gap: 1.5rem;
  }

  .ds-card {
    flex-direction: column;
    padding: 2.25rem 2rem;
  }

  .ds-card-icon {
    width: auto;
    height: 72px;
  }

  .ds-card-body {
    padding-top: 0;
  }

  .ds-card h3 {
    font-size: 1.375rem;
  }

  .ds-card p {
    font-size: 1rem;
  }
}

@media (max-width: 991.98px) {
  .ds-heading {
    margin-bottom: 2.5rem;
  }

  .ds-heading h2,
  .ds-intro-content h2 {
    font-size: 2.5rem;
  }

  /* responsive.css steps the root font size down to 13px here and 12px below
     768px, which takes rem-sized body copy to 12px on a phone. Pinned in px,
     as the services page does for its descriptions. */
  .ds-copy,
  .ds-card p,
  .ds-step p,
  .ds-heading-text {
    font-size: 15px;
  }

  .ds-intro-media {
    max-width: 600px;
    margin: 0 auto 2.5rem;
  }

  .ds-intro-content {
    max-width: none;
  }

  .ds-create-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 767.98px) {
  /* Beside a centred heading there's no room for the accent; lift it clear
     above the heading instead. */
  .ds-shape {
    top: -4.5rem;
    width: 72px;
  }

  /* Phones: centre each card's icon, title and copy (client request). */
  .ds-card {
    align-items: center;
    text-align: center;
  }

  .ds-intro-tagline,
  .ds-card h3 {
    font-size: 18px;
  }
}

@media (max-width: 575.98px) {
  .ds-create-grid,
  .ds-process-map {
    grid-template-columns: 1fr;
  }

  .ds-card {
    padding: 1.75rem 1.5rem;
  }
}

/* --- Copy blocks added with the client's final content ---------------------
   Everything below arrived with the written copy: the showcase's four
   environments, the Complete Content Production section, the closing CTA, and
   the two Start Your Project buttons. Appended rather than merged into the
   sections above so the PSD build stays readable as one piece. */

.ds-btn {
  margin-top: 2rem;
}

/* Sections whose intro runs to two paragraphs. */
.ds-heading-text + .ds-heading-text {
  margin-top: 1rem;
}

/* One long paragraph reads better a little wider than the 30em default. */
.ds-heading-text--wide {
  max-width: 40em;
}

/* --- Video Showcase: the four environments ---------------------------------
   Text blocks, not cards: the pictures above should stay the loudest thing in
   the section, and four white cards would compete with them. */
/* Flex, not grid, for the same reason as the picture row above: when the tabs
   filter this down to one category, a grid would leave it stranded in column 1
   with three empty tracks beside it. */
.ds-audience {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2.5rem;
  margin-top: 3.5rem;
}

.ds-audience-item {
  flex: 0 0 calc((100% - 3 * 2.5rem) / 4);
}

.ds-audience-item h3 {
  position: relative;
  font-size: 1.375rem;
  line-height: 1.25;
  margin-bottom: 0.75rem;
  padding-bottom: 0.75rem;
}

/* Four across, "Digital Outdoor Billboards" is the one title that wraps, and it
   alone pushed its rule and copy below the other three. Reserving two lines on
   every title lines the row back up. Only at the four-column width: narrower,
   the titles sit above their own copy and the reserve would just add a gap. */
@media (min-width: 1200px) {
  .ds-audience-item h3 {
    min-height: calc(2.5em + 0.75rem);
  }
}

.ds-audience-item h3::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 48px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, #1e08c4, #21c7f7);
}

.ds-audience-item p {
  font-size: 1rem;
  line-height: 1.6;
  color: #333;
}

/* A category tab leaves one write-up on its own. At the four-across width it
   would be a quarter-wide column under three pictures, so it gets a readable
   measure, centred, with its rule centred under the title. */
.ds-audience.is-single .ds-audience-item {
  flex-basis: min(100%, 640px);
  text-align: center;
}

.ds-audience.is-single .ds-audience-item h3 {
  min-height: 0;
}

.ds-audience.is-single .ds-audience-item h3::after {
  left: 50%;
  transform: translateX(-50%);
}

/* --- Complete Content Production -------------------------------------------
   Same white card and 24px radius as What We Create, told apart by the
   gradient rule along the top and no icon column. */
.ds-production-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2.125rem 2.5rem;
}

.ds-prod-card {
  position: relative;
  height: 100%;
  padding: 2.75rem 2rem 2.5rem;
  background: var(--white);
  border-radius: 24px;
  overflow: hidden;
}

.ds-prod-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 2rem;
  width: 64px;
  height: 5px;
  border-radius: 0 0 4px 4px;
  background: linear-gradient(90deg, #1e08c4, #21c7f7);
}

.ds-prod-card h3 {
  font-size: 1.5rem;
  line-height: 1.25;
  margin-bottom: 0.75rem;
}

.ds-prod-card p {
  font-size: 1.0625rem;
  line-height: 1.6;
  color: #333;
}

/* --- Closing CTA -----------------------------------------------------------
   The site-wide "Let's Talk" phone heading follows immediately and carries its
   own 5rem top margin, so this section adds no padding of its own below. */
.ds-cta {
  padding-bottom: 0;
}

.ds-cta-heading {
  margin-bottom: 0;
}

@media (max-width: 1499.98px) {
  .ds-production-grid {
    gap: 1.5rem;
  }

  .ds-prod-card {
    padding: 2.25rem 1.75rem 2rem;
  }

  .ds-prod-card::before {
    left: 1.75rem;
  }

  .ds-prod-card h3 {
    font-size: 1.375rem;
  }

  .ds-prod-card p {
    font-size: 1rem;
  }

  .ds-audience {
    gap: 1.75rem;
  }

  .ds-audience-item {
    flex-basis: calc((100% - 3 * 1.75rem) / 4);
  }
}

@media (max-width: 1199.98px) {
  .ds-audience-item {
    flex-basis: calc((100% - 1.75rem) / 2);
  }
}

@media (max-width: 991.98px) {
  .ds-production-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* px for the same reason as the rules above: the root font size steps down
     to 13px here and 12px below 768px. */
  .ds-prod-card p,
  .ds-audience-item p {
    font-size: 15px;
  }

  .ds-audience {
    margin-top: 2.5rem;
  }
}

@media (max-width: 767.98px) {
  .ds-prod-card h3,
  .ds-audience-item h3 {
    font-size: 18px;
  }
}

@media (max-width: 575.98px) {
  .ds-production-grid {
    grid-template-columns: 1fr;
  }

  .ds-audience-item {
    flex-basis: 100%;
  }

  .ds-prod-card {
    padding: 1.75rem 1.5rem;
  }

  .ds-prod-card::before {
    left: 1.5rem;
  }
}

/* Keep the What We Create heading clear of the corner shape: the client's
   "Content Built for Your Digital Displays" is far longer than the PSD's "What
   We Create" and ran underneath it. The heading is centred and the shape is
   151px wide against the right edge, so reserving that plus a gap on BOTH sides
   keeps them apart. px, not rem: responsive.css steps the root size down at
   992px and 768px, which would shrink a rem reserve just as the container gets
   narrow. Below 768px the shape already lifts clear above the heading. */
@media (min-width: 768px) {
  .ds-heading--shape h2 {
    max-width: calc(100% - 2 * (151px + 24px));
    margin-inline: auto;
  }
}

/* --- Our Process: the WebGL sign -------------------------------------------
   js/ds-process-3d.js draws into .ds-stage and adds .is-3d to the figure once
   the first frame is on screen. The photograph is never removed: it keeps
   defining the figure's height, so the section cannot change size when the
   model loads, and it is what remains if WebGL is missing. */
.ds-process-figure {
  position: relative;
}

.ds-stage {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.7s ease;
}

.ds-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.ds-process-figure img {
  transition: opacity 0.7s ease;
}

.ds-process-figure.is-3d img {
  opacity: 0;
}

.ds-process-figure.is-3d .ds-stage {
  opacity: 1;
}

/* The pale blue blob behind the stand is part of the photograph, so it has to
   be redrawn under the canvas or it disappears with it. Same colour the photo
   uses: rgba(45, 181, 224, 0.12). */
.ds-process-figure.is-3d::before {
  content: "";
  position: absolute;
  left: -4%;
  top: 11%;
  width: 108%;
  height: 78%;
  background: rgba(45, 181, 224, 0.12);
  border-radius: 58% 42% 46% 54% / 46% 52% 48% 54%;
}

@media (prefers-reduced-motion: reduce) {
  .ds-stage {
    display: none;
  }
}

/* --- Our Process: step reveal ----------------------------------------------
   Keyed off .js-reveal, which js/ds-process-3d.js adds at run time, so a script
   that is blocked or never loads can't leave anything invisible.

   Only the dot and its leader are handled here, because they are pseudo-
   elements and gsap cannot tween those. The heading, the 01-04 numbers, the
   step titles and their copy are animated by the timeline in
   js/ds-process-3d.js instead -- the step boxes themselves are left alone,
   since from 1200px the diagram positions steps 02 and 04 with a transform
   that an animation here would overwrite. */

@media (min-width: 1200px) {
  /* The dot pops, then its leader draws out towards the stand. scaleX rides on
     top of the rotate the leader already carries, so both values are repeated
     in each state -- dropping the rotate would straighten the line. */
  .ds-process.js-reveal .ds-step h3::before {
    transform: scale(0);
    transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
  }

  .ds-process.js-reveal.is-revealed .ds-step h3::before {
    transform: scale(1);
  }

  .ds-process.js-reveal .ds-step--1 h3::after,
  .ds-process.js-reveal .ds-step--3 h3::after {
    transform: rotate(10deg) scaleX(0);
    transition: transform 1.05s cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  .ds-process.js-reveal.is-revealed .ds-step--1 h3::after,
  .ds-process.js-reveal.is-revealed .ds-step--3 h3::after {
    transform: rotate(10deg) scaleX(1);
  }

  .ds-process.js-reveal .ds-step--2 h3::after,
  .ds-process.js-reveal .ds-step--4 h3::after {
    transform: rotate(-10deg) scaleX(0);
    transition: transform 1.05s cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  .ds-process.js-reveal.is-revealed .ds-step--2 h3::after,
  .ds-process.js-reveal.is-revealed .ds-step--4 h3::after {
    transform: rotate(-10deg) scaleX(1);
  }

  .ds-process.js-reveal .ds-step--1 h3::before { transition-delay: 0.30s; }
  .ds-process.js-reveal .ds-step--1 h3::after  { transition-delay: 0.42s; }
  .ds-process.js-reveal .ds-step--2 h3::before { transition-delay: 0.45s; }
  .ds-process.js-reveal .ds-step--2 h3::after  { transition-delay: 0.57s; }
  .ds-process.js-reveal .ds-step--3 h3::before { transition-delay: 0.60s; }
  .ds-process.js-reveal .ds-step--3 h3::after  { transition-delay: 0.72s; }
  .ds-process.js-reveal .ds-step--4 h3::before { transition-delay: 0.75s; }
  .ds-process.js-reveal .ds-step--4 h3::after  { transition-delay: 0.87s; }
}

/* Reduced motion: show the finished state at once. Note these restate the
   rotate rather than using transform: none, which would straighten the
   leaders. */
@media (prefers-reduced-motion: reduce) and (min-width: 1200px) {
  .ds-process.js-reveal .ds-step h3::before {
    transform: scale(1);
    transition: none;
  }

  .ds-process.js-reveal .ds-step--1 h3::after,
  .ds-process.js-reveal .ds-step--3 h3::after {
    transform: rotate(10deg) scaleX(1);
    transition: none;
  }

  .ds-process.js-reveal .ds-step--2 h3::after,
  .ds-process.js-reveal .ds-step--4 h3::after {
    transform: rotate(-10deg) scaleX(1);
    transition: none;
  }
}
