/** Shopify CDN: Minification failed

Line 875:3 Unexpected "!"

**/
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&display=swap');
@import url('https://use.typekit.net/pes1awk.css');

/* ══════════════════════════════════════════════════════════════════════
   DAKUTX — shared stylesheet
   Goes in the theme's Assets folder as  dkx.css

   Every DAKUTX section links this one file, so the whole site's type,
   spacing and colour live here. Change something here and it changes on
   every page at once.

   THE TYPE COLOUR IS ON LINE 21. That one value drives every piece of
   text on every DAKUTX section, light backgrounds and dark. It is here
   rather than in the theme customiser because a theme update can wipe
   customiser settings, and this file survives.
   ══════════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800&display=swap');

.dkx, .dkx *, .dkx *::before, .dkx *::after { box-sizing: border-box; }

/* The type colour sits on :root rather than on .dkx, because the header is the
   theme's own markup and lives outside .dkx. One definition, used in both. */
:root {
  --dkx-type: #919996;
  /* The heading weight lives here too, not just on .dkx. The header is the
     theme's own markup and sits outside .dkx, so a var() defined only there
     resolves to nothing and the whole declaration is thrown away silently.
     That is why the nav and the login button stayed at their normal weight
     twice, even with !important on them. */
  --dkx-weight-head: 700;
  /* Same reason as the weight above. The footer is the theme's own markup and
     lives outside .dkx, so anything it needs has to resolve at :root. These are
     redefined on .dkx as well, which is harmless: the nearer definition wins
     inside a section and this one covers the header and footer. */
  --dkx-dark: #141414;
  --dkx-mono: 'lores-12', 'IBM Plex Mono', ui-monospace, 'SF Mono', SFMono-Regular, Menlo, monospace;
  --dkx-logo: 'lores-15-narrow', 'lores-12', sans-serif;
  --dkx-size-mono: 12px;
  --dkx-rule-dark: #2e2e2e;
}

.dkx {
  --dkx-rule: #e2e2e2;          /* hairlines on light backgrounds */
  --dkx-rule-dark: #2e2e2e;     /* hairlines on dark backgrounds */
  --dkx-paper: #ffffff;
  --dkx-stone: #f4f4f2;
  --dkx-dark: #141414;
  /* Mono, used for the small utility type: eyebrows, kickers, buttons, the
     vertical rail, the arrow links and the sources note. Everything at
     headline and body size stays on the main face. */
  --dkx-mono: 'lores-12', 'IBM Plex Mono', ui-monospace, 'SF Mono', SFMono-Regular, Menlo, monospace;
  --dkx-logo: 'lores-15-narrow', 'lores-12', sans-serif;

  /* Side margins. Two things control them and they apply at different widths.
     The gutter is the space at the edge of a narrow screen. --dkx-max caps the
     content on a wide one, and past that width it is the cap doing the work,
     not the gutter. Both moved together so the margins grow at every size. */
  /* Corner radius on the boxed cards. One value, so every rounded thing on the
     site matches. */
  --dkx-radius: 14px;

  --dkx-gutter: clamp(28px, 5.75vw, 83px);
  --dkx-max: 1280px;

  /* ── HEADING WEIGHT, TRACKING AND LEADING ──
     All three move together. Heavy type wants tight letter-spacing and tight
     leading or it looks bloated. Light type wants both opened up or it looks
     like it is falling apart. Change all three, not one.

        Heavy:      weight 800, tracking -0.04em, leading 0.95
        Medium:     weight 500, tracking -0.02em, leading 1.05
        Light:      weight 300, tracking  0em,    leading 1.15
        Very light: weight 200, tracking  0.01em, leading 1.2

     Available weights: 100 200 300 400 500 600 700 800
     Leading is a multiple of the type size. 1.0 means lines sit exactly one
     type-height apart, which is why 0.95 looks stacked and 1.2 looks airy. */
  --dkx-track-head: -0.045em;

  /* Body tracking. Looser than the heads, because tight tracking on a long
     line costs more in readability than it buys in look. */
  --dkx-track-body: -0.012em;
  --dkx-lead-head: 1.05;

  /* Leading for the smaller headings, h3 and h4, where they wrap to a second
     line. The big heads can sit at 0.95 because they are usually one or two
     words; a wrapping sub-head needs a fraction more, but far less than the
     1.4 these were each carrying separately. */
  --dkx-lead-sub: 1.08;

  /* Leading for the short display lines: statements, standfirsts, the eyebrow.
     These are set in caps more often than not, and caps have no descenders, so
     the gap a normal leading leaves between two lines reads as a hole. */
  --dkx-lead-display: 1.0;

  /* ── THE TYPE SCALE ──
     One value per role. Every rule below points at one of these rather than
     carrying its own number, so a size change happens here and nowhere else.

       h1    the hero headline. Once per page, at the top
       h2    a section heading
       h3    every column heading, a route category, a stat figure
       body  every piece of running text
       mono  every small utility label: eyebrows, buttons, numbers, the rail

     h1, h2 and h3 all take --dkx-weight-head, so they move together. Body is
     the only thing at 400, which is what separates a h3 from the paragraph
     under it even where the sizes are close. */
  --dkx-size-h1:   clamp(40px, 8vw, 116px);
  --dkx-size-h2:   clamp(32px, 5vw, 64px);
  --dkx-size-h3:   clamp(17px, 1.9vw, 22px);
  --dkx-size-h4:   16px;   /* body size, head weight. The quietest heading. */
  --dkx-body-size: 16px;
  --dkx-size-mono: 12px;

  /* One leading for every piece of running text, the same way there is one
     size. Every paragraph rule points at this rather than carrying its own
     number, so tightening the body is one change here. */
  --dkx-lead-body: 1.15;

  font-family: 'helvetica-neue-lt-pro', 'Inter', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  color: var(--dkx-type);
  -webkit-font-smoothing: antialiased;
  text-align: left;
  overflow-x: hidden;
  /* clip, not hidden, where supported: hidden turns this into a scroll box,
     and nothing inside a scroll box can stick to the screen, which is what
     stopped the problem band holding in place. */
  overflow-x: clip;
}

/* ── RESET. Deliberately excludes div and span: an element selector like
   ".dkx div" outranks a single class like ".dkx-cats", which would strip
   the padding off every section. Every layout rule below is written as
   ".dkx .dkx-name" so it wins on specificity regardless. ── */
.dkx h1, .dkx h2, .dkx h3, .dkx h4, .dkx p, .dkx ul, .dkx li, .dkx a,
.dkx em, .dkx strong, .dkx figure {
  font-family: inherit; margin: 0; padding: 0; letter-spacing: var(--dkx-track-body);
  text-transform: none; border: 0; background: none; float: none;
  max-width: none; color: inherit; list-style: none;
}
.dkx h1, .dkx h2, .dkx h3 { font-weight: var(--dkx-weight-head); line-height: 1; }
.dkx p { font-weight: 400; }
.dkx a { text-decoration: none; color: inherit; }
.dkx em { font-style: italic; }
.dkx strong { font-weight: 600; }
.dkx img { display: block; max-width: 100%; height: auto; }

/* ══ CONTAINERS ══ */
.dkx .dkx-bleed { width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
.dkx .dkx-wrap  { max-width: var(--dkx-max); margin: 0 auto;
                  padding-left: var(--dkx-gutter); padding-right: var(--dkx-gutter); }

/* ══ BACKGROUNDS — set per section in the customiser ══ */
.dkx .bg-paper { background: var(--dkx-paper); }
.dkx .bg-stone { background: var(--dkx-stone); }
.dkx .bg-dark  { background: var(--dkx-dark); }
/* Lighter black. Rendered with bg-dark as well, so every dark-section rule
   applies, and only the ground changes. Two blacks side by side separate
   sections without a line. */
.dkx .bg-dark.bg-graphite { background: #1e1e20; }
.dkx .bg-dark .dkx-rule-line { border-color: var(--dkx-rule-dark); }

/* ══ VERTICAL RHYTHM — set per section in the customiser ══ */
.dkx .pad-s  { padding-top: clamp(84px, 9vw, 140px);   padding-bottom: clamp(84px, 9vw, 140px); }
.dkx .pad-m  { padding-top: clamp(128px, 15vw, 244px);  padding-bottom: clamp(128px, 15vw, 244px); }
.dkx .pad-l  { padding-top: clamp(180px, 23vw, 380px);  padding-bottom: clamp(180px, 23vw, 380px); }
.dkx .pad-xl { padding-top: clamp(240px, 31vw, 528px);  padding-bottom: clamp(240px, 31vw, 528px); }

/* Butt a section straight against its neighbour. Set per section, and after the
   pad rules so it wins without needing !important. */
.dkx .pad-top-none    { padding-top: 0 !important; }
.dkx .pad-bottom-none { padding-bottom: 0 !important; }
.dkx .rule-below { border-bottom: 1px solid var(--dkx-rule); }
.dkx .bg-dark.rule-below { border-bottom-color: var(--dkx-rule-dark); }

/* ══ SHARED TYPE SCALE ══ */
.dkx .dkx-eyebrow { line-height: var(--dkx-lead-display); font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400; letter-spacing: 0.21em;
                    text-transform: uppercase; margin-bottom: 28px; opacity: 0.85; }
.dkx .dkx-h1 { font-size: var(--dkx-size-h1); font-weight: var(--dkx-weight-head);
               line-height: var(--dkx-lead-head); letter-spacing: var(--dkx-track-head); }
.dkx .dkx-h2 { font-size: var(--dkx-size-h2); font-weight: var(--dkx-weight-head);
               line-height: var(--dkx-lead-head); letter-spacing: var(--dkx-track-head); margin-bottom: 28px; }

/* Headline lines. Each line of the hero headline is its own block carrying its
   own alignment, so these rules are per line rather than per headline.

   Justified is the one worth explaining. text-align: justify widens the spaces
   between words, and these lines are usually a single word with no spaces in
   them, so it does nothing at all. dkx-hero.liquid puts every character in its
   own element instead, and space-between shares the slack out between them.
   Tracking is zeroed on a justified line because those gaps are doing that job
   now; leaving it on adds an extra gap after the last letter and pushes the
   line past the right edge.

   Line spacing is set per hero from the customiser, as an inline style on the
   h1, so it is not in here. */
.dkx .dkx-h1-lines { display: block; width: 100%; }
.dkx .dkx-h1-lines .dkx-h1-line { display: block; }
.dkx .dkx-h1-lines .al-left    { text-align: left; }
.dkx .dkx-h1-lines .al-center  { text-align: center; }
.dkx .dkx-h1-lines .al-right   { text-align: right; }
.dkx .dkx-h1-lines .al-justify { display: flex; justify-content: space-between; letter-spacing: 0; }
/* keeps a real space at full width, for a line like MADE TO ORDER */
.dkx .dkx-h1-lines .al-justify > span { white-space: pre; }

/* Under about 600px a word spread across the full width leaves gaps wide enough
   to read as separate letters, so a justified line sets normally instead. */
@media (max-width: 600px) {
  .dkx .dkx-h1-lines .al-justify { display: block; letter-spacing: var(--dkx-track-head); }
  .dkx .dkx-h1-lines .al-justify > span { display: inline; white-space: normal; }
}
/* size-m used to be a second, smaller section heading. One head size means it
   now matches the standard one. The control is left in place so existing
   sections do not break. */
.dkx .dkx-h2.size-m { font-size: var(--dkx-size-h2); }
/* Standfirsts. The opening line under a heading, the sentence under the chips,
   the hero paragraph and the statements in the top columns. Body size, head
   weight, so they lead into the section without becoming another heading. */
/* Ledes run at h3, the same size as the What-we-make subheading, so every
   opening line on the page is set at one size rather than three. */
.dkx .dkx-lede { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head); letter-spacing: var(--dkx-track-head);
                 line-height: var(--dkx-lead-display); max-width: 560px; }
.dkx .dkx-body { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); }
.dkx .dkx-body + .dkx-body { margin-top: 26px; }
.dkx .dkx-body p + p { margin-top: 26px; }
.dkx .dkx-small { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); opacity: 0.8; }

/* ══ HERO ══ */
/* The hero already sits inside .dkx-bleed, which takes it to the window edges,
   so it does not need to bleed again itself. */
/* Where the headline block sits against the pictures. Bottom is the default and
   what the hero has always done; the other two are set per section. */
.dkx .dkx-hero { position: relative; width: 100%; display: flex;
                 align-items: flex-end; overflow: hidden;
                 /* Everything in the hero sits on top of a photograph, so it
                    takes white rather than the site's grey. Scoped to the hero,
                    so the rest of the page is untouched. */
                 color: #ffffff; }
.dkx .dkx-hero.textv-top    { align-items: flex-start; }
.dkx .dkx-hero.textv-middle { align-items: center; }
.dkx .dkx-hero.textv-bottom { align-items: flex-end; }
/* The top and bottom padding on the inner block is there to hold the text off
   the edges. Centred, it fights the centring, so it comes off. */
.dkx .dkx-hero.textv-middle .dkx-hero-in { padding-top: 0; padding-bottom: 0; }

.dkx .dkx-hero-img { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; }
/* Video sits one layer above the still and below the shade, so the image shows
   through until the video is actually playing.

   Full width, natural height. It is not cropped to fit the hero box: it spans
   the width and takes whatever height its own proportions give it. If that
   comes up shorter than the hero, the still image simply shows below it, which
   is why the image is worth setting even when a video is used. */
.dkx .dkx-hero-vid { position: absolute; top: 0; left: 0; width: 100%; height: auto;
                     display: block; z-index: 1; pointer-events: none; }
.dkx .dkx-hero-vid video { width: 100%; height: auto; display: block; }
.dkx .dkx-hero-shade { position: absolute; inset: 0; z-index: 2; }
.dkx .dkx-hero-in { position: relative; z-index: 3; width: 100%;
                    padding-top: 80px; padding-bottom: clamp(44px, 6vw, 76px); }
.dkx .dkx-kicker { font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400; letter-spacing: 0.21em; line-height: var(--dkx-lead-sub);
                   text-transform: uppercase;
                   max-width: 390px; margin-bottom: 22px; }
/* Mono, and tracking back to normal with it. The head tracking is negative,
   which pulls a monospace face into itself and undoes the even spacing that is
   the whole point of it. */
/* The main face, not the mono, but at the kicker's size so the two lines in the
   hero sit at the same scale. */
.dkx .dkx-hero-sub { margin-top: 26px; max-width: 520px;
                     font-weight: 500; letter-spacing: 0.21em;
                     font-size: var(--dkx-size-mono); line-height: var(--dkx-lead-display); }

/* The SVG headline rules that used to sit here have been removed. Nothing
   referenced .dkx-fit or .dkx-fitline, and the comment described an approach
   the markup never used, which made it look like the live implementation. The
   real headline rules are under SHARED TYPE SCALE above. */
.dkx .dkx-rail { position: absolute; top: 0; height: 100%; display: flex;
                 align-items: center; z-index: 4;
                 right: calc(var(--dkx-gutter) - 4px); }
.dkx .dkx-rail span { font-family: var(--dkx-mono); writing-mode: vertical-rl; font-size: var(--dkx-size-mono); font-weight: 400;
                      /* Doubles the gap either side of the separators. In a
                         monospace face a space is one character wide, so adding
                         1em makes it two. Rail only; the horizontal mono keeps
                         its normal word spacing. */
                      word-spacing: 1em;
                      letter-spacing: 0.21em; text-transform: uppercase; opacity: 0.8; }
@media (max-width: 1000px) { .dkx .dkx-rail { display: none; } }

/* The rail sits inside the right-hand gutter, which is also where the headline
   stops, so long lines ran straight into the vertical type. When a rail is set,
   the hero's content column stops short of it. Only above 1000px, because the
   rail is hidden below that and the extra space would be wasted. */
@media (min-width: 1001px) {
  .dkx .dkx-hero.has-rail .dkx-wrap { padding-right: calc(var(--dkx-gutter) + 54px); }
}

/* ══ REVEAL ON SCROLL ══
   Both classes below are added by dkx.js. Nothing is hidden by CSS on its own,
   so if that file never loads the page still reads normally. Hiding content
   behind JavaScript that might not run is how a page ends up blank. */
.dkx-anim .dkx-r    { opacity: 0; transform: translateY(20px);
                      transition: opacity .7s cubic-bezier(.22,.61,.36,1),
                                  transform .7s cubic-bezier(.22,.61,.36,1); }
.dkx-anim .dkx-r.dkx-in { opacity: 1; transform: none; }
/* The body copy in each image row rises as one block, and so does the
   ecosystem's opening paragraph. Both rise
   further and more slowly than headings, so the words seem to surface after
   the heading has landed. */
.dkx-anim .dkx .dkx-ed-body.dkx-r, .dkx-anim .dkx .dkx-orbit-foot.dkx-r {
  transform: translateY(40px);
  transition: opacity 1s cubic-bezier(.22,.61,.36,1), transform 1s cubic-bezier(.22,.61,.36,1); }
.dkx-anim .dkx .dkx-ed-body.dkx-r.dkx-in, .dkx-anim .dkx .dkx-orbit-foot.dkx-r.dkx-in { opacity: 1; transform: none; }
.dkx-anim .dkx .dkx-orbit-leg.dkx-r { transform: translateY(40px);
  transition: opacity 1s cubic-bezier(.22,.61,.36,1), transform 1s cubic-bezier(.22,.61,.36,1); }
.dkx-anim .dkx .dkx-orbit-leg.dkx-r.dkx-in { opacity: 1; transform: none; }
/* The stacked points dissolve against the scroll rather than on a trigger, so
   they are driven by dkx.js frame by frame. Nothing is hidden unless that script
   has run and said so, or a page with no JavaScript would be a blank band. */
.dkx-fade [data-dkx-fade] { will-change: opacity, transform; }

/* Belt and braces: the script already bails out on this setting, but if the
   preference is switched on after load the rules stop applying too. */
@media (prefers-reduced-motion: reduce) {
  .dkx-anim .dkx-r, .dkx-anim .dkx-r.dkx-in {
    opacity: 1; transform: none; transition: none; }
}

/* Marks above a column heading. Stroke only, no fill, inheriting the text
   colour so they work on white, off-white and near-black alike. 1.25px reads as
   a drawn line rather than a UI icon at this size. */
.dkx .dkx-mark { display: block; width: 38px; height: 38px; margin-bottom: 22px;
                 fill: none; stroke: currentColor; stroke-width: 1.25;
                 stroke-linecap: butt; stroke-linejoin: miter; overflow: visible; }
.dkx .dkx-col.type-s .dkx-mark { width: 32px; height: 32px; margin-bottom: 18px; }

/* A statement. Sub-head size, written as a paragraph, for a section that is one
   sentence and nothing else. */
/* A statement. Sub-head size, written as a paragraph, for a section that is one
   sentence and nothing else. */
.dkx .dkx-statement { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                      letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-display);
                      max-width: 780px; }

/* Centred sections. The max-widths that hold a line to a readable measure are
   set from the left, so they have to be centred too, or the text centres inside
   a block still sitting against the left edge. */
.dkx .dkx-wrap.align-centre { text-align: center; }
.dkx .dkx-wrap.align-centre .dkx-statement,
.dkx .dkx-wrap.align-centre .dkx-lede,
.dkx .dkx-wrap.align-centre .dkx-body { margin-left: auto; margin-right: auto; }

/* ══ SPLIT STATEMENT ══
   Two columns of large type facing each other across a centre line. The left
   column is set right-aligned and the right column left-aligned, so both blocks
   meet at the gutter instead of starting from the same edge.

   The gutter is the gap, and it has to be wide enough that the two sides read
   as separate phrases rather than one run-on line. Grid handles that: two equal
   columns with a gap between, so the meeting point stays centred whatever the
   line lengths are. */
.dkx .dkx-split-row { display: grid; grid-template-columns: 1fr 1fr;
                      gap: clamp(20px, 3vw, 56px); align-items: baseline; }
.dkx .dkx-split-row + .dkx-split-row { margin-top: clamp(8px, 1vw, 18px); }
.dkx .dkx-split-l { text-align: right; }
.dkx .dkx-split-r { text-align: left; }
.dkx .dkx-split-l, .dkx .dkx-split-r {
  font-weight: var(--dkx-weight-head); letter-spacing: var(--dkx-track-head);
  line-height: var(--dkx-lead-head); }
.dkx .dkx-split.size-h1 .dkx-split-l, .dkx .dkx-split.size-h1 .dkx-split-r { font-size: var(--dkx-size-h1); }
.dkx .dkx-split.size-h2 .dkx-split-l, .dkx .dkx-split.size-h2 .dkx-split-r { font-size: var(--dkx-size-h2); }
.dkx .dkx-split.size-h3 .dkx-split-l, .dkx .dkx-split.size-h3 .dkx-split-r { font-size: var(--dkx-size-h3); }

/* The right column carries less weight so the pair reads as term and meaning
   rather than two competing halves. */
.dkx .dkx-split-r { opacity: 0.55; }

/* On a phone two columns of big type leaves neither side room, so the stack
   goes single file and both sides set from the left. */
@media (max-width: 749px) {
  .dkx .dkx-split-row { grid-template-columns: 1fr; gap: 0; }
  .dkx .dkx-split-l, .dkx .dkx-split-r { text-align: left; }
  .dkx .dkx-split-row + .dkx-split-row { margin-top: clamp(18px, 4vw, 32px); }
}

/* ══ FEATURE ══
   A centred line with a picture or video running the full width beneath it.
   The words sit in their own band above the media rather than over it, so the
   type never has to fight a photograph for contrast. */
.dkx .dkx-feature-words { display: flex; flex-direction: column; justify-content: center;
                          text-align: center; margin-bottom: clamp(48px, 6vw, 96px); }
.dkx .dkx-feature-media { position: relative; width: 100%; overflow: hidden; }
.dkx .dkx-feature-img { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0;
                        transform: translateY(var(--dkx-par, 0px)) scale(var(--dkx-zoom, 1)); }
/* A parallax image has to be taller than its frame or drifting it reveals an
   edge. The extra height is split above and below so the starting position is
   still centred. JS only sets --dkx-par; the zoom stays in CSS so the two
   transforms compose instead of overwriting each other. */
.dkx .dkx-feature-img.dkx-parallax {
  /* Overscan is set per image by the script, from its own strength, so a gentle
     parallax does not carry the same oversized picture as a strong one. */
  height: calc(100% + var(--dkx-over, 30%));
  top: calc(var(--dkx-over, 30%) / -2);
  will-change: transform;
}
/* Video sits over the still, so the image is what shows until it plays. */
.dkx .dkx-feature-vid { position: absolute; inset: 0; width: 100%; height: 100%;
                        object-fit: cover; z-index: 1; pointer-events: none; }
.dkx .dkx-feature-vid video { width: 100%; height: 100%; object-fit: cover; }

/* ══ CENTRE SPLIT HERO ══
   Two big words on one line, with their small text on opposite sides of it.
   Three rows across two columns:

     row 1   kicker, right-aligned   |  (empty)
     row 2   first word,  right      |  second word, left
     row 3   (empty)                 |  paragraph,  left

   Putting both words in the same grid row is what keeps them on one line
   regardless of length, and it is why this cannot be done by stacking blocks.
   The columns meet at the centre, so the words face each other across it. */
/* The gap between the two words is a real gutter, set from the customiser. It
   is what lets the right edge of the left stack line up with the end of the
   left word, and the left edge of the right stack line up with the start of the
   right one. Too small and the words read as one string. */
.dkx .dkx-split-hero { display: grid; width: 100%;
                       grid-template-columns: 1fr 1fr;
                       column-gap: var(--sh-gap, 6%); }
.dkx .dkx-split-hero .sh-kicker { grid-column: 1; grid-row: 1; text-align: right; }
.dkx .dkx-split-hero .sh-a      { grid-column: 1; grid-row: 2; text-align: right; }
.dkx .dkx-split-hero .sh-b      { grid-column: 2; grid-row: 2; text-align: left; }
.dkx .dkx-split-hero .sh-sub    { grid-column: 2; grid-row: 3; text-align: left; }

/* The two words take the hero size; the small text takes the mono treatment the
   kicker and paragraph already use elsewhere, so nothing new is introduced. */
/* The two words are h2, the stacks either side are h3, per the layout brief.
   Both stacks keep their line breaks, so a four-line stack stays four lines. */
.dkx .dkx-split-hero .sh-a, .dkx .dkx-split-hero .sh-b {
  font-size: var(--dkx-size-h2); font-weight: var(--dkx-weight-head);
  letter-spacing: var(--dkx-track-head); }
.dkx .dkx-split-hero .sh-kicker, .dkx .dkx-split-hero .sh-sub {
  font-size: var(--dkx-size-h4); font-weight: var(--dkx-weight-head);
  letter-spacing: var(--dkx-track-head); line-height: 0.95;
  text-transform: uppercase;
  white-space: pre-line; }

/* Where each stack sits against the word next to it. The kicker stack hangs
   from the bottom of its row so it stays tight under the top of the word, and
   the paragraph stack sits at the top of its row for the same reason. */
.dkx .dkx-split-hero .sh-kicker { align-self: end;   margin-bottom: 10px; }
.dkx .dkx-split-hero .sh-sub    { align-self: start; margin-top: 10px; }
.dkx .dkx-split-hero .sh-a, .dkx .dkx-split-hero .sh-b { align-self: baseline; }

/* On a phone two columns of hero type leaves neither word room, so it stacks
   and everything sets from the left. */
@media (max-width: 749px) {
  .dkx .dkx-split-hero { grid-template-columns: 1fr; }
  .dkx .dkx-split-hero .sh-kicker,
  .dkx .dkx-split-hero .sh-a,
  .dkx .dkx-split-hero .sh-b,
  .dkx .dkx-split-hero .sh-sub { grid-column: 1; text-align: left; }
  .dkx .dkx-split-hero .sh-kicker { grid-row: 1; }
  .dkx .dkx-split-hero .sh-a { grid-row: 2; }
  .dkx .dkx-split-hero .sh-b { grid-row: 3; }
  .dkx .dkx-split-hero .sh-sub { grid-row: 4; }
}

/* h4. Body size at head weight and head tracking, so it is told apart from the
   paragraph under it by weight alone rather than by getting bigger. */
.dkx .dkx-h4 { font-size: var(--dkx-size-h4); font-weight: var(--dkx-weight-head);
               letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-body); }

/* Words over the picture. The stack becomes the positioning context, the media
   fills it, and the words sit on top centred both ways.

   The scrim is a wash over the picture and under the words. Type on a photograph
   fails when the picture happens to be light exactly where the words are, and no
   amount of choosing a colour fixes that on every image. A scrim does, and it is
   a slider because how much you need depends entirely on the photograph. */
.dkx .dkx-feature-stack { position: relative; }
.dkx .dkx-feature-stack .dkx-feature-media { margin: 0; }
.dkx .dkx-feature-stack .dkx-feature-media::after {
  content: ""; position: absolute; inset: 0; z-index: 2;
  background: rgba(0,0,0,var(--dkx-scrim, 0.25)); pointer-events: none; }
.dkx .dkx-feature-stack .dkx-feature-words {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; justify-content: center;
  margin-bottom: 0; }
.dkx .dkx-feature-stack.tone-light .dkx-feature-words { color: #ffffff; }
.dkx .dkx-feature-stack.tone-dark  .dkx-feature-words { color: var(--dkx-dark); }
/* A dark scrim under near-black type would fight it, so that pairing lightens. */
.dkx .dkx-feature-stack.tone-dark .dkx-feature-media::after {
  background: rgba(255,255,255,var(--dkx-scrim, 0.25)); }

/* A texture layer behind a section's content. Its own element rather than a CSS
   background, so opacity applies to the picture alone and leaves the type at
   full strength. Position relative on the parent is what keeps it contained. */
.dkx .has-bg-image { position: relative; overflow: hidden; }
.dkx .has-bg-image > *:not(.dkx-bgimg) { position: relative; z-index: 1; }
.dkx .dkx-bgimg { position: absolute; inset: 0; width: 100%; height: 100%;
                  z-index: 0; opacity: var(--dkx-bgimg-opacity, 0.3);
                  pointer-events: none;
                  transform: translateY(var(--dkx-par, 0px)); }
/* Same overscan rule as the feature image: a drifting picture needs more height
   than its frame or it shows an edge. The script sizes it from the strength. */
.dkx .dkx-bgimg.dkx-parallax {
  height: calc(100% + var(--dkx-over, 30%));
  top: calc(var(--dkx-over, 30%) / -2);
  will-change: transform;
}

/* Text colour per section, for a section sitting over a dark texture or a dark
   background where the site grey disappears. */
.dkx .tone-light { color: #ffffff; }
.dkx .tone-dark  { color: var(--dkx-dark); }

/* ══ CHIPS — the category strip ══ */
.dkx .dkx-chips { display: flex; flex-wrap: wrap; gap: 10px 12px; }
.dkx .dkx-chips span { font-size: var(--dkx-body-size); font-weight: 600;
                       letter-spacing: -0.015em; border: 1px solid var(--dkx-rule);
                       border-radius: 2px; padding: 9px 16px; }
.dkx .bg-dark .dkx-chips span { border-color: var(--dkx-rule-dark); }
/* ══ FRAME — one box around a whole column row ══
   Different job to the existing "box" setting, which draws a card per column.
   This draws a single container behind all of them, so three outcomes read as
   one statement rather than three separate claims.

   Two treatments. The outlined one keeps the page background and separates with
   a hairline, which suits a row that sits directly under another section. The
   solid one is pure black with the stacked shadow the route cards use, for when
   the row needs to stop the page. */
/* The box breaks out past the text column, and takes that same distance back
   as padding, so the words inside still start on the page's own margin. The
   pull is always smaller than the gutter, so it can never reach the screen edge. */
.dkx .dkx-frame { --dkx-out: clamp(18px, 2.6vw, 52px);
                  border-radius: 24px;
                  margin-left: calc(var(--dkx-out) * -1);
                  margin-right: calc(var(--dkx-out) * -1);
                  padding: clamp(72px, 7.5vw, 130px) calc(clamp(44px, 4.8vw, 84px) + var(--dkx-out)); }
.dkx .dkx-frame.frame-line { border: 1px solid var(--dkx-rule); background: transparent; }
.dkx .bg-dark .dkx-frame.frame-line { border-color: var(--dkx-rule-dark); }
/* Pure #000 rather than --dkx-dark. The page's near-black is #141414, and against
   it a #141414 box would vanish, so the frame takes the one tone the palette does
   not otherwise use. */
.dkx .dkx-frame.frame-solid { background: #000; color: var(--dkx-paper); border: 0;
                              box-shadow: 0 1px 2px rgba(20,20,20,0.06),
                                          0 10px 26px rgba(20,20,20,0.10),
                                          0 28px 56px rgba(20,20,20,0.08); }
/* Raised frame. Same three-shadow stack as the route cards and the raised
   columns, so a box here reads as the same kind of object as a box anywhere else
   on the page. The eyebrow above it stays outside the box, because it labels the
   box rather than belonging to it. */
.dkx .dkx-frame.frame-raised { background: var(--dkx-paper); border: 0;
                               box-shadow: 0 1px 2px rgba(20,20,20,0.05),
                                           0 8px 20px rgba(20,20,20,0.06),
                                           0 24px 48px rgba(20,20,20,0.05); }
.dkx .bg-dark .dkx-frame.frame-raised { background: rgba(255,255,255,0.045); box-shadow: none; }
.dkx .dkx-frame.frame-solid .dkx-col,
.dkx .dkx-frame.frame-solid h3,
.dkx .dkx-frame.frame-solid p { color: var(--dkx-paper); }
/* The marks take currentColor, so they invert with the text and need no rule. */
@media (max-width: 700px) { .dkx .dkx-frame { padding: 26px 22px; } }

/* ══ WHAT WE MAKE — heading list left, subheading right ══
   A second layout for DKX Chips. The categories stop being a row of pills and
   become the heading itself, one per line, with the explaining sentence set
   beside them rather than underneath. Column split mirrors DKX About so the two
   sections line up down the page.

   Leading is pulled tighter than a normal heading. At h2 size a list of five
   single words at standard leading spreads far enough that it stops reading as
   one block and starts reading as five separate headings. */
/* Centred, not top-aligned. The left column is five lines of h2 and the right is
   two short paragraphs, so aligning both to the top leaves the sentence stranded
   against the first category with a long drop under it. Centring sits it against
   the middle of the list, which is where the eye already is. */
.dkx .dkx-makes-grid { display: grid; align-items: center;
                       grid-template-columns: minmax(0, 1fr) minmax(0, 0.52fr);
                       gap: clamp(48px, 7vw, 120px); }
@media (max-width: 900px) { .dkx .dkx-makes-grid { grid-template-columns: 1fr; gap: 40px;
                                                    align-items: start; } }
.dkx .dkx-makes-list { font-size: var(--dkx-size-h2); font-weight: var(--dkx-weight-head);
                       letter-spacing: var(--dkx-track-head); line-height: 1.06;
                       margin: 0; }
/* The right column starts on the same optical line as the first category, not
   at the top of the eyebrow above it. */
.dkx .dkx-makes-sub { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                      letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-display);
                      max-width: 340px; }
.dkx .dkx-makes-sub + .dkx-makes-note { margin-top: 26px; }
.dkx .dkx-makes-note { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); max-width: 340px; }

.dkx .dkx-chips-foot { margin-top: 40px; font-weight: var(--dkx-weight-head); letter-spacing: var(--dkx-track-head); font-size: var(--dkx-size-h3); line-height: var(--dkx-lead-display); max-width: 620px; }

/* ══ THREE-UP — repeating columns, three sizes ══
   Row gap is deliberately larger than column gap. When four columns wrap onto
   two rows, an equal gap makes the two rows read as one block; a wider row gap
   keeps them separate. ══ */
/* The row gap was set when these sections were always a single row, so it was
   really separating one section from the next. Now that six blocks wrap to two
   rows it is separating rows within one idea, and wants to be much closer to
   the column gap than to the section spacing. */
.dkx .dkx-grid { display: grid;
                 column-gap: clamp(32px, 5vw, 76px);
                 row-gap: clamp(56px, 6vw, 96px); }
.dkx .dkx-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.dkx .dkx-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.dkx .dkx-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .dkx .dkx-grid.cols-3, .dkx .dkx-grid.cols-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px) { .dkx .dkx-grid { grid-template-columns: 1fr !important; row-gap: 104px; } }
.dkx .dkx-grid-head { margin-bottom: clamp(96px, 11vw, 190px); }
/* When the head is an eyebrow on its own, with no heading and no opening line,
   the full gap is measured against type that is not there. Half of it puts the
   label back in contact with what it labels. Same clamp, every value halved, so
   it scales identically rather than drifting apart at one screen width. */
.dkx .dkx-grid-head.head-eyebrow-only { margin-bottom: clamp(48px, 5.5vw, 95px); }
/* Inside a box the head is already held by the box's own padding, so the full
   section gap would open a hole between the heading and what it introduces. */
.dkx .dkx-frame .dkx-grid-head { margin-bottom: clamp(44px, 4.6vw, 72px); }

/* Section wordmark. Height is set from the nav's own type size rather than a
   round number, so the two stay locked together if that size ever changes.
   The 0.72 is cap height: the file is all capitals with nothing above or below
   them, so matching its height to the full font size would draw it noticeably
   larger than the letters in the menu beside it. */
.dkx .dkx-secmark { display: block; font-family: var(--dkx-logo);
                    font-size: calc(var(--dkx-size-mono) * 1.728); font-weight: 400;
                    line-height: 1; letter-spacing: 0.06em; text-transform: uppercase;
                    margin-bottom: clamp(60px, 6.4vw, 104px); opacity: 0.85; }

/* A heading that sits inside the grid and spans every column, so one section can
   carry two headed groups of columns under a single eyebrow and a single
   background image. Splitting that into two sections is what made a shared
   background impossible: two sections are siblings, each clipping its own image
   to its own height, so the picture restarted halfway down.

   Top margin is larger than the bottom one. The heading belongs to the columns
   under it, so it needs to sit away from the group above and close to its own. */
.dkx .dkx-grid-break { grid-column: 1 / -1;
                       margin-top: clamp(120px, 13vw, 200px);
                       margin-bottom: calc(clamp(96px, 11vw, 190px) - clamp(16px, 1.6vw, 24px)); }

/* ── COLUMN BOXES — a second level of hierarchy, sitting on top of whatever
   background the section itself is set to. Filled boxes always pick the
   opposite tone to the surface they sit on, so a box never disappears into
   its own background. ── */
.dkx .dkx-col.card-fill,
.dkx .dkx-col.card-raised,
.dkx .dkx-col.card-line { padding: clamp(24px, 2.6vw, 38px); border-radius: 2px; }
.dkx .dkx-col.card-fill { background: var(--dkx-stone); }
.dkx .bg-stone .dkx-col.card-fill { background: var(--dkx-paper); }
.dkx .bg-dark  .dkx-col.card-fill { background: rgba(255,255,255,0.055); }
.dkx .dkx-col.card-line { border: 1px solid var(--dkx-rule); }
/* Raised card. Same three-shadow stack as the route cards, so a column here and
   a doorway card there read as the same object on the page. One shadow alone
   sits either too tight to register as depth or too wide to look sharp, which is
   why it is a hairline contact shadow, a mid one for the lift and a wide faint
   one for the ambient light. No border: with a shadow separating the card from
   the page, a line as well is belt and braces.

   Radius is --dkx-radius, not the 2px the other two card styles use, because
   this one is copying the routes and they run at the full radius. */
.dkx .dkx-col.card-raised { background: var(--dkx-paper); border: 0;
                            border-radius: var(--dkx-radius);
                            box-shadow: 0 1px 2px rgba(20,20,20,0.05),
                                        0 8px 20px rgba(20,20,20,0.06),
                                        0 24px 48px rgba(20,20,20,0.05); }
/* On a near-black ground a shadow cannot be seen, so the card lifts its own
   surface instead. Same fallback the routes use. */
.dkx .bg-dark .dkx-col.card-raised { background: rgba(255,255,255,0.045); box-shadow: none; }
.dkx .bg-dark .dkx-col.card-line { border-color: var(--dkx-rule-dark); }
/* boxes carry their own padding, so the gap between them tightens */
.dkx .dkx-grid.boxed { column-gap: clamp(16px, 1.6vw, 24px); row-gap: clamp(16px, 1.6vw, 24px); }
@media (max-width: 700px) { .dkx .dkx-grid.boxed { row-gap: 20px; } }

/* 0.3pt. Browsers work in px, and 0.3pt is 0.4px, which is a true hairline on
   a retina screen and the thinnest line that still renders on a standard one. */
.dkx .dkx-col.topline { border-top: 0.4px solid currentColor; padding-top: 20px; }
/* a rule above the heading INSIDE a box, rather than above the box itself */
.dkx .dkx-col.card-fill.topline,
.dkx .dkx-col.card-raised.topline,
.dkx .dkx-col.card-line.topline { border-top: 0; }
.dkx .dkx-col.card-fill.topline h3,
.dkx .dkx-col.card-raised.topline h3,
.dkx .dkx-col.card-line.topline h3 { border-top: 0.4px solid currentColor; padding-top: 18px; }
.dkx .dkx-col h3 { margin-bottom: 12px; }
.dkx .dkx-col.type-l h3 { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                          letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-head); margin-bottom: 14px; }
.dkx .dkx-col.type-l p { font-weight: var(--dkx-weight-head); letter-spacing: var(--dkx-track-head); font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); }
/* one step heavier than the display headings, since 19px needs more weight
   than 64px does to read as a heading at all */
/* Sub-heads sit at body size and are told apart by weight rather than scale.
   Medium against the body's normal, on the same baseline rhythm. */
.dkx .dkx-col.type-m h3 { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                          letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub); }
.dkx .dkx-col.type-m p { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); }
.dkx .dkx-col.type-s h3 { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                          letter-spacing: var(--dkx-track-head); margin-bottom: 12px; }
.dkx .dkx-col.type-s p { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); }

/* ══ STAT BAND — heading left, figures right ══ */
.dkx .dkx-band-grid { display: grid; align-items: start;
                      grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
                      gap: clamp(56px, 9vw, 152px); }
@media (max-width: 900px) { .dkx .dkx-band-grid { grid-template-columns: 1fr; gap: 64px; } }

/* The other arrangement: heading above, figures in a row underneath, laid out
   exactly like a Columns section so the two can sit on the same page and read
   as one system rather than two. Same intro spacing, same column gap, and the
   dividing lines come off because Columns does not use them. */
.dkx .dkx-band-grid.layout-above { grid-template-columns: 1fr; gap: 0; }
.dkx .dkx-band-grid.layout-above > :first-child { margin-bottom: clamp(96px, 11vw, 190px); }
.dkx .dkx-band-grid.layout-above .dkx-band-lede { max-width: 560px; }
.dkx .dkx-band-grid.layout-above .dkx-stats {
  grid-template-columns: repeat(4, 1fr); column-gap: clamp(32px, 5vw, 76px); }
.dkx .dkx-band-grid.layout-above .dkx-stat {
  padding: 0; border: 0; }
.dkx .dkx-band-grid.layout-above .dkx-stat:nth-child(even) { padding-left: 0; }
@media (max-width: 900px) {
  .dkx .dkx-band-grid.layout-above .dkx-stats { grid-template-columns: repeat(2, 1fr); row-gap: 56px; }
}
@media (max-width: 700px) {
  .dkx .dkx-band-grid.layout-above .dkx-stats { grid-template-columns: 1fr; row-gap: 48px; }
}
/* Matched to .dkx-orbit-foot and .dkx-lede. All three are an opening line under
   a heading, so they are one size. This one had its own smaller value, which is
   why the entry-problem paragraph read lighter than the orbit line under it. */
.dkx .dkx-band-lede { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                      letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-display);
                      max-width: 560px; }
/* Two across is right for four figures. With three it leaves a row of two and a
   widow, so an odd count stacks instead. The divider rules go with it, because
   a right-hand border on a single column is a line down the middle of nothing. */
.dkx .dkx-stats { display: grid; grid-template-columns: 1fr 1fr; }
.dkx .dkx-stats.count-1,
.dkx .dkx-stats.count-3 { grid-template-columns: 1fr; }
/* Stacked, every rule written for the two-column grid has to be undone, not just
   the column count. Three of them were showing:

   · nth-child(even) adds 28px of left padding, which indented the middle item
     against the two either side of it
   · nth-last-child(-n+2) removes the bottom border from the last two items,
     correct for the last row of a two-column grid, so stacked it left exactly
     one line under the first item and none under the others
   · the right-hand divider, which has nothing to divide in a single column

   All of it comes off, and the measure narrows so a point is a readable width
   rather than the full half of the section. */
.dkx .dkx-stats.count-1 .dkx-stat,
.dkx .dkx-stats.count-3 .dkx-stat {
  border: 0;
  padding: 0 0 clamp(64px, 7vw, 112px) 0;
  max-width: 340px;
}
.dkx .dkx-stats.count-1 .dkx-stat:last-child,
.dkx .dkx-stats.count-3 .dkx-stat:last-child { padding-bottom: 0; }
.dkx .dkx-stat { padding: 44px 44px 44px 0; border-bottom: 1px solid var(--dkx-rule); }
.dkx .bg-dark .dkx-stat { border-bottom-color: var(--dkx-rule-dark); }
.dkx .dkx-stat:nth-child(odd) { border-right: 1px solid var(--dkx-rule); }
.dkx .bg-dark .dkx-stat:nth-child(odd) { border-right-color: var(--dkx-rule-dark); }
.dkx .dkx-stat:nth-child(even) { padding-left: 28px; padding-right: 0; }
.dkx .dkx-stat:nth-last-child(-n+2) { border-bottom: none; }
.dkx .dkx-stat-num { font-size: var(--dkx-size-h2); font-weight: var(--dkx-weight-head);
                     letter-spacing: var(--dkx-track-head); line-height: 1; margin-bottom: 10px; }
.dkx .dkx-stat p { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); opacity: 0.8; }
/* The one deliberate exception to the scale. A sources line is a citation
   rather than running text, and it is meant to sit quietly under the figures
   it supports. */
.dkx .dkx-sources { margin-top: 56px; font-size: 11px; line-height: var(--dkx-lead-body);
                    max-width: 780px; opacity: 0.6; }
@media (max-width: 520px) {
  .dkx .dkx-stats { grid-template-columns: 1fr; }
  .dkx .dkx-stat, .dkx .dkx-stat:nth-child(odd), .dkx .dkx-stat:nth-child(even) {
    padding: 22px 0; border-right: none; border-bottom: 1px solid var(--dkx-rule); }
  .dkx .bg-dark .dkx-stat { border-bottom-color: var(--dkx-rule-dark); }
  .dkx .dkx-stat:last-child { border-bottom: none; }
}

/* ══ ROUTES — the doorway cards ══ */
/* Separate cards rather than a joined grid. The gap does the separating, so the
   grid drops the shared background and border that used to draw the dividing
   lines between them. */
.dkx .dkx-routes-grid { display: grid; grid-template-columns: repeat(4, 1fr);
                        gap: clamp(16px, 1.8vw, 28px);
                        margin-top: clamp(72px, 9vw, 132px); }
/* Four across needs two steps down, not one. Going straight from four columns to
   one leaves the tablet width with columns too narrow to hold "Labels & Designers"
   on a single line, which is where the set stops reading as a row. */
/* Six cards on the Programs page sit three across, two rows. */
.dkx .dkx-routes-grid.dkx-routes-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 1080px) { .dkx .dkx-routes-grid, .dkx .dkx-routes-grid.dkx-routes-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px)  { .dkx .dkx-routes-grid, .dkx .dkx-routes-grid.dkx-routes-3 { grid-template-columns: 1fr; } }
/* Three shadows rather than one. A single shadow either sits too tight to read
   as depth or too wide to read as sharp. Stacking a hairline contact shadow, a
   mid one for the lift and a wide faint one for the ambient light is what makes
   it look like an object on a surface instead of a box with grey behind it.
   The border comes off: with a shadow doing the separating, a line as well
   reads as belt and braces. */
.dkx .dkx-route { background: var(--dkx-paper); padding: clamp(30px, 2.5vw, 44px);
                  border: 0; border-radius: var(--dkx-radius);
                  display: flex; flex-direction: column; justify-content: space-between;
                  min-height: 320px;
                  box-shadow: 0 1px 2px rgba(20,20,20,0.05),
                              0 8px 20px rgba(20,20,20,0.06),
                              0 24px 48px rgba(20,20,20,0.05);
                  transition: box-shadow 0.28s ease, transform 0.28s ease; }
/* On the near-black background a shadow is invisible, so the card separates
   with a faint lift in its own surface instead. */
.dkx .bg-dark .dkx-route { box-shadow: none; background: rgba(255,255,255,0.045); }
/* Lifts on hover. 2px is enough to register and small enough not to shove the
   text about. */
.dkx .dkx-route:hover { transform: translateY(-2px);
                        box-shadow: 0 2px 4px rgba(20,20,20,0.06),
                                    0 14px 30px rgba(20,20,20,0.09),
                                    0 34px 64px rgba(20,20,20,0.07); }
.dkx .bg-dark .dkx-route:hover { transform: translateY(-2px);
                                 background: rgba(255,255,255,0.075); box-shadow: none; }
.dkx .dkx-route-num { font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400; letter-spacing: 0.21em;
                      margin-bottom: 16px; opacity: 0.75; }
.dkx .dkx-route h3 { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                     letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub); margin-bottom: 14px; }
.dkx .dkx-route p { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); margin-bottom: 40px; }
.dkx .dkx-go { font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400; letter-spacing: 0.21em;
               text-transform: uppercase; display: flex; align-items: center; gap: 8px;
               transition: gap 0.18s ease; }
.dkx .dkx-route:hover .dkx-go { gap: 14px; }

/* ══ ABOUT — heading left, prose right ══ */
.dkx .dkx-about-grid { display: grid; align-items: start;
                       grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
                       gap: clamp(56px, 8vw, 140px); }
@media (max-width: 900px) { .dkx .dkx-about-grid { grid-template-columns: 1fr; gap: 48px; } }
.dkx .dkx-worn { margin-top: 64px; padding-top: 40px; border-top: 1px solid var(--dkx-rule); }
.dkx .bg-dark .dkx-worn { border-top-color: var(--dkx-rule-dark); }
.dkx .dkx-worn .dkx-eyebrow { margin-bottom: 14px; }
.dkx .dkx-worn-list { display: flex; flex-wrap: wrap; gap: 6px 0; }
.dkx .dkx-worn-list span { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); }
.dkx .dkx-worn-list span:not(:last-child)::after {
  content: '\00a0\00b7\00a0\00a0'; font-weight: 400; opacity: 0.55; }

/* ══ CTA ══ */
.dkx .dkx-cta-in { text-align: center; }
.dkx .dkx-cta-in .dkx-h2 { text-align: center; }
.dkx .dkx-cta-in p { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); max-width: 520px;
                     margin: 0 auto 56px; text-align: center; }
.dkx .dkx-btn { font-family: var(--dkx-mono); display: inline-block; background: var(--dkx-paper); color: var(--dkx-dark);
                font-size: var(--dkx-size-mono); font-weight: 400; letter-spacing: 0.21em;
                text-transform: uppercase; padding: 17px 40px; border-radius: 2px; }
.dkx .dkx-btn:hover { background: #e6e6e4; }
.dkx .bg-paper .dkx-btn, .dkx .bg-stone .dkx-btn {
  background: var(--dkx-dark); color: var(--dkx-paper); }
.dkx .bg-paper .dkx-btn:hover, .dkx .bg-stone .dkx-btn:hover { background: #2e2e2e; }

/* ══ HEADER NAV ══
   The only rules in this file that reach outside .dkx, and a deliberate
   exception. The nav belongs to the theme's own header, not to a DKX section.

   It is kept here rather than edited into the theme's own stylesheet for two
   reasons. Those files are built and minified, so an edit is unreadable and
   easily lost. And everything this project changes then stays in one file that
   is pushed and reverted together.

   The underline is not a border. The theme sets text-decoration: underline
   permanently on the label and then switches text-decoration-color to reveal
   it, so removing the decoration itself is what takes it off. The extra class
   in the selector is there to out-rank the theme's own rule without !important.

   Both header variants are covered because the theme ships two and only one is
   active at a time. */
   !important is deliberate here and only here. These rules override a built,
   minified theme stylesheet, and the theme sets the underline on one element
   and then reveals it by changing text-decoration-color on three others, so
   winning on specificity alone proved unreliable. Both the decoration and its
   colour are killed, on both the link and its inner label, because the theme
   uses different ones in its two header variants.

   The hover underline is left alone. It is drawn as a separate line element
   rather than a text decoration, so it still works. */
.header-menu-new .header-menu__item,
.header-menu-new .header-menu__item-text,
.header-menu-new .header-menu__item:hover .header-menu__item-text,
.header-menu-new .header-menu__item--active .header-menu__item-text,
.header-menu-new .header-menu__item.is-active .header-menu__item-text,
.header-menu .header-menu__item,
.header-menu .header-menu__item-text {
  text-decoration: none !important;
  text-decoration-color: transparent !important;
}

/* The theme draws the nav underline two different ways and only removing one
   of them left the lines on screen. This is the second: a 1px element sitting
   6px under the label, normally invisible and revealed by opacity. Removing the
   element rather than hiding it, so nothing can turn it back on. */
/* The client login button, matched to the menu beside it: same colour, same
   weight, same caps, one step smaller again so it reads as secondary. */
.clientlogin, .clientlogin.client, .clientlogin.customer {
  color: var(--dkx-type) !important;
  font-weight: var(--dkx-weight-head) !important;
  text-transform: uppercase;
  font-size: 0.8em;
  border-color: var(--dkx-type) !important;
  /* A literal rather than --dkx-radius, because that is defined on .dkx and the
     header sits outside it. 3px reads as softened rather than as a pill. */
  border-radius: 3px;
}

/* And the nav takes the same grey as the rest of the type, rather than the
   theme's near-black. */
.header-menu-new .header-menu__item, .header-menu .header-menu__item,
.header-menu-new .header-menu__item-text, .header-menu .header-menu__item-text {
  color: var(--dkx-dark) !important;
  text-transform: uppercase;
  /* !important on the weight too. Without it the theme's own rule was winning
     and the menu stayed at its normal weight. */
  font-weight: var(--dkx-weight-head) !important;
  /* Relative, so it tracks whatever the theme sets rather than a fixed size. */
  font-size: 0.9em;
}

.header-menu .header-menu__item-text::after,
.header-menu-new .header-menu__item-text::after,
.header-menu .header-menu__item--active .header-menu__item-text::after,
.header-menu-new .header-menu__item--active .header-menu__item-text::after {
  display: none !important;
}

/* ══ TEXTURE ══
   Fine grain over a flat background. Generated by an SVG turbulence filter held
   in a data URI, so it costs no request, tiles without a seam and stays sharp on
   any screen. An uploaded noise tile would band on a large flat area and would
   need a second file to serve retina.

   It sits on ::after with pointer-events off, above the background image layer
   and under the text. Opacity is deliberately very low: at anything above about
   0.05 it stops reading as paper and starts reading as dirt on the screen. */
.dkx .textured { position: relative; }
.dkx .textured::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  opacity: 0.075; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='320' height='320' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}
/* Dark grounds get their own frequency, arrived at by bracketing two failures.
   At 0.85 the pattern is single-pixel speckle, which on black is the definition
   of sensor noise. At 0.018 it is cloud-scale blotches with nothing fine in them.
   0.3 with three octaves sits between: visible as surface, too fine to read as
   weather. Tile drops to 300px to match, since a finer pattern needs a smaller
   tile before the repeat becomes visible.

   It also runs hotter than the light version, at 0.12 against 0.075. Screen on
   black adds light to nothing, so it needs more to register than multiply does
   against white. */
.dkx .bg-dark.textured::after {
  mix-blend-mode: screen; opacity: 0.085;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='d'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.55' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='600' height='600' filter='url(%23d)'/%3E%3C/svg%3E");
  background-size: 300px 300px;
}

/* The wrap has to out-rank the grain, or the texture lies over the type. */
.dkx .textured > .dkx-wrap { position: relative; z-index: 1; }

/* ══ ORBIT — one centre, four capabilities around it ══
   Slide 4 of the deck. The idea only survives if manufacturing is visibly one
   of four rather than the headline, and a plain row cannot say that: a row has
   no centre for anything to be in orbit around.

   So it is a 3x3 grid with the core in the middle and the four points at twelve,
   three, six and nine o'clock. Block order sets position, so reordering in the
   customiser moves them round the clock.

   The ring is a bordered circle on a pseudo-element rather than an SVG. It has
   to sit behind the type and scale with the box, and a border-radius circle does
   both without a file or a viewBox to keep in sync. */
.dkx .dkx-orbit { position: relative; width: 100%; margin: clamp(56px, 6vw, 96px) auto 0;
                  aspect-ratio: 1.45; }
/* The ring and the four labels are placed from the same two numbers. The ring is
   inset 13%, so its edge sits at 13% and 87%, and each label is centred on one of
   those points. That is the whole fix: before, the labels were in grid cells and
   the ring was a separate centred circle, so they could only line up by accident.

   Each label carries the section's own background colour, which masks the ring
   behind it. That is what produces the arc-with-gaps look in the deck, without
   having to draw four separate arcs and keep their end points in sync. */
/* A tilted ellipse, as in the deck, rather than a circle.

   Every number below comes out of one parametric equation, not from nudging
   things until they looked right. The ellipse has semi-axes a = 0.35 and
   b = 0.245 of the container width, tilted 12 degrees anticlockwise. A point on
   it at angle t sits at

       x = a·cos(t)·cos(-12) - b·sin(t)·sin(-12)
       y = a·cos(t)·sin(-12) + b·sin(t)·cos(-12)

   and the four labels are that equation solved at t = 270, 0, 90 and 180. Which
   is why they are at odd-looking percentages: on a tilted ellipse the top of the
   shape is not above the centre, it is up and slightly left.

   The vertical figures also carry a x1.45 factor, because the container is 1.45
   times wider than it is tall and a percentage of height is not the same
   distance as a percentage of width. */
.dkx .dkx-orbit::before { content: ''; position: absolute; left: 50%; top: 50%;
                          width: 74%; height: 71%;
                          transform: translate(-50%, -50%) rotate(-12deg);
                          border: 2px solid var(--dkx-rule); border-radius: 50%;
                          pointer-events: none; }
.dkx .bg-dark .dkx-orbit::before { border-color: var(--dkx-rule-dark); }

.dkx .dkx-orbit-core,
.dkx .dkx-orbit-point { position: absolute; transform: translate(-50%, -50%); text-align: center; }

.dkx .dkx-orbit-core { left: 50%; top: 50%; width: min(52%, 330px); }
.dkx .dkx-orbit-mark { display: block; font-family: var(--dkx-logo);
                       font-size: clamp(30px, 3.92vw, 60px); font-weight: 400;
                       line-height: 1; letter-spacing: 0.16em; text-transform: uppercase;
                       text-align: center; margin: 0 auto clamp(16px, 1.6vw, 24px); }
.dkx .dkx-orbit-name { font-size: var(--dkx-size-h2); font-weight: var(--dkx-weight-head);
                       letter-spacing: 0.02em; line-height: 1; margin-bottom: 18px; }
.dkx .dkx-orbit-centre { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); opacity: 0.9; }

/* The fill has to stay: it is what breaks the ring so the label is legible on it.
   The outline is what stops that fill reading as a solid block sitting on a line. */
/* Ellipses, not rounded rectangles. An ellipse only contains a rectangle about
   0.7 of its own width and height, so the horizontal padding has to roughly
   double or the last letter of a long label sits outside the curve. That extra
   width is also why the ring came in from 77% to 74%: at the old size the side
   labels ran off the edge of the container.

   Border is 1.5px against the ring's 2px. Matching them would make the label
   read as a break in the line rather than an object sitting on it. */
/* Now circles, with one word to a line. A circle wide enough for the longest
   single word, Manufacturing, fits every label once the words are stacked. */
.dkx .dkx-orbit-point { width: clamp(150px, 18%, 164px); aspect-ratio: 1; padding: 14px;
                        display: flex; align-items: center; justify-content: center; border-radius: 50%;
                        background: var(--dkx-paper); border: 1.5px solid var(--dkx-rule); }
.dkx .bg-stone .dkx-orbit-point { background: var(--dkx-stone); }
.dkx .bg-dark  .dkx-orbit-point { background: var(--dkx-dark); border-color: var(--dkx-rule-dark); }
/* Bold body rather than h3. At h3 the labels compete with the section heading
   above, and every extra character pushes the ring wider. */
.dkx .dkx-orbit-point h3 { font-size: var(--dkx-body-size); font-weight: var(--dkx-weight-head);
                           letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub);
                           margin-bottom: 0; }
/* Solved at t = 270, 0, 90, 180. The top and bottom two are pulled 1.5% toward
   the centre for the same reason as before: at the end of an axis the curve runs
   away from the label across its width, so sitting the box on the single tangent
   point puts the line out through the corners. */
.dkx .dkx-orbit-point.pos-1 { left: 44.9%; top: 16.8%; }
.dkx .dkx-orbit-point.pos-2 { left: 86.2%; top: 38.8%; }
.dkx .dkx-orbit-point.pos-3 { left: 55.1%; top: 83.2%; }
.dkx .dkx-orbit-point.pos-4 { left: 13.8%; top: 61.2%; }

/* Below 900px the clock face stops working. Absolute positioning comes off, the
   square container comes off, and it becomes an ordinary stack with the centre
   first. The ring goes because there is nothing left to orbit. */
@media (max-width: 900px) {
  .dkx .dkx-orbit { aspect-ratio: auto; width: 100%;
                    display: flex; flex-direction: column; align-items: center; gap: 34px; }
  .dkx .dkx-orbit::before { display: none; }
  .dkx .dkx-orbit-path { display: none !important; }
  .dkx .dkx-orbit-point { aspect-ratio: auto !important; display: block !important; }
  .dkx .is-orbiting .dkx-orbit-point, .dkx .is-orbiting .dkx-orbit-point h3 { animation: none !important; }
  .dkx .dkx-orbit-core,
  .dkx .dkx-orbit-point { position: static; transform: none; width: auto; max-width: 420px;
                          background: transparent; padding: 0; }
  .dkx .dkx-orbit-core { order: -1; }
}

.dkx .dkx-orbit-foot { margin-top: 22px; font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                       letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-display);
                       max-width: 560px; }

/* Below 900px the clock face stops working: the side points squeeze to nothing
   long before the layout actually breaks. It becomes one column, centre first,
   and the ring comes off because there is no longer anything to orbit. */
@media (max-width: 900px) {
  .dkx .dkx-orbit { grid-template-columns: 1fr; gap: 40px; }
  .dkx .dkx-orbit::before { display: none; }
  .dkx .dkx-orbit-path { display: none !important; }
  .dkx .dkx-orbit-point { aspect-ratio: auto !important; display: block !important; }
  .dkx .is-orbiting .dkx-orbit-point, .dkx .is-orbiting .dkx-orbit-point h3 { animation: none !important; }
  .dkx .dkx-orbit-core,
  .dkx .dkx-orbit-point.pos-1, .dkx .dkx-orbit-point.pos-2,
  .dkx .dkx-orbit-point.pos-3, .dkx .dkx-orbit-point.pos-4 { grid-column: 1; grid-row: auto; }
  .dkx .dkx-orbit-core { order: -1; }
}

/* The worn-by line under the orbit. Same dot separator the old about-section
   list used, so it reads as the same object moved rather than a new one. */
.dkx .dkx-orbit-worn { margin-top: clamp(48px, 5vw, 78px); padding-top: clamp(28px, 3vw, 44px);
                       border-top: 1px solid var(--dkx-rule); text-align: center; }
.dkx .bg-dark .dkx-orbit-worn { border-top-color: var(--dkx-rule-dark); }
.dkx .dkx-orbit-worn .dkx-eyebrow { margin-bottom: 16px; }
.dkx .dkx-orbit-names { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 0; }
.dkx .dkx-orbit-names span { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); }
.dkx .dkx-orbit-names span:not(:last-child)::after {
  content: '\00a0\00b7\00a0\00a0'; font-weight: 400; opacity: 0.55; }

/* The legend under the orbit. The ring gives the shape, this gives the detail.
   Numbers rather than a repeated heading alone, so a reader can match a column
   back to its point on the circle without counting round it. */
/* The ring is drawn from the centre of the grid outwards, so at some widths its
   lower edge sits below the bottom label. The gap has to clear the circle, not
   just the text, which is why it is roughly double what a normal row would take. */
.dkx .dkx-orbit-legend { display: grid; grid-template-columns: repeat(4, 1fr);
                         gap: clamp(20px, 2.4vw, 40px);
                         margin-top: clamp(104px, 11vw, 180px); }
@media (max-width: 1080px) { .dkx .dkx-orbit-legend { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .dkx .dkx-orbit-legend { grid-template-columns: 1fr; } }
.dkx .dkx-orbit-leg-n { font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400;
                        letter-spacing: 0.21em; opacity: 0.55; margin-bottom: 12px; }
.dkx .dkx-orbit-leg h3 { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
                         letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub);
                         margin-bottom: 10px; }
.dkx .dkx-orbit-leg .dkx-mark { width: 32px; height: 32px; margin-bottom: 16px; }

/* The legend icons carry more parts than a tick, so they draw one piece at a
   time rather than all at once. Each path waits a little longer than the last,
   which is what makes the machine or the globe assemble itself. */
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp { transition-duration: 0.55s; }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(1) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 0ms); }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(2) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 180ms); }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(3) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 330ms); }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(4) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 470ms); }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(5) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 600ms); }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(6) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 720ms); }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(7) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 830ms); }
.dkx-anim .dkx .dkx-orbit-leg .dkx-mark.is-drawn .dkx-dp:nth-child(8) { transition-delay: calc(var(--dkx-draw-delay, 0ms) + 930ms); }
.dkx .dkx-orbit-leg p { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); opacity: 0.85; }

/* The labels keep a solid fill, because it is the only thing stopping the ring
   running straight through the words. Making them see-through would show the
   texture and the line, and the line is the problem.

   So instead of removing the fill, the fill gets the same grain the section has.
   Same frequency, same tile, same opacity, same blend. The box then reads as a
   piece of the background rather than a panel sitting on it, which is what
   "transparent" was actually after. */
.dkx .textured .dkx-orbit-point::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; border-radius: 50%;
  opacity: 0.075; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='320' height='320' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}
.dkx .bg-dark.textured .dkx-orbit-point::before {
  opacity: 0.085; mix-blend-mode: screen;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='d'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.55' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='600' height='600' filter='url(%23d)'/%3E%3C/svg%3E");
  background-size: 300px 300px;
}
/* the label text has to sit above its own grain */
.dkx .dkx-orbit-point h3 { position: relative; z-index: 1; }

/* ══ FOOTER ══
   The second place in this file that reaches outside .dkx, and for the same
   reason as the header nav: the footer belongs to the theme, not to a DKX
   section, and keeping the override here means everything this project changes
   is pushed and reverted as one file.

   The theme writes its footer colours as inline custom properties on the
   <footer> element itself. An inline style beats a stylesheet for the same
   property on the same element, so redefining --section-background here would do
   nothing. The concrete properties have to be set instead, which is why these
   rules carry !important and the variables are not touched.

   What was wrong: the ground was #2c2a28, a warm brown-grey that matches nothing
   else on the site, and the type ran at #d2d2d2 and #e6e6e6, both lighter and
   cooler than the grey used everywhere else. */
.footer { background: var(--dkx-dark) !important; }
.footer,
.footer__copyright,
.footer__navigation-list-link,
.footer__navigation-list-link:visited { color: var(--dkx-type) !important; }
/* Tighter leading. The theme runs the footer list at body leading, which is set
   for paragraphs of running text. These are single-line links stacked in a
   column, so the space between them is doing the separating and the line-height
   only adds to it. 1.25 on the link, with the list-item spacing left alone so
   the gap between entries stays deliberate rather than accidental. */
.footer__navigation-list-link { text-decoration: none !important; transition: color .18s ease;
                                line-height: 1.25 !important; }
.footer__navigation-list-item { line-height: 1.25 !important; margin-bottom: 2px !important; }
/* Footer type matched to the top nav: the theme's body font, the nav's size
   (0.9 of the theme body size), head weight, capitals. The spacing between
   links came from the theme's 7-10px padding on every list item, not from the
   line-height, which is why tightening the leading alone did not close it. */
.footer .footer__navigation-list-link,
.footer .footer__navigation-heading,
.footer .footer__navigation-heading.h2 {
  font-family: inherit !important;
  font-size: calc(var(--body-font-size, 15px) * 0.9) !important;
  font-weight: var(--dkx-weight-head) !important;
  letter-spacing: normal !important;
  text-transform: uppercase !important;
  line-height: 1.2 !important;
}
.footer .footer__navigation-list-item { padding: 3px 0 !important; margin-bottom: 0 !important; }
.footer .footer__navigation-list { margin: 0 !important; padding-bottom: 0 !important; }
.footer .footer__navigation-heading { margin: 0 0 12px !important; }
.footer .footer__copyright { font-size: calc(var(--body-font-size, 15px) * 0.9) !important; }
.footer__navigation-list { line-height: 1.25 !important; }
.footer__copyright { line-height: 1.35 !important; }
.footer__navigation-list-link:hover { color: #ffffff !important; }

/* Section headings take the same treatment as every other small label on the
   site: mono, uppercase, tracked out, one size. The theme sets them as h2, which
   is why they were arriving at heading scale and heading weight. */
.footer__navigation-heading,
.footer__navigation-heading.h2 {
  font-family: var(--dkx-mono) !important;
  font-size: var(--dkx-size-mono) !important;
  font-weight: 400 !important;
  letter-spacing: 0.21em !important;
  text-transform: uppercase !important;
  color: var(--dkx-type) !important;
  line-height: 1.25 !important;
}
.footer--border-top { border-top: 1px solid var(--dkx-rule-dark) !important; }

/* An optional button at the foot of a section, for the places where the argument
   has just landed and the next step should be within reach. Centred, because it
   follows a full-width row rather than a column of text. */
.dkx .dkx-section-cta { margin-top: clamp(76px, 8.5vw, 140px); text-align: center; }

/* The section button is quieter than the one in the CTA band. That band is the
   end of the page and is allowed to shout. These two sit inside the argument, so
   a filled button there reads as an interruption rather than an offer.

   Outline, mono, one grey. Written after the filled rules and at the same
   specificity, so it wins by order rather than by !important. */
.dkx .dkx-section-cta .dkx-btn,
.dkx .bg-paper .dkx-section-cta .dkx-btn,
.dkx .bg-stone .dkx-section-cta .dkx-btn,
.dkx .bg-dark  .dkx-section-cta .dkx-btn {
  background: transparent;
  color: var(--dkx-type);
  border: 1px solid var(--dkx-rule);
  padding: 15px 34px;
  transition: border-color .18s ease, color .18s ease;
}
.dkx .bg-dark .dkx-section-cta .dkx-btn { border-color: var(--dkx-rule-dark); }
/* Hover firms the outline and the type rather than filling the button, so the
   weight of the page does not jump when a cursor crosses it. */
.dkx .dkx-section-cta .dkx-btn:hover { background: transparent; border-color: var(--dkx-type); color: var(--dkx-dark); }
.dkx .bg-dark .dkx-section-cta .dkx-btn:hover { background: transparent; border-color: var(--dkx-type); color: var(--dkx-paper); }

/* The two header links, swapped round.

   CLIENT LOGIN is for people who already have an account, so it does not need a
   button at all. It reads as plain text and firms to black on hover. Its side
   padding comes off as well, or a borderless link keeps a button's footprint and
   the gap to the CTA looks wrong.

   REQUEST ACCESS takes the outline. It is still the primary of the two, because
   an outlined button next to a plain text link is unambiguous, and it fills on
   hover rather than sitting filled all the time. */
.clientlogin.client {
  border: 0 !important;
  background: transparent !important;
  color: var(--dkx-type) !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
  margin-right: 20px !important;
}
.clientlogin.client:hover { background: transparent !important; color: var(--dkx-dark) !important; }

.clientlogin.requestaccess {
  background: transparent !important;
  border: 1px solid var(--dkx-dark) !important;
  color: var(--dkx-type) !important;
  margin-right: 0 !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.clientlogin.requestaccess:hover {
  background: var(--dkx-dark) !important;
  border-color: var(--dkx-dark) !important;
  color: #ffffff !important;
}

/* The CTA on mobile. The theme hides all three .clientlogin links below 768px and
   only reveals them at desktop width, so a phone visitor had no way to contact
   DAKUTX from the header at all. The two logins stay hidden, because someone who
   already has an account can find it, and someone who does not is the one the
   header should be serving.

   It also shrinks. At desktop size the label plus padding does not leave room for
   the logo and the burger on a narrow phone. */
@media (max-width: 767px) {
  .clientlogin.requestaccess {
    display: block !important;
    font-size: 12px !important;
    padding: 6px 12px !important;
    margin-right: 10px !important;
    white-space: nowrap;
    line-height: 1;
  }
}
@media (max-width: 400px) {
  .clientlogin.requestaccess { font-size: 11px !important; padding: 5px 9px !important; letter-spacing: 0; }
}

/* ══ EDITORIAL — the magazine spread ══
   Deliberately a different grammar to the homepage. The homepage is the cover:
   full-bleed images, one statement per screen, nothing to read. These pages are
   the spread inside, where someone has already chosen the subject and will read.

   So the images get smaller and more frequent, the text sits beside them rather
   than under them, and the side alternates so the eye crosses the page on every
   row instead of running straight down one edge. */
.dkx .dkx-ed-row { display: grid; align-items: center;
                   grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
                   gap: clamp(36px, 5vw, 92px); }
/* Tripled. On a spread the white band between rows is what says 'new thought',
   and at the old spacing two rows read as one block with a picture in it. */
.dkx .dkx-ed-row + .dkx-ed-row { margin-top: clamp(228px, 27vw, 450px); }
/* Only the image moves. Putting order on the text as well means two rules to
   keep in step and a stacking order that breaks the moment a row is reordered. */
.dkx .dkx-ed-row.flip .dkx-ed-img { order: 2; }
.dkx .dkx-ed-img img { display: block; width: 100%; height: auto;
                       object-fit: cover; border-radius: 8px; }
/* Barely there. It has to hold the space so the row keeps its shape, but a
   filled grey block reads as a design element rather than as a gap waiting for
   a picture, which is how an empty row ends up looking deliberate. */
.dkx .dkx-ed-placeholder { width: 100%; background: var(--dkx-stone);
                           border: 1px dashed var(--dkx-rule); border-radius: 8px; }
.dkx .bg-dark .dkx-ed-placeholder { background: rgba(255,255,255,0.05); border-color: var(--dkx-rule-dark); }
.dkx .bg-dark .dkx-ed-placeholder { background: rgba(255,255,255,0.05); border-color: var(--dkx-rule-dark); }
.dkx .dkx-ed-text h3 { font-size: var(--dkx-size-h2); font-weight: var(--dkx-weight-head);
                       letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-head);
                       margin-bottom: clamp(34px, 3.4vw, 56px); }
.dkx .dkx-ed-text .dkx-eyebrow { margin-bottom: 18px; }
.dkx .dkx-ed-body { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); max-width: 460px; }
.dkx .dkx-ed-body p + p { margin-top: 18px; }
/* One column below 860px, image first in every row. Alternating sides means
   nothing once there is only one column, and keeping the flip would put some
   images above their text and some below for no reason a reader could follow. */
@media (max-width: 860px) {
  .dkx .dkx-ed-row { grid-template-columns: 1fr; gap: 28px; }
  .dkx .dkx-ed-row.flip .dkx-ed-img { order: 0; }
  .dkx .dkx-ed-row + .dkx-ed-row { margin-top: 120px; }
  .dkx .dkx-ed-body { max-width: none; }
}

/* A stat that states a problem rather than counts one. The mark replaces the
   figure in the same slot, so the column rhythm does not change between a band
   of numbers and a band of points. */
.dkx .dkx-stat-mark { width: 32px; height: 32px; margin-bottom: 18px; }
/* A step above h3. There is no token between h3 and h2, and h2 is 64px, which
   would make a three-point list read as three headings. */
.dkx .dkx-stat-head { font-size: clamp(21px, 2.5vw, 29px); font-weight: var(--dkx-weight-head);
                      letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub);
                      margin-bottom: 15px; }

/* A lighter editorial row, for benefits that are real but secondary. Smaller
   image, tighter gap, so a page can carry seven points without seven identical
   full-height rows. It is the same grammar at a lower volume, which is what
   stops the back half of a long page reading as filler. */
.dkx .dkx-editorial-compact .dkx-ed-row { grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
                                          gap: clamp(28px, 3.4vw, 56px); }
.dkx .dkx-editorial-compact .dkx-ed-row + .dkx-ed-row { margin-top: clamp(96px, 10vw, 170px); }
.dkx .dkx-editorial-compact .dkx-ed-text h3 { font-size: var(--dkx-size-h3);
                                              margin-bottom: clamp(18px, 1.8vw, 28px); }
@media (max-width: 860px) {
  .dkx .dkx-editorial-compact .dkx-ed-row { grid-template-columns: 1fr; }
  .dkx .dkx-editorial-compact .dkx-ed-row + .dkx-ed-row { margin-top: 56px; }
}

/* An image above a column. Every one takes its shape from the section rather
   than from the file, so a row of three is a row of three matching pictures
   however they were cropped on the way in. No drift here: these are a set read
   across, and moving them at different rates would break the row. */
.dkx .dkx-col-img { display: block; width: 100%; height: auto; object-fit: cover;
                    border-radius: 8px; margin-bottom: clamp(20px, 2vw, 32px); }

/* Same slot for a column. Only drawn when the section says it carries images,
   so every other Columns section on the site stays unaffected. */
.dkx .dkx-col-placeholder { width: 100%; background: var(--dkx-stone);
                            border: 1px dashed var(--dkx-rule); border-radius: 8px;
                            margin-bottom: clamp(20px, 2vw, 32px); }
.dkx .bg-dark .dkx-col-placeholder { background: rgba(255,255,255,0.05); border-color: var(--dkx-rule-dark); }

/* The big gap belongs above the label, not below it. A section eyebrow names
   what follows, so it should sit close to the thing it names and the air should
   be between this section and the last one. */
.dkx .has-col-images { padding-top: clamp(150px, 18vw, 300px); }
.dkx .has-col-images .dkx-grid-head,
.dkx .has-col-images .dkx-grid-head.head-eyebrow-only { margin-bottom: clamp(26px, 2.4vw, 40px); }

/* ---------- Drawn marks ----------
   Ticks and crosses draw themselves in when they reach the screen: the open
   circle first, then the check or the X. Paths are hidden only once dkx.js
   has confirmed motion is welcome (html.dkx-anim), so with no script, or with
   reduced motion, every mark is simply there. */
.dkx-anim .dkx .dkx-mark .dkx-dp { stroke-dasharray: 1; stroke-dashoffset: 1; }
.dkx-anim .dkx .dkx-mark.is-drawn .dkx-dp { stroke-dashoffset: 0;
  transition: stroke-dashoffset 0.8s cubic-bezier(0.65, 0, 0.35, 1) var(--dkx-draw-delay, 0ms); }
.dkx-anim .dkx .dkx-mark.is-drawn .dkx-dp + .dkx-dp { transition-duration: 0.5s;
  transition-delay: calc(var(--dkx-draw-delay, 0ms) + 650ms); }

/* ---------- Section divider ----------
   A heavier rule that stops at the content margin rather than running to the
   edge of the screen. */
.dkx .has-divider { position: relative; }
/* The texture rule lifts every .dkx-wrap into normal flow, which had parked this
   line straight under the text above. The extra classes put it back on its own.
   It sits a short, fixed distance above the bottom edge. The section after it
   is set to no space above, so that same distance is all there is between the
   line and the next section's first line: the large space stays above the line
   and the small one sits below it. */
.dkx .dkx-divider, .dkx .textured > .dkx-wrap.dkx-divider { position: absolute; z-index: 1;
  left: 0; right: 0;
  bottom: clamp(64px, 6.5vw, 104px); }
.dkx .dkx-divider hr { border: 0; height: 2px; margin: 0; background: var(--dkx-rule); }
.dkx .bg-dark .dkx-divider hr { background: var(--dkx-acc-rule, #3a3a3a); }

/* The heading of a dark stat band, such as the entry problem, is white. */
.dkx .bg-dark .dkx-band-head { color: #ffffff; }

/* Column headings on dark sections, such as What you also get, are white. */
.dkx .bg-dark .dkx-col h3 { color: #ffffff; }

/* ---------- Balanced headings ----------
   Every heading wraps into lines of even length, so a line is never left
   holding a single word. The line breaks that used to be typed into headings
   have come out of the page content: they were set for one screen width and
   stranded a word at every other. The stacks that are one word per line on
   purpose (the ring names, the hero words) keep their breaks. */
.dkx h1, .dkx h2, .dkx h3, .dkx .dkx-h2, .dkx .dkx-makes-sub, .dkx .dkx-orbit-foot { text-wrap: balance; }
/* Section headings stop about three-quarters of the way across. Without the
   typed breaks a long heading ran the full width on one line. In em, so the
   break falls in the same place at every screen size. The one-size-down
   heading is left alone, because it is meant to sit on one line. */
.dkx .dkx-grid-head .dkx-h2:not(.dkx-h2-down) { max-width: 14em; }
/* Body copy avoids ending a paragraph on a single word. */
.dkx p { text-wrap: pretty; }

/* ---------- Headings follow the background ----------
   Section headings and column headings are near black on white and off-white
   sections, and white on dark ones. Placed before the per-section heading
   rules below, so a section that sets its own colour still wins. Two
   exceptions: a section set to light text over an image keeps white, and the
   hover-reveal answers stay grey until the pointer reaches them. */
.dkx .bg-paper .dkx-h2, .dkx .bg-stone .dkx-h2 { color: var(--dkx-dark); }
.dkx .bg-dark .dkx-h2 { color: #ffffff; }
.dkx .bg-paper .dkx-col h3, .dkx .bg-stone .dkx-col h3,
.dkx .bg-paper .dkx-route h3, .dkx .bg-stone .dkx-route h3 { color: var(--dkx-dark); }
.dkx .bg-dark .dkx-route h3 { color: #ffffff; }
.dkx .bg-dark .dkx-makes-list, .dkx .bg-dark .dkx-makes-sub { color: #ffffff; }
.dkx .bg-paper .dkx-makes-list, .dkx .bg-stone .dkx-makes-list, .dkx .bg-paper .dkx-makes-sub, .dkx .bg-stone .dkx-makes-sub { color: var(--dkx-dark); }
.dkx .bg-paper .tone-light .dkx-h2, .dkx .bg-stone .tone-light .dkx-h2 { color: #ffffff; }
.dkx .bg-paper .is-hover-reveal .dkx-col h3, .dkx .bg-stone .is-hover-reveal .dkx-col h3 { color: var(--dkx-type); }

/* ---------- Heading colours and sub-levels ----------
   Headings on white and off-white sections can be set near black. */
.dkx .dkx-h2.dkx-h2-down { font-size: var(--dkx-size-h3); line-height: var(--dkx-lead-sub); text-transform: uppercase; }
.dkx .bg-paper .dkx-h2.dkx-h2-down, .dkx .bg-stone .dkx-h2.dkx-h2-down { color: var(--dkx-dark); }
.dkx .dkx-subhead { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
  letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub); margin-top: 18px; }
.dkx .bg-paper .dkx-ed-text h3, .dkx .bg-stone .dkx-ed-text h3 { color: var(--dkx-dark); }
/* A sentence picked out inside an editorial row. Shopify rich text only allows
   plain tags, so it is marked as emphasis and styled upright, in black. */
.dkx .bg-paper .dkx-ed-text em, .dkx .bg-stone .dkx-ed-text em { font-style: normal; color: var(--dkx-dark); }
.dkx .bg-dark .dkx-ed-text em { font-style: normal; color: #ffffff; }
.dkx .bg-paper .dkx-tl-head .dkx-h2, .dkx .bg-stone .dkx-tl-head .dkx-h2 { color: var(--dkx-dark); }
.dkx .dkx-grid-head.head-black .dkx-h2 { color: var(--dkx-dark); }
/* The closing call to action on a dark section has a white heading. */
.dkx .bg-dark .dkx-cta-in .dkx-h2 { color: #ffffff; }
/* The closing heading bookends the hero headline. The Labels hero uses the
   split layout, where LABELS // REINVENTED is set at the h2 size, not h1. This
   takes that same size, weight, tracking and solid line spacing, in sentence case. */
.dkx .dkx-cta-in .dkx-h2 { font-size: var(--dkx-size-h2); line-height: 1; }
/* A column section set to a black heading takes black column headings too. */
.dkx .dkx-grid-head.head-black ~ .dkx-grid .dkx-col h3 { color: var(--dkx-dark); }
.dkx .bg-paper .dkx-tl-step h3, .dkx .bg-stone .dkx-tl-step h3 { color: var(--dkx-dark); }
.dkx .dkx-grid-head.head-white .dkx-h2 { color: #ffffff; }
.dkx .dkx-col-num { font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400;
  letter-spacing: 0.21em; line-height: 1; margin-bottom: 14px; }

/* The problem headings in a dark stat band are white. */
.dkx .bg-dark .dkx-stat-head { color: #ffffff; }

/* ---------- Toggles ----------
   A column section set to open and close stacks into one list, each question
   on a hairline, with a plus that turns to a minus when it is open. */
.dkx .dkx-grid.is-toggles { grid-template-columns: 1fr !important; row-gap: 0 !important; column-gap: 0 !important; max-width: 880px; }
.dkx .is-toggles .dkx-col.topline { padding-top: 0; }
.dkx .is-toggles .dkx-col:last-child { border-bottom: 0.4px solid currentColor; }
.dkx .dkx-toggle summary { list-style: none; display: flex; align-items: center; justify-content: space-between;
  gap: 24px; padding: 24px 0; cursor: pointer; }
.dkx .dkx-toggle summary::-webkit-details-marker { display: none; }
.dkx .dkx-col .dkx-toggle summary h3 { margin: 0; }
.dkx .dkx-toggle-mark { position: relative; flex: none; width: 14px; height: 14px; }
.dkx .dkx-toggle-mark::before, .dkx .dkx-toggle-mark::after { content: ""; position: absolute; left: 0; right: 0; top: 50%;
  height: 1.5px; margin-top: -0.75px; background: currentColor; transition: transform 0.25s ease; }
.dkx .dkx-toggle-mark::after { transform: rotate(90deg); }
.dkx .dkx-toggle[open] .dkx-toggle-mark::after { transform: rotate(0deg); }
.dkx .dkx-toggle-body { padding: 0 0 28px; max-width: 700px; }

/* ---------- Hover reveal ----------
   On a computer with a mouse, the text under each heading is hidden until the
   pointer is over that column (or it is tabbed to), then fades up. It is only
   made transparent, never removed, so its space is kept and nothing below it
   moves. Phones and tablets cannot hover, so there it is always shown. */
@media (hover: hover) and (pointer: fine) {
  .dkx .is-hover-reveal .dkx-col p:not(.dkx-col-num) { opacity: 0; transform: translateY(6px);
    transition: opacity 0.35s ease, transform 0.35s ease; }
  .dkx .is-hover-reveal .dkx-col:hover p, .dkx .is-hover-reveal .dkx-col:focus-within p { opacity: 1; transform: none; }
  .dkx .is-hover-reveal .dkx-col h3 { transition: color 0.25s ease; }
  .dkx .bg-paper .is-hover-reveal .dkx-col:hover h3, .dkx .bg-stone .is-hover-reveal .dkx-col:hover h3,
  .dkx .bg-paper .is-hover-reveal .dkx-col:focus-within h3, .dkx .bg-stone .is-hover-reveal .dkx-col:focus-within h3 { color: var(--dkx-dark); }
}
.dkx .is-hover-reveal .dkx-col:focus { outline: none; }

/* ---------- Page accent ----------
   A page can take an accent colour from its hero's settings. The hero writes
   three variables onto the page: one for lights and marks on dark sections,
   one for the timeline's production stretch on light sections, and one for
   the divider rule. Every use below falls back to the site's original colour,
   so a page with no accent looks exactly as it did. */

/* ---------- Orbit motion ----------
   On a dark orbit: the heading and the four capability names are white. A
   light travels the ring every 14s, clockwise from the top, and each name lights
   up as it passes: Manufacturing at 0s, Design at 3.5s, Brand at 7s, Market reach
   at 10.5s. The legend ticks draw on that same 3.5s beat. Nothing moves until
   dkx.js adds .is-orbiting, so without the script the section is unchanged. */
.dkx .bg-dark .dkx-orbit-head .dkx-h2,
.dkx .bg-dark .dkx-orbit-point h3,
.dkx .bg-dark .dkx-orbit-leg h3 { color: #ffffff; }
.dkx .dkx-orbit-path { display: none; position: absolute; left: 50%; top: 50%; width: 74%; height: 71%;
  transform: translate(-50%, -50%) rotate(-12deg); pointer-events: none; }
.dkx .dkx-orbit.is-orbiting .dkx-orbit-path { display: block; }
.dkx .dkx-orbit-x, .dkx .dkx-orbit-y { position: absolute; inset: 0; }
.dkx .is-orbiting .dkx-orbit-x { animation: dkx-orb-x 7s cubic-bezier(0.37, 0, 0.63, 1) -3.5s infinite alternate; }
.dkx .is-orbiting .dkx-orbit-y { animation: dkx-orb-y 7s cubic-bezier(0.37, 0, 0.63, 1) 0s infinite alternate; }
@keyframes dkx-orb-x { from { transform: translateX(-50%); } to { transform: translateX(50%); } }
@keyframes dkx-orb-y { from { transform: translateY(-50%); } to { transform: translateY(50%); } }
.dkx .dkx-orbit-y i { position: absolute; left: 50%; top: 50%; width: 8px; height: 8px; margin: -4px 0 0 -4px;
  border-radius: 50%; background: var(--dkx-dark); box-shadow: 0 0 0 1.5px var(--dkx-acc-on-dark, #ffffff); }
/* Radar: a black dot with a white outline. Every 1.4s it sends out one ring:
   a circle with a crisp white edge and a clean gradient inside, clear at the
   centre and brighter towards the rim. It grows by width and height rather
   than by scaling, so the edge stays sharp instead of blurring into smoke. */
.dkx .dkx-orbit-y i::before { content: ""; position: absolute; left: 50%; top: 50%; width: 8px; height: 8px;
  transform: translate(-50%, -50%); border-radius: 50%; opacity: 0; pointer-events: none;
  background: radial-gradient(circle, transparent 0%, color-mix(in srgb, var(--dkx-acc-on-dark, #ffffff) 8%, transparent) 55%, color-mix(in srgb, var(--dkx-acc-on-dark, #ffffff) 38%, transparent) 100%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--dkx-acc-on-dark, #ffffff) 85%, transparent); }
.dkx .is-orbiting .dkx-orbit-y i::before { animation: dkx-orb-ping 1.4s cubic-bezier(0.2, 0.6, 0.35, 1) infinite; }
@keyframes dkx-orb-ping {
  0%   { width: 8px;  height: 8px;  opacity: 1; }
  100% { width: 46px; height: 46px; opacity: 0; }
}
.dkx .bg-dark .is-orbiting .dkx-orbit-point { animation: dkx-orb-hit 14s linear infinite; }
.dkx .bg-dark .is-orbiting .dkx-orbit-point h3 { animation: dkx-orb-hit-text 14s linear infinite; animation-delay: inherit; }
.dkx .bg-dark .is-orbiting .dkx-orbit-point.pos-1 { animation-delay: 0s; }
.dkx .bg-dark .is-orbiting .dkx-orbit-point.pos-2 { animation-delay: -10.5s; }
.dkx .bg-dark .is-orbiting .dkx-orbit-point.pos-3 { animation-delay: -7s; }
.dkx .bg-dark .is-orbiting .dkx-orbit-point.pos-4 { animation-delay: -3.5s; }
@keyframes dkx-orb-hit {
  0%, 100% { border-color: color-mix(in srgb, var(--dkx-acc-on-dark, #ffffff) 85%, transparent); box-shadow: 0 0 24px 2px color-mix(in srgb, var(--dkx-acc-on-dark, #ffffff) 22%, transparent); }
  10%, 93% { border-color: var(--dkx-rule-dark);   box-shadow: 0 0 0 0 rgba(255,255,255,0); }
}
/* While the light runs, a name is grey and turns white as the light reaches
   it. Without the animation the names stay white. */
@keyframes dkx-orb-hit-text {
  0%, 100% { color: #ffffff; text-shadow: 0 0 14px rgba(255,255,255,0.75); }
  14%, 88% { color: #7d7d7a; text-shadow: 0 0 0 rgba(255,255,255,0); }
}
/* Ticks and crosses on dark sections draw in white with a soft glow, then
   settle back to their normal colour. */
.dkx-anim .dkx .bg-dark .dkx-mark.is-drawn { animation: dkx-mark-glow 2.6s ease-out both; animation-delay: var(--dkx-draw-delay, 0ms); }
.dkx-anim .dkx .bg-dark .dkx-mark.is-drawn .dkx-dp { animation: dkx-mark-lit 2.2s ease-out both; animation-delay: var(--dkx-draw-delay, 0ms); }
.dkx-anim .dkx .bg-dark .dkx-mark.is-drawn .dkx-dp + .dkx-dp { animation-delay: calc(var(--dkx-draw-delay, 0ms) + 650ms); }
@keyframes dkx-mark-lit { 0%, 55% { stroke: #ffffff; } 100% { stroke: var(--dkx-acc-mark-dark, currentColor); } }
@keyframes dkx-mark-glow {
  0%, 50% { filter: drop-shadow(0 0 4px color-mix(in srgb, var(--dkx-acc-on-dark, #ffffff) 60%, transparent)); }
  100%    { filter: drop-shadow(0 0 0 rgba(255,255,255,0)); }
}

/* ---------- Timeline ----------
   One order, left to right. One line of even weight runs dash to dash and
   darkens as the order moves: light grey before production, grey through
   production, black through shipping. Each dash takes the colour of the line
   it sits on. Three pulses travel the line at uneven gaps, and each dash
   flares as a pulse passes it.
   On phones the line turns vertical and the phases are listed above. */
.dkx .dkx-tl { --tl-gap: clamp(16px, 2vw, 32px); --tl-dot: 13px; --tl-line: 2px; --tl-top: 0px;
  --tl-c1: #e2e2df; --tl-c2: var(--dkx-acc-on-light, #a3a39f); --tl-c3: var(--dkx-dark);
  --tl-colw: calc((100% - (var(--tl-n) - 1) * var(--tl-gap)) / var(--tl-n));
  margin-top: clamp(48px, 5.4vw, 88px); }
.dkx .dkx-tl-body { position: relative; }
.dkx .dkx-tl-body.has-phases { padding-top: 40px; --tl-top: 40px; }
.dkx .dkx-tl-rail, .dkx .dkx-tl-steps {
  display: grid; grid-template-columns: repeat(var(--tl-n), minmax(0, 1fr));
  column-gap: var(--tl-gap); list-style: none; margin: 0; padding: 0; }
.dkx .dkx-tl-rail { position: absolute; left: 0; right: 0; top: var(--tl-top); height: var(--tl-dot); z-index: 1; }
.dkx .dkx-tl-seg { grid-row: 1; align-self: center; position: relative; height: var(--tl-line);
  margin-left: calc(var(--tl-dot) / 2);
  margin-right: calc(-1 * (var(--tl-gap) + var(--tl-dot) / 2)); }
.dkx .dkx-tl-seg.w-thick   { background: var(--tl-c2); }
.dkx .dkx-tl-seg.w-thicker { background: var(--tl-c3); }
.dkx .dkx-tl-seg-label { position: absolute; left: 0; bottom: calc(100% + 16px); white-space: nowrap;
  font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400;
  letter-spacing: 0.21em; text-transform: uppercase; }
.dkx .dkx-tl-steps { position: relative; }
.dkx .dkx-tl-steps::before { content: ""; position: absolute; height: var(--tl-line);
  top: calc(var(--tl-dot) / 2 - var(--tl-line) / 2);
  left: calc(var(--tl-dot) / 2); right: calc(var(--tl-colw) - var(--tl-dot) / 2);
  background: var(--tl-c1); }
.dkx .dkx-tl-step { position: relative; padding-top: 38px; }
.dkx .dkx-tl-dot { position: absolute; z-index: 2; width: 2px; height: 12px;
  top: calc(var(--tl-dot) / 2 - 6px); left: calc(var(--tl-dot) / 2 - 1px); background: var(--tl-c1); }
.dkx .tone-c2 .dkx-tl-dot { background: var(--tl-c2); }
.dkx .tone-c3 .dkx-tl-dot { background: var(--tl-c3); }
.dkx .dkx-tl-flow { position: absolute; z-index: 3; pointer-events: none; overflow: hidden;
  height: 40px; top: calc(var(--tl-top) + var(--tl-dot) / 2 - 20px);
  left: calc(var(--tl-dot) / 2); right: calc(var(--tl-colw) - var(--tl-dot) / 2 - 12px); }
/* A pulse is a streak with a lit head: a dark tail that fades out behind it,
   and a white core with its glow pushed behind it, so it trails like a comet. The tail shows on the
   light and grey stretches, the white core shows on the black one. */
.dkx .dkx-tl-flow i { position: absolute; left: 0; top: 50%; width: 140px; height: var(--tl-line);
  margin: calc(var(--tl-line) / -2) 0 0 -140px; opacity: 0;
  background: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--dkx-acc-on-light, #141414) 15%, transparent) 45%, color-mix(in srgb, var(--dkx-acc-on-light, #141414) 90%, transparent) 100%);
  animation: dkx-tl-pulse 6s linear infinite; }
.dkx .dkx-tl-flow i::after { content: ""; position: absolute; right: -3px; top: 50%;
  width: 6px; height: 6px; margin-top: -3px; border-radius: 50%; background: #ffffff;
  box-shadow: -7px 0 9px 1px color-mix(in srgb, var(--dkx-acc-on-light, #141414) 26%, transparent), -20px 0 18px 2px color-mix(in srgb, var(--dkx-acc-on-light, #141414) 9%, transparent); }
.dkx .dkx-tl-flow i:nth-child(2) { animation-delay: -0.8s; }
.dkx .dkx-tl-flow i:nth-child(3) { animation-delay: -3.9s; }
@keyframes dkx-tl-pulse {
  0%   { left: 0;    opacity: 0; }
  3%   { opacity: 1; }
  96%  { opacity: 1; }
  100% { left: calc(100% - 12px); opacity: 0; }
}
/* Three flare layers on each dash, one per pulse, each timed from the step's
   inline --tl-d1/2/3. They sit over the dash and fade, so the dash itself
   never changes and the timeline reads the same with no animation. */
.dkx .dkx-tl-dot > b, .dkx .dkx-tl-dot::before, .dkx .dkx-tl-dot::after {
  content: ""; position: absolute; inset: 0; display: block; opacity: 0;
  background: var(--dkx-dark); box-shadow: 0 0 10px 2px rgba(20,20,20,0.35); }
.dkx .dkx-tl.is-animated .dkx-tl-dot > b     { animation: dkx-tl-flare 6s linear infinite; animation-delay: var(--tl-d1, 0ms); }
.dkx .dkx-tl.is-animated .dkx-tl-dot::before { animation: dkx-tl-flare 6s linear infinite; animation-delay: var(--tl-d2, 0ms); }
.dkx .dkx-tl.is-animated .dkx-tl-dot::after  { animation: dkx-tl-flare 6s linear infinite; animation-delay: var(--tl-d3, 0ms); }
@keyframes dkx-tl-flare {
  0%   { opacity: 1; transform: scaleY(1.7); }
  7%   { opacity: 0; transform: scaleY(1); }
  100% { opacity: 0; transform: scaleY(1); }
}
.dkx .dkx-tl-n { font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400;
  letter-spacing: 0.21em; opacity: 0.55; margin-bottom: 12px; }
.dkx .dkx-tl-step h3 { font-size: var(--dkx-size-h3); font-weight: var(--dkx-weight-head);
  letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub); margin-bottom: 10px; }
.dkx .dkx-tl-step p:not(.dkx-tl-n) { font-size: var(--dkx-body-size); line-height: var(--dkx-lead-body); opacity: 0.85; }
.dkx .dkx-tl-phases-m { display: none; }
@media (max-width: 760px) {
  .dkx .dkx-tl-rail, .dkx .dkx-tl-flow { display: none; }
  .dkx .dkx-tl-body.has-phases { padding-top: 0; }
  .dkx .dkx-tl-phases-m { display: block; list-style: none; margin: 0 0 32px; padding: 0; }
  .dkx .dkx-tl-phases-m li { display: flex; align-items: center; gap: 14px; margin-bottom: 12px;
    font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400;
    letter-spacing: 0.21em; text-transform: uppercase; }
  .dkx .dkx-tl-phases-m span { display: block; width: 36px; height: var(--tl-line); }
  .dkx .dkx-tl-phases-m .w-thick span { background: var(--tl-c2); }
  .dkx .dkx-tl-phases-m .w-thicker span { background: var(--tl-c3); }
  .dkx .dkx-tl-steps { grid-template-columns: 1fr; }
  .dkx .dkx-tl-steps::before { top: 6px; bottom: 6px; left: 5px; right: auto;
    width: var(--tl-line); height: auto; background: var(--tl-c2); }
  .dkx .dkx-tl-step { padding: 0 0 32px 40px; }
  .dkx .dkx-tl-step:last-child { padding-bottom: 0; }
  .dkx .dkx-tl-dot { width: 12px; height: 2px; top: 11px; left: 0.5px; }
  .dkx .dkx-tl.is-animated .dkx-tl-dot > b, .dkx .dkx-tl.is-animated .dkx-tl-dot::before,
  .dkx .dkx-tl.is-animated .dkx-tl-dot::after { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
  .dkx .dkx-tl-flow { display: none; }
  .dkx .dkx-tl.is-animated .dkx-tl-dot > b, .dkx .dkx-tl.is-animated .dkx-tl-dot::before,
  .dkx .dkx-tl.is-animated .dkx-tl-dot::after { animation: none; }
}

/* ---------- Mono stays one size ----------
   Every mono label is var(--dkx-size-mono). Some of them are paragraphs that
   sit inside containers whose own "p" rule sets body size, and that rule was
   winning: the step numbers in The DAKUTX process came out at 16px instead of
   matching the eyebrow above them. These restate the mono size with enough
   weight to win, and sit last in the file so they are never out-ranked. */
.dkx .dkx-col p.dkx-col-num.dkx-col-num,
.dkx .dkx-col p.dkx-eyebrow.dkx-eyebrow,
.dkx .dkx-orbit-leg p.dkx-orbit-leg-n.dkx-orbit-leg-n,
.dkx .dkx-stat p.dkx-eyebrow.dkx-eyebrow,
.dkx .dkx-route p.dkx-route-num.dkx-route-num,
.dkx .dkx-cta-in p.dkx-eyebrow.dkx-eyebrow {
  font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400;
  letter-spacing: 0.21em; line-height: 1; }
.dkx .dkx-h2.tone-black { color: var(--dkx-dark); }

/* ---------- Scroll effects (switched on per page) ----------

   1. Sections fade into each other. dkx.js reads which section is under the
      middle of the screen and blends the page background between its colour
      and the next one's as a boundary passes. The sections themselves go
      transparent while this runs, and their grain is taken off, because a
      grain that stops dead at a boundary would put the hard line back. */
html.dkx-dissolve-on body { background-color: var(--dkx-scroll-bg, #ffffff) !important; }
html.dkx-dissolve-on .dkx > div > .bg-paper,
html.dkx-dissolve-on .dkx > div > .bg-stone,
html.dkx-dissolve-on .dkx > div > .bg-dark { background: transparent !important; }
html.dkx-dissolve-on .dkx .textured::after { display: none; }

/* 2. The problem band holds still and each problem becomes its answer.
      Live only on screens at least 900px wide and 640px tall, set by dkx.js.
      Everywhere else the band reads as before and the answers stay hidden. */
.dkx .dkx-stat-answer { display: none; }
.dkx .dkx-flip-tick { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 0.5s ease 0.3s; }
.dkx .has-pin.is-live .dkx-pin-track { height: calc(var(--pin-h, 750px) + 90vh); }
.dkx .has-pin.is-live .dkx-pin-stage { position: sticky; top: max(104px, calc((100vh - var(--pin-h, 600px)) / 2)); }
.dkx .has-pin.is-live .dkx-pin-stage > .dkx-band-grid { width: 100%; }
.dkx .has-pin.is-live .dkx-stat { position: relative; opacity: 1 !important; padding-bottom: clamp(28px, 3.4vw, 48px); }
.dkx .has-pin.is-live .dkx-stat-answer { display: block; position: absolute; left: 0; right: 0; top: 60px; margin: 0;
  color: #ffffff; opacity: 0; transform: translateY(12px); transition: opacity 0.45s ease 0.15s, transform 0.45s ease 0.15s; }
.dkx .has-pin.is-live .dkx-stat-head:not(.dkx-stat-answer),
.dkx .has-pin.is-live .dkx-stat > p { transition: opacity 0.35s ease, transform 0.35s ease; }
.dkx .has-pin.is-live .dkx-stat.is-flipped .dkx-stat-head:not(.dkx-stat-answer),
.dkx .has-pin.is-live .dkx-stat.is-flipped > p { opacity: 0; transform: translateY(-12px); }
.dkx .has-pin.is-live .dkx-stat.is-flipped .dkx-stat-answer { opacity: 1; transform: none; }
html .dkx .has-pin.is-live .dkx-stat.is-flipped .dkx-mark .dkx-flip-tick { stroke-dashoffset: 0; stroke: var(--dkx-acc-on-dark, #ffffff); }
html .dkx .has-pin.is-live .dkx-stat.is-flipped .dkx-mark .dkx-dp + .dkx-dp { stroke-dashoffset: 1 !important; transition: stroke-dashoffset 0.3s ease !important; }

/* 3. A column section as one sideways row. It swipes on a phone and scrolls
      with a trackpad; dkx.js adds the arrows. The row runs out past the right
      margin, so a cut-off card shows there is more to see. */
.dkx .dkx-grid.is-gallery { grid-template-columns: none !important; grid-auto-flow: column !important;
  grid-auto-columns: clamp(260px, 29%, 420px); column-gap: clamp(20px, 2.4vw, 36px) !important; row-gap: 0 !important;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
  margin-right: calc(var(--dkx-gutter) * -1); padding-right: var(--dkx-gutter); }
.dkx .dkx-grid.is-gallery::-webkit-scrollbar { display: none; }
.dkx .dkx-grid.is-gallery > .dkx-col { scroll-snap-align: start; }
@media (max-width: 700px) { .dkx .dkx-grid.is-gallery { grid-auto-columns: 82%; } }
.dkx .dkx-gal-nav { display: none; justify-content: flex-end; gap: 12px; margin-top: clamp(28px, 3vw, 44px); }
.dkx .dkx-gal-nav.is-ready { display: flex; }
.dkx .dkx-gal-btn { width: 48px; height: 48px; border-radius: 50%; border: 1px solid currentColor; background: transparent;
  color: inherit; cursor: pointer; display: grid; place-items: center; opacity: 0.75; transition: opacity 0.2s ease, background-color 0.2s ease, color 0.2s ease; }
.dkx .dkx-gal-btn:hover { opacity: 1; }
.dkx .bg-dark .dkx-gal-btn:hover { background: #ffffff; color: var(--dkx-dark); }
.dkx .bg-paper .dkx-gal-btn:hover, .dkx .bg-stone .dkx-gal-btn:hover { background: var(--dkx-dark); color: #ffffff; }
.dkx .dkx-gal-btn[disabled] { opacity: 0.25; cursor: default; background: transparent; color: inherit; }
.dkx .dkx-gal-ico { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.5; }

/* ---------- Button halo ----------
   Request access, wherever it appears, lifts on hover with a soft drop
   shadow and no outline. Dark on white sections and in the header, light on
   black sections. */
.dkx .dkx-btn { transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .3s ease; }
.dkx .dkx-section-cta .dkx-btn, .dkx .bg-paper .dkx-section-cta .dkx-btn,
.dkx .bg-stone .dkx-section-cta .dkx-btn, .dkx .bg-dark .dkx-section-cta .dkx-btn { transition: background-color .18s ease, border-color .18s ease, color .18s ease, box-shadow .3s ease; }
.dkx .bg-dark .dkx-btn:hover { box-shadow: 0 10px 30px 2px rgba(255,255,255,0.14); }
.dkx .bg-paper .dkx-btn:hover, .dkx .bg-stone .dkx-btn:hover { box-shadow: 0 10px 28px 2px rgba(20,20,20,0.18); }
.clientlogin.requestaccess:hover { box-shadow: 0 8px 22px 1px rgba(20,20,20,0.2) !important; }

/* On hover the outline goes, leaving only the shadow. */
.dkx .dkx-section-cta .dkx-btn:hover, .dkx .bg-paper .dkx-section-cta .dkx-btn:hover,
.dkx .bg-stone .dkx-section-cta .dkx-btn:hover, .dkx .bg-dark .dkx-section-cta .dkx-btn:hover { border-color: transparent; }

/* Request access buttons have softly rounded corners, in the page, the
   section buttons and the header. */
.dkx .dkx-btn, .dkx .dkx-section-cta .dkx-btn { border-radius: 8px; }

/* The held band is exactly as tall as its content and sits centred on the
   screen while it is held (dkx.js measures it into --pin-h on the track). The track
   is that height plus the scroll distance, as real height: a sticky element
   cannot travel into its container's padding, so padding gave it nowhere to go, so when the last answer is in, the band
   moves on with no empty screen behind it, and the section keeps its normal
   padding. */

/* ---------- Planets without outlines ----------
   The capability circles on the ecosystem ring keep their fill, which is what
   breaks the ring behind each name, but lose the outline. The light passing
   still lifts each one with its glow. */
.dkx .dkx-orbit-point, .dkx .bg-dark .dkx-orbit-point, .dkx .bg-stone .dkx-orbit-point { border: 0 !important; }
/* While sections fade into each other, the page background is one blended
   colour and the section grain is off. The planets follow it: same colour as
   the page at that moment, no grain of their own, so no darker rim shows. */
html.dkx-dissolve-on .dkx .dkx-orbit-point { background: var(--dkx-scroll-bg, var(--dkx-dark)) !important; }
html.dkx-dissolve-on .dkx .dkx-orbit-point::before { display: none !important; }

/* ---------- Badges strip ----------
   Small seals under the hero: an outlined circle with an icon, and a short
   mono label beside it. Compact padding, so it reads as a strip rather than a
   section. */
.dkx .dkx-badges-band { padding-block: clamp(20px, 2.4vw, 36px); }
.dkx .dkx-badges { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 26px clamp(20px, 3vw, 48px); }
.dkx .dkx-badges.count-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.dkx .dkx-badges.count-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.dkx .dkx-badges.count-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.dkx .dkx-badge { display: flex; align-items: center; justify-content: center; gap: 14px; }
.dkx .dkx-mark.dkx-badge-ico { width: 32px; height: 32px; margin: 0; flex: none; }
.dkx .dkx-badge-label { font-family: var(--dkx-mono); font-size: var(--dkx-size-mono); font-weight: 400;
  letter-spacing: 0.21em; text-transform: uppercase; line-height: 1.5; max-width: 16ch; text-wrap: balance; }
.dkx .bg-paper .dkx-badge-label, .dkx .bg-stone .dkx-badge-label { color: var(--dkx-dark); }
.dkx .bg-dark .dkx-badge-label { color: #ffffff; }
@media (max-width: 900px) {
  .dkx .dkx-badges { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .dkx .dkx-badge { justify-content: flex-start; }
}

/* ---------- Boxed call to action ----------
   The closing section as a rounded box of the darker black, sitting on the
   lighter black. Heading, text and button all live inside it. */
.dkx .dkx-cta-box { background: var(--dkx-dark); border-radius: 28px;
  padding: clamp(104px, 11vw, 200px) clamp(24px, 5vw, 96px); }
.dkx .dkx-cta-box > :last-child { margin-bottom: 0; }

/* ---------- Button fill on hover ----------
   Every Request access button lifts on hover with a drop shadow and fills:
     on any black or grey-black background (including the Book a meeting box)
                                 -> white, with near-black type
     on cream (off-white)        -> white
     on white, and in the header -> cream */
.dkx .bg-dark .dkx-btn:hover, .dkx .bg-dark .dkx-section-cta .dkx-btn:hover,
.dkx .dkx-cta-box .dkx-btn:hover { background: #ffffff !important; color: #141414 !important; }
.dkx .bg-stone .dkx-btn:hover, .dkx .bg-stone .dkx-section-cta .dkx-btn:hover { background: #ffffff !important; color: #141414 !important; }
.dkx .bg-paper .dkx-btn:hover, .dkx .bg-paper .dkx-section-cta .dkx-btn:hover { background: #f4f4f2 !important; color: #141414 !important; }

/* ---------- Split hero spacing ----------
   The slashes sit visually centred between the two words. The first word has
   a normal space before its slashes; the gap after them is set a little under
   a full space, because the R of the second word carries more side space of
   its own than the S before the slashes does. The small text above and below keeps a slightly larger gap. It is a fixed length rather
   than a percentage, because a percentage gap cannot be matched vertically.
   The vertical gaps are 8px shorter, because the big capitals already carry
   that much empty space above their tops, so to the eye all three read equal. */
.dkx .dkx-split-hero { --sh-space: clamp(20px, 1.8vw, 28px);
  column-gap: clamp(5px, 0.7vw, 9px) !important; row-gap: max(14px, calc(var(--sh-space) - 6px)); }
.dkx .dkx-split-hero .sh-kicker { margin-bottom: 0; }
.dkx .dkx-split-hero .sh-sub { margin-top: 0; }

/* Badge seals draw themselves in: the outer circle first, then the icon
   inside it, one badge after another. The circle takes 1.6s and the icon
   1.2s, starting as soon as the strip shows at the bottom of the screen. */
.dkx-anim .dkx .dkx-badge-ico.is-drawn .dkx-dp { transition: stroke-dashoffset 1.6s cubic-bezier(0.65, 0, 0.35, 1) var(--dkx-draw-delay, 0ms); }
.dkx-anim .dkx .dkx-badge-ico.is-drawn .dkx-dp ~ .dkx-dp { transition-duration: 1.2s; transition-delay: calc(var(--dkx-draw-delay, 0ms) + 1000ms); }

/* The small line under the hero words lines up with the ink of the second word,
   not its text box. A bold capital R at hero size sits 0.0586em in from its
   box; the F starting the small line sits only 1.37px in. The difference is
   added as padding so the two letters' left edges align. */
.dkx .dkx-split-hero .sh-sub { padding-left: max(0px, calc(var(--dkx-size-h2) * 0.0586 - 1.37px)); }

/* Badge labels in the site grey rather than near black. */
.dkx .bg-paper .dkx-badge-label, .dkx .bg-stone .dkx-badge-label { color: var(--dkx-type); }

/* The gap between the ecosystem heading and the paragraph under it matches the
   gap between heading and body in the image rows. */
.dkx .dkx-orbit-foot { margin-top: clamp(34px, 3.4vw, 56px); }

/* A heading between the ring and the capability columns. It takes the space
   the columns used to have above them, and the columns sit closer under it. */
.dkx .dkx-orbit-leg-head { margin-top: clamp(104px, 11vw, 180px); max-width: 32ch;
  font-size: clamp(22px, 2.4vw, 34px); font-weight: var(--dkx-weight-head);
  letter-spacing: var(--dkx-track-head); line-height: var(--dkx-lead-sub); text-wrap: balance; }
.dkx .bg-dark .dkx-orbit-leg-head { color: #ffffff; }
.dkx .bg-paper .dkx-orbit-leg-head, .dkx .bg-stone .dkx-orbit-leg-head { color: var(--dkx-dark); }
.dkx .dkx-orbit-leg-head + .dkx-orbit-legend { margin-top: clamp(40px, 4vw, 64px); }
@media (max-width: 1080px) { .dkx .dkx-orbit-leg-head { margin-top: 72px; } }

/* ---------- Hero type sizes ----------
   The two big words are set at Heading 1, capped at 7% of the hero's own width
   (cqw), the largest size at which the longest word on any page still fits its
   half. The small lines either side are Heading 4, the quietest heading.

   Even space either side of the slashes. The grid gap is zero; the space after
   the slashes is padding on the second word (0.16em) and the space before them
   is margin on the slashes. The margin adds back the R's own left side space
   (0.0586em) and takes off the average right side space of the letters these
   words end on (S, E, L: about 0.025em), so both gaps look the same. The small
   line under the second word moves over by the same padding, less the F's own
   side space, so it still starts where the R's ink starts. */
.dkx .dkx-split-hero { container-type: inline-size; column-gap: 0 !important; row-gap: clamp(14px, 1.3vw, 22px) !important; }
.dkx .dkx-split-hero .sh-a, .dkx .dkx-split-hero .sh-b { font-size: min(var(--dkx-size-h1), 7cqw); }
.dkx .dkx-split-hero .sh-b { padding-left: 0.16em; }
.dkx .dkx-split-hero .sh-slash { margin-left: 0.1936em; }
.dkx .dkx-split-hero .sh-kicker, .dkx .dkx-split-hero .sh-sub { font-size: var(--dkx-size-h4); line-height: 0.95; }
.dkx .dkx-split-hero .sh-sub { padding-left: max(0px, calc(min(var(--dkx-size-h1), 7cqw) * 0.2416 - 1.37px)); }
@media (max-width: 749px) {
  .dkx .dkx-split-hero .sh-a, .dkx .dkx-split-hero .sh-b { font-size: min(var(--dkx-size-h1), 13cqw); }
  .dkx .dkx-split-hero .sh-b, .dkx .dkx-split-hero .sh-sub { padding-left: 0; }
}

/* Every badge label is exactly two lines: the break is set in the label, and on
   a computer each line is kept from wrapping again. */
@media (min-width: 901px) { .dkx .dkx-badge-label { white-space: nowrap; max-width: none; } }
/* On a phone the icon sits above its label, so each label gets the full column
   width and still holds to two lines. */
@media (max-width: 900px) {
  .dkx .dkx-badge { flex-direction: column; align-items: flex-start; gap: 10px; }
  .dkx .dkx-badge-label { white-space: nowrap; max-width: none; }
}

/* Sections with a photo behind them keep their own solid colour while the
   page fades. A faded photo over a transparent section would take on the
   blended page colour and look washed out. */
html.dkx-dissolve-on .dkx > div > .bg-dark.has-bg-image { background: var(--dkx-dark) !important; }
html.dkx-dissolve-on .dkx > div > .bg-paper.has-bg-image { background: var(--dkx-paper) !important; }
html.dkx-dissolve-on .dkx > div > .bg-stone.has-bg-image { background: var(--dkx-stone) !important; }

/* A badge strip set to keep its background stays solid while the page fades. */
html.dkx-dissolve-on .dkx > div > .bg-paper.keep-bg { background: var(--dkx-paper) !important; }
html.dkx-dissolve-on .dkx > div > .bg-stone.keep-bg { background: var(--dkx-stone) !important; }
html.dkx-dissolve-on .dkx > div > .bg-dark.keep-bg { background: var(--dkx-dark) !important; }

/* The big figures in a dark stat band are white. */
.dkx .bg-dark .dkx-stat-num { color: #ffffff; }

/* ---------- Moving badge strip ----------
   A thin strip that runs edge to edge, one line per badge, sliding left on a
   loop. The track holds the badges four times and moves by one set, so the
   join never shows. Icons are shown fully drawn. */
.dkx .dkx-badges-band.is-thin { padding-block: clamp(10px, 1vw, 15px); }
.dkx .dkx-badges.is-marquee { display: block; width: 100%; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%); }
.dkx .dkx-marquee-track { display: flex; width: max-content; animation: dkx-marquee 40s linear infinite; }
.dkx .dkx-marquee-track .dkx-badge { display: inline-flex; flex-direction: row !important; align-items: center; gap: 12px;
  padding: 0 clamp(28px, 3.2vw, 52px); }
.dkx .dkx-marquee-track .dkx-mark.dkx-badge-ico { width: 28px; height: 28px; }
.dkx .dkx-marquee-track .dkx-badge-label { white-space: nowrap; max-width: none; }
.dkx .dkx-marquee-track .dkx-dp { stroke-dasharray: none !important; stroke-dashoffset: 0 !important; }
@keyframes dkx-marquee { from { transform: translateX(0); } to { transform: translateX(-25%); } }
@media (prefers-reduced-motion: reduce) { .dkx .dkx-marquee-track { animation: none; } }

/* On a black strip the badge icons are white, like the labels. */
.dkx .bg-dark .dkx-badge-ico { color: #ffffff; }

/* A phrase picked out in white inside a dark stat band's figure text. */
.dkx .bg-dark .dkx-stat p em { font-style: normal; color: #ffffff; }

/* ---------- Cards that turn black ----------
   On a white section, each raised card lifts slightly and black sweeps across
   it from left to right, with the type turning white as the sweep passes, one
   card after another. Nothing changes unless dkx.js marks the card, so
   without the script the cards stay white. */
.dkx .is-inking .dkx-col.card-raised { position: relative; overflow: hidden; isolation: isolate;
  transition: opacity .7s cubic-bezier(.22,.61,.36,1), color .3s ease calc(var(--ink-delay, 0ms) + 180ms),
              box-shadow .5s ease var(--ink-delay, 0ms), transform .5s cubic-bezier(.22,.61,.36,1) var(--ink-delay, 0ms); }
/* The ink fills downward, in steps, matching the way the card itself builds.
   It used to scale on X from the left edge, which is what read as the whole
   row sliding left to right. */
.dkx .is-inking .dkx-col.card-raised::before { content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--dkx-dark); transform: scaleY(0); transform-origin: center top;
  transition: transform .45s steps(8, end) var(--ink-delay, 0ms); }
.dkx .is-inking .dkx-col.card-raised.is-inked::before { transform: scaleY(1); }
.dkx .is-inking .dkx-col.card-raised.is-inked { color: #b9b9b5; transform: translateY(-6px);
  box-shadow: 0 2px 4px rgba(20,20,20,.08), 0 16px 32px rgba(20,20,20,.16), 0 32px 64px rgba(20,20,20,.12); }
.dkx .bg-paper .is-inking .dkx-col.is-inked h3, .dkx .bg-stone .is-inking .dkx-col.is-inked h3 { color: #ffffff; }
.dkx .is-inking .dkx-col h3, .dkx .is-inking .dkx-col .dkx-mark { transition: color .3s ease calc(var(--ink-delay, 0ms) + 180ms); }
.dkx .is-inking .dkx-col.is-inked .dkx-mark { color: #ffffff; }

/* ---------- Offer box ----------
   The whole offer (heading, plans and button) sits in one raised box, and the
   plans inside it are outlined rather than raised, so the box reads as the object
   and the plans read as options within it. */
.dkx .dkx-frame .dkx-col.card-line { border-radius: var(--dkx-radius); background: transparent; }
.dkx .dkx-frame .dkx-section-cta:last-child { margin-bottom: 0; }

/* ---------- Button inside a card ----------
   Used where each card in a section is its own path, such as Retail Pro and
   Enterprise, so each gets its own button. The card becomes a column and the
   button drops to the bottom, so buttons line up across cards of different
   lengths. */
.dkx .dkx-col:has(.dkx-card-cta) { display: flex; flex-direction: column; }
.dkx .dkx-col:has(.dkx-card-cta) > p:last-child { flex: 1; display: flex; flex-direction: column; }
.dkx .dkx-card-cta { display: block; margin-top: auto; padding-top: clamp(24px, 2.4vw, 36px); }
.dkx .dkx-card-cta .dkx-btn { display: inline-block; }
/* Two-line card buttons keep an even gap between the lines. */
.dkx .dkx-card-cta .dkx-btn { line-height: 1.7; }
/* Buttons inside a white box (the offer sections). Cream on hover vanishes
   against the white box, so these go light grey instead. */
.dkx .dkx-frame .dkx-btn:hover,
.dkx .bg-paper .dkx-frame .dkx-btn:hover,
.dkx .bg-paper .dkx-frame .dkx-section-cta .dkx-btn:hover { background: #dcdcd9 !important; color: #141414 !important; border-color: transparent !important; }

/* ---------- Bulleted lists in cards ----------
   A card body can't hold a real list (it renders inside a paragraph), so the
   items are spans set as blocks. The dot takes the page accent. */
.dkx .dkx-ul { display: block; margin-top: 14px; }
.dkx .dkx-li { display: block; position: relative; padding-left: 1.15em; }
.dkx .dkx-li + .dkx-li { margin-top: 5px; }
.dkx .dkx-li::before { content: ""; position: absolute; left: 0.1em; top: 0.68em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--dkx-acc-on-light, currentColor); }
.dkx .bg-dark .dkx-li::before { background: var(--dkx-acc-on-dark, currentColor); }
/* In the offer box the hover presses the button in rather than lifting it:
   an inner shadow and a 1px drop, no outer shadow. */
.dkx .dkx-frame .dkx-btn:hover,
.dkx .bg-paper .dkx-frame .dkx-btn:hover,
.dkx .bg-paper .dkx-frame .dkx-section-cta .dkx-btn:hover {
  box-shadow: inset 0 2px 5px rgba(20,20,20,0.28), inset 0 1px 1px rgba(20,20,20,0.18) !important;
  transform: translateY(1px); }
/* Replaces the pressed-in hover above. In the offer box the button lights up in
   the page's own accent (olive, burgundy, ink or bronze) with a soft glow of the
   same colour. The deep version of each accent is used so white type stays readable. */
.dkx .dkx-frame .dkx-btn:hover,
.dkx .bg-paper .dkx-frame .dkx-btn:hover,
.dkx .bg-paper .dkx-frame .dkx-section-cta .dkx-btn:hover {
  background: var(--dkx-acc-on-light, #141414) !important; color: #ffffff !important;
  border-color: transparent !important; transform: none;
  box-shadow: 0 0 0 1px var(--dkx-acc-on-light, #141414),
              0 6px 26px 2px color-mix(in srgb, var(--dkx-acc-on-light, #141414) 45%, transparent) !important; }

/* "Everything in Access, plus:" style lead inside a plan card, sitting between
   the card's one-line description and its bullet list. */
.dkx .dkx-plus { display: block; margin-top: 14px; color: inherit; font-weight: 500; }
.dkx .dkx-plus + .dkx-ul { margin-top: 8px; }

/* Phones: the longer "Production typically / 7-10 business days" badge label
   may wrap rather than run into the screen edge. */
@media (max-width: 600px) {
  .dkx .dkx-badges:not(.is-marquee) .dkx-badge-label { white-space: normal; }
  .dkx .dkx-marquee-track .dkx-badge-label { white-space: nowrap; }
}

/* ── Hero sub head on the mono face ──────────────────────────────────────
   The split hero's kicker and sub were styled as one pair on the heading
   face. The sub now takes the same treatment as every other small label so
   it matches the eyebrow. Weight 400 because the pixel face carries only
   one weight and anything heavier renders as a synthetic bold. Declared
   last so it beats the earlier pair rule and the media-query override
   without needing extra specificity. */
.dkx .dkx-split-hero .sh-kicker,
.dkx .dkx-split-hero .sh-sub {
  font-family: var(--dkx-mono);
  font-weight: 400;
  letter-spacing: 0.09em;
  /* Roughly double the old 16px. Clamped rather than fixed because a rule in
     the mobile block above also sets this size, and both ends land on the
     12-pixel grid the face is drawn on. */
  font-size: clamp(12px, 2vw, 19px);
  line-height: 1.05;
}

/* ── Headings on Helvetica Neue LT Pro ───────────────────────────────────
   Every element styled as a heading, plus the subs that pair with them
   (lede, subhead, the makes and orbit feet). The kit carries this face at
   weight 500 only, so the weight is stated rather than left on
   --dkx-weight-head (700), which the browser renders as a synthetic bold.

   Deliberately NOT listed: .sh-kicker and .sh-sub in the hero, and every
   eyebrow, badge, button and number. Those stay on Lo-Res 12. Declared
   last so it beats the earlier rules without extra specificity. */
.dkx h1, .dkx h2, .dkx h3, .dkx h4,
.dkx .dkx-h1, .dkx .dkx-h2, .dkx .dkx-h4,
.dkx .dkx-lede,
.dkx .dkx-split-l, .dkx .dkx-split-r,
.dkx .dkx-split-hero .sh-a, .dkx .dkx-split-hero .sh-b,
.dkx .dkx-makes-list, .dkx .dkx-makes-sub,
.dkx .dkx-chips-foot,
.dkx .dkx-col.type-l h3, .dkx .dkx-col.type-l p,
.dkx .dkx-col.type-m h3, .dkx .dkx-col.type-s h3,
.dkx .dkx-band-lede,
.dkx .dkx-stat-num, .dkx .dkx-stat-head,
.dkx .dkx-route h3,
.dkx .dkx-orbit-name, .dkx .dkx-orbit-point h3,
.dkx .dkx-orbit-foot, .dkx .dkx-orbit-leg h3, .dkx .dkx-orbit-leg-head,
.dkx .dkx-ed-text h3,
.dkx .dkx-subhead,
.dkx .dkx-tl-step h3 {
  font-family: 'helvetica-neue-lt-pro', 'Inter', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  font-weight: 500;
}

/* The statement takes the eyebrow face. Weight 400 because the face carries
   one weight, and tracking positive because the heading tracking is negative
   and pulls a monospaced face into itself. */
.dkx .dkx-statement {
  font-family: var(--dkx-mono);
  font-weight: 400;
  letter-spacing: 0.06em;
  font-size: clamp(12px, 2vw, 19px);
}

/* ── Lo-Res bit reveal ───────────────────────────────────────────────────
   Characters pop in one at a time rather than the block fading up, so the
   pixel face reads as it is being drawn. No fade on each character: a
   steps(1) transition means it is either off or on, which is the point.

   Nothing is hidden unless the script has run and added .dkx-bits, so a
   page with no JavaScript shows the text normally. The .dkx-r override
   stops the block-level reveal double-handling these elements. */
.dkx-anim .dkx .dkx-bits.dkx-r { opacity: 1; transform: none; transition: none; }
.dkx .dkx-bits .dkx-bit { opacity: 0; }
.dkx .dkx-bits.dkx-bits-in .dkx-bit {
  opacity: 1;
  transition: opacity 1ms steps(1, end);
  transition-delay: calc((var(--bit-i) + var(--bit-j, 0)) * 24ms);
}
@media (prefers-reduced-motion: reduce) {
  .dkx .dkx-bits .dkx-bit { opacity: 1; transition: none; }
}

/* ── Card headings in the 3 and 4 column grids ───────────────────────────
   On the Lo-Res face at the same size as the hero's small type, so the
   cards read as labels rather than as headings. Scoped to cols-3 and
   cols-4 so other column layouts keep the heading face. Weight 400 and
   positive tracking, as everywhere the pixel face is used. */
.dkx .dkx-grid.cols-3 .dkx-col h3,
.dkx .dkx-grid.cols-4 .dkx-col h3,
.dkx .dkx-route h3,
.dkx .dkx-orbit-point h3,
.dkx .dkx-orbit-leg h3 {
  font-family: var(--dkx-mono);
  font-weight: 400;
  letter-spacing: 0.06em;
  font-size: clamp(12px, 2vw, 19px);
}

/* The orbit labels sit inside a ring, so they take the 12px mono size
   rather than the header size the other Lo-Res headings use. 12px is also
   exact on the face's own pixel grid. */
.dkx .dkx-orbit-point h3 {
  font-size: 14px;
  text-transform: uppercase;
  /* The ring has no room for a wrap, so a label that would run on is kept
     on one line. The deliberate breaks in "Brand & Marketing" and "Market
     Reach" come through as <br> and are unaffected by this. */
  white-space: nowrap;
}
/* The legend below the ring has room the ring itself does not, so it takes
   the header size while the labels around the orbit stay at 12px. */
.dkx .dkx-orbit-leg h3 {
  font-size: clamp(12px, 2vw, 19px);
  text-transform: uppercase;
}

/* The what-we-make subheading on the Lo-Res face at the header size. */
.dkx .dkx-makes-sub {
  font-family: var(--dkx-mono);
  font-weight: 400;
  letter-spacing: 0.06em;
  font-size: clamp(12px, 2vw, 19px);
  text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
}

/* The card headings in the 3 and 4 column grids sit at zero tracking. The
   routes and orbit labels keep the 0.06em the rest of the Lo-Res type uses. */
.dkx .dkx-grid.cols-3 .dkx-col h3,
.dkx .dkx-grid.cols-4 .dkx-col h3 {
  letter-spacing: 0;
}

/* Eyebrow-family labels at full strength rather than knocked back. Covers
   every eyebrow, the kicker, the vertical rail and the statement, so they
   all read at the same weight of colour. */
.dkx .dkx-eyebrow,
.dkx .dkx-kicker,
.dkx .dkx-rail span,
.dkx .dkx-statement {
  opacity: 1;
}

/* A tone-light section sits over a photograph even when its background is
   paper or stone. The existing rule only turned the h2 white, so the
   eyebrow and statement stayed in body grey and vanished into the image.
   Scoped to tone-light, so eyebrows everywhere else are untouched. */
.dkx .bg-paper .tone-light .dkx-eyebrow, .dkx .bg-stone .tone-light .dkx-eyebrow,
.dkx .bg-paper .tone-light .dkx-statement, .dkx .bg-stone .tone-light .dkx-statement {
  color: #ffffff;
}

/* Nav on the Lo-Res face. The header is the theme's own markup, so these
   need !important the same way the colour rules above do. 12px because the
   face is drawn on a 12-pixel grid and anything between goes soft, and
   weight 400 because the kit carries only one. */
.header-menu-new .header-menu__item,
.header-menu-new .header-menu__item-text,
.header-menu .header-menu__item,
.header-menu .header-menu__item-text,
.clientlogin, .clientlogin.client, .clientlogin.customer, .clientlogin.requestaccess {
  font-family: var(--dkx-mono) !important;
  font-weight: 400 !important;
  font-size: 12px !important;
  letter-spacing: 0.09em !important;
  text-transform: uppercase !important;
}

/* The lede paragraphs run at heading size but read as body, and the heading
   tracking of -0.045em pulls them too tight at that length. Loosened for
   the stat band lede and the section lede, which are the same style. */
.dkx .dkx-lede,
.dkx .dkx-band-lede,
.dkx .dkx-orbit-foot {
  letter-spacing: -0.015em;
}

/* Pixel icons run larger than the stroke marks they replaced. At 38px a
   20x20 grid gives blocks under 2px and the detail disappears. */

/* The routes section runs on graphite, which renders as bg-dark, so its
   Request access button needs white type. The shared section-CTA rule
   above leaves it on the dark text colour, which all but disappears. */
.dkx .bg-dark .dkx-section-cta .dkx-btn,
.dkx .bg-graphite .dkx-section-cta .dkx-btn {
  color: #ffffff;
}

/* ── Nav re-digitises on hover ───────────────────────────────────────────
   The characters sit visible by default and only run the reveal while the
   replay class is on, so a script or animation failure can never leave the
   menu blank. Driven by an animation rather than a transition because a
   class toggle then restarts it cleanly. */
.dkx-navbits .dkx-bit { opacity: 1; display: inline-block; }
.dkx-navbits.is-replay .dkx-bit {
  opacity: 0;
  animation: dkx-bit-on 1ms steps(1, end) forwards;
  animation-delay: calc((var(--bit-i) + var(--bit-j, 0)) * 26ms);
}
@keyframes dkx-bit-on { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .dkx-navbits.is-replay .dkx-bit { opacity: 1; animation: none; }
}

/* The feature section's eyebrow is the word "dakutx", so it takes the
   condensed logo face rather than the label face the other eyebrows use. */
.dkx .dkx-feature .dkx-eyebrow,
.dkx .dkx-feature-stack .dkx-eyebrow {
  font-family: var(--dkx-logo);
  font-weight: 400;
}

/* The DAKUTX wordmark above a column group: tracked out to match the one in
   the orbit, 30% larger, and at full strength rather than knocked back into
   the body grey. White on dark sections so it does not disappear. */
.dkx .dkx-secmark {
  letter-spacing: 0.16em;
  font-size: calc(var(--dkx-size-mono) * 2.25);
  opacity: 1;
}
.dkx .bg-paper .dkx-secmark, .dkx .bg-stone .dkx-secmark { color: var(--dkx-dark); }
.dkx .bg-dark .dkx-secmark, .dkx .bg-graphite .dkx-secmark { color: #ffffff; }

/* ── Cards build in scanlines ────────────────────────────────────────────
   The four-column cards drop the rise-and-fade and build top to bottom in
   eight discrete bands, using a stepped clip. Opacity and transform are
   neutralised so the generic reveal does not run alongside it.

   The stagger between cards still comes from the transition-delay dkx.js
   sets on each one, so they arrive in order rather than together. */
.dkx-anim .dkx .dkx-grid.cols-4 .dkx-col.dkx-r,
.dkx-anim .dkx .dkx-grid.cols-3 .dkx-col.dkx-r,
.dkx-anim .dkx .dkx-route.dkx-r {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 100% 0);
  transition: clip-path .4s steps(8, end);
}
/* The cards carry a 14px radius. A plain inset clips to a sharp rectangle,
   which squares the corners off and leaves a hard grey edge under the
   bottom of each card. Rounding the clip to the same radius fixes it.

   The drop shadow stays. It was removed at one point along with the sharp
   corner, but on a white card sitting on a white section the shadow is the
   only thing describing the edge, so without it the cards vanish. */
.dkx-anim .dkx .dkx-grid.cols-4 .dkx-col.dkx-r,
.dkx-anim .dkx .dkx-grid.cols-3 .dkx-col.dkx-r,
.dkx-anim .dkx .dkx-route.dkx-r {
  clip-path: inset(0 0 100% 0 round 14px);
}
.dkx-anim .dkx .dkx-grid.cols-3 .dkx-col.dkx-r.dkx-in {
  clip-path: inset(0 0 0 0);
}
.dkx-anim .dkx .dkx-grid.cols-4 .dkx-col.dkx-r.dkx-in,
.dkx-anim .dkx .dkx-grid.cols-3 .dkx-col.dkx-r.dkx-in,
.dkx-anim .dkx .dkx-route.dkx-r.dkx-in {
  clip-path: inset(0 0 0 0 round 14px);
}
@media (prefers-reduced-motion: reduce) {
  .dkx-anim .dkx .dkx-grid.cols-4 .dkx-col.dkx-r,
  .dkx-anim .dkx .dkx-grid.cols-4 .dkx-col.dkx-r.dkx-in,
  .dkx-anim .dkx .dkx-grid.cols-3 .dkx-col.dkx-r,
  .dkx-anim .dkx .dkx-grid.cols-3 .dkx-col.dkx-r.dkx-in,
  .dkx-anim .dkx .dkx-route.dkx-r,
  .dkx-anim .dkx .dkx-route.dkx-r.dkx-in {
    clip-path: none; transition: none; }
}

/* The route card headings are the audience names, so they run in caps like
   the other Lo-Res labels. */
.dkx .dkx-route h3 { text-transform: uppercase; }

/* REINVENTED on Lo-Res 12, the wider of the two pixel faces. Weight 400 and
   positive tracking because the heading tracking is negative and pulls a
   monospaced face into itself. Clamp ends on multiples of 12 so the pixels
   land on whole pixels, and scaled up because Lo-Res has a shorter cap
   height than the Helvetica beside it. */
.dkx .dkx-split-hero .sh-b {
  font-family: var(--dkx-mono);
  font-weight: 400;
  letter-spacing: 0.02em;
  font-size: clamp(42px, 6.6vw, 84px);
}

/* The hero word spells out rather than scattering. The shared reveal adds a
   random jitter to each character so the type arrives with texture; here the
   jitter is ignored and the delay is a clean multiple of the index, so the
   letters land strictly left to right. Slower per character too, because at
   this size it is meant to be read as it appears. */
.dkx .dkx-split-hero .sh-b.dkx-bits.dkx-bits-in .dkx-bit {
  transition-delay: calc(var(--bit-i) * 70ms);
}

/* ── Badge icon relights with its label ─────────────────────────────────
   While a label is re-digitising its icon is dark, then it blinks back on
   once the last character has landed. Stepped, not faded, so it reads as a
   lamp rather than a dissolve. */
.dkx .dkx-badge-ico { transition: none; }
.dkx .dkx-badge-ico.is-off { opacity: 0; }
.dkx .dkx-badge-ico.is-lit { animation: dkx-relight .34s steps(1, end) 1; }
@keyframes dkx-relight {
  0%   { opacity: 0; }
  25%  { opacity: 1; }
  45%  { opacity: 0; }
  65%  { opacity: 1; }
  80%  { opacity: 0; }
  100% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .dkx .dkx-badge-ico.is-off { opacity: 1; }
  .dkx .dkx-badge-ico.is-lit { animation: none; }
}

/* The route cards glow on hover. White, because that section runs on
   graphite, and stepped in only on the shadow so nothing shifts position. */
.dkx .dkx-route { transition: box-shadow .22s ease, background-color .22s ease; }
/* The card fills white on hover and the type reverses, matching the way the
   Request access button behaves under it. The bg-dark selectors are carried
   here because the existing hover rule is scoped that way and would
   otherwise outrank this on specificity. */
.dkx .dkx-route:hover, .dkx .dkx-route:focus-visible,
.dkx .bg-dark .dkx-route:hover, .dkx .bg-dark .dkx-route:focus-visible,
.dkx .bg-graphite .dkx-route:hover, .dkx .bg-graphite .dkx-route:focus-visible {
  background: #ffffff;
  color: var(--dkx-dark);
  box-shadow: 0 0 0 1px rgba(255,255,255,0.35), 0 0 34px 3px rgba(255,255,255,0.25);
}
.dkx .dkx-route:hover h3, .dkx .dkx-route:hover p,
.dkx .dkx-route:hover .dkx-go, .dkx .dkx-route:hover .dkx-route-num,
.dkx .bg-dark .dkx-route:hover h3, .dkx .bg-dark .dkx-route:hover p,
.dkx .bg-dark .dkx-route:hover .dkx-go, .dkx .bg-dark .dkx-route:hover .dkx-route-num,
.dkx .bg-graphite .dkx-route:hover h3, .dkx .bg-graphite .dkx-route:hover p,
.dkx .bg-graphite .dkx-route:hover .dkx-go {
  color: var(--dkx-dark);
}
/* The mark is stroked in currentColor, so it reverses with the type. */
.dkx .dkx-route:hover .dkx-mark { stroke: var(--dkx-dark); color: var(--dkx-dark); }

/* Section CTA buttons on light sections read in black rather than the body
   grey, and fill black on hover instead of only firming the outline. The
   bg-paper and bg-stone selectors are carried so this outranks the shared
   section-CTA rule above it. */
.dkx .bg-paper .dkx-section-cta .dkx-btn,
.dkx .bg-stone .dkx-section-cta .dkx-btn {
  border-color: var(--dkx-dark);
  color: var(--dkx-dark);
}
/* !important is needed here, not for weight but to beat an earlier rule that
   already uses it: a bg-paper hover further up sets a pale fill with
   !important, which a later, more specific rule still loses to. */
.dkx .bg-paper .dkx-section-cta .dkx-btn:hover,
.dkx .bg-paper .dkx-section-cta .dkx-btn:focus-visible,
.dkx .bg-stone .dkx-section-cta .dkx-btn:hover,
.dkx .bg-stone .dkx-section-cta .dkx-btn:focus-visible {
  /* White fill with black type, matching the way these behave on the dark
     sections. The border stays black so the button still has an edge on a
     white background, where a white fill alone would leave nothing to see. */
  background: #ffffff !important;
  border-color: var(--dkx-dark) !important;
  color: var(--dkx-dark) !important;
}

/* START HERE and its arrow run white on the route cards, which sit on
   graphite. Declared before the hover rule below, because a bg-scoped
   selector would otherwise outrank the hover and stop the type reversing
   when the card fills white. */
.dkx .bg-dark .dkx-route .dkx-go,
.dkx .bg-graphite .dkx-route .dkx-go,
.dkx .bg-dark .dkx-route .dkx-go svg,
.dkx .bg-graphite .dkx-route .dkx-go svg {
  color: #ffffff;
  stroke: #ffffff;
}
.dkx .bg-dark .dkx-route:hover .dkx-go,
.dkx .bg-graphite .dkx-route:hover .dkx-go,
.dkx .bg-dark .dkx-route:hover .dkx-go svg,
.dkx .bg-graphite .dkx-route:hover .dkx-go svg {
  color: var(--dkx-dark);
  stroke: var(--dkx-dark);
}


/* Request access: square, and no drop shadow resting or hovered. Scoped to
   the button itself rather than to any header link pointing at the contact
   page, which is what used to dress the Contact nav item as a button too. */
.clientlogin.requestaccess,
.clientlogin.requestaccess:hover {
  border-radius: 0 !important;
  box-shadow: none !important;
}

/* The header button reads in black at rest, with its outline to match. The
   hover state already fills black with white type and is left alone. */
.clientlogin.requestaccess {
  color: var(--dkx-dark) !important;
  border-color: var(--dkx-dark) !important;
}

/* Trial: the strip keeps its icons but loses the ring around each one, so
   the mark reads on its own. The circle is a separate element inside the
   SVG, so hiding it leaves the glyph untouched and is a one-line revert. */
.dkx .dkx-badge-ico circle { display: none; }

/* ── Contact form, brought into the system ──────────────────────────────
   The form is the theme's own section and ships on Jost and Nunito Sans
   with grey fills. These rules restate it in the DKX faces. Scoped to the
   contact__ class names, which only exist on that section, so nothing
   else is touched. !important throughout because the theme's own
   stylesheet loads after this one. */
.contact__title,
.contact__info-title,
.contact__form-title {
  font-family: 'helvetica-neue-lt-pro', 'Inter', -apple-system, sans-serif !important;
  font-weight: 500 !important;
  letter-spacing: -0.02em !important;
  color: var(--dkx-dark) !important;
  text-transform: none !important;
}
.contact__info-heading,
.contact__info h4,
.contact__info .h4 {
  font-family: var(--dkx-mono) !important;
  font-weight: 400 !important;
  font-size: 12px !important;
  letter-spacing: 0.21em !important;
  text-transform: uppercase !important;
  color: var(--dkx-dark) !important;
}
.contact__form input,
.contact__form textarea,
.contact__textarea,
.contact__form .input {
  font-family: 'helvetica-neue-lt-pro', 'Inter', -apple-system, sans-serif !important;
  font-size: 15px !important;
  color: var(--dkx-dark) !important;
  background: #ffffff !important;
  border: 1px solid #e2e2e2 !important;
  border-radius: 0 !important;
  padding: 14px 16px !important;
}
.contact__form input:focus,
.contact__form textarea:focus,
.contact__textarea:focus {
  border-color: var(--dkx-dark) !important;
  outline: none !important;
}
/* The theme puts a placeholder AND a floating label on every field, and
   keeps the placeholder invisible so only the label shows. Forcing the
   placeholder visible made both render, one over the other. The label is
   the thing to style. */
.contact__form .input-label {
  font-family: 'helvetica-neue-lt-pro', 'Inter', -apple-system, sans-serif !important;
  color: var(--dkx-type) !important;
}

.contact__button,
.contact__form .button,
.contact__form .button--secondary {
  font-family: var(--dkx-mono) !important;
  font-weight: 400 !important;
  font-size: 12px !important;
  letter-spacing: 0.21em !important;
  text-transform: uppercase !important;
  background: transparent !important;
  color: var(--dkx-dark) !important;
  border: 1px solid var(--dkx-dark) !important;
  border-radius: 0 !important;
  padding: 15px 34px !important;
  box-shadow: none !important;
  transition: background-color .18s ease, color .18s ease !important;
}
.contact__button:hover,
.contact__form .button:hover,
.contact__form .button--secondary:hover {
  background: var(--dkx-dark) !important;
  color: #ffffff !important;
  border-color: var(--dkx-dark) !important;
}

/* ── Contact section geometry ───────────────────────────────────────────
   The theme's contact section runs its own width, background and page
   title. These three rules sit it inside the DKX grid instead: the same
   1280px measure and gutter every other section uses, a paper background
   rather than the theme's grey, and the page title hidden because the
   section already carries its own heading. */
/* Literal values, not the variables. --dkx-max, --dkx-gutter and
   --dkx-paper are declared on .dkx rather than :root, and this section
   sits outside .dkx, so var() resolves to nothing and the whole
   declaration is dropped. That is why max-width computed as none. */
.contact__container {
  max-width: 1280px !important;
  margin-left: auto !important;
  margin-right: auto !important;
  padding-left: clamp(28px, 5.75vw, 83px) !important;
  padding-right: clamp(28px, 5.75vw, 83px) !important;
  box-sizing: border-box !important;
}
.contact,
.contact__content,
[id*="contact-page-template"] {
  background: #ffffff !important;
}
.contact__title { display: none !important; }

/* ── Unboxed columns must not clip horizontally ─────────────────────────
   A column with no card around it has its text hard against its own edge,
   so a clip that rounds the corners shaves the first glyph of the first
   and last lines. A zero loses its left side and reads as a J.

   Carded columns are fine, because their padding holds the text clear of
   the corner, so they keep the rounded clip. Unboxed ones get a clip that
   is inset negatively on both sides: the downward build still works, and
   nothing is ever cut horizontally. Declared last so it wins. */
.dkx-anim .dkx .dkx-col.dkx-r:not(.card-raised):not(.card-fill):not(.card-line) {
  clip-path: inset(0 -8px 100% -8px);
}
.dkx-anim .dkx .dkx-col.dkx-r.dkx-in:not(.card-raised):not(.card-fill):not(.card-line) {
  clip-path: inset(0 -8px 0 -8px);
}

/* Room under the apply button before the section ends. */
.contact__form .contact__button,
.contact__form .button {
  margin-bottom: clamp(40px, 5vw, 80px) !important;
}

/* The real class names on that section are contact__content-col-heading
   and contact__content-info-heading. The earlier rules guessed at
   contact__form-title and contact__info-title, which match nothing, so
   both headings stayed on the theme's own face. */
.contact__content-col-heading,
.contact__content .h2,
.contact__content h2 {
  font-family: 'helvetica-neue-lt-pro', 'Inter', -apple-system, sans-serif !important;
  font-weight: 500 !important;
  letter-spacing: -0.02em !important;
  color: #141414 !important;
}
.contact__content-info-heading,
.contact__content-info h4,
.contact__content-info .h4 {
  font-family: var(--dkx-mono) !important;
  font-weight: 400 !important;
  font-size: 12px !important;
  letter-spacing: 0.21em !important;
  text-transform: uppercase !important;
  color: #141414 !important;
}


/* Secondary text link under a CTA button (21 Sep 2026). Lo-Res face, small,
   underlined, so it reads as a step sideways rather than a second button.
   Literal values only: this sits inside .dkx, so .dkx variables resolve. */
.dkx .dkx-cta-more { margin-top: 22px; text-align: center; }
.dkx .dkx-cta-more a {
  font-family: var(--dkx-mono); font-weight: 400; font-size: 13px; letter-spacing: 0.06em;
  text-transform: uppercase; text-decoration: underline; text-underline-offset: 4px;
  color: var(--dkx-type); opacity: .8; transition: opacity .18s ease;
}
.dkx .bg-dark .dkx-cta-more a, .dkx .dkx-cta-box .dkx-cta-more a { color: #ffffff; }
.dkx .dkx-cta-more a:hover { opacity: 1; }


/* Pricing and process column headings stay on Helvetica (21 Sep 2026).
   The 3 and 4 column grids set their card headings in Lo-Res so they read as
   labels. The offer section is the pricing section on every audience page, and
   on Corporate it has three columns, so it picked that up. The process section
   is the six steps, also three columns. This puts both back on the heading face
   and weight used by the 2 column offers.
   Each section id ends in its key ("offer", "process"), which is how they are
   targeted. This is listed after the Lo-Res rules so it wins at equal
   specificity. */
[id$="__offer"] .dkx .dkx-grid .dkx-col.type-m h3,
[id$="__process"] .dkx .dkx-grid .dkx-col.type-m h3 {
  font-family: 'helvetica-neue-lt-pro', 'Inter', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  font-size: var(--dkx-size-h3);
  font-weight: var(--dkx-weight-head);
  letter-spacing: var(--dkx-track-head);
  line-height: var(--dkx-lead-sub);
}
