:root {
    /* The logo diamond, shifted to a 0-origin viewBox - its path was
       authored at x=100..116. Shared by the rail thumb and the hero
       scroll cue so the geometry exists once. */
    --dni-diamond: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16.172 24'%3E%3Cpath d='M8.086 0C11.561 7.94402 16.172 13 16.172 13L15.951 13.2003C14.952 14.1297 10.786 17.2664 8.086 23.9973L8.089 23.9824L8.084 24L8.081 23.9862C4.995 16.3005 0 13 0 13C0.022 12.9807 4.618 7.92511 8.086 0L8.085 0.00159801L8.093 0.0287642L8.086 0Z' fill='%23000'/%3E%3C/svg%3E");
}

/* =========================================
   SECTION SLIDER

   A vertical navigator on the right edge: a
   track, a tick per section, and a thumb
   that slides to whichever section you are
   in. Click a tick to travel there.

   No blend modes and no labels. The first
   version used mix-blend-mode: difference so
   the marks would invert over light and dark
   sections - it worked, but difference
   against mid-lilac returns muddy colours,
   which is why it flashed red over the hero.
   Brand violet at full strength is legible
   on both grounds without any trickery:
   #7E29FE reads 4.8:1 against the light
   sections and 2.8:1 against black, and this
   is a mark rather than text, so both are
   comfortably visible.
   ========================================= */

.dni-rail {
    --rail-step: 38px;          /* one stop; the thumb travels in these */

    /* the one line everything on the rail is measured from, in from the
       rail's own right edge */
    --rail-axis: 11px;

    /* the logo diamond, lifted from the button mark and shifted to a
       0-origin viewBox (its path was authored at x=100..116) */
    /* one sine period, 8x40, drawn down the middle of its box; repeated
       vertically it makes the rail read as a wave rather than a ruled line */
    --rail-wave: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 40'%3E%3Cpath d='M4 0C1.1 10 6.9 30 4 40' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");

    --rail-diamond: var(--dni-diamond);

    /* Palette, swapped by script according to what is actually behind the
       rail. Default is the light-ground set. */
    --rail-ink: #7E29FE;        /* thumb, active tick, ribbon head */
    --rail-ink-soft: rgba(126, 41, 254, .70);
    --rail-track: rgba(126, 41, 254, .50);
    --rail-halo: rgba(255, 255, 255, .92);
    --rail-glow: rgba(126, 41, 254, .55);

    position: fixed;
    top: 50%;
    right: 14px;   /* tight to the edge, clear of the content column */
    transform: translateY(-50%);
    z-index: 60;
    margin: 0;
    padding: 0;
    list-style: none;

    /* The site's container leaves only ~24-48px of gutter at 1200-1440px,
       so the rail's box necessarily overlaps the content column there. It
       therefore catches no pointer events itself - only the marks and the
       scrubber do, and those sit in the outermost ~36px. Without this the
       rail would quietly swallow clicks on the footer links underneath
       it. */
    pointer-events: none;
}

.dni-rail__btn,
.dni-rail__scrub {
    pointer-events: auto;
}

/* below this there is no room beside the content, and a phone has the
   off-canvas menu already */
@media (max-width: 1199px) {
    .dni-rail { display: none; }
}

/* ---- the track ---------------------------------------------- */
/* ---- the track ----------------------------------------------
   A hairline, not a drawn line. Everything on the rail shares one axis,
   --rail-axis, measured in from the rail's right edge, so the track, the
   progress bar, the thumb and the end of every tick are on it by
   construction rather than by four separate numbers agreeing.

   The wave is gone. A navigator's job is to report position precisely; a
   hand-drawn stem says the opposite of precise, and at 1px of ink the
   wobble was most of what you could see. */
.dni-rail::before {
    content: "";
    position: absolute;
    right: calc(var(--rail-axis) - .5px);
    top: 0;
    bottom: 0;
    width: 1px;
    background: linear-gradient(to bottom,
        transparent,
        var(--rail-track) 8%,
        var(--rail-track) 92%,
        transparent);
}

/* ---- the light that travels the track -----------------------
   A short segment of brand violet runs the length of the hairline and
   fades out at each end. It is the one thing on the rail that moves
   without being asked to, so it reads as a live instrument rather than a
   drawn ruler - and it is on the same 1px axis, so it costs no width.

   background-position rather than transform: the segment has to travel
   inside a 1px box that is already the full height of the rail, and
   moving the paint is cheaper than moving a second layer over it. */
.dni-rail::after {
    content: "";
    position: absolute;
    right: calc(var(--rail-axis) - .5px);
    top: 0;
    bottom: 0;
    width: 1px;
    background-image: linear-gradient(to bottom,
        transparent 0%,
        var(--rail-ink) 42%,
        var(--rail-ink) 58%,
        transparent 100%);
    background-size: 100% 64px;
    background-repeat: no-repeat;
    background-position: 0 -64px;
    animation: dni-rail-run 4.6s cubic-bezier(.55, 0, .45, 1) infinite;
    pointer-events: none;
}

@keyframes dni-rail-run {
    0%        { background-position: 0 -64px; opacity: 0; }
    14%       { opacity: .75; }
    78%       { opacity: .75; }
    100%      { background-position: 0 100%; opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .dni-rail::after { animation: none; opacity: 0; }
}

/* ---- the thumb ---------------------------------------------- */
/* The brand diamond, sized to the track and carrying its own glow so it
   stays findable against the black sections. It is positioned by
   translateY in multiples of --rail-step, set from script. */
.dni-rail__thumb {
    position: absolute;

    /* On the line, not beside it. The track sits at right:8px and is 2px
       wide, so its axis is 9px in; the ticks (18px, flush right) and the
       ribbon (right:7px, 4px wide) are both centred on that same 9px. The
       thumb was at right:3px with an 18px box, putting its centre at 12px
       - 3px off every other mark on the rail. right:0 puts it back on. */
    /* Size is driven from the height alone. The mark's own ratio is
       16.172:24 = .674, so the box follows it, and `right` is solved from
       the 9px axis rather than typed - change --thumb-h and it stays on
       the line. */
    --thumb-h: 22px;
    --thumb-w: calc(var(--thumb-h) * .674);
    right: calc(var(--rail-axis) - var(--thumb-w) / 2);
    top: 0;
    width: var(--thumb-w);
    height: var(--thumb-h);
    margin-top: calc((var(--rail-step) - var(--thumb-h)) / 2);

    /* The brand mark itself rather than a plain rhombus - the same
       geometry as the .dni-mark in the buttons, masked so the token
       colours still drive it. Its own 16.172x24 ratio is preserved by
       `contain`, and it stays centred in the 18px box, so the axis above
       still holds. */
    background: var(--rail-ink);
    -webkit-mask: var(--rail-diamond) center / contain no-repeat;
            mask: var(--rail-diamond) center / contain no-repeat;

    /* drop-shadow, not box-shadow: a mask clips the border box, which
       takes any box-shadow with it. drop-shadow follows the alpha of the
       mark, so the separation ring and the glow trace the shape. */
    /* one tight ring to separate it from whatever is behind, one soft
       glow to seat it. Three stacked shadows only muddied the edge. */
    filter: drop-shadow(0 0 1.5px var(--rail-halo))
            drop-shadow(0 0 5px var(--rail-glow));
    transform: translateY(calc(var(--rail-at, 0) * var(--rail-step)));
    /* Short and linear. The thumb now follows scroll continuously, so a
       long eased transition would lag behind the page instead of easing
       into place - this only smooths frame-to-frame jitter. A click still
       reads as a glide because Lenis eases the scroll itself. */
    transition: transform .09s linear;
    pointer-events: none;
}

/* ---- the stops ---------------------------------------------- */
.dni-rail__item {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    height: var(--rail-step);
}

.dni-rail__btn {
    appearance: none;
    border: 0;
    background: none;
    /* padding only on the left of the mark, so the button box hugs the
       edge rather than reaching back across the content */
    padding-block: 0;
    padding-inline: 14px var(--rail-axis);
    height: var(--rail-step);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    cursor: pointer;
}

/* ---- the stop's name ---------------------------------------- */
/* Revealed on hover or focus, so the rail can be read before it is used.
   It is laid out but not painted at rest - visibility and opacity rather
   than display, so the width is stable and revealing it cannot reflow the
   rail or shift the ticks. pointer-events stay off so the chip can never
   intercept a click meant for the tick beside it. */
.dni-rail__name {
    position: absolute;
    right: 34px;
    white-space: nowrap;
    font-family: Inter, sans-serif;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .01em;
    line-height: 1;
    padding: 7px 11px;
    border-radius: 7px;
    color: var(--rail-name-ink, #2F086D);
    background: var(--rail-name-bg, rgba(255, 255, 255, .94));
    box-shadow: 0 6px 20px rgba(47, 8, 109, .16);
    opacity: 0;
    visibility: hidden;
    transform: translateX(6px);
    transition: opacity .18s ease-out,
                transform .18s cubic-bezier(.22, 1, .36, 1),
                visibility 0s linear .18s;
    pointer-events: none;
}

.dni-rail__btn:hover .dni-rail__name,
.dni-rail__btn:focus-visible .dni-rail__name {
    opacity: 1;
    visibility: visible;
    transform: translateX(0);
    transition-delay: 0s;
}

.dni-rail[data-on="dark"] {
    --rail-name-ink: #1A0733;
    --rail-name-bg: rgba(236, 231, 255, .96);
}

@media (prefers-reduced-motion: reduce) {
    .dni-rail__name { transition: opacity .01s, visibility 0s; }
}

/* Short and level, stopping exactly on the axis rather than crossing it.
   A tick's job is to mark a position, and 30px of bar marks a region. The
   active one earns its length. */
.dni-rail__tick {
    display: block;
    width: 9px;
    height: 1px;
    border-radius: 1px;
    background: var(--rail-ink-soft);
    opacity: .65;
    transition: width .26s cubic-bezier(.22, 1, .36, 1),
                opacity .26s ease-out,
                background-color .26s ease-out;
}

.dni-rail__btn:hover .dni-rail__tick,
.dni-rail__btn:focus-visible .dni-rail__tick {
    width: 18px;
    opacity: 1;
    background: var(--rail-ink);
}

/* The current stop reads as lit rather than merely longer. */
.dni-rail__item[aria-current="true"] .dni-rail__tick {
    width: 22px;
    height: 2px;
    opacity: 1;
    background: var(--rail-ink);
}

/* hello-elementor's reset.css styles every bare <button> on the site:

       button:focus, button:hover { background: #CC3366; color: #fff }

   #CC3366 is nowhere in the brand, and :hover is precisely when someone
   is using this rail - so a red block appeared under the cursor on every
   tick. My first pass covered :focus and :active and missed :hover,
   which is why it survived. All four states are named here, and `color`
   too: the reset also sets it, and `currentColor` is what the tick's
   outline and border resolve from. */
.dni-rail__btn,
.dni-rail__btn:hover,
.dni-rail__btn:focus,
.dni-rail__btn:active,
.dni-rail__btn:focus-within {
    outline: none;
    background: none !important;
    box-shadow: none;
    color: inherit !important;
}

.dni-rail__btn:focus-visible {
    outline: 2px solid var(--rail-ink);
    outline-offset: 3px;
    border-radius: 3px;
}

@media (prefers-reduced-motion: reduce) {
    .dni-rail__thumb,
    .dni-rail__tick { transition: none; }
}

/* ---- the ribbon ---------------------------------------------- */
/* A progress ribbon down the track: it fills as the page scrolls, and it
   can be grabbed and dragged to travel the whole page in one gesture -
   the ticks jump between sections, this scrubs continuously.

   It sits under the ticks in the stack so the marks stay legible on top
   of it, and it is drawn with scaleY from the top rather than by
   animating height, which keeps it on the compositor. */
.dni-rail__ribbon {
    position: absolute;
    right: calc(var(--rail-axis) - 1px);
    top: 0;
    width: 2px;
    border-radius: 2px;
    height: calc(100% * var(--rail-progress, 0));
    background: var(--rail-ink);
    opacity: .9;
    pointer-events: none;
}

/* the grab area is wider than the ribbon, or it is unhittable */
.dni-rail__scrub {
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 22px;
    cursor: grab;
    touch-action: none;
}

.dni-rail__scrub:active { cursor: grabbing; }

.dni-rail.is-scrubbing .dni-rail__thumb,
.dni-rail.is-scrubbing .dni-rail__ribbon {
    transition: none;      /* follow the finger exactly while dragging */
}

/* ---- the dark-ground set ------------------------------------- */
/* Set when the script finds a dark ground behind the rail. Violet on
   black is legible but dull; this lifts the marks to the pale end of the
   brand so they read as lit, and swaps the separating halo from white to
   near-black so it still separates. */
.dni-rail[data-on="dark"] {
    --rail-ink: #C9A9FF;
    --rail-ink-soft: rgba(201, 169, 255, .74);
    --rail-track: rgba(201, 169, 255, .46);
    --rail-halo: rgba(10, 3, 20, .85);
    --rail-glow: rgba(185, 140, 255, .55);
}

/* the transition is on the colours, so a section change reads as the rail
   adapting rather than blinking */
.dni-rail__tick,
.dni-rail__thumb,
.dni-rail__ribbon,
.dni-rail::before {
    /* height is deliberately NOT in this list. It is the ribbon's progress
       now that scaleY is gone, and it is driven directly by scroll - easing
       it over .35s makes the ribbon lag the page instead of tracking it.
       Only the palette swap is eased. */
    transition-property: background-color, background, box-shadow, width;
    transition-duration: .35s;
    transition-timing-function: ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .dni-rail__tick,
    .dni-rail__thumb,
    .dni-rail__ribbon,
    .dni-rail::before { transition: none; }
}
