/*
 * Inner pages: masthead, artwork placeholders, and the section patterns the
 * content pages are assembled from.
 *
 * Loaded after ds-home.css. Responsive is treated as the requirement, not the
 * cleanup pass — the template's desktop numbers (155px clearance, 100px insets,
 * 54px titles) are unusable below a laptop, so every one of them is stepped
 * down on the same 1399 / 1199 / 991 / 767 ladder the rest of the site uses.
 */

/* ------------------------------------------------------------------ */
/* artwork placeholder                                                 */
/* ------------------------------------------------------------------ */

.ds-ph {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  padding: 16px;
  border-radius: 15px;
  overflow: hidden;
  text-align: center;
}
.ds-ph-label {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: #fff;
  max-width: 30ch;
}
.ds-ph-meta {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.72);
}
@media (max-width: 767px) {
  .ds-ph-label {
    font-size: 13px;
  }
}

/* ------------------------------------------------------------------ */
/* page masthead                                                       */
/* ------------------------------------------------------------------ */

.ds-phero {
  padding: 40px 40px 0;
}
.ds-phero-inner {
  position: relative;
  z-index: 1;
  overflow: hidden;
  border: 10px solid #fff;
  border-radius: 30px;
  background: var(--ds-ink);
}
.ds-phero-bg {
  position: absolute;
  inset: 0;
}
.ds-phero-bg .ds-ph,
.ds-phero-bg > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 0;
  opacity: 0.5;
}
/* Keeps the title legible whatever the artwork turns out to be. */
.ds-phero-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, rgba(28, 28, 37, 0.9) 25%, rgba(0, 150, 136, 0.55) 100%);
}
.ds-phero-content {
  position: relative;
  padding: 120px 0 128px;
}
.ds-phero-content h1 {
  margin: 0;
  max-width: 20ch;
  font-size: 54px;
  font-weight: 600;
  line-height: 1.22;
  color: #fff;
}
.ds-phero-content p {
  max-width: 60ch;
  margin: 18px 0 0;
  font-size: 17px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.76);
}

.ds-crumb {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0 8px;
  margin: 23px 0 0;
  padding: 12px 30px;
  list-style: none;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 50px;
  background: rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
}
.ds-crumb li {
  font-size: 15px;
  font-weight: 600;
  color: #fff;
}
.ds-crumb li + li::before {
  content: "/";
  margin-right: 8px;
  color: rgba(255, 255, 255, 0.5);
}
.ds-crumb a {
  color: rgba(255, 255, 255, 0.72);
  transition: color 0.3s ease;
}
.ds-crumb a:hover {
  color: #fff;
}

@media (max-width: 1199px) {
  .ds-phero {
    padding: 24px 24px 0;
  }
  .ds-phero-content {
    padding: 88px 0 92px;
  }
  .ds-phero-content h1 {
    font-size: 42px;
  }
}
@media (max-width: 991px) {
  .ds-phero {
    padding: 16px 16px 0;
  }
  .ds-phero-inner {
    border-width: 6px;
    border-radius: 22px;
  }
  .ds-phero-content {
    padding: 64px 0 68px;
  }
  .ds-phero-content h1 {
    font-size: 34px;
    max-width: none;
  }
  .ds-phero-content p {
    font-size: 16px;
  }
}
@media (max-width: 767px) {
  .ds-phero {
    padding: 12px 12px 0;
  }
  .ds-phero-content {
    padding: 48px 0 52px;
  }
  .ds-phero-content h1 {
    font-size: 28px;
  }
  .ds-crumb {
    padding: 9px 18px;
  }
  .ds-crumb li {
    font-size: 13.5px;
  }
}

/* ------------------------------------------------------------------ */
/* prose — the readable body copy the content pages are made of         */
/* ------------------------------------------------------------------ */

.ds-prose {
  max-width: 72ch;
}
.ds-prose > * + * {
  margin-top: 20px;
}
.ds-prose p {
  margin: 0;
  font-size: 17px;
  line-height: 1.75;
  color: var(--ds-muted);
}
.ds-prose h2 {
  margin: 44px 0 0;
  font-size: 32px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ds-ink);
}
.ds-prose h3 {
  margin: 32px 0 0;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ds-ink);
}
.ds-prose ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.ds-prose li {
  position: relative;
  margin-bottom: 12px;
  padding-left: 30px;
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--ds-muted);
}
.ds-prose li::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 11px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ds-teal);
}
.ds-prose strong {
  color: var(--ds-ink);
  font-weight: 600;
}
@media (max-width: 767px) {
  .ds-prose p {
    font-size: 16px;
  }
  .ds-prose h2 {
    font-size: 26px;
    margin-top: 34px;
  }
  .ds-prose h3 {
    font-size: 20px;
  }
}

/* ------------------------------------------------------------------ */
/* split — copy beside artwork                                         */
/* ------------------------------------------------------------------ */

.ds-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
}
.ds-split.is-flipped .ds-split-art {
  order: -1;
}
/* Photographs get the same 15px corner and 4:3 crop the placeholder used, so
   swapping a real image in does not change the rhythm of the page. */
.ds-split-img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 15px;
  display: block;
}
@media (max-width: 991px) {
  .ds-split {
    grid-template-columns: 1fr;
    gap: 34px;
  }
  /* On one column the picture always follows the words it illustrates. */
  .ds-split.is-flipped .ds-split-art {
    order: 0;
  }
}

/* ------------------------------------------------------------------ */
/* figure row                                                          */
/* ------------------------------------------------------------------ */

/* ================================================================== */
/* the figure row                                                      */
/* ================================================================== */

/* Four tinted tiles, each with a big teal number centred in it, and nothing
   else. The problem was never the styling — it was that a number centred on
   its own reads as a score. "1" over "Certificate Per Drive" looked like a
   counter that had failed to finish, and "0" over "Hours Of Downtime" looked
   like an error. Neither told the reader anything.
   
   So the tile is now a statement rather than a score: the figure and its unit
   sit on one baseline, the label names what is being counted, and a note under
   a hairline says what the number is measured against. Left-aligned, because a
   sentence that has to be read is not centred. */
.ds-figrow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(228px, 1fr));
  gap: 18px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: fig;
}
.ds-figrow li {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 26px 26px 24px;
  border: 1px solid var(--ds-line);
  border-radius: 16px;
  background: #fff;
  overflow: hidden;
  transition: border-color 0.35s ease, transform 0.35s ease, box-shadow 0.35s ease;
}
/* A teal edge that grows down the left of the tile on hover. Cheap to paint,
   and it gives the row somewhere to go without moving any type. */
.ds-figrow li::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--ds-teal);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.ds-figrow li:hover {
  border-color: rgba(0, 150, 136, 0.38);
  transform: translateY(-3px);
  box-shadow: 0 14px 34px -22px rgba(28, 28, 37, 0.4);
}
.ds-figrow li:hover::before {
  transform: scaleY(1);
}

/* The figure. Tabular figures so 25 and 100% occupy the same rhythm and the
   row does not jitter while a counter is still running. */
.ds-figrow strong {
  display: block;
  margin-bottom: 10px;
  font-size: 46px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  color: var(--ds-teal);
}
/* A short unit or qualifier riding on the figure's baseline — "standards",
   "per drive". Smaller and in ink, so the eye still lands on the number. */
/* A figure that is a word rather than a number — "SED", "LUN", "SHA-256",
   "IMEI". At 46px a word shouts where a number simply reads large, so it steps
   down and tightens. The class is set by the renderer when the figure carries
   no digit at the front. */
.ds-figrow li.is-word strong {
  font-size: 34px;
  letter-spacing: -0.005em;
}
.ds-figrow strong em {
  font-size: 17px;
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ds-ink);
}
.ds-figrow .ds-fig-label {
  font-size: 15.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ds-ink);
}
/* The sentence that makes the number mean something. Under a hairline so it
   reads as a footnote to the figure rather than as a second label. */
.ds-figrow .ds-fig-note {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--ds-line);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ds-muted);
}
/* On a tinted band the white tile is the contrast, so only the border softens. */
.ds-section-grey .ds-figrow li {
  border-color: #dfe3e3;
}

@media (max-width: 991px) {
  .ds-figrow {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
  }
  .ds-figrow strong {
    font-size: 38px;
  }
  .ds-figrow li.is-word strong {
    font-size: 30px;
  }
}
@media (max-width: 575px) {
  .ds-figrow {
    grid-template-columns: minmax(0, 1fr);
  }
  .ds-figrow li {
    padding: 22px 20px 20px;
  }
  .ds-figrow strong {
    font-size: 36px;
  }
}

/* Cards inside a content page carry no icon, so the title leads. */
.ds-card > h3:first-child {
  margin-top: 0;
}

/* ------------------------------------------------------------------ */
/* spec table                                                          */
/* ------------------------------------------------------------------ */

.ds-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--ds-line);
  border-radius: 15px;
}
.ds-table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  background: #fff;
}
.ds-table th,
.ds-table td {
  padding: 15px 20px;
  text-align: left;
  font-size: 15.5px;
  border-bottom: 1px solid var(--ds-line);
}
.ds-table th {
  font-weight: 600;
  color: var(--ds-ink);
  background: var(--ds-teal-wash);
  white-space: nowrap;
}
.ds-table td {
  color: var(--ds-muted);
}
.ds-table tr:last-child td {
  border-bottom: 0;
}

/* ------------------------------------------------------------------ */
/* matrix                                                              */
/* ------------------------------------------------------------------ */

/* For pages whose content *is* the table — the standards list, the compliance
   grid. Wider than .ds-table and with no privileged first column, though the
   first cell of each row is still the row's name and is set in ink. */
.ds-matrix {
  width: 100%;
  min-width: 820px;
  border-collapse: collapse;
  background: #fff;
}
.ds-matrix th,
.ds-matrix td {
  padding: 14px 18px;
  text-align: left;
  font-size: 15px;
  line-height: 1.55;
  vertical-align: top;
  border-bottom: 1px solid var(--ds-line);
}
.ds-matrix th {
  position: sticky;
  top: 0;
  font-weight: 600;
  color: var(--ds-ink);
  background: var(--ds-teal-wash);
  white-space: nowrap;
}
.ds-matrix td {
  color: var(--ds-muted);
}
.ds-matrix td strong {
  font-weight: 600;
  color: var(--ds-ink);
}
/* The short columns — passes, region — should not be pulled wide by the long
   description column beside them. */
.ds-matrix td:not(:first-child):not(:last-child),
.ds-matrix th:not(:first-child):not(:last-child) {
  white-space: nowrap;
}
.ds-matrix tr:last-child td {
  border-bottom: 0;
}
/* A tall table needs alternating rows to stay trackable across its width. */
.ds-matrix tbody tr:nth-child(even) td {
  background: #fbfdfd;
}

/* ------------------------------------------------------------------ */
/* CTA at the foot of every content page                               */
/* ------------------------------------------------------------------ */

/* ================================================================== */
/* the closing query form                                              */
/* ================================================================== */

/* ================================================================== */
/* the query form                                                      */
/* ================================================================== */

/*
 * What used to be a full-width dark banner, and then a flat tinted rectangle.
 *
 * The banner ended every page with the same shape and sent the reader somewhere
 * else to start again. The tinted rectangle that replaced it fixed that and
 * introduced two problems of its own: it sat on `padding-top: 0`, so its top
 * edge touched the section above with no air at all, and it was the same wash
 * as half the bands on the page, so the last thing a reader saw was one more
 * grey rectangle.
 *
 * It is a two-panel plate now. The left is a dark teal gradient carrying the
 * ask; the right is a white card holding the fields. The colour is the point:
 * every page now ends on the one section that is not a band.
 */

/* The section's own air. `paddingTop: 0` was set inline on the element and has
   been removed — this class is what restores the top padding, and it is
   slightly tighter than a full section because the plate carries its own
   internal padding and a full band above it read as a gap. */
.ds-query-section {
  padding-top: 40px;
}

.ds-query {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1fr);
  align-items: stretch;
  gap: 0;
  border-radius: 26px;
  /* The panels have square inner corners; this is what rounds the plate. */
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--ds-line);
  box-shadow: 0 30px 70px -50px rgba(28, 28, 37, 0.55);
}

/* ---- the ask, on the dark plate ---- */

.ds-query-copy {
  position: relative;
  display: flex;
  align-items: center;
  padding: 48px 46px;
  /* The blooms are inset -35%, so they extend well past this panel. Without
     this they bleed across the seam and haze the white card beside them. */
  overflow: hidden;
  /* Ink into teal rather than flat teal: a single flat fill at this size reads
     as a colour block, and the ramp gives the panel a direction that matches
     the headings' own duotone treatment. */
  background: linear-gradient(150deg, #12303a 0%, #0d5e56 55%, var(--ds-teal-deep) 100%);
  isolation: isolate;
}

/* Two soft blooms drifting behind the type. Both live on one pseudo-element as
   a pair of radial gradients, animated by transform only — no repaint, no
   image, and it stops dead under prefers-reduced-motion. */
.ds-query-glow {
  position: absolute;
  inset: -35%;
  z-index: -1;
  background:
    radial-gradient(38% 38% at 22% 28%, rgba(79, 214, 199, 0.5) 0%, transparent 70%),
    radial-gradient(32% 32% at 78% 76%, rgba(0, 150, 136, 0.55) 0%, transparent 72%);
  animation: ds-query-drift 18s ease-in-out infinite alternate;
}
@keyframes ds-query-drift {
  from {
    transform: translate3d(-3%, -2%, 0) scale(1);
  }
  to {
    transform: translate3d(4%, 3%, 0) scale(1.12);
  }
}

.ds-query-copy-in {
  position: relative;
  width: 100%;
}

/* A quieter eyebrow than the teal pill: on a teal ground that pill would
   disappear, so this one is a glass chip. */
.ds-query-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 18px;
  padding: 8px 16px;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 50px;
  background: rgba(255, 255, 255, 0.1);
  color: #cdefe9;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  line-height: 1;
  text-transform: uppercase;
}

/* Not the site's clipped-gradient h2: that ramp runs ink to teal and would be
   invisible here. Declared after ds-heads.css would set it, and specific
   enough to win. */
.ds-query .ds-query-copy h2 {
  margin: 0 0 14px;
  max-width: 18ch;
  font-size: 32px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: #fff;
  background-image: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
}
.ds-query-copy p {
  margin: 0;
  max-width: 42ch;
  font-size: 15.5px;
  line-height: 1.72;
  color: rgba(255, 255, 255, 0.8);
}

.ds-query-link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 20px;
  padding-bottom: 3px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  transition: border-color 0.3s ease, color 0.3s ease;
}
.ds-query-link i {
  transition: transform 0.3s ease;
}
.ds-query-link:hover {
  color: #8fe8de;
  border-color: #8fe8de;
}
.ds-query-link:hover i {
  transform: translateX(5px);
}

/* The two ways to reach us that are not this form. */
.ds-query-alt {
  margin: 30px 0 0;
  padding: 24px 0 0;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  list-style: none;
  display: grid;
  gap: 13px;
}
.ds-query-alt li {
  display: flex;
  align-items: center;
  gap: 13px;
}
.ds-query-alt-ico {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.12);
  color: #8fe8de;
  transition: background-color 0.3s ease, transform 0.3s ease;
}
.ds-query-alt a {
  font-size: 14.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.88);
  transition: color 0.25s ease;
  overflow-wrap: anywhere;
}
.ds-query-alt li:hover .ds-query-alt-ico {
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-2px);
}
.ds-query-alt li:hover a {
  color: #fff;
}

/* ---- the fields ---- */

.ds-query-form {
  display: grid;
  align-content: center;
  gap: 18px;
  padding: 48px 46px;
  background: #fff;
}
.ds-query-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
}

/* min-width: 0 is not optional: an <input> carries an automatic minimum width
   from its `size` attribute that beats `1fr`, so without this the two columns
   are not equal and the row overflows its card on a narrow laptop. */
.ds-field {
  position: relative;
  min-width: 0;
}

/* The label floats, so the control reserves the space it will move into:
   22px of top padding is the label's parked position. */
.ds-field input,
.ds-field textarea {
  display: block;
  width: 100%;
  padding: 23px 16px 9px;
  border: 1px solid var(--ds-line);
  border-radius: 13px;
  background: #f7faf9;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ds-ink);
  transition: border-color 0.25s ease, background-color 0.25s ease, box-shadow 0.25s ease;
}
.ds-field textarea {
  /* Vertical only: a textarea dragged wider breaks the grid it sits in. */
  resize: vertical;
  min-height: 116px;
  padding-top: 26px;
}

/* The label itself. It starts where a placeholder would be and rises to the
   top of the field once there is something in it — or once it has focus. */
.ds-field label {
  position: absolute;
  top: 15px;
  left: 17px;
  max-width: calc(100% - 34px);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 15px;
  font-weight: 500;
  color: #8d939c;
  pointer-events: none;
  transform-origin: left top;
  transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1), color 0.22s ease;
}
/* `:placeholder-shown` is the whole mechanism, and it is why every control in
   this form carries `placeholder=" "` — a field with no placeholder attribute
   never matches, and one with real placeholder text shows two labels at once. */
.ds-field input:focus + label,
.ds-field input:not(:placeholder-shown) + label,
.ds-field textarea:focus + label,
.ds-field textarea:not(:placeholder-shown) + label {
  /* scale + translate rather than a font-size change: a transform does not
     trigger layout, so the whole form does not reflow on every focus. */
  transform: translateY(-9px) scale(0.72);
  color: var(--ds-teal);
}

/* A line that draws itself across the foot of the focused field. Inset by the
   border radius so it never pokes out of the rounded corners. */
.ds-field-line {
  position: absolute;
  left: 13px;
  right: 13px;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--ds-teal);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.ds-field input:focus ~ .ds-field-line,
.ds-field textarea:focus ~ .ds-field-line {
  transform: scaleX(1);
}

.ds-field input:hover,
.ds-field textarea:hover {
  border-color: #ccd4d3;
}
/* Focus is a ring drawn as a shadow rather than an outline, so focusing a
   field does not move it by a pixel and shift the row. */
.ds-field input:focus,
.ds-field textarea:focus {
  outline: none;
  border-color: rgba(0, 150, 136, 0.55);
  background: #fff;
  box-shadow: 0 0 0 4px rgba(0, 150, 136, 0.12);
}

/* ---- send ---- */

.ds-query-send {
  position: relative;
  justify-self: start;
  margin-top: 4px;
  overflow: hidden;
}
/* A sheen that crosses the button on hover. Transform only, and it sits under
   the label because the label is given its own stacking context below. */
.ds-query-send::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.32), transparent);
  transform: translateX(0);
  transition: transform 0.65s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}
.ds-query-send:hover::after {
  transform: translateX(360%);
}
.ds-query-send span,
.ds-query-send i {
  position: relative;
  z-index: 1;
}
.ds-query-send i {
  transition: transform 0.3s ease;
}
.ds-query-send:hover i {
  transform: translateX(4px);
}

.ds-query-note {
  margin: 2px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ds-muted);
}

/* ---- narrow ---- */

@media (max-width: 1199px) {
  .ds-query-copy,
  .ds-query-form {
    padding: 38px 34px;
  }
  .ds-query .ds-query-copy h2 {
    font-size: 28px;
  }
}
@media (max-width: 991px) {
  .ds-query {
    grid-template-columns: minmax(0, 1fr);
    border-radius: 22px;
  }
  .ds-query-copy {
    padding: 36px 30px;
  }
  .ds-query-form {
    padding: 32px 30px;
  }
  .ds-query .ds-query-copy h2 {
    font-size: 26px;
    max-width: 24ch;
  }
  .ds-query-alt {
    margin-top: 24px;
    padding-top: 20px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 575px) {
  .ds-query-section {
    padding-top: 28px;
  }
  .ds-query {
    border-radius: 18px;
  }
  .ds-query-copy,
  .ds-query-form {
    padding: 28px 20px;
  }
  .ds-query .ds-query-copy h2 {
    font-size: 23px;
  }
  .ds-query-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
  }
  .ds-query-alt {
    grid-template-columns: minmax(0, 1fr);
  }
  .ds-query-send {
    justify-self: stretch;
    justify-content: center;
  }
}

/* The blooms are the only thing here that moves on its own. */
@media (prefers-reduced-motion: reduce) {
  .ds-query-glow {
    animation: none;
  }
}

/* ================================================================== */
/* downloads                                                           */
/* ================================================================== */

/* The sample documents block. Ungated on purpose — both competitors put their
   sample certificate behind a form, and a buyer who cannot see the document
   before they talk to someone has no way to judge it. */
.ds-dl {
  display: flex;
  flex-direction: column;
  padding: 30px;
  border: 1px solid var(--ds-line);
  border-radius: 18px;
  background: #fff;
}
.ds-dl-ico {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: 20px;
  border-radius: 14px;
  background: rgba(0, 150, 136, 0.1);
  color: var(--ds-teal);
}
.ds-dl h3 {
  margin: 0 0 10px;
  font-size: 21px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ds-ink);
}
.ds-dl > p {
  margin: 0 0 20px;
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--ds-muted);
}
/* What is in the file, so the reader knows before the download rather than
   after it. */
.ds-dl-list {
  margin: 0 0 26px;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 9px;
}
.ds-dl-list li {
  position: relative;
  padding-left: 26px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ds-muted);
}
.ds-dl-list li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 8px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ds-teal);
}
/* Pushed to the card foot so two cards of different length still line their
   buttons up. */
.ds-dl-btn {
  margin-top: auto;
  align-self: flex-start;
  gap: 12px;
}
.ds-dl-meta {
  padding-left: 12px;
  border-left: 1px solid rgba(255, 255, 255, 0.32);
  font-size: 13px;
  font-weight: 500;
  opacity: 0.82;
}

@media (max-width: 991px) {
  .ds-dl {
    padding: 24px;
  }
}
@media (max-width: 767px) {
  .ds-grid-2 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ================================================================== */
/* pricing                                                             */
/* ================================================================== */

/* The band above the self-service ceiling. Not a table row, because it has no
   price to put in the price column — it is the point at which the ladder stops
   and a conversation starts. */
.ds-pricenote {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 24px;
  margin-top: 26px;
  padding: 26px 30px;
  border: 1px solid var(--ds-line);
  border-radius: 18px;
  background: #fff;
}
.ds-pricenote-ico {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  background: rgba(0, 150, 136, 0.1);
  color: var(--ds-teal);
}
.ds-pricenote h3 {
  margin: 0 0 6px;
  font-size: 18px;
  font-weight: 600;
  color: var(--ds-ink);
}
.ds-pricenote p {
  margin: 0;
  max-width: 78ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ds-muted);
}
.ds-pricenote .ds-btn {
  white-space: nowrap;
}

/* What every licence includes. Two columns of ticks rather than a feature
   matrix, because there is nothing to compare it against — every band has all
   of it. */
.ds-inclist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 40px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ds-inclist li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 12px;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--ds-muted);
}
.ds-inclist svg {
  margin-top: 2px;
  color: var(--ds-teal);
}

.ds-buyrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
  margin-top: 40px;
}
.ds-buyrow-alt {
  font-size: 15px;
  font-weight: 500;
  color: var(--ds-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.ds-buyrow-alt:hover {
  color: var(--ds-teal);
}

@media (max-width: 991px) {
  .ds-pricenote {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
  }
  /* The button drops to its own row rather than squeezing the copy. */
  .ds-pricenote .ds-btn {
    grid-column: 1 / -1;
    justify-self: start;
  }
  .ds-inclist {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (max-width: 575px) {
  .ds-pricenote {
    padding: 22px 20px;
  }
}

/* ================================================================== */
/* contact                                                             */
/* ================================================================== */

.ds-contact {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
  gap: 48px 64px;
  align-items: start;
}
.ds-contact h2 {
  margin: 0 0 22px;
  font-size: 26px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ds-ink);
}
.ds-contact-form > p {
  margin: -12px 0 26px;
  max-width: 56ch;
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--ds-muted);
}

.ds-contact-list {
  margin: 0 0 40px;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 22px;
}
.ds-contact-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}
.ds-contact-ico {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  background: rgba(0, 150, 136, 0.1);
  color: var(--ds-teal);
}
.ds-contact-list strong {
  display: block;
  margin-bottom: 3px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ds-muted);
}
.ds-contact-list a,
.ds-contact-list div > span {
  font-size: 16px;
  line-height: 1.55;
  color: var(--ds-ink);
}
.ds-contact-list a:hover {
  color: var(--ds-teal);
}

.ds-contact-sub {
  margin: 0 0 14px;
  font-size: 18px;
  font-weight: 600;
  color: var(--ds-ink);
}
.ds-hours {
  margin: 0;
  padding: 0;
  list-style: none;
  border: 1px solid var(--ds-line);
  border-radius: 14px;
  overflow: hidden;
}
.ds-hours li {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 13px 18px;
  font-size: 15px;
  border-bottom: 1px solid var(--ds-line);
}
.ds-hours li:last-child {
  border-bottom: 0;
}
.ds-hours li span:first-child {
  font-weight: 600;
  color: var(--ds-ink);
}
.ds-hours li span:last-child {
  color: var(--ds-muted);
}

.ds-contact-form form {
  display: grid;
  gap: 18px;
  padding: 34px;
  border: 1px solid var(--ds-line);
  border-radius: 20px;
  background: var(--ds-teal-wash);
}
.ds-contact-form .ds-btn {
  justify-self: start;
}
/* Says where the message actually goes. A form that implies a ticket was raised
   when nothing was raised is worse than no form. */
.ds-formnote {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ds-muted);
}

@media (max-width: 991px) {
  .ds-contact {
    grid-template-columns: minmax(0, 1fr);
    gap: 44px;
  }
}
@media (max-width: 575px) {
  .ds-contact-form form {
    padding: 24px 20px;
  }
  .ds-contact-form .ds-btn {
    justify-self: stretch;
    justify-content: center;
  }
}

/* ================================================================== */
/* collected FAQ                                                       */
/* ================================================================== */

/* The FAQ page groups its questions by the page that answers them, so each
   group carries a heading and a way back to the long version. */
.ds-faqgroup + .ds-faqgroup {
  margin-top: 44px;
}
.ds-faqgroup-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px 24px;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--ds-line);
}
.ds-faqgroup-head h3 {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--ds-ink);
}

/* A small label above a card's title — the section a linked page came from. */
.ds-kicker {
  display: block;
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ds-teal);
}

/* ================================================================== */
/* legal                                                               */
/* ================================================================== */

/* Imported policy text: long, heavily sectioned and read rather than scanned,
   so it gets a wider measure than .ds-prose alone and tighter heading rhythm. */
.ds-legal {
  max-width: 78ch;
}
.ds-legal-date {
  margin: 0 0 28px !important;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--ds-line);
  font-size: 14px !important;
  color: var(--ds-muted);
}
.ds-legal h2 {
  margin-top: 38px;
}
.ds-legal h3 {
  margin-top: 28px;
}
.ds-legal a {
  color: var(--ds-teal);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.ds-legal a:hover {
  color: var(--ds-teal-deep);
}

/* ---------------- section intro ---------------- */

/* One column on phones and tablets, two from 1100px.

   The old markup put a 72ch .ds-prose inside a 1410px container, so on a laptop
   the copy filled the left half and the right half was blank on every content
   page. Splitting it keeps the measure readable - neither column exceeds about
   62ch - and gives the section something to sit against. */
.ds-intro {
  display: grid;
  gap: 24px;
}
.ds-intro-lead {
  margin: 0;
  font-size: 19px;
  line-height: 1.65;
  font-weight: 500;
  color: var(--ds-ink);
}
.ds-intro-rest > p {
  margin: 0 0 18px;
  font-size: 16.5px;
  line-height: 1.75;
  color: var(--ds-muted);
}
.ds-intro-rest > p:last-child {
  margin-bottom: 0;
}

@media (min-width: 1100px) {
  .ds-intro {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 56px;
    align-items: start;
  }
  .ds-intro-lead {
    /* A standfirst, so it carries a little more weight than the body beside it
       without becoming a heading. */
    font-size: 22px;
    line-height: 1.55;
    /* Optically aligns the first line with the body text opposite. */
    padding-top: 2px;
  }
}

/* ---------------- articles ---------------- */

.ds-artmeta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  margin-bottom: 12px;
  font-size: 12.5px;
  color: var(--ds-muted);
}
.ds-artmeta em {
  padding: 4px 12px;
  border-radius: 50px;
  background: var(--ds-teal);
  color: #fff;
  font-style: normal;
  font-weight: 600;
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* The lead piece: image left, words right, one card wide. A grid where every
   card is identical gives a reader no way in; one that says "start here" does. */
.ds-artlead {
  display: grid;
  gap: 0;
  margin-bottom: 26px;
  border: 1px solid var(--ds-line);
  border-radius: 22px;
  background: #fff;
  overflow: hidden;
  text-decoration: none;
  transition: border-color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
.ds-artlead:hover {
  border-color: var(--ds-teal);
  box-shadow: 0 20px 44px rgba(0, 0, 0, 0.09);
  transform: translateY(-3px);
}
.ds-artlead-art {
  overflow: hidden;
  background: var(--ds-teal-wash);
}
.ds-artlead-art img {
  display: block;
  width: 100%;
  /* A ratio, not height:100%. Filling the grid row made the image as tall as
     whatever the text column happened to be, which on a short standfirst was a
     portrait photograph two thirds of a screen high. */
  aspect-ratio: 16 / 11;
  object-fit: cover;
  transition: transform 0.5s ease;
}
.ds-artlead:hover .ds-artlead-art img {
  transform: scale(1.04);
}
.ds-artlead-body {
  padding: 32px;
}
.ds-artlead-body h2 {
  margin: 0 0 10px;
  font-size: 27px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--ds-ink);
}
.ds-artlead-body p {
  margin: 0;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ds-muted);
}
.ds-artmore {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ds-teal);
}
.ds-artlead:hover .ds-artmore i {
  transform: translateX(4px);
}
.ds-artmore i {
  font-size: 12px;
  transition: transform 0.25s ease;
}

.ds-artgrid {
  display: grid;
  gap: 22px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.ds-artcard {
  display: flex;
  flex-direction: column;
  padding: 0 0 24px;
  border: 1px solid var(--ds-line);
  border-radius: 18px;
  background: #fff;
  overflow: hidden;
  text-decoration: none;
  transition: border-color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
.ds-artcard:hover {
  border-color: var(--ds-teal);
  box-shadow: 0 16px 34px rgba(0, 0, 0, 0.08);
  transform: translateY(-3px);
}
.ds-artcard-art {
  overflow: hidden;
  background: var(--ds-teal-wash);
}
.ds-artcard-art img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform 0.5s ease;
}
.ds-artcard:hover .ds-artcard-art img {
  transform: scale(1.05);
}
.ds-artcard .ds-artmeta {
  margin: 20px 24px 10px;
}
.ds-artcard h3 {
  margin: 0 24px 8px;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.32;
  color: var(--ds-ink);
}
.ds-artcard p {
  margin: 0 24px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ds-muted);
  /* Three lines then ellipsis, so a stack of cards has a straight bottom edge
     whatever the standfirsts do. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---- the article itself ---- */

.ds-article {
  display: grid;
  gap: 32px;
}
.ds-article-meta {
  align-self: start;
}
.ds-article-by {
  margin: 0;
  font-size: 13.5px;
  color: var(--ds-muted);
}
.ds-article-body {
  max-width: 68ch;
}
.ds-article-body p {
  margin: 0 0 22px;
  font-size: 17.5px;
  line-height: 1.78;
  color: var(--ds-body, #384049);
}
.ds-article-body h2 {
  margin: 40px 0 14px;
  font-size: 26px;
  font-weight: 700;
  line-height: 1.28;
  color: var(--ds-ink);
}
.ds-article-body ul {
  margin: 0 0 24px;
  padding-left: 22px;
}
.ds-article-body li {
  margin-bottom: 11px;
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--ds-muted);
}
/* A pull quote, set against a teal rule rather than in quotation marks — the
   marks read as decoration at this size and the rule does the same work. */
.ds-pullquote {
  margin: 30px 0;
  padding: 6px 0 6px 24px;
  border-left: 3px solid var(--ds-teal);
  font-size: 21px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ds-ink);
}

@media (min-width: 900px) {
  .ds-artlead {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    align-items: center;
  }
  .ds-artlead-body {
    padding: 40px;
  }
}
@media (min-width: 1100px) {
  .ds-article {
    grid-template-columns: 200px minmax(0, 1fr);
    gap: 56px;
  }
  .ds-article-meta {
    position: sticky;
    top: 120px;
  }
}

/* ---------------- tick list ---------------- */

/* The "what is in the box" list on a content page.

   It used to sit inside .ds-prose, whose 72ch cap is correct for a paragraph
   and wrong for a column of short items — measured across nine pages it left
   this section using 54% of the container with the right half empty, and it was
   the only narrow section on almost all of them.

   Columns rather than one long run: each item is a phrase, and a phrase set to
   72ch is mostly whitespace anyway. */
.ds-ticklist {
  display: grid;
  gap: 14px 32px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ds-ticklist li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 12px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ds-muted);
}
.ds-ticklist li svg {
  margin-top: 3px;
  color: var(--ds-teal);
  flex: none;
}

@media (min-width: 900px) {
  .ds-ticklist {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: 1300px) {
  .ds-ticklist {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ================================================================== */
/* the lifecycle chain                                                 */
/* ================================================================== */

/*
 * "Identify → Erase → Verify → Report → Reuse, Recycle or Destroy".
 *
 * Written as a line of text with arrows in it, this is a caption, and the eye
 * skips captions. Drawn as connected nodes that light in order it is the
 * process it describes, and the reader watches it run once before reading a
 * word of it.
 *
 * The rail is two lines on top of each other: a grey one that is always there,
 * and a teal one that grows across it left to right. Each node's ring fills as
 * the teal reaches it. Everything is a transform, a scale or an opacity, so
 * nothing here triggers layout while it plays.
 *
 * The whole sequence is timed off two custom properties — `--ds-flow-n`, the
 * number of steps, and `--ds-flow-i`, this step's index — so adding or removing
 * a step re-times the chain on its own with no hand-set delays to fall out of
 * step.
 */

.ds-flow-rail {
  /* how long one node takes to arrive, and the gap between arrivals */
  --ds-flow-beat: 0.42s;
  --ds-flow-lead: 0.12s;

  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--ds-flow-n, 5), minmax(0, 1fr));
  gap: 0 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* ---- the rail ----

   Both lines are drawn on the ::before/::after of the list itself rather than
   between the items, so the chain is one continuous line under every node
   instead of four separate connectors that never quite meet. It sits at the
   vertical centre of the node row — 31px is half of the 62px node. */
.ds-flow-rail::before,
.ds-flow-rail::after {
  content: "";
  position: absolute;
  top: 31px;
  /* stops inside the first and last node rather than running off the ends */
  left: calc((100% - (var(--ds-flow-n, 5) - 1) * 18px) / var(--ds-flow-n, 5) / 2);
  right: calc((100% - (var(--ds-flow-n, 5) - 1) * 18px) / var(--ds-flow-n, 5) / 2);
  height: 2px;
  border-radius: 2px;
}
.ds-flow-rail::before {
  background: var(--ds-line);
}
/* The pass travelling through the chain. */
.ds-flow-rail::after {
  background: linear-gradient(90deg, var(--ds-teal-deep), var(--ds-teal));
  transform: scaleX(0);
  transform-origin: left center;
}
.ds-flow-rail.is-running::after {
  animation: ds-flow-fill calc(var(--ds-flow-beat) * var(--ds-flow-n, 5)) cubic-bezier(0.65, 0, 0.35, 1) var(--ds-flow-lead) both;
}
@keyframes ds-flow-fill {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

/* ---- a step ---- */
.ds-flow-step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  opacity: 0;
  transform: translateY(14px);
}
.ds-flow-rail.is-running .ds-flow-step {
  animation: ds-flow-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--ds-flow-lead) + var(--ds-flow-i) * var(--ds-flow-beat));
}
@keyframes ds-flow-in {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ---- the node ----

   Solid white, not transparent: it has to sit on top of the rail and hide the
   line behind it, or the grey rail shows through the ring. */
.ds-flow-node {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  border: 2px solid var(--ds-line);
  border-radius: 50%;
  background: #fff;
  color: var(--ds-muted);
}
.ds-flow-node svg {
  width: 26px;
  height: 26px;
}
.ds-flow-rail.is-running .ds-flow-step .ds-flow-node {
  animation: ds-flow-node 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
  /* a beat behind its own step, so the tile arrives and *then* lights */
  animation-delay: calc(var(--ds-flow-lead) + var(--ds-flow-i) * var(--ds-flow-beat) + 0.18s);
}
@keyframes ds-flow-node {
  0% {
    border-color: var(--ds-line);
    background: #fff;
    color: var(--ds-muted);
    transform: scale(1);
  }
  55% {
    transform: scale(1.12);
  }
  100% {
    border-color: var(--ds-teal);
    background: var(--ds-teal);
    color: #fff;
    transform: scale(1);
  }
}

/* A single ring that expands out of the node as it lights, then fades. It is a
   separate element only because a node cannot both scale and ripple. */
.ds-flow-node::after {
  content: "";
  position: absolute;
  inset: -2px;
  border: 2px solid var(--ds-teal);
  border-radius: 50%;
  opacity: 0;
}
.ds-flow-rail.is-running .ds-flow-step .ds-flow-node::after {
  animation: ds-flow-ping 0.85s ease-out both;
  animation-delay: calc(var(--ds-flow-lead) + var(--ds-flow-i) * var(--ds-flow-beat) + 0.18s);
}
@keyframes ds-flow-ping {
  0% {
    opacity: 0.6;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(1.55);
  }
}

/* ---- the type ---- */
.ds-flow-i {
  margin-top: 18px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
  color: var(--ds-teal);
}
/* Two lines' worth of room whether the label needs them or not. "Reuse,
   Recycle Or Destroy" wraps where "Erase" does not, and without this the
   paragraph under the long one starts a line lower than the other four and the
   row stops reading as a row. */
.ds-flow-step h3 {
  margin: 6px 0 0;
  min-height: calc(2 * 1.3em);
  font-size: 19px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ds-ink);
}
.ds-flow-step p {
  max-width: 30ch;
  margin: 9px 0 0;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ds-muted);
}

@media (max-width: 1199px) {
  .ds-flow-step h3 {
    font-size: 17.5px;
  }
  .ds-flow-step p {
    font-size: 14px;
  }
}

/* ---- narrow ----

   Below 900px five columns each hold about three words per line. The chain
   turns on its side: the rail becomes vertical, running down the left through
   the nodes, and the copy sits beside it. Same animation, same order, read top
   to bottom instead of left to right. */
@media (max-width: 899px) {
  .ds-flow-rail {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
  }
  /* One rail on the list cannot work vertically: its bottom edge is the bottom
     of the last step's paragraph, not the centre of the last node, so the line
     ran on past the end of the chain. Turned on its side the connector belongs
     to each step instead — drawn from its own node down into the gap below it,
     and simply absent on the last one, which is where the chain stops.

     It also times better this way. Each connector fills in the beat between
     its own node lighting and the next one, so the line is visibly travelling
     rather than one bar growing behind five separate events. */
  .ds-flow-rail::before,
  .ds-flow-rail::after {
    display: none;
  }
  .ds-flow-step::before,
  .ds-flow-step::after {
    content: "";
    position: absolute;
    /* the node is 52px wide, so its centre is 26px in; less 1px for a 2px line */
    left: 25px;
    top: 52px;
    /* down into the 26px row gap, meeting the next node */
    bottom: -26px;
    width: 2px;
    border-radius: 2px;
  }
  .ds-flow-step::before {
    background: var(--ds-line);
  }
  .ds-flow-step::after {
    background: var(--ds-teal);
    transform: scaleY(0);
    transform-origin: top center;
  }
  .ds-flow-rail.is-running .ds-flow-step::after {
    animation: ds-flow-fill-v var(--ds-flow-beat) linear both;
    /* starts as this node lights and lands as the next one does */
    animation-delay: calc(var(--ds-flow-lead) + var(--ds-flow-i) * var(--ds-flow-beat) + 0.18s);
  }
  .ds-flow-step:last-child::before,
  .ds-flow-step:last-child::after {
    display: none;
  }
  .ds-flow-step {
    display: grid;
    grid-template-columns: 52px minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    align-items: start;
    gap: 0 20px;
    text-align: left;
  }
  .ds-flow-node {
    grid-row: 1 / 4;
    width: 52px;
    height: 52px;
  }
  .ds-flow-node svg {
    width: 22px;
    height: 22px;
  }
  .ds-flow-i {
    margin-top: 2px;
  }
  .ds-flow-step h3 {
    margin-top: 4px;
    min-height: 0;
    font-size: 18px;
  }
  .ds-flow-step p {
    max-width: 60ch;
  }
}

/* Declared outside the media query: a @keyframes nested inside one is valid CSS
   but it is not scoped by it, and keeping it here says so. */
@keyframes ds-flow-fill-v {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

/* Nothing in the chain carries meaning the still frame does not: the finished
   state is every node lit and the rail solid, which is the process complete. */
@media (prefers-reduced-motion: reduce) {
  .ds-flow-rail::after,
  .ds-flow-step,
  .ds-flow-step::after,
  .ds-flow-node,
  .ds-flow-node::after {
    animation: none !important;
  }
  .ds-flow-rail::after,
  .ds-flow-step::after {
    transform: none;
  }
  .ds-flow-step {
    opacity: 1;
    transform: none;
  }
  .ds-flow-node {
    border-color: var(--ds-teal);
    background: var(--ds-teal);
    color: #fff;
  }
  .ds-flow-node::after {
    opacity: 0;
  }
}

/* ==================================================================== */
/* Blocks added 29 Aug 2026                                             */
/*                                                                      */
/* Every service page and every sector page now answers the same set of */
/* questions in the same order — what it covers, what you get, what     */
/* proof arrives, which standard governs, where to read next. These are */
/* the four blocks that were missing. None of them introduces a new     */
/* visual language: they are the existing card, tick list and section   */
/* head, arranged for the content they carry.                           */
/* ==================================================================== */

/* ---------------- supported media, grouped ---------------- */

/* A card that carries a list rather than a paragraph. The hover orb and the
   lift belong on a card the reader can act on; on a reference list they are
   just movement, so this variant drops both and keeps the frame. */
.ds-card-plain {
  padding: 26px 28px;
}
.ds-card-plain::before {
  display: none;
}
.ds-card-plain:hover {
  border-color: var(--ds-line);
  transform: none;
}
.ds-card-plain h3 {
  margin-bottom: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--ds-line);
  font-size: 18px;
}
/* Inside a card the list is one column whatever the viewport, because the card
   is already the column. */
.ds-ticklist-tight {
  grid-template-columns: minmax(0, 1fr);
  gap: 11px;
}
.ds-ticklist-tight li {
  font-size: 15px;
  line-height: 1.5;
}

/* ---------------- what you receive ---------------- */

.ds-evidence {
  display: grid;
  /* `minmax(0, …)` on both tracks: the right-hand list contains long items and
     a bare `1fr` would floor at their min-content width, widening the section
     past its container on a narrow laptop. */
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 40px 56px;
  align-items: start;
}
.ds-evidence-body {
  margin: 0;
  max-width: 62ch;
  font-size: 18px;
  line-height: 1.7;
  color: var(--ds-ink);
}

/* ---------------- standards, explained ---------------- */

.ds-std {
  display: flex;
  flex-direction: column;
}
.ds-std h3 {
  font-size: 18px;
  /* Long marks — "NIST SP 800-88 Rev. 2", "PCI-DSS Requirement 9" — must be
     allowed to break rather than set the card's minimum width. */
  overflow-wrap: anywhere;
}
/* Pushed to the foot of the card so the "when it applies" lines sit on one
   baseline across the row however long the description above them runs. */
.ds-std-when {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--ds-line);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ds-muted);
}
.ds-std-when span {
  display: block;
  margin-bottom: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ds-teal);
}
.ds-std p + .ds-std-when {
  margin-top: auto;
}

/* ---------------- tables on a phone ---------------- */

/* A table that scrolls sideways inside its own box never breaks the page, and
   that is what .ds-table-wrap has always done. It is still a poor read on a
   360px screen: an 820px matrix means dragging a viewport-and-a-half to see
   the end of a row, with no indication there is anything there.
   Below 640px both tables stop being tables and become one block per row, the
   column heading printed as a label beside its value. The markup is unchanged
   — the labels come from the data-label attribute the renderer writes. */
@media (max-width: 639px) {
  .ds-table-wrap {
    overflow-x: visible;
    border: 0;
    border-radius: 0;
  }
  .ds-table,
  .ds-matrix {
    min-width: 0;
    display: block;
    background: transparent;
  }
  .ds-table thead,
  .ds-matrix thead {
    /* Clipped rather than display:none — the header cells still name the
       columns for a screen reader reading the table linearly. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .ds-table tbody,
  .ds-matrix tbody {
    display: grid;
    gap: 14px;
  }
  .ds-table tr,
  .ds-matrix tr {
    display: block;
    padding: 4px 18px 14px;
    border: 1px solid var(--ds-line);
    border-radius: 15px;
    background: #fff;
  }
  .ds-table td,
  .ds-matrix td {
    display: block;
    padding: 12px 0 0;
    border: 0;
    white-space: normal;
  }
  .ds-table td + td,
  .ds-matrix td + td {
    border-top: 1px solid var(--ds-line);
  }
  /* The column heading, printed above its value. */
  .ds-table td::before,
  .ds-matrix td::before {
    content: attr(data-label);
    display: block;
    margin: 10px 0 3px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ds-teal);
  }
  /* The first cell is the row's own name; it needs no label above it. */
  .ds-table td:first-child::before,
  .ds-matrix td:first-child::before {
    display: none;
  }
  .ds-table td:first-child,
  .ds-matrix td:first-child {
    padding-top: 14px;
    font-size: 16.5px;
  }
  /* Undoes the desktop rule that keeps the short middle columns on one line;
     stacked, nowrap is what would push a card sideways. */
  .ds-matrix td:not(:first-child):not(:last-child) {
    white-space: normal;
  }
}

/* ---------------- responsive ---------------- */

@media (max-width: 1099px) {
  .ds-evidence {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
  }
  .ds-evidence-body {
    font-size: 17px;
  }
}

/* Inner-page hero, centred on tablet and phone — the same reasoning as the
   homepage hero in ds-home.css: below 992px it is a single column, and a
   single column reads as centred on purpose rather than as text that ran out
   of room. The breadcrumb centres with the title it belongs to. */
@media (max-width: 991px) {
  .ds-phero-content {
    text-align: center;
  }
  .ds-phero-content h1,
  .ds-phero-content p {
    margin-left: auto;
    margin-right: auto;
  }
  .ds-crumb {
    justify-content: center;
  }
}

/* The floating labels are `nowrap` with an ellipsis, which is right — a label
   that wraps breaks the rise-and-shrink animation. But the longest one in the
   DS-AI query form ("What are you trying to erase, and how many?") measured
   323px against a 278px field at 390 wide, so a third of it was ellipsised
   away before the visitor had typed anything. Slightly smaller type and a
   tighter right inset fit it whole on a phone; the label still shrinks again
   when it floats, so nothing about the focused state changes. */
@media (max-width: 575px) {
  .ds-field label {
    left: 14px;
    max-width: calc(100% - 24px);
    font-size: 13px;
  }
  .ds-field input,
  .ds-field textarea {
    padding-left: 14px;
    padding-right: 14px;
  }
}
