/* --------------------------------------------------
   Fluid sizes

   Sizes the Elementor kit has no variable for, built the same way the kit's
   own are: phone at 375px, tablet at 768px, desktop at 1390px, fixed
   outside that range. The comment on each is phone / tablet / desktop.
   -------------------------------------------------- */

:root {
    /* Icons */
    --ds-icon-size-300: calc(clamp(11px, 16.87px - 0.765vw, 14px) + clamp(11px, 4.8px + 0.806vw, 16px) - 11px); /* 14px / 11px / 16px */
    --ds-icon-size-320: calc(clamp(12px, 17.87px - 0.765vw, 15px) + clamp(12px, 5.08px + 0.901vw, 17.6px) - 12px); /* 15px / 12px / 17.6px */
    --ds-icon-size-330: calc(clamp(12px, 17.87px - 0.765vw, 15px) + clamp(12px, 4.58px + 0.966vw, 18px) - 12px); /* 15px / 12px / 18px */
    --ds-icon-size-350: calc(clamp(13px, 20.83px - 1.02vw, 17px) + clamp(13px, 4.35px + 1.126vw, 20px) - 13px); /* 17px / 13px / 20px */
    --ds-icon-size-360: calc(clamp(14px, 21.83px - 1.02vw, 18px) + clamp(14px, 5.18px + 1.147vw, 21.12px) - 14px); /* 18px / 14px / 21.12px */
    --ds-icon-size-380: calc(clamp(15px, 22.83px - 1.02vw, 19px) + clamp(15px, 5.86px + 1.19vw, 22.4px) - 15px); /* 19px / 15px / 22.4px */
    --ds-icon-size-400: calc(clamp(16px, 23.83px - 1.02vw, 20px) + clamp(16px, 6.1px + 1.288vw, 24px) - 16px); /* 20px / 16px / 24px */
    --ds-icon-size-460: calc(clamp(19px, 26.83px - 1.02vw, 23px) + clamp(19px, 6.88px + 1.577vw, 28.8px) - 19px); /* 23px / 19px / 28.8px */
    --ds-icon-size-480: calc(clamp(20px, 27.83px - 1.02vw, 24px) + clamp(20px, 7.63px + 1.61vw, 30px) - 20px); /* 24px / 20px / 30px */
    --ds-icon-size-500: calc(clamp(20px, 29.78px - 1.274vw, 25px) + clamp(20px, 5.16px + 1.931vw, 32px) - 20px); /* 25px / 20px / 32px */
    --ds-icon-size-900: calc(clamp(58px, 44.63px + 3.564vw, 72px) + clamp(72px, 2.84px + 9.005vw, 128px) - 72px); /* 58px / 72px / 128px */

    /* Fixed element sizes */
    --ds-el-size-100: calc(clamp(4px, 6.94px - 0.383vw, 5.5px) + clamp(4px, 1.5px + 0.324vw, 6px) - 4px); /* 5.5px / 4px / 6px */
    --ds-el-size-200: calc(clamp(8px, 13.87px - 0.765vw, 11px) + clamp(8px, 3.05px + 0.644vw, 12px) - 8px); /* 11px / 8px / 12px */
    --ds-el-size-680: calc(clamp(28px, 35.83px - 1.02vw, 32px) + clamp(28px, 5.76px + 2.895vw, 46px) - 28px); /* 32px / 28px / 46px */
    --ds-el-size-700: calc(clamp(30px, 35.87px - 0.765vw, 33px) + clamp(30px, 7.76px + 2.895vw, 48px) - 30px); /* 33px / 30px / 48px */
    --ds-el-size-800: calc(clamp(38px, 41.92px - 0.511vw, 40px) + clamp(38px, 5.88px + 4.182vw, 64px) - 38px); /* 40px / 38px / 64px */
    --ds-el-size-900: calc(clamp(112px, 205.81px - 12.215vw, 160px) + clamp(112px, 52.72px + 7.718vw, 160px) - 112px); /* 160px / 112px / 160px */
}

/* --------------------------------------------------
   Heading element
   -------------------------------------------------- */

.ds-heading {
    display: flex;
    flex-direction: column;
        justify-content: center;
    align-items: flex-start;
    gap: var(--el-spacing-300);
    margin: 0;

    font-family: var(--main-font);
}

/* Both are selected with their class doubled rather than through .ds-heading.
   That gives the margin reset the weight to outrank theme rules such as
   ".entry-content h1", which only apply in the separated mode and would
   otherwise push the two apart there but not when combined, and it keeps the
   eyebrow and the title looking the same when another element prints them
   without the heading wrapper. The font is declared here too for that reason:
   printed without the wrapper they would otherwise inherit whatever font
   their container has, an Elementor widget's global font for instance. */
.ds-eyebrow.ds-eyebrow,
.ds-heading__title.ds-heading__title {
    display: block;
    margin: 0;

    font-family: var(--main-font);
}

/* The colon stays in the markup for search engines, but is removed from view. */
.ds-heading__colon {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.ds-eyebrow.ds-eyebrow {
    line-height: var(--overline-line-height-400);
    font-weight: var(--ds-global-overline-font-weight-400);
    letter-spacing: var(--ds-global-overline-letter-spacing-400);

    background-color: var(--color-overline-bg-1);

    padding: var(--el-padding-300);

    border-radius: var(--el-border-radius-300);
}

.ds-eyebrow--300 {
    font-size: var(--overline-300);
}

/* Two classes, like the eyebrow's own rule above, so its padding and corners
   give way to these on the smaller step. */
.ds-eyebrow.ds-eyebrow--300 {
    padding: var(--el-padding-200);
    border-radius: var(--el-border-radius-150);
}

.ds-eyebrow--400 {
    font-size: var(--overline-400);
}

.ds-heading__title.ds-heading__title {
    line-height: var(--heading-line-height-400);
    font-weight: var(--ds-global-heading-font-weight-400);
}

/* Letter spacing steps. Two classes, like the rule above, so they keep the
   weight the letter spacing had there. Any step can be picked, a step without
   a rule here falls back to the browser's normal spacing. */
.ds-heading__title.ds-heading__title--letter-spacing-400 {
    letter-spacing: var(--ds-global-heading-letter-spacing-400);
}

.ds-heading__title.ds-heading__title--letter-spacing-600 {
    letter-spacing: var(--ds-global-heading-letter-spacing-600);
}

/* Font size steps off the heading type scale. */
.ds-heading__title--100 {
    font-size: var(--heading-100);
}

.ds-heading__title--150 {
    font-size: var(--heading-150);
}

.ds-heading__title--200 {
    font-size: var(--heading-200);
}

.ds-heading__title--250 {
    font-size: var(--heading-250);
}

.ds-heading__title--300 {
    font-size: var(--heading-300);
}

.ds-heading__title--400 {
    font-size: var(--heading-400);
}

.ds-heading__title--600 {
    font-size: var(--heading-600);
}

/* Colors. Inside the heading shortcode the eyebrow and the title take the color
   the heading names, and anywhere else they carry a color class of their own. */
.ds-heading--color-main .ds-heading__title,
.ds-heading--color-main .ds-eyebrow,
.ds-heading__title.ds-heading__title--color-main,
.ds-eyebrow.ds-eyebrow--color-main {
    color: var(--color-1);
}

.ds-heading--color-secondary .ds-heading__title,
.ds-heading--color-secondary .ds-eyebrow,
.ds-heading__title.ds-heading__title--color-secondary,
.ds-eyebrow.ds-eyebrow--color-secondary {
    color: var(--color-6);
}

.ds-heading--color-secondary .ds-eyebrow,
.ds-eyebrow.ds-eyebrow--color-secondary {
    background-color: var(--color-overline-bg-6);
}

/* Color ids, for the title outside the heading shortcode, where an element
   lets its color be picked. */
.ds-heading__title.ds-heading__title--color-1 {
    color: var(--color-1);
}

.ds-heading__title.ds-heading__title--color-2 {
    color: var(--color-2);
}

.ds-heading__title.ds-heading__title--color-3 {
    color: var(--color-3);
}

.ds-heading__title.ds-heading__title--color-4 {
    color: var(--color-4);
}

.ds-heading__title.ds-heading__title--color-5 {
    color: var(--color-5);
}

.ds-heading__title.ds-heading__title--color-6 {
    color: var(--color-6);
}

.ds-heading__title__highlight--color-2 {
    color: var(--color-2);
}

/* Alignment. The modifier classes only set these custom properties, the title
   and the eyebrow read them. The eyebrow follows the heading until it is given
   an alignment of its own. align-self moves the box, which shows once a ch
   max-width makes the title narrower than the heading, and text-align lines up
   the text inside it. Tablet and mobile classes are only printed when set, so
   without one the larger breakpoint's value carries down. */
.ds-heading {
    --ds-heading-text-align: left;
    --ds-heading-self-align: flex-start;
    --ds-heading-eyebrow-text-align: var(--ds-heading-text-align);
    --ds-heading-eyebrow-self-align: var(--ds-heading-self-align);
}

.ds-heading .ds-heading__title {
    text-align: var(--ds-heading-text-align);
    align-self: var(--ds-heading-self-align);
}

.ds-heading .ds-eyebrow {
    text-align: var(--ds-heading-eyebrow-text-align);
    align-self: var(--ds-heading-eyebrow-self-align);
}

.ds-heading--align-desktop-left { --ds-heading-text-align: left; --ds-heading-self-align: flex-start; }
.ds-heading--align-desktop-center { --ds-heading-text-align: center; --ds-heading-self-align: center; }
.ds-heading--align-desktop-right { --ds-heading-text-align: right; --ds-heading-self-align: flex-end; }

.ds-heading--eyebrow-align-desktop-left { --ds-heading-eyebrow-text-align: left; --ds-heading-eyebrow-self-align: flex-start; }
.ds-heading--eyebrow-align-desktop-center { --ds-heading-eyebrow-text-align: center; --ds-heading-eyebrow-self-align: center; }
.ds-heading--eyebrow-align-desktop-right { --ds-heading-eyebrow-text-align: right; --ds-heading-eyebrow-self-align: flex-end; }

@media ( max-width: 1024px ) {
    .ds-heading--align-tablet-left { --ds-heading-text-align: left; --ds-heading-self-align: flex-start; }
    .ds-heading--align-tablet-center { --ds-heading-text-align: center; --ds-heading-self-align: center; }
    .ds-heading--align-tablet-right { --ds-heading-text-align: right; --ds-heading-self-align: flex-end; }

    .ds-heading--eyebrow-align-tablet-left { --ds-heading-eyebrow-text-align: left; --ds-heading-eyebrow-self-align: flex-start; }
    .ds-heading--eyebrow-align-tablet-center { --ds-heading-eyebrow-text-align: center; --ds-heading-eyebrow-self-align: center; }
    .ds-heading--eyebrow-align-tablet-right { --ds-heading-eyebrow-text-align: right; --ds-heading-eyebrow-self-align: flex-end; }
}

@media ( max-width: 767px ) {
    .ds-heading--align-mobile-left { --ds-heading-text-align: left; --ds-heading-self-align: flex-start; }
    .ds-heading--align-mobile-center { --ds-heading-text-align: center; --ds-heading-self-align: center; }
    .ds-heading--align-mobile-right { --ds-heading-text-align: right; --ds-heading-self-align: flex-end; }

    .ds-heading--eyebrow-align-mobile-left { --ds-heading-eyebrow-text-align: left; --ds-heading-eyebrow-self-align: flex-start; }
    .ds-heading--eyebrow-align-mobile-center { --ds-heading-eyebrow-text-align: center; --ds-heading-eyebrow-self-align: center; }
    .ds-heading--eyebrow-align-mobile-right { --ds-heading-eyebrow-text-align: right; --ds-heading-eyebrow-self-align: flex-end; }
}

/* The mobile font size steps of the title and the eyebrow, printed only when
   they are given one, so that one without it keeps the step above at every
   width. The eyebrow's padding and corners go with its step, so they are set
   again here, with its two classes like its own rules. */
@media ( max-width: 767px ) {
    .ds-heading__title--mobile-100 {
        font-size: var(--heading-100);
    }

    .ds-heading__title--mobile-150 {
        font-size: var(--heading-150);
    }

    .ds-heading__title--mobile-200 {
        font-size: var(--heading-200);
    }

    .ds-heading__title--mobile-250 {
        font-size: var(--heading-250);
    }

    .ds-heading__title--mobile-300 {
        font-size: var(--heading-300);
    }

    .ds-heading__title--mobile-400 {
        font-size: var(--heading-400);
    }

    .ds-heading__title--mobile-600 {
        font-size: var(--heading-600);
    }

    .ds-eyebrow--mobile-300 {
        font-size: var(--overline-300);
    }

    .ds-eyebrow.ds-eyebrow--mobile-300 {
        padding: var(--el-padding-200);
        border-radius: var(--el-border-radius-150);
    }

    .ds-eyebrow--mobile-400 {
        font-size: var(--overline-400);
    }

    .ds-eyebrow.ds-eyebrow--mobile-400 {
        padding: var(--el-padding-300);
        border-radius: var(--el-border-radius-300);
    }
}

/* --------------------------------------------------
   Button element
   -------------------------------------------------- */

.ds-button {
    --ds-local-border-weight-default: 0;
    --ds-local-border-weight-bottom: 0;
    --ds-local-padding-inline-default: 0;
    --ds-local-padding-block-default: 0;
    --ds-local-padding-block-bottom: calc( var(--ds-local-padding-block-default) - (var(--ds-local-border-weight-bottom) - var(--ds-local-border-weight-default)) );

    /* a button printed as a real button element loses the browser's own look */
    -webkit-appearance: none;
    appearance: none;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--el-spacing-150);

    padding-inline: var(--ds-local-padding-inline-default);
    padding-block: var(--ds-local-padding-block-default);
    padding-block-end: var(--ds-local-padding-block-bottom);

    border-style: solid;
    border-width: var(--ds-local-border-weight-default);
    border-bottom-width: var(--ds-local-border-weight-bottom);
    border-radius: 100em;
    color: var(--color-6);

    font-family: var(--main-font);
    font-weight: 700;
    line-height: 1em;
    letter-spacing: var(--ds-global-button-text-letter-spacing-400);
    text-align: center;
    text-decoration: none;

    cursor: pointer;
    transition: filter 0.2s ease;
}

.ds-button:hover,
.ds-button:focus-visible {
    filter: brightness(1.1);
}

/* The wrapper around the icon left of the label. Next to a label it is a
   single pixel tall and lets the icon overflow it, so the icon does not add
   to the button's height however large it is drawn. A button that is only
   its icon takes its size from the icon, so its wrapper keeps the icon's
   height. The gap on .ds-button spaces the icon and the label. */
.ds-button__icon-wrap {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: visible;
}

.ds-button:not(.ds-button--icon-only) .ds-button__icon-wrap {
    height: 1px;
}

/* The icon is sized by the button's size step, which sets
   --ds-local-icon-size below. A button without a step takes 1.32em. */
.ds-button__icon {
    flex: none;
    width: var(--ds-local-icon-size, 1.32em);
    height: var(--ds-local-icon-size, 1.32em);
}

/* Text color ids. 6 is the default, the color on .ds-button is only the
   fallback for markup without a modifier. */
.ds-button--text-color-1 {
    color: var(--color-1);
}

.ds-button--text-color-2 {
    color: var(--color-2);
}

.ds-button--text-color-3 {
    color: var(--color-3);
}

.ds-button--text-color-4 {
    color: var(--color-4);
}

.ds-button--text-color-5 {
    color: var(--color-5);
}

.ds-button--text-color-6 {
    color: var(--color-6);
}

/* Font size steps off the button type scale. */
.ds-button--200 {
    font-size: var(--button-200);

    --ds-local-icon-size: var(--ds-icon-size-320);
}

.ds-button--300 {
    font-size: var(--button-300);

    --ds-local-icon-size: var(--ds-icon-size-360);

    --ds-local-border-weight-default: 0.125rem;
    --ds-local-border-weight-bottom: 0.25rem;

    --ds-local-padding-inline-default: var(--el-padding-350);
    --ds-local-padding-block-default: var(--el-padding-400);
}

.ds-button--350 {
    font-size: var(--button-350);

    padding: 0;
    border-width: 0;
}

.ds-button--400 {
    font-size: var(--button-400);

    --ds-local-icon-size: var(--ds-icon-size-460);

    --ds-local-border-weight-default: 0.125rem;
    --ds-local-border-weight-bottom: 0.25rem;

    --ds-local-padding-inline-default: var(--el-padding-600);
    --ds-local-padding-block-default: var(--el-padding-450);
}

.ds-button--800 {
    font-size: var(--button-800);
}

/* Icon only. The inline padding takes the block padding, so the button is as
   wide as it is tall and its radius rounds it into a circle. The compound
   selector outranks the size steps above. */
.ds-button.ds-button--icon-only {
    --ds-local-padding-inline-default: var(--ds-local-padding-block-default);
}

/* Layered background. The gradient class sits on a layer inside the button
   rather than on the button, so an element can fade it by its opacity, which
   a gradient itself cannot be. The button's own fill and border are cleared
   for an element to set. */
.ds-button--layered {
    position: relative;
    isolation: isolate;

    background: none;
    border-color: transparent;
}

/* The theme's gradient classes paint the border through a transparent one, so
   the layer reaches out over the button's border and draws a border of the
   same widths in the same place. */
.ds-button__background {
    position: absolute;
    inset: calc( var(--ds-local-border-weight-default) * -1 );
    bottom: calc( var(--ds-local-border-weight-bottom) * -1 );
    z-index: -1;

    border-style: solid;
    border-width: var(--ds-local-border-weight-default);
    border-bottom-width: var(--ds-local-border-weight-bottom);
    border-radius: inherit;

    pointer-events: none;
}

/* Secondary type. A shorter button than the default one. The compound
   selector outranks the size steps above. */
.ds-button.ds-button--type-secondary {
    --ds-local-padding-block-default: var(--el-padding-400);
}

.ds-button--300.ds-button--type-secondary {
    --ds-local-padding-block-default: var(--el-padding-350);
}

/* Underline type. No background, border or padding, only the label with the
   animated underline under it, which is drawn in its own section below. The
   compound selector keeps the size steps above from putting their padding
   and borders back. */
.ds-button.ds-button--type-underline {
    --ds-local-border-weight-default: 0;
    --ds-local-border-weight-bottom: 0;
    --ds-local-padding-inline-default: 0;
    --ds-local-padding-block-default: 0;

    background-color: transparent;

    border-radius: 0;
}

/* Icon type. No background, border or padding, only the icon itself. The
   compound selector keeps the size steps and the icon only rule above from
   putting their padding and borders back. */
.ds-button.ds-button--type-icon {
    --ds-local-border-weight-default: 0;
    --ds-local-border-weight-bottom: 0;
    --ds-local-padding-inline-default: 0;
    --ds-local-padding-block-default: 0;

    border-radius: 0;
}

/* Phone width, for the width_mobile option. The option only prints the
   modifier on a button with a background and a label. */
@media ( max-width: 767px ) {
    .ds-button--width-mobile {
        width: 16rem;
        max-width: 100%;
    }
}

/* The mobile size steps, printed only when the button is given one, so that a
   button without it keeps the step above at every width. Each sets what its
   step above sets. */
@media ( max-width: 767px ) {
    .ds-button--mobile-200 {
        font-size: var(--button-200);

        --ds-local-icon-size: var(--ds-icon-size-320);
    }

    .ds-button--mobile-300 {
        font-size: var(--button-300);

        --ds-local-icon-size: var(--ds-icon-size-360);

        --ds-local-border-weight-default: 0.125rem;
        --ds-local-border-weight-bottom: 0.25rem;

        --ds-local-padding-inline-default: var(--el-padding-350);
        --ds-local-padding-block-default: var(--el-padding-400);
    }

    .ds-button--mobile-350 {
        font-size: var(--button-350);

        padding: 0;
        border-width: 0;
    }

    .ds-button--mobile-400 {
        font-size: var(--button-400);

        --ds-local-icon-size: var(--ds-icon-size-460);

        --ds-local-border-weight-default: 0.125rem;
        --ds-local-border-weight-bottom: 0.25rem;

        --ds-local-padding-inline-default: var(--el-padding-600);
        --ds-local-padding-block-default: var(--el-padding-450);
    }

    .ds-button--mobile-800 {
        font-size: var(--button-800);
    }
}

/* --------------------------------------------------
   Animated underline
   -------------------------------------------------- */

/* Shared by the underline button type, the links in body text and the
   citation links, so all of them draw the same line with the same animation.
   The line is drawn rather than a text-decoration so that it can be animated:
   by ::before on the button and the citation links, and by a background on the
   body text links, which can wrap onto more than one line (see below). */
.ds-button--type-underline,
.ds-body-text .ds-body-text__link,
.ds-ref .ds-ref__link {
    --ds-underline-thickness: max( 2px, 0.15em );
    --ds-underline-offset: calc(clamp(0.22em, 0.2591em - 0.081vw, 0.24em) + clamp(0.22em, 0.0965em + 0.257vw, 0.32em) - 0.22em); /* 0.24em / 0.22em / 0.32em */
    --ds-underline-duration: 0.7s;
    --ds-underline-easing: cubic-bezier( 0.65, 0, 0.35, 1 );

    font-weight: 700;

    position: relative;
}

.ds-button--type-underline::before,
.ds-ref .ds-ref__link::before {
    content: '';
    position: absolute;
    inset-inline: 0;
    bottom: calc( var(--ds-underline-offset) * -1 );
    height: var(--ds-underline-thickness);
    background-color: currentColor;
    pointer-events: none;
}

/* On hover the line slides off to the right, then draws back in from the
   left. It ends the way it started, so leaving half way through only snaps
   back to the full line. */
.ds-button--type-underline:hover::before,
.ds-button--type-underline:focus-visible::before,
.ds-ref .ds-ref__link:hover::before,
.ds-ref .ds-ref__link:focus-visible::before {
    animation: ds-underline-slide var(--ds-underline-duration) var(--ds-underline-easing);
}

.ds-body-text .ds-body-text__link:hover,
.ds-body-text .ds-body-text__link:focus-visible {
    animation: ds-underline-slide-background var(--ds-underline-duration) var(--ds-underline-easing);
}

/* The origin only flips while the line is scaled to nothing, so the jump
   from right to left is never seen. */
@keyframes ds-underline-slide {
    0% {
        transform: scaleX( 1 );
        transform-origin: right;
    }

    50% {
        transform: scaleX( 0 );
        transform-origin: right;
    }

    50.1% {
        transform: scaleX( 0 );
        transform-origin: left;
    }

    100% {
        transform: scaleX( 1 );
        transform-origin: left;
    }
}

/* The same slide for a line drawn as a background. The position only matters
   while the line is shorter than the link, so it flips from right to left
   while the line is at nothing, just as the origin does above. Across a link
   that wraps, the line leaves from the end of its last line and comes back in
   from the start of its first. */
@keyframes ds-underline-slide-background {
    0% {
        background-size: 100% var(--ds-underline-thickness);
        background-position: 100% 100%;
    }

    50% {
        background-size: 0% var(--ds-underline-thickness);
        background-position: 100% 100%;
    }

    50.1% {
        background-size: 0% var(--ds-underline-thickness);
        background-position: 0% 100%;
    }

    100% {
        background-size: 100% var(--ds-underline-thickness);
        background-position: 0% 100%;
    }
}

/* The line stays put. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-button--type-underline:hover::before,
    .ds-button--type-underline:focus-visible::before,
    .ds-ref .ds-ref__link:hover::before,
    .ds-ref .ds-ref__link:focus-visible::before,
    .ds-body-text .ds-body-text__link:hover,
    .ds-body-text .ds-body-text__link:focus-visible {
        animation: none;
    }
}

/* --------------------------------------------------
   Conditions showcase element
   -------------------------------------------------- */

.ds-conditions-showcase {
    --ds-conditions-gap: var(--el-spacing-250);
    --ds-conditions-radius: var(--el-border-radius-300);

    /* the fallback duration matters: without the script the rows still travel,
       just not at a speed matched to how wide they turned out */
    --ds-conditions-row-duration: 53s;

    /* how far in from either edge the rows have faded out completely */
    --ds-conditions-fade: 6%;

    /* the longer of the two highlight durations. Coming on, the fill takes this
       and the label half of it; going off, the label takes this and the fill
       half. The script overwrites this from the shortcode attribute. */
    --ds-conditions-fade-duration: 600ms;

    /* Symmetric on purpose: the fill and the label are two different properties
       on two different elements, so they share this one curve rather than each
       stating its own. The label's duration is derived from the fill's, so the
       two stay in step. Symmetric also means going out feels like coming in,
       rather than the highlight snapping away at the end. */
    --ds-conditions-fade-easing: cubic-bezier(0.45, 0, 0.55, 1);

    --ds-conditions-item-bg: rgba(117, 54, 74, 0.12);
    --ds-conditions-item-text: var(--color-1);
    --ds-conditions-item-active-text: var(--color-6);

    display: flex;
    flex-direction: column;
    gap: var(--ds-conditions-gap);

    /* narrower on tablet, full width on mobile, both below */
    max-width: 50rem;

    /* the rows are wider than the element on purpose, this is what keeps the
       overflow off the page */
    overflow: hidden;

    font-family: var(--main-font);

    /* both edges fade out rather than cutting off, so a pill leaves the frame
       instead of vanishing at a hard border */
    -webkit-mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 var(--ds-conditions-fade),
        #000 calc(100% - var(--ds-conditions-fade)),
        transparent 100%
    );
    mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 var(--ds-conditions-fade),
        #000 calc(100% - var(--ds-conditions-fade)),
        transparent 100%
    );
}

/* Declared on its own so a browser without color-mix keeps the flat fallback
   above rather than dropping the whole custom property block. */
@supports ( background: color-mix( in srgb, red 12%, transparent ) ) {
    .ds-conditions-showcase {
        --ds-conditions-item-bg: color-mix( in srgb, var(--color-1) 12%, transparent );
    }
}

.ds-conditions-showcase__row {
    overflow: hidden;
}

/* Only once the script has set the rows up to be dragged, since without it
   there is nothing to grab. A finger moving across a row is the row's, while
   one moving up or down is still the page's, which the script decides as the
   finger sets off. A pinch still zooms the page, where a browser understands
   as much. */
.ds-conditions-showcase--draggable .ds-conditions-showcase__row {
    cursor: grab;
    touch-action: pan-y;
    touch-action: pan-y pinch-zoom;
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}

.ds-conditions-showcase--draggable .ds-conditions-showcase__row--dragging {
    cursor: grabbing;
}

.ds-conditions-showcase__track {
    display: flex;
    width: max-content;
    padding: 0;
    margin: 0;
    list-style: none;

    /* the track holds the row twice, so half its width is exactly one full set
       of pills: travelling that far puts the copy where the original was and
       the loop restarts on an identical frame */
    animation: ds-conditions-scroll-left var(--ds-conditions-row-duration) linear infinite;
    will-change: transform;
}

.ds-conditions-showcase__row--right .ds-conditions-showcase__track {
    animation-name: ds-conditions-scroll-right;
}

@keyframes ds-conditions-scroll-left {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(-50%, 0, 0); }
}

@keyframes ds-conditions-scroll-right {
    from { transform: translate3d(-50%, 0, 0); }
    to { transform: translate3d(0, 0, 0); }
}

.ds-conditions-showcase__item {
    /* the spacing is a trailing margin rather than a gap on the track, because
       a gap would sit between the two halves but not after the second one, and
       the loop would jump by that much on every pass */
    margin-inline-end: var(--ds-conditions-gap);

    flex: 0 0 auto;
    position: relative;

    /* keeps the highlight, laid below the label, inside the pill rather than
       behind whatever the row is travelling over */
    isolation: isolate;

    /* Every pill drawn as a layer of its own, rather than the whole track as
       one. The track is several thousand pixels wide on a phone's screen, and
       a phone only keeps the part of a layer that size drawn near what is on
       screen. When the loop came round, the track jumped back to its start, a
       stretch that had gone off screen long before and been thrown away, and
       the row showed nothing for a frame while it was drawn again. A layer
       the size of a pill is always kept whole, so the loop finds everything
       ready, and a highlight fading in or out only redraws its own pill. */
    will-change: transform;

    padding: var(--el-padding-400);
    border-radius: var(--ds-conditions-radius);

    /* the resting fill, and it is left alone from here on: nothing transitions
       it, so the pill's own paint never has to be redone mid fade */
    background-color: var(--ds-conditions-item-bg);

    color: var(--ds-conditions-item-text);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: var(--ds-global-heading-letter-spacing-400, -0.04em);
    text-align: center;
    text-transform: lowercase;
    white-space: nowrap;

    /* A transition runs with the durations of the state being entered, so these
       are the ones used on the way back to rest: the fill goes in half the time
       the label takes. The active rule below swaps them for the way in. */
    --ds-conditions-text-duration: var(--ds-conditions-fade-duration, 2400ms);
    --ds-conditions-fill-duration: calc(var(--ds-conditions-fade-duration, 2400ms) / 2);

    transition: color
        var(--ds-conditions-text-duration)
        var(--ds-conditions-fade-easing, cubic-bezier(0.45, 0, 0.55, 1));
}

/* The highlight, laid over the resting fill and faded in and out by opacity
   rather than by transitioning the pill's background-color.

   The background-color route is what was blinking. The section background
   carries the grain as a blended background layer, and it sits in a track that is promoted for
   its transform animation, so every frame of a color fade forced the whole
   layer's background stack to be blended again. Under load the browser drops
   one of those frames and the fill flashes back to its resting color for an
   instant. An opacity fade is handled by the compositor and needs no repaint at
   all, so there is no frame left to drop.

   It is a real element rather than a pseudo element because its fill is the
   theme's section background class, ds-sc-bg-<id>, which the script puts on
   it, and a class can only go on an element. */
.ds-conditions-showcase__item__highlight {
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;

    opacity: 0;
    pointer-events: none;

    transition: opacity
        var(--ds-conditions-fill-duration)
        var(--ds-conditions-fade-easing, cubic-bezier(0.45, 0, 0.55, 1));
}

.ds-conditions-showcase__item--active .ds-conditions-showcase__item__highlight {
    opacity: 1;
}

/* The fill is held on the layer for the whole of the fade out, not just while it
   is lit. If the script dropped the color class the moment a pill was released,
   the layer would lose its fill instantly and the background would disappear
   while the label was still easing back. The script drops it once the fade has
   finished instead. */

/* The label is lowercased as a whole, so an acronym has to be put back. */
.ds-conditions-showcase__item__acronym {
    text-transform: uppercase;
}

/* Font size steps off the type scale. */
.ds-conditions-showcase__item--200 {
    font-size: var(--heading-200);
}

.ds-conditions-showcase__item--250 {
    font-size: var(--heading-250);
}

.ds-conditions-showcase__item--350 {
    font-size: var(--body-350);
}

.ds-conditions-showcase__item--400 {
    font-size: var(--heading-400);
}

.ds-conditions-showcase__item--600 {
    font-size: var(--heading-600);
}

/* The highlight the script applies, held for a moment before the pill settles
   back. The fill itself is the theme's ds-sc-bg-<id> class on the highlight
   layer, so there are no color rules here. */
.ds-conditions-showcase__item--active {
    --ds-conditions-item-text: var(--ds-conditions-item-active-text);

    /* on the way in the label turns in half the time the fill takes */
    --ds-conditions-text-duration: calc(var(--ds-conditions-fade-duration, 2400ms) / 2);
    --ds-conditions-fill-duration: var(--ds-conditions-fade-duration, 2400ms);
}

@media ( max-width: 1024px ) {
    .ds-conditions-showcase {
        max-width: 32rem;
    }
}

@media ( max-width: 767px ) {
    .ds-conditions-showcase {
        max-width: 100%;
    }
}

/* Nothing moves on its own, and the rows become scrollable instead so every
   condition can still be reached. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-conditions-showcase__track {
        animation: none;
    }

    .ds-conditions-showcase__row {
        overflow-x: auto;
        scrollbar-width: none;
    }

    .ds-conditions-showcase__row::-webkit-scrollbar {
        display: none;
    }

    .ds-conditions-showcase__item,
    .ds-conditions-showcase__item__highlight {
        transition: none;
    }
}

/* --------------------------------------------------
   Card deck element
   -------------------------------------------------- */

.ds-card-deck {
    /* one number the whole deck is measured from: the cards are laid out in
       card widths rather than in pixels, so the deck keeps its proportions at
       every size it is allowed to take */
    --ds-card-deck-card-width: clamp( 16rem, 30vw, 21.875rem );

    /* 452 over 350, the card off the design */
    --ds-card-deck-card-ratio: 1.2914;
    --ds-card-deck-card-radius: var(--el-border-radius-600);

    /* how far the card before and the card after sit from the middle, how much
       smaller they are drawn and how far they are tilted away */
    --ds-card-deck-side-offset: 0.366;
    --ds-card-deck-side-scale: 0.885;
    --ds-card-deck-side-angle: 12deg;

    /* and the same for the one the deck reaches for at its ends, which is
       further out and tilted further still */
    --ds-card-deck-far-offset: 0.54;
    --ds-card-deck-far-scale: 0.78;
    --ds-card-deck-far-angle: 22deg;

    --ds-card-deck-duration: 520ms;
    --ds-card-deck-ease: cubic-bezier( 0.33, 1, 0.68, 1 );

    --ds-card-deck-card-bg: var(--color-1);
    --ds-card-deck-card-text: var(--color-6);

    /* the resting track of the progress bar, flat so a browser without
       color-mix still has one */
    --ds-card-deck-track: rgba( 117, 54, 74, 0.16 );

    /* how far along the deck the reader is. The shortcode prints the card it
       opens on into a style block of its own and the script takes over from
       there */
    --ds-card-deck-progress: 0%;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--el-spacing-400);

    font-family: var(--main-font);
}

@supports ( background: color-mix( in srgb, red 16%, transparent ) ) {
    .ds-card-deck {
        --ds-card-deck-track: color-mix( in srgb, var(--color-1) 16%, transparent );
    }
}

/* --------------------------------------------------
   The deck itself
   -------------------------------------------------- */

.ds-card-deck__top {
    position: relative;

    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--el-spacing-400);

    width: 100%;

    /* the tilted cards reach past the stage on both sides, and at the ends of
       the deck the far card reaches further than the stage is wide, so
       whatever is left over is cut off here rather than being allowed to widen
       the page. The padding keeps the cut off the tops and the bottoms of the
       cards, which a rotation lifts a couple of pixels past the stage. */
    padding-block: var(--el-padding-200);
    overflow: hidden;
}

/* Where a browser can cut one way only, the cards are cut off at the sides
   alone: one lifted or leaning on its way across the deck reaches a little
   past the top and the bottom, and is left whole there. */
@supports ( overflow: clip ) {
    .ds-card-deck__top {
        overflow: visible;
        overflow-x: clip;
    }
}

/* Every card is laid in the same cell, so they stack without being taken out
   of the flow: the cell is as tall as the tallest of them and the stage needs
   no height of its own. */
.ds-card-deck__stage {
    display: grid;
    align-items: stretch;
    justify-items: center;

    flex: 0 1 auto;

    /* the middle card plus what the two beside it reach out to */
    width: calc( var(--ds-card-deck-card-width) * 1.835 );

    /* the cards are laid over one another in an order of their own, kept to
       themselves so that it is never read against the buttons beside them */
    isolation: isolate;
}

.ds-card-deck__card {
    grid-area: 1 / 1;

    position: relative;

    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    width: var(--ds-card-deck-card-width);
    min-height: calc( var(--ds-card-deck-card-width) * var(--ds-card-deck-card-ratio) );
    padding: var(--el-padding-500) var(--el-padding-400);
    border-radius: var(--ds-card-deck-card-radius);

    /* the fill, grain and all, is the theme's .ds-sc-bg-* class on the card */
    color: var(--ds-card-deck-card-text);

    /* where a card sits without the script. With it, the script writes the
       place of every card itself on every frame, reading the three places
       below to work out the ones in between, so nothing is transitioned here */
    transform: var(--ds-card-deck-card-transform, none);
    opacity: var(--ds-card-deck-card-opacity, 1);
}

/* The positions. The card being read is the only one left upright, and every
   other one is turned away from it by the side it is on. */
.ds-card-deck__card--main {
    --ds-card-deck-card-transform: translateX( 0 ) rotate( 0deg ) scale( 1 );

    z-index: 3;
}

.ds-card-deck__card--prev {
    --ds-card-deck-card-transform:
        translateX( calc( var(--ds-card-deck-card-width) * var(--ds-card-deck-side-offset) * -1 ) )
        rotate( calc( var(--ds-card-deck-side-angle) * -1 ) )
        scale( var(--ds-card-deck-side-scale) );

    z-index: 2;
}

.ds-card-deck__card--next {
    --ds-card-deck-card-transform:
        translateX( calc( var(--ds-card-deck-card-width) * var(--ds-card-deck-side-offset) ) )
        rotate( var(--ds-card-deck-side-angle) )
        scale( var(--ds-card-deck-side-scale) );

    z-index: 2;
}

/* The two the deck only reaches for at its ends, where one of the sides has
   run out of cards and the other one carries the third card instead. */
.ds-card-deck__card--far-prev,
.ds-card-deck__card--hidden-prev {
    --ds-card-deck-card-transform:
        translateX( calc( var(--ds-card-deck-card-width) * var(--ds-card-deck-far-offset) * -1 ) )
        rotate( calc( var(--ds-card-deck-far-angle) * -1 ) )
        scale( var(--ds-card-deck-far-scale) );

    z-index: 1;
}

.ds-card-deck__card--far-next,
.ds-card-deck__card--hidden-next {
    --ds-card-deck-card-transform:
        translateX( calc( var(--ds-card-deck-card-width) * var(--ds-card-deck-far-offset) ) )
        rotate( var(--ds-card-deck-far-angle) )
        scale( var(--ds-card-deck-far-scale) );

    z-index: 1;
}

/* A card that is not in view waits where it would come in from, so it travels
   in from beyond the edge rather than appearing out of the middle. */
.ds-card-deck__card--hidden-prev,
.ds-card-deck__card--hidden-next {
    --ds-card-deck-card-opacity: 0;

    z-index: 0;
    pointer-events: none;
}

/* The cards to either side are the plainest way to reach the one next to the
   one being read, so they are made to look like it. */
.ds-card-deck__card--prev,
.ds-card-deck__card--next,
.ds-card-deck__card--far-prev,
.ds-card-deck__card--far-next {
    cursor: pointer;
}

/* Once the script has the deck, a pointer moving sideways over the cards is
   the deck's while one moving up or down is still the page's, and nothing in
   the deck is picked up as text or dragged off as a picture on the way. */
.ds-card-deck--ready .ds-card-deck__stage {
    touch-action: pan-y;

    /* and a pinch still zooms the page, where a browser understands as much */
    touch-action: pan-y pinch-zoom;

    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
}

/* The deck can be taken hold of, which only a mouse has any way of showing. */
.ds-card-deck--draggable .ds-card-deck__card--main {
    cursor: grab;
}

.ds-card-deck--dragging .ds-card-deck__stage,
.ds-card-deck--dragging .ds-card-deck__card {
    cursor: grabbing;
}

/* Only while the deck moves: the cards are handed to the compositor for the
   move and given back at the end of it, so their text is drawn afresh, and
   sharp, at whatever size each card has settled at. */
.ds-card-deck--moving .ds-card-deck__card {
    will-change: transform, opacity;
}

.ds-card-deck .ds-card-deck__card__items {
    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-400);

    width: 100%;
    padding: 0;
    margin: 0;
    list-style: none;
}

.ds-card-deck .ds-card-deck__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--el-spacing-200);

    margin: 0;
}

/* The mark heading a body text: a light disc with the card's own color drawn
   on it. */
.ds-card-deck__item__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;

    width: var(--ds-icon-size-400);
    height: var(--ds-icon-size-400);
    border-radius: 999px;

    background-color: var(--color-6);
    color: var(--ds-card-deck-card-bg);
}

.ds-card-deck__item__glyph {
    display: block;
    width: auto;
    height: calc( var(--ds-icon-size-400) * 0.65 / 1.5 );
}

.ds-card-deck__item__glyph--help {
    height: calc( var(--ds-icon-size-400) * 0.7 / 1.5 );
}

/* The warning mark sits inside warning.svg's own 16 x 17 canvas, so the glyph
   is sized to that canvas to keep the mark itself at the size it was drawn. */
.ds-card-deck__item__glyph--warning {
    height: var(--ds-icon-size-300);
}

/* The text is a body text, so its type comes from the body text styles. It is
   held well short of the card's own width, which is what gives the card its
   short, centred lines. */
.ds-card-deck .ds-card-deck__item__text {
    max-width: min( 100%, 18rem );
}

/* The fill comes from the theme's .ds-sc-bg-* class, these only tell the mark
   on every body text which color the card is, so it can be drawn in it. */
.ds-card-deck__card.ds-sc-bg-1 {
    --ds-card-deck-card-bg: var(--color-1);
}

.ds-card-deck__card.ds-sc-bg-2 {
    --ds-card-deck-card-bg: var(--color-2);
}

.ds-card-deck__card.ds-sc-bg-3 {
    --ds-card-deck-card-bg: var(--color-3);
}

.ds-card-deck__card.ds-sc-bg-4 {
    --ds-card-deck-card-bg: var(--color-4);
}

.ds-card-deck__card.ds-sc-bg-5 {
    --ds-card-deck-card-bg: var(--color-5);
}

/* --------------------------------------------------
   The controls
   -------------------------------------------------- */

/* The previous and next controls are Button basic elements holding only their
   arrows, so their fill, border and hover are the button's own. They are only
   held to the size the design draws them at, the same one the accordion's
   toggles take. It is a real button element, so the browser's own look is
   taken off. */
.ds-card-deck .ds-card-deck__nav {
    -webkit-appearance: none;
    appearance: none;

    flex: 0 0 auto;
    position: relative;
    isolation: isolate;
    z-index: 4;

    width: var(--ds-el-size-800);
    height: var(--ds-el-size-700);
    padding: 0;

    transition:
        opacity var(--ds-card-deck-duration) var(--ds-card-deck-ease),
        filter 0.2s ease;
}

/* At an end of the deck the button it belongs to has nowhere to go, and fades
   back rather than leaving the row. The cursor says it cannot be pressed, the
   same as the orbital tabs' step buttons. */
.ds-card-deck__nav[disabled] {
    opacity: 0.32;
    cursor: not-allowed;
}

.ds-card-deck__nav[disabled]:hover {
    filter: none;
}

.ds-card-deck__nav__glyph {
    display: block;
    width: auto;
    height: var(--ds-icon-size-320);
}

.ds-card-deck__nav-bar {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--el-spacing-400);

    width: 100%;
}

.ds-card-deck__progress {
    width: min( 100%, 16.125rem );
    height: var(--ds-el-size-200);
    border-radius: 999px;

    background-color: var(--ds-card-deck-track);
}

/* The fill and its border are the theme's .ds-bg-gd-* class, the one the
   deck's buttons are drawn with, which paints the border through a
   transparent one. The widths are the accordion bar's, which is as tall. */
.ds-card-deck__progress__fill {
    box-sizing: border-box;
    width: var(--ds-card-deck-progress, 0%);
    height: 100%;
    min-width: var(--ds-el-size-200);
    border-style: solid;
    border-width: 1.7px;
    border-radius: 100px;
}

/* Every card's title and text is printed, all of them laid in the same cell:
   the cell stays as tall as the longest of them, so nothing below the deck
   moves as it is read. */
.ds-card-deck__captions {
    display: grid;
    justify-items: center;

    width: 100%;
}

.ds-card-deck__caption {
    grid-area: 1 / 1;

    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-350);

    width: 100%;

    color: var(--color-1);
    text-align: center;

    /* the caption of the card being read is the one shown, and the script
       fades them as the deck passes between the two */
    opacity: 0;
    visibility: hidden;
}

.ds-card-deck__caption--active {
    opacity: 1;
    visibility: visible;
}

/* A caption's title and text may be given a width of their own, and are kept
   in the middle of the caption when they are narrower than it. */
.ds-card-deck .ds-card-deck__caption__title,
.ds-card-deck .ds-card-deck__caption__text {
    margin-inline: auto;
}

.ds-card-deck .ds-card-deck__counter {
    position: relative;
    isolation: isolate;

    display: inline-flex;
    align-items: center;
    justify-content: center;

    padding: var(--el-padding-200) var(--el-padding-300);
    margin: 0;

    /* the fill and the border are the theme's .ds-bg-gd-* class, the same the
       deck's buttons carry, at the button's widths */
    border-style: solid;
    border-width: 0.125rem;
    border-bottom-width: 0.25rem;
    border-radius: 100px;

    color: var(--color-6);
}

/* The box is the div; the words are the paragraph inside it, which lays the
   three spans out in a row. */
.ds-card-deck .ds-card-deck__counter__text {
    display: inline-flex;
    align-items: center;
    gap: 0.25em;

    margin: 0;
    padding: 0;

    margin-block: 0.05em -0.05em;

    color: inherit;
    font-size: var(--body-200);
    font-weight: var(--ds-global-heading-font-weight-400, 900);
    line-height: 1;
    letter-spacing: var(--ds-global-heading-letter-spacing-400, -0.04em);
    text-align: center;
    text-transform: lowercase;
}

.ds-card-deck .ds-card-deck__counter__text span {
    line-height: 0.9em;
}

/* --------------------------------------------------
   Narrower screens
   -------------------------------------------------- */

@media ( max-width: 1024px ) {
    .ds-card-deck__top {
        gap: 1rem;
    }
}

/* There is no room left beside the cards for the buttons, and a phone swipes
   through the deck anyway, so the buttons are left out. */
@media ( max-width: 767px ) {
    .ds-card-deck {
        --ds-card-deck-card-width: min( 74vw, 20rem );
        --ds-card-deck-side-offset: 0.3;
        --ds-card-deck-far-offset: 0.45;

        gap: 1.5rem;
    }

    .ds-card-deck__stage {
        width: 100%;
    }

    .ds-card-deck .ds-card-deck__nav {
        display: none;
    }

    .ds-card-deck__nav-bar {
        gap: 1.5rem;
    }

    .ds-card-deck__caption {
        gap: 1rem;
    }
}

/* Little moves: the script takes the deck the shortest way to its card, with
   none of the lean, the lift or the rise under the mouse, and the controls
   stop fading as well. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-card-deck .ds-card-deck__nav {
        transition: none;
    }
}

/* The deck takes the keyboard's focus itself, so the cards can be stepped
   through with the arrow keys and not only with the buttons. */
.ds-card-deck__stage:focus {
    outline: none;
}

.ds-card-deck__stage:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 8px;
    border-radius: var(--ds-card-deck-card-radius);
}

/* --------------------------------------------------
   Accordion tabs element
   -------------------------------------------------- */

.ds-accordion-tabs {
    --ds-accordion-tabs-gap: var(--el-spacing-550);
    --ds-accordion-tabs-width: clamp(512px, 156.4px + 46.302vw, 800px); /* 512px / 512px / 800px */

    /* the tabs row, and how far under a tab its bar sits */
    --ds-accordion-tabs-tab-gap: var(--el-spacing-250);
    --ds-accordion-tabs-marker-gap: var(--el-padding-200);
    --ds-accordion-tabs-marker-height: var(--ds-el-size-200);

    /* placed by the script, which measures the tab being read. Nothing is
       drawn from these until it has: the bar is kept out of view until the
       ready class is on, so it never sits under the wrong tab for a frame */
    --ds-accordion-tabs-marker-x: 0px;
    --ds-accordion-tabs-marker-y: 0px;
    --ds-accordion-tabs-marker-width: 0px;

    --ds-accordion-tabs-move-duration: 420ms;

    /* how long a tab takes to fade between the selected and resting colors */
    --ds-accordion-tabs-tab-fade-duration: 500ms;
    --ds-accordion-tabs-move-easing: cubic-bezier(0.4, 0, 0.2, 1);

    /* the item divider, flat as a fallback and mixed where color-mix is
       understood, the same shape the conditions showcase uses */
    --ds-accordion-tabs-divider: rgba(117, 54, 74, 0.16);

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ds-accordion-tabs-gap);

    width: 100%;

    font-family: var(--main-font);
    color: var(--color-1);
}

@supports ( background: color-mix( in srgb, red 16%, transparent ) ) {
    .ds-accordion-tabs {
        --ds-accordion-tabs-divider: color-mix( in srgb, var(--color-1) 16%, transparent );
    }
}

/* Tabs
   -------------------------------------------------- */

/* The bar is placed against this, so it is what the script measures the tabs
   against as well: wherever the element sits and however the tabs have
   wrapped, the two agree. */
.ds-accordion-tabs__tabs {
    position: relative;

    /* the room the bar travels in, below the tabs themselves */
    padding-block-end: calc( var(--ds-accordion-tabs-marker-gap) + var(--ds-accordion-tabs-marker-height) );

    max-width: 100%;
}

.ds-accordion-tabs__tabs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--ds-accordion-tabs-tab-gap);
}

/* Every tab is the site's button, so its size, border widths and hover come
   from there. It is a real button element, so the browser's own look is taken
   off.

   Every tab rests on the secondary button colors, and the one being read has
   the button's gradient faded in over them on its background layer. The
   secondary fill is see-through, so it stays under the gradient rather than
   the gradient being faded out beneath it. */
.ds-accordion-tabs .ds-accordion-tabs__tab {
    -webkit-appearance: none;
    appearance: none;

    background: var(--color-btn-secondary-bg-1);
    border-color: var(--color-btn-secondary-border-1);

    transition:
        color var(--ds-accordion-tabs-tab-fade-duration) var(--ds-accordion-tabs-move-easing),
        filter 0.2s ease;
}

/* A tab that is not being read takes the dark label that reads on the
   secondary colors. The selected tab keeps the button's own text color. */
.ds-accordion-tabs .ds-accordion-tabs__tab:not(.ds-accordion-tabs__tab--active) {
    color: var(--color-1);
}

.ds-accordion-tabs .ds-accordion-tabs__tab .ds-button__background {
    opacity: 0;

    transition: opacity var(--ds-accordion-tabs-tab-fade-duration) var(--ds-accordion-tabs-move-easing);
}

.ds-accordion-tabs .ds-accordion-tabs__tab--active .ds-button__background {
    opacity: 1;
}

/* The site's button has no focus ring of its own, and a tab is reached with the
   arrow keys as often as with the pointer. */
.ds-accordion-tabs__tab:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

/* The bar under the tabs. There is one of it, and it is moved and resized to
   the tab being read rather than being turned off under one and on under the
   next, which is what makes it travel. Both the move and the resize are
   transitioned, so a tab of a different width is reached in one motion. */
.ds-accordion-tabs__marker {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;

    isolation: isolate;

    width: var(--ds-accordion-tabs-marker-width);
    height: var(--ds-accordion-tabs-marker-height);

    /* the fill and border are the theme's .ds-bg-gd-* class, which paints the
       border through a transparent one, as on the card deck's progress bar */
    border-style: solid;
    border-width: 1.7px;
    border-radius: 999px;

    /* hidden until the script has measured a tab: an unplaced bar would sit at
       the top left corner of the tabs for a frame */
    opacity: 0;

    transform: translate(
        var(--ds-accordion-tabs-marker-x),
        calc( var(--ds-accordion-tabs-marker-y) + var(--ds-accordion-tabs-marker-gap) )
    );

    pointer-events: none;
}

.ds-accordion-tabs--ready .ds-accordion-tabs__marker {
    opacity: 1;

    transition:
        transform var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing),
        width var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing),
        opacity 200ms linear;
}

/* Panels
   -------------------------------------------------- */

.ds-accordion-tabs__panels {
    width: 100%;
    max-width: var(--ds-accordion-tabs-width);
}

.ds-accordion-tabs__panel {
    animation: ds-accordion-tabs-panel-in var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing) both;
}

@keyframes ds-accordion-tabs-panel-in {
    from {
        opacity: 0;
        transform: translateY(0.5rem);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

.ds-accordion-tabs__items {
    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-400);
}

/* Items
   -------------------------------------------------- */

.ds-accordion-tabs__item {
    display: flex;
    flex-direction: column;
}

/* The rule that heads every item. It is drawn rather than being a border so it
   keeps its rounded ends, and it belongs to the item below it, which is why
   the last item has none under it.
   
   The space under it is its own margin rather than a gap on the item, because
   a gap would also be held between the title and a body that is closed, and a
   closed item would carry an empty band the height of the one below it. */
.ds-accordion-tabs__item::before {
    content: '';

    display: block;
    height: var(--ds-el-size-100);
    margin-block-end: var(--el-spacing-400);
    border-radius: 999px;

    background-color: var(--ds-accordion-tabs-divider);
}

/* The title and its toggle share the heading, the title taking the room the
   toggle leaves. */
.ds-accordion-tabs .ds-accordion-tabs__item__heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--el-spacing-500);

    margin: 0;
    padding: 0;

    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
}

/* Once the script is running, a click anywhere on the heading opens the item,
   so all of it shows the pointer the toggle does. An item without a body has
   no toggle and never gets the class. */
.ds-accordion-tabs .ds-accordion-tabs__item__heading--clickable {
    cursor: pointer;
}

/* The toggle is the site's button holding only the icon, so its fill, border
   and hover come from there. The design draws it as a pill rather than the
   circle an icon-only button is, which is the size set here. It is a real
   button element, so the browser's own look is taken off. */
.ds-accordion-tabs .ds-accordion-tabs__item__toggle {
    -webkit-appearance: none;
    appearance: none;

    flex: 0 0 auto;

    width: var(--ds-el-size-800);
    height: var(--ds-el-size-700);
    padding: 0;
    padding-block-start: calc( var(--ds-local-border-weight-bottom) - var(--ds-local-border-weight-default) );
}

.ds-accordion-tabs__item__toggle:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

/* An item's title is a body text and looks the way body text does everywhere.
   It is lowercased as a whole, so an acronym has to be put back:
   <span class="ds-accordion-tabs__acronym">AI</span>. */
.ds-accordion-tabs__acronym {
    text-transform: uppercase;
}

/* The arrow is turned over rather than swapped for a second mark, so open and
   closed are one shape. An icon from the media library turns the same way. */
.ds-accordion-tabs .ds-accordion-tabs__item__toggle .ds-button__icon {
    width: var(--ds-icon-size-300);
    height: auto;

    /* the arrow's rounded ends touch the edges of its viewBox, which a
       fractional width can shave off, so they are let past the edge */
    overflow: visible;

    transition: transform var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing);
}

.ds-accordion-tabs__item--open .ds-accordion-tabs__item__toggle .ds-button__icon {
    transform: rotate(180deg);
}

/* The body, opened by letting its row grow from nothing to what the text needs
   rather than by animating a height nothing knows in advance. The visibility
   is what takes a closed body out of reach, and it is held until the row has
   finished closing so the text does not vanish before it has folded away. */
.ds-accordion-tabs__item__body {
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;

    transition:
        grid-template-rows var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing),
        opacity var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing),
        visibility 0s linear var(--ds-accordion-tabs-move-duration);

    opacity: 0;
}

.ds-accordion-tabs__item--open .ds-accordion-tabs__item__body {
    grid-template-rows: 1fr;
    visibility: visible;
    opacity: 1;

    transition:
        grid-template-rows var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing),
        opacity var(--ds-accordion-tabs-move-duration) var(--ds-accordion-tabs-move-easing),
        visibility 0s linear;
}

.ds-accordion-tabs__item__body__inner {
    /* both are needed for the row to be able to shrink to nothing */
    min-height: 0;
    overflow: hidden;
}

/* The answer is a body text laid out in paragraphs and styled by the theme's
   ds-elementor-text. The room above it keeps it off the title, and the
   paragraphs at either end give up their outer margin. The theme's gap under
   every paragraph and list is dropped from the last one, so an open item
   does not end in an empty gap. */
.ds-accordion-tabs__item__text {
    padding-block-start: var(--el-padding-400);
}

.ds-accordion-tabs .ds-accordion-tabs__item__text > p:first-child {
    margin-block-start: 0;
}

.ds-accordion-tabs .ds-accordion-tabs__item__text > p:last-child {
    margin-block-end: 0;
}

.ds-accordion-tabs .ds-accordion-tabs__item__text > :last-child {
    padding-block-end: 0;
}

@media ( max-width: 767px ) {
    .ds-accordion-tabs {
        --ds-accordion-tabs-gap: 2.5rem;
        --ds-accordion-tabs-tab-gap: 0.75rem;
    }

    /* On a phone the tab being read is told apart by its fill alone. The bar
       is not drawn, so the room it travels in under the tabs goes with it. */
    .ds-accordion-tabs__tabs {
        padding-block-end: 0;
    }

    .ds-accordion-tabs__marker {
        display: none;
    }

    /* The tabs keep to one line and are scrolled through sideways, with the
       scrollbar hidden the way the conditions showcase hides its own. The row
       starts at the left rather than centered: a centered row wider than its
       container hangs off both sides, and what hangs off the left can never
       be scrolled back to. A row that fits is still centered, since the tabs
       bar around it is only as wide as the tabs.

       A scrolling row clips whatever reaches past it, so it is padded above
       and below by the focus ring's width and offset, and pulled back by as
       much so the tabs stay where they were. Its sides take the panels'
       padding, so the first tab starts in line with the text below. */
    .ds-accordion-tabs__tabs__list {
        flex-wrap: nowrap;
        justify-content: flex-start;

        overflow-x: auto;
        scrollbar-width: none;

        padding-block: 5px;
        padding-inline: var(--el-spacing-300);
        margin-block: -5px;
    }

    .ds-accordion-tabs__tabs__list::-webkit-scrollbar {
        display: none;
    }

    /* a tab keeps the width of its label rather than being squeezed to fit
       the row and wrapping it */
    .ds-accordion-tabs .ds-accordion-tabs__tab {
        flex: 0 0 auto;
    }

    .ds-accordion-tabs__panels {
        padding-inline: var(--el-spacing-300);
    }

    .ds-accordion-tabs__items {
        gap: 1.5rem;
    }

    .ds-accordion-tabs__item::before {
        margin-block-end: 1.5rem;
    }

    .ds-accordion-tabs .ds-accordion-tabs__item__heading {
        gap: var(--el-spacing-500);
    }
}

/* Nothing travels: the bar is simply where the selected tab is, the panels are
   swapped rather than faded in and an item's body is open or it is not. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-accordion-tabs--ready .ds-accordion-tabs__marker,
    .ds-accordion-tabs .ds-accordion-tabs__tab,
    .ds-accordion-tabs .ds-accordion-tabs__tab .ds-button__background,
    .ds-accordion-tabs .ds-accordion-tabs__item__toggle .ds-button__icon,
    .ds-accordion-tabs__item__body,
    .ds-accordion-tabs__item--open .ds-accordion-tabs__item__body {
        transition: none;
    }

    .ds-accordion-tabs__panel {
        animation: none;
    }
}

/* --------------------------------------------------
   Pricing card element
   -------------------------------------------------- */

.ds-pricing-card {
    /* The widest the card gets, which the header fills and the body is laid
       inset from, fluid like the sizes at the top: 400px on a phone, 320px on
       a tablet and 460px, the design's, on desktop. The card fills whatever it
       is put in up to that, so a column narrower than this gets a narrower
       card rather than an overflowing one. */
    --ds-pricing-card-width: calc(clamp(320px, 476.34px - 20.356vw, 400px) + clamp(320px, 147.14px + 22.508vw, 460px) - 320px); /* 400px / 320px / 460px */

    --ds-pricing-card-radius: var(--el-border-radius-600);

    /* how much narrower the body is laid than the header, on either side */
    --ds-pricing-card-inset: var(--el-padding-200);

    /* Every other size the card sets itself. They are gathered here so the
       small card below can swap each for the step under it in one place. The
       text sizes are not among them: those are the basic elements' own steps,
       picked in the shortcode. */
    --ds-pricing-card-border-width: 4px;

    --ds-pricing-card-header-gap: var(--el-spacing-400);
    --ds-pricing-card-header-padding: var(--el-padding-650);
    --ds-pricing-card-header-padding-end: var(--el-padding-500);

    --ds-pricing-card-intro-gap: var(--el-spacing-300);
    --ds-pricing-card-main-row-gap: var(--el-spacing-150);
    --ds-pricing-card-main-column-gap: var(--el-spacing-250);

    --ds-pricing-card-body-gap: var(--el-padding-450);
    --ds-pricing-card-body-padding-inline: var(--el-padding-500);
    --ds-pricing-card-body-padding-end: var(--el-padding-800);

    --ds-pricing-card-title-gap: var(--el-padding-200);
    --ds-pricing-card-items-gap: var(--el-spacing-250);
    --ds-pricing-card-items-offset: var(--el-spacing-300);
    --ds-pricing-card-item-gap: var(--el-padding-200);
    --ds-pricing-card-icon-size: var(--ds-icon-size-400);

    --ds-pricing-card-toggle-gap: var(--el-spacing-150);
    --ds-pricing-card-toggle-padding-block: var(--el-padding-350);
    --ds-pricing-card-toggle-padding-inline: var(--el-padding-500);
    --ds-pricing-card-toggle-font-size: var(--body-250);

    --ds-pricing-card-sections-gap: var(--el-spacing-400);
    --ds-pricing-card-sections-padding: var(--el-padding-500);
    --ds-pricing-card-sections-padding-end: var(--el-padding-200);

    --ds-pricing-card-text: var(--color-6);

    /* The backgrounds are the theme's, picked by the color id: ds-bg-gd-N-t2
       on the header and ds-sc-bg-N on the body. This is only what the check
       marks are drawn in, on the cream disc they are set on, and each color
       modifier below sets it to the card's own color. */
    --ds-pricing-card-accent: var(--color-1);

    /* the rules that run out from a section title to either edge */
    --ds-pricing-card-rule: rgba( 248, 247, 243, 0.24 );

    display: flex;
    flex-direction: column;

    width: 100%;
    max-width: var(--ds-pricing-card-width);
    margin-inline: auto;

    font-family: var(--main-font);
}

/* The small card. Every size is the step under the one above it, picked so the
   whole card comes down by about the same amount, 0.85 of the default, on a
   phone, a tablet and desktop alike. The kit has no radius between 400 and
   600, so the radius, like the width, is a fluid size of the card's own at
   0.85 of the default one. The eyebrow and the chevron keep their size: they
   are already on the smallest step their scale has.

   The size is picked for desktop and tablet and for a phone on their own, so
   the same set is given twice, once for each. The two ranges do not meet, so
   a card small on one of them keeps the default sizes above on the other. */
@media ( min-width: 768px ) {
    .ds-pricing-card--size-desktop-small {
        --ds-pricing-card-width: calc(clamp(272px, 404.89px - 17.303vw, 340px) + clamp(272px, 126.3px + 18.971vw, 390px) - 272px); /* 340px / 272px / 390px */

        --ds-pricing-card-radius: calc(clamp(14px, 19.86px - 0.763vw, 17px) + clamp(14px, 6.59px + 0.965vw, 20px) - 14px); /* 17px / 14px / 20px */

        --ds-pricing-card-inset: var(--el-padding-150);

        --ds-pricing-card-border-width: 3px;

        --ds-pricing-card-header-gap: var(--el-spacing-350);
        --ds-pricing-card-header-padding: var(--el-padding-550);
        --ds-pricing-card-header-padding-end: var(--el-padding-450);

        --ds-pricing-card-intro-gap: var(--el-spacing-250);
        --ds-pricing-card-main-row-gap: var(--el-spacing-100);
        --ds-pricing-card-main-column-gap: var(--el-spacing-200);

        --ds-pricing-card-body-gap: var(--el-padding-400);
        --ds-pricing-card-body-padding-inline: var(--el-padding-450);
        --ds-pricing-card-body-padding-end: var(--el-padding-750);

        --ds-pricing-card-title-gap: var(--el-padding-150);
        --ds-pricing-card-items-gap: var(--el-spacing-200);
        --ds-pricing-card-items-offset: var(--el-spacing-250);
        --ds-pricing-card-item-gap: var(--el-padding-150);
        --ds-pricing-card-icon-size: var(--ds-icon-size-350);

        --ds-pricing-card-toggle-gap: var(--el-spacing-100);
        --ds-pricing-card-toggle-padding-block: var(--el-padding-300);
        --ds-pricing-card-toggle-padding-inline: var(--el-padding-450);
        --ds-pricing-card-toggle-font-size: var(--body-200);

        --ds-pricing-card-sections-gap: var(--el-spacing-350);
        --ds-pricing-card-sections-padding: var(--el-padding-450);
        --ds-pricing-card-sections-padding-end: var(--el-padding-150);
    }
}

@media ( max-width: 767px ) {
    .ds-pricing-card--size-mobile-small {
        --ds-pricing-card-width: calc(clamp(272px, 404.89px - 17.303vw, 340px) + clamp(272px, 126.3px + 18.971vw, 390px) - 272px); /* 340px / 272px / 390px */

        --ds-pricing-card-radius: calc(clamp(14px, 19.86px - 0.763vw, 17px) + clamp(14px, 6.59px + 0.965vw, 20px) - 14px); /* 17px / 14px / 20px */

        --ds-pricing-card-inset: var(--el-padding-150);

        --ds-pricing-card-border-width: 3px;

        --ds-pricing-card-header-gap: var(--el-spacing-350);
        --ds-pricing-card-header-padding: var(--el-padding-550);
        --ds-pricing-card-header-padding-end: var(--el-padding-450);

        --ds-pricing-card-intro-gap: var(--el-spacing-250);
        --ds-pricing-card-main-row-gap: var(--el-spacing-100);
        --ds-pricing-card-main-column-gap: var(--el-spacing-200);

        --ds-pricing-card-body-gap: var(--el-padding-400);
        --ds-pricing-card-body-padding-inline: var(--el-padding-450);
        --ds-pricing-card-body-padding-end: var(--el-padding-750);

        --ds-pricing-card-title-gap: var(--el-padding-150);
        --ds-pricing-card-items-gap: var(--el-spacing-200);
        --ds-pricing-card-items-offset: var(--el-spacing-250);
        --ds-pricing-card-item-gap: var(--el-padding-150);
        --ds-pricing-card-icon-size: var(--ds-icon-size-350);

        --ds-pricing-card-toggle-gap: var(--el-spacing-100);
        --ds-pricing-card-toggle-padding-block: var(--el-padding-300);
        --ds-pricing-card-toggle-padding-inline: var(--el-padding-450);
        --ds-pricing-card-toggle-font-size: var(--body-200);

        --ds-pricing-card-sections-gap: var(--el-spacing-350);
        --ds-pricing-card-sections-padding: var(--el-padding-450);
        --ds-pricing-card-sections-padding-end: var(--el-padding-150);
    }
}

/* The card's color, so the check marks are drawn in the same color the card
   is. */
.ds-pricing-card--color-1 {
    --ds-pricing-card-accent: var(--color-1);
}

.ds-pricing-card--color-2 {
    --ds-pricing-card-accent: var(--color-2);
}

.ds-pricing-card--color-3 {
    --ds-pricing-card-accent: var(--color-3);
}

.ds-pricing-card--color-4 {
    --ds-pricing-card-accent: var(--color-4);
}

.ds-pricing-card--color-5 {
    --ds-pricing-card-accent: var(--color-5);
}

/* --------------------------------------------------
   The raised header
   -------------------------------------------------- */

.ds-pricing-card__header {
    /* over the body, which is tucked up behind it: the body then shows in the
       two notches the header's bottom corners leave, which is what makes the
       header read as a lid rather than as a block sat on top */
    position: relative;
    z-index: 1;

    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--ds-pricing-card-header-gap);

    padding: var(--ds-pricing-card-header-padding);
    padding-bottom: var(--ds-pricing-card-header-padding-end);
    border-radius: var(--ds-pricing-card-radius);

    /* ds-bg-gd-N-t2 paints its border gradient under the border and sets the
       border's color to transparent, so it only shows where the element has a
       border to show it through. The style and the width are given here, the
       color is left to the theme's class. */
    --ds-border-gd-width: var(--ds-pricing-card-border-width);

    border-style: solid;
    border-width: var(--ds-border-gd-width);

    color: var(--ds-pricing-card-text);

    box-shadow: 0 0.75rem 1.5rem -0.75rem rgba( 0, 0, 0, 0.32 );
}

/* --------------------------------------------------
   The body under it
   -------------------------------------------------- */

.ds-pricing-card__body {
    position: relative;
    z-index: 0;

    display: flex;
    flex-direction: column;
    gap: var(--ds-pricing-card-body-gap);

    /* pulled up by its own radius so the header's rounded bottom sits on it
       rather than beside it, and the padding gives that height back on the
       inside so nothing is written into the part that is covered */
    margin-top: calc( var(--ds-pricing-card-radius) * -1 );
    margin-inline: var(--ds-pricing-card-inset);

    padding-block-start: calc( var(--ds-pricing-card-radius) + var(--ds-pricing-card-body-gap) );
    padding-inline: var(--ds-pricing-card-body-padding-inline);
    padding-block-end: var(--ds-pricing-card-body-padding-end);
    border-radius: var(--ds-pricing-card-radius);

    color: var(--ds-pricing-card-text);
}

/* --------------------------------------------------
   What the header holds
   -------------------------------------------------- */

/* The eyebrow and the row of the name and the price, kept together and set
   closer to each other than the header sets them to the button under them. */
.ds-pricing-card__intro {
    display: flex;
    flex-direction: column;
    gap: var(--ds-pricing-card-intro-gap);
}

/* The eyebrow is the heading's eyebrow and looks the way it does everywhere.
   The chip is only as wide as the words in it, so it is kept from stretching
   across the header. */
.ds-pricing-card .ds-pricing-card__eyebrow {
    align-self: flex-start;
}

/* The name of the plan and what it costs, read across rather than down: the
   two sit on the same line at the bottom, which is what lines the price up
   with the last line of a name that runs to two. */
.ds-pricing-card__main {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--ds-pricing-card-main-row-gap) var(--ds-pricing-card-main-column-gap);
}

/* The name of the plan is a heading and looks the way headings do everywhere,
   except for its line height. This gives it that and its share of the row it
   shares with the price. Two classes, like the heading's own rule, and later in
   the file, so the line height here is the one that applies. */
.ds-pricing-card .ds-pricing-card__heading {
    flex: 1 1 8ch;
    line-height: var(--heading-line-height-500);

    margin-bottom: -0.1em;
}

/* The price steps are carried here rather than on the price itself, and the
   price that applies is set in em off this. The price that no longer applies
   carries a step of its own. Both read their steps off the body scale. */
.ds-pricing-card .ds-pricing-card__prices {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.25em;

    flex: 0 1 auto;
    margin: 0;

    text-align: right;
}

.ds-pricing-card__prices--450 {
    font-size: var(--body-450);
}

.ds-pricing-card__prices--500 {
    font-size: var(--body-500);
}

.ds-pricing-card__prices--550 {
    font-size: var(--body-550);
}

.ds-pricing-card__price {
    line-height: var(--heading-line-height-400, 1em);
    font-weight: var(--ds-global-heading-font-weight-400, 900);
    letter-spacing: var(--ds-global-heading-letter-spacing-400, -0.04em);
    white-space: nowrap;
}

/* The price that no longer applies. It is set in a step of its own off the
   body scale rather than against the price that does. */
.ds-pricing-card .ds-pricing-card__price--scratched {
    font-weight: 500;
    opacity: 0.72;
    text-decoration-line: line-through;
    text-decoration-thickness: 0.08em;
}

.ds-pricing-card .ds-pricing-card__price--200 {
    font-size: var(--body-200);
}

.ds-pricing-card .ds-pricing-card__price--250 {
    font-size: var(--body-250);
}

.ds-pricing-card .ds-pricing-card__price--300 {
    font-size: var(--body-300);
}

/* The mobile steps of the prices and of the price that no longer applies,
   printed only when a phone takes another step than the one above. */
@media ( max-width: 767px ) {
    .ds-pricing-card__prices--mobile-450 {
        font-size: var(--body-450);
    }

    .ds-pricing-card__prices--mobile-500 {
        font-size: var(--body-500);
    }

    .ds-pricing-card__prices--mobile-550 {
        font-size: var(--body-550);
    }

    .ds-pricing-card .ds-pricing-card__price--mobile-200 {
        font-size: var(--body-200);
    }

    .ds-pricing-card .ds-pricing-card__price--mobile-250 {
        font-size: var(--body-250);
    }

    .ds-pricing-card .ds-pricing-card__price--mobile-300 {
        font-size: var(--body-300);
    }
}

.ds-pricing-card__price--current {
    display: block;
    font-size: 1em;
}

/* A price read off the Pricing settings. The symbol is an acronym in CA$, US$
   and A$, so it is put back in the capitals the lowercased price takes out. */
.ds-pricing-card .ds-pricing-card__price__symbol {
    text-transform: uppercase;
}

/* A price with nothing set in the currency the page is read in. The switcher
   hides it rather than leave the last currency's price on show. */
.ds-pricing-card .ds-pricing-card__price[data-ds-currency-unavailable] {
    display: none;
}

/* --------------------------------------------------
   What the body holds
   -------------------------------------------------- */

/* The title of a section, set in a chip with a rule running out from it to
   either edge. The rules are drawn rather than written, so a title is one line
   of text however wide the card turns out. */
.ds-pricing-card .ds-pricing-card__section__title {
    display: flex;
    align-items: center;
    gap: var(--ds-pricing-card-title-gap);

    margin: 0;
}

.ds-pricing-card__section__title::before,
.ds-pricing-card__section__title::after {
    content: '';

    flex: 1 1 0;
    height: 2px;

    border-radius: 100em;

    background-color: var(--ds-pricing-card-rule);
}

/* The title itself is the heading's eyebrow, held to its words between the two
   rules. */
.ds-pricing-card__section__title__label {
    flex: 0 1 auto;

    text-align: center;
}

.ds-pricing-card .ds-pricing-card__items {
    display: flex;
    flex-direction: column;
    gap: var(--ds-pricing-card-items-gap);

    padding: 0;
    margin: var(--ds-pricing-card-items-offset) 0 0;

    list-style: none;
}

/* Every line is a body text beside its mark. */
.ds-pricing-card .ds-pricing-card__item {
    display: flex;
    align-items: flex-start;
    gap: var(--ds-pricing-card-item-gap);

    margin: 0;
}

.ds-pricing-card__item__icon {
    /* the mark keeps its size while the line beside it grows, and the nudge
       sets it against the first line of that text rather than against the
       block of it */
    flex: 0 0 auto;
    display: block;

    width: var(--ds-pricing-card-icon-size);
    height: var(--ds-pricing-card-icon-size);
}

.ds-pricing-card__item__glyph {
    display: block;
    width: 100%;
    height: 100%;
}

.ds-pricing-card__item__glyph__disc {
    fill: var(--ds-pricing-card-text);
}

.ds-pricing-card__item__glyph__mark {
    stroke: var(--ds-pricing-card-accent);
}

/* --------------------------------------------------
   The collapsible body
   -------------------------------------------------- */

.ds-pricing-card--collapsible {
    --ds-pricing-card-move-duration: 320ms;
    --ds-pricing-card-move-easing: cubic-bezier( 0.33, 1, 0.68, 1 );
}

/* The body keeps its color, its inset and the part of it tucked under the
   header, and hands the rest of its room to the sections and to the toggle
   under them, so a closed card is the header over a strip as tall as the
   toggle. */
.ds-pricing-card--collapsible .ds-pricing-card__body {
    gap: 0;

    padding-block-start: var(--ds-pricing-card-radius);
    padding-inline: 0;
    padding-block-end: 0;
}

/* The strip at the foot of the body that opens and closes it. It is a real
   button, so the browser's own look, and any the theme gives buttons, is taken
   off, and its label and chevron are held together in the middle of it. */
.ds-pricing-card .ds-pricing-card__toggle,
.ds-pricing-card .ds-pricing-card__toggle:hover,
.ds-pricing-card .ds-pricing-card__toggle:focus {
    background: transparent;
    color: inherit;
}

.ds-pricing-card .ds-pricing-card__toggle {
    -webkit-appearance: none;
    appearance: none;

    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ds-pricing-card-toggle-gap);

    width: 100%;
    margin: 0;
    padding: var(--ds-pricing-card-toggle-padding-block) var(--ds-pricing-card-toggle-padding-inline);

    border: 0;
    border-radius: 0 0 var(--ds-pricing-card-radius) var(--ds-pricing-card-radius);

    font: inherit;
    text-align: center;
    cursor: pointer;
}

.ds-pricing-card .ds-pricing-card__toggle:focus-visible {
    outline: 2px solid var(--ds-pricing-card-text);
    outline-offset: -0.375rem;
}

/* The label carries its whole look itself rather than the body text classes:
   the section lines' size step, in bold and in the card's cream. It is only as
   wide as its words, so the label and the chevron are centered as a pair
   rather than the label filling the button. */
.ds-pricing-card .ds-pricing-card__toggle__label {
    display: block;
    flex: 0 1 auto;
    width: auto;
    margin: 0;

    font-family: var(--main-font);
    font-size: var(--ds-pricing-card-toggle-font-size);
    font-weight: 700;
    line-height: var(--body-line-height-400);
    letter-spacing: var(--ds-global-body-text-letter-spacing-400, -0.04em);
    text-align: center;

    color: var(--ds-pricing-card-text);
}

/* Both labels are printed, the one for the state the card is in is shown. */
.ds-pricing-card .ds-pricing-card__toggle__label--open,
.ds-pricing-card--open .ds-pricing-card__toggle__label--closed {
    display: none;
}

.ds-pricing-card--open .ds-pricing-card__toggle__label--open {
    display: block;
}

/* The chevron is turned over rather than swapped, so open and closed are one
   shape. */
.ds-pricing-card .ds-pricing-card__toggle__arrow {
    display: block;
    flex: 0 0 auto;

    width: var(--ds-icon-size-300);
    height: calc( var(--ds-icon-size-300) * 0.6153 );
    max-width: none;
    margin: 0;

    transition: transform var(--ds-pricing-card-move-duration) var(--ds-pricing-card-move-easing);
}

.ds-pricing-card--open .ds-pricing-card__toggle__arrow {
    transform: rotate( 180deg );

    margin-top: 0.1em;
}

/* The sections, opened by letting their row grow from nothing to what they
   need rather than by animating a height nothing knows in advance. The
   visibility takes a closed body out of reach of the keyboard and of a screen
   reader, and it is held until the row has finished closing so the sections do
   not vanish before they have folded away. */
.ds-pricing-card__panel {
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;
    opacity: 0;

    transition:
        grid-template-rows var(--ds-pricing-card-move-duration) var(--ds-pricing-card-move-easing),
        opacity var(--ds-pricing-card-move-duration) var(--ds-pricing-card-move-easing),
        visibility 0s linear var(--ds-pricing-card-move-duration);
}

.ds-pricing-card--open .ds-pricing-card__panel {
    grid-template-rows: 1fr;
    visibility: visible;
    opacity: 1;

    transition:
        grid-template-rows var(--ds-pricing-card-move-duration) var(--ds-pricing-card-move-easing),
        opacity var(--ds-pricing-card-move-duration) var(--ds-pricing-card-move-easing),
        visibility 0s linear;
}

.ds-pricing-card__panel__inner {
    /* both are needed for the row to be able to shrink to nothing */
    min-height: 0;
    overflow: hidden;
}

/* The padding sits a level in from the row that collapses, since a box cannot
   shrink below its own padding. Off the open design: 2rem from the header to
   the first section and between sections, and 2rem from the last section to
   the toggle's label, three quarters of it here and the rest the toggle's own
   padding. */
.ds-pricing-card__sections {
    display: flex;
    flex-direction: column;
    gap: var(--ds-pricing-card-sections-gap);

    padding-block-start: var(--ds-pricing-card-sections-padding);
    padding-inline: var(--ds-pricing-card-sections-padding);
    padding-block-end: var(--ds-pricing-card-sections-padding-end);
}

/* Nothing folds: the body is open or it is not. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-pricing-card .ds-pricing-card__toggle__arrow,
    .ds-pricing-card__panel,
    .ds-pricing-card--open .ds-pricing-card__panel {
        transition: none;
    }
}

/* --------------------------------------------------
   Currency switcher element
   -------------------------------------------------- */

.ds-currency-switcher {
    --ds-currency-switcher-color: var(--color-1);
    --ds-currency-switcher-duration: 0.2s;

    /* Which side the button keeps to, and where the list opens against it:
       flush with the same side, or centred over it. Set per breakpoint by the
       align classes below. */
    --ds-currency-switcher-justify: flex-end;
    --ds-currency-switcher-list-left: auto;
    --ds-currency-switcher-list-right: 0;
    --ds-currency-switcher-list-shift: 0;

    /* the list is placed against this, on the side the button keeps to */
    position: relative;

    display: flex;
    justify-content: var(--ds-currency-switcher-justify);

    font-family: var(--main-font);
}

/* Tablet and mobile classes are only printed when set, so without one the
   larger breakpoint's side carries down. */
.ds-currency-switcher--align-desktop-left { --ds-currency-switcher-justify: flex-start; --ds-currency-switcher-list-left: 0; --ds-currency-switcher-list-right: auto; --ds-currency-switcher-list-shift: 0; }
.ds-currency-switcher--align-desktop-center { --ds-currency-switcher-justify: center; --ds-currency-switcher-list-left: 50%; --ds-currency-switcher-list-right: auto; --ds-currency-switcher-list-shift: -50%; }
.ds-currency-switcher--align-desktop-right { --ds-currency-switcher-justify: flex-end; --ds-currency-switcher-list-left: auto; --ds-currency-switcher-list-right: 0; --ds-currency-switcher-list-shift: 0; }

@media ( max-width: 1024px ) {
    .ds-currency-switcher--align-tablet-left { --ds-currency-switcher-justify: flex-start; --ds-currency-switcher-list-left: 0; --ds-currency-switcher-list-right: auto; --ds-currency-switcher-list-shift: 0; }
    .ds-currency-switcher--align-tablet-center { --ds-currency-switcher-justify: center; --ds-currency-switcher-list-left: 50%; --ds-currency-switcher-list-right: auto; --ds-currency-switcher-list-shift: -50%; }
    .ds-currency-switcher--align-tablet-right { --ds-currency-switcher-justify: flex-end; --ds-currency-switcher-list-left: auto; --ds-currency-switcher-list-right: 0; --ds-currency-switcher-list-shift: 0; }
}

@media ( max-width: 767px ) {
    .ds-currency-switcher--align-mobile-left { --ds-currency-switcher-justify: flex-start; --ds-currency-switcher-list-left: 0; --ds-currency-switcher-list-right: auto; --ds-currency-switcher-list-shift: 0; }
    .ds-currency-switcher--align-mobile-center { --ds-currency-switcher-justify: center; --ds-currency-switcher-list-left: 50%; --ds-currency-switcher-list-right: auto; --ds-currency-switcher-list-shift: -50%; }
    .ds-currency-switcher--align-mobile-right { --ds-currency-switcher-justify: flex-end; --ds-currency-switcher-list-left: auto; --ds-currency-switcher-list-right: 0; --ds-currency-switcher-list-shift: 0; }
}

/* The button is the flag, the code and the arrow off the design and nothing
   more, so whatever the theme or Elementor dress a button in is taken off. */
.ds-currency-switcher .ds-currency-switcher__toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--el-spacing-150);

    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--el-border-radius-100);

    background: none;
    color: var(--ds-currency-switcher-color);
    box-shadow: none;

    font: inherit;
    text-transform: none;

    cursor: pointer;
}

.ds-currency-switcher .ds-currency-switcher__toggle:hover,
.ds-currency-switcher .ds-currency-switcher__toggle:focus {
    background: none;
    color: var(--ds-currency-switcher-color);
}

.ds-currency-switcher .ds-currency-switcher__toggle:focus-visible {
    outline: 2px solid var(--ds-currency-switcher-color);
    outline-offset: 4px;
}

.ds-currency-switcher__current {
    display: inline-flex;
    align-items: center;
    gap: var(--el-spacing-150);
}

/* the display set above would otherwise win over hidden */
.ds-currency-switcher .ds-currency-switcher__current[hidden],
.ds-currency-switcher .ds-currency-switcher__list[hidden] {
    display: none;
}

/* The height is the design's, the width follows it through the flag's own
   viewBox, since the flags are not all drawn to the same one. Left to its
   width attribute, a flag would keep that width while the height shrinks
   below desktop, and the ones exported without a fixed aspect ratio stretch. */
.ds-currency-switcher .ds-currency-switcher__flag {
    display: block;
    flex: 0 0 auto;

    width: auto;
    height: var(--ds-icon-size-300);
    max-width: none;
}

/* Geomanist Medium, trimmed to the cap height like in the design, so the code
   centres against the flag by its letters rather than by its line box. The
   code is an acronym and keeps its capitals. */
.ds-currency-switcher__code {
    line-height: 1.26;
    font-weight: 500;
    letter-spacing: var(--ds-global-body-text-letter-spacing-400, -0.04em);
    text-transform: uppercase;
    white-space: nowrap;

    text-box: trim-both cap alphabetic;
}

/* Font size steps off the body type scale. */
.ds-currency-switcher__code--250 {
    font-size: var(--body-250);
}

.ds-currency-switcher__code--300 {
    font-size: var(--body-300);
}

.ds-currency-switcher__code--350 {
    font-size: var(--body-350);
}

.ds-currency-switcher__code--400 {
    font-size: var(--body-400);
}

.ds-currency-switcher .ds-currency-switcher__arrow {
    display: block;
    flex: 0 0 auto;

    width: var(--ds-icon-size-300);
    height: calc( var(--ds-icon-size-300) * 0.625 );
    max-width: none;

    transition: transform var(--ds-currency-switcher-duration) ease;
}

.ds-currency-switcher--open .ds-currency-switcher__arrow {
    transform: rotate( 180deg );
}

/* The list, opened above the button. It is as wide as its longest currency
   rather than as wide as the column the switcher sits in. Its fill and grain
   come from the theme's .ds-sc-bg-6, set on the element itself. */
.ds-currency-switcher .ds-currency-switcher__list {
    position: absolute;
    bottom: calc( 100% + var(--el-padding-200) );
    left: var(--ds-currency-switcher-list-left);
    right: var(--ds-currency-switcher-list-right);
    z-index: 20;

    transform: translateX( var(--ds-currency-switcher-list-shift) );

    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-50);

    width: max-content;
    margin: 0;
    padding: var(--el-spacing-150);
    border-radius: var(--el-border-radius-300);

    box-shadow: 0 0.75rem 1.5rem -0.75rem rgba( 0, 0, 0, 0.32 );

    list-style: none;
}

.ds-currency-switcher .ds-currency-switcher__list:focus {
    outline: none;
}

/* A currency that is not the chosen one is drawn faint, the chosen one and
   the one the pointer or the keyboard is on in full. */
.ds-currency-switcher .ds-currency-switcher__option {
    display: flex;
    align-items: center;
    gap: var(--el-spacing-150);

    margin: 0;
    padding: var(--el-padding-150) var(--el-padding-200);
    border-radius: var(--el-border-radius-200);

    color: var(--ds-currency-switcher-color);
    opacity: 0.56;

    cursor: pointer;

    transition:
        opacity var(--ds-currency-switcher-duration) ease,
        background-color var(--ds-currency-switcher-duration) ease;
}

.ds-currency-switcher .ds-currency-switcher__option--active,
.ds-currency-switcher .ds-currency-switcher__option--focused {
    opacity: 1;
}

.ds-currency-switcher .ds-currency-switcher__option--focused {
    background-color: var(--color-btn-secondary-bg-1);
}

/* the ring only shows while the list is worked with the keyboard */
.ds-currency-switcher .ds-currency-switcher__list:focus-visible .ds-currency-switcher__option--focused {
    box-shadow: inset 0 0 0 1px var(--color-btn-secondary-border-1);
}

@media ( prefers-reduced-motion: reduce ) {
    .ds-currency-switcher .ds-currency-switcher__arrow,
    .ds-currency-switcher .ds-currency-switcher__option {
        transition: none;
    }
}

/* --------------------------------------------------
   Currency placeholder
   -------------------------------------------------- */

/* While the visitor's currency is still being worked out, the html element
   carries ds-currency-pending, and every price and every currency switcher is
   drawn as a faint bar flickering softly in its own color, so nobody reads the
   default price that is about to change. See DesensitizeElementsCurrency.

   A card's prices are covered by one bar over the whole of their container,
   the crossed out price and every suffix included, and a switcher's flag and
   code by one bar of their own. What is under a bar is hidden but keeps its
   room, so the bar is the size of what it stands in for and nothing moves
   once that shows.

   Once the currency is known, the html element carries ds-currency-revealing
   instead for a moment: the bar fades away and what was under it fades in,
   rising a little out of a soft blur. */
.ds-currency-pending .ds-pricing-card .ds-pricing-card__prices,
.ds-currency-revealing .ds-pricing-card .ds-pricing-card__prices,
.ds-currency-pending .ds-currency-switcher .ds-currency-switcher__current,
.ds-currency-revealing .ds-currency-switcher .ds-currency-switcher__current {
    position: relative;
}

.ds-currency-pending .ds-pricing-card .ds-pricing-card__prices > *,
.ds-currency-pending .ds-currency-switcher .ds-currency-switcher__current > * {
    visibility: hidden;
}

.ds-currency-pending .ds-pricing-card .ds-pricing-card__prices::after,
.ds-currency-revealing .ds-pricing-card .ds-pricing-card__prices::after,
.ds-currency-pending .ds-currency-switcher .ds-currency-switcher__current::after,
.ds-currency-revealing .ds-currency-switcher .ds-currency-switcher__current::after {
    content: "";

    position: absolute;
    inset: 0;

    border-radius: 0.2em;
    background-color: currentColor;
    pointer-events: none;
}

.ds-currency-pending .ds-currency-switcher .ds-currency-switcher__current::after,
.ds-currency-revealing .ds-currency-switcher .ds-currency-switcher__current::after {
    background-color: var(--ds-currency-switcher-color);
}

.ds-currency-pending .ds-pricing-card .ds-pricing-card__prices::after,
.ds-currency-pending .ds-currency-switcher .ds-currency-switcher__current::after {
    animation: ds-currency-pending 0.9s ease-in-out infinite alternate;
}

.ds-currency-revealing .ds-pricing-card .ds-pricing-card__prices::after,
.ds-currency-revealing .ds-currency-switcher .ds-currency-switcher__current::after {
    animation: ds-currency-reveal-bar 0.35s ease-out forwards;
}

/* The fade in has no end of its own, so each part ends on the opacity it
   already has: the crossed out price stays as faint as it always is. */
.ds-currency-revealing .ds-pricing-card .ds-pricing-card__prices > *,
.ds-currency-revealing .ds-currency-switcher .ds-currency-switcher__current > * {
    animation: ds-currency-reveal-text 0.5s cubic-bezier( 0.2, 0.7, 0.3, 1 ) 0.1s both;
}

@keyframes ds-currency-pending {
    from {
        opacity: 0.08;
    }

    to {
        opacity: 0.22;
    }
}

@keyframes ds-currency-reveal-bar {
    from {
        opacity: 0.15;
    }

    to {
        opacity: 0;
    }
}

@keyframes ds-currency-reveal-text {
    from {
        opacity: 0;
        filter: blur( 0.12em );
        transform: translateY( 0.2em );
    }
}

/* Without motion the bar holds still, and the prices take its place at once. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-currency-pending .ds-pricing-card .ds-pricing-card__prices::after,
    .ds-currency-pending .ds-currency-switcher .ds-currency-switcher__current::after {
        animation: none;
        opacity: 0.15;
    }

    .ds-currency-revealing .ds-pricing-card .ds-pricing-card__prices::after,
    .ds-currency-revealing .ds-currency-switcher .ds-currency-switcher__current::after {
        display: none;
    }

    .ds-currency-revealing .ds-pricing-card .ds-pricing-card__prices > *,
    .ds-currency-revealing .ds-currency-switcher .ds-currency-switcher__current > * {
        animation: none;
    }
}

/* --------------------------------------------------
   Orbital tabs element
   -------------------------------------------------- */

.ds-orbital-tabs {
    /* The whole of the ring's geometry, taken off the design and written as
       shares so the figure scales with the element rather than being measured.

       The design's frame is 1280 by 1179, and the icon the ring turns around
       stands at 700, 557 in it. A circle passing straight up over the icon
       rises 454 + 126.858 = 580.858 above it, 23.858 higher than that frame's
       top, so the stage is the frame with that much added above it: 1280 by
       1202.858, with the icon at 700, 580.858. The five circles are 253.716
       across and their centres lie 454 out from that icon: the centres on the
       design sit 40.5, 40.5, 41.4 and 41.7 degrees apart on a ring of exactly
       that radius, which is the 41 degree step the element is drawn on and the
       one the shortcode hands to the script.

       The radius is written as a share of a circle's own width rather than of
       the stage, because a percentage inside a transform is read against the
       element being transformed: 454 / 253.716 is 178.89%. Since a circle's
       width is itself a share of the stage, the radius still comes out at
       454 / 1280 of it, and the one number holds the ring together at any
       size the element is given. */
    /* The design's 700 puts the circle at three o'clock 700 + 454 + 126.858 =
       1280.858 across, just past the stage's edge, where the stage cuts it
       off along with its focus outline. The ring and the icon are drawn 16
       further left instead, which leaves that circle 15 clear of the edge. */
    --ds-orbital-tabs-center-x: 53.4375%;   /* 684 / 1280 */
    --ds-orbital-tabs-center-y: 48.2898%;   /* 580.858 / 1202.858 */
    --ds-orbital-tabs-item: 19.822%;        /* 253.716 / 1280 */
    --ds-orbital-tabs-orbit: 178.89%;       /* 454 / 253.716 */

    /* how far down the stage the text column stands, the design's 400 and the
       23.858 added above it. It is
       read off the stage's width rather than its height, so the overlay inside
       the column can be carried back up by the very same distance: a
       percentage in there would be read against the column, not the stage */
    --ds-orbital-tabs-main-top: 33.1139cqi; /* 423.858 / 1280 */

    /* the room the stage keeps above the frame. A circle near the top of the
       ring rises and grows under the mouse, and without it that circle, or
       its focus outline, is cut off at the stage's edge */
    --ds-orbital-tabs-stage-top: var(--el-spacing-250);

    /* the hub: the icon and the two trails of dots beside it, 472 across
       altogether, and the share of that each gap between them takes. A trail
       is a dot connector at the connector's own sizes, 92 across on desktop */
    --ds-orbital-tabs-hub: 36.875%;         /* 472 / 1280 */
    --ds-orbital-tabs-hub-icon: var(--ds-icon-size-900);
    --ds-orbital-tabs-hub-gap: 16.9492%;    /* 80 / 472 */

    /* a circle's edge. It is a length rather than a share, because it is a
       weight the design holds to rather than part of the drawing, and the
       bottom of it is the heavier one every button on the site carries */
    --ds-orbital-tabs-rule: 0.3125rem;
    --ds-orbital-tabs-rule-bottom: 0.4225rem;

    /* the clock on the circle at rest: how thick its ring is, and the white it
       fills with. The rest of the ring has no track, only the part that has
       filled is drawn */
    --ds-orbital-tabs-progress-width: 5px;
    --ds-orbital-tabs-progress-fill: rgba( 248, 247, 243, 0.8 );

    /* how long the clock on a circle, and a circle passing round the back of
       the ring, take to fade. The turn itself, and the panels changing under
       it, are drawn by the script frame by frame, the way the card deck is */
    --ds-orbital-tabs-fade-duration: 420ms;
    --ds-orbital-tabs-fade-easing: cubic-bezier( 0.4, 0, 0.2, 1 );

    /* Nothing inside the element gives it a width of its own: the stage is a
       size container and everything on it is placed absolutely, and on a phone
       the ring's row is as wide as the screen. A parent that sizes what it
       holds by its content, such as a flex row, would shrink it to nothing or
       stretch it past the edges, so it always takes its parent's width. */
    width: 100%;

    font-family: var(--main-font);
    color: var(--color-1);
}

/* The design's frame. Everything inside it is placed against this one box, so
   the ring, the icon and the text keep the positions they were drawn in
   however wide the element ends up being.

   It is a container as well, so a cqi anywhere inside it is a share of the
   stage's own width, which is what the text column is carried down it by.

   Its height is exactly the reach of the ring, so no circle passes out of it at
   any point of a turn, and whatever does lie outside it, such as the corner of
   the overlay, is cut off at its edge.

   The room above the frame is padding on top of that height. The stage is
   sized by its content box, so the ratio stays the frame's alone, and the ring
   and the text are carried down past the padding. */
.ds-orbital-tabs__stage {
    position: relative;
    box-sizing: content-box;
    aspect-ratio: 1280 / 1202.858;
    padding-top: var(--ds-orbital-tabs-stage-top);
    overflow: hidden;

    container-type: inline-size;
}

/* The ring and the icon it turns around. It is drawn before the text and left
   below it, so a circle that swings round to the far side of the ring passes
   behind the copy rather than over it. */
.ds-orbital-tabs__orbit {
    position: absolute;
    inset: var(--ds-orbital-tabs-stage-top) 0 0;
    z-index: 1;
}

.ds-orbital-tabs__main {
    position: absolute;
    left: 0;
    top: calc( var(--ds-orbital-tabs-stage-top) + var(--ds-orbital-tabs-main-top) );
    z-index: 2;

    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-550);

    width: min( 25rem, 36% );
}

/* The page's own background in an ellipse at the stage's top left corner, so a
   circle that comes round under it sinks into the page.

   It sits in the orbit between the ring and the icon, so it is painted over the
   circles and under the icon. It takes no pointer, so a circle showing through
   its faded side can still be pressed.

   The fill and the grain are the theme's .ds-sc-bg-6, the cream the page itself
   is painted in, which the element puts on it. The mask fades that fill out: a
   radial gradient from the middle of the left edge, fully solid from the left
   side to the middle and transparent by the right side. */
.ds-orbital-tabs__overlay {
    /* the size of the ellipse: set these two to reshape it. Both are shares of
       the stage, the width of its width and the height of its height. */
    --ds-orbital-tabs-overlay-width: 72%;
    --ds-orbital-tabs-overlay-height: 106.41%;

    --ds-orbital-tabs-overlay-mask: radial-gradient(farthest-side at 0% 50%, #000 64%, transparent 100%);

    /* top is a share of the stage's height and left of its width */
    position: absolute;
    top: -18.24%;
    left: -8%;

    width: var(--ds-orbital-tabs-overlay-width);
    height: var(--ds-orbital-tabs-overlay-height);
    border-radius: 50%;

    pointer-events: none;

    -webkit-mask: var(--ds-orbital-tabs-overlay-mask);
    mask: var(--ds-orbital-tabs-overlay-mask);
}

/* The ring
   -------------------------------------------------- */

/* Every circle is laid at the middle of the ring and then carried out to its
   own angle, so the middle is the one point they are all placed from and the
   transform is the whole of what tells them apart.

   Left and top put the circle's own middle exactly on the icon's: the two
   margins are shares of the stage's width, which is what a margin percentage
   is read against whichever side it sits on, so half a circle is taken back
   off each of them. */
.ds-orbital-tabs__item {
    position: absolute;
    left: var(--ds-orbital-tabs-center-x);
    top: var(--ds-orbital-tabs-center-y);

    width: var(--ds-orbital-tabs-item);
    aspect-ratio: 1;

    margin-left: calc( var(--ds-orbital-tabs-item) / -2 );
    margin-top: calc( var(--ds-orbital-tabs-item) / -2 );

    display: flex;
    align-items: center;
    justify-content: center;

    /* A padding percentage is read against the stage's width rather than the
       circle's own, so the shares the design gives it, 23.68 down and 20.297
       across of a 253.716 circle, are taken off the circle's width first and
       what is left is a share of the stage like everything else here. */
    padding:
        calc( var(--ds-orbital-tabs-item) * 0.0933 )
        calc( var(--ds-orbital-tabs-item) * 0.08 );
    border-width: var(--ds-orbital-tabs-rule);
    border-bottom-width: var(--ds-orbital-tabs-rule-bottom);
    border-style: solid;
    border-radius: 50%;

    /* the fill, the edge and the grain come from the site's .ds-bg-gd-{color}
       class, which the element puts on the circle from its color id */

    color: var(--color-6);

    font-family: inherit;
    cursor: pointer;

    /* Where a circle stands on the ring.

       A circle is placed by three parts: turn out to its angle, travel the
       ring's radius along the turned axis, then turn back by the same angle so
       the label inside is left upright. PHP writes those three on every circle
       for the first paint. Once the script has the ring it writes them itself
       on every frame of a turn, from where the ring stands at that moment, so
       the circles travel the arc of the ring rather than cutting the chord
       across it, and the turn is not transitioned here. Only the fade a circle
       is given as it passes round the back of the ring is. */
    transition: opacity var(--ds-orbital-tabs-fade-duration) var(--ds-orbital-tabs-fade-easing);
}

/* The circles are laid over one another with the one nearest rest on top, which
   the script keeps true as the ring turns. That order is kept to the ring, so
   it is never read against the overlay and the icon drawn over the circles. */
.ds-orbital-tabs__ring {
    isolation: isolate;
}

/* The clock on the circle at rest: a ring held just inside its edge that fills
   clockwise from twelve o'clock over the time the tab is held, so it is full
   at the moment the ring turns to the next one.

   How far round it has filled is --ds-orbital-tabs-progress, a share from 0 to
   1 the script writes on the circle every frame from the same clock that turns
   the ring.

   The ring is an SVG circle stroked as one dash, because a stroke is what can
   carry fully rounded ends. The circle is given a path length of 1, so the
   share is the dash's length as it stands. A circle's path starts at three
   o'clock and runs clockwise, so the drawing is turned a quarter back to start
   it at twelve. */
.ds-orbital-tabs__item__progress {
    position: absolute;
    /* the design holds it 13.532 in from the circle's edge, which is 8.458 in
       from the inside of the edge, and that is what an inset is measured from */
    /* an SVG is a replaced element, so the inset alone does not stretch it and
       the size it is left with is given outright */
    left: 3.5%;
    top: 3.5%;
    width: 93%;
    height: 93%;
    max-width: none;
    overflow: visible;
    transform: rotate( -90deg );

    opacity: 0;
    transition: opacity var(--ds-orbital-tabs-fade-duration) var(--ds-orbital-tabs-fade-easing);

    pointer-events: none;
}

.ds-orbital-tabs__item__progress__arc {
    /* the stroke is centred on the circle's line, so the radius is taken in
       by half of it to keep the ring's outer edge on the inset above */
    r: calc( 50% - var(--ds-orbital-tabs-progress-width) / 2 );

    fill: none;
    stroke: var(--ds-orbital-tabs-progress-fill);
    stroke-width: var(--ds-orbital-tabs-progress-width);
    stroke-linecap: round;
    stroke-dasharray: var(--ds-orbital-tabs-progress, 0) 1;
}

/* It is only shown while there is a clock for it to show: once the script is
   running and for as long as the ring is turning on its own. A ring that has
   been paused, or that was never set turning, has no clock and no ring. */
.ds-orbital-tabs--ready:not(.ds-orbital-tabs--paused) .ds-orbital-tabs__item--active .ds-orbital-tabs__item__progress {
    opacity: 0.32;
}

.ds-orbital-tabs__item:hover {
    filter: brightness( 1.04 );
}

.ds-orbital-tabs__item:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 4px;
}

/* Once the script has the ring, a circle can be taken hold of and turned round
   the icon, and nothing on it is picked up as text or dragged off as a picture
   on the way.

   A finger on a circle turns the ring when it goes the way the circle travels,
   and the other way is still the page's. A circle beside the icon travels up
   and down, so going across it is left to the page, and one above or below the
   icon travels across, so going up and down it is. The script says which a
   circle is doing as the ring turns. A pinch still zooms the page, where a
   browser understands as much. */
.ds-orbital-tabs--draggable .ds-orbital-tabs__item {
    touch-action: pan-x;
    touch-action: pan-x pinch-zoom;

    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
}

.ds-orbital-tabs--draggable .ds-orbital-tabs__item[data-ds-orbital-tabs-axis="x"] {
    touch-action: pan-y;
    touch-action: pan-y pinch-zoom;
}

/* The ring can be taken hold of, which only a mouse has any way of showing. The
   other circles keep the pointer, since pressing one is the plainest way to
   reach its tab. */
.ds-orbital-tabs--draggable .ds-orbital-tabs__item--active {
    cursor: grab;
}

.ds-orbital-tabs--dragging .ds-orbital-tabs__ring,
.ds-orbital-tabs--dragging .ds-orbital-tabs__item {
    cursor: grabbing;
}

/* Only while the ring moves: the circles are handed to the compositor for the
   move and given back at the end of it, so their wording is drawn afresh, and
   sharp, once they have come to rest. */
.ds-orbital-tabs--moving .ds-orbital-tabs__item {
    will-change: transform;
}

/* How far round the back of the ring a circle has gone.

   The ring is drawn wider than the element, so its far side lies over the text
   rather than beside it. A circle that reaches there passes under the overlay
   beside the text and is taken out of reach, and it comes back as the ring
   carries it round to the front again. Everything the design shows at once,
   which is the whole arc from one side of the icon to the other, stays in front
   the whole time. */
.ds-orbital-tabs__item[data-ds-orbital-tabs-depth="rim"] {
    opacity: 0.32;
}

.ds-orbital-tabs__item[data-ds-orbital-tabs-depth="behind"] {
    pointer-events: none;
}

.ds-orbital-tabs__item__step {
    position: absolute;
    left: 50%;
    top: 12.35%;                            /* 34.93 of 253.716, measured from
                                               the inside of the circle's edge,
                                               which is what an offset on an
                                               absolutely placed child is read
                                               against */
    transform: translateX( -50% );

    display: flex;
    align-items: center;
    justify-content: center;

    width: 13.14%;                          /* 32 of the 243.568 inside it */
    aspect-ratio: 1;
    border-radius: 25%;

    background-color: var(--color-overline-bg-6, rgba( 248, 247, 243, 0.16 ));

    font-size: var(--body-300);
    font-weight: var(--ds-global-heading-font-weight-400, 900);
    line-height: 1.1;
    letter-spacing: var(--ds-global-heading-letter-spacing-400, -0.04em);
}

/* Centred in the circle, so a width given to it narrows it from both sides.
   Its text is set the way .ds-button sets a button label. */
.ds-orbital-tabs__item__label {
    display: block;
    width: 100%;
    margin-inline: auto;

    font-family: var(--main-font);
    font-weight: 700;
    line-height: 1em;
    letter-spacing: var(--ds-global-button-text-letter-spacing-400);
    text-align: center;
    text-transform: lowercase;
    text-wrap: balance;
}

/* Font size steps off the heading type scale. */
.ds-orbital-tabs__item__label--100 { font-size: var(--heading-100); }
.ds-orbital-tabs__item__label--150 { font-size: var(--heading-150); }
.ds-orbital-tabs__item__label--200 { font-size: var(--heading-200); }
.ds-orbital-tabs__item__label--250 { font-size: var(--heading-250); }

/* The hub
   -------------------------------------------------- */

/* The icon at the middle of the ring, with a trail of dots running out either
   side of it. It is placed from the same two shares the circles are, so the
   ring turns around the icon's own middle and not around a point near it.
   Each trail is a dot connector element, left at the connector's own sizes. */
.ds-orbital-tabs__hub {
    position: absolute;
    left: var(--ds-orbital-tabs-center-x);
    top: var(--ds-orbital-tabs-center-y);
    transform: translate( -50%, -50% );

    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ds-orbital-tabs-hub-gap);

    width: var(--ds-orbital-tabs-hub);
}

/* The icon and the line about the app under it, in one container so the line
   is centred on the icon. The container is only as big as the icon, so the
   icon stays on the middle of the ring and the line hangs below it. */
.ds-orbital-tabs__center {
    position: relative;

    display: flex;
    justify-content: center;
}

.ds-orbital-tabs__icon {
    position: relative;

    display: flex;
    align-items: center;
    justify-content: center;

    width: var(--ds-orbital-tabs-hub-icon);
    aspect-ratio: 1;
    border-radius: 25%;                     /* 32 of 128 */

    /* the light the icon is lifted off the page with, and the shadow that
       presses it back into it */
    background-image: linear-gradient( 180deg, #eceadf 28.63%, var(--color-6) 100% );
    box-shadow: inset 0 0 0.5rem rgba( 117, 54, 74, 0.16 );
}

/* The window the mark is shown through, 80 of the icon's 128. The logomark is
   drawn at that same 80, so it fills the window exactly. */
.ds-orbital-tabs__icon__frame {
    position: relative;
    overflow: hidden;

    width: calc( var(--ds-orbital-tabs-hub-icon) * 0.625 );
    aspect-ratio: 1;
}

.ds-orbital-tabs__icon__logomark {
    display: block;
    width: 100%;
    height: 100%;
}

/* A picture given through the icon attribute is larger than the window and
   pulled up inside it, which is the crop the design takes off the app's own
   icon. */

.ds-orbital-tabs__icon__image {
    position: absolute;
    left: -11.16%;
    top: -31.62%;
    width: 122.49%;
    height: 162.54%;
    max-width: none;
}

/* The line under the icon that points at the app, centred on the icon and 22
   below it, the gap the design leaves between the two.

   It is a single body text with its link and looks the way body text does
   everywhere, so only where it sits is set here. */
.ds-orbital-tabs__app {
    position: absolute;
    left: 50%;
    top: calc( 100% + var(--el-padding-250) );
    transform: translateX( -50% );

    white-space: nowrap;
}
/* The text
   -------------------------------------------------- */

/* Every tab's text is printed and all five are laid in the same cell, so the
   panel is as tall as the longest of them and the copy beside the ring never
   jumps as the ring turns. */
.ds-orbital-tabs__panels {
    display: grid;
}

.ds-orbital-tabs__panel {
    grid-area: 1 / 1;

    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-350);

    /* the panel of the tab at rest is the one shown. The script fades them as
       the ring passes between two, and slides them up and down with it, the
       way the card deck's captions slide across with the cards, so nothing is
       transitioned here */
    opacity: 0;
    visibility: hidden;
}

.ds-orbital-tabs__panel--active {
    opacity: 1;
    visibility: visible;
}

/* The panel's heading is a heading and the copy under it a body text, so their
   type comes from those elements. The heading is only held to the wrap the
   design sets it on. */
.ds-orbital-tabs__panel__heading {
    max-width: 65.25%;                      /* 261 of 400 */
}

.ds-orbital-tabs__panel__text > p {
    margin: 0 0 1em;
}

.ds-orbital-tabs__panel__text > p:last-child {
    margin-bottom: 0;
}

/* The controls
   -------------------------------------------------- */

/* Nothing here does anything without the script, so the row is kept out of the
   way until the script has said it is running. The element itself still reads
   as the design draws it in the meantime: the tab the shortcode opened on is
   the one on show. */
.ds-orbital-tabs__nav {
    display: none;
    align-items: center;
    gap: var(--el-spacing-400);
}

.ds-orbital-tabs--ready .ds-orbital-tabs__nav {
    display: flex;
}

.ds-orbital-tabs__nav__steps {
    display: flex;
    align-items: center;
    gap: var(--el-spacing-150);
}

/* The three controls are Button basic elements holding only their marks, so
   their fill, edge and hover are the button's own. They are only held to the
   size the design draws them at, the same one the accordion's toggles take.
   Their bottom edge is thicker than the rest of the border, so the top is
   padded by the difference to put the mark in the middle of the whole
   button rather than above it. */
.ds-orbital-tabs .ds-orbital-tabs__pause,
.ds-orbital-tabs .ds-orbital-tabs__nav__button {
    -webkit-appearance: none;
    appearance: none;

    width: var(--ds-el-size-800);
    height: var(--ds-el-size-700);
    padding: 0;
    padding-block-start: calc( var(--ds-local-border-weight-bottom) - var(--ds-local-border-weight-default) );
}

/* On the first tab there is no going back and on the last no going on, so the
   button that would is disabled. It fades back rather than leaving the row, the
   same as the card deck's, and the cursor says it cannot be pressed. */
.ds-orbital-tabs .ds-orbital-tabs__nav__button:disabled {
    opacity: 0.32;
    cursor: not-allowed;
}

.ds-orbital-tabs .ds-orbital-tabs__nav__button:disabled:hover {
    filter: none;
}

.ds-orbital-tabs__pause:focus-visible,
.ds-orbital-tabs__nav__button:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

/* Both marks are printed and the button shows whichever one it is offering, so
   the swap costs nothing at the moment it is pressed. They are as tall as
   the chevrons beside them stand once turned, which is the chevron's width. */
.ds-orbital-tabs .ds-orbital-tabs__pause__glyph {
    width: auto;
    height: var(--ds-icon-size-300);
}

.ds-orbital-tabs__pause__glyph--play,
.ds-orbital-tabs--paused .ds-orbital-tabs__pause__glyph--pause {
    display: none;
}

.ds-orbital-tabs--paused .ds-orbital-tabs__pause__glyph--play {
    display: block;
}

/* The chevron is drawn once pointing down, the same one the other elements
   carry, and turned a quarter round either way here. */
.ds-orbital-tabs .ds-orbital-tabs__nav__glyph {
    width: var(--ds-icon-size-300);
    height: auto;
}

.ds-orbital-tabs__nav__button--prev .ds-orbital-tabs__nav__glyph {
    transform: rotate( 90deg );
}

.ds-orbital-tabs__nav__button--next .ds-orbital-tabs__nav__glyph {
    transform: rotate( -90deg );
}

/* What an element written with the wrong number of tabs shows whoever can put
   it right. A reader is shown nothing at all. */
.ds-orbital-tabs__error {
    padding: var(--el-padding-300) var(--el-padding-350);
    border: 1px solid var(--color-1);
    border-radius: var(--el-border-radius-200);

    background-color: var(--color-btn-secondary-bg-1, rgba( 117, 54, 74, 0.08 ));
    color: var(--color-1);
    font-family: var(--main-font);
    font-size: var(--body-250);
}

/* --------------------------------------------------
   Orbital tabs, tablet and phone

   Nothing below reaches the desktop layout: every rule sits in a query that
   ends just short of 1390px, where the site's fluid sizes reach their desktop
   values.

   Below that, the circles are sized off the label rather than off the stage,
   so a circle keeps the proportions it has on desktop at every width, just
   larger or smaller: it is as many labels across, and its edge, its clock and
   its number are the same share of it. The numbers are the desktop circle as
   it is drawn at 1390px, 267.6 across for a 24px label, so every size here
   meets the desktop's there.
   -------------------------------------------------- */

@media ( max-width: 1389.98px ) {
    .ds-orbital-tabs {
        --ds-orbital-tabs-item: calc( var(--heading-150) * 11.1499 );   /* 267.6 / 24 */
        --ds-orbital-tabs-rule: calc( var(--heading-150) * 0.2083 );     /* 5 / 24 */
        --ds-orbital-tabs-rule-bottom: calc( var(--heading-150) * 0.2817 );   /* 6.76 / 24 */
        --ds-orbital-tabs-progress-width: calc( var(--heading-150) * 0.2083 );  /* 5 / 24 */

        /* the icon: 128px on desktop and 72px on a tablet, the same as
           --ds-icon-size-900, and the 96px the phone layout draws it at */
        --ds-orbital-tabs-hub-icon: calc(clamp(72px, 118.9px - 6.107vw, 96px) + clamp(72px, 2.86px + 9.003vw, 128px) - 72px); /* 96px / 72px / 128px */
    }

    /* the number on a circle, 18px for the desktop's 24px label */
    .ds-orbital-tabs__item__step {
        font-size: calc( var(--heading-150) * 0.75 );
    }

    /* the shadow the icon is pressed into the page with, 8px on the desktop's
       128px icon */
    .ds-orbital-tabs__icon {
        box-shadow: inset 0 0 calc( var(--ds-orbital-tabs-hub-icon) * 0.0625 ) rgba( 117, 54, 74, 0.16 );
    }
}

/* Tablet: the desktop layout, scaled down.

   The ring is laid out from its circles: its middle stands one ring's reach,
   2.2889 circles, in from the stage's right edge, less the margin the desktop
   leaves there, and the same reach down from the top, so the circle at three
   o'clock and a circle passing over the top of the ring keep to the stage
   exactly as they do on desktop. The stage is as tall as the ring reaches
   below that, and the text column is carried down it with the ring.

   The circles take a larger share of a tablet's width than of the desktop's,
   because the label they are sized off shrinks more slowly than the screen, so
   what is left between them is taken in: the text column narrows, and the
   trails of dots beside the icon move in towards it. */
@media ( max-width: 1389.98px ) {
    .ds-orbital-tabs {
        --ds-orbital-tabs-edge: clamp(9.2px, 0.69px + 1.108vw, 16.09px);   /* 9.2px / 16.09px */
        --ds-orbital-tabs-center-x: calc( 100% - var(--ds-orbital-tabs-item) * 2.2889 - var(--ds-orbital-tabs-edge) );
        --ds-orbital-tabs-center-y: calc( var(--ds-orbital-tabs-item) * 2.2894 );

        /* how far above the ring's middle the text column starts, and how wide
           it is */
        --ds-orbital-tabs-main-rise: clamp(133px, 92.76px + 5.24vw, 165.59px);   /* 133px / 165.59px */
        --ds-orbital-tabs-main-top: calc( var(--ds-orbital-tabs-center-y) - var(--ds-orbital-tabs-main-rise) );
        --ds-orbital-tabs-main-width: clamp(225px, 8.92px + 28.135vw, 400px);   /* 225px / 400px */

        /* the room the stage keeps below the ring */
        --ds-orbital-tabs-stage-foot: clamp(24px, -0.09px + 3.137vw, 43.51px);   /* 24px / 43.51px */

        /* the gap between a trail of dots and the icon */
        --ds-orbital-tabs-hub-gap: clamp(22px, -55.02px + 10.029vw, 84.38px);   /* 22px / 84.38px */
    }

    .ds-orbital-tabs__stage {
        aspect-ratio: auto;
        height: calc( var(--ds-orbital-tabs-center-y) + var(--ds-orbital-tabs-item) * 2.2889 + var(--ds-orbital-tabs-stage-foot) );
    }

    .ds-orbital-tabs__main {
        width: var(--ds-orbital-tabs-main-width);
    }

    /* The hub is as wide as the icon and its two trails, laid out in lengths
       rather than in shares of a width.

       It stands halfway between the text column and the circle at rest, as it
       does on desktop. The ring cannot move right with it, since its circle at
       three o'clock already meets the stage's edge, so the hub moves on its own
       and the ring turns around a point a little left of the icon. That
       circle's near edge is the ring's middle plus its radius less half a
       circle, 1.2889 circles. */
    .ds-orbital-tabs__hub {
        left: calc( ( var(--ds-orbital-tabs-main-width) + var(--ds-orbital-tabs-center-x) + var(--ds-orbital-tabs-item) * 1.2889 ) / 2 );
        width: auto;
    }
}

/* Phone: the ring rests its tab at the top, and everything is stacked under it
   and centred, as the phone design draws it: the ring, three dots, the icon and
   the line about the app, three dots, the text and the controls.

   The ring is turned a quarter back, so the tab at rest stands at twelve
   o'clock rather than at three, and it is the same ring turning the same way:
   the script reads the turn off --ds-orbital-tabs-turn. The circles to either
   side come in from the edges of the screen, lower down and faded, and every
   circle past them is out of sight. */
@media ( max-width: 767.98px ) {
    .ds-orbital-tabs {
        --ds-orbital-tabs-turn: -90deg;

        /* the stage is laid out in the flow here and cuts nothing off at the
           top, so it keeps no room above the ring */
        --ds-orbital-tabs-stage-top: 0px;

        /* the phone design sets the circles a little closer together than the
           desktop does, so the two beside the one at rest reach in from the
           screen's edges by as much as it shows */
        --ds-orbital-tabs-orbit: 175%;

        --ds-orbital-tabs-app-gap: calc(clamp(10px, 21.73px - 1.527vw, 16px) + clamp(10px, 5.06px + 0.643vw, 14px) - 10px); /* 16px / 10px / 14px */
        --ds-orbital-tabs-app-text: calc(clamp(0.5625rem, 0.685rem - 0.254vw, 0.625rem) + clamp(0.5625rem, 0.177rem + 0.804vw, 0.875rem) - 0.5625rem); /* 10px / 9px / 14px */
        --ds-orbital-tabs-panel-gap: calc(clamp(16px, 31.63px - 2.036vw, 24px) + clamp(16px, 6.12px + 1.286vw, 24px) - 16px); /* 24px / 16px / 24px */
        --ds-orbital-tabs-text: calc(clamp(0.875rem, 1.608rem - 1.527vw, 1.25rem) + clamp(0.875rem, 0.258rem + 1.286vw, 1.375rem) - 0.875rem); /* 20px / 14px / 22px */
        --ds-orbital-tabs-main-gap: calc(clamp(38px, 57.54px - 2.545vw, 48px) + clamp(38px, 5.9px + 4.18vw, 64px) - 38px); /* 48px / 38px / 64px */
        --ds-orbital-tabs-nav-gap: calc(20px + clamp(20px, 5.18px + 1.929vw, 32px) - 20px); /* 20px / 20px / 32px */
        --ds-orbital-tabs-button-width: calc(clamp(38px, 57.54px - 2.545vw, 48px) + clamp(38px, 5.9px + 4.18vw, 64px) - 38px); /* 48px / 38px / 64px */
        --ds-orbital-tabs-button-height: calc(clamp(30px, 41.73px - 1.527vw, 36px) + clamp(30px, 7.77px + 2.894vw, 48px) - 30px); /* 36px / 30px / 48px */
    }

    .ds-orbital-tabs__stage {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: var(--el-spacing-400);

        height: auto;
        overflow: visible;

        /* nothing is placed by the stage's width here, and as a container it
           could not be sized by what it holds, which is now in the flow */
        container-type: normal;
    }

    .ds-orbital-tabs__orbit,
    .ds-orbital-tabs__main {
        position: static;
        width: 100%;
    }

    .ds-orbital-tabs__orbit {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: var(--el-spacing-400);
    }

    /* The row the ring is seen through: a circle tall, and as wide as the
       screen, so the circles either side of the one at rest are cut off at the
       screen's edges rather than the element's. It cuts them off across only,
       so they can hang down past it beside the icon. */
    .ds-orbital-tabs__ring {
        position: relative;
        flex: 0 0 auto;

        width: 100vw;
        height: var(--ds-orbital-tabs-item);

        overflow-x: clip;
    }

    /* Every circle is placed from the middle of the ring, which lies one
       radius below the middle of the circle at rest: half a circle down to
       that and 175% of one further, 2.25 circles from the top of the row.

       How faded a circle is follows how far from rest it stands, which the
       script writes on it as it turns: fully in view at rest, the 0.32 the
       design gives the circles either side one tab out, and gone by two. */
    .ds-orbital-tabs .ds-orbital-tabs__item {
        left: 50%;
        top: calc( var(--ds-orbital-tabs-item) * 2.25 );

        opacity: clamp( 0, max( 1 - 0.68 * var(--ds-orbital-tabs-away, 0), 0.32 * ( 2 - var(--ds-orbital-tabs-away, 0) ) ), 1 );
        transition: none;
    }

    /* until the script is running, only the circle at rest is shown */
    .ds-orbital-tabs:not(.ds-orbital-tabs--ready) .ds-orbital-tabs__item:not(.ds-orbital-tabs__item--active) {
        opacity: 0;
    }

    .ds-orbital-tabs__overlay {
        display: none;
    }

    /* The icon and the line about the app, with three dots above and three
       below: the hub is stood on end, and each trail with it through the
       trail's own mobile options. */
    .ds-orbital-tabs__hub {
        position: static;
        transform: none;

        flex-direction: column;
        gap: var(--el-spacing-400);
    }

    .ds-orbital-tabs__center {
        flex-direction: column;
        align-items: center;
        gap: var(--ds-orbital-tabs-app-gap);
    }

    .ds-orbital-tabs__app {
        position: static;
        transform: none;
    }

    .ds-orbital-tabs .ds-orbital-tabs__app__text {
        font-size: var(--ds-orbital-tabs-app-text);
    }

    /* The text and the controls, centred. The heading keeps the share of the
       width it has on desktop, and the copy the width it is given in ch. */
    .ds-orbital-tabs__main {
        align-items: center;
        gap: var(--ds-orbital-tabs-main-gap);
    }

    .ds-orbital-tabs__panels {
        width: 100%;
    }

    .ds-orbital-tabs__panel {
        gap: var(--ds-orbital-tabs-panel-gap);

        text-align: center;
    }

    .ds-orbital-tabs .ds-orbital-tabs__panel .ds-orbital-tabs__panel__heading {
        margin-inline: auto;
    }

    .ds-orbital-tabs .ds-orbital-tabs__panel .ds-orbital-tabs__panel__text {
        margin-inline: auto;
        text-align: center;
    }

    /* the copy at its default size is set larger on a phone than the body
       text scale has it */
    .ds-orbital-tabs .ds-orbital-tabs__panel .ds-orbital-tabs__panel__text.ds-body-text--400 {
        font-size: var(--ds-orbital-tabs-text);
    }

    .ds-orbital-tabs__nav {
        justify-content: center;
        gap: var(--ds-orbital-tabs-nav-gap);
    }

    .ds-orbital-tabs .ds-orbital-tabs__pause,
    .ds-orbital-tabs .ds-orbital-tabs__nav__button {
        width: var(--ds-orbital-tabs-button-width);
        height: var(--ds-orbital-tabs-button-height);
    }
}

/* Nothing turns on its own: the script takes the ring the shortest way to the
   tab being asked for, with none of the lean, the lift or the rise under the
   mouse, the panels fade without sliding, and nothing else fades at all. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-orbital-tabs__item,
    .ds-orbital-tabs__item__progress {
        transition: none;
    }
}

/* --------------------------------------------------
   Pricing table element
   -------------------------------------------------- */

.ds-pricing-table {
    --ds-pricing-table-gap: var(--el-spacing-400);
    --ds-pricing-table-radius: var(--el-border-radius-300);

    /* how far in from the edge of a row its feature title is set. The two
       answer columns are centered, so this only ever shapes the first one. */
    --ds-pricing-table-inset: var(--el-padding-750);

    --ds-pricing-table-row-block: var(--el-padding-500);
    --ds-pricing-table-head-block: var(--el-padding-400);

    /* Every other size the table sets itself. They are gathered here so the
       small table below can swap each for the step under it in one place. The
       text sizes are not among them: those are the basic elements' own steps,
       picked in the shortcode. */
    --ds-pricing-table-head-inline: var(--el-padding-500);
    --ds-pricing-table-head-offset: var(--el-padding-300);
    --ds-pricing-table-answer-inline: var(--el-padding-300);
    --ds-pricing-table-disc-size: var(--ds-icon-size-500);
    --ds-pricing-table-cross-size: var(--ds-icon-size-350);
    --ds-pricing-table-toggle-offset: var(--el-spacing-500);

    --ds-pricing-table-accordion-gap: 1rem;
    --ds-pricing-table-section-gap: var(--el-spacing-250);
    --ds-pricing-table-section-padding: var(--el-padding-500);
    --ds-pricing-table-section-glyph-size: var(--ds-icon-size-320);
    --ds-pricing-table-list-offset: var(--el-padding-200);
    --ds-pricing-table-list-item-gap: var(--el-spacing-500);
    --ds-pricing-table-list-item-padding: var(--el-padding-500);

    /* every other row is tinted, which is what carries the eye across a row
       that is mostly white space between a title and two marks */
    --ds-pricing-table-zebra: var(--color-pricing-row-bg-1);

    /* the head is held at the top while the rows pass under it. Its ground is
       the theme's ds-sc-bg-6. The table's script sets this on the table to the
       height of the site's header, so the head is held just under it; 0 is
       only what it starts at before the script has measured. */
    --ds-pricing-table-head-top: 0px;

    --ds-pricing-table-move-duration: 320ms;
    --ds-pricing-table-move-easing: cubic-bezier( 0.33, 1, 0.68, 1 );

    /* How far a collapsed table lets its rows run before it fades them out,
       which is about four of them. The design clips the table at 480px with
       its head inside that, and the head is not part of what is clipped here,
       so this is that 480 less the 86 the head takes. */
    --ds-pricing-table-collapsed-height: 24.625rem;

    /* longer than the accordion's, there is a great deal more to move */
    --ds-pricing-table-open-duration: 520ms;

    /* The table is its own layer, set at the level of the page. The sticky
       head and its cells are stacked inside it, so however they are raised
       over the rows they never rise over the site's sticky header, which is
       laid over the page and so passes over the table's head too. */
    position: relative;
    z-index: 0;

    display: block;

    font-family: var(--main-font);
}

/* --------------------------------------------------
   The table, as it is read on a desktop
   -------------------------------------------------- */

/* Every row is laid on the same three tracks, the head included, so the
   columns hold their line down the table however far a feature title runs or a
   plan name wraps. The feature takes half the width and the two plans a
   quarter each, which is the split the design is drawn on. */
.ds-pricing-table__row {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    gap: var(--ds-pricing-table-gap);
    align-items: center;
}

/* The three cells that head the table are matched to the tallest of them, so a
   plan name that wraps to two lines leaves the row level rather than leaving
   the other two cells short. */
.ds-pricing-table__row--head {
    align-items: stretch;

    padding-block-end: var(--ds-pricing-table-head-offset);
}

.ds-pricing-table__body .ds-pricing-table__row:nth-child(even) {
    border-radius: var(--ds-pricing-table-radius);

    background-color: var(--ds-pricing-table-zebra);
}

/* Set on the head's row group, not on its row: a sticky element only travels
   inside its parent, and the group's parent is the whole table while the row's
   is the group, which is no taller than the row. */
.ds-pricing-table__head--sticky {
    position: sticky;
    top: var(--ds-pricing-table-head-top);
    z-index: 1;
}

/* --------------------------------------------------
   A table that folds
   -------------------------------------------------- */

/* The rows are what is held back, not the whole table: the head is held at
   the top of the page while they pass under it, and a sticky element only
   travels inside its parent, so it stays outside of anything that clips.

   Everything below is gated on the ready class the script adds, so the table
   the shortcode prints folded is only foldable once there is something to
   unfold it with. */
.ds-pricing-table--ready.ds-pricing-table--collapsible .ds-pricing-table__body {
    overflow: hidden;

    transition: max-height var(--ds-pricing-table-open-duration) var(--ds-pricing-table-move-easing);
}

/* The rows fade out towards the bottom rather than stopping at one, so the
   table reads as carrying on past where it is cut. It is a mask, the way the
   conditions showcase fades out at its sides, rather than the design's cream
   overlay, so it fades into whatever the table is laid on.

   The design's fade is already slightly on at the top of the table; it starts
   here at nothing instead, so the first rows are as solid as they are once the
   table is open and opening it does not lift a haze off them. */
.ds-pricing-table--ready.ds-pricing-table--collapsed .ds-pricing-table__body {
    max-height: var(--ds-pricing-table-collapsed-height);

    -webkit-mask-image: linear-gradient(
        to bottom,
        #000 0,
        rgba( 0, 0, 0, 0.68 ) 60.5%,
        transparent 100%
    );
    mask-image: linear-gradient(
        to bottom,
        #000 0,
        rgba( 0, 0, 0, 0.68 ) 60.5%,
        transparent 100%
    );
}

/* The button under it, which the table only has when it was asked to fold.
   It is hidden until the script is ready for the same reason the fold is. */
.ds-pricing-table__toggle-wrap {
    display: none;
    justify-content: center;

    padding-block-start: var(--ds-pricing-table-toggle-offset);
}

.ds-pricing-table--ready .ds-pricing-table__toggle-wrap {
    display: flex;
}

/* A table whose rows fit inside the collapsed height anyway is left open and
   its button taken away, so there is never one that opens nothing. The script
   adds this after measuring. */
.ds-pricing-table--fits .ds-pricing-table__toggle-wrap {
    display: none;
}

/* The button carries both of its labels and only ever shows the one that says
   what pressing it will do next. */
.ds-pricing-table__toggle__label--expand {
    display: none;
}

.ds-pricing-table--collapsed .ds-pricing-table__toggle__label--expand {
    display: inline;
}

.ds-pricing-table--collapsed .ds-pricing-table__toggle__label--collapse {
    display: none;
}

/* --------------------------------------------------
   The three cells that head it
   -------------------------------------------------- */

.ds-pricing-table__head-cell {
    position: relative;
    z-index: 0;

    isolation: isolate;

    display: flex;
    align-items: center;
    justify-content: center;

    padding: var(--ds-pricing-table-head-block) var(--ds-pricing-table-head-inline);
    border-radius: var(--ds-pricing-table-radius);

    /* the background is the theme's ds-sc-bg-N, picked by the column's color
       id, so no background is set here to paint over it */
    color: var(--ds-pricing-table-head-cell-text, var(--color-6));

    text-align: center;
}

/* The first one names the column rather than a plan, so it is set with its
   text where the titles under it begin rather than in the middle. */
.ds-pricing-table__head-cell--features {
    justify-content: flex-start;

    padding-inline: var(--ds-pricing-table-inset);

    text-align: start;
}

/* --------------------------------------------------
   The rows under them
   -------------------------------------------------- */

.ds-pricing-table__cell--feature {
    padding: var(--ds-pricing-table-row-block) var(--ds-pricing-table-inset);
}

.ds-pricing-table__cell--answer {
    display: flex;
    align-items: center;
    justify-content: center;

    padding: var(--el-padding-150) var(--ds-pricing-table-answer-inline);
}

/* --------------------------------------------------
   The two marks

   A feature a plan has is a tick on a disc drawn in that plan's color, and one
   it does not have is a cross on nothing. The weight is the point: an answer
   of yes should be the thing the eye finds while a row is being scanned, and
   an answer of no should not compete with it.
   -------------------------------------------------- */

.ds-pricing-table__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    flex-shrink: 0;
}

.ds-pricing-table__mark__disc {
    position: relative;
    z-index: 0;

    isolation: isolate;

    display: flex;
    align-items: center;
    justify-content: center;

    width: var(--ds-pricing-table-disc-size);
    height: var(--ds-pricing-table-disc-size);

    /* The background is the theme's ds-bg-gd-N, picked by the plan's color id.
       It paints its border gradient under the border and makes the border's
       color transparent, so only the border's style and weight are given here.
       The underside is drawn heavier than the rest, which is what gives the
       disc the little bit of depth it is drawn with. */
    border-style: solid;
    border-width: 1.33px;
    border-bottom-width: 2.67px;
    border-radius: 999px;

    color: var(--color-6);
}

.ds-pricing-table__mark--included .ds-pricing-table__mark__glyph {
    width: var(--ds-icon-size-300);
    height: calc( var(--ds-icon-size-300) * 0.75 );

    margin-top: 0.1em;
}

/* The cross is drawn in the plan's own color rather than in the dark the row
   is written in, so it still belongs to its column while carrying none of the
   weight the disc beside it does. */
.ds-pricing-table__mark--excluded {
    color: var(--ds-pricing-table-mark-color);
}

.ds-pricing-table__mark--excluded .ds-pricing-table__mark__glyph {
    width: var(--ds-pricing-table-cross-size);
    height: var(--ds-pricing-table-cross-size);
}

/* --------------------------------------------------
   The color ids a column may take, 1 through 5

   Six is the cream the page is laid on, so it is left out: a cream column
   would be written on in cream. The discs take their backgrounds from the
   theme's ds-bg-gd-N, so all that is set here is the color the cross is drawn
   in.
   -------------------------------------------------- */

/* The head cells take their backgrounds from the theme's ds-sc-bg-N. Five is
   the light pink, so the cell is written on in the dark it is taken from
   rather than in cream. */
.ds-pricing-table__head-cell--color-5 {
    --ds-pricing-table-head-cell-text: var(--color-1);
}

.ds-pricing-table__mark--color-1 {
    --ds-pricing-table-mark-color: var(--color-1);
}

.ds-pricing-table__mark--color-2 {
    --ds-pricing-table-mark-color: var(--color-2);
}

.ds-pricing-table__mark--color-3 {
    --ds-pricing-table-mark-color: var(--color-3);
}

.ds-pricing-table__mark--color-4 {
    --ds-pricing-table-mark-color: var(--color-4);
}

/* Five is light enough that a cream tick would be lost on it, so the disc is
   ticked in the dark instead. */
.ds-pricing-table__mark--color-5 {
    --ds-pricing-table-mark-color: var(--color-5);
}

.ds-pricing-table__mark--color-5 .ds-pricing-table__mark__disc {
    color: var(--color-1);
}

/* And the same ids on a phone, where a plan's button is the block its section
   is headed by. The fill itself is the theme's ds-sc-bg class on the button,
   the way the column heads are filled on a desktop, so the button is laid on
   the same grained colour rather than on a flat one. Only the label is set
   here, and only where the plan's colour is too light to read cream on. */
.ds-pricing-table__section--color-5 {
    --ds-pricing-table-section-text: var(--color-1);
}

/* --------------------------------------------------
   The accordion, which is how the same rows are read on a phone

   The table is not narrowed, it is put away: below the breakpoint each plan
   becomes a section of its own listing every feature with that plan's answer
   beside it, so a comparison is made by opening one plan and then the other
   rather than by dragging a table sideways.
   -------------------------------------------------- */

.ds-pricing-table__accordion {
    display: none;
}

.ds-pricing-table .ds-pricing-table__section__heading {
    margin: 0;
}

.ds-pricing-table__section__toggle {
    position: relative;
    z-index: 0;

    isolation: isolate;

    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-pricing-table-section-gap);

    width: 100%;
    margin: 0;
    padding: var(--ds-pricing-table-section-padding);
    border: 0;
    border-radius: var(--ds-pricing-table-radius);

    color: var(--ds-pricing-table-section-text, var(--color-6));

    font-family: inherit;
    text-align: start;

    cursor: pointer;
}

.ds-pricing-table__section__toggle:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 4px;
}

/* The mark on a section's button. It is drawn pointing down and turned over
   once the section is open, so the two states are one shape rather than two. */
.ds-pricing-table__section__icon {
    display: flex;
    align-items: center;
    justify-content: center;

    flex-shrink: 0;

    transition: transform var(--ds-pricing-table-move-duration) var(--ds-pricing-table-move-easing);
}

.ds-pricing-table__section--open .ds-pricing-table__section__icon {
    transform: rotate( 180deg );
}

.ds-pricing-table__section__glyph {
    width: var(--ds-pricing-table-section-glyph-size);
    height: auto;
}

/* The body is printed open and is only foldable once the script has said so,
   which is what leaves a page whose script never arrives with two plain lists
   rather than two headings and nothing under them. It is opened by letting its
   row grow from nothing to what the list needs rather than by animating a
   height nothing knows in advance, and the visibility is held until the row
   has finished closing so the list does not vanish before it has folded away. */
.ds-pricing-table--ready .ds-pricing-table__section__body {
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;

    transition:
        grid-template-rows var(--ds-pricing-table-move-duration) var(--ds-pricing-table-move-easing),
        opacity var(--ds-pricing-table-move-duration) var(--ds-pricing-table-move-easing),
        visibility 0s linear var(--ds-pricing-table-move-duration);

    opacity: 0;
}

.ds-pricing-table--ready .ds-pricing-table__section--open .ds-pricing-table__section__body {
    grid-template-rows: 1fr;
    visibility: visible;
    opacity: 1;

    transition:
        grid-template-rows var(--ds-pricing-table-move-duration) var(--ds-pricing-table-move-easing),
        opacity var(--ds-pricing-table-move-duration) var(--ds-pricing-table-move-easing),
        visibility 0s linear;
}

.ds-pricing-table__section__body__inner {
    /* both are needed for the row to be able to shrink to nothing */
    min-height: 0;
    overflow: hidden;
}

.ds-pricing-table .ds-pricing-table__list {
    margin: 0;
    padding: var(--ds-pricing-table-list-offset) 0 0;

    list-style: none;
}

.ds-pricing-table__list__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-pricing-table-list-item-gap);

    margin: 0;
    padding: var(--ds-pricing-table-list-item-padding);
    border-radius: var(--ds-pricing-table-radius);
}

.ds-pricing-table__list__item:nth-child(even) {
    background-color: var(--ds-pricing-table-zebra);
}

/* A feature the plan does not have is still listed, so the list is the whole
   comparison rather than only the half of it that flatters the plan. It is
   held back rather than left out, which is what lets the ones it does have be
   read straight down. */
.ds-pricing-table__list__item--excluded .ds-pricing-table__feature {
    opacity: 0.56;
}

/* --------------------------------------------------
   The widths in between

   The table holds its three columns down to the tablet, where the insets come
   in rather than the columns being allowed to run out of room.
   -------------------------------------------------- */

@media ( max-width: 1024px ) {
    .ds-pricing-table {
        --ds-pricing-table-gap: 1rem;
        --ds-pricing-table-inset: var(--el-padding-450);
        --ds-pricing-table-row-block: var(--el-padding-400);
        --ds-pricing-table-head-block: var(--el-padding-350);

        /* the rows are shorter here, so a folded table is held shorter too
           and still lets about four of them through */
        --ds-pricing-table-collapsed-height: 19.5rem;
    }
}

/* The small table. Every size is the step under the one above it, picked so
   the whole table comes down by about the same amount, 0.85 of the default, on
   a phone, a tablet and desktop alike. The kit has no radius between 200 and
   300, so the radius is a fluid size of the table's own at 0.85 of the default
   one, and the fixed sizes are taken down by the same 0.85. The collapsed
   height is too, so a folded table still lets about four of its shorter rows
   through. The tick on a disc keeps its size: it is already on the smallest
   step its scale has.

   The size is picked for desktop and tablet and for a phone on their own. The
   table is only read on desktop and tablet and the accordion only on a phone,
   so the desktop size is set on the table and the button under it, and the
   mobile one on the accordion, and neither needs a media query to keep to its
   own widths. The corners and the marks are drawn in both views, so those are
   set on the view itself rather than on the element around both.

   The desktop set comes after the tablet rule above so it outranks it, and
   its own tablet rule comes after it for the same reason. */
.ds-pricing-table--size-desktop-small {
    --ds-pricing-table-gap: var(--el-spacing-350);

    --ds-pricing-table-inset: var(--el-padding-700);

    --ds-pricing-table-row-block: var(--el-padding-450);
    --ds-pricing-table-head-block: var(--el-padding-350);

    --ds-pricing-table-head-inline: var(--el-padding-450);
    --ds-pricing-table-head-offset: var(--el-padding-250);
    --ds-pricing-table-answer-inline: var(--el-padding-250);
    --ds-pricing-table-toggle-offset: var(--el-spacing-450);

    /* 0.85 of 24.625rem */
    --ds-pricing-table-collapsed-height: 20.9375rem;
}

@media ( max-width: 1024px ) {
    .ds-pricing-table--size-desktop-small {
        --ds-pricing-table-gap: 0.875rem;
        --ds-pricing-table-inset: var(--el-padding-400);
        --ds-pricing-table-row-block: var(--el-padding-350);
        --ds-pricing-table-head-block: var(--el-padding-300);

        /* 0.85 of 19.5rem */
        --ds-pricing-table-collapsed-height: 16.5625rem;
    }
}

.ds-pricing-table--size-desktop-small .ds-pricing-table__table,
.ds-pricing-table--size-mobile-small .ds-pricing-table__accordion {
    --ds-pricing-table-radius: calc(clamp(7px, 10.91px - 0.509vw, 9px) + clamp(7px, 3.3px + 0.482vw, 10px) - 7px); /* 9px / 7px / 10px */

    --ds-pricing-table-disc-size: var(--ds-icon-size-460);
    --ds-pricing-table-cross-size: var(--ds-icon-size-300);
}

.ds-pricing-table--size-mobile-small .ds-pricing-table__accordion {
    --ds-pricing-table-accordion-gap: 0.875rem;
    --ds-pricing-table-section-gap: var(--el-spacing-200);
    --ds-pricing-table-section-padding: var(--el-padding-450);
    --ds-pricing-table-section-glyph-size: var(--ds-icon-size-300);
    --ds-pricing-table-list-offset: var(--el-padding-150);
    --ds-pricing-table-list-item-gap: var(--el-spacing-450);
    --ds-pricing-table-list-item-padding: var(--el-padding-450);
}

@media ( max-width: 767px ) {
    .ds-pricing-table__table {
        display: none;
    }

    .ds-pricing-table__accordion {
        display: flex;
        flex-direction: column;
        gap: var(--ds-pricing-table-accordion-gap);
    }

    /* The collapsed option is for the table only. The accordion here is read
       one plan at a time and holds nothing back to begin with, so there is
       nothing for a button to open. The table itself needs no undoing, it is
       not on the page at this width at all. */
    .ds-pricing-table .ds-pricing-table__toggle-wrap {
        display: none;
    }
}

/* The sections open and close, they do not unfold, the table opens out and
   folds back in the same way, and the mark on a button is simply the way round
   its section is. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-pricing-table__section__icon,
    .ds-pricing-table--ready .ds-pricing-table__section__body,
    .ds-pricing-table--ready .ds-pricing-table__section--open .ds-pricing-table__section__body,
    .ds-pricing-table--ready.ds-pricing-table--collapsible .ds-pricing-table__body {
        transition: none;
    }
}

/* --------------------------------------------------
   Form field element
   -------------------------------------------------- */

/* An input cannot hold a pseudo element, so the border and the fill are drawn
   by the frame around it and the input inside is left bare. */
.ds-form-field {
    position: relative;
    isolation: isolate;

    display: block;

    /* The site's light secondary fill and border, the ones its secondary
       buttons are drawn with. */
    border: 3px solid var(--color-btn-secondary-border-1, rgba( 117, 54, 74, 0.24 ));
    border-radius: 999px;

    background: var(--color-btn-secondary-bg-1, rgba( 117, 54, 74, 0.08 ));

    font-family: var(--main-font);
}

.ds-form-field:focus-within {
    outline: 3px solid var(--color-2);
    outline-offset: 3px;
}

/* Selected through .ds-form-field so the reset outranks the input styles the
   theme and Elementor set. */
.ds-form-field .ds-form-field__input {
    -webkit-appearance: none;
    appearance: none;

    display: block;
    width: 100%;

    /* The design trims the text to its cap height and pads it 26px either
       side, the 3px border drawn inside that. 1cap measures the cap height off
       the font itself, and the fixed height before it is the fallback. */
    height: calc( var(--ds-el-size-680) + 0.875rem );
    height: calc( 1cap + var(--ds-el-size-680) );

    margin: 0;
    padding: 0 var(--el-padding-500);
    border: 0;
    border-radius: inherit;

    background: transparent;
    box-shadow: none;
    color: var(--color-1);

    font-family: inherit;
    font-weight: 600;
    line-height: normal;
    letter-spacing: var(--ds-global-body-text-letter-spacing-400, -0.04em);
}

.ds-form-field .ds-form-field__input:focus {
    outline: none;
}

/* The placeholder is the color of what is typed over it, dimmed a little so
   it reads as a hint rather than a value. */
.ds-form-field__input::placeholder {
    color: var(--color-1);
    opacity: 0.6;
}

/* Autofill paints its own fill over the field, so the fill is held off for as
   long as anyone will be looking at it. */
.ds-form-field__input:-webkit-autofill,
.ds-form-field__input:-webkit-autofill:hover,
.ds-form-field__input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--color-1);
    transition: background-color 600000s 0s, color 600000s 0s;
}

/* Font size steps off the body type scale. */
.ds-form-field__input--300 {
    font-size: var(--form-input-text-300);
}

.ds-form-field__input--350 {
    font-size: var(--form-input-text-350);
}

.ds-form-field__input--400 {
    font-size: var(--form-input-text-400);
}

@media ( max-width: 767px ) {
    .ds-form-field .ds-form-field__input {
        padding-inline: var(--el-padding-450);
    }
}

/* --------------------------------------------------
   Signup form element
   -------------------------------------------------- */

/* The email field is a form field, the button a button and the message under
   them a body text, so this lays them out and draws the button's loading and
   done states, and nothing of what they look like on their own. */
.ds-signup-form {
    /* The widest the form gets, fluid like the sizes at the top: 352px, 22rem,
       on a tablet and 540px, the design's, on a phone and on desktop. A
       phone's column is narrower than that anyway. It fills a narrower column
       rather than overflowing it. */
    --ds-signup-form-width: calc(clamp(352px, 719.39px - 47.837vw, 540px) + clamp(352px, 119.87px + 30.225vw, 540px) - 352px); /* 540px / 352px / 540px */
    --ds-signup-form-gap: var(--el-spacing-250);

    /* 360 over 16. With the gap and the 10rem button it comes to 536px, inside
       the form's 540 on desktop. In the narrower form on a tablet the field
       gives way. */
    --ds-signup-form-field-width: 22.5rem;

    /* the part of the loader's ring that does not travel */
    --ds-signup-form-loader-track: rgba( 248, 247, 243, 0.32 );

    --ds-signup-form-state-duration: 200ms;
    --ds-signup-form-state-easing: cubic-bezier( 0.33, 1, 0.68, 1 );

    width: 100%;
    max-width: var(--ds-signup-form-width);

    font-family: var(--main-font);
}

@supports ( background: color-mix( in srgb, red 8%, transparent ) ) {
    .ds-signup-form {
        --ds-signup-form-loader-track: color-mix( in srgb, var(--color-6) 32%, transparent );
    }
}

.ds-signup-form__row {
    display: flex;
    align-items: center;
    gap: var(--ds-signup-form-gap);
}

/* The field is a set width rather than whatever room the button leaves it,
   which in a container that shrinks to its content is only as wide as the
   browser's default input. It still gives way in a column too narrow for it. */
.ds-signup-form__field {
    flex: 0 1 auto;
    width: var(--ds-signup-form-field-width);
    min-width: 0;
}

/* The field is as tall as the button. The button at size 400 is 5rem: its
   1.25rem label, its 1.75rem and 1.625rem of padding and its 0.125rem and
   0.25rem borders. The field's frame draws 3px above and below the input, so
   the input is that much shorter. Written from the button's own padding and
   label size, so the two stay level at every width. */
.ds-signup-form .ds-signup-form__input {
    height: calc( 2 * var(--el-padding-450) + var(--button-400) - 2px );
}

/* The button
   -------------------------------------------------- */

/* The button is the site's button, and all of its look and size come from
   there. It is only kept from shrinking in the row, and it is what the loader
   and the checkmark are laid over. */
.ds-signup-form .ds-signup-form__button {
    position: relative;
    flex: 0 0 auto;
}

/* The site's button has no focus ring of its own, and this one is pressed from
   the keyboard as often as not. */
.ds-signup-form .ds-signup-form__button:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

/* Disabled only while it is busy or done, neither of which is a button that
   is out of reach, so it keeps its color. */
.ds-signup-form .ds-signup-form__button:disabled {
    cursor: default;
}

.ds-signup-form--loading .ds-signup-form__button:disabled {
    cursor: progress;
}

/* The loader and the checkmark take no room of their own. They are laid over
   the middle of the button, so it keeps the label's size whichever of the
   three is showing. */
.ds-signup-form__button__loader,
.ds-signup-form__button__check {
    position: absolute;
    inset: 0;
    margin: auto;
}

/* The label is hidden by its opacity rather than its visibility, which would
   take the button's accessible name away with it. */
.ds-signup-form__button__label {
    transition: opacity var(--ds-signup-form-state-duration) var(--ds-signup-form-state-easing);
}

.ds-signup-form--loading .ds-signup-form__button__label,
.ds-signup-form--success .ds-signup-form__button__label {
    opacity: 0;
}

/* The loader: a ring in the label's color with one side of it travelling. It
   is swapped for the checkmark at once rather than faded, so the ring is never
   seen stopping mid turn. */
.ds-signup-form__button__loader {
    display: block;

    width: var(--ds-icon-size-400);
    height: var(--ds-icon-size-400);
    border: 3px solid var(--ds-signup-form-loader-track);
    border-top-color: var(--color-6);
    border-radius: 50%;

    opacity: 0;
}

.ds-signup-form--loading .ds-signup-form__button__loader {
    opacity: 1;

    animation: ds-signup-form-spin 0.8s linear infinite;
}

@keyframes ds-signup-form-spin {
    to {
        transform: rotate( 360deg );
    }
}

/* The checkmark is the design's check icon, stroked in the label's color. */
.ds-signup-form__button__check {
    display: block;

    width: var(--ds-icon-size-400);
    height: calc( var(--ds-icon-size-400) * 0.75 );

    opacity: 0;
    transform: scale( 0.6 );
}

.ds-signup-form__button__check svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.ds-signup-form__button__check path {
    stroke: currentColor;
}

.ds-signup-form--success .ds-signup-form__button__check {
    opacity: 1;
    transform: scale( 1 );

    transition:
        opacity var(--ds-signup-form-state-duration) var(--ds-signup-form-state-easing),
        transform 320ms cubic-bezier( 0.34, 1.56, 0.64, 1 );
}

/* The error
   -------------------------------------------------- */

/* The message is a live region, so it stays in the page and is only ever
   emptied: a region that is taken out of the page and put back is not reliably
   read out. Empty, it has no height, and the gap above it and its mark only
   come in with the error class. */
.ds-signup-form__error {
    display: flex;
    align-items: flex-start;
    gap: var(--el-spacing-150);
}

.ds-signup-form--error .ds-signup-form__error {
    margin-block-start: var(--ds-signup-form-gap);
}

/* The warning mark on a disc, the way the card deck draws it, sized to sit on
   the first line of the text. */
.ds-signup-form__error__icon {
    display: none;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;

    width: var(--ds-icon-size-300);
    height: var(--ds-icon-size-300);
    border-radius: 999px;

    background-color: var(--color-1);
    color: var(--color-6);
}

.ds-signup-form--error .ds-signup-form__error__icon {
    display: inline-flex;
}

.ds-signup-form__error__glyph {
    display: block;
    width: auto;
    height: calc( var(--ds-icon-size-300) / 2 );
}

/* The trap is moved out of sight rather than hidden, since a bot skips a field
   that is not displayed at all. */
.ds-signup-form__trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media ( max-width: 767px ) {
    .ds-signup-form {
        --ds-signup-form-gap: 0.75rem;
    }

    /* On a phone the field takes the whole width and the button goes under
       it, centred, at the width buttons take on a phone. */
    .ds-signup-form__row {
        flex-direction: column;
        align-items: center;
    }

    .ds-signup-form__field {
        width: 100%;
    }
}

/* The ring does not turn, it breathes, and the checkmark is simply there. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-signup-form__button__label,
    .ds-signup-form--success .ds-signup-form__button__check {
        transition: none;
    }

    .ds-signup-form__button__check {
        transform: none;
    }

    .ds-signup-form--loading .ds-signup-form__button__loader {
        animation: ds-signup-form-pulse 1.6s ease-in-out infinite;
    }
}

@keyframes ds-signup-form-pulse {
    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.4;
    }
}

/* --------------------------------------------------
   Table of contents element
   -------------------------------------------------- */

.ds-table-of-contents {
    /* between the header and the list, between the icon and the title, and
       between every entry of the list, the rows of h3s included */
    --ds-table-of-contents-gap: var(--el-spacing-400);
    --ds-table-of-contents-header-gap: var(--el-padding-150);
    --ds-table-of-contents-item-gap: var(--el-spacing-300);

    /* a row of h3s: the rail, the room beside it, and the room above the
       first h3 and below the last one */
    --ds-table-of-contents-rail-width: 3px;
    --ds-table-of-contents-group-gap: var(--el-spacing-300);
    --ds-table-of-contents-group-padding: var(--el-padding-300);

    --ds-table-of-contents-icon-width: var(--ds-icon-size-400);
    --ds-table-of-contents-icon-height: var(--ds-icon-size-300);

    /* the marker: as wide as the rhombus turned on its point, and as tall as
       the h3 beside it and the overhang above and below, never shorter than
       the minimum a one-line h3 gets */
    --ds-table-of-contents-marker-width: var(--ds-icon-size-400);
    --ds-table-of-contents-marker-min-height: var(--ds-el-size-700);
    --ds-table-of-contents-marker-overhang: var(--el-spacing-250);
    --ds-table-of-contents-marker-rhombus-size: var(--ds-icon-size-300);
    --ds-table-of-contents-marker-rhombus-radius: var(--el-border-radius-80);

    /* the button beside an h2 that opens and closes its h3s */
    --ds-table-of-contents-toggle-size: var(--ds-icon-size-400);
    --ds-table-of-contents-toggle-icon-size: var(--ds-icon-size-300);
    --ds-table-of-contents-toggle-gap: var(--el-padding-200);

    /* placed by the script: the middle of the h3 being read, from the top of
       its row */
    --ds-table-of-contents-marker-y: 0px;

    --ds-table-of-contents-duration: 320ms;
    --ds-table-of-contents-easing: cubic-bezier(0.4, 0, 0.2, 1);

    /* the marker's travel between h3s: eased in and out over a little longer,
       so it gathers speed and settles rather than setting off at full speed */
    --ds-table-of-contents-marker-duration: 480ms;
    --ds-table-of-contents-marker-easing: cubic-bezier(0.65, 0, 0.35, 1);

    /* the design trims every line of text to its capitals, so the gaps above
       are measured between the tops and the baselines of the letters. This is
       the cap height of Geomanist, for the browsers that cannot trim */
    --ds-table-of-contents-cap-height: 0.72em;

    /* flat as a fallback and mixed where color-mix is understood, the same
       shape the other elements use */
    --ds-table-of-contents-muted: rgba(117, 54, 74, 0.48);
    --ds-table-of-contents-rail: rgba(117, 54, 74, 0.16);

    /* the table is kept within the window: the script sets how far down it
       its top stays, and the gap is left free under its bottom */
    --ds-table-of-contents-viewport-top: 0px;
    --ds-table-of-contents-viewport-gap: var(--el-spacing-350);

    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--ds-table-of-contents-gap);

    width: 100%;
    max-height: calc(100vh - var(--ds-table-of-contents-viewport-top) - var(--ds-table-of-contents-viewport-gap));

    font-family: var(--main-font);
    color: var(--ds-table-of-contents-muted);
}

@supports ( color: color-mix( in srgb, red 48%, transparent ) ) {
    .ds-table-of-contents {
        --ds-table-of-contents-muted: color-mix( in srgb, var(--color-1) 48%, transparent );
        --ds-table-of-contents-rail: color-mix( in srgb, var(--color-1) 16%, transparent );
    }
}

/* the window's height without the browser bars that come and go on phones */
@supports ( height: 100dvh ) {
    .ds-table-of-contents {
        max-height: calc(100dvh - var(--ds-table-of-contents-viewport-top) - var(--ds-table-of-contents-viewport-gap));
    }
}

/* Header
   -------------------------------------------------- */

.ds-table-of-contents__header {
    flex: none;

    display: flex;
    align-items: center;
    gap: var(--ds-table-of-contents-header-gap);
}

.ds-table-of-contents__icon {
    flex: none;

    width: var(--ds-table-of-contents-icon-width);
    height: var(--ds-table-of-contents-icon-height);

    /* the drawing is solid, faded like the muted text until a link is active */
    opacity: 0.48;

    transition: opacity var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing);
}

.ds-table-of-contents__icon__image {
    display: block;

    width: 100%;
    max-width: none;
    height: 100%;
}

/* Selected through .ds-table-of-contents so the margin reset outranks the
   theme's paragraph margins. */
.ds-table-of-contents .ds-table-of-contents__title {
    margin: 0;
}

.ds-table-of-contents__title {
    color: var(--ds-table-of-contents-muted);

    font-weight: var(--ds-global-heading-font-weight-400, 900);
    line-height: var(--body-line-height-400, 1.16em);
    letter-spacing: var(--ds-global-heading-letter-spacing-400, -0.04em);

    text-box: trim-both cap alphabetic;

    transition: color var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing);
}

/* The header turns solid while the script has a link marked as the one being
   read. */
.ds-table-of-contents:has(.ds-table-of-contents__link--active) .ds-table-of-contents__icon {
    opacity: 1;
}

.ds-table-of-contents:has(.ds-table-of-contents__link--active) .ds-table-of-contents__title {
    color: var(--color-1);
}

/* Font size steps off the overline type scale. */
.ds-table-of-contents__title--300 {
    font-size: var(--overline-300);
}

.ds-table-of-contents__title--400 {
    font-size: var(--overline-400);
}

/* List
   -------------------------------------------------- */

.ds-table-of-contents .ds-table-of-contents__list,
.ds-table-of-contents .ds-table-of-contents__sublist {
    display: flex;
    flex-direction: column;
    gap: var(--ds-table-of-contents-item-gap);

    margin: 0;
    padding: 0;

    list-style: none;
}

/* The list scrolls when the table is taller than the window lets it be, and
   the header stays put above it. It reaches out past the table by the room
   the marker and the focus outline stick out by, and pads that back in, so
   the scrolling edge does not clip them. */
.ds-table-of-contents .ds-table-of-contents__list {
    --ds-table-of-contents-list-room: var(--el-padding-200);

    flex: 0 1 auto;
    min-height: 0;

    width: calc(100% + 2 * var(--ds-table-of-contents-list-room));
    margin: calc(-1 * var(--ds-table-of-contents-list-room));
    padding: var(--ds-table-of-contents-list-room);

    overflow-y: auto;
    overscroll-behavior: contain;

    scrollbar-width: thin;
    scrollbar-color: var(--ds-table-of-contents-rail) transparent;
}

.ds-table-of-contents .ds-table-of-contents__section,
.ds-table-of-contents .ds-table-of-contents__subitem {
    margin: 0;
}

.ds-table-of-contents__section {
    display: flex;
    flex-direction: column;
    gap: var(--ds-table-of-contents-item-gap);
}

/* Collapsible sections
   -------------------------------------------------- */

/* An h2 with h3s under it opens and closes them. The gap under the h2 moves
   inside the panel, so a closed section takes no more room than its h2. */
.ds-table-of-contents .ds-table-of-contents__section--collapsible {
    gap: 0;
}

.ds-table-of-contents__section__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-table-of-contents-toggle-gap);
}

.ds-table-of-contents__section__header .ds-table-of-contents__link {
    flex: 1 1 auto;
    min-width: 0;
}

/* Selected through .ds-table-of-contents, hover and focus included, so the
   reset outranks the theme's and Elementor's button styles. */
.ds-table-of-contents .ds-table-of-contents__section__toggle,
.ds-table-of-contents .ds-table-of-contents__section__toggle:hover,
.ds-table-of-contents .ds-table-of-contents__section__toggle:focus {
    background: none;
    border: 0;
    box-shadow: none;
}

.ds-table-of-contents .ds-table-of-contents__section__toggle {
    -webkit-appearance: none;
    appearance: none;

    flex: none;

    display: inline-flex;
    align-items: center;
    justify-content: center;

    width: var(--ds-table-of-contents-toggle-size);
    min-width: 0;
    height: var(--ds-table-of-contents-toggle-size);
    min-height: 0;

    margin: 0;
    padding: 0;
    border-radius: 999px;

    color: var(--ds-table-of-contents-muted);
    line-height: 0;

    cursor: pointer;

    transition: color var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing);
}

.ds-table-of-contents .ds-table-of-contents__section__toggle:hover,
.ds-table-of-contents .ds-table-of-contents__section__header:has(.ds-table-of-contents__link--active) .ds-table-of-contents__section__toggle {
    color: var(--color-1);
}

.ds-table-of-contents .ds-table-of-contents__section__toggle:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 2px;
}

.ds-table-of-contents__section__toggle__icon {
    display: block;

    width: var(--ds-table-of-contents-toggle-icon-size);
    height: var(--ds-table-of-contents-toggle-icon-size);

    transition: transform var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing);
}

.ds-table-of-contents__section--open .ds-table-of-contents__section__toggle__icon {
    transform: rotate( 180deg );
}

/* The panel grows from nothing to the height of its h3s. It clips only top
   and bottom, so the marker still sticks out beside the rail, and what it
   hides is hidden from the keyboard and screen readers as well. */
.ds-table-of-contents__section__panel {
    display: grid;
    grid-template-rows: 0fr;
}

.ds-table-of-contents__section--open .ds-table-of-contents__section__panel {
    grid-template-rows: 1fr;
}

.ds-table-of-contents__section__panel__inner {
    display: flow-root;

    min-height: 0;

    overflow-x: visible;
    overflow-y: clip;

    visibility: hidden;
}

.ds-table-of-contents__section--open .ds-table-of-contents__section__panel__inner {
    visibility: visible;
}

.ds-table-of-contents__section__panel__inner > .ds-table-of-contents__group {
    margin-top: var(--ds-table-of-contents-item-gap);
}

/* Only animated once the script has set the table as the page loaded, so a
   page opened halfway down does not play the sections opening and closing. */
.ds-table-of-contents--animated .ds-table-of-contents__section__panel {
    transition: grid-template-rows var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing);
}

.ds-table-of-contents--animated .ds-table-of-contents__section__panel__inner {
    transition: visibility 0s linear var(--ds-table-of-contents-duration);
}

.ds-table-of-contents--animated .ds-table-of-contents__section--open .ds-table-of-contents__section__panel__inner {
    transition-delay: 0s;
}

/* A row of h3s, with the rail drawn beside them as the row's first item so it
   runs their whole height. */
.ds-table-of-contents__group {
    position: relative;

    display: flex;
    gap: var(--ds-table-of-contents-group-gap);

    margin-inline-start: var(--el-spacing-350);
}

.ds-table-of-contents__group::before {
    content: '';

    flex: 0 0 var(--ds-table-of-contents-rail-width);

    border-radius: 999px;
    background-color: var(--ds-table-of-contents-rail);
}

.ds-table-of-contents .ds-table-of-contents__sublist {
    flex: 1 1 0;
    min-width: 0;

    padding-block: var(--ds-table-of-contents-group-padding);
}

/* Selected through .ds-table-of-contents so the color outranks the theme's
   a:visited and a:hover, which carry a class's weight of their own. */
.ds-table-of-contents .ds-table-of-contents__link {
    display: block;

    color: var(--ds-table-of-contents-muted);

    font-weight: 500;
    line-height: var(--body-line-height-400, 1.16em);
    letter-spacing: var(--ds-global-body-text-letter-spacing-400, -0.04em);
    text-decoration: none;
    overflow-wrap: break-word;

    text-box: trim-both cap alphabetic;

    transition: color var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing);
}

.ds-table-of-contents .ds-table-of-contents__link:hover,
.ds-table-of-contents .ds-table-of-contents__link--active {
    color: var(--color-1);
}

.ds-table-of-contents .ds-table-of-contents__link:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 4px;
}

/* Font size steps off the body type scale. */
.ds-table-of-contents__link--200 {
    font-size: var(--body-200);
}

.ds-table-of-contents__link--250 {
    font-size: var(--body-250);
}

.ds-table-of-contents__link--300 {
    font-size: var(--body-300);
}

.ds-table-of-contents__link--350 {
    font-size: var(--body-350);
}

.ds-table-of-contents__link--400 {
    font-size: var(--body-400);
}

.ds-table-of-contents__link--450 {
    font-size: var(--body-450);
}

.ds-table-of-contents__link--500 {
    font-size: var(--body-500);
}

.ds-table-of-contents__link--550 {
    font-size: var(--body-550);
}

/* Where text cannot be trimmed, the lines are pulled in by the room the
   trimming would have taken off, so the gaps come out as designed. */
@supports not ( text-box: trim-both cap alphabetic ) {
    .ds-table-of-contents .ds-table-of-contents__title,
    .ds-table-of-contents .ds-table-of-contents__link {
        margin-block: calc( ( var(--ds-table-of-contents-cap-height) - var(--body-line-height-400, 1.16em) ) / 2 );
    }
}

/* The marker
   -------------------------------------------------- */

/* The dark stretch of rail with the diamond on it, centred on the rail. Every
   row of h3s has one, shown only on the row being read. It fades in where it
   belongs, and only once it is showing is its move given a transition, so it
   travels between the h3s of its own row but never slides across from the
   last place it stood when the reader comes back to the row. Leaving the row
   keeps the transition on while it fades, so a move under way is finished
   rather than cut short. */
.ds-table-of-contents__marker {
    position: absolute;
    top: 0;
    left: calc( ( var(--ds-table-of-contents-rail-width) - var(--ds-table-of-contents-marker-width) ) / 2 );

    /* the height of the h3 being read is set on the row by the script, so it
       is only read here, with nothing until the script has measured one */
    width: var(--ds-table-of-contents-marker-width);
    height: max(
        var(--ds-table-of-contents-marker-min-height),
        calc( var(--ds-table-of-contents-marker-link-height, 0px) + 2 * var(--ds-table-of-contents-marker-overhang) )
    );

    opacity: 0;

    transform: translateY( calc( var(--ds-table-of-contents-marker-y) - 50% ) );

    pointer-events: none;

    transition: opacity var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing);
}

/* The dark stretch of rail, over the rail and the marker's whole height. */
.ds-table-of-contents__marker__bar {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;

    width: var(--ds-table-of-contents-rail-width);

    border-radius: 999px;
    background-color: var(--color-1);

    transform: translateX( -50% );
}

/* A rounded square turned on its point, on the middle of the bar. */
.ds-table-of-contents__marker__rhombus {
    position: absolute;
    top: 50%;
    left: 50%;

    width: var(--ds-table-of-contents-marker-rhombus-size);
    height: var(--ds-table-of-contents-marker-rhombus-size);

    border-radius: var(--ds-table-of-contents-marker-rhombus-radius);
    background-color: var(--color-1);

    transform: translate( -50%, -50% ) rotate( 45deg );
}

.ds-table-of-contents__group--active .ds-table-of-contents__marker {
    opacity: 1;
}

.ds-table-of-contents__group--tracking .ds-table-of-contents__marker {
    transition:
        opacity var(--ds-table-of-contents-duration) var(--ds-table-of-contents-easing),
        transform var(--ds-table-of-contents-marker-duration) var(--ds-table-of-contents-marker-easing),
        height var(--ds-table-of-contents-marker-duration) var(--ds-table-of-contents-marker-easing);
}

@media ( prefers-reduced-motion: reduce ) {
    .ds-table-of-contents .ds-table-of-contents__link,
    .ds-table-of-contents__marker,
    .ds-table-of-contents__group--tracking .ds-table-of-contents__marker,
    .ds-table-of-contents__section__toggle__icon,
    .ds-table-of-contents--animated .ds-table-of-contents__section__panel,
    .ds-table-of-contents--animated .ds-table-of-contents__section__panel__inner,
    .ds-table-of-contents--animated .ds-table-of-contents__section--open .ds-table-of-contents__section__panel__inner {
        transition: none;
    }
}

/* --------------------------------------------------
   Dot connector element
   -------------------------------------------------- */

/* A row of seven dots (three when short) in one color, faded out from the middle. The color is
   held on the wrapper alone: the modifier classes below set it and every dot
   reads it from there. The dots are a fixed size in px rather than a fluid
   one, picked by the size steps further down. The wrapper on its own is
   drawn at 400, the default: 8px on desktop, and 6px on tablet and mobile
   below. */
.ds-dot-connector {
    --ds-dot-connector-color: var(--color-1);
    --ds-dot-connector-dot: 8px;
    --ds-dot-connector-gap: var(--el-spacing-100);
    --ds-dot-connector-direction: row;
    --ds-dot-connector-outer-display: block;
    --ds-dot-connector-center-opacity: 1;
    --ds-dot-connector-near-opacity: 0.5;

    display: flex;
    flex-direction: var(--ds-dot-connector-direction);
    align-items: center;
    justify-content: center;
    gap: var(--ds-dot-connector-gap);
}

.ds-dot-connector__dot {
    flex-shrink: 0;

    width: var(--ds-dot-connector-dot);
    height: var(--ds-dot-connector-dot);
    border-radius: 50%;

    background-color: var(--ds-dot-connector-color);
    opacity: 0.125;
}

@media ( max-width: 1024px ) {
    .ds-dot-connector {
        --ds-dot-connector-dot: 6px;
    }
}

/* Read from the middle outwards: the dot at the centre is solid and the rest
   halve away to either side, down to the 0.125 set above at the two ends. The
   centre and the two beside it read custom properties, so the short length
   below can change them. */
.ds-dot-connector__dot:nth-child(4) { opacity: var(--ds-dot-connector-center-opacity); }
.ds-dot-connector__dot:nth-child(3),
.ds-dot-connector__dot:nth-child(5) { opacity: var(--ds-dot-connector-near-opacity); }
.ds-dot-connector__dot:nth-child(2),
.ds-dot-connector__dot:nth-child(6) { opacity: 0.25; }

/* The outer two on each side, hidden by the short length. */
.ds-dot-connector__dot:nth-child(-n+2),
.ds-dot-connector__dot:nth-child(n+6) {
    display: var(--ds-dot-connector-outer-display);
}

/* Length and direction. The modifier classes only set the custom properties
   above. Short keeps the middle three of the seven. The mobile classes are
   always printed, short and vertical unless the element is told otherwise. */
.ds-dot-connector--length-default {
    --ds-dot-connector-outer-display: block;
    --ds-dot-connector-center-opacity: 1;
    --ds-dot-connector-near-opacity: 0.5;
}

.ds-dot-connector--length-short {
    --ds-dot-connector-outer-display: none;
    --ds-dot-connector-center-opacity: 1;
    --ds-dot-connector-near-opacity: 0.5;
}

.ds-dot-connector--direction-horizontal { --ds-dot-connector-direction: row; }
.ds-dot-connector--direction-vertical { --ds-dot-connector-direction: column; }

@media ( max-width: 767px ) {
    .ds-dot-connector--length-mobile-default {
        --ds-dot-connector-outer-display: block;
        --ds-dot-connector-center-opacity: 1;
        --ds-dot-connector-near-opacity: 0.5;
    }

    .ds-dot-connector--length-mobile-short {
        --ds-dot-connector-outer-display: none;
        --ds-dot-connector-center-opacity: 1;
        --ds-dot-connector-near-opacity: 0.5;
    }

    .ds-dot-connector--direction-mobile-horizontal { --ds-dot-connector-direction: row; }
    .ds-dot-connector--direction-mobile-vertical { --ds-dot-connector-direction: column; }
}

/* The size steps, which only set the dot size above. 400 is 8px, and 6px on
   tablet and mobile, 300 is 6px at every width. */
.ds-dot-connector--size-400 { --ds-dot-connector-dot: 8px; }
.ds-dot-connector--size-300 { --ds-dot-connector-dot: 6px; }

@media ( max-width: 1024px ) {
    .ds-dot-connector--size-400 { --ds-dot-connector-dot: 6px; }
}

/* The color ids, 1 through 6. */
.ds-dot-connector--color-1 {
    --ds-dot-connector-color: var(--color-1);
}

.ds-dot-connector--color-2 {
    --ds-dot-connector-color: var(--color-2);
}

.ds-dot-connector--color-3 {
    --ds-dot-connector-color: var(--color-3);
}

.ds-dot-connector--color-4 {
    --ds-dot-connector-color: var(--color-4);
}

.ds-dot-connector--color-5 {
    --ds-dot-connector-color: var(--color-5);
}

/* Six is the cream the page itself is laid on, so it is only visible on a
   darker section. */
.ds-dot-connector--color-6 {
    --ds-dot-connector-color: var(--color-6);
}

/* The rounded shape from assets/svgs/rounded-div.svg. The color comes from the
   theme's .ds-sc-bg-* class on the same element, which is a textured background
   rather than a fill, so the SVG is used as a mask and the background shows only
   inside the shape. The aspect ratio is the file's viewBox, 1512 by 104, so the
   shape stretches to the width of its container and keeps its proportions. */
.ds-rounded-div {
    display: block;

    width: 100%;
    aspect-ratio: 1512 / 104;

    /* The SVG's viewBox starts 8 units above the curve, a solid band that tucks
       under the section before it, so the mask's soft top edge never lands on
       the seam, which Safari and Firefox otherwise show as a see-through line.
       A percentage margin resolves against the container's width, the element's
       own width, so this pulls it up by exactly those 8 units at any size and
       the curve stays where it was. */
    margin-top: calc(-8 / 1512 * 100%);

    -webkit-mask-image: url(../svgs/rounded-div.svg);
    -webkit-mask-size: 100% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-image: url(../svgs/rounded-div.svg);
    mask-size: 100% 100%;
    mask-repeat: no-repeat;
}

/* --------------------------------------------------
   Loader element
   -------------------------------------------------- */

/* Two dots circling inside a turning one. It takes no room in the flow, so
   whatever holds it places it itself, and it is drawn out of view until the
   active class is put on it: hidden rather than only transparent, so it is
   never in the way of a pointer, and scaled down so it grows in. scale is set
   apart from transform, which the turning takes.

   The size steps further down set the size and how far out the two dots sit,
   which is the one thing that does not simply scale with it: a smaller loader
   reads better with them a little further apart. */
.ds-loader {
    /* the dot in the middle, how far the two circling it are inset from its
       edge, and how far out they sit */
    --ds-loader-size: 1.0625rem;
    --ds-loader-inset: 15%;
    --ds-loader-orbit: 150%;

    --ds-loader-color: var(--color-1);

    /* easing in and out of the wait, eased out and never running past where
       it ends */
    --ds-loader-duration: 0.32s;
    --ds-loader-easing: cubic-bezier( 0.25, 1, 0.5, 1 );

    display: grid;

    width: var(--ds-loader-size);
    aspect-ratio: 1;

    border-radius: 50%;
    background: var(--ds-loader-color);

    opacity: 0;
    visibility: hidden;
    scale: 0.4;

    pointer-events: none;

    animation: ds-loader-turn 2s infinite linear;

    transition:
        opacity var(--ds-loader-duration) var(--ds-loader-easing),
        scale var(--ds-loader-duration) var(--ds-loader-easing),
        visibility 0s linear var(--ds-loader-duration);
}

/* The two circling dots, laid in the same cell so they turn around the same
   middle, half a turn apart. They take the color of the dot they sit in. */
.ds-loader::before,
.ds-loader::after {
    content: '';

    grid-area: 1 / 1;

    margin: var(--ds-loader-inset);

    border-radius: 50%;
    background: inherit;

    transform: rotate( 0deg ) translate( var(--ds-loader-orbit) );

    animation: ds-loader-orbit 1s infinite;
}

.ds-loader::after {
    animation-delay: -0.5s;
}

.ds-loader--active {
    opacity: 1;
    visibility: visible;
    scale: 1;

    transition:
        opacity var(--ds-loader-duration) var(--ds-loader-easing),
        scale var(--ds-loader-duration) var(--ds-loader-easing),
        visibility 0s;
}

@keyframes ds-loader-turn {
    100% {
        transform: rotate( 1turn );
    }
}

@keyframes ds-loader-orbit {
    100% {
        transform: rotate( 1turn ) translate( var(--ds-loader-orbit) );
    }
}

/* The size steps. 400 is 17px, 300 is 12px with its two dots further out. */
.ds-loader--size-400 {
    --ds-loader-size: 1.0625rem;
    --ds-loader-orbit: 150%;
}

.ds-loader--size-300 {
    --ds-loader-size: 0.75rem;
    --ds-loader-orbit: 185%;
}

/* The mobile step, printed only when the loader is given one, so that a
   loader without it keeps the size above at every width. */
@media ( max-width: 767px ) {
    .ds-loader--size-mobile-400 {
        --ds-loader-size: 1.0625rem;
        --ds-loader-orbit: 150%;
    }

    .ds-loader--size-mobile-300 {
        --ds-loader-size: 0.75rem;
        --ds-loader-orbit: 185%;
    }
}

/* The color ids, 1 through 6. */
.ds-loader--color-1 {
    --ds-loader-color: var(--color-1);
}

.ds-loader--color-2 {
    --ds-loader-color: var(--color-2);
}

.ds-loader--color-3 {
    --ds-loader-color: var(--color-3);
}

.ds-loader--color-4 {
    --ds-loader-color: var(--color-4);
}

.ds-loader--color-5 {
    --ds-loader-color: var(--color-5);
}

/* Six is the cream the page itself is laid on, so it is only visible on a
   darker section. */
.ds-loader--color-6 {
    --ds-loader-color: var(--color-6);
}

/* --------------------------------------------------
   Body text element
   -------------------------------------------------- */

/* Block in every tag, span included, so the ch max-width printed per instance
   and the alignment below apply to it. */
.ds-body-text {
    display: block;

    font-family: var(--main-font);
    line-height: var(--body-line-height-400);
    letter-spacing: var(--ds-global-body-text-letter-spacing-400);
}

/* Font size steps off the body type scale. 400 is the default. Declared on the
   element itself, which is also what the ch max-width resolves against. */
.ds-body-text--200 {
    font-size: var(--body-200);
}

.ds-body-text--250 {
    font-size: var(--body-250);
}

.ds-body-text--300 {
    font-size: var(--body-300);
}

.ds-body-text--350 {
    font-size: var(--body-350);
}

.ds-body-text--400 {
    font-size: var(--body-400);
}

.ds-body-text--450 {
    font-size: var(--body-450);
}

.ds-body-text--500 {
    font-size: var(--body-500);
}

.ds-body-text--550 {
    font-size: var(--body-550);
}

/* The mobile steps, printed only when the copy is given one, so that copy
   without it keeps the step above at every width. */
@media ( max-width: 767px ) {
    .ds-body-text--mobile-200 {
        font-size: var(--body-200);
    }

    .ds-body-text--mobile-250 {
        font-size: var(--body-250);
    }

    .ds-body-text--mobile-300 {
        font-size: var(--body-300);
    }

    .ds-body-text--mobile-350 {
        font-size: var(--body-350);
    }

    .ds-body-text--mobile-400 {
        font-size: var(--body-400);
    }

    .ds-body-text--mobile-450 {
        font-size: var(--body-450);
    }

    .ds-body-text--mobile-500 {
        font-size: var(--body-500);
    }

    .ds-body-text--mobile-550 {
        font-size: var(--body-550);
    }
}

/* Font weights, 100 through 900. 600 is the default. */
.ds-body-text--weight-100 {
    font-weight: 100;
}

.ds-body-text--weight-200 {
    font-weight: 200;
}

.ds-body-text--weight-300 {
    font-weight: 300;
}

.ds-body-text--weight-400 {
    font-weight: 400;
}

.ds-body-text--weight-500 {
    font-weight: 500;
}

.ds-body-text--weight-600 {
    font-weight: 600;
}

.ds-body-text--weight-700 {
    font-weight: 700;
}

.ds-body-text--weight-800 {
    font-weight: 800;
}

.ds-body-text--weight-900 {
    font-weight: 900;
}

/* Text color ids, 1 through 6. */
.ds-body-text--color-1 {
    color: var(--color-1);
}

.ds-body-text--color-2 {
    color: var(--color-2);
}

.ds-body-text--color-3 {
    color: var(--color-3);
}

.ds-body-text--color-4 {
    color: var(--color-4);
}

.ds-body-text--color-5 {
    color: var(--color-5);
}

.ds-body-text--color-6 {
    color: var(--color-6);
}

/* Alignment. The desktop class is always printed, left when none is given, so
   these rules also carry the margin reset. They are doubled up with
   .ds-body-text so they outrank theme rules such as ".entry-content p".
   text-align lines up the text, and the inline margins move the box itself,
   which shows once a ch max-width makes it narrower than its container.
   Tablet and mobile classes are only printed when set, so without one the
   larger breakpoint's value carries down. */
.ds-body-text.ds-body-text--align-desktop-left { margin: 0 auto 0 0; text-align: left; }
.ds-body-text.ds-body-text--align-desktop-center { margin: 0 auto; text-align: center; }
.ds-body-text.ds-body-text--align-desktop-right { margin: 0 0 0 auto; text-align: right; }

@media ( max-width: 1024px ) {
    .ds-body-text.ds-body-text--align-tablet-left { margin: 0 auto 0 0; text-align: left; }
    .ds-body-text.ds-body-text--align-tablet-center { margin: 0 auto; text-align: center; }
    .ds-body-text.ds-body-text--align-tablet-right { margin: 0 0 0 auto; text-align: right; }
}

@media ( max-width: 767px ) {
    .ds-body-text.ds-body-text--align-mobile-left { margin: 0 auto 0 0; text-align: left; }
    .ds-body-text.ds-body-text--align-mobile-center { margin: 0 auto; text-align: center; }
    .ds-body-text.ds-body-text--align-mobile-right { margin: 0 0 0 auto; text-align: right; }
}

/* The break an <hr> in the copy is turned into. Block so it ends the line it
   sits on, and its height is the gap that sets the two paragraphs apart. In em,
   so it follows whichever font size step the copy is set in. */
.ds-body-text .ds-body-text__break {
    display: block;
    height: var(--ds-body-text-break-gap, 0.75em);
}

/* The links added by the nested link shortcodes. They take the color of the
   copy around them and the animated underline instead of a text-decoration,
   selected through .ds-body-text so the rule outranks theme link rules such
   as ".entry-content a". The link stays inline so a long one, a url most of
   all, wraps like the copy around it, and the underline is a background so
   it is drawn under each line the link takes rather than once under the
   whole of it. overflow-wrap lets a url too long for a line of its own break
   anywhere instead of running off the side of a phone.
   The line sits closer to the copy than on the button, at half the gap. The
   button's line is the offset under its 1em box, which ends 0.17em under
   Geomanist's baseline, so the gap is halved from the offset plus that. An
   inline box's background ends at the font's descent, 0.34em under the
   baseline, and the padding brings its bottom edge down from there to the
   gap plus the line's thickness. */
.ds-body-text .ds-body-text__link {
    --ds-body-text-link-gap: calc( ( var(--ds-underline-offset) + 0.17em ) / 2 );

    color: inherit;
    text-decoration: none;
    overflow-wrap: anywhere;

    padding-bottom: calc( var(--ds-body-text-link-gap) + var(--ds-underline-thickness) - 0.34em );
    background-image: linear-gradient( currentColor, currentColor );
    background-repeat: no-repeat;
    background-position: 0% 100%;
    background-size: 100% var(--ds-underline-thickness);
}

/* --------------------------------------------------
   Modal window
   -------------------------------------------------- */

/* The dialog covers the viewport and holds the panel, which is what is seen of
   it. A closed dialog is hidden by the browser's own display: none, so nothing
   here sets a display, which would put every closed one on show. The position
   and the z-index only count in a browser that takes the dialog out of the top
   layer the moment it closes, where they keep the panel over the page while it
   slides away. The display and overlay transitions are what hold the dialog
   open for as long as that takes everywhere else. */
.ds-modal {
    position: fixed;
    inset: 0;
    z-index: 100000;

    box-sizing: border-box;
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    overflow: hidden;

    background: none;
    color: inherit;

    transition:
        display 0.4s allow-discrete,
        overlay 0.4s allow-discrete;
}

/* Literal values rather than custom properties, since an older browser does
   not let the backdrop inherit them from the dialog. */
.ds-modal::backdrop {
    background-color: rgb( 0 0 0 / 0 );

    transition:
        background-color 0.4s ease,
        display 0.4s allow-discrete,
        overlay 0.4s allow-discrete;
}

.ds-modal[open]::backdrop {
    background-color: rgb( 0 0 0 / 0.4 );
}

@starting-style {
    .ds-modal[open]::backdrop {
        background-color: rgb( 0 0 0 / 0 );
    }
}

/* The panel comes in from the right and is as tall as the viewport. Its fill
   and grain come from the theme's .ds-sc-bg-* class. Its padding is the
   header's, so the close button lands where a button at the end of the header
   stood. */
.ds-modal__panel {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;

    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-400, 2rem);

    box-sizing: border-box;
    width: 100%;
    max-width: 32rem;
    height: 100%;
    padding-block: var(--sc-padding-block-150, 1.25rem) var(--el-spacing-400, 2rem);
    padding-inline: var(--el-spacing-300, 1.25rem);

    overflow-y: auto;
    overscroll-behavior: contain;

    font-family: var(--main-font);

    transform: translateX( 100% );
    transition: transform 0.4s cubic-bezier( 0.65, 0, 0.35, 1 );
}

.ds-modal[open] .ds-modal__panel {
    transform: none;
}

@starting-style {
    .ds-modal[open] .ds-modal__panel {
        transform: translateX( 100% );
    }
}

.ds-modal__bar {
    display: flex;
    justify-content: flex-end;
}

.ds-modal__content {
    display: flex;
    flex: 1 0 auto;
    flex-direction: column;
}

/* The site's button has no focus ring of its own, and a window is as often
   closed with the keyboard as with the pointer. */
.ds-modal .ds-modal__close:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

/* The page behind an open window stays where it is. The gutter is kept, so the
   page does not shift sideways where the scrollbar takes room of its own. */
html:has( .ds-modal[open] ) {
    overflow: hidden;
    scrollbar-gutter: stable;
}

/* The window is simply there, and simply gone. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-modal,
    .ds-modal::backdrop,
    .ds-modal__panel {
        transition: none;
    }
}

/* --------------------------------------------------
   Mobile menu modal window
   -------------------------------------------------- */

/* The window is not a modal dialog, so it is not in the top layer and sits in
   the page's own stacking order: over everything on the page, under the header
   and the promotion bar, which the script raises over it while it is open. It
   covers the page from where the header ends, which the script measures into
   --ds-mobile-menu-top, down, with the backdrop drawn under the panel, and
   clips the panel sliding in under the header.

   A closed dialog is hidden by the browser's display: none, which would cut
   the slide back up short, so the dialog is always displayed and hidden with
   visibility instead, which also keeps its links out of reach while closed.
   The visibility only turns hidden once the panel is back up. */
.ds-mobile-menu {
    position: fixed;
    top: var(--ds-mobile-menu-top, 0px);
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 9998;

    display: block;
    box-sizing: border-box;
    width: auto;
    max-width: none;
    height: auto;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    overflow: hidden;

    background: none;
    color: inherit;

    visibility: hidden;
    transition: visibility 0s linear 0.4s;
}

.ds-mobile-menu[open] {
    visibility: visible;
    transition: visibility 0s linear 0s;
}

/* The backdrop: the page blurred under a light tint. The blur itself stays
   put and only the layer's opacity is faded, which every browser animates
   smoothly, where a changing blur radius stutters on slower phones. A browser
   without backdrop-filter gets a deeper tint in its place, and so does a
   reader who has asked their system for less transparency. */
.ds-mobile-menu::before {
    content: "";
    position: absolute;
    inset: 0;

    background-color: rgb( 0 0 0 / 0.2 );
    -webkit-backdrop-filter: blur( 12px ) saturate( 1.2 );
    backdrop-filter: blur( 12px ) saturate( 1.2 );

    opacity: 0;
    transition: opacity 0.4s ease;
}

.ds-mobile-menu[open]::before {
    opacity: 1;
}

@supports not ( ( backdrop-filter: blur( 1px ) ) or ( -webkit-backdrop-filter: blur( 1px ) ) ) {
    .ds-mobile-menu::before {
        background-color: rgb( 0 0 0 / 0.4 );
    }
}

@media ( prefers-reduced-transparency: reduce ) {
    .ds-mobile-menu::before {
        background-color: rgb( 0 0 0 / 0.4 );
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
}

/* The panel is the menu's body with the rounded div hanging under it. It is as
   tall as both, and only when that is taller than the space under the header is
   it held to that space, the body then scrolling on its own above the curve.
   The panel itself takes no clicks, so a click beside the curve, where the mask
   leaves it see-through, reaches the dialog and closes the window. */
.ds-mobile-menu__panel {
    position: relative;

    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    max-height: 100%;

    pointer-events: none;

    font-family: var(--main-font);

    transform: translateY( -100% );
    transition: transform 0.4s cubic-bezier( 0.65, 0, 0.35, 1 );
}

.ds-mobile-menu[open] .ds-mobile-menu__panel {
    transform: none;
}

/* The fill and grain come from the theme's .ds-sc-bg-* class. */
.ds-mobile-menu__body {
    flex: 0 1 auto;
    min-height: 0;

    overflow-y: auto;
    overscroll-behavior: contain;

    pointer-events: auto;
}

/* The rounded div's own negative top margin already tucks its solid top band
   under the body, which hides the seam Safari and Firefox otherwise show. It
   is drawn over the body, and a whole pixel more of overlap covers the
   rounding of fractional heights while the panel slides. */
.ds-mobile-menu__panel > .ds-rounded-div {
    position: relative;
    flex: 0 0 auto;

    margin-top: calc( -8 / 1512 * 100% - 1px );
}

/* The menu and the buttons, centered one over the other. The gap between them
   is four of the gaps between the menu's items, as in the design. */
.ds-mobile-menu__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    
    gap: var(--el-spacing-700);
    padding-block: var(--el-spacing-700);
    padding-inline: var(--el-spacing-350);
}

/* Selected through .ds-mobile-menu and the menu's own class, so the rules
   outrank the custom nav menu's layout further down the stylesheet. */
.ds-mobile-menu .ds-custom-nav-menu .ds-custom-nav-menu__list {
    align-items: center;
    gap: var(--el-spacing-400);
}

/* The kit has no nav menu step for the design's item size yet, so the step
   falls back to the body step of the same size until it has one. The line is
   trimmed to the capitals, so the gaps between the items are the design's. */
.ds-mobile-menu .ds-custom-nav-menu .ds-custom-nav-menu__text--600 {
    font-size: var(--nav-menu-600, var(--body-550));
}

.ds-mobile-menu .ds-custom-nav-menu .ds-custom-nav-menu__text {
    text-box: trim-both cap alphabetic;
}

.ds-mobile-menu .ds-custom-nav-menu .ds-custom-nav-menu__link:focus-visible,
.ds-mobile-menu .ds-mobile-menu__button:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

.ds-mobile-menu .ds-mobile-menu__buttons {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--el-spacing-300);
}

.ds-mobile-menu .ds-mobile-menu__button {
    box-sizing: border-box;
    min-width: var(--ds-el-size-900);
}

/* The page behind the open window stays where it is, with the gutter kept so
   it does not shift sideways where the scrollbar takes room of its own. */
html.ds-mobile-menu-is-active {
    overflow: hidden;
    scrollbar-gutter: stable;
}

/* The header and the promotion bar, over the window. Only the stacking order
   changes, both are already positioned. */
html.ds-mobile-menu-is-active .ds-mobile-menu-above {
    z-index: 9999;
}

/* The window is simply there, and simply gone. */
@media ( prefers-reduced-motion: reduce ) {
    .ds-mobile-menu,
    .ds-mobile-menu[open],
    .ds-mobile-menu::before,
    .ds-mobile-menu__panel {
        transition: none;
    }
}

/* --------------------------------------------------
   Hero graphic element
   -------------------------------------------------- */

/* The app open on a module with the next lesson floating over it, drawn at the
   design's 608 by 665 pixels and scaled as a whole to the width it is given,
   the way an image is. Every length inside is a count of design pixels times
   --ds-hero-graphic-px, one design pixel at the current width, so the type,
   radii, gaps and shadows all keep their proportions. The cqi in it measures
   the stage, the size container below. */
.ds-hero-graphic {
    --ds-hero-graphic-px: calc( 100cqi / 608 );

    /* SF Pro's cap height, for the browsers that cannot trim text to it */
    --ds-hero-graphic-cap-height: 0.7046em;

    /* flat as a fallback and mixed where color-mix is understood, the same
       shape the other elements use */
    --ds-hero-graphic-tint: rgba(117, 54, 74, 0.16);
    --ds-hero-graphic-phone-shadow: rgba(117, 54, 74, 0.1);
    --ds-hero-graphic-next-shadow: rgba(117, 54, 74, 0.2);

    position: relative;

    display: block;
    width: 100%;

    font-family: "SF Pro", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

    /* It stands in for a picture, so nothing in it can be selected, copied,
       dragged or long-pressed: pointers pass through it to the page. */
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    pointer-events: none;
}

@supports ( color: color-mix( in srgb, red 16%, transparent ) ) {
    .ds-hero-graphic {
        --ds-hero-graphic-tint: color-mix( in srgb, var(--color-1) 16%, transparent );
        --ds-hero-graphic-phone-shadow: color-mix( in srgb, var(--color-1) 10%, transparent );
        --ds-hero-graphic-next-shadow: color-mix( in srgb, var(--color-1) 20%, transparent );
    }
}

/* The canvas is never drawn on, it only gives the element an image's natural
   size: it fills a container that sets a width, shows at 608px in one that
   sizes to its content, and its height always follows the width. */
.ds-hero-graphic__sizer {
    display: block;

    width: 100%;
    height: auto;
}

/* Laid over the canvas at its exact size. It is the size container rather than
   the wrapper, since a container cannot be sized by its content and the
   wrapper needs the canvas to size it. */
.ds-hero-graphic__stage {
    position: absolute;
    inset: 0;

    container-type: inline-size;
}

/* The phone
   -------------------------------------------------- */

/* The phone fades out towards the bottom edge. It is a mask rather than the
   design's cream overlay, so it fades into whatever the element sits on, and it
   is set on a layer as big as the graphic so the phone's shadow is not cut off
   at the phone's own edges. The fade starts 82.39 design pixels up. */
.ds-hero-graphic__device {
    position: absolute;
    inset: 0;

    -webkit-mask-image: linear-gradient( to bottom, #000 87.61%, transparent 100% );
    mask-image: linear-gradient( to bottom, #000 87.61%, transparent 100% );
}

.ds-hero-graphic__phone {
    position: absolute;
    top: calc( 75 * var(--ds-hero-graphic-px) );
    left: calc( 75 * var(--ds-hero-graphic-px) );

    display: flex;
    flex-direction: column;

    width: calc( 458 * var(--ds-hero-graphic-px) );
    height: calc( 590 * var(--ds-hero-graphic-px) );
    padding: calc( 12 * var(--ds-hero-graphic-px) ) calc( 12 * var(--ds-hero-graphic-px) ) 0;
    border-radius: calc( 80 * var(--ds-hero-graphic-px) ) calc( 80 * var(--ds-hero-graphic-px) ) 0 0;

    background-color: var(--color-6);
    box-shadow: 0 calc( 4 * var(--ds-hero-graphic-px) ) calc( 24 * var(--ds-hero-graphic-px) ) var(--ds-hero-graphic-phone-shadow);
}

/* The rim's tint is the theme's burgundy from .ds-sc-bg-1, grain and all, let
   through at 12% over the phone's cream. */
.ds-hero-graphic__phone__rim {
    position: absolute;
    inset: 0;

    border-radius: inherit;

    opacity: 0.12;
}

/* Positioned so it is painted over the rim, which comes before it. */
.ds-hero-graphic__phone__screen {
    position: relative;

    flex: 1 1 auto;

    border-radius: calc( 68 * var(--ds-hero-graphic-px) ) calc( 68 * var(--ds-hero-graphic-px) ) 0 0;

    background-color: var(--color-6);
}

.ds-hero-graphic__module {
    display: flex;
    flex-direction: column;
    gap: calc( 20 * var(--ds-hero-graphic-px) );

    padding: calc( 48 * var(--ds-hero-graphic-px) ) calc( 32 * var(--ds-hero-graphic-px) );
}

.ds-hero-graphic__module__header {
    display: flex;
    align-items: center;
    justify-content: space-between;

    opacity: 0.48;
}

.ds-hero-graphic__module__title {
    display: flex;
    flex-direction: column;
    gap: calc( 10 * var(--ds-hero-graphic-px) );
}

.ds-hero-graphic__module__menu {
    display: flex;
    align-items: center;
    justify-content: center;

    width: calc( 44 * var(--ds-hero-graphic-px) );
    height: calc( 44 * var(--ds-hero-graphic-px) );
    border-radius: 999px;

    background-color: var(--ds-hero-graphic-tint);
}

.ds-hero-graphic__module__menu__icon {
    display: block;

    width: calc( 24 * var(--ds-hero-graphic-px) );
    max-width: none;
    height: calc( 24 * var(--ds-hero-graphic-px) );
}

.ds-hero-graphic__module__rule {
    display: block;

    height: calc( 3 * var(--ds-hero-graphic-px) );
    border-radius: 999px;

    background-color: var(--color-1);
    opacity: 0.12;
}

/* The next lesson
   -------------------------------------------------- */

/* Floating over the phone and wider than it, so it is left out of the phone's
   fade. */
.ds-hero-graphic__next {
    position: absolute;
    top: calc( 223 * var(--ds-hero-graphic-px) );
    left: calc( 41 * var(--ds-hero-graphic-px) );

    display: flex;
    flex-direction: column;
    gap: calc( 16 * var(--ds-hero-graphic-px) );

    width: calc( 525.221 * var(--ds-hero-graphic-px) );
    padding: calc( 32 * var(--ds-hero-graphic-px) );
    border-radius: calc( 36 * var(--ds-hero-graphic-px) );

    background-color: var(--color-6);
    box-shadow: 0 calc( 4 * var(--ds-hero-graphic-px) ) calc( 24 * var(--ds-hero-graphic-px) ) var(--ds-hero-graphic-next-shadow);
}

/* The burgundy and its grain come from the theme's .ds-sc-bg-1 on the same
   element, so nothing here sets a background. */
.ds-hero-graphic__lesson {
    position: relative;

    display: flex;
    flex-direction: column;
    gap: calc( 12.465 * var(--ds-hero-graphic-px) );

    height: calc( 280 * var(--ds-hero-graphic-px) );
    padding: calc( 28 * var(--ds-hero-graphic-px) );
    border-radius: calc( 24 * var(--ds-hero-graphic-px) );

    overflow: hidden;
}

.ds-hero-graphic__lesson__badge {
    align-self: flex-start;

    display: flex;
    align-items: center;
    justify-content: center;

    padding: calc( 8 * var(--ds-hero-graphic-px) );
    border-radius: 999px;

    background-color: var(--color-6);
}

.ds-hero-graphic__lesson__details {
    flex: 1 1 auto;

    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: calc( 12.465 * var(--ds-hero-graphic-px) );
}

/* It runs the width of the card, the photo laid over it hides the rest. */
.ds-hero-graphic__lesson__rule {
    display: block;

    height: calc( 2 * var(--ds-hero-graphic-px) );
    border-radius: 999px;

    background-color: var(--color-6);
}

/* It reaches the bottom of the card, so only its top corners are rounded. */
/* Selected through .ds-hero-graphic so the radius and height outrank
   Elementor's .elementor img rule, which sets them to 0 and auto. */
.ds-hero-graphic .ds-hero-graphic__lesson__photo {
    position: absolute;
    top: calc( 28 * var(--ds-hero-graphic-px) );
    right: calc( 27.22 * var(--ds-hero-graphic-px) );

    display: block;

    width: calc( 231 * var(--ds-hero-graphic-px) );
    max-width: none;
    height: calc( 252 * var(--ds-hero-graphic-px) );
    border-radius: calc( 24 * var(--ds-hero-graphic-px) ) calc( 24 * var(--ds-hero-graphic-px) ) 0 0;

    object-fit: cover;
}

.ds-hero-graphic__lesson__play {
    position: absolute;
    top: 50%;
    left: calc( 50% + 0.39 * var(--ds-hero-graphic-px) );

    display: flex;
    align-items: center;
    justify-content: center;

    width: calc( 80 * var(--ds-hero-graphic-px) );
    height: calc( 80 * var(--ds-hero-graphic-px) );
    border-radius: 50%;

    background-color: rgba(255, 255, 255, 0.32);

    transform: translate( -50%, -50% );
}

.ds-hero-graphic__lesson__play__icon {
    display: block;

    width: calc( 47 * var(--ds-hero-graphic-px) );
    max-width: none;
    height: calc( 42 * var(--ds-hero-graphic-px) );
}

/* Text
   -------------------------------------------------- */

/* Selected through .ds-hero-graphic so the margin reset outranks the theme's
   own margins. */
.ds-hero-graphic .ds-hero-graphic__text {
    margin: 0;
}

/* Every line is trimmed to its cap height and baseline, as it is in the design,
   so the gaps and paddings around it come out as drawn. */
.ds-hero-graphic__text {
    display: block;

    color: var(--color-1);

    font-size: calc( 12 * var(--ds-hero-graphic-px) );
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    white-space: nowrap;

    text-box: trim-both cap alphabetic;
}

.ds-hero-graphic__module__number {
    font-size: calc( 16 * var(--ds-hero-graphic-px) );
}

.ds-hero-graphic__module__name {
    font-size: calc( 28 * var(--ds-hero-graphic-px) );
}

.ds-hero-graphic__next__label {
    font-size: calc( 20 * var(--ds-hero-graphic-px) );
}

.ds-hero-graphic__lesson__badge__label {
    line-height: 1;
}

.ds-hero-graphic__lesson__title {
    width: calc( 160 * var(--ds-hero-graphic-px) );

    color: var(--color-6);

    font-size: calc( 16 * var(--ds-hero-graphic-px) );
    line-height: 1;
    white-space: normal;
}

.ds-hero-graphic__lesson__author {
    width: calc( 125 * var(--ds-hero-graphic-px) );

    color: var(--color-6);

    font-weight: 510;
    line-height: 1.2;
    white-space: normal;
}

/* Where text cannot be trimmed, the lines are pulled in by the room the
   trimming would have taken off, so the gaps come out as designed. */
@supports not ( text-box: trim-both cap alphabetic ) {
    .ds-hero-graphic .ds-hero-graphic__text {
        margin-block: calc( ( var(--ds-hero-graphic-cap-height) - 1lh ) / 2 );
    }
}

/* --------------------------------------------------
   Newsletter signup graphic element
   -------------------------------------------------- */

/* The kickstarter pack in front of two lessons fanned out behind it, drawn at
   the design's 625 by 479 pixels and scaled as a whole to the width it is
   given, the way the hero graphic is. Every length inside is a count of design
   pixels times --ds-newsletter-signup-graphic-px, one design pixel at the
   current width, so the type, radii, gaps and borders all keep their
   proportions. The cqi in it measures the stage, the size container below.
   The cards are the theme's flat ds-sc-bg-N colors and the check discs its
   ds-bg-gd-6, so nothing here sets a background. */
.ds-newsletter-signup-graphic {
    --ds-newsletter-signup-graphic-px: calc( 100cqi / 625 );

    /* Geomanist's cap height, for the browsers that cannot trim text to it */
    --ds-newsletter-signup-graphic-cap-height: 0.72em;

    position: relative;

    display: block;
    width: 100%;

    font-family: "Geomanist", var(--main-font), sans-serif;

    /* It stands in for a picture, so nothing in it can be selected, copied,
       dragged or long-pressed: pointers pass through it to the page. */
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    pointer-events: none;
}

/* The canvas is never drawn on, it only gives the element an image's natural
   size: it fills a container that sets a width, shows at 625px in one that
   sizes to its content, and its height always follows the width. */
.ds-newsletter-signup-graphic__sizer {
    display: block;

    width: 100%;
    height: auto;
}

/* Laid over the canvas at its exact size. It is the size container rather than
   the wrapper, since a container cannot be sized by its content and the
   wrapper needs the canvas to size it. */
.ds-newsletter-signup-graphic__stage {
    position: absolute;
    inset: 0;

    container-type: inline-size;
}

/* The cards
   -------------------------------------------------- */

/* Every card is the front card's layout, placed by its center and measured in
   --ds-newsletter-signup-graphic-card-px. The two behind are the same card
   drawn at 288.203 design pixels wide instead of 404, which is all that unit
   changes, and turned 20 degrees. */
.ds-newsletter-signup-graphic__card {
    --ds-newsletter-signup-graphic-card-px: var(--ds-newsletter-signup-graphic-px);
    --ds-newsletter-signup-graphic-accent: var(--color-3);

    position: absolute;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: calc( 32 * var(--ds-newsletter-signup-graphic-card-px) );

    box-sizing: border-box;
    width: calc( 404 * var(--ds-newsletter-signup-graphic-card-px) );
    min-height: calc( 478 * var(--ds-newsletter-signup-graphic-card-px) );
    padding: calc( 64 * var(--ds-newsletter-signup-graphic-card-px) ) calc( 48 * var(--ds-newsletter-signup-graphic-card-px) );
    border-radius: calc( 24 * var(--ds-newsletter-signup-graphic-card-px) );

    translate: -50% -50%;
}

.ds-newsletter-signup-graphic__card--main {
    top: calc( 240 * var(--ds-newsletter-signup-graphic-px) );
    left: calc( 312.05 * var(--ds-newsletter-signup-graphic-px) );

    justify-content: center;
}

.ds-newsletter-signup-graphic__card--left,
.ds-newsletter-signup-graphic__card--right {
    --ds-newsletter-signup-graphic-card-px: calc( var(--ds-newsletter-signup-graphic-px) * 288.203 / 404 );

    top: calc( 239.5 * var(--ds-newsletter-signup-graphic-px) );
}

.ds-newsletter-signup-graphic__card--left {
    left: calc( 193.72 * var(--ds-newsletter-signup-graphic-px) );

    rotate: -20deg;
}

.ds-newsletter-signup-graphic__card--right {
    left: calc( 431.17 * var(--ds-newsletter-signup-graphic-px) );

    rotate: 20deg;
}

/* The card's color, so the check marks are drawn in the same color the card
   is. */
.ds-newsletter-signup-graphic__card--color-1 {
    --ds-newsletter-signup-graphic-accent: var(--color-1);
}

.ds-newsletter-signup-graphic__card--color-2 {
    --ds-newsletter-signup-graphic-accent: var(--color-2);
}

.ds-newsletter-signup-graphic__card--color-3 {
    --ds-newsletter-signup-graphic-accent: var(--color-3);
}

/* The list
   -------------------------------------------------- */

/* Selected through .ds-newsletter-signup-graphic so the list resets outrank
   the theme's own. */
.ds-newsletter-signup-graphic .ds-newsletter-signup-graphic__list {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: calc( 24 * var(--ds-newsletter-signup-graphic-card-px) );

    margin: 0;
    padding: 0;

    list-style: none;
}

.ds-newsletter-signup-graphic .ds-newsletter-signup-graphic__item {
    display: flex;
    align-items: center;
    gap: calc( 12 * var(--ds-newsletter-signup-graphic-card-px) );

    margin: 0;
    padding: 0;
}

/* The cream disc is the theme's ds-bg-gd-6, whose gradient border shows in the
   border set here, twice as thick at the bottom as at the sides. The padding
   on top makes up the difference, so the check is centered on the whole disc
   rather than on the room inside the border, which sits higher. */
.ds-newsletter-signup-graphic__item__icon {
    flex: 0 0 auto;

    display: flex;
    align-items: center;
    justify-content: center;

    box-sizing: border-box;
    width: calc( 24 * var(--ds-newsletter-signup-graphic-card-px) );
    height: calc( 24 * var(--ds-newsletter-signup-graphic-card-px) );
    border-style: solid;
    padding: calc( 0.75 * var(--ds-newsletter-signup-graphic-card-px) ) 0 0;
    border-width: calc( 0.75 * var(--ds-newsletter-signup-graphic-card-px) ) calc( 0.75 * var(--ds-newsletter-signup-graphic-card-px) ) calc( 1.5 * var(--ds-newsletter-signup-graphic-card-px) );
    border-radius: 50%;

    color: var(--ds-newsletter-signup-graphic-accent);
}

.ds-newsletter-signup-graphic__item__check {
    display: block;

    width: calc( 12 * var(--ds-newsletter-signup-graphic-card-px) );
    max-width: none;
    height: calc( 9 * var(--ds-newsletter-signup-graphic-card-px) );

    overflow: visible;
}

.ds-newsletter-signup-graphic__item__check path {
    stroke: currentColor;
}

/* Text
   -------------------------------------------------- */

/* Selected through .ds-newsletter-signup-graphic so the margin reset outranks
   the theme's own margins. */
.ds-newsletter-signup-graphic .ds-newsletter-signup-graphic__text {
    margin: 0;
}

/* Every line is trimmed to its cap height and baseline, as it is in the design,
   so the gaps and paddings around it come out as drawn. The copy comes from
   the attributes, so the lines are balanced rather than broken by hand. */
.ds-newsletter-signup-graphic__text {
    display: block;

    color: var(--color-6);

    font-size: calc( 20 * var(--ds-newsletter-signup-graphic-card-px) );
    font-weight: 500;
    line-height: 1.28;
    letter-spacing: -0.03em;
    overflow-wrap: break-word;
    text-wrap: balance;

    text-box: trim-both cap alphabetic;
}

/* It runs the full width of the card. The design's 260 pixels were measured
   against a tighter letter-spacing, and at the wider one the front title
   would break into four lines instead of three. The lines are balanced, so
   they still come out even. */
.ds-newsletter-signup-graphic__title {
    width: 100%;

    font-size: calc( 32 * var(--ds-newsletter-signup-graphic-card-px) );
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.02em;
    text-align: center;
}

.ds-newsletter-signup-graphic__item__text {
    max-width: calc( 272 * var(--ds-newsletter-signup-graphic-card-px) );
}

/* Where text cannot be trimmed, the lines are pulled in by the room the
   trimming would have taken off, so the gaps come out as designed. */
@supports not ( text-box: trim-both cap alphabetic ) {
    .ds-newsletter-signup-graphic .ds-newsletter-signup-graphic__text {
        margin-block: calc( ( var(--ds-newsletter-signup-graphic-cap-height) - 1lh ) / 2 );
    }
}

/* --------------------------------------------------
   Blog last updated
   -------------------------------------------------- */

/* The line is a body text, so its type comes from the body text styles. Only
   the date is set apart from it. */
.ds-blog-last-updated .ds-blog-last-updated__date {
    font-weight: 700;
}

/* --------------------------------------------------
   Blog reading time
   -------------------------------------------------- */

/* The line is a body text, so its type comes from the body text styles. Only
   the reading time is set apart from it. */
.ds-blog-reading-time .ds-blog-reading-time__time {
    font-weight: 700;
}

/* --------------------------------------------------
   Reference list
   -------------------------------------------------- */

.ds-reference-list {
    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-400);
    justify-content: flex-start;
    align-items: flex-start;
}

/* The numbers are drawn as body text rather than as list markers, so they
   take the size the text has. The items share the list's two columns, which
   keeps the text of 9 and 10 starting in the same place. */
.ds-reference-list .ds-reference-list__list {
    display: grid;
    grid-template-columns: auto minmax( 0, 1fr );
    column-gap: 0.5em;
    row-gap: var(--el-spacing-250);

    margin: 0;
    padding: 0;

    list-style: none;
}

/* A link to a reference stops short of a header stuck to the top of the
   window. This is only the fallback while the reference list script has not
   run: the script measures the header and writes the real margin onto each
   item. */
.ds-reference-list .ds-reference-list__item {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;

    scroll-margin-top: var(--ds-reference-list-scroll-offset, 24px);
}

/* The highlight a reference gets once the page has come to rest on it after a
   citation was followed: its text blinks twice, fading to half see-through
   and back each time.
   Opacity rather than color, since the color is set on the body text inside
   the item, and this way the number, the text and the links fade together
   while keeping their own colors. */
.ds-reference-list .ds-reference-list__item--highlighted {
    animation: ds-reference-list-highlight 0.6s ease-in-out 2;
}

@keyframes ds-reference-list-highlight {
    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.4;
    }
}

/* The item gets focus when a citation is followed, which the tint already
   shows, so no outline is drawn around it. */
.ds-reference-list .ds-reference-list__item:focus {
    outline: none;
}

.ds-reference-list .ds-reference-list__number {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* A long web address breaks rather than running out of the column. */
.ds-reference-list .ds-reference-list__text {
    overflow-wrap: anywhere;
}

.ds-reference-list .ds-reference-list__text > :first-child {
    margin-block-start: 0;
}

.ds-reference-list .ds-reference-list__text > :last-child {
    margin-block-end: 0;
}

/* --------------------------------------------------
   Ref
   -------------------------------------------------- */

/* A raised number would otherwise push the line it sits in further from the
   one above it. The links take the body text link style from the Animated
   underline section. */
.ds-ref {
    line-height: 0;

    padding-inline: 0.25em;
}

/* The number takes the color of the text it is cited in, over any color the
   theme or an Elementor widget gives links. The underline is drawn in
   currentColor, so it follows. */
.ds-ref,
.ds-ref .ds-ref__link {
    color: inherit;

    font-weight: 800 !important;
}

/* A raised number is small, so the line sits closer under it than under a
   body text link. Declared after the Animated underline section, which sets
   the same property with the same weight, so this one wins. */
.ds-ref .ds-ref__link {
    --ds-underline-offset: 0em;
}

/* --------------------------------------------------
   Blog posts archive element
   -------------------------------------------------- */

.ds-blog-posts-archive {
    --ds-blog-posts-archive-gap: var(--el-spacing-400);

    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-500);

    width: 100%;

    font-family: var(--main-font);
}

.ds-blog-posts-archive__grid {
    display: grid;
    grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    gap: var(--ds-blog-posts-archive-gap);
}

/* The fill is the theme's .ds-sc-bg-* class on the card, picked by the post's
   position. The category, the title and the button keep the looks of their
   own elements, this only lays them out. */
.ds-blog-posts-archive__card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    gap: var(--el-spacing-700);

    min-height: 23.75rem;
    padding: var(--el-spacing-500);

    border-radius: var(--el-border-radius-600);
    overflow: hidden;
}

.ds-blog-posts-archive__main {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--el-spacing-400);

    width: 100%;
    max-width: 30rem;

    overflow-wrap: break-word;
}

/* The title looks the way headings do everywhere, except for its line height.
   Two classes, like the heading's own rule, and later in the file, so the line
   height here is the one that applies. */
.ds-blog-posts-archive .ds-blog-posts-archive__heading {
    line-height: var(--heading-line-height-500);

    text-align: center;
}

.ds-blog-posts-archive .ds-blog-posts-archive__cta {
    width: 100%;
}

.ds-blog-posts-archive .ds-blog-posts-archive__cta:focus-visible {
    outline: 2px solid var(--color-6);
    outline-offset: 3px;
}

/* The load more button
   -------------------------------------------------- */

.ds-blog-posts-archive__footer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--el-spacing-300);
}

.ds-blog-posts-archive__footer[hidden] {
    display: none;
}

/* The site's button, as a real button element with the browser's look taken
   off. The label and the loader share one cell so it keeps the label's width
   whichever is showing. */
.ds-blog-posts-archive .ds-blog-posts-archive__more {
    -webkit-appearance: none;
    appearance: none;

    display: grid;
    place-items: center;

    margin: 0;

    white-space: nowrap;
}

.ds-blog-posts-archive .ds-blog-posts-archive__more:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

.ds-blog-posts-archive--loading .ds-blog-posts-archive__more:disabled {
    cursor: progress;
}

.ds-blog-posts-archive__more__label,
.ds-blog-posts-archive__more__loader {
    grid-area: 1 / 1;
}

/* Hidden by its opacity rather than its visibility, which would take the
   button's accessible name away with it. */
.ds-blog-posts-archive__more__label {
    display: block;

    transition: opacity 200ms ease;
}

.ds-blog-posts-archive--loading .ds-blog-posts-archive__more__label {
    opacity: 0;
}

.ds-blog-posts-archive__more__loader {
    display: block;

    width: var(--ds-icon-size-350);
    height: var(--ds-icon-size-350);
    border: 3px solid rgba( 248, 247, 243, 0.32 );
    border-top-color: currentColor;
    border-radius: 50%;

    opacity: 0;
}

.ds-blog-posts-archive--loading .ds-blog-posts-archive__more__loader {
    opacity: 1;

    animation: ds-blog-posts-archive-spin 0.8s linear infinite;
}

@keyframes ds-blog-posts-archive-spin {
    to {
        transform: rotate( 360deg );
    }
}

.ds-blog-posts-archive .ds-blog-posts-archive__error:empty {
    display: none;
}

@media ( max-width: 767px ) {
    .ds-blog-posts-archive__grid {
        grid-template-columns: minmax( 0, 1fr );
    }

    .ds-blog-posts-archive__card {
        min-height: 0;
        padding: var(--el-spacing-400) var(--el-spacing-350);
    }
}

@media ( prefers-reduced-motion: reduce ) {
    .ds-blog-posts-archive__more__label {
        transition: none;
    }

    .ds-blog-posts-archive--loading .ds-blog-posts-archive__more__loader {
        animation: ds-signup-form-pulse 1.6s ease-in-out infinite;
    }
}

/* --------------------------------------------------
   Team members element
   -------------------------------------------------- */

.ds-team-members {
    /* How wide the pictures are, fluid like the sizes at the top: 200px on a
       phone, 144px on a tablet and 256px, the design's, on desktop. */
    --ds-team-members-photo-size: calc(clamp(144px, 253.44px - 14.249vw, 200px) + clamp(144px, 5.71px + 18.006vw, 256px) - 144px); /* 200px / 144px / 256px */

    display: grid;
    grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
    gap: var(--el-spacing-550) var(--el-spacing-600);

    margin: 0;
    padding: 0;

    list-style: none;
    font-family: var(--main-font);
}

/* The small element: pictures a step down from the default ones on a tablet
   and desktop, in a thinner ring. On a phone they are the same 200px at either
   size. The name and the text take smaller steps from the markup. */
.ds-team-members.ds-team-members--size-small {
    --ds-team-members-photo-size: calc(clamp(112px, 283.97px - 22.392vw, 200px) + clamp(112px, 13.22px + 12.862vw, 192px) - 112px); /* 200px / 112px / 192px */
}

.ds-team-members--size-small .ds-team-members__photo {
    --ds-border-gd-width: calc(clamp(2.33px, 5.93px - 0.468vw, 4.17px) + clamp(2.33px, 0.28px + 0.268vw, 4px) - 2.33px); /* 4.17px / 2.33px / 4px */
}

/* Every part of a member is left out when it has nothing to show, so the gap
   is the only space between them and an empty part leaves none behind. The
   name, the text and the button keep the looks of their own elements, this
   only lays them out. */
.ds-team-members__member {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--el-spacing-300);

    min-width: 0;
    margin: 0;

    text-align: center;
    overflow-wrap: break-word;
}

/* The ring is the theme's .ds-border-gd-1 class, which only takes its width
   from here, fluid with the picture so it stays the same share of it at every
   width: 6px around the 256px desktop picture, 4px around the small 192px one.
   It is drawn just outside the padding box, so the circle is not clipped with
   overflow, the image rounds itself instead. */
.ds-team-members__photo {
    --ds-border-gd-width: calc(clamp(3.38px, 5.94px - 0.333vw, 4.69px) + clamp(3.38px, 0.15px + 0.421vw, 6px) - 3.38px); /* 4.69px / 3.38px / 6px */

    box-sizing: border-box;

    width: var(--ds-team-members-photo-size);
    max-width: 100%;
    aspect-ratio: 1;

    border-radius: 50%;
}

/* Doubled up against the theme's own img rules. The image keeps itself square:
   nothing clips the container any more, so a portrait photo would otherwise
   stretch it into an oval. */
.ds-team-members .ds-team-members__photo__image {
    display: block;

    width: 100%;
    max-width: none;
    height: auto;
    aspect-ratio: 1;

    border-radius: 50%;
    object-fit: cover;
}

.ds-team-members .ds-team-members__name,
.ds-team-members .ds-team-members__details > .ds-body-text {
    margin: 0;
}

.ds-team-members__details {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.ds-team-members .ds-team-members__cta:focus-visible {
    outline: 2px solid var(--color-1);
    outline-offset: 3px;
}

@media ( max-width: 1024px ) {
    .ds-team-members {
        grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
        column-gap: var(--el-spacing-400);
    }
}

@media ( max-width: 767px ) {
    .ds-team-members {
        grid-template-columns: minmax( 0, 1fr );
        row-gap: var(--el-spacing-500);
    }
}

/* --------------------------------------------------
   YouTube stats element
   -------------------------------------------------- */

/* The size, weight and color come from the Body text classes on the line. */
.ds-youtube-stats {
    margin: 0;
}

/* A stat never breaks between its count and its label, only at the
   separator. */
.ds-youtube-stats__stat {
    white-space: nowrap;
}

/* The K, M and B of a shortened count keep the capitals the design gives them.
   The count carries no lowercase class, and this wins over the one the line
   passes down. */
.ds-youtube-stats__count {
    text-transform: uppercase;
}

/* --------------------------------------------------
   Download app QR code element
   -------------------------------------------------- */

/* The fill and the border's gradient are the theme's .ds-bg-gd-1-t2 class,
   which only takes the border's width and style from here. The design's
   border is heavier along the bottom. */
.ds-download-app-qr-code {
    position: relative;
    display: flex;
    box-sizing: border-box;
    width: var(--ds-el-size-900);
    height: var(--ds-el-size-900);

    border-style: solid;
    border-width: 2px 2px 4px;
    border-radius: var(--el-border-radius-300);
}

.ds-download-app-qr-code__code {
    display: flex;
    flex: 1 0 0;
    min-width: 0;
    padding: 0.48rem;
    overflow: hidden;
}

.ds-download-app-qr-code__image {
    display: block;
    width: 100%;
    height: 100%;
}

/* The export fills every module with its own color, which the theme's color
   replaces. The rects the export clips with are never painted. */
.ds-download-app-qr-code__image path {
    fill: var(--color-6);
}

/* The logomark on a cream disc, over the middle of the code. */
.ds-download-app-qr-code__logo {
    position: absolute;
    top: 50%;
    left: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: calc( var(--ds-el-size-900) * 0.25 );
    height: calc( var(--ds-el-size-900) * 0.25 );
    padding: calc( var(--ds-el-size-900) * 0.032 );
    
    background: var(--color-6);
    border-radius: calc( var(--ds-el-size-900) * 0.075 );
    transform: translate(-50%, -50%);
}

.ds-download-app-qr-code__logo__icon {
    display: block;
    width: 100%;
    height: 100%;
}

/* The code and the button that stands in for it on a phone. The element
   prints both and the device class on the html element, which its script in
   the head sets, decides which of the two is seen: a page cache serves one
   visitor's copy of a page to everyone after them, so the choice cannot be
   made while the page is built.

   The code is what shows until that class is there, so a browser running no
   script is shown what the element always showed. The button names .ds-button
   alongside its own class so that hiding it does not rest on this rule
   sitting after the display .ds-button sets, and the phone's rule is the
   later of the two selectors that then tie. */
.ds-device-mobile .ds-download-app-qr-code {
    display: none;
}

.ds-button.ds-download-app-button {
    display: none;
}

.ds-device-mobile .ds-download-app-button {
    display: inline-flex;
}

/* --------------------------------------------------
   Custom nav menu element
   -------------------------------------------------- */

.ds-custom-nav-menu .ds-custom-nav-menu__list {
    display: flex;
    flex-direction: column;
    gap: var(--el-spacing-350, 1.5rem);

    margin: 0;
    padding: 0;
    list-style: none;
}

.ds-custom-nav-menu--horizontal .ds-custom-nav-menu__list {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--el-spacing-250, 1rem);
}

.ds-custom-nav-menu .ds-custom-nav-menu__item {
    margin: 0;
}

/* Selected through .ds-custom-nav-menu so the rule outranks the link colors of
   the Elementor kit. The title and the badge beside it, when there is one,
   sit in a row. */
.ds-custom-nav-menu .ds-custom-nav-menu__link {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;

    text-decoration: none;
}

/* The items' color, picked by the item_color attribute. 1 is the default. */
.ds-custom-nav-menu--color-1 .ds-custom-nav-menu__link {
    color: var(--color-1);
}

.ds-custom-nav-menu--color-2 .ds-custom-nav-menu__link {
    color: var(--color-2);
}

.ds-custom-nav-menu--color-3 .ds-custom-nav-menu__link {
    color: var(--color-3);
}

.ds-custom-nav-menu--color-4 .ds-custom-nav-menu__link {
    color: var(--color-4);
}

.ds-custom-nav-menu--color-5 .ds-custom-nav-menu__link {
    color: var(--color-5);
}

.ds-custom-nav-menu--color-6 .ds-custom-nav-menu__link {
    color: var(--color-6);
}

/* The item's title. The size comes from its font size step class below. */
.ds-custom-nav-menu__text {
    font-family: var(--main-font);
    font-weight: 700;
    line-height: 1em;
    letter-spacing: -0.02em;
}

/* The item's Additional Text, as a pill. The fill is the theme's ds-sc-bg-N
   class, picked by the color chosen for the item. */
.ds-custom-nav-menu .ds-custom-nav-menu__additional-text {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;

    padding: var(--el-spacing-150) var(--el-padding-200);
    border-radius: 999px;
}

.ds-custom-nav-menu .ds-custom-nav-menu__additional-text__text {
    display: block;

    line-height: 1;
    white-space: nowrap;
}

/* Down the page the badge hangs off the right of the title rather than taking
   room beside it, so the title itself is what is centered. Across the page it
   keeps its room beside the title, so it never runs into the next item. */
.ds-custom-nav-menu--vertical .ds-custom-nav-menu__link {
    position: relative;
}

.ds-custom-nav-menu--vertical .ds-custom-nav-menu__additional-text {
    position: absolute;
    top: 50%;
    left: calc( 100% + var(--el-spacing-200) );

    transform: translateY( -50% );
}

/* Font size steps off the nav menu type scale. 400 is the default. */
.ds-custom-nav-menu__text--100 {
    font-size: var(--nav-menu-100);
}

.ds-custom-nav-menu__text--150 {
    font-size: var(--nav-menu-150);
}

.ds-custom-nav-menu__text--175 {
    font-size: var(--nav-menu-175);
}

.ds-custom-nav-menu__text--200 {
    font-size: var(--nav-menu-200);
}

.ds-custom-nav-menu__text--300 {
    font-size: var(--nav-menu-300);
}

.ds-custom-nav-menu__text--400 {
    font-size: var(--nav-menu-400);
}

.ds-custom-nav-menu__text--500 {
    font-size: var(--nav-menu-500);
}

.ds-custom-nav-menu__text--600 {
    font-size: var(--nav-menu-600);
}

.ds-custom-nav-menu__text--700 {
    font-size: var(--nav-menu-700);
}

.ds-custom-nav-menu__text--800 {
    font-size: var(--nav-menu-800);
}

/* On phones the items down the page are centered on their titles, and a title
   that wraps is centered line by line. */
@media ( max-width: 767px ) {
    .ds-custom-nav-menu--vertical .ds-custom-nav-menu__list {
        align-items: center;

        text-align: center;
    }
}

/* --------------------------------------------------
   App features graphic element
   -------------------------------------------------- */

/* A part of the app on a colored card, drawn at the design's 405 by 289
   pixels and scaled as a whole to the width it is given, the way the hero
   graphic is. Every length inside is a count of design pixels times
   --ds-app-features-graphic-px, one design pixel at the current width, so the
   type, radii, gaps, borders and icons all keep their proportions. The cqi in
   it measures the stage, the size container below. */
.ds-app-features-graphic {
    --ds-app-features-graphic-px: calc( 100cqi / 405 );

    /* SF Pro's cap height, for the browsers that cannot trim text to it */
    --ds-app-features-graphic-cap-height: 0.7046em;

    position: relative;

    display: block;
    width: 100%;

    font-family: "SF Pro", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

    /* The text is set the way the design draws it, capitals included, whatever
       the widget or the text around the element is set to. */
    font-style: normal;
    text-align: left;
    text-transform: none;
    word-spacing: normal;

    /* It stands in for a picture, so nothing in it can be selected, copied,
       dragged or long-pressed: pointers pass through it to the page. */
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    pointer-events: none;
}

/* The canvas is never drawn on, it only gives the element an image's natural
   size: it fills a container that sets a width, shows at 405px in one that
   sizes to its content, and its height always follows the width. */
.ds-app-features-graphic__sizer {
    display: block;

    width: 100%;
    height: auto;
}

/* Laid over the canvas at its exact size. It is the size container rather than
   the wrapper, since a container cannot be sized by its content and the
   wrapper needs the canvas to size it. */
.ds-app-features-graphic__stage {
    position: absolute;
    inset: 0;

    container-type: inline-size;
}

/* The card
   -------------------------------------------------- */

/* The color and its grain come from the theme's .ds-sc-bg-N on the same
   element, so nothing here sets a background. What is on the card is placed
   against it and cut off at its edges. */
.ds-app-features-graphic__card {
    --ds-app-features-graphic-accent: var(--color-2);

    position: absolute;
    inset: 0;

    border-radius: calc( 24 * var(--ds-app-features-graphic-px) );

    overflow: hidden;
}

/* The card's color, so the text, borders and fills on it are drawn in the
   same color the card is. */
.ds-app-features-graphic__card--color-2 {
    --ds-app-features-graphic-accent: var(--color-2);
}

.ds-app-features-graphic__card--color-3 {
    --ds-app-features-graphic-accent: var(--color-3);
}

.ds-app-features-graphic__card--color-4 {
    --ds-app-features-graphic-accent: var(--color-4);
}

/* Type 1: the modules
   -------------------------------------------------- */

.ds-app-features-graphic__modules {
    position: absolute;
    inset: 0;

    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: calc( 20 * var(--ds-app-features-graphic-px) );
}

/* The modules either side of the one that is picked are smaller, and the card
   shows through them. They are drawn at one width, so they match whatever
   their labels are, while the picked one is as wide as its label. */
.ds-app-features-graphic__module {
    display: flex;
    align-items: center;
    justify-content: center;

    width: calc( 210 * var(--ds-app-features-graphic-px) );
    padding: calc( 13.333 * var(--ds-app-features-graphic-px) );
    border-radius: calc( 999 * var(--ds-app-features-graphic-px) );

    background-color: var(--color-6);
    opacity: 0.64;
}

.ds-app-features-graphic__module--current {
    width: auto;
    padding: calc( 18 * var(--ds-app-features-graphic-px) );

    opacity: 1;
}

/* Type 2: the practices
   -------------------------------------------------- */

/* The phone rises from the bottom edge of the card, which cuts it off. */
.ds-app-features-graphic__phone {
    position: absolute;
    top: calc( 48 * var(--ds-app-features-graphic-px) );
    right: calc( 48 * var(--ds-app-features-graphic-px) );
    bottom: 0;
    left: calc( 48 * var(--ds-app-features-graphic-px) );

    display: flex;
    flex-direction: column;
    gap: calc( 16 * var(--ds-app-features-graphic-px) );

    padding: calc( 24 * var(--ds-app-features-graphic-px) );
    border-radius: calc( 24 * var(--ds-app-features-graphic-px) ) calc( 24 * var(--ds-app-features-graphic-px) ) 0 0;

    background-color: var(--color-6);

    overflow: hidden;
}

.ds-app-features-graphic__section {
    display: flex;
    flex-direction: column;
    gap: calc( 10 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__section__list {
    display: flex;
    flex-direction: column;
    gap: calc( 12 * var(--ds-app-features-graphic-px) );
}

/* The design draws the border inside the padding, where CSS adds it outside,
   so the padding here is the design's less the border and the practice comes
   out as tall as it is drawn. */
.ds-app-features-graphic__practice {
    display: flex;
    align-items: center;
    justify-content: space-between;

    padding: calc( 8 * var(--ds-app-features-graphic-px) ) calc( 8 * var(--ds-app-features-graphic-px) ) calc( 8 * var(--ds-app-features-graphic-px) ) calc( 18 * var(--ds-app-features-graphic-px) );
    border: calc( 2 * var(--ds-app-features-graphic-px) ) solid var(--ds-app-features-graphic-accent);
    border-radius: calc( 999 * var(--ds-app-features-graphic-px) );

    color: var(--ds-app-features-graphic-accent);
}

.ds-app-features-graphic__practice--completed {
    background-color: var(--ds-app-features-graphic-accent);
}

.ds-app-features-graphic__practice__badge {
    flex: 0 0 auto;

    display: flex;
    align-items: center;
    justify-content: center;
    gap: calc( 2 * var(--ds-app-features-graphic-px) );

    height: calc( 22 * var(--ds-app-features-graphic-px) );
    padding: 0 calc( 6 * var(--ds-app-features-graphic-px) );
    border-radius: calc( 999 * var(--ds-app-features-graphic-px) );

    background-color: var(--color-6);
    color: var(--ds-app-features-graphic-accent);
}

/* Type 3: the comment
   -------------------------------------------------- */

.ds-app-features-graphic__post {
    position: absolute;
    inset: calc( 48 * var(--ds-app-features-graphic-px) );

    display: flex;
    flex-direction: column;
    gap: calc( 10 * var(--ds-app-features-graphic-px) );

    padding: calc( 24 * var(--ds-app-features-graphic-px) );
    border-radius: calc( 24 * var(--ds-app-features-graphic-px) );

    background-color: var(--color-6);

    overflow: hidden;
}

/* It takes the height the field under it leaves, and the likes are placed at
   the bottom of that. */
.ds-app-features-graphic__message {
    flex: 1 1 0;

    display: flex;
    gap: calc( 16 * var(--ds-app-features-graphic-px) );

    min-height: 0;
}

/* Selected through .ds-app-features-graphic so the radius and height outrank
   Elementor's .elementor img rule, which sets them to 0 and auto. */
.ds-app-features-graphic .ds-app-features-graphic__message__avatar {
    flex: 0 0 auto;
    align-self: flex-start;

    display: block;

    width: calc( 40 * var(--ds-app-features-graphic-px) );
    max-width: none;
    height: calc( 40 * var(--ds-app-features-graphic-px) );
    border-radius: 50%;

    object-fit: cover;
}

/* Positioned, so the likes are placed against it. */
.ds-app-features-graphic__message__body {
    position: relative;

    flex: 1 1 0;

    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: calc( 16 * var(--ds-app-features-graphic-px) );

    min-width: 0;
}

.ds-app-features-graphic__message__header {
    display: flex;
    align-items: center;
    gap: calc( 8 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__message__likes {
    position: absolute;
    right: 0;
    bottom: 0;

    display: flex;
    align-items: center;
    justify-content: center;
    gap: calc( 2 * var(--ds-app-features-graphic-px) );

    padding: calc( 6 * var(--ds-app-features-graphic-px) ) calc( 8 * var(--ds-app-features-graphic-px) );
    border-radius: calc( 999 * var(--ds-app-features-graphic-px) );

    background-color: var(--ds-app-features-graphic-accent);
    color: var(--color-6);
}

/* The field's border is drawn inside the design's padding as well, like the
   practices' borders. */
.ds-app-features-graphic__reply {
    display: flex;
    align-items: center;

    padding: calc( 14 * var(--ds-app-features-graphic-px) );
    border: calc( 2 * var(--ds-app-features-graphic-px) ) solid var(--ds-app-features-graphic-accent);
    border-radius: calc( 999 * var(--ds-app-features-graphic-px) );
}

/* Icons
   -------------------------------------------------- */

.ds-app-features-graphic__practice__icon,
.ds-app-features-graphic__practice__badge__icon,
.ds-app-features-graphic__message__likes__icon {
    flex: 0 0 auto;

    display: block;

    max-width: none;
}

.ds-app-features-graphic__practice__icon {
    width: calc( 22 * var(--ds-app-features-graphic-px) );
    height: calc( 22 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__practice__badge__icon {
    width: calc( 12 * var(--ds-app-features-graphic-px) );
    height: calc( 9 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__message__likes__icon {
    width: calc( 12 * var(--ds-app-features-graphic-px) );
    height: calc( 11 * var(--ds-app-features-graphic-px) );
}

/* Every icon is drawn in the color of the text beside it. */
.ds-app-features-graphic__practice__icon path,
.ds-app-features-graphic__practice__badge__icon path {
    stroke: currentColor;
}

.ds-app-features-graphic__message__likes__icon path {
    fill: currentColor;
    stroke: currentColor;
}

/* Text
   -------------------------------------------------- */

/* Selected through .ds-app-features-graphic so the margin reset outranks the
   theme's own margins. */
.ds-app-features-graphic .ds-app-features-graphic__text {
    margin: 0;
}

/* Every line is trimmed to its cap height and baseline, as it is in the design,
   so the gaps and paddings around it come out as drawn. The weights are SF
   Pro's own: 860 is its heavy, 590 its semibold. */
.ds-app-features-graphic__text {
    display: block;

    color: var(--ds-app-features-graphic-accent);

    font-size: calc( 14 * var(--ds-app-features-graphic-px) );
    font-weight: 860;
    line-height: 1.1;
    letter-spacing: -0.02em;
    white-space: nowrap;

    text-box: trim-both cap alphabetic;
}

.ds-app-features-graphic__module__label {
    font-size: calc( 18.333 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__module--current .ds-app-features-graphic__module__label {
    font-size: calc( 24.75 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__section__title {
    font-size: calc( 12 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__practice--completed .ds-app-features-graphic__practice__label {
    color: var(--color-6);
}

.ds-app-features-graphic__practice__badge__label {
    font-size: calc( 10 * var(--ds-app-features-graphic-px) );
}

.ds-app-features-graphic__message__author {
    font-size: calc( 18 * var(--ds-app-features-graphic-px) );
}

/* The padding sets the time a little lower than the middle of the name. */
.ds-app-features-graphic__message__time {
    padding-top: calc( 2 * var(--ds-app-features-graphic-px) );

    font-size: calc( 12 * var(--ds-app-features-graphic-px) );
    font-weight: 590;
}

/* The lines are broken in the markup where the design breaks them. Left to
   wrap at the design's width, they would break differently at small sizes,
   where SF Pro spaces its letters wider, and in the fallback fonts. */
.ds-app-features-graphic__message__text {
    font-size: calc( 16 * var(--ds-app-features-graphic-px) );
    font-weight: 700;
    letter-spacing: -0.04em;
}

.ds-app-features-graphic__message__likes__count {
    color: var(--color-6);

    font-size: calc( 12 * var(--ds-app-features-graphic-px) );
    font-weight: 700;
}

.ds-app-features-graphic__reply__label {
    font-weight: 590;
}

/* Where text cannot be trimmed, the lines are pulled in by the room the
   trimming would have taken off, so the gaps come out as designed. */
@supports not ( text-box: trim-both cap alphabetic ) {
    .ds-app-features-graphic .ds-app-features-graphic__text {
        margin-block: calc( ( var(--ds-app-features-graphic-cap-height) - 1lh ) / 2 );
    }
}

/* --------------------------------------------------
   Mobile nav menu button element
   -------------------------------------------------- */

.ds-mobile-nav-menu-button {
    --ds-mobile-nav-menu-button-size: var(--ds-icon-size-480);

    position: relative;
    display: inline-flex;
    flex-shrink: 0;
    width: var(--ds-mobile-nav-menu-button-size);
    height: var(--ds-mobile-nav-menu-button-size);
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    color: inherit;

    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* Reaches the 44px a finger needs without making the icon any bigger or
   moving what sits next to it. */
.ds-mobile-nav-menu-button::before {
    content: "";
    position: absolute;
    inset: min( 0px, ( var(--ds-mobile-nav-menu-button-size) - 44px ) / 2 );
}

/* Themes give buttons a background on hover and focus. */
.ds-mobile-nav-menu-button:hover,
.ds-mobile-nav-menu-button:focus {
    background: none;
    color: inherit;
}

.ds-mobile-nav-menu-button:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 4px;
}

.ds-mobile-nav-menu-button__icon {
    display: block;
    width: 100%;
    height: 100%;
}

/* The icon shown is read off aria-expanded, the same attribute a screen
   reader announces the state from. */
.ds-mobile-nav-menu-button[aria-expanded="true"] .ds-mobile-nav-menu-button__icon--open,
.ds-mobile-nav-menu-button:not([aria-expanded="true"]) .ds-mobile-nav-menu-button__icon--close {
    display: none;
}

/* --------------------------------------------------
   Post authors element
   -------------------------------------------------- */

.ds-post-authors {
    --ds-post-authors-photo-size: 64px;

    /* how far each picture slides under the one before it */
    --ds-post-authors-photo-overlap: calc( var(--ds-post-authors-photo-size) * 0.3 );

    display: flex;
    align-items: center;
    gap: var(--el-spacing-250);
}

.ds-post-authors__photos {
    display: flex;
    flex: none;
    align-items: center;
}

/* The ring is the theme's ds-border-gd-<id> class, sized here to 3px. It is
   drawn just outside the padding box, so the circle is not clipped with
   overflow, the image rounds itself instead. */
.ds-post-authors__photo {
    --ds-border-gd-width: 3px;

    box-sizing: border-box;
    position: relative;

    width: var(--ds-post-authors-photo-size);
    aspect-ratio: 1;

    border-radius: 50%;
}

.ds-post-authors__photo + .ds-post-authors__photo {
    margin-inline-start: calc( var(--ds-post-authors-photo-overlap) * -1 );
}

/* Doubled up against the theme's own img rules. The image keeps itself square,
   so a portrait photo cannot stretch the circle into an oval. */
.ds-post-authors .ds-post-authors__photo__image {
    display: block;

    width: 100%;
    max-width: none;
    height: auto;
    aspect-ratio: 1;

    border-radius: 50%;
    object-fit: cover;
}

.ds-post-authors__text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
}

.ds-post-authors .ds-post-authors__label {
    margin: 0;
}

.ds-post-authors__list {
    display: flex;
    flex-wrap: wrap;
    column-gap: 0.3em;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ds-post-authors__author {
    margin: 0;
    padding: 0;
}

/* The name and the designation run on as one line of text. */
.ds-post-authors .ds-post-authors__author > .ds-body-text {
    display: inline;
    margin: 0;
}

/* --------------------------------------------------
   Author box element
   -------------------------------------------------- */

.ds-author-box {
    /* How wide the pictures are, in step with the text beside them, which is
       15px on a phone, 12px on a tablet and 18px on desktop: 53px on a phone,
       43px on a tablet and 64px, the design's, on desktop. */
    --ds-author-box-photo-size: calc(clamp(43px, 62.54px - 2.545vw, 53px) + clamp(43px, 17.07px + 3.376vw, 64px) - 43px); /* 53px / 43px / 64px */
}

/* One author, or one of several: the picture beside the text. */
.ds-author-box__author {
    display: flex;
    align-items: center;
    gap: var(--el-spacing-250);
    min-width: 0;
    margin: 0;
    padding: 0;
}

/* The ring is the theme's ds-border-gd-<id> class, 3px on desktop as on the
   post authors element's pictures, and thinner on smaller screens in step
   with the picture. It is drawn just outside the padding box, so the circle
   is not clipped with overflow, the image rounds itself instead. */
.ds-author-box__photo {
    --ds-border-gd-width: calc(clamp(2px, 2.98px - 0.127vw, 2.5px) + clamp(2px, 0.77px + 0.161vw, 3px) - 2px); /* 2.5px / 2px / 3px */

    box-sizing: border-box;
    flex: none;

    width: var(--ds-author-box-photo-size);
    aspect-ratio: 1;

    border-radius: 50%;
}

/* Doubled up against the theme's own img rules. The image keeps itself square,
   so a portrait photo cannot stretch the circle into an oval. */
.ds-author-box .ds-author-box__photo__image {
    display: block;

    width: 100%;
    max-width: none;
    height: auto;
    aspect-ratio: 1;

    border-radius: 50%;
    object-fit: cover;
}

.ds-author-box__text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    min-width: 0;
}

/* A single author's label sits a little further above their name than a
   name does above its designation. */
.ds-author-box--single .ds-author-box__text {
    gap: 0;
}

/* With several authors the designation is shown above the name. It still
   follows the name in the markup, so it is read after it. */
.ds-author-box--multiple .ds-author-box__text {
    flex-direction: column-reverse;
}

/* The text keeps its full line height, the way the post authors element
   sets it, which also leaves room under a name for its link's underline. */
.ds-author-box .ds-body-text {
    margin: 0;
    overflow-wrap: break-word;
}

/* Several authors: the label over them, the authors two to a row. Each
   column is as wide as its widest author, so the rows line up. */
.ds-author-box--multiple {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--el-spacing-300);
}

.ds-author-box__authors {
    display: grid;
    grid-template-columns: repeat( 2, minmax( 0, max-content ) );
    column-gap: var(--el-spacing-400);
    row-gap: var(--el-spacing-300);
    max-width: 100%;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* On a phone two authors side by side do not fit, so each takes a row. */
@media ( max-width: 767px ) {
    .ds-author-box__authors {
        grid-template-columns: minmax( 0, 1fr );
    }
}
