/* #region Faces */
/* The panel's three faces come from the panel's own origin, never from a font service: an operator's
   address reaches nobody when a screen opens. Each brand's panel serves its own copies of these files
   under /fonts/ (the variable cuts, so every weight a screen asks for is one file). */
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('/fonts/PlusJakartaSans-VariableFont_wght.ttf') format('truetype');
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('/fonts/PlusJakartaSans-Italic-VariableFont_wght.ttf') format('truetype');
    font-weight: 200 800;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Playfair Display';
    src: url('/fonts/PlayfairDisplay-VariableFont_wght.ttf') format('truetype');
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Playfair Display';
    src: url('/fonts/PlayfairDisplay-Italic-VariableFont_wght.ttf') format('truetype');
    font-weight: 400 900;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Montserrat';
    src: url('/fonts/Montserrat-VariableFont_wght.ttf') format('truetype');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}
/* #endregion */

/* #region Tokens */
/* Every panel is the house seen from behind, so the palette, the hairline and the two typefaces
   are the houses' own: gold #b6a574 on near-black, Playfair Display for headings, Plus Jakarta Sans
   for everything a person has to read fast. A brand's own stylesheet loads after this one and leans
   on these tokens rather than restating them. */
:root {
    /* Every control the browser draws itself, drawn dark. The panel styles its own inputs but not
       the widgets inside them — the up/down arrows on a number field, the calendar button and the
       whole date picker behind it, the scrollbars, the block a browser paints over an autofilled
       field. Unset, those are the light-theme ones: a white stepper glaring out of a black cell on
       the stocktaking screen, and a white calendar dropping out of every date field in the panel.
       One declaration, because the cause is one thing: the browser has to be told which panel this
       is. */
    color-scheme: dark;

    --colorDark: #050505;
    --colorSurface: #080808;
    --colorSurfaceRaised: #0d0d0d;
    --colorWhite: #f5f5f5;
    --colorLight: #c8c8c8;
    --colorText: #e0e0e0;
    --colorMuted: #7d7d7d;
    --colorVeryLight: #fafafa;
    --colorAccent: #b6a574;
    --colorAccentSoft: rgba(182, 165, 116,0.55);
    --colorAccentFaint: rgba(182, 165, 116,0.08);
    /* One hairline for the whole panel. The name stays as it is: views carry var(--colorGray)
       in inline styles, and editors override it locally. */
    --colorGray: rgba(182, 165, 116,0.15);
    --colorGrayStrong: rgba(182, 165, 116,0.32);
    --colorRed: #d35050;
    --colorGreen: #6f9f78;
    /* The fourth state colour. Gold already means "waiting on us" and is the brand's own, so a
       record that is merely running needs a colour of its own to be told apart at a glance. */
    --colorBlue: #6f8ec4;
    --font: 'Plus Jakarta Sans', sans-serif;
    --fontDisplay: 'Playfair Display', serif;
    --fontLogo: 'Montserrat', sans-serif;
    /* Machine-written values (a deduplication key, an identifier) are compared character by
       character rather than read, so they are set in the reader's own monospace face — nothing
       is fetched for it, and every character keeps the same width whatever the system supplies. */
    --fontMono: ui-monospace, 'SFMono-Regular', 'Cascadia Mono', 'Consolas', monospace;
    --weightRegular: 400;
    --weightMedium: 500;
    --weightBold: 600;
    --sizeMicro: 10px;
    --sizeSmall: 12px;
    --sizeNormal: 14px;
    --sizeBig: 20px;
    --sizeLarge: 40px;
    --track: 0.14em;
    --length: 0.2s;
}
/* #endregion */

/* #region Reset & base */
html {
    margin: 0;
    padding: 0;
    background: var(--colorDark);
    color: var(--colorLight);
    font-family: var(--font);
    font-size: var(--sizeNormal);
    -webkit-font-smoothing: antialiased;
}

body {
    margin: 0;
    padding: 0;
    min-height: 100vh;
}

a {
    color: var(--colorLight);
    text-decoration: none;
    border-bottom: 1px solid var(--colorGrayStrong);
    cursor: pointer;
    transition: color linear var(--length), border-bottom-color linear var(--length);
}

    a:hover {
        color: var(--colorAccent);
        border-bottom-color: var(--colorAccent);
    }

/* Bold is weight alone, never a lift towards near-white: on a dense list — where the first cell
   of every row is bold — that reads as a column of lit text and tires the eye out. Where
   something has to be a different colour, it says so itself. */
b {
    font-weight: var(--weightBold);
}

small {
    color: var(--colorMuted);
    font-size: var(--sizeSmall);
}

::selection {
    background: var(--colorAccent);
    color: var(--colorDark);
}

input, select, textarea {
    font-family: var(--font);
    font-size: var(--sizeNormal);
    background: var(--colorSurface);
    color: var(--colorText);
}

    select option {
        font-family: var(--font);
        background: var(--colorDark);
    }

    input::placeholder,
    textarea::placeholder {
        color: #5a5a5a;
    }

textarea {
    resize: vertical;
}

:focus-visible {
    outline: 1px solid var(--colorAccentSoft);
    outline-offset: 2px;
}
/* #endregion */

/* #region Typography */
/* Headings name a screen; they are not the screen. Everything here is one or two steps down
   from the site's scale, because a panel heading that reads as a poster costs three rows of
   data on every list. */
h1, h2, h3, h4 {
    margin-top: 0;
    margin-bottom: 14px;
    color: var(--colorWhite);
    font-family: var(--fontDisplay);
    font-weight: var(--weightRegular);
    letter-spacing: -0.02em;
    line-height: 1.14;
}

h1 {
    /* The title names the screen and then gets out of the way: the data underneath it is
       what the operator came for, and every row it pushes below the fold costs a scroll. */
    margin-bottom: 16px;
    font-size: 28px;
}

    /* The counter or qualifier a heading carries is data, not display type: it stays sans,
       stays sentence case (it is often an e-mail address) and steps back in tone. */
    h1 small,
    h2 small,
    h3 small {
        display: inline-block;
        margin-left: 14px;
        color: var(--colorMuted);
        font-family: var(--font);
        font-size: var(--sizeSmall);
        font-weight: var(--weightMedium);
        letter-spacing: 0.1em;
        vertical-align: middle;
    }

        h1 small::before,
        h2 small::before,
        h3 small::before {
            content: "— ";
            color: var(--colorGrayStrong);
        }

    /* A condition of the whole screen — a missing integration, a switch left off — stated beside
       its title in red, because it changes how every row below is handled. It is not a counter,
       so it takes no em dash; it is not a case, so it never sits in the list. */
    h1 .page-warning,
    h2 .page-warning {
        display: inline-block;
        margin-left: 14px;
        color: var(--colorRed);
        font-family: var(--font);
        font-size: var(--sizeSmall);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
        vertical-align: middle;
    }

h2 {
    font-size: 21px;
}

h3 {
    font-size: 17px;
}

h4 {
    font-size: 15px;
}

/* The uppercase micro-label the site uses above every section: here it names a column,
   a field or a group without competing with the data underneath it. */
.eyebrow,
.dashboard-section {
    margin: 0 0 10px;
    color: var(--colorAccent);
    font-family: var(--font);
    font-size: var(--sizeMicro);
    font-weight: var(--weightMedium);
    letter-spacing: var(--track);
    text-transform: uppercase;
}

    /* A section label that follows something stands away from it: the label belongs to what is
       under it, and set tight against the previous block it reads as that block's footnote. The
       first one on a screen keeps its own spacing. */
    * + h2.dashboard-section {
        margin-top: 26px;
    }

    /* A table carries no margin of its own, and a heading none above it, so a heading straight after
       a table would sit on its last rule. The same holds for everything else a section can end with —
       a form, a table in its scrolling wrapper, a grid of columns, an empty-state line — so a new section
       always opens with the same breath above it, whatever the one before ended on. */
    main table + h2,
    main form + h2,
    main .table-wrapper + h2,
    main .columns-two + h2,
    main .columns-three + h2,
    main .form-actions + h2,
    main p.empty + h2 {
        margin-top: 26px;
    }

    /* A row of actions is a block like the rest, so whatever follows it opens with that same breath —
       not only a heading. A row of buttons carries no margin of its own and a form none above it, so the
       next form's first label sat directly under the buttons: on the Lens scenario screen the scenario's
       name appeared glued to Activate, which reads as one control with a caption rather than as two
       separate things to do. */
    main .form-actions + form,
    main .form-actions + .columns-two,
    main .form-actions + .columns-three,
    main .form-actions + .table-wrapper,
    main .form-actions + table {
        margin-top: 26px;
    }

    /* A step under the 12 px the shared heading rule gives it, and no further: the qualifier is a
       sentence somebody actually reads, so it stops short of the size a section label uses. It
       also drops the label's capitals rather than inheriting them — this is prose, not a tag. */
    .dashboard-section small {
        font-size: 11px;
        letter-spacing: 0.04em;
        text-transform: none;
    }

p.explanation,
p.empty {
    margin: 10px 0 14px;
    color: var(--colorMuted);
    font-size: var(--sizeSmall);
    line-height: 1.55;
}
/* #endregion */

/* #region Header */
header {
    position: sticky;
    top: 0;
    z-index: 900;
    /* The header owns its own stacking context, so nothing a screen draws can surface
       through an open dropdown. */
    isolation: isolate;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 34px;
    /* The same 16px the shell keeps, so the wordmark stands over the first column of data. */
    padding: 11px 16px;
    border-bottom: 1px solid var(--colorGray);
    color: var(--colorLight);
}

    /* The frosted pane is a layer of its own behind the bar, carrying both the tint and the blur.
       They cannot stay on the bar itself: backdrop-filter makes the element that carries it the
       root of its own backdrop, and a menu hanging out of that element is composited inside it,
       which puts an open dropdown behind the tiles of the screen it is meant to cover. Down
       here the pane has the page behind it to blur, and the menus above it are ordinary
       children of an ordinary stacking context. */
    header::before {
        content: "";
        position: absolute;
        inset: 0;
        z-index: -1;
        background: rgba(5, 5, 5, 0.92);
        backdrop-filter: blur(15px);
        -webkit-backdrop-filter: blur(15px);
        pointer-events: none;
    }

/* The logo is the site's logo: the brand's drawing (PanelOptions.WordmarkImageUrl) where there is one,
   and the letters where there is not. White rather than the accent, because a brand that lights its own
   name has nothing left to light the thing that matters on the screen below it. */
header > div > a,
header > div > a:hover {
    border-bottom: 0;
    color: var(--colorWhite);
    font-family: var(--fontLogo);
    /* A shade smaller than the site's: here the wordmark only says where you are, and the
       screen underneath it is a table. */
    font-size: 15px;
    font-weight: 300;
    letter-spacing: .6em;
    text-transform: uppercase;
    text-decoration: none;
    transition: opacity 0.3s;
}

    /* The letters' own line height would sit under a drawing as empty space, so the slot collapses to
       the mark — but only where the mark is a drawing, or the brand that kept its letters loses them. */
    header > div > a:has(img) {
        display: inline-block;
        line-height: 0;
    }

    /* The file is drawn 720 units tall for a 700-unit cap, so the height sets the letters themselves —
       15px of type with this tracking reads as about 11px of cap. */
    header > div > a img {
        display: block;
        width: auto;
        height: 11px;
    }

    header > div > a:hover {
        opacity: 0.7;
    }

header nav {
    flex: 1 1 auto;
}

    /* The menu sits on the right, against the way out. The wordmark holds the left edge and the
       space between them is the panel's own breathing room, not a gap to be filled. */
    header nav ul {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: flex-end;
        gap: 2px 24px;
        margin: 0;
        padding: 0;
        list-style-type: none;
    }

        header nav ul li {
            position: relative;
            margin: 0;
        }

            /* Sign-out keeps a small gap of its own — enough that it is not read as another
               section of the panel, not so much that it drifts off on its own. */
            header nav ul li.margin-left {
                margin-left: 18px;
                padding-left: 18px;
                border-left: 1px solid var(--colorGray);
            }

            header nav ul li > a,
            header nav ul li > span.nav-group,
            header nav ul li > form > button {
                display: inline-block;
                padding: 4px 0;
                border-bottom: 1px solid transparent;
                color: var(--colorLight);
                font-size: 11px;
                font-weight: var(--weightMedium);
                letter-spacing: var(--track);
                text-transform: uppercase;
                white-space: nowrap;
                transition: color linear var(--length), border-bottom-color linear var(--length);
            }

            header nav ul li > span.nav-group {
                cursor: default;
            }

            /* Sign-out is a POST form (a link would slip past the antiforgery guard),
               so its button is undressed back into the link it replaces. */
            header nav ul li > form {
                margin: 0;
            }

            /* Undressed back into the link it replaces — including on hover: the panel's own
               button rule fills a hovered button with gold, and gold-on-gold loses the sign-out
               label under the pointer. */
            header nav ul li > form > button:hover {
                background: none;
                color: var(--colorAccent);
            }

            header nav ul li > form > button {
                margin: 0;
                border: none;
                border-bottom: 1px solid transparent;
                background: none;
                font-family: inherit;
                line-height: inherit;
                cursor: pointer;
            }

            header nav ul li:hover > a,
            header nav ul li:hover > span.nav-group,
            header nav ul li:hover > form > button,
            header nav ul li > a.is-current {
                color: var(--colorAccent);
                border-bottom-color: var(--colorAccentSoft);
            }

            header nav ul li > span.nav-group.is-current {
                color: var(--colorAccent);
                border-bottom-color: var(--colorAccentSoft);
            }

            /* The groups on the right open leftwards, or the last of them would hang off the
               window — the bar is right-aligned, so its end is the screen's end. */
            header nav ul li:nth-last-child(-n+4) > ul.nav-dropdown {
                left: auto;
                right: -18px;
            }

            header nav ul li > ul.nav-dropdown {
                display: none;
                position: absolute;
                top: 100%;
                left: -18px;
                margin-top: 12px;
                min-width: 210px;
                padding: 8px 0;
                background: var(--colorSurfaceRaised);
                border: 1px solid var(--colorGray);
                box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
                list-style-type: none;
                z-index: 100;
                /* Its own compositor layer. A <video> with native controls is painted in a layer
                   of the browser's own, which an ordinary element does not always beat however
                   high its z-index — so without this the menu falls behind the cards on the
                   social board and on no other screen. */
                transform: translateZ(0);
            }

                /* The gap under the label is bridged by an invisible strip. Without it the pointer
                   leaves the item on its way down to the list and the menu closes before it can be used. */
                header nav ul li > ul.nav-dropdown::before {
                    content: "";
                    position: absolute;
                    top: -13px;
                    left: 0;
                    right: 0;
                    height: 13px;
                }

            header nav ul li:hover > ul.nav-dropdown {
                display: block;
            }

            header nav ul li > ul.nav-dropdown > li {
                display: block;
                margin: 0;
            }

                /* A caption inside a group — the product or the process the screens under it
                   belong to. It is not a link and never behaves like one: the bar names nine
                   parts of the business, and these say which part of a part you are looking at. */
                header nav ul li > ul.nav-dropdown > li.nav-heading {
                    margin: 12px 0 4px;
                    padding: 0 18px;
                    color: var(--colorAccent);
                    font-size: var(--sizeMicro);
                    font-weight: var(--weightMedium);
                    letter-spacing: var(--track);
                    text-transform: uppercase;
                    white-space: nowrap;
                }

                    header nav ul li > ul.nav-dropdown > li.nav-heading:first-child {
                        margin-top: 4px;
                    }

                header nav ul li > ul.nav-dropdown > li > a {
                    display: block;
                    padding: 9px 18px;
                    border-bottom: none;
                    color: var(--colorLight);
                    font-size: 11px;
                    font-weight: var(--weightMedium);
                    letter-spacing: var(--track);
                    text-transform: uppercase;
                    white-space: nowrap;
                    transition: color linear var(--length), background linear var(--length);
                }

                    header nav ul li > ul.nav-dropdown > li > a:hover,
                    header nav ul li > ul.nav-dropdown > li > a.is-current {
                        background: var(--colorAccentFaint);
                        color: var(--colorAccent);
                        border-bottom: none;
                    }

@media (max-width: 768px) {
    header {
        position: static;
        flex-direction: column;
        align-items: flex-start;
        gap: 18px;
        padding: 16px 14px;
    }

        header nav ul {
            justify-content: flex-start;
            gap: 4px 18px;
        }

            header nav ul li.margin-left {
                margin-left: 0;
                padding-left: 0;
                border-left: 0;
            }

            header nav ul li > ul.nav-dropdown {
                position: static;
                display: block;
                margin: 0;
                padding: 0;
                min-width: 0;
                background: transparent;
                border: none;
                box-shadow: none;
            }

                header nav ul li > ul.nav-dropdown::before {
                    display: none;
                }

                header nav ul li > ul.nav-dropdown > li > a {
                    padding: 4px 0;
                }
}
/* #endregion */

/* #region Page shell */
/* The panel is a working surface, not a magazine: a table of two hundred orders, a log, a
   month of Lens usage. Space is the scarce thing here, so the shell takes the whole window
   and keeps only enough margin to stop the data touching the glass. */
main {
    display: block;
    /* One stacking context for everything a screen draws, held at ground level. Without it a card,
       a sticky column header or a browser-composited <video> can surface through the open menu, and
       the alternative is answering that screen by screen. The header sits far above this and cannot
       be reached from inside it at all. */
    position: relative;
    z-index: 0;
    max-width: none;
    margin: 0;
    /* Room under the last thing on the screen. At 26 px a form's save button, or the final row of a
       list, sits on the bottom edge of the window and reads as though the page had been cut off
       rather than ended. */
    padding: 16px 16px 54px;
}

@media (max-width: 768px) {
    main {
        padding: 12px 12px 24px;
    }
}

/* Every screen opens the same way: actions to the right, title to the left, filters underneath. */
/* .pane-buttons is the same strip inside a tab pane, where a screen has an action belonging to
   one pane rather than to the page. It exists so that a screen with three such panes does not
   borrow the page-head's id three times over: an id is one element, and everything reaching for
   this one by name finds the header's instead. */
main div#page-buttons,
main div.pane-buttons {
    float: right;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 10px;
    margin: 4px 0 10px 24px;
}

main div.filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: -6px 0 12px;
}

main section.form-section {
    margin: 0 0 14px;
    padding: 14px 16px 16px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
}

    /* Two forms in one section are two decisions; the second one's first field must not sit on the
       first one's button. */
    /* Forms standing one under another in a section, and only those: a row of one-button forms inside it — an
       action strip, a scene's arrows and delete — is laid out by its own container, and pushed down 22px each
       its buttons stood on different lines. */
    main section.form-section > form + form {
        margin-top: 22px;
    }

    main section.form-section > h2 {
        margin: 0 0 12px;
        padding-bottom: 10px;
        border-bottom: 1px solid var(--colorGray);
        font-size: 18px;
    }

    /* The save sits close under the last row of fields. The fields already carry their own
       spacing underneath, so the button's default margin on top of it opens a gap wide enough
       to read as a missing field. */
    main section.form-section > form > button {
        margin-top: 0;
    }

    main section.form-section > p {
        margin: 0 0 12px;
        color: var(--colorText);
        line-height: 1.6;
    }

        main section.form-section > p:last-child {
            margin-bottom: 0;
        }

    /* Only the form that opens the section — right under its heading, or first of all — sits flush. A form
       further down follows something (a list of facts, a table, a fold) and takes the screen's one distance
       between blocks, like everywhere else. */
    main section.form-section > :is(h2, h3) + form,
    main section.form-section > form:first-child {
        margin-top: 0;
    }

        main section.form-section form:last-child {
            margin-bottom: 0;
        }

/* A record read as a record: the label is a quiet uppercase caption in a fixed column, the value
   sits on the same baseline, and one hairline separates each fact from the next. */
dl.facts {
    display: grid;
    grid-template-columns: minmax(150px, 220px) 1fr;
    margin: 0;
}

    dl.facts dt {
        padding: 6px 18px 6px 0;
        border-top: 1px solid var(--colorGray);
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        line-height: 1.7;
        text-transform: uppercase;
    }

    dl.facts dd {
        margin: 0;
        padding: 6px 0;
        border-top: 1px solid var(--colorGray);
        color: var(--colorText);
        line-height: 1.7;
        word-break: break-word;
    }

        dl.facts dt:first-of-type,
        dl.facts dt:first-of-type + dd {
            border-top: 0;
        }

        dl.facts dd small {
            display: block;
            margin-top: 3px;
        }

        /* A unit belongs to the figure in front of it, not under it. The rule above drops a
           <small> to its own line so a value can carry a second fact beneath it — a phone under
           an address, a note under a name — and a currency code is not a second fact. */
        dl.facts dd small.unit {
            display: inline;
            margin-top: 0;
        }

        /* A second rendering of the same fact — the line as the customer read it beside the
           configuration it names — stands on the fact's own line, apart by the gap an action takes. */
        dl.facts dd small.beside {
            display: inline;
            margin: 0 0 0 14px;
        }

        /* An action that undoes a fact belongs beside it, on the fact's own line — a state and the
           way back out of it are read together. A form is a block and its button carries a form's
           top margin, so both are undone here rather than by a view inventing an inline style. */
        dl.facts dd form.fact-action {
            display: inline;
        }

            dl.facts dd form.fact-action button {
                margin: 0 0 0 14px;
                padding: 2px 12px;
                vertical-align: baseline;
            }

/* A list of facts standing inside a form is a block of the form like any field, and needs the
   same air under it before whatever follows — usually the button that saves the rest. */
main form dl.facts {
    margin-bottom: 18px;
}

@media (max-width: 768px) {
    dl.facts {
        grid-template-columns: 1fr;
    }

        dl.facts dt {
            padding-bottom: 0;
        }

        dl.facts dd,
        dl.facts dt:first-of-type + dd {
            padding-top: 4px;
            border-top: 0;
        }
}

/* A transcript, not a table: the rule on the left says who spoke, the text runs full width. */
.transcript {
    display: grid;
    gap: 2px;
}

.transcript-line {
    padding: 10px 14px;
    background: var(--colorDark);
    box-shadow: inset 2px 0 0 var(--colorGray);
}

    .transcript-line.is-assistant {
        background: var(--colorSurfaceRaised);
        box-shadow: inset 2px 0 0 var(--colorAccent);
    }

    .transcript-line header {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        gap: 10px;
        margin-bottom: 8px;
    }

.transcript-role {
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    font-weight: var(--weightMedium);
    letter-spacing: var(--track);
    text-transform: uppercase;
}

.transcript-line.is-assistant .transcript-role {
    color: var(--colorAccent);
}

.transcript-meta {
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    letter-spacing: 0.04em;
}

.transcript-line p {
    margin: 0;
    max-width: 90ch;
    color: var(--colorText);
    line-height: 1.75;
    white-space: pre-wrap;
}

div.group {
    margin-top: 12px;
    padding: 0 14px 14px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
}

    div.group:first-of-type {
        margin-top: 20px;
    }

@media (min-width: 768px) {
    main .columns-two {
        display: grid;
        grid-template-columns: 1fr 1fr;
        grid-column-gap: 30px;
    }

    main .columns-three {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-column-gap: 30px;
    }

    main .columns-four {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr 1fr;
        grid-column-gap: 20px;
    }

    main .columns-five {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
        grid-column-gap: 20px;
        /* A grid of many short fields (a package's thirty addresses) runs over several rows, and fields whose
           own margin is zeroed would otherwise touch the row above. */
        grid-row-gap: 8px;
    }
}

/* A record read across the screen instead of down it: who this is, what was said to them, what
   we promised. The three are read separately, so they sit side by side — stacked, the promise
   made on the telephone sits several screens below the name of the person who made it. The
   columns are deliberately unequal: a list of facts is narrow, a trail of notes is not. They
   are held to the top, because the three columns never end level and a note column stretched
   to the height of the facts beside it would just be a tall empty box. */
@media (min-width: 1200px) {
    main .record-columns {
        display: grid;
        grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.35fr) minmax(0, 1fr);
        grid-column-gap: 20px;
        align-items: start;
    }

        /* A record whose state calls for no step has fewer than three readings — an object already shipped
           has its facts and nothing beside them. Three tracks kept for one or two leave the rest of the
           screen as an empty band on the right, so the tracks follow what is actually there. */
        main .record-columns:has(> :only-child) {
            grid-template-columns: minmax(0, 1fr);
        }

        main .record-columns:has(> :nth-child(2):last-child) {
            grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.35fr);
        }
}
/* #endregion */

/* #region Settings */
/* One switch per row, and the row says everything about it in the order the question is asked:
   what this is, what it is doing now, and the one control that changes it. Set as two columns of
   headings, badges and loose forms, which button belongs to which state has to be worked out — on the
   one screen that can close the shop. */
main .setting-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 320px) auto;
    align-items: center;
    gap: 10px 20px;
}

    /* The panel gives every div inside a form 12 px underneath it, which is right for a stack of
       fields and wrong for a row that is a grid: the two switches whose row sits inside a form
       collect that margin three times over — on the row, on the description and on the state —
       and stand visibly taller than the two whose row does not. */
    main form .setting-row,
    main .setting-row div {
        margin-bottom: 0;
    }

    /* A second switch in one section would rule off against the first; with one to a section
       there is nothing to rule off, and the row adds no spacing of its own. */
    main .setting-row + .setting-row {
        margin-top: 13px;
        padding-top: 13px;
        border-top: 1px solid var(--colorGray);
    }

/* The gap under the control matches the gap above it. The section's own bottom padding is four
   pixels deeper than the space a heading leaves beneath itself, which on a section holding one
   row puts the button visibly off-centre between the two edges. */
main section.form-section:has(.setting-row) {
    padding-bottom: 12px;
}

    main .setting-body strong {
        display: block;
        color: var(--colorWhite);
        font-size: var(--sizeNormal);
        font-weight: var(--weightMedium);
    }

    main .setting-body span {
        display: block;
        max-width: 68ch;
        margin-top: 4px;
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
        line-height: 1.55;
    }

    /* The state column: a badge, or the field that is the state. */
    main .setting-state {
        justify-self: start;
    }

        main .setting-state.is-field {
            justify-self: stretch;
        }

        main .setting-state div.input {
            margin: 0;
        }

    /* The row's own control sits at the end of it, always in the same place down the column, so
       the eye finds the buttons without reading the rows. */
    main .setting-row form,
    main .setting-row > button {
        margin: 0;
        justify-self: end;
    }

        main .setting-row form button {
            margin-top: 0;
        }

@media (max-width: 1400px) {
    main .setting-row {
        grid-template-columns: minmax(0, 1fr);
    }

        main .setting-row form,
        main .setting-row > button,
        main .setting-state {
            justify-self: start;
        }
}
/* #endregion */

/* #region Entries */
/* The shape for anything a person writes into a record and reads back: a note in a trail, a
   promise, a comment. Two parts, and they must not look alike — the gold-framed form that adds
   one, and the hairline-framed boxes holding the ones already written. The difference is the
   frame alone: both stand on the panel's own surface, so a column of entries reads as one
   surface with lines drawn on it rather than as a stack of tiles. */
main .entry-form {
    /* Set like every other form in a frame — fields straight on the section, no frame of its own —
       and parted from the trail below by one hairline, the same rule that parts rows elsewhere. */
    margin: 0 0 10px;
    padding: 0 0 14px;
    border-bottom: 1px solid var(--colorGray);
}

    /* The form's own submit sits tight under its last field, in the size every other action in
       the panel is: a full-size button inside a frame this small is the largest thing on it. */
    main .entry-form button {
        margin-top: 4px;
        padding: 6px 11px;
        font-size: var(--sizeMicro);
        letter-spacing: var(--track);
    }

    main .entry-form div.input:last-of-type {
        margin-bottom: 0;
    }

main .entry-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Two or three standalone actions side by side inside a section — each its own form, because
   each is its own decision. They read from the left like the save button of a form, not from
   the right like the buttons of a dialog. */
main .form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

    main .form-actions form {
        margin: 0;
    }

    main .form-actions button {
        margin-top: 0;
    }

/* A flag is a flag wherever it stands, not only inside a table cell — the fact lists on a
   record use the same mark for the same thing. Square, like the flags of the seven-language
   field: one shape for a language across the panel. */
img.flag-small {
    width: 14px;
    height: 14px;
    margin-right: 5px;
    border: 1px solid var(--colorGray);
    object-fit: cover;
    vertical-align: middle;
}

/* An entry is a paragraph somebody wrote, and a paragraph in a table cell is either a column
   too narrow to read or a row too tall to scan past. So: the facts once along the top, the text
   at full width under them, the actions in the corner where actions live. */
main .entry {
    padding: 9px 12px 10px;
    border: 1px solid var(--colorGray);
}

    main .entry.is-overdue {
        box-shadow: inset 3px 0 0 var(--colorRed);
    }

    main .entry.is-due-today {
        box-shadow: inset 3px 0 0 var(--colorAccent);
    }

    /* Values only, no labels: a date reads as a date and an address reads as an address, and
       three labels would be longer than the three facts they name. */
    main .entry-head {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 2px 12px;
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

        main .entry-head .entry-kind {
            color: var(--colorAccent);
        }

        /* Who wrote it is the least of the three and goes to the far end, where it can be
           ignored while the date and the kind are being read. */
        main .entry-head .entry-author {
            margin-left: auto;
            text-transform: none;
            letter-spacing: 0.02em;
        }

    main .entry-body {
        margin-top: 6px;
        color: var(--colorText);
        font-size: var(--sizeSmall);
        line-height: 1.55;
        word-break: break-word;
    }

    /* What can be done to an entry rides on the line that says who wrote it. As a row of chips
       underneath, it costs a centimetre per entry — on a trail of twenty, the whole record. They
       are text, like the actions in a table row, for the same reason: a bordered chip is taller
       than the line of data beside it. */
    main .entry-links {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 2px 12px;
    }

        main .entry-links form {
            margin: 0;
        }

        main .entry-links button,
        main .entry-links a {
            display: inline;
            margin: 0;
            padding: 0;
            border: 0;
            background: none;
            color: var(--colorMuted);
            font-family: var(--font);
            font-size: var(--sizeMicro);
            font-weight: var(--weightMedium);
            letter-spacing: var(--track);
            line-height: inherit;
            text-decoration: none;
            text-transform: uppercase;
            cursor: pointer;
            transition: color var(--length);
        }

            main .entry-links button:hover,
            main .entry-links a:hover {
                background: none;
                color: var(--colorAccent);
            }

            /* Deleting is the one thing here that cannot be undone, and in this panel red is the
               colour that means "act". */
            main .entry-links button.button-red {
                color: var(--colorRed);
            }

    /* Ready-made phrases under a field: one click writes the usual half of the sentence. */
    main .entry-presets {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        margin-top: 6px;
    }

        main .entry-presets button {
            margin: 0;
            padding: 4px 9px;
            border: 1px solid var(--colorGray);
            font-size: var(--sizeMicro);
            letter-spacing: var(--track);
        }
/* #endregion */

/* #region Buttons, actions and filters */
/* One shape for anything a person clicks that is not body copy: an outlined, tracked
   uppercase chip that fills with gold on hover, like the site's call to action. */
form button,
div.buttons button,
/* Translate beside a seven-language field is the same control whether or not the field sits in a form — the
   subtitle editor's words are posted as JSON, not by a form, and there it showed as the browser's grey box. */
main .translation-tabs button.translation-translate {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 12px;
    padding: 10px 20px;
    border: 1px solid var(--colorGrayStrong);
    background: transparent;
    color: var(--colorLight);
    font-family: var(--font);
    font-size: 11px;
    font-weight: var(--weightMedium);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    cursor: pointer;
    transition: border-color var(--length), color var(--length), background var(--length);
}

    form button:hover,
    div.buttons button:hover,
    main .translation-tabs button.translation-translate:hover {
        border-color: var(--colorAccent);
        background: var(--colorAccent);
        color: var(--colorDark);
    }

/* A control that cannot be pressed has to look like one. Undressed, a disabled button is the same
   outlined gold chip as a live one, hovers like one and does nothing when clicked, which reads as a
   panel at fault rather than as a button waiting for something. Dimmed and with the arrow cursor it
   says so before the click. */
form button:disabled,
div.buttons button:disabled {
    border-color: var(--colorGray);
    color: var(--colorMuted);
    cursor: not-allowed;
}

    form button:disabled:hover,
    div.buttons button:disabled:hover {
        border-color: var(--colorGray);
        background: transparent;
        color: var(--colorMuted);
    }

/* The two names the views already use: button-red is the committing action, button-dark the way out. */
button.button-red {
    border-color: var(--colorAccentSoft);
    color: var(--colorAccent);
}

button.button-dark {
    border-color: var(--colorGray);
    color: var(--colorMuted);
}

    button.button-dark:hover {
        border-color: var(--colorGrayStrong);
        background: transparent;
        color: var(--colorLight);
    }

div.buttons {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 12px;
}

    div.buttons > * {
        margin-left: 0;
    }

/* Row actions, page actions and filter chips share one size, so a link and a form button
   sitting next to each other in the same cell cannot look like two different controls. */
main div#page-buttons > a,
main div#page-buttons > button,
main div.pane-buttons > a,
main div.pane-buttons > button,
/* An action that has to be a POST is wrapped in a form, which puts its button one level deeper.
   Unnamed here it falls back to the full-size form button, margin and all, and the header bar it
   sits in stands taller than the same bar on the screen next door. */
main div#page-buttons > form > button,
main div.pane-buttons > form > button,
/* The same control standing in the body of a screen rather than in its header — a player's markers, a
   strip of acts beside what they act on. Outside a form a <button> has no panel rule at all and shows
   as the browser's grey box. */
main div.button-strip > button,
main div.filters > a,
/* Page numbers are the same control as everything else a person clicks on a list screen, so
   they are sized here rather than in a rule of their own that would drift from this one. */
main div.pagination > a,
main table tr td div.chips > a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* A flex box swallows the whitespace between its children, so the space typed between a
       chip's label and its count is not enough to separate them. */
    gap: 7px;
    margin: 0;
    padding: 6px 11px;
    border: 1px solid var(--colorGray);
    background: transparent;
    color: var(--colorLight);
    font-family: var(--font);
    font-size: var(--sizeMicro);
    font-weight: var(--weightMedium);
    letter-spacing: var(--track);
    line-height: 1.3;
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: border-color var(--length), color var(--length), background var(--length);
}

    main div#page-buttons > a:hover,
    main div#page-buttons > button:hover,
    main div#page-buttons > form > button:hover,
    main div.pane-buttons > a:hover,
    main div.pane-buttons > button:hover,
    main div.pane-buttons > form > button:hover,
    main div.button-strip > button:hover,
    main div.filters > a:hover,
    main div.pagination > a:hover,
    main table tr td div.chips > a:hover {
        border-color: var(--colorAccent);
        background: var(--colorAccentFaint);
        color: var(--colorAccent);
    }

/* A filter with no state of its own — All, and the plain ones beside it — is still one of ours,
   so its hairline is the brand's gold rather than the grey of a table rule. */
main div.filters > a {
    border-color: var(--colorAccentSoft);
}

/* A filter that carries a warning keeps its colour while it is only an option; once it is the
   filter in force it goes gold like any other, so the screen states one thing at a time. */
main div.filters > a.is-alert {
    border-color: rgba(211, 80, 80, 0.45);
    color: var(--colorRed);
}

    main div.filters > a.is-alert:hover {
        border-color: var(--colorRed);
        background: rgba(211, 80, 80, 0.1);
        color: var(--colorRed);
    }

/* A chip for the amber state — something waiting on us, without the alarm of red. */
main div.filters > a.is-pending {
    border-color: var(--colorAccentSoft);
    color: var(--colorAccent);
}

    main div.filters > a.is-pending:hover {
        border-color: var(--colorAccent);
        background: var(--colorAccentFaint);
        color: var(--colorAccent);
    }

main div.filters > a.is-positive {
    border-color: rgba(111, 159, 120, 0.45);
    color: var(--colorGreen);
}

    main div.filters > a.is-positive:hover {
        border-color: var(--colorGreen);
        background: rgba(111, 159, 120, 0.1);
        color: var(--colorGreen);
    }

main div.filters > a.is-current,
main div.filters > a.is-current:hover {
    border-color: var(--colorAccent);
    background: var(--colorAccent);
    color: var(--colorDark);
}

main div.filters > a b {
    font-weight: var(--weightBold);
}

main div.filters > span.filters-divider {
    width: 1px;
    height: 18px;
    background: var(--colorGray);
}

/* A cell holding several equal links — the seven locales of one message, the formats of one
   material — reads as a row of chips, not as a sentence of links. It wraps rather than stacking:
   the actions column's narrow-screen rule below turns chips into full-width blocks, and seven
   of those in one cell is a column nobody can scan. */
main table tr td div.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

    /* A row of flags is already a row of chips — the picture is the chip, so the border and the
       padding around it only make the cell taller. */
    main table tr td div.chips.is-flags {
        align-items: center;
        gap: 8px;
    }

        /* A material that exists in versions — one document at several statuses — draws one line of
           flags per version, so each line has to say which version it is. The name is a chip's
           label without the chip around it: same size and tracking, no border, one fixed width so
           the flags underneath line up and the three lines read as one control. */
        main table tr td div.chips.is-flags + div.chips.is-flags {
            margin-top: 6px;
        }

        /* A fixed width, not a minimum, so every line starts its flags at the same place. The labels are
           three-letter abbreviations with the full name in the hint. */
        main table tr td div.chips.is-flags > span.chips-label {
            flex: 0 0 40px;
            width: 40px;
            color: var(--colorMuted);
            font-size: var(--sizeMicro);
            font-weight: var(--weightMedium);
            letter-spacing: var(--track);
            line-height: 1.3;
            text-transform: uppercase;
            white-space: nowrap;
        }

        main table tr td div.chips.is-flags > a {
            padding: 0;
            border: 0;
        }

            main table tr td div.chips.is-flags > a:hover {
                background: none;
                opacity: 0.7;
            }

            main table tr td div.chips.is-flags > a img {
                margin: 0;
                vertical-align: middle;
            }

main table tr td.cell-actions {
    white-space: nowrap;
}

    /* Actions are text, not chips. A bordered chip is taller than the line of data beside it,
       so the row could never be shorter than its buttons — and on a list of two hundred orders
       that height is the whole screen. They read as what they are: small, tracked, gold on hover. */
    main table tr td.cell-actions a,
    main table tr td.cell-actions button {
        display: inline;
        margin: 0 12px 0 0;
        padding: 0;
        border: 0;
        background: none;
        color: var(--colorMuted);
        font-family: var(--font);
        /* A step up from the micro size: these are the things a person clicks on a list, and set
           at the size of a column caption they read as a label rather than as an action. */
        font-size: 11px;
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        line-height: inherit;
        text-transform: uppercase;
        text-decoration: none;
        white-space: nowrap;
        cursor: pointer;
        transition: color var(--length);
    }

        main table tr td.cell-actions a:last-child,
        main table tr td.cell-actions button:last-child {
            margin-right: 0;
        }

        main table tr td.cell-actions a:hover,
        main table tr td.cell-actions button:hover {
            background: none;
            color: var(--colorAccent);
        }

    main table tr td.cell-actions form,
    main div#page-buttons form,
    main div.pane-buttons form {
        display: inline;
        margin: 0;
    }

        main table tr td.cell-actions form div,
        main div#page-buttons form div,
        main div.pane-buttons form div {
            display: inline;
            margin: 0;
        }

/* #endregion */

/* #region Tables */
/* The table bleeds into the shell's margin by exactly its own cell padding, so the first
   column's text keeps the page's left edge while the rows themselves run the full window. */
main table {
    width: calc(100% + 20px);
    margin-left: -10px;
    margin-right: -10px;
    border-collapse: collapse;
    font-size: var(--sizeNormal);
    line-height: 1.4;
}

    main table tr th {
        padding: 6px 10px;
        border-bottom: 1px solid var(--colorGrayStrong);
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-align: left;
        text-transform: uppercase;
        white-space: nowrap;
    }

    main table tr td {
        /* A list is read by the row, so a row is as short as its content allows: everything a
           shorter row adds up to is one more record visible without a scroll. */
        padding: 6px 10px;
        border-top: 1px solid var(--colorGray);
        border-bottom: 1px solid var(--colorGray);
        color: var(--colorLight);
        text-align: left;
        vertical-align: top;
    }

        main table tr td a {
            color: var(--colorLight);
        }

        main table tr td img.flag,
        main table tr td img.flag-small,
        main table tr th img.flag-small {
            width: 20px;
            height: 20px;
            border: 1px solid var(--colorGray);
            object-fit: cover;
            margin-right: 5px;
            margin-top: 4px;
            margin-bottom: -4px;
        }

        main table tr td img.flag-small,
        main table tr th img.flag-small {
            width: 14px;
            height: 14px;
            margin-top: 2px;
            margin-bottom: 0;
        }

        main table tr td img.flag-blink {
            animation: blink 1.4s ease-in-out infinite;
        }

    main table tr td .tooltip img.flag {
        height: 16px;
    }

    main table tr td img.photo {
        height: 60px;
        border: 1px solid var(--colorGray);
    }

/* A field shown for one choice only (data-show-when): hidden means gone, whatever display a rule gives it. */
[data-show-when][hidden] {
    display: none !important;
}

/* The answers a field pointing at another record offers while it is typed (data-suggest): hung under
   the field, the name first and the address after it, because the name is what somebody recognises
   and the address is what the form saves. */
.suggest-host {
    position: relative;
}

ul.suggest-list {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 50;
    min-width: 100%;
    max-height: 280px;
    margin: 2px 0 0;
    padding: 4px 0;
    overflow-y: auto;
    list-style: none;
    border: 1px solid var(--colorGrayStrong);
    background: var(--colorSurface);
    white-space: nowrap;
}

    ul.suggest-list li {
        padding: 6px 12px;
        color: var(--colorText);
        font-size: var(--sizeSmall);
        cursor: pointer;
    }

        ul.suggest-list li b {
            font-weight: var(--weightMedium);
        }

        ul.suggest-list li span {
            margin-left: 10px;
            color: var(--colorMuted);
        }

        ul.suggest-list li:hover,
        ul.suggest-list li.is-active {
            background: var(--colorGray);
            color: var(--colorAccent);
        }

/* The same picture beside a file field is a preview of what the upload would replace, not the
   picture itself — the full image is one click away, in its own tab. */
main form img.photo {
    display: block;
    width: 160px;
    height: 160px;
    margin-bottom: 8px;
    border: 1px solid var(--colorGray);
    object-fit: cover;
}

    /* A thumbnail that costs the list nothing: the cell gives up its padding, the square fills the
       row's own height and the row stays one line tall — a 60 px photograph makes every row in the
       journal four lines deep for a picture nobody can judge at that size anyway. Judging it is
       what the hover is for. */
    main table tr td.cell-thumb {
        width: 1px;
        padding: 0;
        position: relative;
    }

        /* The row's marker (red, gold) is the first cell's inset rule, which a thumbnail with no padding
           covered completely. So a thumbnail that opens the row keeps exactly the rule's width free on its
           left: the marker stands beside the picture, never on it. Only the first cell — a second
           thumbnail in the row (an artwork beside the artist) is not where a row's marker belongs. */
        main table tr > td.cell-thumb:first-child {
            padding-left: 3px;
        }

        main table tr td.cell-thumb img.photo-thumb {
            display: block;
            width: 30px;
            height: 30px;
            /* Square, like every image in the system, and cropped rather than squashed. */
            object-fit: cover;
        }

    main table tr td.cell-highlight {
        color: var(--colorWhite);
        font-weight: var(--weightBold);
    }

    main table tr th.cell-border-left,
    main table tr td.cell-border-left {
        border-left: 1px solid var(--colorGrayStrong);
    }

    main table tr.inactive td {
        opacity: 30%;
    }

        main table tr.inactive td img,
        main table tr.inactive td video {
            filter: grayscale(100%);
            opacity: 30%;
        }

        main table tr.inactive td a {
            border-color: var(--colorMuted);
            color: var(--colorMuted);
        }

            main table tr.inactive td a:hover {
                color: var(--colorLight);
                border-color: var(--colorLight);
            }

    main table tr.important td {
        color: var(--colorRed);
    }

        main table tr.important td a {
            color: var(--colorRed);
            border-bottom-color: var(--colorRed);
        }

            main table tr.important td a:hover {
                color: var(--colorLight);
                border-bottom-color: var(--colorLight);
            }

    main table tr:hover td {
        background: var(--colorAccentFaint);
        color: var(--colorWhite);
    }

td.cell-count {
    font-size: var(--sizeSmall);
}

div.small {
    color: var(--colorMuted);
    font-size: var(--sizeSmall);
    line-height: 1.35;
}

    div.small:first-of-type {
        margin-top: 3px;
    }

.column-no-wrap {
    white-space: nowrap;
}

a.no-underline {
    border-bottom: none;
    text-decoration: none;
}

@media (max-width: 768px) {
    div.table-wrapper {
        width: 100%;
        overflow-x: auto;
    }
}
/* #endregion */

/* #region Pagination */
/* The strip itself. The numbers on it are sized by the shared control rule above, so a page
   number, a filter chip and a row action are one size on every screen. */
main div.pagination {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    margin-top: 26px;
}

    /* The ellipsis stands for pages nobody can click, so it is not drawn as something to. */
    main div.pagination > a.pagination-gap {
        border-color: transparent;
        cursor: default;
    }

        main div.pagination > a.pagination-gap:hover {
            border-color: transparent;
            background: transparent;
            color: var(--colorMuted);
        }

        main div.pagination a:hover {
            border-color: var(--colorAccent);
            color: var(--colorAccent);
        }

        main div.pagination a.pagination-current {
            border-color: var(--colorAccent);
            background: var(--colorAccent);
            color: var(--colorDark);
            font-weight: var(--weightMedium);
        }
/* #endregion */

/* #region Forms */
main form div {
    margin-bottom: 12px;
}

/* Both shapes the panel uses are covered: a label above its field, and a label wrapping it.
   Scoped to a div instead, half the forms — the delivery address, the internal note — render
   as bare browser controls. */
main form label {
    display: block;
    margin-bottom: 5px;
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    font-weight: var(--weightMedium);
    letter-spacing: var(--track);
    text-transform: uppercase;
}

    main form label + label {
        margin-top: 18px;
    }

/* A control belongs to a form in one of two ways: it sits inside it, or it names it with the form=
   attribute. The second kind is how a screen puts one row's fields in several forms without nesting them —
   the Lens storyboard does it for every shot — and written as a descendant selector alone this whole dress
   missed them: they kept the browser's own border and height, next to fields wearing the panel's, which is
   what made that screen look half-styled. Every rule below that says `main form <control>` says the
   attribute form too. */
main form input:not([type="hidden"]),
main form select,
main form textarea,
main input[form]:not([type="hidden"]),
main select[form],
main textarea[form] {
    width: 100%;
    /* The padding and the hairline count towards the width, not on top of it. Without this a
       field asks for 100% of its column and then adds 22 px to it, so a textarea hangs out past
       the edge of the panel it sits in — invisible at full width, obvious the moment a column
       is narrow. */
    box-sizing: border-box;
    padding: 8px 10px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
    color: var(--colorText);
    font-family: var(--font);
    font-size: var(--sizeNormal);
    /* A wrapping label is uppercase; what is typed into it is not. */
    text-transform: none;
    letter-spacing: normal;
    transition: border-color var(--length);
}

    main form label > input,
    main form label > select,
    main form label > textarea {
        margin-top: 8px;
    }

/* A file field in the house's own dress. The browser's bare control — a grey system button and a line of
   system text — was the one field in the panel that looked borrowed. The field keeps the box every input has,
   drawn dashed because it is a place to drop a file rather than to type; its button is the panel's outlined,
   tracked chip that fills with gold, and the chosen file's name sits quietly beside it. */
main form input[type="file"] {
    padding: 6px;
    border-style: dashed;
    border-color: var(--colorGrayStrong);
    color: var(--colorMuted);
    font-size: var(--sizeSmall);
    cursor: pointer;
}

    main form input[type="file"]:hover {
        border-color: var(--colorAccentSoft);
    }

    main form input[type="file"]::file-selector-button {
        margin-right: 14px;
        padding: 8px 16px;
        border: 1px solid var(--colorGrayStrong);
        background: transparent;
        color: var(--colorLight);
        font-family: var(--font);
        font-size: 11px;
        font-weight: var(--weightMedium);
        letter-spacing: 0.18em;
        text-transform: uppercase;
        cursor: pointer;
        transition: border-color var(--length), background var(--length), color var(--length);
    }

        main form input[type="file"]:hover::file-selector-button {
            border-color: var(--colorAccent);
            background: var(--colorAccent);
            color: var(--colorDark);
        }

/* A tick is not a field. The rule above dresses every input in a form as a full-width padded box,
   which is right for something typed into and absurd for a checkbox. A div.checkbox wrapper corrects
   only a checkbox written inside one: written any other way — beside its words in a label, in a table
   cell, in a column of settings — a checkbox comes out stretched across its column with a border round
   it. This is the same size and the same accent that wrapper gives, applied wherever the tick is
   written. */
main form input[type="checkbox"],
main form input[type="radio"],
main input[form][type="checkbox"],
main input[form][type="radio"] {
    width: 20px;
    height: 20px;
    padding: 0;
    accent-color: var(--colorAccent);
    vertical-align: middle;
}

    /* Beside its words rather than above them, when the label wraps the tick. */
    main form label > input[type="checkbox"],
    main form label > input[type="radio"] {
        margin-top: 0;
        margin-right: 6px;
    }

    main form input:focus,
    main form select:focus,
    main form textarea:focus,
    main input[form]:focus,
    main select[form]:focus,
    main textarea[form]:focus {
        outline: none;
        border-color: var(--colorAccentSoft);
    }

    main form select[multiple] {
        height: 200px;
    }

/* A textarea grows with what is typed into it, so nobody drags a corner to read what they just
   wrote. No drag handle, because there is no manual sizing: the height is set by script on load and
   on every keystroke. The ceiling exists for the long ones — a soul's prompt,
   an article's section — where a field the height of the text would be a field nobody can see
   the buttons under; past it the field scrolls, as it always did. */
main form textarea {
    height: auto;
    min-height: 62px;
    max-height: 60vh;
    resize: none;
    overflow-y: auto;
    line-height: 1.6;
}

    /* The same fact on a list row, after the wording: the language codes that carry nothing.
       It sits on its own line so a long title is not pushed out of the cell by it. */
    small.translation-missing {
        display: block;
        margin-top: 3px;
        font-size: var(--sizeMicro);
        letter-spacing: var(--track);
    }

    /* One field in seven languages: a row of square flags, one open pane under it. The flag's frame is the
       language's state — green written, a thick red frame empty — so which languages are missing is read off the
       row, and the flag that is open stands at full strength while the rest step back. */
    main .translation-tabs {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 6px;
        margin-bottom: 6px;
    }

        main .translation-tabs .translation-flag {
            display: block;
            margin: 0;
            padding: 0;
            border: 2px solid var(--colorGreen);
            background: none;
            line-height: 0;
            opacity: 0.55;
            cursor: pointer;
        }

            /* A missing language pulses, like a missing flag in a table: a red frame among green ones is
               easy to read past on a long form, a light going on and off is not. */
            main .translation-tabs .translation-flag.is-empty {
                border: 3px solid var(--colorRed);
                animation: blink 1.4s ease-in-out infinite;
            }

            /* A flag is a button inside a form, and a form's button fills with gold and turns its words dark on
               hover — which left the reader count beside the flag dark on the dark panel, gone under the pointer.
               A flag only steps forward. */
            main .translation-tabs .translation-flag.is-current,
            main .translation-tabs .translation-flag:hover {
                background: none;
                color: var(--colorLight);
                opacity: 1;
            }

            main .translation-tabs .translation-flag img {
                display: block;
                width: 18px;
                height: 18px;
                object-fit: cover;
            }

            /* A count beside the flag, where a screen has one per language (the readers of a letter). */
            main .translation-tabs .translation-flag b {
                display: block;
                padding: 0 6px;
                font-size: var(--sizeMicro);
                line-height: 18px;
            }

            main .translation-tabs .translation-flag:has(b) {
                display: flex;
                align-items: center;
            }

        main .translation-tabs button.translation-translate {
            margin: 0 0 0 8px;
            padding: 3px 12px;
        }

        main .translation-tabs .translation-notice {
            font-size: var(--sizeSmall);
        }

    main form div div.translation div.translation-pane {
        margin-bottom: 6px;
    }

    main form div div.input {
        display: flex;
        align-items: center;
        gap: 10px;
        margin-bottom: 0;
    }

    main form div div.checkbox {
        display: flex;
        align-items: center;
        gap: 12px;
        margin-bottom: 0;
    }

        main form div div.checkbox input[type="checkbox"] {
            width: 20px;
            height: 20px;
            padding: 0;
            margin: 0;
            accent-color: var(--colorAccent);
        }

        main form div div.checkbox label {
            margin-bottom: 0;
        }

        /* The rule above takes the field's margin off because a tick usually sits inside a field's own
           div, under its label, like div.input. Standing as a row of its own with a field after it — a
           switch heading the fields it enables — it is a field itself and keeps the field's gap. */
        main form div div.checkbox:has(+ div) {
            margin-bottom: 12px;
        }

    /* The sentence under a field that explains what it does. It reads as a hint, not as data. */
    main form div > small {
        display: block;
        margin-top: 7px;
        max-width: 70ch;
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
        line-height: 1.6;
    }

/* A refusal stated where the mistake is. It is the one explanatory text in the panel that stays
   visible without hovering, because an error must not hide — and it is the same mark whether the
   controller decided it or the browser did. */
main form span.field-validation-error {
    display: block;
    margin-top: 6px;
    color: var(--colorRed);
    font-size: var(--sizeSmall);
    font-weight: var(--weightMedium);
}

/* The same refusal gathered at the head of a form, for the three screens that show one: an artist
   record, the artist letter and the subscribers' letter. Unstyled, a rejected save prints its
   reasons in ordinary grey body text above the fields — indistinguishable from the form's own
   explanatory sentences, which is exactly the thing an error must not be. Keyed on
   the class the validation tag helper itself stamps — it writes validation-summary-errors when
   there is something to say and validation-summary-valid when there is not — so the empty div it
   always renders stays invisible without this stylesheet having to guess at its contents. */
main form .validation-summary-errors {
    margin: 0 0 16px;
    padding: 11px 14px;
    border-left: 3px solid var(--colorRed);
    background: var(--colorSurface);
    color: var(--colorRed);
    font-size: var(--sizeSmall);
    font-weight: var(--weightMedium);
    line-height: 1.55;
}

    main form .validation-summary-errors ul {
        margin: 0;
        padding-left: 18px;
    }

/* The field itself is marked too: the sentence underneath says what is wrong, the border says
   which of the three fields it is about. */
main form input[aria-invalid="true"],
main form select[aria-invalid="true"],
main form textarea[aria-invalid="true"],
main input[form][aria-invalid="true"],
main select[form][aria-invalid="true"],
main textarea[form][aria-invalid="true"] {
    border-color: var(--colorRed);
}

main form textarea {
    font-family: var(--font);
    font-size: var(--sizeNormal);
}

input.search-box,
select.search-box {
    padding: 8px 12px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
    color: var(--colorText);
    font-family: var(--font);
    font-size: var(--sizeSmall);
    transition: border-color var(--length);
}

    input.search-box:focus,
    select.search-box:focus {
        outline: none;
        border-color: var(--colorAccentSoft);
    }
/* #endregion */

/* #region Messages, dialog and tooltip */
/* One sentence saying what just happened, as a strip across the whole window under the bar.
   As a bordered panel inside the content column it is tall enough to push the first row of data below
   the fold on every save, and a confirmation that costs a scroll is a worse confirmation. Solid rather
   than outlined, because at this height an outline is a smudge. */
div#message-success,
div#message-failure {
    margin: 0;
    padding: 6px 16px;
    border: 0;
    /* Darker than the state green used for text and tints: white on that lighter green is legible
       but works for it, and this strip is read in passing or not at all. */
    background: #3f6f4d;
    color: var(--colorWhite);
    font-family: var(--font);
    font-size: var(--sizeSmall);
    font-weight: var(--weightMedium);
    letter-spacing: 0.02em;
}

div#message-failure {
    background: var(--colorRed);
}

/* A dialog with no background of its own is drawn white by the browser, which on a black
   panel is a flash in the face. It is a panel surface like any other. */
dialog {
    padding: 40px;
    min-width: 400px;
    max-width: min(560px, calc(100vw - 40px));
    border: 1px solid var(--colorGray);
    background: var(--colorSurfaceRaised);
    color: var(--colorLight);
    font-family: var(--font);
    font-size: var(--sizeNormal);
    box-shadow: 0 30px 80px rgba(0, 0, 0, 0.7);
}

    dialog[open] {
        animation: fadein 0.15s ease-in forwards;
    }

    dialog::backdrop {
        background-color: var(--colorDark);
        opacity: 0.82;
    }

    dialog form {
        margin: 0;
    }

    dialog h2 {
        margin: 0 0 18px;
        font-size: 24px;
    }

    dialog p {
        margin: 0;
        color: var(--colorText);
        line-height: 1.7;
    }

    dialog div.buttons {
        margin-top: 10px;
    }

    /* The reason an action needs, asked in the confirmation itself — the one field a dialog may carry. */
    dialog div.dialog-reason {
        margin: 16px 0 0;
    }

        dialog div.dialog-reason label {
            display: block;
            margin-bottom: 5px;
            color: var(--colorMuted);
            font-size: var(--sizeMicro);
            font-weight: var(--weightMedium);
            letter-spacing: var(--track);
            text-transform: uppercase;
        }

        dialog div.dialog-reason textarea {
            width: 100%;
            min-height: 70px;
            padding: 10px 12px;
            border: 1px solid var(--colorGrayStrong);
            background: var(--colorDark);
            color: var(--colorText);
            font-family: var(--font);
            font-size: var(--sizeNormal);
            resize: vertical;
        }

        dialog div.dialog-reason small {
            display: block;
            margin-top: 6px;
        }

@media (max-width: 768px) {
    dialog {
        padding: 24px;
        min-width: 0;
        width: calc(100vw - 40px);
    }
}

.tooltip {
    min-width: 30px;
    /* An absolutely positioned box is offered the width of whatever it is anchored in, and that
       is usually a narrow table header — so it wraps into a column two words wide. It takes
       its natural width instead, and only then is it held to the limit. */
    width: max-content;
    max-width: min(700px, calc(100vw - 40px));
    position: absolute;
    top: 0;
    left: 0;
    padding: 10px 12px;
    background: var(--colorSurfaceRaised);
    border: 1px solid var(--colorGrayStrong);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
    color: var(--colorLight);
    /* Every text property is stated here, none inherited. The tooltip is written into the page
       wherever its (i) stands — inside a heading, a column header, a field label, a fold's
       summary — and each of those styles its own text. A heading is set in Playfair, so the
       same sentence comes out serif over one icon and sans over the next; a column header is
       uppercase and tracked, a label is smaller again. The guidance must read identically
       whatever it hangs from, so nothing about it is left to the neighbourhood. */
    font-family: var(--font);
    font-style: normal;
    font-weight: var(--weightRegular);
    font-size: var(--sizeSmall);
    font-variant: normal;
    letter-spacing: normal;
    word-spacing: normal;
    line-height: 1.5;
    text-align: left;
    text-indent: 0;
    text-transform: none;
    /* A tooltip is usually anchored in a table header, and a header cell is nowrap so its label
       never breaks. Inherited, that turns every tooltip into one endless line running out of
       its own box — so the wrapping is restored here, beside the other inherited resets. */
    white-space: normal;
    display: none;
    z-index: 1000;
}

    .tooltip div.tooltip-arrow {
        position: absolute;
        width: 20px;
        height: 20px;
        margin-top: -1px;
        background: var(--colorSurfaceRaised);
        border: 1px solid var(--colorGrayStrong);
        border-bottom: 0;
        border-right: 0;
        transform: rotate(45deg);
    }

mark {
    padding: 2px 6px;
    border: 1px solid var(--colorAccentSoft);
    background: transparent;
    color: var(--colorAccent);
    font-size: var(--sizeSmall);
    font-weight: var(--weightMedium);
}

/* A state marker in a row: a hairline chip, not a coloured pill. Six hues from another palette, one
   per fact, read as six warnings. */
span.badge {
    display: inline-block;
    margin: 2px 4px 2px 0;
    padding: 3px 8px;
    border: 1px solid var(--colorGray);
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    font-weight: var(--weightMedium);
    letter-spacing: var(--track);
    text-transform: uppercase;
    white-space: nowrap;
}

    span.badge.is-positive {
        border-color: rgba(111, 159, 120, 0.45);
        color: var(--colorGreen);
    }

    span.badge.is-alert {
        border-color: rgba(211, 80, 80, 0.45);
        color: var(--colorRed);
    }

/* A consent read as a dot, green given and red not: set larger than the text around it, because at the
   type's own size the two colours are a pixel apart and the column has to be read at a glance. */
main span.is-yes,
main span.is-no {
    font-size: 16px;
    line-height: 1;
    vertical-align: middle;
}

main span.is-yes {
    color: var(--colorGreen);
}

main span.is-no {
    color: var(--colorRed);
}

/* Three words for a state, so a table never has to carry a colour in an inline style. The hover
   rule is repeated here because a row highlight must not wash the signal out of the cell. */
main .is-alert-text,
main table tr:hover td.is-alert-text {
    color: var(--colorRed);
}

    /* A link inside a warning stays the warning's colour: taking the sentence's one word that leads
       somewhere out of the red divides the sentence in half. The hairline under it, and gold on hover,
       are what say it is a link. */
    main .is-alert-text a {
        color: inherit;
    }

main .is-positive-text,
main table tr:hover td.is-positive-text {
    color: var(--colorGreen);
}

main .is-pending-text,
main table tr:hover td.is-pending-text {
    color: var(--colorAccent);
}

main .is-info-text,
main table tr:hover td.is-info-text {
    color: var(--colorBlue);
}

/* A state that is simply over — cancelled, archived, closed. It steps back rather than
   colouring, because a finished row competing with a waiting one is the whole problem. */
main .is-quiet-text,
main table tr:hover td.is-quiet-text {
    color: var(--colorMuted);
}

/* The row's own colour, and only for the exceptions. A tinted row is read before any cell in it is,
   which is the whole point: scanning two hundred records for the three that are wrong should not
   mean reading a status column. So only two states tint — wrong, and waiting on us — beside the
   dimmed row that is over; a row that is running or done is plain, and its status word carries the
   colour. A page where every row wears one is a page where none of them says anything. The tint
   travels as a variable so the hover highlight still wins over it. */
main table tr.row-alert {
    --rowTint: rgba(211, 80, 80, 0.11);
}

main table tr.row-pending {
    --rowTint: rgba(182, 165, 116, 0.10);
}

/* A cell that holds more than it shows. One line by default, because a list is worth having only
   while it can be scanned — one exception with its stack trace is taller than twenty ordinary
   rows. The plus stays at the top left of the cell so the column of them reads as a column. */
main table tr td.cell-expand {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

    main table tr td.cell-expand button.expand-toggle {
        flex: 0 0 auto;
        width: 16px;
        height: 16px;
        margin: 1px 0 0;
        padding: 0;
        border: 1px solid var(--colorGrayStrong);
        background: transparent;
        color: var(--colorMuted);
        font-family: var(--font);
        font-size: 11px;
        font-weight: var(--weightMedium);
        line-height: 1;
        cursor: pointer;
        transition: color var(--length), border-color var(--length);
    }

        main table tr td.cell-expand button.expand-toggle:hover {
            border-color: var(--colorAccent);
            background: transparent;
            color: var(--colorAccent);
        }

    main table tr td.cell-expand .expandable {
        min-width: 0;
        /* Clamped rather than height-capped, so the first line ends in an ellipsis and says for
           itself that there is more — a cut line reads as a line that happens to be short. */
        display: -webkit-box;
        -webkit-line-clamp: 1;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

        main table tr td.cell-expand .expandable.is-expanded {
            display: block;
            overflow: visible;
            /* An unbroken stack trace is one word as far as the layout is concerned, and it would
               push the table wider than the screen rather than wrap. */
            overflow-wrap: anywhere;
        }

/* A technical value carried under the one it belongs to — a deduplication key under the subject
   of the message it deduplicates. It is read once in a hundred openings of a screen, so it is set
   as small as it can be read and tight enough to cost the row no height. Monospace, because such a
   key is compared with another one rather than read: identical prefixes then line up under each
   other, and the characters that a proportional face makes ambiguous stay apart. */
main table tr td small.cell-subtle {
    display: block;
    margin-top: -2px;
    color: var(--colorMuted);
    font-family: var(--fontMono);
    font-size: 9px;
    letter-spacing: 0;
    line-height: 1.2;
    word-break: break-all;
}

/* Which way a figure moved against the period just before it (_Trend): small, beside the figure, green up
   and red down — read in passing down a column, the exact change is under the cursor. */
span.trend {
    margin-left: 4px;
    font-size: 9px;
    vertical-align: middle;
    cursor: default;
}

    span.trend.is-up {
        color: var(--colorGreen);
    }

    span.trend.is-down {
        color: var(--colorRed);
    }

/* The heading row of a group inside a table: the part of the site, with its own totals beside it. Gold
   and bold at the table's own size — the group is read before its events, and its figures are numbers to
   compare with the rows under them, which a smaller type made harder rather than easier. */
main table tr.row-group > td {
    padding-top: 16px;
    border-bottom: 1px solid var(--colorGrayStrong);
    color: var(--colorAccent);
    font-weight: var(--weightBold);
}

/* The panel's category palette: six hues for telling one kind of record from another, and none
   of them a state. Red and green are spoken for — red acts, green is done — so a category never
   borrows either, and gold is reserved for "waiting on us". Opaque, because they colour a mark a
   few pixels wide rather than a whole row: a thinned hue that size is only a grey dot. */
:root {
    --catViolet: rgb(150, 110, 220);
    --catAzure: rgb(70, 140, 235);
    --catTeal: rgb(45, 185, 190);
    --catAmber: rgb(230, 160, 60);
    --catRose: rgb(230, 110, 160);
    --catLime: rgb(150, 195, 70);
}

/* What kind of record a row is — a customer's category, a product, a rung on a ladder, a role —
   is the word that names it, set in the kind's colour, never the row's background: a row's colour
   is kept for the exceptions above. The word itself carries the meaning, so the colour is a shortcut
   for those who have learnt it and never the only carrier. A square beside the word said the same
   thing twice and read as a control nobody could click. Each module names its own kinds as
   modifiers setting --catColor; a kind keeps one colour panel-wide. */
main .cat-name {
    color: var(--catColor, var(--colorMuted));
}

/* The three roles carry no state: violet for the role that can grant access to others, blue for
   the one with the same reach and not that power, and grey-green for day-to-day work. Gold is
   deliberately not among them — in this panel gold means something is waiting on us, and a CEO
   is not a warning. */
.cat-name.is-role-ceo {
    --catColor: rgb(158, 134, 196);
}

.cat-name.is-role-coo {
    --catColor: rgb(111, 142, 196);
}

.cat-name.is-role-concierge {
    --catColor: rgb(122, 146, 150);
}

main table tr > td {
    background: var(--rowTint, transparent);
}

/* And a bar down the left edge, because a tint alone is a colour somebody has to have been told
   about, while a bar reads as a marker. It sits on the first cell: a border-collapse table
   draws nothing of its own on a row. */
main table tr.row-alert > td:first-child {
    box-shadow: inset 3px 0 0 var(--colorRed);
}

main table tr.row-pending > td:first-child {
    box-shadow: inset 3px 0 0 var(--colorAccent);
}

/* One hover for every thumbnail in a list, wherever the list is. A picture in a table is small on
   purpose — a row is one line tall, and a 60 px photograph makes every row four lines deep for
   something nobody can judge at that size anyway. Judging it is what this is for: about 320 px
   while the pointer is on it, whatever size the list draws it at — one factor for every size left
   the smallest thumbnail at 150 px, still too small to judge — anchored at the left edge so it opens
   over the rows rather than over the title beside it, and lifted, because a table cell paints its own
   background over an untouched z-index. Nothing in the layout moves, so no row changes height. */
main table td img.photo-thumb,
main table td img.thumb,
main table td img.thumb-large,
main table td img.photo {
    transition: transform var(--length);
}

    main table td img.photo-thumb:hover,
    main table td img.thumb:hover,
    main table td img.thumb-large:hover,
    main table td img.photo:hover {
        position: relative;
        z-index: 10;
        transform-origin: left center;
    }

    /* The factor per drawn size: 30, 50, 60 and 80 px each open to about 320. */
    main table td img.photo-thumb:hover {
        transform: scale(11);
    }

    main table td img.thumb:hover {
        transform: scale(6.4);
    }

    main table td img.photo:hover {
        transform: scale(5.3);
    }

    main table td img.thumb-large:hover {
        transform: scale(4);
    }

/* A thumbnail in a list: one square, one hairline, never a hand-written width. */
main table td img.thumb {
    width: 50px;
    height: 50px;
    border: 1px solid var(--colorGray);
    object-fit: cover;
}

main table td img.thumb-large {
    width: 80px;
    height: 80px;
    border: 1px solid var(--colorGray);
    object-fit: cover;
}

/* The tag picker: one row per group — the group's name in a narrow column on the left, its tags as small chips
   beside it. Each chip is a checkbox in a label: the box itself is hidden and the chip fills with gold while it
   is ticked. The form's own rules (a spaced block per div, uppercase block labels) are undone here, because
   seventy tags set as form fields fill a screen. */
main div.tag-picker {
    display: grid;
    gap: 8px;
    margin: 4px 0 0;
}

    main form div.tag-picker div.tag-group {
        display: grid;
        grid-template-columns: 96px minmax(0, 1fr);
        align-items: baseline;
        gap: 10px;
        margin: 0;
    }

    main div.tag-picker span.tag-group-label {
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    main form div.tag-picker div.tag-chips {
        display: flex;
        flex-wrap: wrap;
        gap: 5px;
        margin: 0;
    }

    main form div.tag-picker label.tag-chip {
        position: relative;
        display: inline-flex;
        margin: 0;
        cursor: pointer;
        letter-spacing: normal;
        text-transform: none;
    }

        main form div.tag-picker label.tag-chip input[type="checkbox"] {
            position: absolute;
            width: 1px;
            height: 1px;
            opacity: 0;
            pointer-events: none;
        }

        main form div.tag-picker label.tag-chip span {
            padding: 3px 9px;
            border: 1px solid var(--colorGray);
            color: var(--colorLight);
            font-size: 12px;
            line-height: 1.5;
            transition: border-color var(--length), background var(--length), color var(--length);
        }

        main form div.tag-picker label.tag-chip:hover span {
            border-color: var(--colorAccentSoft);
        }

        main form div.tag-picker label.tag-chip input:checked + span {
            border-color: var(--colorAccent);
            background: var(--colorAccent);
            color: var(--colorDark);
        }

        main form div.tag-picker label.tag-chip input:focus-visible + span {
            outline: 1px solid var(--colorAccent);
            outline-offset: 2px;
        }

/* A two-way switch at the top of a form (one kind of record or another): the same hidden-radio chips as the
   tag picker, larger, joined into one segmented control. */
main form div.segment-switch {
    display: inline-flex;
    margin: 0 0 18px;
    border: 1px solid var(--colorGrayStrong);
}

    main form div.segment-switch label {
        position: relative;
        display: inline-flex;
        margin: 0;
        cursor: pointer;
    }

        main form div.segment-switch label input[type="radio"] {
            position: absolute;
            width: 1px;
            height: 1px;
            opacity: 0;
            pointer-events: none;
        }

        main form div.segment-switch label span {
            padding: 9px 18px;
            color: var(--colorMuted);
            font-size: 11px;
            font-weight: var(--weightMedium);
            letter-spacing: 0.18em;
            text-transform: uppercase;
            transition: background var(--length), color var(--length);
        }

        main form div.segment-switch label input:checked + span {
            background: var(--colorAccent);
            color: var(--colorDark);
        }

        main form div.segment-switch label input:focus-visible + span {
            outline: 1px solid var(--colorAccent);
            outline-offset: -3px;
        }

        /* A choice that cannot be made now stays in its place, dimmed, so the switch keeps its shape. */
        main form div.segment-switch label:has(input:disabled) {
            cursor: default;
            opacity: 0.35;
        }

main table .cell-prewrap {
    white-space: pre-line;
}

.visits-unresolved {
    color: var(--colorAccent);
}

.big-top-margin {
    margin-top: 24px !important;
}

/* #endregion */

/* #region Statistics */
div.statistics {
    margin-bottom: 30px;
    color: var(--colorLight);
    font-weight: var(--weightMedium);
    line-height: 1.7;
}

    div.statistics b {
        color: var(--colorAccent);
    }

    div.statistics small {
        font-size: var(--sizeSmall);
    }

table.table-statistics img.flag {
    height: 16px;
    vertical-align: middle;
    margin-top: -5px;
}

table.table-statistics b {
    color: var(--colorAccent);
}

table.table-statistics div.tooltip section {
    margin-top: 0;
    margin-bottom: 10px;
}

    table.table-statistics div.tooltip section:last-of-type {
        margin-bottom: 0;
    }

table.table-statistics div.tooltip b {
    color: var(--colorWhite);
}
/* #endregion */

/* #region Dashboard */
.dashboard-intro {
    max-width: 90ch;
    margin: 0 0 30px;
    color: var(--colorMuted);
    font-size: var(--sizeSmall);
    line-height: 1.7;
}

/* The house: figures that are worth reading even when nothing is wrong. */
/* Six across, the same six the tiles below it keep: the dashboard is read as rows of six, and a
   row that reflows to five while the one under it holds six turns a screen into two grids. */
.pulse-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 1px;
    margin-bottom: 18px;
    border: 1px solid var(--colorGray);
    background: var(--colorGray);
}

/* A screen with two or three figures rather than the dashboard's six. The band's background is
   what draws the hairlines between tiles, so on a fixed six-column grid the empty tracks are
   painted too — four columns of nothing in the same frame as the figures. Sized to its own
   content, the frame ends where the tiles end. */
.pulse-grid.is-compact {
    grid-template-columns: repeat(auto-fit, minmax(180px, 240px));
    width: max-content;
    max-width: 100%;
}

@media (max-width: 1500px) {
    .pulse-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    /* The compact band sizes itself, so it needs none of the narrower-screen column counts. */
    .pulse-grid.is-compact {
        grid-template-columns: repeat(auto-fit, minmax(180px, 240px));
    }
}

@media (max-width: 900px) {
    .pulse-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.pulse-card {
    display: block;
    padding: 13px 16px 15px;
    border: 0;
    background: var(--colorSurface);
    transition: background var(--length);
}

    .pulse-card:hover {
        background: var(--colorSurfaceRaised);
    }

    .pulse-card small {
        display: block;
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    .pulse-card strong {
        display: block;
        margin: 8px 0 5px;
        color: var(--colorWhite);
        font-family: var(--fontDisplay);
        font-size: 28px;
        font-weight: var(--weightRegular);
        letter-spacing: -0.03em;
        line-height: 1;
    }

    .pulse-card:hover strong {
        color: var(--colorAccent);
    }

    .pulse-card span {
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
    }

    /* The figure against its previous period. Growth is green — the one number on this screen
       that is allowed to celebrate; a decline stays quiet, because a slow month is a fact to
       know, not an alarm to answer. */
    .pulse-card .pulse-trend {
        display: block;
        margin-top: 4px;
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        letter-spacing: 0.05em;
    }

        .pulse-card .pulse-trend.is-up {
            color: var(--colorGreen);
        }

/* The good news: what actually happened lately, written as sentences. It sits under the pulse
   because the numbers say how the house is doing and this says what it just did. */
.wins {
    margin: 0 0 18px;
    padding: 12px 16px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
    box-shadow: inset 3px 0 0 var(--colorGreen);
}

    .wins p {
        margin: 0 0 5px;
        color: var(--colorText);
        font-size: var(--sizeSmall);
        line-height: 1.6;
    }

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

    .wins b {
        color: var(--colorGreen);
    }

/* The all-clear becomes the reward it is, not an empty grey box. */
.attention-clear.is-positive {
    border-color: rgba(111, 159, 120, 0.45);
    box-shadow: inset 3px 0 0 var(--colorGreen);
    color: var(--colorText);
}

.attention-clear {
    margin: 0 0 28px;
    padding: 16px 18px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
    color: var(--colorMuted);
    font-size: var(--sizeSmall);
}

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 30px;
}

@media (max-width: 1500px) {
    .dashboard-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 900px) {
    .dashboard-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* #region Next steps */
/* The band a record screen opens with: what to do with this record, before any of its facts. It
   is deliberately the same vocabulary as the dashboard's rows — an instruction, the sentence that
   explains it, and the way to the control — so the first screen of the day and the record itself
   say the same thing in the same words. */
.next-steps {
    margin: 0 0 22px;
    padding: 14px 18px 16px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
}

/* The same band on a list screen, and deliberately lighter than the record's: a record's band is
   instructions to read, a module's is a row of counts to aim at. It sits between the heading and
   the table, so it has to cost almost no height — a list is the one screen where a row of data is
   worth more than a row of chrome. */
.module-work {
    margin: 0 0 14px;
}

    .module-work h2 {
        margin: 0 0 8px;
        color: var(--colorMuted);
        font-family: var(--font);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

.module-work-items {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* One figure and what it is. The count leads, in the display face the dashboard's jobs use: it is
   what decides whether the next ten minutes go here. */
.module-work-item {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 7px 12px;
    border: 1px solid var(--colorGray);
    border-left-width: 3px;
    background: var(--colorSurface);
    color: var(--colorText);
    transition: border-color var(--length), background var(--length);
}

    a.module-work-item:hover {
        border-color: var(--colorAccent);
        background: var(--colorSurfaceRaised);
    }

    /* A figure on a screen that is already showing everything it has. It carries the same colour
       and weight — it is the same fact — and only drops the affordance of somewhere to go. */
    .module-work-item.is-static {
        cursor: default;
    }

    .module-work-item.is-alert {
        border-left-color: var(--colorRed);
    }

    .module-work-item.is-action {
        border-left-color: var(--colorAccent);
    }

    .module-work-item b {
        font-family: var(--fontDisplay);
        font-size: var(--sizeNormal);
    }

    .module-work-item span {
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
    }

    .next-steps h2 {
        margin: 0 0 10px;
        color: var(--colorMuted);
        font-family: var(--font);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    .next-steps ol {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .next-steps li {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: baseline;
        gap: 4px 16px;
        padding: 9px 0 9px 14px;
        /* The state on the leading edge, as on the dashboard's rows and a table's own state
           colours: red has run out of time, gold is our turn, a dim bar is nothing to do. */
        border-left: 3px solid var(--colorGray);
    }

        .next-steps li + li {
            border-top: 1px solid var(--colorGray);
        }

        .next-steps li.is-alert {
            border-left-color: var(--colorRed);
        }

        .next-steps li.is-action {
            border-left-color: var(--colorAccent);
        }

        .next-steps li b {
            color: var(--colorWhite);
            font-size: var(--sizeNormal);
            font-weight: var(--weightMedium);
        }

        .next-steps li.is-waiting b {
            color: var(--colorMuted);
        }

        .next-steps li small {
            grid-column: 1;
            color: var(--colorMuted);
            font-size: var(--sizeSmall);
            line-height: 1.5;
        }

        .next-steps li a {
            grid-row: 1 / span 2;
            grid-column: 2;
            align-self: center;
            color: var(--colorAccent);
            font-size: var(--sizeSmall);
            white-space: nowrap;
        }
/* #endregion */

/* #region The day's work */
/* The dashboard's own rows. A tile has room for a number and three words, and three words force
   a label to name a state — "In production, awaiting shipment" — leaving the reader to work out
   what to do about it. A row has room for the instruction, the
   sentence that explains it and the name of the screen it lands on, which is the whole of what
   somebody opening the panel in the morning needs. */
.jobs {
    display: grid;
    gap: 6px;
    margin-bottom: 30px;
}

.job {
    display: grid;
    grid-template-columns: 62px minmax(0, 1fr) auto;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    border: 1px solid var(--colorGray);
    /* The state is carried by a bar down the leading edge rather than by the whole border: on a
       list of rows a full coloured outline round every one of them is a cage, and the eye stops
       telling the red ones from the gold ones — which is the only thing the colour is for. */
    border-left-width: 3px;
    background: var(--colorSurface);
    transition: border-color var(--length), background var(--length);
}

    .job:hover {
        border-color: var(--colorAccent);
        background: var(--colorSurfaceRaised);
    }

    .job.is-alert {
        border-left-color: var(--colorRed);
    }

    .job.is-warning {
        border-left-color: var(--colorAccent);
    }

    /* The count leads, in the display face the tiles used: it is the one thing on the row read
       before the words, because it decides whether the row is worth the next ten minutes. */
    .job .job-count {
        color: var(--colorWhite);
        font-family: var(--fontDisplay);
        font-size: 26px;
        font-weight: var(--weightRegular);
        letter-spacing: -0.02em;
        line-height: 1;
        text-align: right;
    }

    .job.is-alert .job-count {
        color: var(--colorRed);
    }

    .job .job-body b {
        display: block;
        color: var(--colorWhite);
        font-size: var(--sizeNormal);
        font-weight: var(--weightMedium);
    }

    .job .job-body small {
        display: block;
        margin-top: 3px;
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
        line-height: 1.45;
    }

    /* Where it lands. Set like a menu entry, because that is what it is: the row says where it is
       taking you before it is clicked, which is how the panel gets learned by being used. */
    .job .job-where {
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
        white-space: nowrap;
    }

    .job:hover .job-where {
        color: var(--colorAccent);
    }

@media (max-width: 900px) {
    .job {
        grid-template-columns: 44px minmax(0, 1fr);
        gap: 12px;
    }

        /* The destination steps under the instruction rather than off the edge of the screen. */
        .job .job-where {
            grid-column: 2;
        }
}
/* #endregion */

.dashboard-tile {
    display: block;
    /* Sized for six across rather than four: the figure still leads the tile, but a tile a
       quarter of the screen wide makes a row of six taller than the work it describes. */
    padding: 13px 15px 15px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
    transition: border-color var(--length), background var(--length);
}

    /* Only a tile that leads somewhere reacts to the pointer; the health screen states facts. */
    a.dashboard-tile:hover {
        border-color: var(--colorAccent);
        background: var(--colorSurfaceRaised);
    }

    .dashboard-tile small {
        display: block;
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    .dashboard-tile strong {
        display: block;
        margin: 10px 0 5px;
        color: var(--colorWhite);
        font-family: var(--fontDisplay);
        font-size: 27px;
        font-weight: var(--weightRegular);
        letter-spacing: -0.02em;
        line-height: 1;
    }

    .dashboard-tile span {
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
    }

    .dashboard-tile.is-alert {
        border-color: var(--colorRed);
    }

        .dashboard-tile.is-alert strong {
            color: var(--colorWhite);
        }

    .dashboard-tile.is-warning {
        border-color: var(--colorAccentSoft);
    }

    .dashboard-tile.is-quiet strong {
        color: var(--colorMuted);
    }

/* #endregion */

/* #region Text block */
/* A quoted body of text anywhere in the panel — a dispatch draft, a base copy, a customer's
   words — under a name every module may use. */
.text-block {
    margin: 0 0 18px;
    padding: 14px 16px;
    border-left: 2px solid var(--colorGrayStrong);
    color: var(--colorText);
    font-size: var(--sizeSmall);
    line-height: 1.7;
    white-space: pre-wrap;
}
/* #endregion */

/* #region Panel patterns */
/* The shared skeleton every screen is being moved onto. One line for the title and everything
   that operates on the list — filters, search, actions — because a bar under the heading costs
   one to two visible rows on every single screen. */
.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 18px;
    /* The same 16 px an h1 keeps on a screen that has no bar, so the gap under the title is one
       measurement in the panel rather than two that differ by six pixels. */
    margin-bottom: 16px;
}

    .page-head h1 {
        margin-bottom: 0;
    }

.page-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 8px 14px;
    margin-left: auto;
}

    /* The existing pieces keep their classes and simply move inside the bar, so a screen is
       converted by wrapping, not rewriting: the float and the negative margins that placed
       them on their own rows are switched off here. */
    .page-tools div.filters,
    main .page-tools div.filters {
        margin: 0;
    }

    .page-tools div#page-buttons,
    main .page-tools div#page-buttons {
        float: none;
        margin: 0;
    }

    /* An action that must be a POST is wrapped in a form. The wrapper is layout only: it takes
       no room of its own, so a button that posts sits on the same line, at the same height, as
       the link beside it. */
    .page-tools div#page-buttons > form,
    main .page-tools div#page-buttons > form {
        display: inline-flex;
        align-items: center;
        margin: 0;
    }

    /* The first thing under the bar starts where the bar's own margin ends: otherwise a heading followed
       by a paragraph and a heading followed by a table sit at different distances. */
    main .page-head + * {
        margin-top: 0;
    }

    /* A form is the exception. Its first line is a small grey label rather than a row of data,
       and set at the same distance as a table it reads as part of the bar above it. */
    main .page-head + form,
    main .page-head + section.form-section {
        margin-top: 14px;
    }

    /* One distance between any two blocks of a screen, whatever they are. None of these blocks — a
       form, a lone button in its form, a list of facts, a fold, a table, an empty-state line, a grid of
       columns, a framed section — carries a top margin of its own, so wherever two met without a rule
       written for that exact pair (a form under a fact list, a fold under a form, a form under a button)
       they touched. This states the distance once for every pair. It stays out of the places where the
       blocks sit in a row or inside a cell — table cells, the bar of page buttons, inline entry links,
       a fact's own line, the tab strip, the side-by-side record columns — because there a top margin
       would break the line, not open it. Written with :where, so it weighs nothing: any rule that already
       sets a distance for a particular pair still wins, and this only fills the gaps nobody wrote. */
    main :where(form, dl.facts, details.fold, .table-wrapper, table, p.empty, .columns-two, .columns-three, .columns-four, section.form-section, .record-columns)
        + :where(form, dl.facts, details.fold, .table-wrapper, table, .columns-two, .columns-three, .columns-four, section.form-section, .record-columns):where(:not(td *, th *, #page-buttons *, .pane-buttons *, .entry-links *, dd *, nav.tabs *, .review-actions *, .filters *, .record-columns > *)) {
        margin-top: 18px;
    }

/* Column headers stay put while two hundred rows scroll under them — on a dense list the
   header is the legend, and a legend that scrolls away makes every column a guess. The offset
   is the sticky header's height; where the menu wraps to two lines the columns simply scroll,
   which is the cheaper failure. */
@media (min-width: 769px) {
    main table thead th {
        position: sticky;
        top: 47px;
        z-index: 5;
        background: var(--colorDark);
    }
}

/* The "i" beside a label or a heading. All guidance lives behind it, in the shared tooltip —
   never as a paragraph on the screen; the one thing that stays visible without hovering is a
   validation error, because an error must not hide. */
span.info-tip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    margin-left: 6px;
    border: 1px solid var(--colorGrayStrong);
    border-radius: 50%;
    color: var(--colorMuted);
    font-family: var(--font);
    font-size: 10px;
    font-style: normal;
    font-weight: var(--weightMedium);
    letter-spacing: 0;
    line-height: 1;
    text-transform: none;
    vertical-align: middle;
    cursor: help;
    transition: color var(--length), border-color var(--length);
}

    span.info-tip:hover,
    span.info-tip:focus-visible {
        border-color: var(--colorAccent);
        color: var(--colorAccent);
    }

/* Tabs on a record's screen: the facts and the everyday action stay above them, the record's
   other worlds live behind them. One switch, no page load, and the pane that is not open costs
   no screen at all. */
nav.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    margin: 6px 0 16px;
    border-bottom: 1px solid var(--colorGrayStrong);
}

    nav.tabs button {
        margin: 0;
        padding: 9px 14px;
        border: 0;
        border-bottom: 2px solid transparent;
        background: none;
        color: var(--colorMuted);
        font-family: var(--font);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
        white-space: nowrap;
        cursor: pointer;
        transition: color var(--length), border-bottom-color var(--length);
    }

        nav.tabs button:hover {
            background: none;
            color: var(--colorLight);
        }

        nav.tabs button.is-current {
            border-bottom-color: var(--colorAccent);
            color: var(--colorAccent);
        }

        /* The count of things waiting inside a pane, so a closed tab can still call. */
        nav.tabs button b {
            margin-left: 6px;
            color: inherit;
        }

.tab-pane[hidden] {
    display: none;
}

/* A rare operation folded shut. The screen shows what the record is; what can be done to it
   once a quarter waits behind one line and does not compete with the everyday action. */
details.fold {
    margin: 0 0 14px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
}

    details.fold > summary {
        padding: 10px 16px;
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
        list-style: none;
        cursor: pointer;
        transition: color var(--length);
    }

        details.fold > summary::-webkit-details-marker {
            display: none;
        }

        details.fold > summary::before {
            content: "+";
            margin-right: 10px;
            color: var(--colorAccent);
        }

        details.fold > summary:hover {
            color: var(--colorLight);
        }

    details.fold[open] > summary::before {
        content: "\2212";
    }

    details.fold > div.fold-body {
        padding: 2px 16px 16px;
    }

/* A fold that lives inside a table cell, opened by a pencil standing to the left of the value it
   corrects. Undressed it is a framed block with the word EDIT in it, which in a cell is a second row
   per record — and the eye starts the line at the left, where the handle belongs. */
details.fold.fold-inline {
    display: inline-block;
    vertical-align: top;
    margin: 0;
    border: 0;
    background: transparent;
}

    details.fold.fold-inline > summary {
        display: inline-block;
        padding: 0;
        margin-right: 8px;
        color: var(--colorAccent);
        font-size: var(--sizeSmall);
        letter-spacing: 0;
        text-transform: none;
    }

        /* The family's "+"/"−" handle is the summary's own text here — the pencil. */
        details.fold.fold-inline > summary::before {
            content: none;
        }

    /* Open, it takes the cell's width — a form laid out inside a shrink-to-fit box gives an input
       the width of the word in it. The value it corrects then reads underneath. */
    details.fold.fold-inline[open] {
        display: block;
    }

    details.fold.fold-inline > div.fold-body {
        padding: 8px 0 0;
    }

    /* A fold living inside a table cell is furniture of the row, not a section of the page:
       it keeps the row's rhythm instead of pushing the next record away. */
    main table td details.fold {
        margin: 6px 0 0;
    }

    /* In the actions column it slims down to a bare disclosure — the bordered box is taller
       than the row of text actions beside it. */
    main table td.cell-actions details.fold {
        margin: 0;
        border: none;
        background: none;
    }

        main table td.cell-actions details.fold > summary {
            display: inline;
            padding: 0;
        }

        main table td.cell-actions details.fold > div.fold-body {
            padding: 8px 0 0;
        }

    /* A select standing in an action cell sizes to its content — a full-width control would
       hand the whole row to one column. */
    main table td.cell-actions select {
        width: auto;
        max-width: 220px;
    }

    /* A note under the controls of an action cell — who marked it, why it will not print — is a line of
       its own: kept on the controls' line in a no-wrap cell, it widened the column into its neighbour. */
    main table tr td.cell-actions small {
        display: block;
        margin-top: 4px;
        white-space: normal;
    }

/* A sortable column: the header is the control, the arrow rides the active sort. */
main table tr th a {
    border-bottom: none;
    color: inherit;
    transition: color var(--length);
}

    main table tr th a:hover,
    main table tr th a.is-current {
        color: var(--colorAccent);
    }

/* The count of things waiting, hung on a menu entry or a bell: red, because in this panel red
   is the one colour that means "act". Zero renders nothing — a grey zero is noise. */
span.nav-badge {
    /* Not a flex box: the height of the line does the centring, which is the one way that does
       not depend on how the box model and the font's metrics happen to interact. The line box is
       the badge's own height, so the text sits in the middle of it by construction. */
    display: inline-block;
    box-sizing: border-box;
    min-width: 17px;
    height: 17px;
    margin-left: 6px;
    padding: 0 5px;
    text-align: center;
    /* A pill, not a circle with a fixed radius: three digits are as ordinary here as one, and
       an 8 px radius on a 26 px wide badge draws a lozenge. */
    border-radius: 999px;
    /* Every figure the same width, so a badge does not change shape as the count ticks over. */
    font-variant-numeric: tabular-nums;
    background: var(--colorRed);
    color: var(--colorWhite);
    font-size: 10px;
    font-weight: var(--weightBold);
    letter-spacing: 0;
    /* Two pixels short of the badge's own 17, which seats the line one pixel above the middle —
       the correction this typeface needs, its digits sitting low in their line box. Measured on
       the screen rather than derived: the metrics that would predict it are the font's own, and
       the difference between right and nearly right here is a single pixel. */
    line-height: 15px;
    vertical-align: middle;
}
/* Money is read down a column, not across a row: ranged left, the thousands of one amount sit
   under the hundreds of the next and the eye has to re-find the decimal point on every line. The
   header goes with the figures — a caption ranged left over figures ranged right is the same
   misalignment one line higher — and the digits are tabular, so a 1 takes the width of an 8 and
   the columns of a list stay in step as it pages. */
main table th.cell-amount,
main table td.cell-amount {
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* A badge that follows something — an order number, a name — rather than leading a row of its
   own. The badge box carries no left margin on purpose, because a row of badges must start flush
   with the cell; one that comes after a word needs the space that margin does not give it. */
main span.badge.badge-after {
    margin-left: 7px;
}

/* The one form on a screen that is otherwise a record to be read. A hairline in the house gold
   says "this part changes something" without a filled panel behind it: a background would make it
   a second surface on a screen that has one, and the form is not a different kind of thing from
   the facts above it — only the part that writes. */
main .form-framed {
    margin-bottom: 18px;
    padding: 18px 20px;
    border: 1px solid var(--colorAccentSoft);
}

    main .form-framed > h2:first-child {
        margin-top: 0;
    }

/* The same value stated a second time in somebody else's words: the description of a line as the
   customer read it, under the panel's own reading of that line. What it says is not ours, and it is
   written in whatever language they were buying in, so it is set quiet and in italics — without
   quotation marks, which read as a remark somebody made rather than as the line's own wording. */
main table tr td small.cell-quote {
    display: block;
    margin-top: 3px;
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    font-style: italic;
    line-height: 1.5;
}
/* #endregion */

/* #region Animations */
@keyframes fadein {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes blink {
    0%, 100% {
        opacity: 1;
    }

    50% {
        opacity: 0.2;
    }
}

@media (prefers-reduced-motion: reduce) {
    main table tr td img.flag-blink {
        animation: none;
        border-color: var(--colorRed);
    }

    main .translation-tabs .translation-flag.is-empty {
        animation: none;
    }
}
/* #endregion */

/* #region Sign-in */
/* Sign-in is the only screen in the panel with no data on it, so it is the only one that may
   be a composition rather than a surface: the photographs on the left, the form on the right,
   and nothing else — no header, no navigation, nothing to click but the field. The stills are
   the site's own product photography, and they take the whole left column rather than a plate
   inside it: this is the one screen where an image is the subject and not an illustration. */
body.signin-page main {
    max-width: none;
    margin: 0;
    padding: 0;
}

    /* A flash message survives here (a sign-out, a session that expired mid-click) but it is
       not part of the composition: it lands over it as a strip and leaves the layout alone. */
    body.signin-page div#message-success,
    body.signin-page div#message-failure {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: 10;
        text-align: center;
    }

.signin-shell {
    display: grid;
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
    min-height: 100vh;
}

/* The photographs are the column: full bleed, edge to edge, with nothing standing on top of
   them. A still cropped to a plate in the middle reads as an illustration of the panel; one
   that fills the door reads as the room behind it, which is what the products are about. */
.signin-gallery {
    position: relative;
    border-right: 1px solid var(--colorGray);
    overflow: hidden;
}

    /* The photograph is lit from the middle and the form sits to its right, so the frame is
       darkened where it meets the panel and along its own edges: the seam between the two
       halves stays a seam, and no still can throw a bright corner at the field. */
    .signin-gallery::after {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 2;
        background: linear-gradient(90deg, rgba(0, 0, 0, 0.42) 0%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0) 62%, rgba(0, 0, 0, 0.5) 100%), linear-gradient(180deg, rgba(0, 0, 0, 0.34) 0%, rgba(0, 0, 0, 0) 26%, rgba(0, 0, 0, 0) 68%, rgba(0, 0, 0, 0.42) 100%);
        pointer-events: none;
    }

.signin-plate {
    position: absolute;
    inset: 0;
    z-index: 1;
    margin: 0;
    background: var(--colorSurface);
    overflow: hidden;
}

    /* One photograph, held still — the house's own, the same still the site opens with. Never a
       set of them cross-fading: a picture that changes while somebody is typing their address is
       movement asking to be watched, and a sign-in screen is the one place in the panel with
       nothing to watch. */
    .signin-plate img {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

    /* The passe-partout a framed work has inside its frame, in the brand's gold. It is drawn on
       the column rather than on the photograph, so it stays above the darkening and holds its
       line. */
    .signin-gallery::before {
        content: "";
        position: absolute;
        inset: clamp(18px, 2.2vw, 34px);
        z-index: 3;
        border: 1px solid rgba(182, 165, 116, 0.26);
        pointer-events: none;
    }

.signin-panel {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 60px clamp(28px, 5vw, 90px);
    background: var(--colorDark);
}

.signin-panel-inner {
    width: 100%;
    max-width: 420px;
    margin: 0 auto;
}

    /* The one screen where a heading may be display type: there is no data under it. */
    .signin-panel-inner h1 {
        margin-bottom: 28px;
        font-size: 34px;
    }

    .signin-panel-inner form {
        margin: 0;
    }

    .signin-panel-inner div.buttons {
        margin-bottom: 0;
    }

        .signin-panel-inner div.buttons button {
            flex: 1;
            margin-top: 6px;
        }

    /* The code is eight characters read off a phone: it is set large and spaced so a person
       can check what they typed without leaning in. The verifier uppercases what is typed,
       so showing it uppercase is honest. */
    .signin-panel-inner input.code-input {
        padding: 16px 13px;
        font-size: 26px;
        font-weight: var(--weightMedium);
        letter-spacing: .42em;
        /* Letter-spacing trails the last character, which pushes centred text left by one gap. */
        text-indent: .42em;
        text-align: center;
        text-transform: uppercase;
    }

    /* The enrolment QR. White ground regardless of the panel's dark shell, because a phone camera
       reads a dark-on-light code and a great many will not read an inverted one at all. */
    .signin-panel-inner .signin-enrolment {
        margin: 0 0 24px;
        text-align: center;
    }

    .signin-panel-inner img.signin-qr {
        width: 196px;
        height: 196px;
        padding: 10px;
        background: #ffffff;
        border: 1px solid var(--colorGray);
    }

    /* The same secret in type, for the camera that will not focus. Monospace so that the groups of
       four stay groups of four, and selectable because it is meant to be copied by hand. */
    .signin-panel-inner p.signin-secret {
        margin: 12px 0 0;
        color: var(--colorMuted);
        font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
        font-size: var(--sizeSmall);
        letter-spacing: .12em;
        user-select: all;
    }

    /* The one printed instruction on any sign-in screen. Quiet, because it is read once — the first
       time somebody signs in — and is scenery on every sign-in after a reset. */
    .signin-panel-inner p.signin-instruction {
        margin: 14px auto 0;
        max-width: 34em;
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
        line-height: 1.5;
    }

    /* The quiet way out under the committing action: another address, another code. */
    .signin-panel-inner .signin-alternative {
        margin: 28px 0 0;
        padding-top: 20px;
        border-top: 1px solid var(--colorGray);
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
    }

@media (max-width: 1100px) {
    .signin-shell {
        grid-template-columns: 1fr;
        min-height: 0;
    }

    /* Stacked, the column becomes a band: the photographs still run edge to edge, and the height
       is fixed here because a full-bleed frame has no content of its own to give it one. */
    .signin-gallery {
        min-height: clamp(220px, 38vh, 340px);
        border-right: none;
        border-bottom: 1px solid var(--colorGray);
    }

    .signin-panel {
        padding: 44px 24px 60px;
    }
}

/* #endregion */

/* #region Print */
/* Some screens exist to be printed — a proof, a certificate, a letter. Everything else in the bar above
   them is navigation, and a proof that carries a menu down its first page is not a document anybody
   files. The panel is dark, and a browser prints backgrounds only if asked — so the ink is set
   explicitly rather than left to a light-grey-on-white accident. */
/* The printed sheet's own head, drawn only on paper — the brand renders it. */
.print-letterhead {
    display: none;
}

/* A clause quoted word for word — the wording somebody actually accepted. Left unstyled it is set by
   the browser's default indent and nothing else, which on the two licence screens makes the most
   consequential paragraph on the page read as an afterthought. */
main blockquote {
    margin: 14px 0 18px;
    padding: 2px 0 2px 16px;
    border-left: 2px solid var(--colorAccent);
    color: var(--colorText);
    font-size: var(--sizeNormal);
    line-height: 1.65;
}

/* A fingerprint or an identifier in a table cell is one unbroken word of sixty-four characters: on a screen it would
   push the table wider than the frame, so it breaks where it must, as it does on paper. */
main table td code {
    overflow-wrap: anywhere;
    word-break: break-all;
}

/* The page itself. Without this the sheet takes the browser's default margin while the panel's own
   padding is stripped off for print, so a proof of licence comes out hard against the paper's edge
   — which is not a document anybody files. Generous at the head, because that is the edge a reader
   holds and the edge a stapler takes. */
@page {
    margin: 18mm 16mm 16mm;
}

@media print {
    /* Printouts are pure black on pure white (#000 on #fff), never the screen's #050505/#F5F5F5.
       The light text tokens turn to ink here, so no text left on a screen token prints white on white. */
    :root {
        color-scheme: light;
        --colorWhite: #000;
        --colorLight: #000;
        --colorText: #000;
        --colorVeryLight: #000;
    }

    header,
    main div.page-tools,
    main div#page-buttons,
    main div.pane-buttons,
    span.info-tip,
    div.tooltip,
    dialog {
        display: none !important;
    }

    html,
    body,
    main {
        background: #fff;
        color: #000;
    }

    main {
        max-width: none;
        margin: 0;
        /* The page margin above is the whole of the white space: a padding here is added to it,
           and the two together push a long licence onto a second sheet. */
        padding: 0;
        font-size: 10.5pt;
        line-height: 1.5;
    }

    .print-letterhead {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 4px 12px;
        margin-bottom: 14pt;
        padding-bottom: 8pt;
        border-bottom: 1pt solid #000;
    }

        /* The wordmark is a drawing here too; the height is the letters' own cap, since the file is
           drawn 720 units tall for a 700-unit cap. */
        .print-letterhead img {
            width: auto;
            height: 2.6mm;
        }

        .print-letterhead small {
            font-size: 8pt;
        }

    /* A heading, a clause and a row of a table are each one thing: a page break through the middle
       of any of them is what makes a printed document look like a screenshot. */
    main h1,
    main h2 {
        break-after: avoid;
        page-break-after: avoid;
    }

    main table tr,
    main li,
    main blockquote {
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* The document tables — the licence's facts and its earlier grants. On screen they are read
       down a dark column; on paper they are a form, and a form needs its rules drawn. */
    /* On paper the table stands in the text's own column: the screen bleeds it 10px into the margin so the
       first column's words keep the page edge, but a ruled table on a sheet then juts out past the heading. */
    main table {
        width: 100%;
        margin-left: 0;
        border-collapse: collapse;
    }

        main table tr > th,
        main table tr > td {
            padding: 4pt 6pt;
            border: 0.5pt solid #999999;
            text-align: left;
            vertical-align: top;
        }

        main table tr > th {
            font-weight: 600;
        }

        /* The label column of a facts table — never a column header: four headers of a third each made
           the earlier-grants table a third wider than the sheet. */
        main table tbody tr > th {
            width: 34%;
        }

        /* Nothing on paper may be wider than the paper. A screen keeps cells on one line and lets a table
           scroll; a sheet cannot scroll, so a cell wraps, and a 64-character fingerprint breaks anywhere
           rather than running off the edge. */
        main table tr > th,
        main table tr > td,
        main table tr td.column-no-wrap {
            white-space: normal;
            overflow-wrap: anywhere;
        }

        main code {
            white-space: normal;
            word-break: break-all;
        }

    main .table-wrapper {
        overflow: visible;
    }

    /* A framed screen prints as one document: the frames are a screen's way of grouping, and on paper they
       would be boxes around every paragraph of a proof. */
    main section.form-section {
        margin: 0 0 12pt;
        padding: 0;
        border: 0;
        background: transparent;
    }

        /* A section's heading rule, in ink: the screen's gold hairline prints as a smudge. */
        main section.form-section > h2 {
            margin: 0 0 6pt;
            padding-bottom: 3pt;
            border-bottom: 0.5pt solid #000;
            font-size: 13pt;
        }

    html,
    body,
    main {
        width: auto;
        min-width: 0;
    }

    main blockquote {
        margin: 8pt 0;
        padding-left: 10pt;
        border-left: 1.5pt solid #000;
    }

        main h1,
        main h2,
        main h3,
        main p,
        main li,
        main dt,
        main dd,
        main table tr td,
        main table tr th,
        main b,
        main strong,
        main small {
            color: #000;
        }

        /* A tint that means something on a screen means nothing on paper, and the row it sits on
           has to stay readable through it. */
        main table tr > td {
            background: transparent;
        }

        main table tr.inactive td {
            opacity: 1;
        }
}
/* #endregion */

/* #region Letter review */
/* The one-at-a-time review of promotional mail. What the letter is — recipient, subject, type — reads
   in one strip with the decision beside it, because a list of facts stacked above the letter pushed the
   letter itself below the fold, and the letter is what is being judged. */
main .review-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 28px;
    margin: 0 0 12px;
}

    main .review-strip dl {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 4px 22px;
        margin: 0;
    }

        main .review-strip dl > div {
            display: flex;
            align-items: baseline;
            gap: 8px;
        }

        main .review-strip dt {
            color: var(--colorMuted);
            font-size: var(--sizeMicro);
            font-weight: var(--weightMedium);
            letter-spacing: var(--track);
            text-transform: uppercase;
        }

        main .review-strip dd {
            margin: 0;
            color: var(--colorText);
        }

    main .review-strip .review-actions {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 12px;
    }

        main .review-strip .review-actions form,
        main .review-strip .review-actions button {
            margin: 0;
        }

        /* The reason field opens beside the buttons and pushes nothing below it away. */
        main .review-strip .review-actions details.fold {
            margin: 0;
        }

/* The letter itself, framed as a sandboxed document of the panel's own, filling what the window has
   left under the strip — so it reads to its signature without scrolling the screen around it. */
main iframe.letter-frame {
    background: var(--colorDark);
    border: 1px solid var(--colorGrayStrong);
    display: block;
    height: calc(100vh - 210px);
    min-height: 480px;
    width: 100%;
}
/* #endregion */

/* #region Brand library */
/* A brand's library (BrandControllerBase) and Brand ▸ Logo. The tags above the list: a row of filters of its own,
   wrapping, because a library grows tags faster than a screen grows width. */
main div.filters.brand-tags {
    flex-wrap: wrap;
    margin: 0 0 18px;
}

/* One piece shown whole on its details, never cropped: its proportions are part of what is chosen. It has a
   column to itself and takes as much of the screen's height as the header leaves, so an upright film is
   judged at a size somebody would actually watch it. */
main img.brand-preview,
main video.brand-preview {
    display: block;
    width: 100%;
    height: auto;
    max-height: calc(100vh - 190px);
    margin: 0;
    border: 1px solid var(--colorGray);
    object-fit: contain;
}

/* Several framed sections in one column of the Details screen, one under another at the sections' own distance. */
main div.brand-stack {
    display: grid;
    gap: 14px;
    align-content: start;
    min-width: 0;
}

    main div.brand-stack > section.form-section {
        margin: 0;
    }

/* Brand ▸ Logo: one card per ink, three across — the mark on the ground it belongs on (the ink's own Ground, set
   on the card), then its files, so a white or gold mark is judged where it will actually stand. */
main div.brand-logo-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
}

@media (max-width: 1100px) {
    main div.brand-logo-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

main div.brand-logo-card {
    min-width: 0;
}

main div.brand-logo-ground {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 160px;
    padding: 24px;
    border: 1px solid var(--colorGray);
}

    /* Contained, never cropped: a wordmark is many times wider than tall, a signet square. */
    main div.brand-logo-ground img {
        display: block;
        max-width: 80%;
        max-height: 100%;
        object-fit: contain;
    }

/* The ink's name and hex with the two vectors beside it — one line above the widths table. */
main div.brand-logo-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 10px 0 6px;
}

    main div.brand-logo-head span.cell-actions {
        margin-left: auto;
    }

/* The typed width and its format beside the widths table: one short row, not a form section of its own. */
main form.brand-mark-size {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px;
    margin: 12px 0 24px;
}

    main form.brand-mark-size > div {
        min-width: 160px;
    }

/* Social ▸ Profiles: a description or a setting as it will be pasted, its own line breaks kept. */
main .social-profile-bio {
    white-space: pre-wrap;
}

main div.social-profile-bio {
    margin: 6px 0 14px;
}

/* The top of a profile as the network lays it out: the visible part of the background (cut around its centre) and the
   profile picture over or under its edge. Every size is a share of the preview's width — a vertical margin in percent
   is measured against the width too — so one set of numbers per network draws it at any width. */
main div.social-profile-mock {
    width: 100%;
    max-width: 900px;
    margin: 6px 0 12px;
    padding-bottom: 12px;
    background: var(--colorSurface);
    border: 1px solid var(--colorGray);
}

    main div.social-profile-mock.is-mobile {
        max-width: 390px;
    }

    main div.social-profile-mock div.social-profile-mock-cover {
        width: 100%;
        overflow: hidden;
        background: var(--colorSurfaceRaised);
    }

        main div.social-profile-mock div.social-profile-mock-cover img {
            display: block;
            width: 100%;
            max-width: none;
            height: 100%;
            object-fit: cover;
            object-position: center;
        }

    main div.social-profile-mock img.social-profile-mock-avatar {
        position: relative;
        display: block;
        aspect-ratio: 1;
        border-radius: 50%;
        box-shadow: 0 0 0 3px var(--colorSurface);
    }

        main div.social-profile-mock img.social-profile-mock-avatar.is-rounded-square {
            border-radius: 10%;
        }

/* The library as a wall of square tiles: the material is what is being chosen, so it takes the space and the
   facts are laid over it. The squares are crops; the preview that opens on hover (div.brand-zoom) is not. */
main div.brand-grid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 10px;
    margin: 0 0 24px;
}

/* Five across on any desk screen — large squares a shot can be judged from — and fewer only where five
   would shrink them past that. Fifty to a page (BrandAssetCatalog.PageSize) is ten full rows. */
@media (max-width: 1100px) {
    main div.brand-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 700px) {
    main div.brand-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

main a.brand-tile {
    position: relative;
    display: block;
    aspect-ratio: 1;
    overflow: hidden;
    border: 1px solid var(--colorGray);
    background: var(--colorSurfaceRaised);
    color: var(--colorWhite);
    text-decoration: none;
    transition: border-color var(--length);
}

    main a.brand-tile:hover {
        border-color: var(--colorAccent);
    }

    main a.brand-tile .brand-tile-media,
    main a.brand-tile .brand-tile-media img,
    main a.brand-tile .brand-tile-media video {
        position: absolute;
        inset: 0;
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

    main a.brand-tile .brand-tile-empty {
        position: absolute;
        inset: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    main a.brand-tile .brand-tile-top {
        position: absolute;
        top: 8px;
        left: 8px;
        right: 8px;
        display: flex;
        justify-content: space-between;
        gap: 6px;
        pointer-events: none;
    }

    main a.brand-tile .brand-tile-kind {
        margin-left: auto;
        padding: 2px 7px;
        background: rgba(5, 5, 5, 0.78);
        font-size: var(--sizeMicro);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    main a.brand-tile .brand-star {
        padding: 0 6px;
        background: rgba(5, 5, 5, 0.78);
    }

    /* The facts on a plain dark band across the foot of the tile — flat, like the rest of the panel. */
    main a.brand-tile .brand-tile-info {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        display: grid;
        gap: 2px;
        padding: 8px 10px;
        background: rgba(5, 5, 5, 0.78);
        font-size: var(--sizeSmall);
        line-height: 1.4;
    }

    main a.brand-tile .brand-tile-tags,
    main a.brand-tile .brand-tile-notes {
        display: -webkit-box;
        overflow: hidden;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
    }

    main a.brand-tile .brand-tile-notes {
        color: var(--colorWhite);
        -webkit-line-clamp: 1;
    }

    main a.brand-tile .brand-tile-tags {
        color: var(--colorAccent);
    }

    main a.brand-tile .brand-tile-facts {
        color: var(--colorLight);
        font-size: var(--sizeMicro);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Faded when it is archived, like an archived table row. */
    main a.brand-tile.inactive .brand-tile-media {
        opacity: 0.4;
    }

/* The hover preview: the piece in its own proportions, grown from the tile it opens over. It takes no pointer
   events, so the tile underneath keeps the pointer and closes it on leaving. */
div.brand-zoom {
    position: fixed;
    z-index: 1000;
    border: 1px solid var(--colorAccent);
    background: var(--colorDark);
    opacity: 0;
    pointer-events: none;
    transform: scale(0.3);
    transition: transform var(--length), opacity var(--length);
}

    div.brand-zoom.is-open {
        opacity: 1;
        transform: scale(1);
    }

    div.brand-zoom img,
    div.brand-zoom video {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: contain;
    }

/* Notes keep the line breaks they were written with. */
main dd.brand-notes {
    white-space: pre-line;
}

/* The mark of a selected piece: the brand's accent, the one colour here that means "the best of", not "act". */
main .brand-star {
    color: var(--colorAccent);
}
/* #endregion */

/* #region Legal documents */
/* An archived edition read inside the panel (Legal Desk ▸ Documents ▸ Preview). The text is the archive's own markup,
   so it is set the way a regulation reads — a measure a line can be followed across, the section headings in the
   display face, the provision numbers carrying the bold — rather than in the panel's dense table type. Its links name
   the site's relative addresses, which lead nowhere from the panel, so they are shown as links and do not open. */
main .legal-preview {
    max-width: 78ch;
    color: var(--colorText);
    font-size: var(--sizeNormal);
    line-height: 1.65;
}

    main .legal-preview h2 {
        margin: 26px 0 8px;
        font-family: var(--fontDisplay);
        font-size: var(--sizeBig);
        font-weight: var(--weightRegular);
        color: var(--colorWhite);
    }

        main .legal-preview h2:first-child {
            margin-top: 0;
        }

    main .legal-preview p {
        margin: 0 0 10px;
    }

    main .legal-preview ul,
    main .legal-preview ol {
        margin: 0 0 10px;
        padding-left: 22px;
    }

    main .legal-preview strong {
        font-weight: var(--weightBold);
        color: var(--colorWhite);
    }

    main .legal-preview a {
        color: inherit;
        text-decoration: underline;
        text-decoration-color: var(--colorAccentSoft);
        pointer-events: none;
    }
/* #endregion */
