:root {
    /* --- Palette ---------------------------------------------------------------
       Every hue exists twice. The **wash** tone tints fills and backgrounds and is
       never read; Bootstrap's own semantic variables hold it, so a themed component
       picks it up without knowing any of this. The **ink** tone is the only one
       allowed on text, on an icon and on a line that has to be seen, and it clears
       4.5:1 against `--vt-surface-bg`. Measured ratios: doc/rules/styles/tokens.md. */

    --bs-primary: #8b0000; /* The brand red, and the only colour ever filled solid */
    --bs-primary-rgb: 139, 0, 0;
    --bs-primary-text: #ffffff; /* Text color when on primary background */
    --bs-primary-hover-bg: #a52a2a; /* Background color for primary elements on hover */

    --bs-secondary: #5a5048; /* Warm stone: a slate grey reads as another semantic hue */
    --bs-secondary-rgb: 90, 80, 72;
    --bs-secondary-text: #ffffff;
    --bs-secondary-hover-bg: #6b6058;

    --bs-link-color: #d4544e; /* The accent ink: 4.69 on the surface */
    --bs-link-color-rgb: 212, 84, 78;
    --bs-link-hover-color: #e8837d;
    --bs-link-hover-color-rgb: 232, 131, 125;

    /* Bootstrap sets these in its own `:root` to its own palette: a field's error in a red
       that reads 4.2:1 on the surface, its success in another green, and code in pink. The
       inks take their place, so a message under a field clears contrast like any text. */
    --bs-form-invalid-color: var(--vt-accent-ink);
    --bs-form-invalid-border-color: var(--vt-accent-ink);
    --bs-form-valid-color: var(--vt-success-ink);
    --bs-form-valid-border-color: var(--vt-success-ink);
    --bs-code-color: var(--vt-accent-ink);

    --bs-body-bg: #000000; /* Background color for the body */
    --bs-body-color: rgba(255, 255, 255, .92); /* Text color for the body */
    /* One step above the browser default. Running text is never sized on a page. */
    --bs-body-font-size: 1.0625rem;
    /* Above Bootstrap's 1.5: the body face has a large x-height and needs the extra
       leading to avoid lines touching. Inherited site-wide. */
    --bs-body-line-height: 1.8;

    --bs-border-color: rgba(255, 255, 255, .12); /* Default border color */
    --bs-border-radius: 0.25rem; /* Global border radius for rounded elements */

    --bs-secondary-color: rgba(255, 255, 255, .62);
    --bs-tertiary-color: rgba(255, 255, 255, .45);
    --bs-emphasis-color: rgba(255, 255, 255, .96);

    /* Wash tones. Muted on purpose: none of them is legible as text, which is what
       keeps them from shouting. Their inks are the `--vt-*-ink` tokens below. */
    --bs-success: #4a7c59;
    --bs-success-rgb: 74, 124, 89;

    --bs-info: #46647f;
    --bs-info-rgb: 70, 100, 127;

    --bs-warning: #8a6a2f;
    --bs-warning-rgb: 138, 106, 47;

    /* Adverse and accent are the same red: on this site danger *is* the house colour,
       and what separates an error from the one action of a page is the form. */
    --bs-danger: #8b0000;
    --bs-danger-rgb: 139, 0, 0;

    --bs-light: #1a1a1a;
    --bs-light-rgb: 26, 26, 26;

    --bs-dark: #0b0b0b;
    --bs-dark-rgb: 11, 11, 11;

    /* Site tokens. Everything in the component layer at the end of this file reads from
       here, so retheming means editing these values and nothing else. */

    /* Typefaces. Four roles, four tokens — no rule below names a family directly.
       Body text uses a face designed for reading on screen; the display face carries the
       character of the site on headings and typographic accents. */
    --vt-font-body: "Merriweather", serif;
    --vt-font-display: "Almendra", serif;
    --vt-font-brand: "Cinzel Decorative", serif;
    --vt-font-hand: "Homemade Apple", cursive;

    --vt-accent: #8b0000; /* Wash tone of the brand red; unreadable by design */
    --vt-accent-rgb: 139, 0, 0;
    --vt-accent-ink: #d4544e; /* Red as letters: text, numerals, drop caps, bars */
    --vt-accent-ink-rgb: 212, 84, 78;

    --vt-success-ink: #7fae8c;
    --vt-success-ink-rgb: 127, 174, 140;
    --vt-info-ink: #8fb0cc;
    --vt-info-ink-rgb: 143, 176, 204;
    --vt-warning-ink: #c9a35a;
    --vt-warning-ink-rgb: 201, 163, 90;

    /* Honours. Gold is ink and thin lines only — it has no wash tone, and used as a
       generic highlight it stops meaning anything. Silver and bronze exist for the
       other two podium places and for nothing else. */
    --vt-gold: #d9b45f;
    --vt-gold-rgb: 217, 180, 95;
    --vt-silver: #c8c8c8;
    --vt-silver-rgb: 200, 200, 200;
    --vt-bronze: #c08a5e;
    --vt-bronze-rgb: 192, 138, 94;

    /* The neutrals. On a near-black page a neutral is white at some opacity, so every
       tint and every faded ink below is written in this one channel. */
    --vt-white: #ffffff;
    --vt-white-rgb: 255, 255, 255;
    --vt-footer-ink: #bdc2c6; /* The footer's quieter text, a cool grey */

    --vt-surface-bg: rgb(16, 16, 16); /* Background of <main>, needed to mask ornaments */
    --vt-backdrop-bg: #0c0404; /* The night of the backdrop beside <main>: the sky of its pictures */
    --vt-hairline: rgba(255, 255, 255, .12);
    --vt-border: rgba(255, 255, 255, .09);

    /* Paper: the site's light surface, for blocks meant to read as a physical document */
    --vt-paper-from: #f5f0e4;
    --vt-paper-to: #e5dcc8;
    --vt-paper-ink: #241c14;
    --vt-paper-ink-strong: #120c06;

    /* How far below the top of the window anything pinned to it stops: the height of the fixed
       navbar plus a breath. A sticky component and the target of an anchor both read it, so a
       heading jumped to is never hidden under the bar. */
    --vt-sticky-top: 6rem;
}


body {
    background-color: var(--bs-body-bg);
    font-family: var(--vt-font-body);
    font-weight: 400;

    /* The backdrop: where the window is wider than <main>, its margins are a night sky with a
       town under a blood moon, one picture per side, laid against the panel's edge and fixed to
       the window. What matters is drawn next to that edge, because a 1920 window shows only the
       inner 300px of each. The edge is half of `.container` at each breakpoint, Bootstrap's
       `$container-max-widths`; under `xl` the margins are too narrow to hold anything. */
    @media (min-width: 1200px) {
        --backdrop-edge: 570px;

        background-color: var(--vt-backdrop-bg);

        &::before,
        &::after {
            content: "";
            position: fixed;
            top: 0;
            bottom: 0;
            z-index: -1;
            background-repeat: no-repeat;
            background-size: auto 100%;
        }

        &::before {
            left: 0;
            right: calc(50% + var(--backdrop-edge));
            background-image: url("../images/background/left-FiO0QdJ.webp");
            background-position: right bottom;
        }

        &::after {
            left: calc(50% + var(--backdrop-edge));
            right: 0;
            background-image: url("../images/background/right-YzdDVI0.webp");
            background-position: left bottom;
        }
    }

    @media (min-width: 1400px) {
        --backdrop-edge: 660px;
    }

    > header {
        h1 {
            font-size: 20px;
            font-family: var(--vt-font-brand);
            font-weight: 700;
            font-style: normal;

            small {
                font-size: 10px;
                display: block;
            }
        }

        /* Under `md` the bar is the wordmark and the menu button, and both have to fit on one
           line: the subtitle goes and the emblem shrinks, or the button drops to a second row. */
        @media (max-width: 767.98px) {
            .navbar {
                flex-wrap: nowrap;

                > .container {
                    flex-wrap: nowrap;
                }

                .collapse.show,
                .collapsing {
                    position: absolute;
                    top: 100%;
                    left: 0;
                    right: 0;
                    padding: 0 var(--bs-gutter-x, .75rem) 1rem;
                    background-color: var(--bs-dark);
                }

                .navbar-brand {
                    --vt-emblem-height: 40px;
                    --vt-emblem-gap: 10px;

                    min-width: 0;

                    img {
                        height: 40px;
                        margin-right: 10px;
                    }
                }
            }

            h1 {
                margin-bottom: 0;
                white-space: nowrap;

                small {
                    display: none;
                }
            }
        }

        /* The bar is fixed over the page, so it is a solid band of the darkest tone: the page
           scrolls under it and would show through a transparent one. */
        .navbar {
            background-color: var(--bs-dark);

            .navbar-brand {
                --vt-emblem-height: 55px;
                --vt-emblem-gap: 15px;

                img {
                    height: 55px;
                    margin-right: 15px;
                }

                /* A celebration's artwork is drawn on a canvas larger than the ankh — 875 × 1364,
                   with the ankh's own 475 × 1024 box at 200, 220 — so whatever it adds can stick
                   out of the bar's emblem. Sized and pulled back by that geometry, the ankh lands
                   exactly where the plain emblem draws it, and the title does not move. */
                img.emblem-celebration {
                    height: calc(var(--vt-emblem-height) * 1364 / 1024);
                    margin:
                        calc(var(--vt-emblem-height) * -220 / 1024)
                        calc(var(--vt-emblem-gap) - var(--vt-emblem-height) * 200 / 1024)
                        calc(var(--vt-emblem-height) * -120 / 1024)
                        calc(var(--vt-emblem-height) * -200 / 1024);
                }
            }

            li {
                a {
                    /* A step under the body size. The bar is a row of eight entries beside a
                       two-line wordmark, and at reading size it competes with the page title
                       instead of framing it. */
                    font-size: .95rem;
                    font-weight: 400;
                }
            }

            /* The language menu is three two-letter entries. The page's leading already
               gives each one a generous row, so they take no padding of their own: with
               Bootstrap's on top they turn into a tall column of mostly air. */
            .dropdown-menu {
                --bs-dropdown-min-width: 5.5rem;
                --bs-dropdown-padding-y: .35rem;
                --bs-dropdown-item-padding-y: 0;
            }

            /* One menu entry may be given weight — a national event, a campaign. It is
               still navigation, so it is a hairline and the accent ink, never a fill.
               Only from `md` up, which is where the bar is a row: in the collapsed menu
               the entries are a stacked list and a box around one of them spans the
               whole panel, so there the ink alone carries the emphasis. */
            .nav-feature {
                color: var(--vt-accent-ink);
                font-weight: 700;
            }

            @media (min-width: 768px) {
                .nav-feature {
                    border: 1px solid rgba(var(--vt-accent-ink-rgb), .55);
                    border-radius: var(--bs-border-radius);
                    font-weight: 400;
                }
            }
        }
    }

    > main {
        background-color: var(--vt-surface-bg);
        color: var(--vt-white);
        margin-top: 80px;

        /* The gutter insets the text from the surface edge. It is not the measure and
           it is not a substitute for one. `.container` declares this variable itself,
           so the rule has to name the class to outrank it. */
        &.container {
            --bs-gutter-x: 3rem;
        }

        @media (min-width: 992px) {
            &.container {
                --bs-gutter-x: 7.5rem;
            }
        }

        h1, h2, h3, h4, h5, h6 {
            font-weight: 400;
        }

        /* The display face stops at `h3`: below that, and in every card title, a
           decorative face at 0.9rem costs legibility and buys no character. */
        h1, h2, h3 {
            font-family: var(--vt-font-display);
        }

        h4, h5, h6 {
            font-family: var(--vt-font-body);
            font-weight: 700;
        }

        /* The page title is the largest step on the page and therefore needs the widest gap
           under it. Bootstrap leaves half a rem, which reads as the opening paragraph
           belonging to the heading rather than following it. */
        h1 {
            margin-bottom: 2rem;
        }

        /* Section rhythm, taken from the long-document pages and made the default so every
           page gets it without classes: an `h2` opens a section and is closed by a hairline,
           an `h3` opens an accented subsection. Headings inside a component are left alone,
           and so is the `h2` of a `.section-head`, which draws the rule itself. */
        h2:not(:is(.card, .alert, .paper, .section-head, .literal, .media-row, .aside-list, .membership-card) *) {
            margin-top: 3.25rem;
            margin-bottom: 1.5rem;
            padding-bottom: .75rem;
            border-bottom: 1px solid var(--vt-hairline);
        }

        /* The bar carries meaning, so it is ink: the wash tone at 3px on a near-black
           page is a line nobody can see. */
        h3:not(:is(.card, .alert, .paper, .section-head, .literal, .media-row, .aside-list, .membership-card) *) {
            margin-top: 2.5rem;
            margin-bottom: 1.25rem;
            padding-left: .9rem;
            border-left: 3px solid var(--vt-accent-ink);
        }

        > :is(h1, h2, h3):first-child {
            margin-top: 0;
        }

        /* Running-text rhythm, applied by default: a content body needs no wrapper class
           to read correctly. Unclassed lists get it too; Bootstrap list components
           (`.nav`, `.list-group`, …) are excluded by the `:not([class])` guard, and
           components that pack content tightly reset the trailing margin themselves. */
        p {
            margin-bottom: 1.5rem;
        }

        ol:not([class]) > li:not(:last-child),
        ul:not([class]) > li:not(:last-child) {
            margin-bottom: .75rem;
        }

        /* Justify running text only, and only from `md` up: a phone column is about 45
           characters wide, where justification opens gaps that hyphenation cannot close.
           Paragraphs inside a component are left out of the rule entirely rather than
           reset afterwards, so alignment utilities like `text-center` keep working on
           them — same reason at panel width, plus an author who centres a block means it.
           A new component with a narrow column joins this list. */
        @media (min-width: 768px) {
            p:not(:is(.card, .alert, .table, .paper, .literal, .pull, .aside-figure, .aside-list, .media-row, .text-center, .text-end, .text-start) *) {
                text-align: justify;
                hyphens: auto;
            }
        }

        a {
            color: var(--bs-link-color);
            text-decoration: underline;
            text-decoration-thickness: .08em;
            text-underline-offset: .18em;
            text-decoration-color: rgba(var(--bs-link-color-rgb), .55);
        }

        a:hover {
            color: var(--bs-link-hover-color);
            text-decoration-color: rgba(var(--bs-link-hover-color-rgb), .85);
        }

        small {
            font-size: 70%;
        }

        /* An example, not a value: dimmer than any text the visitor types, and in italics so it
           never reads as a field already filled in. */
        input::placeholder, .form-control::placeholder {
            color: var(--bs-tertiary-color);
            font-style: italic;
            opacity: .7;
        }
    }

    > footer {
        padding-top: 60px;
        color: var(--vt-footer-ink);

        a {
            color: var(--vt-white);
        }

        /* The licence block: the two logos beside the two notices, above a hairline that
           separates it from the site's own copyright line. */
        .dark-pack {
            margin-bottom: 1.5rem;
            padding-bottom: 1.5rem;
            border-bottom: 1px solid var(--vt-hairline);
            row-gap: 1rem;
            font-size: .82rem;

            img {
                height: 64px;
                width: auto;
                margin-right: 1rem;
            }

            p {
                margin-bottom: .5rem;
            }

            p:last-child {
                margin-bottom: 0;
            }
        }
    }

    /* One table family: no outer box and no grid. Hairlines between rows, the header
       row in the display face as letterspaced capitals, and tabular figures so columns
       of numbers line up. Tables keep 16px while the body runs a step above it: a
       standings table earns its legibility from alignment, and growing the type there
       only forces columns to wrap. */
    .table {
        --bs-table-color: var(--bs-body-color);
        --bs-table-bg: transparent;
        --bs-table-border-color: var(--vt-hairline);

        --bs-table-striped-color: var(--bs-body-color);
        --bs-table-striped-bg: rgba(var(--vt-white-rgb), .03);

        --bs-table-active-color: var(--bs-emphasis-color);
        --bs-table-active-bg: rgba(var(--vt-white-rgb), .06);

        --bs-table-hover-color: var(--bs-emphasis-color);
        --bs-table-hover-bg: rgba(var(--vt-white-rgb), .045);

        font-size: 1rem;
        font-variant-numeric: tabular-nums;

        > caption {
            color: var(--bs-secondary-color);
            font-size: .82rem;

            /* Bootstrap leaves a hidden caption in the flow, since an absolute one breaks the
               table, but keeps its -1px margins: the table ends a pixel short of its rows and
               `.table-responsive` answers with a vertical scrollbar. */
            &.visually-hidden {
                margin: 0 !important;
            }
        }

        > thead > tr > th {
            color: var(--bs-secondary-color);
            font-family: var(--vt-font-display);
            font-weight: 400;
            font-size: .82rem;
            letter-spacing: .14em;
            text-transform: uppercase;
        }

        a {
            text-decoration: none;
        }
    }

    /* The one solid fill on the site, on the action the page exists to provoke. */
    .btn-primary {
        --bs-btn-color: var(--bs-primary-text);
        --bs-btn-bg: var(--bs-primary);
        --bs-btn-border-color: var(--bs-primary);
        --bs-btn-hover-color: var(--bs-primary-text);
        --bs-btn-hover-bg: var(--bs-primary-hover-bg);
        --bs-btn-hover-border-color: var(--bs-primary-hover-bg);
        --bs-btn-active-color: var(--bs-primary-text);
        --bs-btn-active-bg: var(--bs-primary-hover-bg);
        --bs-btn-active-border-color: var(--bs-primary-hover-bg);
        --bs-btn-disabled-color: var(--bs-primary-text);
        --bs-btn-disabled-bg: var(--bs-primary);
        --bs-btn-disabled-border-color: var(--bs-primary);
        --bs-btn-focus-shadow-rgb: var(--vt-accent-ink-rgb);
        --bs-btn-box-shadow: none;
    }

    .btn-secondary {
        --bs-btn-color: var(--bs-secondary-text);
        --bs-btn-bg: var(--bs-secondary);
        --bs-btn-border-color: var(--bs-secondary);
        --bs-btn-hover-color: var(--bs-secondary-text);
        --bs-btn-hover-bg: var(--bs-secondary-hover-bg);
        --bs-btn-hover-border-color: var(--bs-secondary-hover-bg);
        --bs-btn-active-color: var(--bs-secondary-text);
        --bs-btn-active-bg: var(--bs-secondary-hover-bg);
        --bs-btn-active-border-color: var(--bs-secondary-hover-bg);
        --bs-btn-disabled-color: var(--bs-secondary-text);
        --bs-btn-disabled-bg: var(--bs-secondary);
        --bs-btn-disabled-border-color: var(--bs-secondary);
        --bs-btn-focus-shadow-rgb: var(--bs-secondary-rgb);
        --bs-btn-box-shadow: none;
    }

    /* Bootstrap ships `.btn-outline-*` with literal colours baked in at build time, so the
       `--bs-primary` / `--bs-secondary` overrides at the top of this file never reach them —
       an outline primary button renders Bootstrap blue on a dark red site. Restate the
       variables the compiled rules read, in full: overriding the resting colour alone
       leaves the hover and active states blue. Outlines carry the ink tone, because a
       border and a label are both read. */
    .btn-outline-primary {
        --bs-btn-color: var(--vt-accent-ink);
        --bs-btn-border-color: var(--vt-accent-ink);
        --bs-btn-bg: transparent;
        --bs-btn-hover-color: var(--bs-primary-text);
        --bs-btn-hover-bg: var(--bs-primary);
        --bs-btn-hover-border-color: var(--bs-primary);
        --bs-btn-active-color: var(--bs-primary-text);
        --bs-btn-active-bg: var(--bs-primary-hover-bg);
        --bs-btn-active-border-color: var(--bs-primary-hover-bg);
        --bs-btn-disabled-color: var(--vt-accent-ink);
        --bs-btn-disabled-border-color: var(--vt-accent-ink);
        --bs-btn-focus-shadow-rgb: var(--vt-accent-ink-rgb);
    }

    /* The quiet action: a hairline and no fill. Every secondary action is this.
       Its label is read like any other text and therefore carries the emphasis colour, not the
       muted one: at 62% white on this ground a button label reads as a disabled control, and the
       hairline is already what makes it quieter than the solid one. */
    .btn-outline-secondary {
        --bs-btn-color: var(--bs-emphasis-color);
        --bs-btn-border-color: var(--bs-tertiary-color);
        --bs-btn-bg: transparent;
        --bs-btn-hover-color: var(--bs-emphasis-color);
        --bs-btn-hover-bg: rgba(var(--vt-white-rgb), .06);
        --bs-btn-hover-border-color: var(--bs-secondary-color);
        --bs-btn-active-color: var(--bs-emphasis-color);
        --bs-btn-active-bg: rgba(var(--vt-white-rgb), .1);
        --bs-btn-active-border-color: var(--bs-secondary-color);
        --bs-btn-disabled-color: var(--bs-tertiary-color);
        --bs-btn-disabled-border-color: var(--bs-border-color);
        --bs-btn-focus-shadow-rgb: var(--vt-white-rgb);
    }

    /* Semantic buttons are outlined in their ink tone: nothing but the brand red is
       filled solid. One recipe, two custom properties — the ink for the label and the
       border, the wash for the tint that appears under the pointer. */
    .btn-success, .btn-outline-success,
    .btn-info, .btn-outline-info,
    .btn-warning, .btn-outline-warning,
    .btn-danger, .btn-outline-danger {
        --btn-ink: var(--vt-accent-ink);
        --btn-wash-rgb: var(--vt-accent-rgb);

        --bs-btn-color: var(--btn-ink);
        --bs-btn-bg: transparent;
        --bs-btn-border-color: var(--btn-ink);
        --bs-btn-hover-color: var(--bs-emphasis-color);
        --bs-btn-hover-bg: rgba(var(--btn-wash-rgb), .35);
        --bs-btn-hover-border-color: var(--btn-ink);
        --bs-btn-active-color: var(--bs-emphasis-color);
        --bs-btn-active-bg: rgba(var(--btn-wash-rgb), .5);
        --bs-btn-active-border-color: var(--btn-ink);
        --bs-btn-disabled-color: var(--btn-ink);
        --bs-btn-disabled-bg: transparent;
        --bs-btn-disabled-border-color: var(--btn-ink);
        --bs-btn-focus-shadow-rgb: var(--btn-wash-rgb);
        --bs-btn-box-shadow: none;
    }

    .btn-success, .btn-outline-success {
        --btn-ink: var(--vt-success-ink);
        --btn-wash-rgb: var(--bs-success-rgb);
    }

    .btn-info, .btn-outline-info {
        --btn-ink: var(--vt-info-ink);
        --btn-wash-rgb: var(--bs-info-rgb);
    }

    .btn-warning, .btn-outline-warning {
        --btn-ink: var(--vt-warning-ink);
        --btn-wash-rgb: var(--bs-warning-rgb);
    }

    .btn-danger, .btn-outline-danger {
        --btn-ink: var(--vt-accent-ink);
        --btn-wash-rgb: var(--vt-accent-rgb);
    }

    /* Same story as the outline buttons: Bootstrap bakes literal blues into the focus ring
       and the check/radio accents, so an input on this site focuses Bootstrap blue. */
    .form-control,
    .form-select {
        background-color: rgba(var(--vt-white-rgb), .04);
        border-color: var(--vt-border);
        color: var(--bs-body-color);
    }

    /* The options of a `select` are drawn by the browser, not by Bootstrap: left alone they come
       out as a white list with the operating system's blue highlight, which is the one piece of
       this form the theme layer cannot reach through a variable. `accent-color` covers the
       highlight on the engines that honour it. */
    .form-select {
        accent-color: var(--bs-primary);

        option {
            background-color: var(--vt-surface-bg);
            color: var(--bs-body-color);
        }

        option:checked {
            background-color: var(--bs-primary);
            color: var(--bs-primary-text);
        }
    }

    .form-control:focus,
    .form-select:focus {
        background-color: rgba(var(--vt-white-rgb), .06);
        border-color: var(--vt-accent-ink);
        box-shadow: 0 0 0 .2rem rgba(var(--vt-accent-ink-rgb), .25);
        color: var(--bs-body-color);
    }

    .form-check-input {
        background-color: rgba(var(--vt-white-rgb), .06);
        border-color: var(--vt-border);
    }

    .form-check-input:checked {
        background-color: var(--bs-primary);
        border-color: var(--bs-primary);
    }

    .form-check-input:focus {
        border-color: var(--vt-accent-ink);
        box-shadow: 0 0 0 .2rem rgba(var(--vt-accent-ink-rgb), .25);
    }

    /* Alerts and contextual table rows ship as pastel blocks meant for a white page; on
       black they read as holes punched in the layout. Restate them as a tinted wash of the
       same hue behind a hairline of its ink, driven by two custom properties so every
       variant shares one recipe: the wash tints, the ink draws the line that is seen. */
    .alert {
        --alert-rgb: var(--vt-info-ink-rgb);
        --alert-wash-rgb: var(--bs-info-rgb);
        --bs-alert-color: var(--bs-body-color);
        --bs-alert-bg: rgba(var(--alert-wash-rgb), .12);
        --bs-alert-border-color: rgba(var(--alert-rgb), .4);
        --bs-alert-link-color: var(--bs-link-color);
    }

    .alert-primary,
    .alert-danger {
        --alert-rgb: var(--vt-accent-ink-rgb);
        --alert-wash-rgb: var(--vt-accent-rgb);
    }

    .alert-success {
        --alert-rgb: var(--vt-success-ink-rgb);
        --alert-wash-rgb: var(--bs-success-rgb);
    }

    .alert-warning {
        --alert-rgb: var(--vt-warning-ink-rgb);
        --alert-wash-rgb: var(--bs-warning-rgb);
    }

    .alert-info {
        --alert-rgb: var(--vt-info-ink-rgb);
        --alert-wash-rgb: var(--bs-info-rgb);
    }

    .alert-secondary,
    .alert-light,
    .alert-dark {
        --alert-rgb: var(--vt-white-rgb);
        --alert-wash-rgb: var(--vt-white-rgb);
    }

    /* Site addition: honours and rewards have no Bootstrap equivalent. Gold is ink and
       thin lines only, so the line is gold and the tint stays neutral. */
    .alert-gold {
        --alert-rgb: var(--vt-gold-rgb);
        --alert-wash-rgb: var(--vt-white-rgb);
    }

    /* The colour utilities carry Bootstrap's semantic variables, which hold the wash
       tones: `.text-primary` on this page renders `#8b0000` and cannot be read. A hue
       on text or on an icon takes the ink, so they are restated here — the utilities
       themselves are `!important`, which is the only reason this rule is too. */
    .text-primary,
    .text-danger {
        color: var(--vt-accent-ink) !important;
    }

    .text-success {
        color: var(--vt-success-ink) !important;
    }

    .text-info {
        color: var(--vt-info-ink) !important;
    }

    .text-warning {
        color: var(--vt-warning-ink) !important;
    }

    /* On the light surfaces the two tiers swap over, exactly as they do in the email:
       against paper the wash tone is the one that reads and the ink drops to 3.6. */
    .paper,
    .card-img-wrapper {
        .text-primary,
        .text-danger {
            color: var(--bs-primary) !important;
        }

        .text-success {
            color: var(--bs-success) !important;
        }

        .text-info {
            color: var(--bs-info) !important;
        }

        .text-warning {
            color: var(--bs-warning) !important;
        }
    }

    /* Bootstrap 5 dropped the colour variants of `.badge` and left only `.text-bg-*`,
       a saturated block that competes with the one action of the page. The base pill
       is a wash behind a hairline; the roles are in the component layer. */
    /* The roles are in the component layer, so the neutral values are fallbacks inside the
       `var()` calls and not declarations: a `--badge-rgb` declared here would outrank the
       one a `.badge-*` sets, and every badge would come out grey. */
    .badge {
        padding: .4em .7em;
        border: 1px solid rgba(var(--badge-ink-rgb, var(--vt-white-rgb)), .42);
        background-color: rgba(var(--badge-rgb, var(--vt-white-rgb)), .12);
        color: var(--badge-ink, var(--bs-emphasis-color));
        font-weight: 400;
    }

    .table {
        .table-success,
        .table-danger,
        .table-warning,
        .table-info {
            --bs-table-color: var(--bs-body-color);
            --bs-table-bg: rgba(var(--row-rgb), .14);
            --bs-table-border-color: rgba(var(--row-rgb), .3);
            --bs-table-striped-bg: rgba(var(--row-rgb), .2);
            --bs-table-striped-color: var(--bs-body-color);
            --bs-table-active-bg: rgba(var(--row-rgb), .26);
            --bs-table-active-color: var(--bs-body-color);
            --bs-table-hover-bg: rgba(var(--row-rgb), .22);
            --bs-table-hover-color: var(--bs-body-color);

            color: var(--bs-table-color);
            border-color: var(--bs-table-border-color);
        }

        .table-success {
            --row-rgb: var(--bs-success-rgb);
        }

        .table-danger {
            --row-rgb: var(--bs-danger-rgb);
        }

        .table-warning {
            --row-rgb: var(--bs-warning-rgb);
        }

        .table-info {
            --row-rgb: var(--bs-info-rgb);
        }
    }

    /* A `.btn-group` never wraps by design, so a toolbar of actions overflows the
       viewport on a phone. Let it wrap and keep the group's rounded ends per line.
       For actions only: navigation is a `.nav-tabs` or an `.inline-nav`. */
    .btn-group {
        flex-wrap: wrap;
    }

    /* Tab bars: Bootstrap's active tab is a light pill, which punches a hole in a dark
       page. Underline the active tab instead, in the ink — a 2px rule is read. */
    .nav-tabs {
        --bs-nav-tabs-border-color: var(--vt-hairline);
        --bs-nav-tabs-link-hover-border-color: transparent transparent var(--vt-accent-ink);
        --bs-nav-tabs-link-active-color: var(--bs-emphasis-color);
        --bs-nav-tabs-link-active-bg: transparent;
        --bs-nav-tabs-link-active-border-color: transparent transparent var(--vt-accent-ink);
        --bs-nav-link-color: var(--bs-link-color);
        --bs-nav-link-hover-color: var(--bs-link-hover-color);

        .nav-link {
            border-bottom-width: 2px;
            text-decoration: none;
        }

        .nav-link.active {
            font-weight: 700;
        }
    }

    /* Same bug as the outline buttons, in the components that carry a state: Bootstrap
       compiles its blue into the dropdown's active entry, into the pills and into the
       focus ring of a nav link, so the language menu of the header lights up blue.
       Restate the variables the compiled rules read. */
    .dropdown-menu {
        --bs-dropdown-bg: var(--vt-surface-bg);
        --bs-dropdown-border-color: var(--vt-border);
        --bs-dropdown-border-radius: var(--bs-border-radius);
        --bs-dropdown-color: var(--bs-body-color);
        --bs-dropdown-link-color: var(--bs-body-color);
        --bs-dropdown-link-hover-color: var(--bs-emphasis-color);
        --bs-dropdown-link-hover-bg: rgba(var(--vt-white-rgb), .06);
        --bs-dropdown-link-active-color: var(--vt-accent-ink);
        --bs-dropdown-link-active-bg: rgba(var(--vt-accent-rgb), .3);
        --bs-dropdown-link-disabled-color: var(--bs-tertiary-color);
        --bs-dropdown-header-color: var(--bs-secondary-color);
    }

    .nav-pills {
        --bs-nav-pills-link-active-color: var(--bs-primary-text);
        --bs-nav-pills-link-active-bg: var(--bs-primary);
        --bs-nav-pills-border-radius: var(--bs-border-radius);
    }

    .nav-link:focus-visible {
        box-shadow: 0 0 0 .2rem rgba(var(--vt-accent-ink-rgb), .25);
    }

    .card {
        /* A bare Bootstrap card is `--bs-body-bg` (black) on a near-black page, so it reads
           as a hole rather than a raised surface. Lift it a step. One card: a hairline, a
           small radius, no shadow and no coloured edge. */
        --bs-card-bg: rgba(var(--vt-white-rgb), .035);
        --bs-card-border-color: var(--vt-border);

        /* A card title is the reading face in bold at body size: a card is a panel,
           not a section of the document, and a 2rem heading inside one shouts. A
           `.section-head` in a card *is* a section opener and keeps the display face. */
        :is(h2, h3, h4, h5, h6):not(.section-head *) {
            font-family: var(--vt-font-body);
            font-weight: 700;
            font-size: 1.05rem;
        }

        /* The light surface a logo sits on: a bounded tile with the card's radius and
           hairline, on the site's paper rather than a loose grey box. Every tile is the
           same size and the image fills it, so a row stays even whatever shape the logo
           arrives in. The tile also centres a bare `<i>`, for the entries that have an
           icon instead of a logo. */
        .card-img-wrapper {
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 200px;
            padding: .625rem;
            border-bottom: 1px solid var(--vt-border);
            border-radius: var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0;
            background: linear-gradient(160deg, var(--vt-paper-from), var(--vt-paper-to));
            overflow: hidden;
            text-align: center;

            img {
                flex: 0 0 auto;
                display: block;
                width: 100%;
                height: 180px;
                border-radius: var(--bs-border-radius);
                object-fit: cover;
                object-position: center center;
            }
        }
    }
}

@media (min-width: 576px) {
    body {
        > header {
            h1 {
                font-size: 30px;

                small {
                    font-size: 15px;
                }
            }
        }
    }
}

/* The lightbox every image of the site opens in — GLightbox, `clean` skin. Its
   own sheet paints the caption panel solid white with black Arial in it, which
   under the photograph is a hole; these rules put the panel back on the tokens.
   They carry the container class because that sheet is served after this one,
   so equal specificity would lose. The phone layout, which the vendor already
   draws as a gradient over the image, is left alone. */
.glightbox-container.glightbox-clean .gslide-description {
    background: transparent;
    text-align: center;
}

.glightbox-container.glightbox-clean .gdesc-inner {
    padding: 1rem 1.25rem 0;
}

.glightbox-container.glightbox-clean .gslide-title,
.glightbox-container.glightbox-clean .gslide-desc {
    margin-bottom: 0;
    font-family: var(--vt-font-body);
    font-size: .88rem;
    color: var(--bs-secondary-color);
}

/* The bar Turbo draws across the top of the window while a visit takes over half a second, in
   Turbo's own blue unless told otherwise. It is a line meant to be seen on the dark page, so it
   takes the ink tone. Turbo injects its sheet with JavaScript and keeps the bar a child of `html`:
   the child selector outweighs that sheet wherever it lands in the head. */
html > .turbo-progress-bar {
    background: var(--vt-accent-ink);
}

/* The box of the bot check, ALTCHA's widget, the last row of its form before the button. A block
   as wide as the form, like any other row, and spaced like one: the margin of the row above it,
   the button's below; the widget's own cap of 320px would leave it a box adrift. The
   widget writes its palette on `:root` with `light-dark()`, which is white on a page that declares
   no colour scheme; restated on the element itself, the tokens win. The ticked box and an error
   are fills, so they take the wash tones; the focus ring is a line, so the ink. */
altcha-widget {
    display: block;
    --altcha-color-base: var(--vt-surface-bg);
    --altcha-color-base-content: var(--bs-body-color);
    --altcha-color-neutral: var(--vt-hairline);
    --altcha-color-neutral-content: var(--bs-secondary-color);
    --altcha-color-primary: var(--vt-accent-ink);
    --altcha-color-primary-content: var(--bs-body-bg);
    --altcha-color-success: var(--bs-success);
    --altcha-color-success-content: var(--vt-white);
    --altcha-color-error: var(--vt-accent);
    --altcha-color-error-content: var(--vt-white);
    --altcha-border-radius: var(--bs-border-radius);
    --altcha-max-width: 100%;
    --altcha-shadow: none;
    --altcha-transition-duration: 150ms;
}

/* ===========================================================================
   Reusable component layer
   ---------------------------------------------------------------------------
   Generic building blocks for editorial content: long documents, landing
   pages, announcements. Nothing here is tied to a particular page — compose
   these with Bootstrap utilities from any content body or template.

   Three rules keep this layer consistent:
   - Colours, spacing and radii come from the tokens in `:root`. Never
     hardcode a colour here.
   - Typefaces are referenced only through the `--vt-font-*` tokens, never by
     name, so swapping a face stays an edit to `:root`.
   - A hue on text, on an icon or on a line meant to be seen takes the ink
     tone; the wash tone is for tints and fills only.

   Catalogue and usage: see doc/rules/styles/components.md
   =========================================================================== */

/* --- Layout ------------------------------------------------------------- */

/* Multi-column list, for long enumerations that would otherwise run down the
   page. Collapses to one column on narrow viewports. */
.cols-2 > li {
    margin-bottom: .75rem;
    break-inside: avoid;
}

@media (min-width: 992px) {
    .cols-2 {
        column-count: 2;
        column-gap: 3rem;
    }
}

/* A list entry led by a picture of fixed width — a banner, a logo, a cover —
   with its text beside it. The picture sits on a paper tile of one 2:1 shape,
   so a list of pictures of every proportion stays even, and an entry with none
   keeps the empty tile instead of pulling its text out of line. Below `sm` the
   tile stacks above the text: a phone has no width to spare beside it. */
.media-row {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.media-row-thumb {
    flex: 0 0 auto;
    display: block;
    width: 200px;
    aspect-ratio: 2 / 1;
    border: 1px solid var(--vt-border);
    border-radius: var(--bs-border-radius);
    background: linear-gradient(160deg, var(--vt-paper-from), var(--vt-paper-to));
    overflow: hidden;

    img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
}

/* The entry's title, at whatever level the page puts it: a step above the text, in bold, on the
   accent bar of a subsection, and close to the text it heads. */
.media-row :is(h2, h3, h4) {
    margin: 0 0 .25rem;
    padding-left: .9rem;
    border-left: 3px solid var(--vt-accent-ink);
    font-size: 1.25rem;
    font-weight: 700;
}

@media (min-width: 576px) {
    .media-row {
        flex-direction: row;
        align-items: flex-start;
        gap: 1.5rem;
    }
}

/* A picture cropped to a square tile, the whole tile a link: the cover heading a card of a grid
   of covers. Under the pointer it dims, and nothing moves. */
.thumb {
    display: block;
    overflow: hidden;
    border-radius: var(--bs-border-radius);

    img {
        width: 100%;
        aspect-ratio: 1 / 1;
        object-fit: cover;
        transition: opacity .15s ease;
    }
}

.thumb:hover img {
    opacity: .82;
}

/* Pictures of every proportion in columns, none of them cropped: each `.masonry-item` an anchor
   holding a `.masonry-img`. A picture waits as a shimmering tile of its own shape and fades and
   sharpens in once loaded, which `gallery_controller.js` marks with `.is-loaded`. */
.masonry {
    column-count: 4;
    column-gap: .75rem;
}

.masonry-item {
    display: block;
    margin: 0 0 .75rem;
    transition: opacity .15s ease;
    break-inside: avoid;
    overflow: hidden;
    border-radius: var(--bs-border-radius);
    background: linear-gradient(
        110deg,
        rgba(var(--vt-white-rgb), .05) 30%,
        rgba(var(--vt-white-rgb), .14) 50%,
        rgba(var(--vt-white-rgb), .05) 70%
    );
    background-size: 200% 100%;
    animation: masonry-shimmer 1.6s linear infinite;
}

/* The shimmer stops once the picture is in. */
.masonry-item:has(.is-loaded) {
    background: none;
    animation: none;
}

/* A block, so no line box hangs a gap under the picture inside its tile. */
.masonry-img {
    display: block;
    width: 100%;
    height: auto;
    opacity: 0;
    filter: blur(12px);
    transition: opacity .5s ease, filter .5s ease;
}

.masonry-img.is-loaded {
    opacity: 1;
    filter: none;
}

/* A loaded picture dims under the pointer, as a `.thumb` does. On the anchor rather than the
   picture, whose own transition is the slower fade it loads in with. */
.masonry-item:has(.is-loaded):hover {
    opacity: .82;
}

@keyframes masonry-shimmer {
    from {
        background-position: 200% 0;
    }
    to {
        background-position: -200% 0;
    }
}

@media (max-width: 992px) {
    .masonry {
        column-count: 3;
    }
}

@media (max-width: 768px) {
    .masonry {
        column-count: 2;
    }
}

@media (max-width: 480px) {
    .masonry {
        column-count: 1;
    }
}

/* --- Typographic accents ------------------------------------------------ */

/* Decorative initial, sunk two lines: its capital runs from the cap height of the first line to
   the baseline of the second. Put on the opening paragraph of a section. `initial-letter` sizes
   and seats it from the page's own leading, so nothing here repeats the leading. */
.dropcap::first-letter {
    margin-right: .5rem;
    font-family: var(--vt-font-display);
    color: var(--vt-accent-ink);
    -webkit-initial-letter: 2;
    initial-letter: 2;
}

/* Firefox has no `initial-letter`. It floats a first letter on the outline of its glyph rather
   than on a line box, so a size and a nudge are enough to land the capital on the same two
   lines; Chrome would float it on the full leading instead, which is why this is the fallback. */
@supports not ((initial-letter: 2) or (-webkit-initial-letter: 2)) {
    .dropcap::first-letter {
        float: left;
        margin-top: .11em;
        font-size: 4.2rem;
    }
}

/* Small uppercase label above a heading or at the top of a panel. */
.eyebrow {
    display: block;
    font-family: var(--vt-font-display);
    margin-bottom: .5rem;
    color: rgba(var(--vt-white-rgb), .68);
    font-size: .78rem;
    letter-spacing: .18em;
    text-transform: uppercase;
}

/* Heading paired with an oversized marker: a number, a numeral or an icon. */
.section-head {
    display: flex;
    align-items: baseline;
    gap: 1.25rem;
    margin-bottom: 1.75rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--vt-hairline);
}

.section-head > :last-child {
    margin: 0;
}

/* Trimmed to its capital and baseline: at this size the page's leading would hang more than a
   line of air around the glyph, and push the hairline away from the heading it closes. */
.section-marker {
    flex: 0 0 auto;
    font-family: var(--vt-font-display);
    color: var(--vt-accent-ink);
    font-size: 3.4rem;
    text-box: trim-both cap alphabetic;
}

.section-marker-sm {
    font-size: 1.9rem;
}

.section-marker-icon {
    font-size: 2.1rem;
}

/* The code of an error page, drawn large in the brand's face and in one ink. Every code has a 0 in
   the middle, and the emblem of the code stands for it, inside a ring of the figures' weight, so a
   round emblem and a word read alike. The figures are trimmed to their capital and baseline, as a
   marker is, and the emblem is a mask, so the ink stays a token. */
.error-code {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: .08em;
    color: var(--vt-accent-ink);
    font-family: var(--vt-font-brand);
    font-size: clamp(5.5rem, 20vw, 9.5rem);
    font-weight: 700;
}

.error-code > span {
    text-box: trim-both cap alphabetic;
}

/* The size of the face's own 0, whose figures stand .63 of the type size. */
.error-code-emblem {
    display: grid;
    place-items: center;
    width: .58em;
    height: .63em;
    border: .085em solid currentColor;
    border-radius: 50%;
}

.error-code-emblem::before {
    content: "";
    width: var(--error-emblem-width, 74%);
    aspect-ratio: 1;
    background: currentColor;
    -webkit-mask: var(--error-emblem) center / contain no-repeat;
    mask: var(--error-emblem) center / contain no-repeat;
}

/* Malkavian is a word, not a mark: it takes the whole inside of the ring to be read at all. */
.error-code-400 { --error-emblem: url("../images/error/400-bXMUK26.webp"); --error-emblem-width: 96%; }
.error-code-403 { --error-emblem: url("../images/error/403-rIXr6xN.webp"); }
.error-code-404 { --error-emblem: url("../images/error/404-mmMqcba.webp"); }
.error-code-405 { --error-emblem: url("../images/error/405-5eQX_X_.webp"); }
.error-code-500 { --error-emblem: url("../images/error/500-9scvEAJ.webp"); }
.error-code-503 { --error-emblem: url("../images/error/503-c5V6tV-.webp"); }

/* Ornamental separator between major blocks. One per major break, not between
   every heading. */
.ornament {
    position: relative;
    height: 1px;
    margin: 3.75rem 0;
    background: linear-gradient(90deg, transparent, rgba(var(--vt-accent-ink-rgb), .5) 22%,
    rgba(var(--vt-accent-ink-rgb), .5) 78%, transparent);
}

.ornament::after {
    content: "◆";
    position: absolute;
    top: 50%;
    left: 50%;
    padding: 0 1.1rem;
    transform: translate(-50%, -50%);
    background: var(--vt-surface-bg);
    color: var(--vt-accent-ink);
    font-size: 1.1rem;
}

/* The signatures that close a transcribed paper, side by side and wrapping. Each is the name
   written in the hand face, tilted as a pen leaves it, over a hairline with the printed name and
   role. The hand repeats the printed line, so it carries `aria-hidden`. */
.signatures {
    display: flex;
    flex-wrap: wrap;
    gap: 2.5rem 3.5rem;
    margin: 2.5rem 0;
}

.signature {
    display: flex;
    flex-direction: column;
    min-width: 13rem;
}

.signature-hand {
    padding: 0 .75rem .25rem;
    color: var(--bs-emphasis-color);
    font-family: var(--vt-font-hand);
    font-size: 1.55rem;
    transform: rotate(-4deg);
    transform-origin: left bottom;
}

.signature-name {
    padding-top: .5rem;
    border-top: 1px solid var(--vt-hairline);
    font-size: .88rem;
}

/* --- Surfaces ----------------------------------------------------------- */

/* Accent card: Bootstrap's `.card` with its hairline tinted, and nothing else — no
   coloured edge, no elevation, no lift. The colour is a single custom property, so
   one rule covers every variant. Pair with `.h-100` inside a row and put the content
   in a `.card-body`, as usual. */
.card-accent {
    --card-accent-rgb: var(--vt-accent-ink-rgb);

    border-color: rgba(var(--card-accent-rgb), .5);
}

.card-accent-success {
    --card-accent-rgb: var(--vt-success-ink-rgb);
}

.card-accent-info {
    --card-accent-rgb: var(--vt-info-ink-rgb);
}

.card-accent-warning {
    --card-accent-rgb: var(--vt-warning-ink-rgb);
}

.card-accent-gold {
    --card-accent-rgb: var(--vt-gold-rgb);
}

/* Icon leading a card, tinted with the card's own accent. */
.card-icon {
    display: block;
    margin-bottom: .9rem;
    color: rgb(var(--card-accent-rgb, var(--vt-accent-ink-rgb)));
    font-size: 1.9rem;
}

/* An initial leading a card in place of a portrait the site does not keep: the display face in the
   card's ink, inside a ring of that ink and a fainter one around it, as a seal is struck. Trimmed to
   its capital and baseline, so the letter sits in the middle of the ring and not above it; a block
   container, because the trim does not reach the text of a grid or a flex box. */
.card-monogram {
    display: inline-block;
    align-content: center;
    width: 4.5rem;
    aspect-ratio: 1;
    margin-bottom: 1.25rem;
    border: 1px solid rgb(var(--card-accent-rgb, var(--vt-accent-ink-rgb)));
    border-radius: 50%;
    outline: 1px solid rgba(var(--card-accent-rgb, var(--vt-accent-ink-rgb)), .35);
    outline-offset: .3rem;
    color: rgb(var(--card-accent-rgb, var(--vt-accent-ink-rgb)));
    font-family: var(--vt-font-display);
    font-size: 2.1rem;
    text-box: trim-both cap alphabetic;
}

/* A form that is the whole point of its page — signing in, asking for a new password. Compose
   with `.card`: at full page measure two fields and a button read as three stray boxes drifting
   across the column, so the panel is set to the width of its fields and centred. */
.form-panel {
    max-width: 34rem;
    margin: 0 auto;
}

/* Light surface on the dark page: reads as paper. For documents, excerpts,
   anything meant to look like a physical thing. Loud by design — use it rarely. */
.paper {
    padding: 2.25rem;
    border: 1px solid var(--vt-border);
    border-radius: var(--bs-border-radius);
    background: linear-gradient(160deg, var(--vt-paper-from), var(--vt-paper-to));
    color: var(--vt-paper-ink);
}

.paper strong {
    color: var(--vt-paper-ink-strong);
}

/* The membership card of the member area: the brand red as its ground, printed in one ink, the
   paper colour. The ankh is cut out of the red at a size the card cannot hold, so its blade runs
   off the bottom edge, and the membership number sits in the eye of its loop. The text takes the
   space the ankh leaves: who issues the card and the name the member goes by beside the loop and
   the arms, then a rule the blade cuts through, with the member's papers under it. The ankh is
   `images/member/card-ankh.svg`, used as a mask, so the ink stays a token.

   Everything inside is sized in `cqi`, the card's own width, so it scales as one printed object
   and keeps its proportions on a phone; the smallest print has a floor in `rem`. The ankh's
   geometry drives the layout: `--membership-card-emblem` is its width, its arms end 0.858 of that
   width below its top, its loop is widest 0.208 of it in from its left side, and its blade starts
   at 0.427 of it. Card proportions are a floor, not a frame: the card clips with `overflow: clip`,
   so a long name grows it instead of running into the ankh. */
.membership-card {
    --membership-card-emblem: 46cqi;
    --membership-card-top: 3.4cqi;
    --membership-card-pad: 6cqi;
    --membership-card-left: calc(100cqi - 3.4cqi - var(--membership-card-emblem));
    --membership-card-arms: calc(var(--membership-card-top) + var(--membership-card-emblem) * .858);
    --membership-card-blade: calc(var(--membership-card-left) + var(--membership-card-emblem) * .427);

    container-type: inline-size;
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: clip;
    aspect-ratio: 85.6 / 54;
    border-radius: 3.7% / 5.87%;
    background: var(--vt-accent);
    color: var(--vt-paper-from);
}

.membership-card-emblem {
    position: absolute;
    top: var(--membership-card-top);
    left: var(--membership-card-left);
    width: var(--membership-card-emblem);
    aspect-ratio: 475 / 1024;
}

.membership-card-emblem::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--vt-paper-from);
    -webkit-mask: url("../images/member/card-ankh-Bdw-7Yk.svg") 0 0 / 100% 100% no-repeat;
    mask: url("../images/member/card-ankh-Bdw-7Yk.svg") 0 0 / 100% 100% no-repeat;
}

/* The figure is centred on the eye of the loop, a little low so that it and the Nº over it share
   the centre; the Nº hangs from it, so the global leading cannot move the pair. */
.membership-card-number {
    position: absolute;
    top: 11.8%;
    left: 50%;
    translate: -50% -50%;
    font-family: var(--vt-font-display);
    font-size: 6.6cqi;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.membership-card-number small {
    position: absolute;
    bottom: calc(50% + 3.4cqi);
    left: 50%;
    translate: -50% 0;
    font-size: max(.625rem, 2cqi);
    font-weight: 400;
    letter-spacing: .2em;
}

/* Beside the loop and the arms, down to where the arms end: who issues the card, and the name its
   bearer goes by. The name never reaches the left arm. */
.membership-card-head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    flex-shrink: 0;
    min-height: calc(var(--membership-card-arms) - 7.2cqi);
    margin: 5.2cqi var(--membership-card-pad) 0;
    padding-bottom: 2cqi;
}

.membership-card-kind {
    font-family: var(--vt-font-display);
    font-size: max(.625rem, 1.9cqi);
    letter-spacing: .24em;
    text-transform: uppercase;
}

.membership-card-brand {
    margin-top: .8cqi;
    font-family: var(--vt-font-brand);
    font-size: 3.5cqi;
    font-weight: 700;
    letter-spacing: .04em;
}

.membership-card-sub {
    max-width: calc(var(--membership-card-left) + var(--membership-card-emblem) * .208 - var(--membership-card-pad) - 3cqi);
    font-family: var(--vt-font-display);
    font-size: max(.625rem, 2.2cqi);
    font-style: italic;
}

/* An `h3`, for the leading of a heading: the card sets its own titles, so the section rhythm of a
   page leaves it alone. */
.membership-card-name {
    max-width: calc(var(--membership-card-left) - var(--membership-card-pad) - 3cqi);
    margin: auto 0 0;
    padding-top: 2cqi;
    color: inherit;
    font-family: var(--vt-font-display);
    font-size: 7cqi;
    font-weight: 700;
    overflow-wrap: anywhere;
    text-wrap: balance;
}

/* Under the arms, on a rule that runs into the blade: the bearer's papers. */
.membership-card-papers {
    flex-shrink: 0;
    width: calc(var(--membership-card-blade) - var(--membership-card-pad));
    margin: auto 0 4.8cqi var(--membership-card-pad);
    padding: 1.6cqi 3cqi 0 0;
    border-top: 1px solid currentColor;
}

.membership-card-legal {
    font-family: var(--vt-font-body);
    font-size: max(.625rem, 2cqi);
    text-wrap: balance;
}

.membership-card-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0 4.6cqi;
    margin: .8cqi 0 0;
}

.membership-card-facts div {
    display: flex;
    align-items: baseline;
    gap: 1.4cqi;
}

.membership-card-facts dt {
    font-family: var(--vt-font-display);
    font-size: max(.625rem, 1.9cqi);
    font-weight: 400;
    letter-spacing: .18em;
    text-transform: uppercase;
}

.membership-card-facts dd {
    margin: 0;
    font-family: var(--vt-font-display);
    font-size: max(.8125rem, 3.6cqi);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* --- Badges ------------------------------------------------------------- */

/* The roles a `.badge` may carry, matching the ones the alerts use. A wash of the
   hue behind a hairline of its ink, with the label in the ink too. Gold has no wash,
   so its tint stays neutral and only the line and the label are gold. */
.badge-success {
    --badge-rgb: var(--bs-success-rgb);
    --badge-ink: var(--vt-success-ink);
    --badge-ink-rgb: var(--vt-success-ink-rgb);
}

.badge-info {
    --badge-rgb: var(--bs-info-rgb);
    --badge-ink: var(--vt-info-ink);
    --badge-ink-rgb: var(--vt-info-ink-rgb);
}

.badge-warning {
    --badge-rgb: var(--bs-warning-rgb);
    --badge-ink: var(--vt-warning-ink);
    --badge-ink-rgb: var(--vt-warning-ink-rgb);
}

/* Brand and adverse are the same red here as everywhere else. `-primary` exists
   because that is the role a content body names when it labels something as ours. */
.badge-primary,
.badge-danger {
    --badge-rgb: var(--vt-accent-rgb);
    --badge-ink: var(--vt-accent-ink);
    --badge-ink-rgb: var(--vt-accent-ink-rgb);
}

.badge-gold {
    --badge-ink: var(--vt-gold);
    --badge-ink-rgb: var(--vt-gold-rgb);
}

/* --- Callouts ----------------------------------------------------------- */

/* Bootstrap's `.alert` is themed for the dark page in the theme section above, so it is
   the callout: use `.alert.alert-warning` and friends. This modifier restyles it as a
   flush aside — colour bar on the left, no box — and lays out an optional leading icon.
   The bar and the icon take the alert's ink, the panel its wash. */
.alert-flush {
    display: flex;
    gap: 1rem;
    border-width: 0 0 0 3px;
    border-left-color: rgb(var(--alert-rgb));
    border-radius: 0 var(--bs-border-radius) var(--bs-border-radius) 0;
    background: linear-gradient(90deg, rgba(var(--alert-wash-rgb), .13), rgba(var(--alert-wash-rgb), .03));
}

.alert-flush > i {
    flex: 0 0 auto;
    margin-top: .35rem;
    color: rgb(var(--alert-rgb));
    font-size: 1.15rem;
}

.alert-flush > :last-child {
    margin-bottom: 0;
}

/* --- The companion column ----------------------------------------------- */

/* Image with a caption, for the columns left over beside the reading column. The
   caption hangs off a short accent rule. */
.aside-figure {
    margin: 0 0 2.25rem;
}

.aside-figure img {
    display: block;
    width: 100%;
    height: auto;
    border: 1px solid var(--vt-border);
    border-radius: var(--bs-border-radius);
}

.aside-figure figcaption {
    margin-top: 1rem;
    color: var(--bs-secondary-color);
    font-size: .88rem;
}

.aside-figure figcaption::before {
    content: "";
    display: block;
    width: 2.5rem;
    margin-bottom: .75rem;
    border-top: 2px solid var(--vt-accent-ink);
}

/* An emblem instead of a photograph: a clan or sect mark, a discipline icon, drawn on
   transparency. It goes on the page itself and carries no frame, because the mark has no
   edges of its own and a border around it reads as an empty box with a glyph inside. */
.aside-mark {
    margin: 0 0 2.25rem;
    text-align: center;
}

/* Bounded on both axes, because a mark arrives in any proportion: the wide ones are held by the
   width and the tall ones by the height, and every one of them lands the same weight on the page. */
.aside-mark img {
    display: block;
    width: auto;
    max-width: min(13rem, 100%);
    height: auto;
    max-height: 15rem;
    margin: 0 auto;
}

.aside-mark figcaption {
    margin-top: 1rem;
    color: var(--bs-secondary-color);
    font-size: .88rem;
}

/* The tile a mark drawn in black sits on, inside an `.aside-mark`: on the near-black page such a
   mark is invisible, and on the site's paper it reads as a seal stamped on a document. The caption
   stays outside the tile, where the page's own text colour can be read. */
.aside-mark-paper {
    padding: 1.75rem;
    border: 1px solid var(--vt-border);
    border-radius: var(--bs-border-radius);
    background: linear-gradient(160deg, var(--vt-paper-from), var(--vt-paper-to));
}

/* A run of short entries for the companion column — the latest news, the next tournaments — each
   led by its title and closed by a muted line, a picture above the title where there is one. The
   titles are headings under the column's own, but read as the entries of a list: the reading face
   at body size, not a subsection. */
.aside-list :is(h3, h4) {
    margin: 0 0 .25rem;
    font-family: var(--vt-font-body);
    font-size: 1rem;
    font-weight: 400;
}

.aside-list img {
    border-radius: var(--bs-border-radius);
}

/* A sentence lifted out of the text, in the display face, with its source in
   `<cite>`. Companion column only: at full measure it competes with the text. */
.pull {
    margin: 0 0 2.25rem;
    padding-left: 1.25rem;
    border-left: 3px solid var(--vt-accent-ink);
    font-family: var(--vt-font-display);
    font-size: 1.2rem;
}

.pull > :last-child {
    margin-bottom: 0;
}

.pull cite {
    display: block;
    margin-top: .9rem;
    color: var(--bs-secondary-color);
    font-family: var(--vt-font-body);
    font-size: .78rem;
    font-style: normal;
    letter-spacing: .14em;
    text-transform: uppercase;
}

/* --- Emphasis ----------------------------------------------------------- */

/* Verbatim block: shows a format, a command or a naming convention. Pair with
   `<code>` so the monospace comes from the browser, not from a declaration.
   A wash of the accent behind its ink hairline. */
.literal {
    padding: 2rem 1.5rem;
    border: 1px solid rgba(var(--vt-accent-ink-rgb), .4);
    border-radius: var(--bs-border-radius);
    background-color: rgba(var(--vt-accent-rgb), .18);
    text-align: center;
}

.literal code {
    color: var(--bs-primary-text);
    font-size: 1.15rem;
}

.literal .eyebrow {
    margin: 2rem 0 .75rem;
}

.literal-secondary code {
    color: rgba(var(--vt-white-rgb), .8);
    font-size: 1rem;
}

/* The house button: the label in the display face as letterspaced capitals, on the padding a
   stamp needs. Compose with `.btn.btn-primary`, on the one action a page exists for — it is the
   only place the display face reaches a control, and it is what stops the action reading as a
   web widget dropped on an editorial page. */
.btn-seal {
    padding: .85rem 2.4rem;
    font-family: var(--vt-font-display);
    font-size: 1.05rem;
    letter-spacing: .14em;
    text-transform: uppercase;
}

/* Emphatic pill for a single key value: a deadline, a price, a result. A value is not the action
   the page exists for, so it is a wash of the brand red behind a hairline, never its solid fill. */
.seal {
    display: inline-block;
    font-family: var(--vt-font-display);
    padding: .55rem 1.4rem;
    border: 1px solid rgba(var(--vt-accent-ink-rgb), .42);
    border-radius: 999px;
    background: rgba(var(--vt-accent-rgb), .12);
    color: var(--vt-accent-ink);
    font-size: .95rem;
    letter-spacing: .12em;
    text-transform: uppercase;
}

/* --- Navigation --------------------------------------------------------- */

/* Inline list of anchors, separated by an ornament. A section index or a row of
   anchor breadcrumbs: navigation, so never a button. */
.inline-nav {
    display: flex;
    font-family: var(--vt-font-display);
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: .5rem 1.1rem;
    padding: .9rem 0;
    border-top: 1px solid var(--vt-hairline);
    border-bottom: 1px solid var(--vt-hairline);
    font-size: 1rem;
    letter-spacing: .16em;
    text-transform: uppercase;
}

/* A bar right under another is the level below it — a tournament's pages under its season's: it
   hangs off the first one's hairline instead of drawing a second, and steps down a size. The
   negative margin undoes the `mb-4` that `menu/inline.html.twig` gives every bar. */
.inline-nav + .inline-nav {
    margin-top: -1.5rem;
    border-top: 0;
    font-size: .88rem;
}

/* Paging is the one bar that is read as a row rather than followed as an index, so it is the
   one that is centred: a list of page numbers hanging off the left edge of a table reads as
   the start of another column. */
.inline-nav-center {
    justify-content: center;
    font-size: 1.05rem;
}

/* An entry that is a figure and nothing else — a page number, a year — is set in the display
   face, and that face draws its figures far shorter than its capitals, so at the size of the
   words beside them a digit reads as a speck. Set it larger, and drop the tracking: on a
   single glyph a letter-space is only a right margin that knocks it off centre. */
.inline-nav-num {
    font-size: 1.3rem;
    letter-spacing: 0;
}

.inline-nav a {
    padding-bottom: 2px;
    border-bottom: 1px solid transparent;
    color: rgba(var(--vt-white-rgb), .72);
    text-decoration: none;
    transition: color .15s ease, border-color .15s ease;
}

.inline-nav a:hover,
.inline-nav a.active {
    border-bottom-color: var(--vt-accent-ink);
    color: var(--bs-emphasis-color);
}

.inline-nav-sep {
    color: rgba(var(--vt-accent-ink-rgb), .55);
    font-size: .55rem;
}

/* The entry that leaves the bar's portal for the back office: not another page of the same place,
   so it is set apart in the info hue, a wash behind a hairline, never a fill. */
.inline-nav a.inline-nav-backoffice {
    padding: .1rem .75rem;
    border: 1px solid rgba(var(--vt-info-ink-rgb), .45);
    border-radius: 999px;
    background: rgba(var(--bs-info-rgb), .14);
    color: var(--vt-info-ink);
}

.inline-nav a.inline-nav-backoffice:hover {
    border-color: var(--vt-info-ink);
    color: var(--bs-emphasis-color);
}

/* The separator that stands for skipped pages. It says something the diamonds do not, so it
   is set at the size of the bar instead of the size of an ornament, where three dots vanish. */
.inline-nav-gap {
    font-size: .9rem;
}

/* The foot of a public page for whoever administers it: the way to its screen in the back office,
   set apart from the page by a hairline. Drawn by `partial/_button_edit.html.twig` only. */
.admin-bar {
    margin-top: 3rem;
    padding-top: 1rem;
    border-top: 1px solid var(--vt-hairline);
}

/* A heading jumped to through an anchor stops below the fixed navbar instead of under it. */
main [id] {
    scroll-margin-top: var(--vt-sticky-top);
}

/* The index of a long document, pinned beside it in the companion column: small, vertical, and
   lighting the section being read (`floating_nav_controller.js`). Below `lg` the column stacks,
   so it stops being pinned and reads as an ordinary list above the text. */
.floating-nav {
    padding-left: 1rem;
    border-left: 1px solid var(--vt-hairline);
    font-family: var(--vt-font-display);
    font-size: .85rem;
    letter-spacing: .08em;
}

@media (min-width: 992px) {
    .floating-nav {
        position: sticky;
        top: var(--vt-sticky-top);
        max-height: calc(100vh - var(--vt-sticky-top) - 2rem);
        overflow-y: auto;
    }
}

.floating-nav-title {
    display: block;
    margin-bottom: .75rem;
    color: var(--bs-secondary-color);
    font-size: .75rem;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.floating-nav ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.floating-nav li + li {
    margin-top: .4rem;
}

.floating-nav a {
    display: block;
    margin-left: calc(-1rem - 1px);
    padding-left: calc(1rem - 1px);
    border-left: 2px solid transparent;
    color: rgba(var(--vt-white-rgb), .72);
    text-decoration: none;
    transition: color .15s ease, border-color .15s ease;
}

.floating-nav a:hover,
.floating-nav a.active {
    border-left-color: var(--vt-accent-ink);
    color: var(--bs-emphasis-color);
}

/* The subsections of an entry, one step in and a size down, on the same rule as the sections so
   the lit bar still runs down the hairline. */
.floating-nav ul ul {
    margin-top: .4rem;
}

.floating-nav ul ul a {
    padding-left: calc(2rem - 1px);
    font-size: .78rem;
    letter-spacing: .04em;
}

/* Set by the controller when the subsections would not fit in the room the index has. */
.floating-nav-compact ul ul {
    display: none;
}

/* --- Tables ------------------------------------------------------------- */

/* Two-column ledger of label/value rows: the same hairline family as `.table`,
   narrower. Compose with Bootstrap's `.table`. */
.table-ledger {
    --bs-table-cell-padding-y: .85rem;
    --bs-table-cell-padding-x: .35rem;

    margin-bottom: 0;
}

.table-ledger th {
    width: 45%;
    font-family: var(--vt-font-display);
    color: var(--bs-secondary-color);
    font-weight: 400;
    font-size: .95rem;
    letter-spacing: .1em;
    text-transform: uppercase;
}

.table-ledger tr:last-child th,
.table-ledger tr:last-child td {
    border-bottom: 0;
}

/* Podium marks for a standings table. The rank is marked on its own cell, never by
   painting the row, and gold, silver and bronze mean a place and nothing else. */
.rank-1,
.rank-2,
.rank-3 {
    font-family: var(--vt-font-display);
    font-size: 1.2rem;
}

.rank-1 {
    color: var(--vt-gold);
}

.rank-2 {
    color: var(--vt-silver);
}

.rank-3 {
    color: var(--vt-bronze);
}

/* --- Forms: what is required, what unfolds ------------------------------ */

/* A required field says so after its label, in the accent ink; the note above the form says what
   the mark means. Symfony's form theme already puts `required` on those labels. */
.form-label.required::after,
.form-check-label.required::after {
    content: " *";
    color: var(--vt-accent-ink);
}

.form-required-note {
    color: var(--bs-secondary-color);
    font-size: .875rem;
}

/* A rule a field has to meet, as the help line under it, ticked off while it is typed by
   `password_rules_controller.js`. The mark is a glyph and not only a colour, so a met rule reads as
   met without telling the two inks apart. */
.form-rule::before {
    content: "○";
    display: inline-block;
    width: 1.25em;
}

.form-rule.is-met {
    color: var(--vt-success-ink);
}

.form-rule.is-met::before {
    content: "✓";
}

/* One of the few choices a form exists to make — the options of a ballot: the `.form-check` the
   form theme draws, boxed on a hairline with room around it, so each option reads as a decision of
   its own and not as a line of a list. */
.form-choice {
    margin-bottom: 1rem;
    padding: 1.5rem;
    border: 1px solid var(--vt-hairline);
    border-radius: var(--bs-border-radius);
}

/* A long text a form refers to, folded under the one line that says what it comes to. Native
   `<details>`, so it opens without a script and the browser keeps it reachable by keyboard. */
.disclosure {
    margin: 1rem 0;
    padding: .75rem 1rem;
    border: 1px solid var(--vt-border);
    border-radius: var(--bs-border-radius);
}

.disclosure > summary {
    color: var(--bs-secondary-color);
    font-size: .9rem;
    cursor: pointer;
}

.disclosure > summary:hover {
    color: var(--bs-body-color);
}

.disclosure[open] > summary {
    margin-bottom: .75rem;
}

.disclosure-body {
    color: var(--bs-secondary-color);
}

/* --- Search over a list ------------------------------------------------- */

/* One field and its button above a long table, as wide as the table it filters. */
.search-form {
    margin-bottom: 1.5rem;
}

.search-form-status {
    margin: .5rem 0 0;
    color: var(--bs-secondary-color);
    font-size: .875rem;
}

/* --- The final table ---------------------------------------------------- */

/* The final of a tournament, drawn as the table it was: the seats in the order they were seated,
   each player pointing at the one they preyed on, and the fifth closing back on the first. It is
   a circle because the table is one — this is the only shape that says what the seating means.
   The winner is named in the middle of the ring, and their seat carries the gold hairline.

   The ring is laid out for four and for five, which is every final the game plays, at every
   width: the public names are short, and under `md` the seats narrow and the type steps down.
   Any other count keeps a stacked list, the winner above it. */
.seating {
    display: flex;
    flex-direction: column;
    margin: 2rem 0 2.5rem;
}

.seating-seats {
    list-style: none;
    margin: 0;
    padding: 0;
}

.seating-seat {
    position: relative;
    margin-bottom: 2.25rem;
    padding: .85rem 1rem;
    border: 1px solid var(--vt-border);
    border-radius: var(--bs-border-radius);
    background-color: rgba(var(--vt-white-rgb), .035);
    text-align: center;
}

/* Stacked, the arrow is a chevron under each seat. The last one has nothing under it. */
.seating-seat::after {
    content: "▼";
    position: absolute;
    top: 100%;
    left: 50%;
    padding-top: .55rem;
    transform: translateX(-50%);
    color: rgba(var(--vt-accent-ink-rgb), .6);
    font-size: .7rem;
}

.seating-seat:last-child {
    margin-bottom: 0;
}

.seating-seat:last-child::after {
    content: none;
}

.seating-seat a {
    color: var(--bs-body-color);
    text-decoration: none;
}

.seating-seat a:hover {
    color: var(--bs-emphasis-color);
}

/* The seed each finalist earned in the rounds, as a small figure in the corner of the seat: the
   seat is where they chose to sit, the seed is the place that let them choose. */
.seating-seed {
    position: absolute;
    top: .15rem;
    left: .4rem;
    color: var(--bs-secondary-color);
    font-size: .75rem;
    font-variant-numeric: tabular-nums;
}

/* The VEKN number under the name, as the standings print it. */
.seating-vekn {
    display: block;
    color: var(--bs-secondary-color);
    font-size: .75rem;
    font-variant-numeric: tabular-nums;
}

/* The champion's seat: the honour is the gold hairline and the name in the display face. Gold is
   ink and line here as everywhere else — the seat is never filled with it. */
.seating-seat-champion {
    border-color: rgba(var(--vt-gold-rgb), .55);
}

.seating-seat-champion a {
    color: var(--vt-gold);
    font-family: var(--vt-font-display);
}

/* The winner, named: above the list when it is stacked, in the middle of the ring otherwise. */
.seating-center {
    order: -1;
    margin-bottom: 1.5rem;
    text-align: center;
}

.seating-center .eyebrow {
    display: block;
    margin-bottom: .15rem;
}

.seating-winner {
    color: var(--vt-gold);
    font-family: var(--vt-font-display);
    font-size: 1.35rem;
    text-decoration: none;
}

.seating-winner:hover {
    color: var(--bs-emphasis-color);
}

.seating-4,
.seating-5 {
    position: relative;
    display: block;
    width: 100%;
    max-width: 42rem;
    margin: 2.5rem auto 3rem;
    aspect-ratio: 1;
}

/* Ring and arrows in one drawing, used as a mask so the colour is still a token. The chevrons
   sit on the bisectors between seats and turn clockwise, which is the direction of play. */
.seating-4::before,
.seating-5::before {
    content: "";
    position: absolute;
    inset: 0;
    background-color: rgba(var(--vt-accent-ink-rgb), .6);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 100% 100%;
    mask-size: 100% 100%;
}

.seating-5::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='23' fill='none' stroke='%23fff' stroke-width='.45' stroke-dasharray='1.5 2.6'/%3E%3Cg fill='%23fff'%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(36 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(108 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(180 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(252 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(324 50 50)'/%3E%3C/g%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='23' fill='none' stroke='%23fff' stroke-width='.45' stroke-dasharray='1.5 2.6'/%3E%3Cg fill='%23fff'%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(36 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(108 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(180 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(252 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(324 50 50)'/%3E%3C/g%3E%3C/svg%3E");
}

.seating-4::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='23' fill='none' stroke='%23fff' stroke-width='.45' stroke-dasharray='1.5 2.6'/%3E%3Cg fill='%23fff'%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(45 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(135 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(225 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(315 50 50)'/%3E%3C/g%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='23' fill='none' stroke='%23fff' stroke-width='.45' stroke-dasharray='1.5 2.6'/%3E%3Cg fill='%23fff'%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(45 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(135 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(225 50 50)'/%3E%3Cpolygon points='48.4,25.7 52.4,27 48.4,28.3' transform='rotate(315 50 50)'/%3E%3C/g%3E%3C/svg%3E");
}

/* The seats are positioned against the figure, not the list, so the list itself takes no room. */
.seating-4 > .seating-seats > .seating-seat,
.seating-5 > .seating-seats > .seating-seat {
    position: absolute;
    width: 27%;
    margin: 0;
    padding: 1rem .35rem .5rem;
    font-size: .85rem;
    transform: translate(-50%, -50%);
}

.seating-4 > .seating-seats > .seating-seat::after,
.seating-5 > .seating-seats > .seating-seat::after {
    content: none;
}

/* Inside the ring of arrows, which is 46 % across. */
.seating-4 > .seating-center,
.seating-5 > .seating-center {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 40%;
    margin: 0;
    transform: translate(-50%, -50%);
}

.seating-4 > .seating-center .seating-winner,
.seating-5 > .seating-center .seating-winner {
    font-size: 1rem;
}

/* The seats sit on a circle of radius 38 %, the first at twelve o'clock and the rest
   clockwise. The ring of arrows is drawn at 23 %, which is as wide as it can be without
   running under the two seats at the sides. */
.seating-5 .seating-seat:nth-child(1) { top: 12%; left: 50%; }
.seating-5 .seating-seat:nth-child(2) { top: 38.26%; left: 86.14%; }
.seating-5 .seating-seat:nth-child(3) { top: 80.74%; left: 72.34%; }
.seating-5 .seating-seat:nth-child(4) { top: 80.74%; left: 27.66%; }
.seating-5 .seating-seat:nth-child(5) { top: 38.26%; left: 13.86%; }

.seating-4 .seating-seat:nth-child(1) { top: 12%; left: 50%; }
.seating-4 .seating-seat:nth-child(2) { top: 50%; left: 88%; }
.seating-4 .seating-seat:nth-child(3) { top: 88%; left: 50%; }
.seating-4 .seating-seat:nth-child(4) { top: 50%; left: 12%; }

@media (min-width: 768px) {
    .seating-4 > .seating-seats > .seating-seat,
    .seating-5 > .seating-seats > .seating-seat {
        width: 9rem;
        padding: .85rem 1rem;
        font-size: 1rem;
    }

    .seating-4 > .seating-center .seating-winner,
    .seating-5 > .seating-center .seating-winner {
        font-size: 1.35rem;
    }
}

/* --- Responsive / motion ------------------------------------------------ */

@media (min-width: 992px) {
    .paper {
        padding: 3rem;
    }
}

@media (max-width: 575.98px) {
    .section-head {
        gap: .85rem;
    }

    .section-marker {
        font-size: 2.4rem;
    }

    .dropcap::first-letter {
        font-size: 2.9rem;
    }

    .inline-nav {
        font-size: .8rem;
        letter-spacing: .1em;
    }

    .inline-nav-num {
        font-size: 1.05rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .floating-nav a,
    .inline-nav a {
        transition: none;
    }

    .masonry-item {
        animation: none;
        transition: none;
    }

    .thumb img {
        transition: none;
    }

    .masonry-img {
        filter: none;
        transition: opacity .3s ease;
    }
}
