/* www.formuly.com: the redesigned site. Measurements are taken from the design
   files (desktop 1440, mobile 375); the layout scales between them.
   Type: Victor Serif for the serif lines, Special Gothic (variable, 95% width)
   for everything else. Colours are the brand palette, nothing else. */

/* Victor Serif ships as "50 Medium" and "55 Medium Italic": the weights the
   design is drawn in. The Regular pair is not served, so nothing asks for 400. */
@font-face {
    font-family: "Victor Serif";
    src: url("../font/VictorSerif-Medium.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Victor Serif";
    src: url("../font/VictorSerif-MediumItalic.woff2") format("woff2");
    font-weight: 500;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: "Special Gothic";
    src: url("../font/SpecialGothic-Variable.woff2") format("woff2");
    font-weight: 400 700;
    font-stretch: 75% 125%;
    font-display: swap;
}

:root {
    --phthalo: #00514a;
    --phthalo-bright: #008f82;
    --phthalo-deep: #00342f;
    --yellow: #e6ff02;
    --pastel-yellow: #f7ffb3;
    --electric-green: #bfe600;
    --white: #ffffff;
    --half-grey: #f0f2f3;
    --grey: #e1e6e8;
    --half-graphite: #212225;
    --graphite: #303338;
    --black: #111111;

    --serif: "Victor Serif", Georgia, "Times New Roman", serif;
    --sans: "Special Gothic", "Helvetica Neue", Arial, sans-serif;

    /* 20px at 375, 32px at 768, as the design has them. */
    --gutter: clamp(20px, 3.05vw + 8.6px, 52px);
    --content: 1280px;

    /* Page rhythm. Mobile values; the media queries below carry the design's own. */
    /* What the pill actually occupies, so the hero can be pulled up by exactly
       that much at every width. */
    --header-height: calc(var(--pill-top) + var(--pill-height));
    --hero-padding: 96px;
    --hero-lede-gap: 16px;
    --hero-lede-width: 34em;
    --pill-height: 48px;
    --pill-top: 12px;
    /* The design's own: the button sits 8px in from the pill's end on a phone
       and 12px on a desktop, and the wordmark 23px / 27px in from the other. */
    --pill-pad-end: 8px;
    --pill-pad-start: 23px;
    --pill-gap: 19px;
    --pill-logo: 28px;
    --founders-gap: 47px;
    --face-width: 56px;
    --face-height: 70px;
    --panel: #00625a;
    --panel-width: min(1080px, 100% - 2 * var(--gutter));
    --panel-padding: 12px;
    /* The closing card runs up onto the section above it at every width, as the
       design draws it; the hero card only runs down onto the white from 768px,
       where it is a card rather than the full width of the screen. */
    --panel-overlap: 56px;
    --hero-overlap: 0px;
    /* Capped by the screen's own height: on a short one the heading has to leave
       the stage something to pin. */
    --what-padding: min(96px, 14vh);
    --security-padding: 80px;
    /* How far the band runs on past the last pill: 144 at 375, 200 from 768 and
       216 at 1440, measured off the design's own vectors. The card then rises 56
       back into it, so what a visitor sees between the two is 88, 144 and 160. */
    --security-bottom: 144px;
    --security-lede-gap: 20px;
    --security-lede-width: 600px;
    --security-list-gap: 44px;
    --security-item-gap: 40px;
    --security-ring-gap: 22px;
    --ring-size: 80px;
    /* 18 and 16 at every width: the design does not step them at a breakpoint. */
    --assurance-title: 18px;
    --assurance-body: 16px;
    --assurance-copy-gap: 10px;
    /* Where the design puts the pill, measured from the ring's own top, which is
       a shape in both files and so the one datum that needs no ink threshold:
       94.9 below it on a phone, where the ring sits beside the words, and 198.9
       in a column. Ours were 88.4 and 196.4. */
    --assurance-status-gap: 19.5px;
    --closing-padding: 81px;
    --closing-lede-gap: 24px;
    --closing-lede-width: 34em;
    --closing-button-gap: 32px;

    --reel-intro-gap: 15px;

    /* Only what the section is until the script measures the list and sets this
       to a screen plus the opening, the closing, and the list's own length. */
    --reel-height: 450vh;

    --reel-size: 20px;
    /* The design's own: 25px between the lines of an item at 20px and 40px at
       32px, both 1.25. Between one item and the next it leaves 57px on a phone
       and 96px from 768, measured top to top, so the gap is what is left after
       the line: 32px and 56px. The wider spacing is what lets the list scroll at
       the speed of the page without running through the items too quickly. */
    --reel-leading: 1.25;
    --reel-gap: 32px;
    /* How tall the reading band may be: the fixed cap keeps zooming in from
       shrinking it (at 200% the viewport is half as tall, so a height-only value
       would get smaller as the visitor zoomed) and the vh keeps it inside the
       stage on a short screen. */
    --reel-band: min(430px, 46vh);

    /* Type scale: mobile values, overridden from 768px. The hero and the section
       headings are one size at every width, measured from the design's own cap
       heights: 38px at 375, 64px from 768 to 1024, 80px at 1440, and fluid
       between those points rather than stepping at the breakpoint. */
    --display-size: clamp(38px, calc(6.616vw + 13.19px), 64px);
    --display-leading: 1.12;
    --body-size: 16px;
    --body-leading: 24px;
    --small-size: 14px;

    /* Corner marker on framed boxes. */
    --footer-wordmark: 36px;
    --footer-link-gap: 12px;
    /* Every interactive change eases over this rather than snapping. */
    --ease: 200ms;

    --marker: 8px;
    --feature-count: 4;
}

/* Grain over the Phthalo surfaces, to make them tactile. `img/grain.png` is a
   256px tile of grey noise around mid grey, overlaid so mid grey leaves the
   colour alone and the deviations lighten and darken it. Its grain is one pixel
   and its deviation 6.2 levels, both measured off the design file: over the
   green that renders a deviation of 3.93 against the design's 3.93, with
   neighbouring pixels as independent there as they are in the file. A file
   rather than an SVG filter because browsers render feTurbulence differently
   from one another. The yellow is deliberately left flat, as drawn. */
.grain {
    position: relative;
}

.grain::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: url("../img/grain.png");
    background-size: 256px 256px;
    /* One noise sample per CSS pixel, as the design draws it. Without this a
       screen at device-pixel-ratio 2 resamples the tile up and smooths it:
       measured on this page, the deviation falls from 4.0 to 2.6 levels and
       neighbouring pixels go from independent (+0.04) to +0.76 correlated,
       which reads as a blurry enlargement rather than grain. */
    image-rendering: pixelated;
    mix-blend-mode: overlay;
}

/* Base */

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

html {
    /* The pill floats over the page, so an anchor has to stop below it. */
    scroll-padding-top: calc(var(--pill-top) + var(--pill-height) + 24px);
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* The panels' rays run out to the edges of the page, and nothing may scroll sideways. */
    overflow-x: hidden;
}

body {
    margin: 0;
    /* The straps run past the page on their way to its edges; clip rather than
       scroll to them. clip, not hidden, so it stays out of the way of sticky. */
    overflow: clip;
    font-family: var(--sans);
    font-stretch: 95%;
    font-size: var(--body-size);
    line-height: var(--body-leading);
    color: var(--black);
    background: var(--white);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* html carries overflow-x, so the viewport takes its overflow from html and a
   lock on body alone would not hold the page still under the dialog. */
html:has(dialog[open]) {
    overflow: hidden;
}

h1,
h2,
h3,
p {
    margin: 0;
}

a {
    color: inherit;
}

img,
svg {
    display: block;
}

[hidden] {
    display: none !important;
}

button {
    font: inherit;
    font-stretch: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
}

:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
}

/* The ring is drawn outside the control, so on the black pill and the black
   cookie banner a currentColor ring would be black on black: a keyboard had no
   visible focus on "Book a demo", "Home" or "Accept". */
.site-header__pill :focus-visible,
.cookie-banner :focus-visible {
    outline-color: var(--yellow);
}

/* On the green cards the ring lands on the panel, where black is under the 3:1
   a focus indicator needs. */
.panel :focus-visible {
    outline-color: var(--white);
}

.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 100;
    padding: 8px 16px;
    background: var(--black);
    color: var(--white);
    transform: translateY(-200%);
}

.skip-link:focus {
    transform: none;
}

.container {
    width: min(var(--content), 100% - 2 * var(--gutter));
    margin-inline: auto;
}

/* Type */

.display {
    font-size: var(--display-size);
    line-height: var(--display-leading);
    /* Medium on both faces, as the design is drawn: measured against this page's
       own renders, its headings carry the ink of 500 to within 1%, where 600 is
       10% heavier. The tracking is the design's too, on both faces: its glyphs
       are weight-500 wide but its lines are 4% shorter, and the whole difference
       sits in the gaps. */
    font-weight: 500;
    letter-spacing: -0.02em;
    /* A heading that has to wrap breaks its lines evenly rather than leaving a
       word on its own. The two drawn headings set their own lines and are
       unaffected. */
    text-wrap: balance;
}

.display .serif,
.serif {
    font-family: var(--serif);
    font-weight: 500;
}

/* A serif run inside a sans heading would otherwise push the line it sits on
   further from the one above: at the same line-height the two faces put their
   baselines in different places (Special Gothic is 101/30 above and below the
   baseline per 100px, Victor Serif 106/25), so the line box grows by the
   difference. Shrinking the run's own line box by that much puts it back inside
   the block's, and the heading keeps the leading it is given. The closing
   heading sets each line as its own block, so it is not affected. */
.display .serif:not(.line) {
    line-height: 0.96;
}

/* Each run of the heading is its own line, at every width. */
.display .line {
    display: block;
}

.lede {
    max-width: 36em;
}

.small {
    font-size: var(--small-size);
    line-height: 1.5;
}

/* Buttons and links */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 44px;
    padding: 0 24px;
    border-radius: 999px;
    background: var(--yellow);
    color: var(--black);
    font-weight: 500;
    font-size: 16px;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--ease) ease, color var(--ease) ease;
}

.button:hover {
    background: var(--electric-green);
}

.text-link {
    font-weight: 500;
    font-size: 16px;
    text-decoration: underline;
    text-underline-offset: 4px;
    text-decoration-thickness: 1px;
    transition: text-decoration-thickness var(--ease) ease, color var(--ease) ease;
}

.text-link:hover {
    text-decoration-thickness: 2px;
}


/* The button in the header pill: smaller, and white rather than Electric Yellow. */

.button--compact {
    height: 32px;
    /* 112 wide with this label, as the design draws it at every width. */
    padding: 0 16px;
    background: var(--white);
    font-size: 15px;
}

.button--compact:hover {
    background: var(--half-grey);
}

/* Header: one black pill, centred, in view the whole way down the page. */

.site-header {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    justify-content: center;
    padding: var(--pill-top) var(--gutter) 0;
    /* Only the pill takes clicks; the rest of the strip belongs to the page. */
    pointer-events: none;
}

.site-header__pill {
    display: flex;
    align-items: center;
    gap: var(--pill-gap);
    height: var(--pill-height);
    max-width: 100%;
    padding: 0 var(--pill-pad-end) 0 var(--pill-pad-start);
    border-radius: 999px;
    background: var(--black);
    color: var(--yellow);
    pointer-events: auto;
}

.site-header__home {
    display: flex;
}

.site-header .wordmark {
    height: var(--pill-logo);
    width: auto;
    color: inherit;
}

/* Panels: the hero and the closing card. A lighter green square with a marker on
   each corner and a hairline running out of each corner to the edge of the page. */

.panel {
    position: relative;
    z-index: 1;
    width: var(--panel-width);
    margin-inline: auto;
    /* The card's own colour is painted by ::after rather than here, so the
       hairline that runs behind the card can sit under it: a negative z-index
       child still paints above its parent's background, but not above a
       positioned sibling. */
    background: none;
    /* The design draws a hairline around the card at every width it is a card,
       inside the 1080 the width is measured across. */
    border: 1px solid var(--black);
    /* The card lifts off the surface it overlaps. Fitted to the design's own
       falloff on both sides: below the card it darkens by 0.169 at the edge and
       decays to 0.012 over 76px, which this reproduces to an rms of 0.005, and
       above the card the design barely darkens at all, which is what the offset
       is for. */
    box-shadow: 0 30px 50px rgba(0, 0, 0, 0.2);
    --marker: 12px;
}

/* The card's surface, under its contents and over the hairline behind it. */
.panel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--panel);
}

.panel__body {
    position: relative;
    z-index: 1;
}

.panel::before {
    content: "";
    position: absolute;
    z-index: 2;
    inset: calc(var(--marker) / -2);
    pointer-events: none;
    background:
        linear-gradient(var(--black), var(--black)) 0 0 / var(--marker) var(--marker) no-repeat,
        linear-gradient(var(--black), var(--black)) 100% 0 / var(--marker) var(--marker) no-repeat,
        linear-gradient(var(--black), var(--black)) 0 100% / var(--marker) var(--marker) no-repeat,
        linear-gradient(var(--black), var(--black)) 100% 100% / var(--marker) var(--marker) no-repeat;
}

.panel__body {
    padding: var(--panel-pad-top, 40px) var(--panel-padding, 24px) var(--panel-pad-bottom, 40px);
    text-align: center;
}

/* The straps: hairlines leaving the card's corners, all parallel, at the angle
   the design draws them. Its slope is 4 across to 5 down, measured on six of
   them and consistent to a thousandth, which is 38.66 degrees. The hero's leave
   upwards and to the left, the closing card's downwards and to the right, so
   each one runs out over the green rather than across the card. A fifth leaves
   the middle of the edge the others share, as the design has it. */

.panel__rays i {
    position: absolute;
    z-index: -1;
    width: 150vmax;
    height: 1px;
    background: rgba(17, 17, 17, 0.95);
    transform-origin: 0 50%;
}

/* The one hairline that passes behind the card and comes out of its far corner
   is drawn lighter, so it reads as being behind. Measured off the design: it
   lays down 33% of the ink of the hairlines that leave a corner. */
.hero .panel__rays i:nth-child(2),
.closing .panel__rays i:nth-child(3) {
    background: rgba(17, 17, 17, 0.26);
}

.hero .panel__rays i {
    transform: rotate(218.66deg);
}

.closing .panel__rays i {
    transform: rotate(38.66deg);
}

/* Hero: the top two corners, the bottom left, and a point along the top edge. */
.hero .panel__rays i:nth-child(1) { top: 0; left: 0; }
.hero .panel__rays i:nth-child(2) { top: 0; left: 31.6%; }
.hero .panel__rays i:nth-child(3) { top: 0; left: 100%; }
.hero .panel__rays i:nth-child(4) { top: 100%; left: 0; }

/* Closing: the mirror of it, around the bottom edge. The third runs behind the
   card from its TOP LEFT corner, which is what it is attached to; where it comes
   out the other side follows from the card's shape, and the design agrees at
   every width it is visible: the bottom edge at 55% at 1440 and 1024, at 599 of
   704 at 768, and the right edge on a phone, where it never reaches the bottom. */
.closing .panel__rays i:nth-child(1) { top: 0; left: 100%; }
.closing .panel__rays i:nth-child(2) { top: 100%; left: 0; }
.closing .panel__rays i:nth-child(3) { top: 0; left: 0; }
.closing .panel__rays i:nth-child(4) { top: 100%; left: 100%; }

/* A break the design makes once there is room for it. */

.wide-break {
    display: none;
}

/* On phones the hero is the section itself: no card, no markers, no rays. */

@media (max-width: 767px) {
    .hero__card {
        width: auto;
        margin: 0;
        /* No card, so no surface, no border and nothing to cast. */
        border: 0;
        box-shadow: none;
    }

    .hero__card::after {
        display: none;
    }

    /* The design draws the closing card's bottom-left hairline in the light
       shade here, where it runs the length of the footer. */
    .closing .panel__rays i:nth-child(2) {
        background: rgba(17, 17, 17, 0.26);
    }

    /* One link per line, at the design's 28px pitch over a 24px line. */
    .site-footer ul {
        flex-direction: column;
        --footer-link-gap: 4px;
    }

    .hero__card::before,
    .hero .panel__rays {
        display: none;
    }

    /* On a phone the design starts the serif half of the heading on its own
       line; from 768 it runs on, so this is the phone's break alone. It also
       breaks each half where the words run out rather than evenly, so balancing
       is off: the design reads "The model keeps / changing.", not "The model /
       keeps changing." */
    .hero h1 {
        text-wrap: wrap;
    }

    .hero h1 .serif {
        display: block;
    }
}

/* Hero */

.hero {
    position: relative;
    /* Its own block formatting context, so the card's overhang shortens the green
       instead of escaping as a margin on the section. */
    display: flow-root;
    background: var(--phthalo);
    color: var(--white);
    /* The pill sits over the hero rather than above it. */
    margin-top: calc(-1 * var(--header-height));
    padding-top: var(--hero-padding);
}

.hero__card {
    /* The card runs past the bottom of the green, onto the white below. */
    margin-bottom: calc(-1 * var(--hero-overlap));
}

.hero .display {
    color: var(--white);
}

.hero .accent,
.closing .accent {
    color: var(--yellow);
}

.hero .lede {
    margin: var(--hero-lede-gap) auto 0;
    max-width: var(--hero-lede-width);
}

.founders {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: var(--founders-gap);
}

/* Intaglio: each face is black and white paper multiplied onto a pill of colour, so
   the ink stays and the paper becomes the pill.

   The pill's edge is drawn by its background alone. The photograph is clipped to
   the same shape a pixel inside it, so its own soft edge falls on Phthalo Bright
   rather than on the boundary: white paper multiplies to nothing there, and the
   only edge against the section is the pill's, which stays crisp. Clipping the
   photograph on the boundary itself put two soft edges in the same place, and the
   crop then reads as rougher than the shape holding it. Benek asked for the rim
   to go and it did, in the first cut of this batch; David put it back on seeing
   the trade, which is the older note above restored. */
.founders__face {
    position: relative;
    display: block;
    width: var(--face-width);
    height: var(--face-height);
    border-radius: 999px;
    background: var(--phthalo-bright);
}

.founders__face img {
    position: absolute;
    inset: 1px;
    width: calc(100% - 2px);
    height: calc(100% - 2px);
    border-radius: 999px;
    object-fit: cover;
    mix-blend-mode: multiply;
}

.founders__caption {
    margin: var(--caption-gap, 14px) auto 0;
    max-width: var(--caption-width, 240px);
}

/* Built for the deal: the section is as tall as the animation is long, and its
   stage is pinned while it passes. --opened and --offset are set from the scroll
   position, opening the logo and moving the list. */

.what {
    position: relative;
    background: var(--white);
    height: var(--reel-height);
    --opened: 0;
    --offset: 0px;

    /* The bracket is drawn at ONE size and only parts: the storyboard measures
       each half at 98 by 238 in every frame, closed and open alike. 238px is the
       design's height from 768 up and 120px on a phone, capped by the space the
       heading leaves, which only the page can know: the script measures it onto
       --reel-area and the stage's width onto --reel-stage, so the travel is
       bounded by the stage rather than by a viewport width that counts a classic
       scrollbar. */
    --bracket-height: min(120px, calc(var(--reel-area, 100vh) * 0.55));
    /* Measured off the drawn shape: the half is 0.4433 of its height wide, it is
       0.56 of the wordmark box it is cut from, and closed the two leave a gap of
       0.1134 of their height. */
    --bracket-width: calc(var(--bracket-height) * 0.4433);
    --bracket-closed-gap: calc(var(--bracket-height) * 0.1134);
    /* The design lets the halves run past the screen on the narrow frames rather
       than squeeze the list: at 768 and 375 their outer edges sit 20px outside it. */
    --bracket-overhang: 20px;
    /* 720px apart wherever there is room for it, which is what the design draws
       at 1024 and 1440 alike; narrower only when the overhang would be exceeded. */
    --reel-open-gap: min(720px, calc(var(--reel-stage, 100vw) + 2 * var(--bracket-overhang) - 2 * var(--bracket-width)));
    --reel-travel: calc((var(--reel-open-gap) - var(--bracket-closed-gap)) / 2);
    --reel-logo-height: calc(var(--bracket-height) / 0.56);
    --logo-anchor: calc(var(--reel-logo-height) * 1.1825);
    /* Benek: "As the parentheses open, they should not be enlarging." */
    --bracket-grow: 0;
}

.what__stage {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}

/* Everything the heading leaves: the bracket and the list are centred in here
   rather than on the screen, so they cannot reach the words above them. */
.reel__area {
    position: relative;
    flex: 1;
    min-height: 0;
}

.what__intro {
    padding-top: var(--what-padding);
    text-align: center;
}

.what__intro .lede {
    /* The design's gap between the heading and this paragraph: 27px of clear
       space on a phone and 43px from 768, measured ink to ink. */
    margin: var(--reel-intro-gap) auto 0;
    /* 720px at the desktop body size, which is where the design breaks this
       paragraph: after "It does the mechanical". */
    max-width: 36em;
}

/* The logo: the two halves of the wordmark's O, each drawn in the wordmark's own
   coordinate system so the shape is the logo's own, anchored with the O in the
   middle of the screen. --opened parts them; it does not resize them. */

.reel__logo {
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(var(--reel-logo-height) * 3.6583);
    height: var(--reel-logo-height);
    color: var(--black);
    /* The piece is drawn in the whole wordmark's box, so the logo is offset until
       its O lands on the middle of the screen. */
    transform: translate(-50%, -50%) translateX(var(--logo-anchor));
}

.reel__half {
    position: absolute;
    inset: 0;
    transform: translateX(calc(var(--opened) * var(--direction) * var(--reel-travel)));
}

.reel__half--left {
    --direction: -1;
    /* Each half is clipped to its own side of the O. Only the split matters: the
       other three sides run well outside the box, so the O growing past it is not
       cut off. */
    clip-path: polygon(-300% -300%, 17.68% -300%, 17.68% 400%, -300% 400%);
}

.reel__half--right {
    --direction: 1;
    clip-path: polygon(17.68% -300%, 400% -300%, 400% 400%, 17.68% 400%);
}

.reel__layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* The scale is kept as the hook it was, but --bracket-grow is 0: the halves are
   drawn at the size they open to and only move. Set it to 1 to have them grow. */
.reel__bracket {
    transform-origin: 17.68% 50%;
    transform: scale(calc(1 + var(--bracket-grow, 0) * var(--opened)));
}

/* The list runs through a band across the middle of the stage, fading out at the
   top and the bottom so it never reaches the heading. */

.reel__window {
    position: absolute;
    top: 50%;
    left: 50%;
    /* Never wider than the gap the bracket opens, and never taller than the space
       the heading leaves. */
    width: min(640px, calc(var(--reel-open-gap) - 24px), 100% - 2 * var(--gutter));
    height: min(var(--reel-band), 90%);
    transform: translate(-50%, -50%);
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 80%, transparent);
    mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 80%, transparent);
    /* The list fades in once the bracket has started to open. */
    opacity: clamp(0, calc((var(--opened) - 0.12) * 1.8), 1);
}

.reel__list {
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    margin: 0;
    padding: 0;
    list-style: none;
    text-align: center;
    font-size: var(--reel-size);
    line-height: var(--reel-leading);
    font-weight: 500;
    letter-spacing: -0.01em;
    /* It grows with the gap, so it always sits inside the bracket. The offset is
       inside the scale, so the item it centres stays centred while the list grows. */
    transform: translateY(-50%) scale(max(0.28, var(--opened))) translateY(var(--offset));
}

.reel__item + .reel__item {
    margin-top: var(--reel-gap);
}

.reel__item {
    /* The line on the bracket's axis is black; the rest of the list is a 20% tint
       of it. The window's mask takes the ones furthest from the middle away, so
       nothing else needs to fade them. */
    color: rgba(17, 17, 17, 0.2);
    transition: color var(--ease) ease;
    /* v47_final_FINAL.xlsx. is one word and wider than the gap the brackets open
       on a 320px screen; let it break rather than run out of the window. */
    overflow-wrap: anywhere;
}

.reel__item.is-current {
    color: var(--black);
}

/* Security. A graphite band that the closing card runs up onto. Each mark sits
   in a ring: the logo's two brackets, closed into a circle with the same gap at
   the top and the bottom. */

.security {
    background: var(--half-graphite);
    color: var(--white);
    padding-top: var(--security-padding);
    padding-bottom: var(--security-bottom);
    text-align: center;
}

.security .lede {
    margin: var(--security-lede-gap) auto 0;
    max-width: var(--security-lede-width);
}

.security__list {
    --content: 1138px;
    margin: var(--security-list-gap) auto 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--security-item-gap);
}

/* On phones the ring sits beside its words; from 768px each mark is a column. */
.assurance {
    display: grid;
    grid-template-columns: var(--ring-size) 1fr;
    gap: 0 var(--security-ring-gap);
    align-items: start;
    text-align: left;
}

.assurance__ring {
    position: relative;
    display: block;
    width: var(--ring-size);
    height: var(--ring-size);
    color: var(--yellow);
}

.assurance__ring svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.assurance__label {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1.05;
}

.assurance__label b {
    font-size: calc(var(--ring-size) * 0.25);
    font-weight: 700;
}

.assurance__label i {
    font-size: calc(var(--ring-size) * 0.175);
    font-style: normal;
}

.assurance__title {
    margin: 0;
    font-size: var(--assurance-title);
    line-height: 1.25;
    font-weight: 500;
    /* The design's titles are tracked, and that is why ours ran narrower than
       drawn rather than any difference of size or weight: the shortfall was a
       constant 0.56px PER CHARACTER at 18px, the same on "SOC 2" (5), on
       "ISO/IEC 27001" (13) and on "Enterprise security built in" (28). A size
       or width-axis difference would have scaled with the width instead. */
    letter-spacing: 0.03em;
}

.assurance__copy {
    margin: var(--assurance-copy-gap) 0 0;
    font-size: var(--assurance-body);
    line-height: 1.34;
    /* A third of the titles': enough to matter at this size, and it is what
       makes our lines the width the design draws rather than 2% short. */
    letter-spacing: 0.01em;
    /* White, held back: the mark and its title carry the column. */
    color: rgba(255, 255, 255, 0.68);
}

.assurance__status {
    margin: var(--assurance-status-gap) 0 0;
}

.assurance__status span {
    display: inline-block;
    padding: 5px 14px;
    border-radius: 999px;
    background: var(--graphite);
    font-size: 14px;
    line-height: 1.3;
}

/* Bring a live deal */

.closing {
    position: relative;
    display: flow-root;
    background: var(--phthalo);
    color: var(--white);
    padding-bottom: var(--closing-padding);
}

.closing__card {
    /* Pulled up onto the white above, as the hero card runs down onto it. */
    margin-top: calc(-1 * var(--panel-overlap));
}

.closing .lede {
    margin: var(--closing-lede-gap) auto 0;
    max-width: var(--closing-lede-width);
}

.closing .button {
    margin-top: var(--closing-button-gap);
}

/* Footer */

.site-footer {
    background: var(--phthalo);
    color: var(--white);
    padding-bottom: 72px;
    text-align: center;
}

.site-footer__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Over the hairlines that run down through the footer, which the card paints
       at z-index 1. The footer's own ground stays under them. */
    position: relative;
    z-index: 2;
}

.site-footer .wordmark {
    /* 131 by 36 on a phone and 175 by 48 from 768, as the design draws it. */
    height: var(--footer-wordmark);
    width: auto;
}

.site-footer__legal {
    margin-top: 8px;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.75);
}

.site-footer ul {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--footer-link-gap) 32px;
    margin: 42px 0 0;
    padding: 0;
    list-style: none;
    font-size: 16px;
}

.site-footer a {
    text-decoration: none;
    transition: color var(--ease) ease;
}

.site-footer a:hover {
    text-decoration: underline;
    text-underline-offset: 4px;
}
/* Legal pages: one column of prose under the pill. */

.legal {
    padding: 56px 0 96px;
}

.legal-page .site-header__pill {
    /* Over white the pill keeps its black ground, so nothing changes; the page
       simply starts below it. */
    color: var(--yellow);
}

.legal .display {
    font-size: clamp(38px, 4vw, 56px);
    line-height: 1.1;
}

.prose {
    max-width: 68ch;
    margin-top: 32px;
}

.prose h2 {
    margin-top: 48px;
    font-size: 28px;
    line-height: 1.2;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.prose h3 {
    margin-top: 40px;
    font-size: 20px;
    line-height: 1.3;
    font-weight: 600;
}

.prose p,
.prose ul {
    margin-top: 16px;
}

.prose ul {
    padding-left: 20px;
}

.prose li + li {
    margin-top: 8px;
}

.prose code {
    font-size: 0.9em;
    background: var(--half-grey);
    padding: 1px 4px;
    border-radius: 3px;
}

.prose a {
    text-underline-offset: 3px;
}

.prose__updated {
    color: var(--graphite);
}

/* The sub-processor table scrolls rather than squeezing its columns on a narrow
   screen. The scroll lives on a named region with a tab stop, because a
   scrollable box with nothing focusable in it cannot be scrolled by keyboard in
   every browser. */
.prose__scroll {
    margin-top: 20px;
    overflow-x: auto;
}

.prose table {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
}

.prose th,
.prose td {
    padding: 10px 24px 10px 0;
    border-bottom: 1px solid var(--grey);
    vertical-align: top;
    min-width: 8em;
}

.prose thead th {
    border-bottom-color: var(--black);
    font-weight: 600;
}

/* Book a demo: the calendar over the page, nothing else. */

.demo-dialog {
    /* Never narrower than the calendar inside it: HubSpot's iframe holds a
       312px floor, and a 16px gutter each side leaves less than that on a 320px
       screen, so the calendar had to be scrolled sideways to be read. */
    width: min(900px, max(312px, 100vw - 32px));
    max-width: none;
    /* The calendar grows when HubSpot posts a taller layout; keep the dialog
       inside the viewport and let it scroll rather than run off the screen. */
    max-height: calc(100dvh - 24px);
    overflow-y: auto;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--white);
}

.demo-dialog::backdrop {
    background: rgba(17, 17, 17, 0.85);
}

.demo-dialog__close {
    display: flex;
    margin-left: auto;
    width: 44px;
    height: 44px;
    align-items: center;
    justify-content: center;
    color: var(--white);
}

.demo-dialog__close svg {
    width: 20px;
    height: 20px;
}

.demo-dialog__booking {
    position: relative;
    min-height: 320px;
}

.demo-dialog__booking iframe {
    display: block;
    width: 100%;
    min-width: 312px;
    height: 756px;
    border: 0;
}

.demo-dialog__loading {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    text-align: center;
    background: var(--black);
    border-radius: 8px;
}

.demo-dialog__loading[hidden] {
    display: none;
}

.spinner {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 3px solid rgba(255, 255, 255, 0.25);
    border-top-color: var(--yellow);
    animation: spin 0.9s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* Cookie banner */

.cookie-banner {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 30;
    background: var(--black);
    color: var(--white);
    padding: 16px 0;
    font-size: var(--small-size);
    line-height: 1.5;
}

.cookie-banner[hidden] {
    display: none;
}

.cookie-banner__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px 24px;
}

.cookie-banner__text {
    flex: 1 1 480px;
}

.cookie-banner__actions {
    display: flex;
    align-items: center;
    gap: 16px;
}

.cookie-banner__decline {
    text-decoration: underline;
    text-underline-offset: 4px;
    transition: color var(--ease) ease;
}

.cookie-banner__decline:hover {
    color: var(--yellow);
}


/* Tablet and desktop */

@media (min-width: 768px) {
    .wide-break {
        display: inline;
    }

    /* The design's call to action: 242 by 48 with an 18px label. */
    .button {
        height: 48px;
        padding: 0 32px;
        font-size: 18px;
    }

    .button--compact {
        height: 32px;
        padding: 0 16px;
        font-size: 15px;
    }

    :root {
        --display-size: 64px;
        --body-size: 20px;
        --body-leading: 30px;
        --small-size: 16px;

        --hero-padding: 168px;
        --hero-lede-gap: 26px;
        --panel-padding: 40px;
        --panel-pad-top: 56px;
        --panel-pad-bottom: 55px;
        --hero-lede-width: 704px;
        --pill-height: 56px;
        --pill-top: 24px;
        --pill-gap: 23px;
        --pill-logo: 30px;
        --pill-pad-end: 12px;
        --pill-pad-start: 27px;
        --founders-gap: 55px;
        --caption-gap: 19px;
        --caption-width: none;
        --face-width: 64px;
        --face-height: 80px;
        --hero-overlap: 54px;
        --what-padding: min(176px, 18vh);
        --security-padding: 119px;
        --security-bottom: 200px;
        --security-lede-gap: 28px;
        --security-list-gap: 80px;
        --security-ring-gap: 32px;
        --assurance-copy-gap: 8px;
        --assurance-status-gap: 15.5px;
        --reel-intro-gap: 23px;
        --footer-wordmark: 48px;
        --closing-padding: 121px;
        --closing-lede-gap: 36px;
        --closing-lede-width: 470px;
        --closing-button-gap: 32px;

        /* 32px, unless the screen is too short to read that many lines in the
           band the heading leaves: a landscape phone is wide enough for this
           breakpoint but only a few hundred pixels tall. */
        --reel-size: min(32px, 5.2vh);
        --reel-gap: 56px;
    }

    .what {
        --bracket-height: min(238px, calc(var(--reel-area, 100vh) * 0.55));
    }

    .security__list {
        grid-template-columns: repeat(3, 1fr);
        gap: 0;
    }

    .assurance {
        display: block;
        text-align: center;
    }

    .assurance__ring {
        margin: 0 auto 27px;
    }

    .assurance__copy {
        margin-inline: auto;
        /* The width of the design's own text frame, which is pinned between
           281.6 and 283.2: below that the first column's longest line will not
           fit, above it the third column's does, and only inside it do all
           three break where the design breaks them. 17.625em is 282px at the
           default text size and stays a measure rather than a distance if a
           visitor raises it. Narrower than about 919px the column itself is
           the smaller of the two and sets the measure. */
        max-width: 17.625em;
    }


}

/* The wide layout: the design's own frame. */

@media (min-width: 1024px) {
    :root {
        --panel-padding: 64px;
        --display-size: clamp(64px, calc(3.846vw + 24.6px), 80px);
        /* 200px at 1024 and 216 at 1440, the two the design draws, fluid between. */
        --security-bottom: clamp(200px, calc(3.846vw + 160.6px), 216px);

        --reel-band: min(470px, 40vh);
    }
}

/* A visitor who has asked for reduced motion gets no easing either. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
    }
}

/* The reel only runs when the script says so: it adds is-live once it can drive
   the animation, which it will not do without JavaScript or for a visitor who
   has asked for reduced motion. Until then the section is only as tall as its
   contents, the stage is not pinned, and the ten lines are a plain list. */
.what:not(.is-live) {
    height: auto;
}

.what:not(.is-live) .what__stage {
    display: block;
    position: static;
    height: auto;
    overflow: visible;
    padding-bottom: var(--what-padding);
}

.what:not(.is-live) .reel__area {
    position: static;
}

.what:not(.is-live) .reel__logo {
    display: none;
}

.what:not(.is-live) .reel__window {
    position: static;
    width: min(640px, 100% - 2 * var(--gutter));
    height: auto;
    margin: var(--security-list-gap) auto 0;
    transform: none;
    opacity: 1;
    -webkit-mask-image: none;
    mask-image: none;
}

.what:not(.is-live) .reel__list {
    position: static;
    transform: none;
}

.what:not(.is-live) .reel__item {
    color: var(--black);
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}
