/* Odoardo's own screens. Everything every panel shares — the tokens, the shell, forms, tables, buttons,
   the patterns of Platform/docs/panel-design.md — is panel.css from Platform.Management, linked before
   this file, so the rules here lean on its tokens and never restate its patterns. */

/* #region Typography */
/* The shared eyebrow (panel.css .eyebrow), carried by the artist review's step labels. */
.artist-stage {
    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;
}
/* #endregion */

/* #region Settings */
/* The one switch row (panel.css .setting-row) whose state column is a set of controls rather than a
   badge — the products taken off sale. The description gives up the width the products need, so all
   six stay on one line. */
main .setting-row.is-products {
    grid-template-columns: minmax(0, 0.9fr) auto auto;
}

/* The products are ticked in a row of their own chips rather than as a stacked checklist: five
   products stacked make this switch four times the height of the one above it, and six of them
   wrapping to a second line make one decision look like two. */
main .setting-products {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
}

    main .setting-products label.setting-product {
        display: inline-flex;
        align-items: center;
        gap: 7px;
        margin: 0;
        padding: 5px 10px;
        border: 1px solid var(--colorGray);
        color: var(--colorLight);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
        cursor: pointer;
        transition: border-color var(--length), color var(--length);
    }

        main .setting-products label.setting-product:hover {
            border-color: var(--colorAccent);
        }

        /* A product currently off sale is red, because that is what red means here: it is not
           selling, and somebody decided that on purpose. */
        main .setting-products label.setting-product.is-paused {
            border-color: rgba(211, 80, 80, 0.45);
            color: var(--colorRed);
        }

        main .setting-products label.setting-product input[type="checkbox"] {
            width: 13px;
            height: 13px;
            margin: 0;
            padding: 0;
            accent-color: var(--colorRed);
        }

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

    /* Stacked, the products have the whole width and may wrap again — one line matters while
       they share a row with the description, not once they have a row of their own. */
    main .setting-products {
        flex-wrap: wrap;
    }
}
/* #endregion */

/* #region Category marks */
/* Odoardo's kinds on the shared category colour (.cat-name, panel.css): not a state but a kind,
   shown as the colour of the word that names it. A page of accounts is read as "who are
   these people", and seven categories told apart by colour answer that down one column. None of
   them borrows the red or the gold that mean something is wrong or waiting. */
.cat-name.is-cat-city {
    --catColor: rgb(111, 142, 196);
}

.cat-name.is-cat-hotel {
    --catColor: rgb(158, 134, 196);
}

.cat-name.is-cat-restaurant {
    --catColor: rgb(196, 132, 106);
}

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

.cat-name.is-cat-developer {
    --catColor: rgb(140, 160, 120);
}

.cat-name.is-cat-individual {
    --catColor: var(--colorMuted);
}

/* Teal, and deliberately nowhere near the red of an uncategorised row: a pink here reads as a paler
   alarm, which is the one thing a category colour must never do. */
.cat-name.is-cat-artist {
    --catColor: rgb(94, 176, 186);
}

/* The journal is read by thread, not by title: which product a piece belongs to is the first
   thing anybody wants from that list. The same shades name the same products anywhere a list is
   read as "which of ours is this" — an order's lines above all — so the two selectors are written
   together rather than as two blocks free to drift apart. The product names come from the
   Product enum lowercased, which is why Library takes the amber the journal gives Filmable:
   nothing else in this set is a thing to read. */
.cat-name.is-journal-soul,
.cat-name.is-product-soul {
    --catColor: var(--catViolet);
}

.cat-name.is-journal-alibi,
.cat-name.is-product-alibi {
    --catColor: var(--catAzure);
}

.cat-name.is-journal-art,
.cat-name.is-product-art {
    --catColor: var(--catRose);
}

.cat-name.is-journal-lens,
.cat-name.is-product-lens {
    --catColor: var(--catTeal);
}

.cat-name.is-journal-space,
.cat-name.is-product-space {
    --catColor: var(--catLime);
}

.cat-name.is-journal-filmable,
.cat-name.is-product-library {
    --catColor: var(--catAmber);
}

/* The media list is read as "who are these titles to us", so the rung carries a colour of its own:
   a contact nobody has agreed anything with is grey, and the three rungs above it grow in weight.
   None of them borrows red or gold — a record missing its press address takes the red row, and it
   has to win over any rung the record happens to stand on. */
.cat-name.is-media-contact {
    --catColor: var(--colorMuted);
}

.cat-name.is-media-recipient {
    --catColor: var(--catAzure);
}

.cat-name.is-media-patron {
    --catColor: var(--catViolet);
}

.cat-name.is-media-chapter {
    --catColor: var(--catTeal);
}

/* The same idea on the letter list, and for a sharper reason: a letter is only the opening, the
   follow-up call comes a fortnight later, and the one question this screen is opened with is which
   records are owed one. The ladder runs cool to warm — queued, posted, called, talking, bought —
   while a record that said no is dimmed whole-row rather than marked, and an unfinished one takes
   the red row, because it cannot become a letter at all. */
.cat-name.is-prospect-queued {
    --catColor: var(--colorMuted);
}

.cat-name.is-prospect-letter {
    --catColor: var(--catAzure);
}

.cat-name.is-prospect-called {
    --catColor: var(--catViolet);
}

.cat-name.is-prospect-interested {
    --catColor: var(--catTeal);
}

.cat-name.is-prospect-customer {
    --catColor: var(--catLime);
}

/* Who makes a thing is read down the list the way a customer's category is: four trades, each in
   its colour. The hues are the shared category palette — one set of six that every module maps its
   own kinds onto, so a supplier borrowing azure from the journal is the pattern rather than a
   collision: the two never appear on one screen, and within a screen the meaning is constant. */
.cat-name.is-supplier-printer {
    --catColor: var(--catAzure);
}

.cat-name.is-supplier-carpenter {
    --catColor: var(--catAmber);
}

.cat-name.is-supplier-logistics {
    --catColor: var(--catTeal);
}

.cat-name.is-supplier-other {
    --catColor: var(--catViolet);
}
/* #endregion */

/* #region Brand library */
/* The library's tiles, its Details and Brand ▸ Logo are Platform's (panel.css, "Brand library"); what is here is
   Odoardo's own: the list of the /init/brand import. */
main ul.brand-import-list {
    margin: 0;
    padding-left: 18px;
    font-size: var(--sizeSmall);
}
/* #endregion */

/* #region Lens venue logo */
/* A Lens venue logo, shown on black because black is what it is set on: a gold or white mark on
   the panel's light ground would look empty. Contained, never cropped — it is a mark, not a photo. */
img.end-card-logo {
    display: block;
    width: 160px;
    height: 120px;
    padding: 10px;
    background: #050505;
    border: 1px solid var(--colorGray);
    object-fit: contain;
}
/* #endregion */

/* #region Artist review */
.artist-review-list {
    display: grid;
    gap: 22px;
}

.artist-review-card {
    display: grid;
    grid-template-columns: 220px 1fr;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
}

    .artist-review-card.requires-review {
        border-color: var(--colorAccentSoft);
        box-shadow: inset 3px 0 0 var(--colorAccent);
    }

.artist-review-visual {
    display: grid;
    min-height: 220px;
    place-items: center;
    overflow: hidden;
    background: #030303;
    color: var(--colorMuted);
}

    .artist-review-visual a {
        width: 100%;
        height: 100%;
        border: 0;
    }

    .artist-review-visual img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

.artist-review-body {
    padding: 24px;
}

.artist-review-heading {
    display: flex;
    justify-content: space-between;
    gap: 20px;
}

    .artist-review-heading h2 {
        margin: 8px 0 3px;
        font-size: 24px;
    }

    .artist-review-heading time,
    .artist-review-heading small {
        color: var(--colorMuted);
        font-size: var(--sizeSmall);
    }

.artist-review-meta {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin: 22px 0;
    padding-block: 15px;
    border-block: 1px solid var(--colorGray);
}

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

    .artist-review-meta dd {
        margin: 6px 0 0;
        color: var(--colorText);
        font-size: var(--sizeSmall);
    }

.artist-review-evidence {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 20px;
}

    .artist-review-evidence a {
        color: var(--colorAccent);
        font-size: var(--sizeSmall);
    }

.artist-review-form {
    display: grid;
    gap: 12px;
    margin-top: 22px;
}

    /* The label wrapping the comment box: its name over it, in the panel's micro-caps, so the
       rule about a rejection needing a reason is on the screen rather than in a placeholder
       that vanishes on the first keystroke. */
    .artist-review-form > label {
        display: grid;
        gap: 6px;
    }

        /* The gap is the spacing; the general rule's own top margin would be added to it. */
        .artist-review-form > label > textarea {
            margin-top: 0;
        }

/* The same shape inside a table cell — the Lens settlement reference, which is required and is
   the whole proof that a month was paid. */
main table tr td.cell-actions label.usage-reference {
    display: inline-grid;
    gap: 4px;
    margin-right: 12px;
    vertical-align: middle;
    text-align: left;
}

    main table tr td.cell-actions label.usage-reference > span {
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    /* An explicit width: the general form rule gives every field 100%, and 100% of an inline-grid
       column that is sized by its own contents is a width asking itself how wide it is. */
    main table tr td.cell-actions label.usage-reference > input {
        width: 190px;
        margin: 0;
    }

    .artist-review-form textarea {
        min-height: 70px;
        padding: 12px;
        border: 1px solid var(--colorGray);
    }

    .artist-review-form > div {
        display: flex;
        justify-content: flex-end;
        gap: 12px;
    }

    .artist-review-form button {
        margin-top: 0;
    }

        .artist-review-form button.reject {
            border-color: var(--colorRed);
            color: var(--colorRed);
        }

            .artist-review-form button.reject:hover {
                background: var(--colorRed);
                color: var(--colorWhite);
            }

        .artist-review-form button.approve {
            border-color: var(--colorGreen);
            color: var(--colorGreen);
        }

            .artist-review-form button.approve:hover {
                background: var(--colorGreen);
                color: var(--colorDark);
            }

/* The banded notice on the two licence proofs and the artist review screen. Unstyled it is six
   paragraphs of ordinary body text across three screens, and among them the one sentence that must
   never be missed: that the provisions printed underneath are today's wording rather than the
   wording that was accepted. A warning set like prose is a warning nobody reads. Red is the
   panel's own "you must act on this"; the success band is the reassurance that
   the declaration came from the person themselves, so it takes green and the same shape. */
main .artist-review-alert {
    margin: 14px 0 18px;
    padding: 11px 14px;
    border-left: 3px solid var(--colorGray);
    background: var(--colorSurface);
    color: var(--colorText);
    font-size: var(--sizeSmall);
    line-height: 1.55;
}

    main .artist-review-alert.error {
        border-left-color: var(--colorRed);
    }

    main .artist-review-alert.success {
        border-left-color: var(--colorGreen);
    }

    main .artist-review-alert code {
        overflow-wrap: anywhere;
    }

@media (max-width: 900px) {
    .artist-review-card {
        grid-template-columns: 1fr;
    }

    .artist-review-visual {
        aspect-ratio: 1;
    }

    .artist-review-meta {
        grid-template-columns: 1fr 1fr;
    }
}

@media print {
    /* Printouts are pure black on pure white (#000 on #fff), never the screen's #050505/#F5F5F5. */
    /* The notice bands, in ink. A browser prints no backgrounds, so on paper the band has to be
       drawn: a proof of licence whose "this is not the wording that was accepted" warning vanishes on
       paper is worse than one that never carried the warning at all. */
    main .artist-review-alert {
        padding: 6pt 8pt;
        border: 0.5pt solid #000;
        border-left-width: 2pt;
        background: transparent;
        color: #000;
        font-size: 9.5pt;
        break-inside: avoid;
        page-break-inside: avoid;
    }
}
/* #endregion */

/* #region Space qualification documents */
/* The documents a decision is taken on, side by side at a size that can be read: a scan is judged by its
   stamps and its small print, so it is not a thumbnail. A refused one steps back. */
.qualification-documents {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

    .qualification-documents figure {
        margin: 0;
        flex: 0 1 520px;
    }

        .qualification-documents figure.is-refused {
            opacity: 0.55;
        }

    .qualification-documents figcaption {
        margin-bottom: 6px;
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    .qualification-documents img {
        display: block;
        max-width: 100%;
        max-height: 720px;
        border: 1px solid var(--colorGray);
    }
/* #endregion */

/* #region Lens storyboard */
/* A scenario is read as a film, so it is drawn as one: a stack of fragments, each with its name,
   the sentence saying when it plays and the strip of elements inside it. The alternative — one
   flat table with a scene column — is how an operator loses track of which drone plate belongs
   to which fragment, which is the one thing this screen exists to make obvious. */
.storyboard-scene {
    margin-bottom: 22px;
    padding: 18px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurface);
}

    /* A fragment that can never appear in any film. Red, because red in this panel means
       "something is missing", and here something is: an element with no footage behind it. */
    .storyboard-scene.is-broken {
        border-color: var(--colorRed);
        box-shadow: inset 3px 0 0 var(--colorRed);
    }

    /* Every other scene a shade lighter, so where one fragment ends and the next begins is read at a glance
       rather than found by its border. Its cards step up with it, or they would sink into the scene. */
    .storyboard-scene:nth-child(even of .storyboard-scene) {
        background: #121212;
    }

        .storyboard-scene:nth-child(even of .storyboard-scene) .storyboard-point {
            background: #171717;
        }

    .storyboard-scene .table-wrapper {
        margin-block: 12px;
    }

    /* The scenes stand inside the Storyboard frame, whose own padding closes it; the last scene's gap
       to the next one would otherwise open an empty band at the frame's foot. */
    main section.form-section > .storyboard-scene:last-child {
        margin-bottom: 0;
    }

/* Both halves sit on the bottom of the fields, not on their middle. Centred, the short group of
   buttons on the right was floated to the vertical middle of the taller group on the left — so
   „Delete scene" stood a line higher than „Save scene" beside it, on a row where all four controls
   do the same kind of thing. The fields' own baseline is what every other row in this panel aligns
   to (see .point-fields). */
.storyboard-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 12px;
}

/* The fragment's name and its condition edit in place, on one line with the number that says
   where it plays — a fragment is not worth a screen of its own. */
main form.storyboard-title {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
    margin: 0;
    flex: 1 1 480px;
}

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

/* An element of the film, and not a row of a nine-column table with a form control in every cell:
   that gives headings of one or two letters, no field carrying its own name, and four buttons closing
   every row. A shot is one thing with a few settings, so it is drawn as one thing — what it is
   along the top, the settings underneath with their names on them. */
.storyboard-points {
    display: grid;
    gap: 8px;
    margin-block: 12px;
}

.storyboard-point {
    padding: 12px 14px 14px;
    border: 1px solid var(--colorGray);
    background: var(--colorSurfaceRaised);
}

    /* Red means something is missing, and here it is: an element with no footage behind it can
       never appear in any film. The card says so in words as well as in colour. */
    .storyboard-point.is-broken {
        border-color: var(--colorRed);
        box-shadow: inset 3px 0 0 var(--colorRed);
    }

.point-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
    font-size: var(--sizeSmall);
}

/* Where the element falls in the finished film. The one number on the card worth reading first. */
.point-position {
    min-width: 26px;
    color: var(--colorAccent);
    font-family: var(--fontDisplay);
    font-size: var(--sizeBig);
    line-height: 1;
}

.point-kind {
    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;
}

.point-anchor {
    color: var(--colorMuted);
    font-size: var(--sizeSmall);
}

.point-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
}

    .point-actions form {
        margin: 0;
    }

    .point-actions button {
        margin-top: 0;
    }

.point-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px 14px;
}

/* A field with its name over it, in the same micro-caps the rest of the panel labels things in.
   The label is the wrapper, so the whole thing — name included — focuses the control. */
.point-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 0 1 auto;
}

    .point-field > span {
        color: var(--colorMuted);
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    .point-field.is-title {
        flex: 1 1 200px;
    }

    /* The sentence the guest reads is the longest thing on the card and the one most often
       edited, so it takes whatever room is left. */
    .point-field.is-wide {
        flex: 2 1 320px;
    }

    .point-field.is-narrow {
        flex: 0 0 84px;
    }

    .point-field.is-check {
        flex: 0 0 auto;
    }

    /* Every control fills its field — except a checkbox, which is a box and not a column: the
       width rule would stretch it across the whole field. */
    .point-field input:not([type="checkbox"]),
    .point-field select {
        margin: 0;
        width: 100%;
    }

    /* The box sits under its name like every other control here, rather than beside it — a
       checkbox aligned differently from its neighbours is what makes a row look assembled by
       accident. The size and the accent are the panel's own, copied from div.checkbox: without
       them the general form rule above dresses a checkbox as a full-width padded field. */
    .point-field.is-check input[type="checkbox"] {
        align-self: flex-start;
        width: 20px;
        height: 20px;
        margin: 4px 0 0;
        padding: 0;
        accent-color: var(--colorAccent);
    }

.storyboard-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

    .storyboard-actions form {
        margin: 0;
    }

    .storyboard-actions button {
        margin-top: 0;
    }

/* The computed sentence under the name. It is the one piece of explanatory text the panel keeps
   on screen rather than behind an InfoTip, because it is not guidance — it is this record's
   own state, worked out from three fields nobody should have to combine by eye. */
.storyboard-condition {
    margin: 6px 0 0;
    font-size: var(--sizeSmall);
}

/* Adding to a fragment: two forms, each complete in itself and each saying what it adds. Side by side
   as eight bare boxes, their names live in placeholders, which vanish the moment anybody types. */
.storyboard-add {
    display: grid;
    gap: 10px;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--colorGray);
}

    main .storyboard-add form {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-end;
        gap: 10px 14px;
        margin: 0;
    }

    main .storyboard-add button {
        margin-top: 0;
    }

/* What this row of fields adds, said before the fields rather than only on the button at the
   end of them. */
.storyboard-add-title {
    flex: 0 0 100%;
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    font-weight: var(--weightMedium);
    letter-spacing: var(--track);
    text-transform: uppercase;
}

/* The preview: the shots a guest might film, and the film that comes out. */
.cut-preview-shots {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
}

.cut-preview-result {
    margin: 14px 0 0;
    font-size: var(--sizeSmall);
    line-height: 1.7;
}
/* #endregion */

/* #region Soul Live */
/* The live board: one line per message, newest on top. A soul's answer keeps the transcript's gold rule on
   its left; a guest's the grey one. */
.soul-live {
    display: grid;
    gap: 6px;
}

a.soul-live-line {
    display: block;
    padding: 10px 14px;
    border: 1px solid var(--colorGray);
    background: var(--colorDark);
    box-shadow: inset 2px 0 0 var(--colorGray);
    color: var(--colorText);
    text-decoration: none;
}

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

    a.soul-live-line:hover {
        border-color: var(--colorAccentSoft);
    }

    /* Red is the call to act: what looks like a phone number, an e-mail address or a card. */
    a.soul-live-line.is-flagged {
        border-color: var(--colorRed);
        box-shadow: inset 3px 0 0 var(--colorRed);
    }

    a.soul-live-line header {
        display: flex;
        flex-wrap: wrap;
        gap: 6px 14px;
        align-items: baseline;
        margin-bottom: 6px;
    }

    a.soul-live-line p {
        margin: 0;
        max-width: 110ch;
        line-height: 1.7;
        white-space: pre-wrap;
        word-break: break-word;
    }

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

a.soul-live-line.is-soul .soul-live-role {
    color: var(--colorAccent);
}

.soul-live-where {
    color: var(--colorLight);
    font-size: var(--sizeMicro);
}

.soul-live-time {
    margin-left: auto;
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    letter-spacing: 0.04em;
}

.soul-live-flags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}

.soul-live-flag {
    padding: 2px 8px;
    border: 1px solid var(--colorRed);
    color: var(--colorRed);
    font-size: var(--sizeMicro);
    letter-spacing: var(--track);
    text-transform: uppercase;
}

/* An answer that stopped before the model finished it: grey, because it is a fact about the line rather
   than something to act on — red stays for personal data. */
.soul-live-cut {
    padding: 2px 8px;
    border: 1px solid var(--colorMuted);
    color: var(--colorMuted);
    font-size: var(--sizeMicro);
    letter-spacing: var(--track);
    text-transform: uppercase;
}

.soul-live-status.is-live {
    color: var(--colorGreen);
}

.soul-live-status.is-alert {
    color: var(--colorRed);
}
/* #endregion */

/* #region Artist — message to patrons */
/* The artist's recorded message, played on their record. Black behind it rather than the panel's own
   surface: a video letterboxes itself, and a light frame around a dark first frame reads as a fault in
   the file rather than as the shape of the picture. */
.artist-audience-video {
    display: block;
    width: 100%;
    max-width: 480px;
    max-height: 320px;
    margin-bottom: 6px;
    background: #050505;
}
/* #endregion */

/* #region Filmable frames */
/* The frame a curator judges, drawn as large as its column allows, and a replacement waiting for approval
   beside it at the same size — two pictures compared side by side rather than one remembered. Square like
   every Filmable image, and contained rather than cropped, because a crop hides exactly the edge a curator
   may be judging. */
main .filmable-frames {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
}

    main .filmable-frames figure {
        margin: 0;
    }

    main .filmable-frames img {
        display: block;
        width: 100%;
        height: auto;
        aspect-ratio: 1;
        border: 1px solid var(--colorGray);
        object-fit: contain;
    }

    main .filmable-frames figcaption {
        margin-top: 6px;
        font-size: var(--sizeMicro);
        font-weight: var(--weightMedium);
        letter-spacing: var(--track);
        text-transform: uppercase;
    }

    main .filmable-frames figcaption:not([class]) {
        color: var(--colorMuted);
    }
/* #endregion */

/* #region Art — the patron's room */
/* The photographs a patron sent with a request for help choosing works, small enough to take in at once;
   each opens whole in a tab of its own. */
main .room-photos {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
}

    main .room-photos img {
        display: block;
        width: 160px;
        height: 160px;
        border: 1px solid var(--colorGray);
        object-fit: cover;
    }
/* #endregion */
