/* Models & Accounts: the models with their accounts, phones, SIMs and emails
   (Phase 4, section 8). Loaded on every page after analytics.css. Every class
   here starts with inv-, as those of Analytics start with an-; the rest of
   each screen is the admin's own components (card, list, table, badge,
   field, choices, alert, copy-text, section-nav), and the markup of every
   piece is in admin_app/views/README.md, "Models & Accounts".

   The look is the agreed mock's, docs/mockups/phase-4-accounts-and-phones.html:
   black, white and grey, colour only for status and, from 14 October 2026,
   a platform's mark (components.css, "Platform marks"), nothing that moves,
   the same drawing on a phone and a desktop, phone first. [Phase 4, section
   8.18]

   The pieces:
     .inv-title, .inv-title-text   a record's mark or a model's avatar beside
                                   the page title (page-header)
     .inv-search                   the area's search under the title
     .inv-search-panel             its results while typing (app.js)
     .inv-mark, .inv-mark-sm, .inv-mark-lg, .inv-mark-ghost, .inv-mark-bare
                                   a record's mark in its box of 32, 26 or 40
                                   pixels, dashed, or alone
     .inv-avatar, .inv-avatar-sm, .inv-avatar-md, .inv-avatar-lg
                                   a model's picture or portrait, a person's
                                   picture or initials (partials/picture.php);
                                   .inv-avatar-face hers on her page, 64 or 56
                                   pixels, in .inv-face-link with models.manage
     .inv-num, .inv-pnum, .inv-kind, .inv-warn
                                   a number on one line, a phone's "#2", the
                                   platform before a handle, a warning word
     .inv-record, .inv-record-text, .inv-record-sm
                                   a mark or a picture beside a name, a table's
                                   first cell; small beside a model's name
     .table tr.is-ended            an ended record's row, muted
     .inv-look, .inv-look-head, .inv-look-title, .inv-look-list,
     .inv-look-row, .inv-look-text, .inv-look-action
                                   Needs a look, and its quiet "Nothing ..."
     .inv-model-grid, .inv-model-card, .inv-model-body, .inv-model-name,
     .inv-model-counts, .inv-chevron
                                   the model cards
     .inv-ended, .inv-ended-body
                                   "Ended (n)", folded
     .inv-model-page, .inv-numbers, .inv-numbers-head, .inv-numbers-title
                                   a model's page (D95): its stack, and Last 30
                                   days over the tiles
     .inv-accounts, .inv-accounts-actions, .inv-views,
     .inv-views-phones, .inv-accounts-body, .inv-view, .inv-view-links,
     .inv-view-phones, .inv-accounts-foot
                                   its card Accounts: the switch Links | Phones,
                                   radio buttons CSS reads, the two views, and
                                   her own domains at its foot
     .inv-node, .inv-node-text, .inv-node-title, .inv-node-name,
     .inv-node-meta, .inv-node-warn, .inv-node-link, .inv-node-copy
                                   a node of the flow or of a phone: a mark or
                                   a picture beside a name and a line, in a
                                   box; with Copy, its name the link,
                                   stretched over it
     .inv-flow (.is-alone, .is-nowhere, .is-only, .is-several),
     .inv-flow-groups, .inv-flow-group (.is-empty), .inv-flow-sources,
     .inv-flow-none, .inv-flow-wire, .inv-flow-join, .inv-flow-page,
     .inv-flow-photo, .inv-flow-portrait, .inv-flow-out (.is-dashed),
     .inv-flow-merge, .inv-flow-fans (.is-main, .is-each), .inv-flow-in,
     .inv-flow-fan (.is-slip), .inv-flow-figure (.is-inline)
                                   the Links view's flow: accounts, link pages
                                   and her OnlyFans, its lines and arrows CSS,
                                   left to right from a card of 820 pixels, a
                                   chain per page below
     .inv-subhead, .inv-nolink, .inv-acc-rows (.is-faded), .inv-acc-main,
     .inv-acc-text, .inv-acc-name, .inv-acc-link
                                   "No link yet", "On no phone", the ended
                                   accounts, rows of a mark and a name
     .inv-onphones, .inv-onphone (.is-none),
     .inv-onphone-list (li.is-other), .inv-avatar-other
                                   the Phones view: each phone and what sits on
                                   it, another model's accounts faded
     .inv-edit-note                the window Edit's line on who added her
     .inv-progress, .inv-progress-count, .inv-progress-steps,
     .inv-progress-step, .inv-progress-mark, .inv-progress-body,
     .inv-progress-label, .inv-progress-line
                                   "Set up <Name>" on a model's page, while it
                                   is not set up (D80)
     .inv-phone-grid, .inv-phone-card, .inv-phone-head, .inv-phone-number,
     .inv-phone-status, .inv-phone-model, .inv-phone-issue,
     .inv-phone-section, .inv-phone-item, .inv-phone-item-text,
     .inv-phone-item-end, .inv-phone-empty, .inv-phone-more
                                   the phone wall
     .inv-rows, .inv-row, .inv-row-label, .inv-row-value, .inv-row-sub,
     .inv-row-action               setup rows: icon, label, value, action
     .inv-timeline, .inv-tl, .inv-tl-dot, .inv-tl-mark, .inv-tl-text,
     .inv-tl-note, .inv-tl-meta, .inv-tl-more
                                   History: the grey dot, or a mark in its
                                   tone (.is-success, .is-warning, .is-danger,
                                   .is-link, D107); .inv-tl.is-corrected a
                                   corrected bio record: muted, its dot
                                   hollow, and .inv-tl-action its Mark
                                   corrected (D105); .inv-tl.is-note a note
                                   among the entries, its .inv-tl-bubble and
                                   .inv-tl-steps
     .inv-notes, .inv-note, .inv-note-text, .inv-note-meta,
     .inv-note-actions, .inv-note-form
                                   Notes
     .inv-when, .inv-when-at, .inv-reason, .inv-source, .inv-add-note
                                   the forms and dialog pages
     .inv-results, .inv-results-group, .inv-result, .inv-results-more
                                   the search's results, on /search and in
                                   the panel
     .inv-phone-check, .inv-check-due
                                   a monthly check that is overdue (M3)
     .inv-avatar-xl                the picture in the window Edit of a model
                                   (D95) and of a person (D118)

   The badge's outline tone and small size are the badge's own, in
   components.css; the lines of a model's page take --color-tree-line from
   tokens.css. */

/* ------------------------------------------------------------------------
   The header: a record's mark beside its title, the search
   ------------------------------------------------------------------------ */

/* The mark or the avatar stands beside the title and its line, which wrap
   in their own column beside it, so a long address never pushes the mark
   onto a line of its own. */
.inv-title {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
}

.inv-title-text {
    flex: 1;
    min-width: 0;
}

.inv-search {
    position: relative;
    max-width: 560px;
    margin-top: var(--space-4);
}

/* The placeholder names four things; on a narrow phone at the field's 16
   pixels it would be cut. The typed text keeps 16, which a phone does not
   zoom into. */
@media (max-width: 479px) {
    .inv-search .input::placeholder {
        font-size: var(--text-base);
    }
}

/* The results while typing, under the field. */
.inv-search-panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    left: 0;
    z-index: var(--z-panel);
    max-height: min(60vh, 440px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 6px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-lg);
}

/* ------------------------------------------------------------------------
   Marks, initials, numbers and words
   ------------------------------------------------------------------------ */

/* A platform's mark in the text colour, an icon in the muted one, as the
   mock draws them; a platform with colours of its own (platform-<key>,
   components.css) tints the box and colours the glyph. */
.inv-mark {
    display: grid;
    place-items: center;
    flex: none;
    width: 32px;
    height: 32px;
    border: 1px solid var(--mark-border, var(--color-border));
    border-radius: var(--radius-sm);
    background: var(--mark-bg, var(--color-surface-muted));
    color: var(--mark-fg, var(--color-text));
}

.inv-mark .icon {
    width: 16px;
    height: 16px;
    color: var(--color-text-muted);
}

.inv-mark .glyph {
    width: 16px;
    height: 16px;
    fill: currentColor;
}

.inv-mark-sm {
    width: 26px;
    height: 26px;
    border-radius: calc(var(--radius-sm) - 2px);
}

.inv-mark-sm .icon,
.inv-mark-sm .glyph {
    width: 14px;
    height: 14px;
}

.inv-mark-lg {
    width: 40px;
    height: 40px;
    border-radius: calc(var(--radius-md) - 2px);
}

.inv-mark-lg .icon,
.inv-mark-lg .glyph {
    width: 20px;
    height: 20px;
}

/* What is counted rather than named, "+1 account of another model": a box of
   the dashed line of what sits on a phone. */
.inv-mark-ghost {
    border-style: dashed;
    border-color: var(--color-tree-line);
    background: transparent;
}

.inv-mark-ghost .icon {
    color: var(--color-text-subtle);
}

/* The mark alone, 16 pixels, in the colour around it: inside a .list-icon a
   platform's mark in the text colour and an icon at the list's own size, in
   a row's label as the label's icons are. A platform with colours of its
   own keeps its glyph's colour, without the tint. */
.inv-mark-bare {
    display: inline-grid;
    width: auto;
    height: auto;
    border: 0;
    border-radius: 0;
    background: none;
    color: var(--mark-fg, currentColor);
}

.inv-mark-bare .icon {
    color: inherit;
}

.list-icon .inv-mark-bare {
    color: var(--mark-fg, var(--color-text));
}

.list-icon .inv-mark-bare .icon {
    width: 1.125rem;
    height: 1.125rem;
    color: var(--color-text-muted);
}

.inv-avatar {
    display: grid;
    place-items: center;
    flex: none;
    width: 32px;
    height: 32px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-full);
    background: var(--color-surface-muted);
    color: var(--color-text);
    font-family: var(--font-display);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    line-height: 1;
}

.inv-avatar-sm {
    width: 24px;
    height: 24px;
    font-size: 10px;
}

.inv-avatar-md {
    width: 40px;
    height: 40px;
    font-size: var(--text-md);
}

.inv-avatar-lg {
    width: 44px;
    height: 44px;
    font-size: var(--text-md);
}

/* A number that reads as one, "0175 ··· 8813": figures of one width, never
   broken. */
.inv-num {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* In a page's title, whose tight tracking would draw the three dots of a
   short number as one dash. */
.page-title .inv-num {
    letter-spacing: normal;
}

/* A phone's "#2" in a line of text, in the display face, as the wall's large
   numbers are. */
.inv-pnum {
    font-family: var(--font-display);
    font-size: calc(var(--text-base) + 1px);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
}

/* The platform before a handle, "TikTok @nora.tok". */
.inv-kind {
    color: var(--color-text-subtle);
    font-weight: var(--weight-medium);
}

.inv-warn {
    color: var(--color-warning-text);
}

/* A mark or a picture beside a name and its line, the first cell of the
   admin's tables; small beside a model's name in a column of its own. */
.inv-record {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
}

.inv-record-text {
    min-width: 0;
}

.inv-record-sm {
    gap: var(--space-2);
}

/* An ended record's row, such as a banned account behind "Show ended". */
.table tr.is-ended td {
    color: var(--color-text-muted);
}

/* ------------------------------------------------------------------------
   Needs a look
   ------------------------------------------------------------------------ */

.inv-look-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 14px var(--space-5) var(--space-3);
}

.inv-look-title {
    font-size: var(--text-md);
    letter-spacing: -0.01em;
}

/* The icon, the sentence and its action; on a phone the action under the
   sentence, from 640 pixels at the row's end. */
.inv-look-row {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr);
    align-items: center;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-3) var(--space-5);
    border-top: 1px solid var(--color-border);
}

.inv-look-text {
    min-width: 0;
    overflow-wrap: anywhere;
}

.inv-look-action {
    display: flex;
    grid-column: 2;
    justify-self: start;
}

.inv-look-action form {
    display: flex;
}

@media (min-width: 640px) {
    .inv-look-head {
        padding: var(--space-4) var(--space-6) var(--space-3);
    }

    .inv-look-row {
        grid-template-columns: 36px minmax(0, 1fr) auto;
        padding: var(--space-3) var(--space-6);
    }

    .inv-look-action {
        grid-column: auto;
    }
}

/* ------------------------------------------------------------------------
   The model cards: one column on a phone, three from 768 pixels
   ------------------------------------------------------------------------ */

.inv-model-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-3);
}

@media (min-width: 768px) {
    .inv-model-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.inv-model-card {
    display: flex;
    align-items: center;
    gap: 14px;
    height: 100%;
    padding: var(--space-4);
    color: inherit;
    text-decoration: none;
}

@media (hover: hover) {
    .inv-model-card:hover {
        border-color: var(--color-border-strong);
        background: var(--color-surface-hover);
    }
}

.inv-model-body {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.inv-model-name {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.015em;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

.inv-model-counts {
    color: var(--color-text-muted);
    font-size: var(--text-sm);
}

.inv-chevron {
    width: 1rem;
    height: 1rem;
    color: var(--color-text-subtle);
}

/* "Ended (n)", folded under a model's links, the model cards or the phone
   wall. */
.inv-ended {
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-border);
}

.inv-ended-body {
    margin-top: var(--space-3);
}

/* ------------------------------------------------------------------------
   A model's page (D95), after the agreed mock docs/mockups/model-page.html:
   her picture in the header, her last 30 days, and the card Accounts with
   its two views, Links and Phones, and her own domains at its foot. The
   lines are CSS, the same drawing with and without script.
   ------------------------------------------------------------------------ */

.inv-model-page {
    --stack-gap: var(--space-6);
    gap: var(--space-6);
}

/* Her picture, larger than a record's mark, since the page is about her:
   56 pixels on a phone, 64 from 640. With models.manage it opens Edit. */
.inv-avatar-face {
    width: 56px;
    height: 56px;
    font-size: var(--text-xl);
}

@media (min-width: 640px) {
    .inv-avatar-face {
        width: 64px;
        height: 64px;
    }
}

.inv-title:has(.inv-avatar-face) {
    gap: var(--space-4);
}

.inv-face-link {
    display: block;
    flex: none;
    border-radius: var(--radius-full);
    text-decoration: none;
}

@media (hover: hover) {
    .inv-face-link:hover .inv-avatar-face {
        filter: brightness(0.92);
    }
}

/* Last 30 days: its title and "Full analytics" over the tiles. */
.inv-numbers-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.inv-numbers-title {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.01em;
}

.inv-numbers-title a {
    color: inherit;
    text-decoration: none;
}

@media (hover: hover) {
    .inv-numbers-title a:hover {
        text-decoration: underline;
        text-decoration-color: var(--color-border-strong);
        text-underline-offset: 3px;
    }
}

/* The card's head: the switch Links | Phones beside Add account. The
   switch is two radio buttons, and CSS shows the view that is chosen. */
.inv-accounts-actions {
    align-items: center;
}

.inv-views .segment {
    min-height: 28px;
    font-size: var(--text-sm);
}

@media (pointer: coarse) {
    .inv-views .segment {
        min-height: 36px;
    }
}

.inv-view-phones {
    display: none;
}

.inv-accounts:has(.inv-views-phones:checked) .inv-view-links {
    display: none;
}

.inv-accounts:has(.inv-views-phones:checked) .inv-view-phones {
    display: block;
}

/* The flow is laid out by the width of the card, not of the screen. */
.inv-accounts-body {
    container-type: inline-size;
}

/* Her own domains at the card's foot. */
.inv-accounts-foot {
    border-top: 1px solid var(--color-border);
}

/* ------------------------------------------------------------------------
   The nodes of the flow and of the phones: a mark or a picture beside a
   name and a line, in a box. A node that holds a button (Copy) is no link
   itself: its name is, stretched over it.
   ------------------------------------------------------------------------ */

.inv-node {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    padding: 8px 12px 8px 8px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: inherit;
    text-decoration: none;
}

@media (hover: hover) {
    a.inv-node:hover,
    .inv-node:has(.inv-node-link:hover) {
        border-color: var(--color-border-strong);
        background: var(--color-surface-hover);
    }

    a.inv-node:hover .inv-node-name,
    .inv-node-link:hover .inv-node-name {
        text-decoration: underline;
        text-decoration-color: var(--color-border-strong);
        text-underline-offset: 3px;
    }
}

.inv-node:focus-visible {
    outline-offset: 0;
}

.inv-node-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

/* A name is never cut: it wraps, at a dot or anywhere where it must. */
.inv-node-title {
    color: var(--color-text);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    overflow-wrap: anywhere;
}

.inv-node-title .badge {
    margin-left: 6px;
    vertical-align: 1px;
}

.inv-node-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    overflow-wrap: anywhere;
}

.inv-node-warn {
    color: var(--color-warning-text);
    font-size: var(--text-xs);
}

.inv-node-link {
    color: inherit;
    text-decoration: none;
}

.inv-node-link::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

.inv-node-link:focus-visible {
    outline: none;
}

.inv-node:has(.inv-node-link:focus-visible) {
    outline: 2px solid var(--color-focus);
    outline-offset: 0;
}

/* The live link with its Copy, above the stretched name. */
.inv-node-copy {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    min-height: 24px;
    color: var(--color-text-muted);
    font-size: 12.5px;
}

.inv-node-copy [data-copy-text] {
    flex-wrap: nowrap;
    gap: 2px;
    min-width: 0;
}

/* An address breaks after its domain (its <wbr>), never cut. */
.inv-node-copy .mono {
    min-width: 0;
    overflow-wrap: break-word;
}

.inv-node-copy .btn-icon {
    flex: none;
    width: 24px;
    min-width: 24px;
    height: 24px;
    min-height: 24px;
}

.inv-node-copy .btn-icon .icon {
    width: 14px;
    height: 14px;
}

/* A figure on a line, "1,640 visits", on the card's colour over the line. */
.inv-flow-figure {
    position: relative;
    z-index: 1;
    padding: 1px 8px;
    border-radius: var(--radius-full);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
    font-weight: var(--weight-semibold);
    white-space: nowrap;
}

.inv-flow-figure span {
    color: var(--color-text-subtle);
    font-weight: var(--weight-medium);
}

.inv-flow-figure.is-inline {
    display: none;
}

/* A link page's photo, as tall as a phone's screen, or her picture. */
.inv-flow-photo {
    position: relative;
    display: block;
    flex: none;
    width: 32px;
    height: 42px;
    overflow: hidden;
    border-radius: 6px;
    background: var(--color-surface-muted);
}

.inv-flow-photo img,
.inv-flow-portrait {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.inv-flow-page .inv-node-text {
    flex: 1;
}

.inv-flow-page > .icon {
    flex: none;
    width: 16px;
    height: 16px;
    margin-left: auto;
    color: var(--color-text-subtle);
}

/* ------------------------------------------------------------------------
   The flow, wide (a card of 820 pixels and more): per link page a group,
   its accounts joining into it, each page's line on to the spine on the
   right, and from it the arrow into her OnlyFans. Every cluster of pages
   that lead to the same fan accounts is a flow of its own.
   ------------------------------------------------------------------------ */

.inv-flow {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 28px 200px;
    align-items: center;
}

.inv-flow + .inv-flow,
.inv-flow + .inv-nolink {
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px dashed var(--color-border);
}

.inv-flow-groups,
.inv-flow-sources,
.inv-flow-fans {
    margin: 0;
    padding: 0;
    list-style: none;
}

.inv-flow-groups {
    grid-column: 1;
}

.inv-flow-group {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 32px 212px 104px;
    align-items: center;
    padding: 6px 0;
}

.inv-flow-group > .inv-flow-sources,
.inv-flow-group > .inv-flow-none {
    grid-column: 1;
}

.inv-flow-group > .inv-flow-join {
    grid-column: 2;
}

.inv-flow-group > .inv-flow-page {
    grid-column: 3;
}

.inv-flow-group > .inv-flow-out {
    grid-column: 4;
}

.inv-flow-fans.is-each {
    display: none;
}

.inv-flow-sources > li {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 290px) minmax(80px, 1fr);
    align-items: center;
    padding: 5px 0;
}

/* The line from each account to its group's spine, its visits on it. */
.inv-flow-wire {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    align-self: stretch;
    padding-right: 14px;
}

.inv-flow-wire::before,
.inv-flow-join::before,
.inv-flow-out::before,
.inv-flow-merge::before,
.inv-flow-in::before {
    content: "";
    position: absolute;
    top: 50%;
    right: 0;
    left: 0;
    border-top: 1px solid var(--color-tree-line);
}

/* The spines, drawn by each row: from the first row's middle to the
   last's. One for the accounts of a page, one for the pages, one for the
   fan accounts where a cluster leads to several. */
.inv-flow-sources > li::after,
.inv-flow-group::after,
.inv-flow.is-several .inv-flow-fans.is-main > li::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    border-right: 1px solid var(--color-tree-line);
}

.inv-flow.is-several .inv-flow-fans.is-main > li::after {
    right: auto;
    left: 0;
    border-right: 0;
    border-left: 1px solid var(--color-tree-line);
}

.inv-flow-sources > li:first-child::after,
.inv-flow-group:first-child::after,
.inv-flow.is-several .inv-flow-fans.is-main > li:first-child::after {
    top: 50%;
}

.inv-flow-sources > li:last-child::after,
.inv-flow-group:last-child::after,
.inv-flow.is-several .inv-flow-fans.is-main > li:last-child::after {
    bottom: 50%;
}

.inv-flow-sources > li:only-child::after,
.inv-flow-group:only-child::after,
.inv-flow.is-nowhere .inv-flow-group::after {
    display: none;
}

.inv-flow-join,
.inv-flow-out,
.inv-flow-merge,
.inv-flow-in {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    align-self: stretch;
}

/* The arrows: into each link page, and into her OnlyFans. */
.inv-flow-join::before,
.inv-flow-merge::before,
.inv-flow-in::before {
    right: 2px;
}

/* An arrowhead is a square's two borders turned about its own centre, so
   its tip lies exactly on the middle of the 1 pixel line it ends. */
.inv-flow-join::after,
.inv-flow-merge::after,
.inv-flow-in::after {
    content: "";
    position: absolute;
    top: calc(50% - 3.5px);
    right: 3px;
    box-sizing: border-box;
    width: 8px;
    height: 8px;
    border-top: 1.5px solid var(--color-text-subtle);
    border-right: 1.5px solid var(--color-text-subtle);
    transform: rotate(45deg);
    transform-origin: 50% 50%;
}

/* A page no account leads to yet: no line in. One not published yet: its
   line out dashed. */
.inv-flow-group.is-empty .inv-flow-join {
    visibility: hidden;
}

.inv-flow-out.is-dashed::before {
    border-top-style: dashed;
}

.inv-flow-page {
    min-width: 0;
}

/* An address of OnlyFans that names none of her accounts: a quiet node,
   dashed, no link. */
.inv-flow-fan.is-slip {
    border-style: dashed;
    background: transparent;
}

.inv-flow-fan.is-slip .inv-node-title {
    color: var(--color-text-muted);
    font-weight: var(--weight-medium);
}

/* Her fan accounts: one node each. Where a cluster leads to several, the
   line from the pages ends on their spine, and an arrow leads into each. */
.inv-flow-merge {
    grid-column: 2;
}

.inv-flow-fans.is-main {
    grid-column: 3;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.inv-flow-fans.is-main > li {
    max-width: 100%;
}

.inv-flow-in {
    display: none;
}

.inv-flow.is-several .inv-flow-merge::before {
    right: 0;
}

.inv-flow.is-several .inv-flow-merge::after {
    display: none;
}

.inv-flow.is-several .inv-flow-fans.is-main > li {
    position: relative;
    display: flex;
    align-items: center;
    padding: 4px 0;
}

.inv-flow.is-several .inv-flow-in {
    display: flex;
    flex: none;
    width: 28px;
}

/* A cluster of fan accounts no page leads to: they stand where the
   others do, without a line, at the start where she has no page at all. */
.inv-flow.is-alone .inv-flow-in,
.inv-flow.is-alone .inv-flow-fans.is-main > li::after {
    display: none;
}

.inv-flow.is-only .inv-flow-fans.is-main {
    grid-column: 1 / -1;
}

/* ------------------------------------------------------------------------
   The flow, narrow: each page a chain of its own, top to bottom, the spine
   on the left, a small row of her OnlyFans at its end.
   ------------------------------------------------------------------------ */
@container (max-width: 819px) {
    .inv-flow {
        display: block;
    }

    .inv-flow-merge,
    .inv-flow-fans.is-main,
    .inv-flow-group::after {
        display: none;
    }

    .inv-flow-group {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        padding: 0;
    }

    .inv-flow-group + .inv-flow-group {
        margin-top: var(--space-5);
        padding-top: var(--space-5);
        border-top: 1px dashed var(--color-border);
    }

    /* Each chain ends in her fan accounts, small and without a box, so
       four chains do not read as four OnlyFans accounts' worth of weight;
       so do fan accounts no page leads to. */
    .inv-flow-fans.is-each,
    .inv-flow.is-alone .inv-flow-fans.is-main {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
    }

    .inv-flow-fans.is-each .inv-flow-fan,
    .inv-flow.is-alone .inv-flow-fan {
        gap: 10px;
        padding: 2px 8px;
        border-color: transparent;
        background: none;
    }

    .inv-flow-fans.is-each .inv-mark,
    .inv-flow.is-alone .inv-flow-fan .inv-mark {
        width: 28px;
        height: 28px;
    }

    .inv-flow-fans.is-each .inv-node-text,
    .inv-flow.is-alone .inv-flow-fan .inv-node-text {
        flex-direction: row;
        align-items: baseline;
        gap: 6px;
    }

    /* A slip's address is long: its words under it. */
    .inv-flow-fans.is-each .inv-flow-fan.is-slip .inv-node-text {
        flex-direction: column;
        align-items: flex-start;
        gap: 2px;
    }

    .inv-flow.is-several .inv-flow-fans.is-main > li {
        display: block;
        padding: 0;
    }

    .inv-flow.is-several .inv-flow-fans.is-main > li::after,
    .inv-flow.is-several .inv-flow-in {
        display: none;
    }

    .inv-flow-sources {
        padding-left: 44px;
    }

    .inv-flow-sources > li {
        grid-template-columns: minmax(0, 1fr);
        padding: 2px 0;
    }

    .inv-flow-sources > li .inv-node {
        padding: 6px 0;
        border: 0;
        background: none;
    }

    .inv-flow-sources .inv-node-text {
        flex: 1;
    }

    .inv-flow-wire {
        display: none;
    }

    .inv-flow-figure {
        padding: 0;
    }

    .inv-flow-figure.is-inline {
        display: inline;
        margin-left: auto;
        padding-left: var(--space-3);
    }

    /* Each row's stub, and the spine down to the link page. */
    .inv-flow-sources > li::before {
        content: "";
        position: absolute;
        top: 50%;
        left: -20px;
        width: 14px;
        border-top: 1px solid var(--color-tree-line);
    }

    .inv-flow-sources > li::after,
    .inv-flow-sources > li:last-child::after,
    .inv-flow-sources > li:only-child::after {
        display: block;
        top: 0;
        right: auto;
        bottom: 0;
        left: -20px;
        border-right: 0;
        border-left: 1px solid var(--color-tree-line);
    }

    .inv-flow-sources > li:first-child::after {
        top: 50%;
    }

    .inv-flow-group.is-empty .inv-flow-join {
        display: none;
    }

    .inv-flow-join,
    .inv-flow-out {
        justify-content: flex-start;
        height: 28px;
        margin-left: 24px;
    }

    .inv-flow-out {
        height: 36px;
    }

    .inv-flow-join::before,
    .inv-flow-out::before {
        top: 0;
        right: auto;
        bottom: 2px;
        left: 0;
        border-top: 0;
        border-left: 1px solid var(--color-tree-line);
    }

    .inv-flow-out.is-dashed::before {
        border-left-style: dashed;
    }

    .inv-flow-join::after,
    .inv-flow-out::after {
        content: "";
        position: absolute;
        top: auto;
        right: auto;
        bottom: 3px;
        left: -3.5px;
        box-sizing: border-box;
        width: 8px;
        height: 8px;
        border-top: 1.5px solid var(--color-text-subtle);
        border-right: 1.5px solid var(--color-text-subtle);
        transform: rotate(135deg);
        transform-origin: 50% 50%;
    }

    .inv-flow-out .inv-flow-figure {
        margin: 0 0 0 16px;
    }
}

/* ------------------------------------------------------------------------
   Accounts without a link, below the flow, each with its one step; the
   ended ones in their fold; and the rows of a viewer who sees no links.
   ------------------------------------------------------------------------ */

.inv-subhead {
    margin: 0 0 var(--space-2);
    color: var(--color-text-subtle);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
}

.inv-acc-rows {
    margin: 0;
    padding: 0;
    list-style: none;
}

.inv-acc-rows > li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: 6px 0;
    border-radius: var(--radius-md);
}

/* A row is no link itself where it holds Copy: its name is, stretched
   over it, and the Copy stands above. */
.inv-acc-main {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    border-radius: var(--radius-md);
}

.inv-acc-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.inv-acc-text .inv-node-copy {
    align-self: flex-start;
}

.inv-acc-name {
    min-width: 0;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    overflow-wrap: anywhere;
}

.inv-acc-link {
    color: inherit;
    text-decoration: none;
}

.inv-acc-link::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

.inv-acc-link:focus-visible {
    outline: none;
}

.inv-acc-main:has(.inv-acc-link:focus-visible) {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
}

.inv-acc-name .badge {
    margin-left: 6px;
    vertical-align: 1px;
}

@media (hover: hover) {
    .inv-acc-link:hover .inv-node-name {
        text-decoration: underline;
        text-decoration-color: var(--color-border-strong);
        text-underline-offset: 3px;
    }
}

.inv-acc-rows > li > .btn {
    flex: none;
}

.inv-acc-rows.is-faded .inv-acc-name {
    color: var(--color-text-muted);
    font-weight: var(--weight-normal);
}

.inv-acc-rows.is-faded .inv-mark {
    border-color: var(--color-border);
    background: transparent;
    color: var(--color-text-subtle);
}

.inv-view-links .inv-ended {
    margin-top: var(--space-4);
}

/* ------------------------------------------------------------------------
   Phones: each phone and what sits on it, on a dashed line; what belongs
   to another model faded, with her face.
   ------------------------------------------------------------------------ */

.inv-onphones {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--space-6) var(--space-5);
}

.inv-onphone-list {
    margin: 0;
    padding: 4px 0 0 44px;
    list-style: none;
}

.inv-onphone-list > li {
    position: relative;
    padding: 4px 0;
}

.inv-onphone-list > li::before {
    content: "";
    position: absolute;
    top: 50%;
    left: -20px;
    width: 14px;
    border-top: 1px dashed var(--color-tree-line);
}

.inv-onphone-list > li::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -20px;
    border-left: 1px dashed var(--color-tree-line);
}

.inv-onphone-list > li:last-child::after {
    bottom: 50%;
}

.inv-onphone.is-none {
    padding-top: 2px;
}

.inv-onphone.is-none .inv-onphone-list {
    padding-left: 0;
}

.inv-onphone.is-none .inv-onphone-list > li::before,
.inv-onphone.is-none .inv-onphone-list > li::after {
    display: none;
}

.inv-onphone-list .inv-node {
    padding: 4px 8px 4px 4px;
    border-color: transparent;
    background: none;
}

@media (hover: hover) {
    .inv-onphone-list a.inv-node:hover {
        border-color: var(--color-border);
        background: var(--color-surface-hover);
    }
}

.inv-onphone-list > li.is-other .inv-node {
    opacity: 0.45;
}

@media (hover: hover) {
    .inv-onphone-list > li.is-other .inv-node:hover {
        opacity: 0.8;
    }
}

.inv-avatar-other {
    width: 32px;
    height: 32px;
}

/* ------------------------------------------------------------------------
   The window Edit: the quiet line on who added her, under its fields.
   ------------------------------------------------------------------------ */

.inv-edit-note {
    color: var(--color-text-subtle);
    font-size: var(--text-xs);
}

/* ------------------------------------------------------------------------
   "Set up <Name>": the four steps of a model that is not set up yet, done
   ones checked, the next with its one button, later ones quiet. [D80,
   point 7]
   ------------------------------------------------------------------------ */

.inv-progress .card-header {
    align-items: baseline;
}

/* "N of 4 done" beside the title, under it on a phone. */
@media (max-width: 639px) {
    .inv-progress .card-header {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-1);
    }

    .inv-progress .card-header > :first-child {
        flex-basis: auto;
    }
}

.inv-progress-count {
    flex: none;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    font-variant-numeric: tabular-nums;
}

.inv-progress-steps {
    margin: var(--space-4) 0 0;
    padding: 0;
    border-top: 1px solid var(--color-border);
    list-style: none;
}

.inv-progress-step {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-1) var(--space-4);
    min-height: 64px;
    padding: var(--space-3) var(--space-5);
    border-top: 1px solid var(--color-border);
}

.inv-progress-step:first-child {
    border-top: 0;
}

.inv-progress-mark {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border: 1.5px solid var(--color-border-strong);
    border-radius: var(--radius-full);
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.inv-progress-step.is-done .inv-progress-mark {
    border-color: var(--color-primary);
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.inv-progress-step.is-done .inv-progress-mark .icon {
    width: 15px;
    height: 15px;
    stroke-width: 2.75;
}

.inv-progress-step.is-next .inv-progress-mark {
    border-color: var(--color-primary);
    color: var(--color-text);
}

.inv-progress-body {
    min-width: 0;
}

.inv-progress-label {
    display: block;
    font-weight: var(--weight-medium);
}

.inv-progress-line {
    display: block;
    margin-top: 1px;
    overflow-wrap: anywhere;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
}

.inv-progress-step.is-done .inv-progress-label {
    color: var(--color-text-muted);
    font-weight: var(--weight-normal);
}

.inv-progress-step.is-later .inv-progress-label,
.inv-progress-step.is-later .inv-progress-line {
    color: var(--color-text-subtle);
}

.inv-progress-step.is-later .inv-progress-mark {
    border-color: var(--color-border);
}

.inv-progress .readonly-notice {
    margin: 0 var(--space-5) var(--space-4);
}

@media (min-width: 640px) {
    .inv-progress-step {
        padding-inline: var(--space-6);
    }

    .inv-progress .readonly-notice {
        margin-inline: var(--space-6);
    }
}

/* On a narrow phone the step's button goes under its words. */
@media (max-width: 479px) {
    .inv-progress-step {
        grid-template-columns: 28px minmax(0, 1fr);
    }

    .inv-progress-step > .btn,
    .inv-progress-step > form {
        grid-column: 2;
        justify-self: start;
        margin-top: var(--space-2);
    }
}

/* ------------------------------------------------------------------------
   The phone wall: a card per phone, one column on a phone, two from 640
   pixels, three from 1200. The number's link covers the card; each SIM and
   account line is a link of its own above it.
   ------------------------------------------------------------------------ */

.inv-phone-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4);
}

@media (min-width: 640px) {
    .inv-phone-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1200px) {
    .inv-phone-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.inv-phone-card {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: var(--space-4) var(--space-5) 10px;
}

@media (hover: hover) {
    .inv-phone-card:hover {
        border-color: var(--color-border-strong);
    }
}

.inv-phone-card:has(.inv-phone-number:focus-visible) {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
}

.inv-phone-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--space-2) var(--space-3);
}

.inv-phone-number {
    margin-right: auto;
    color: var(--color-text);
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.03em;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    text-decoration: none;
}

.inv-phone-number::after {
    content: "";
    position: absolute;
    inset: 0;
}

.inv-phone-number:focus-visible {
    outline: none;
}

.inv-phone-status {
    padding-top: var(--space-1);
    color: var(--color-text-muted);
    font-size: var(--text-sm);
}

.inv-phone-head .badge {
    margin-top: var(--space-1);
}

.inv-phone-model {
    margin-top: var(--space-1);
    color: var(--color-text-muted);
    overflow-wrap: anywhere;
}

.inv-phone-issue {
    color: var(--color-warning-text);
    font-size: var(--text-sm);
    overflow-wrap: anywhere;
}

.inv-phone-section {
    margin-top: var(--space-3);
    padding-top: 6px;
    border-top: 1px solid var(--color-border);
}

.inv-phone-item {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 38px;
    color: inherit;
    text-decoration: none;
}

.inv-phone-item > .icon {
    width: 16px;
    height: 16px;
    margin: 0 5px;
    color: var(--color-text-subtle);
}

.inv-phone-item:focus-visible {
    outline-offset: 0;
    border-radius: 6px;
}

@media (hover: hover) {
    .inv-phone-item:hover .inv-phone-item-text {
        text-decoration: underline;
        text-decoration-color: var(--color-border-strong);
    }
}

.inv-phone-item-text {
    min-width: 0;
    overflow-wrap: anywhere;
}

.inv-phone-item.is-account {
    flex-wrap: wrap;
    column-gap: 10px;
    row-gap: 0;
    padding: var(--space-1) 0;
}

.inv-phone-item-end {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
}

.inv-phone-empty,
.inv-phone-more {
    display: flex;
    align-items: center;
    min-height: 38px;
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
}

/* ------------------------------------------------------------------------
   Setup rows: an icon in the label, the value, an action. On a phone the
   value under its label; from 640 pixels three columns.
   ------------------------------------------------------------------------ */

.inv-rows {
    display: flex;
    flex-direction: column;
}

.inv-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--space-3);
    padding: var(--space-3) 0;
    border-top: 1px solid var(--color-border);
}

.inv-row:first-child {
    padding-top: 0;
    border-top: 0;
}

.inv-row:last-child {
    padding-bottom: 0;
}

.inv-row-label {
    display: flex;
    grid-column: 1;
    align-items: center;
    gap: var(--space-3);
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
}

.inv-row-label > .icon,
.inv-row-label > .inv-mark-bare {
    width: 18px;
    height: 18px;
    color: var(--color-text-subtle);
}

/* A platform's mark in its own colour, where it has one. */
.inv-row-label > .inv-mark-bare {
    color: var(--mark-fg, var(--color-text-subtle));
}

.inv-row-label .inv-mark-bare .glyph,
.inv-row-label .inv-mark-bare .icon {
    width: 18px;
    height: 18px;
}

/* Under the label, past its icon. */
.inv-row-value {
    grid-column: 1;
    min-width: 0;
    padding-left: 30px;
    overflow-wrap: break-word;
}

.inv-row-sub {
    display: block;
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
}

.inv-row-action {
    display: flex;
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    gap: var(--space-2);
}

@media (min-width: 640px) {
    .inv-row {
        grid-template-columns: calc(18px + var(--space-3) + 8.5rem) minmax(0, 1fr) auto;
        align-items: start;
    }

    .inv-row-label {
        padding-top: 1px;
    }

    .inv-row-value {
        grid-column: 2;
        padding-left: 0;
    }

    .inv-row-action {
        grid-column: 3;
        grid-row: 1;
        align-self: start;
    }
}

/* ------------------------------------------------------------------------
   History: a timeline, newest first. What a person looks for carries its
   mark (D107, point 5): a circle of 22 pixels with its drawing, the event's
   tone around it in a soft wash, grey for a note and a status without a
   tone. Every other entry is the grey dot, the newest filled. Each mark and
   dot stands at the middle of its entry, and the line runs from the first
   one's middle to the last one's. A note written on the account stands in
   its soft bubble, its steps quiet words on its meta line; a corrected
   record (D105) is muted and its dot hollow, the newest too.
   ------------------------------------------------------------------------ */

.inv-timeline {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* --tl-gap: the room under an entry, which its middle leaves out. */
.inv-tl {
    --tl-gap: 18px;
    position: relative;
    padding: 0 0 var(--tl-gap) 30px;
}

.inv-tl:last-child {
    --tl-gap: 0px;
    padding-bottom: 0;
}

.inv-tl::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 5px;
    border-left: 1px solid var(--color-border-strong);
}

.inv-tl:first-child::before {
    top: calc((100% - var(--tl-gap)) / 2);
}

.inv-tl:last-child::before {
    bottom: 50%;
}

.inv-tl-dot {
    position: absolute;
    top: calc((100% - var(--tl-gap)) / 2 - 5.5px);
    left: 0;
    width: 11px;
    height: 11px;
    border: 2px solid var(--color-text-subtle);
    border-radius: var(--radius-full);
    background: var(--color-surface);
}

.inv-tl:first-child .inv-tl-dot {
    border-color: var(--color-text);
    background: var(--color-text);
}

/* The mark: its drawing in its tone (HistoryEntry::$tone), the event tones
   of Add event's drawings. */
.inv-tl-mark {
    --tl-mark: var(--color-text-subtle);
    position: absolute;
    top: calc((100% - var(--tl-gap)) / 2 - 11px);
    left: -5.5px;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-full);
    background: var(--color-surface);
    color: var(--tl-mark);
}

.inv-tl-mark.is-success { --tl-mark: var(--color-event-verification); }
.inv-tl-mark.is-warning { --tl-mark: var(--color-event-status); }
.inv-tl-mark.is-danger { --tl-mark: var(--color-event-danger); }
.inv-tl-mark.is-link { --tl-mark: var(--color-event-link); }

.inv-tl-mark:is(.is-success, .is-warning, .is-danger, .is-link) {
    border-color: color-mix(in srgb, var(--tl-mark) 38%, transparent);
    background: color-mix(in srgb, var(--tl-mark) 11%, var(--color-surface));
}

/* Small, so its stroke is a little stronger, and without the drawing's own
   wash, which the circle's is. */
.inv-tl-mark .icon {
    width: 13px;
    height: 13px;
    stroke-width: 2.1;
}

.inv-tl-mark .icon-wash {
    display: none;
}

.inv-tl.is-note .inv-tl-mark .icon {
    width: 12px;
    height: 12px;
    stroke-width: 2;
}

.inv-tl-text {
    font-weight: var(--weight-medium);
    overflow-wrap: anywhere;
}

.inv-tl-note {
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

.inv-tl-meta {
    margin-top: 2px;
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

.inv-tl-more {
    margin-top: var(--space-3);
}

.inv-tl-action {
    font-size: var(--text-sm);
}

.inv-tl.is-corrected .inv-tl-text {
    color: var(--color-text-muted);
}

.inv-tl.is-corrected .inv-tl-dot,
.inv-tl.is-corrected:first-child .inv-tl-dot {
    border-color: var(--color-text-subtle);
    background: var(--color-surface);
}

/* A note among the entries: its text in a soft bubble, which opens its
   window where the person may change it, as its Edit does. */
.inv-tl-bubble {
    display: block;
    margin: 0;
    padding: var(--space-2) var(--space-3);
    border-radius: 10px;
    background: var(--color-surface-muted);
    color: var(--color-text);
    font-size: var(--text-sm);
    text-decoration: none;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

/* Edit, Pin or Unpin and Delete: quiet words on the note's meta line, a
   block of its own in the markup (it holds forms) that runs on in the line. */
.inv-tl-steps,
.inv-tl-steps form {
    display: inline;
}

.inv-tl-steps .text-button {
    display: inline;
    min-height: 0;
    color: inherit;
    font-size: inherit;
    font-weight: inherit;
}

@media (hover: hover) {
    a.inv-tl-bubble:hover,
    .inv-tl-steps .text-button:hover {
        text-decoration: underline;
        text-decoration-color: var(--color-border-strong);
        text-underline-offset: 3px;
    }

    .inv-tl-steps .text-button:hover {
        color: var(--color-text);
    }
}

/* A finger needs more than a line of small text: the target grows above
   and below by the room its margins give back, so the line stays as it is. */
@media (pointer: coarse) {
    .inv-tl-steps .text-button {
        margin: calc(-1 * var(--space-2)) 0;
        padding: var(--space-2) 0;
    }
}

/* ------------------------------------------------------------------------
   Notes: pinned first, on grey; the field to add one under them
   ------------------------------------------------------------------------ */

.inv-notes {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.inv-note {
    padding: var(--space-3) 14px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

.inv-note.is-pinned {
    background: var(--color-surface-muted);
}

.inv-note-text {
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

.inv-note-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-1) var(--space-3);
    margin-top: var(--space-1);
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
}

.inv-note-meta > span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.inv-note-meta .icon {
    width: 14px;
    height: 14px;
}

.inv-note-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    margin-right: calc(-1 * var(--space-2));
}

.inv-note-actions form {
    display: flex;
}

/* Quieter than a small button where the pointer is precise; a full target
   where a finger is. */
.inv-note-actions .btn {
    min-height: 28px;
    padding: 0 var(--space-2);
}

@media (pointer: coarse) {
    .inv-note-actions .btn {
        min-height: 44px;
    }
}

.inv-note-form {
    margin-top: 14px;
}

.inv-note-form .form {
    gap: var(--space-2);
    max-width: none;
}

.inv-note-form .form-actions {
    justify-content: flex-end;
    padding-top: 0;
}

/* ------------------------------------------------------------------------
   Forms and dialog pages
   ------------------------------------------------------------------------ */

/* When (D108, point 7): Earlier's day and time under the choice, shown
   only while Earlier is chosen. A browser without :has() shows it always,
   and the server reads it for Earlier alone. */
.inv-when-at {
    margin-top: var(--space-4);
}

.inv-when:has(.segmented-input[value="earlier"]:not(:checked)) .inv-when-at {
    display: none;
}

/* A note behind "Add a note" (inventory/add-note, D107 point 2): once
   opened, the step goes and the field stands in its place, as in the
   agreed mock; app.js gives the field the focus. A <details>, so without
   script the same. */
.inv-add-note[open] > summary {
    display: none;
}

.inv-add-note[open] > .disclosure-body {
    margin-top: 0;
}

/* Brought into view with the room under it, clear of a window's fading
   lower edge. */
.inv-add-note .textarea {
    scroll-margin-bottom: var(--space-6);
}

/* An account's reason belongs to Restricted, Suspended, Banned and Lost
   (Phase 4, section 4.1): while another status is chosen it is hidden. A
   browser without :has() shows it always, and the server ignores it then. */
form:has(input[name="status"]:checked):not(:has(input[name="status"]:is([value="restricted"], [value="suspended"], [value="banned"], [value="lost"]):checked)) .inv-reason {
    display: none;
}

/* How we know belongs to Restricted, Suspended and Banned (Phase 4, section
   4.2; D85), not to Lost: hidden while another status is chosen, and shown
   always by a browser without :has(), whose answer the server ignores then. */
form:has(input[name="status"]:checked):not(:has(input[name="status"]:is([value="restricted"], [value="suspended"], [value="banned"]):checked)) .inv-source {
    display: none;
}

/* ------------------------------------------------------------------------
   The search's results: on /search a card per kind of record, in the panel
   under the field the same markup, compact, as the mock's
   ------------------------------------------------------------------------ */

.inv-results {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

.inv-results-more {
    padding: var(--space-3) var(--space-5);
    border-top: 1px solid var(--color-border);
    color: var(--color-text-muted);
    font-size: var(--text-sm);
}

@media (min-width: 640px) {
    .inv-results-more {
        padding: var(--space-3) var(--space-6);
    }
}

.inv-search-panel .inv-results {
    gap: 0;
}

.inv-search-panel .inv-results-group {
    overflow: visible;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
}

.inv-search-panel .inv-results-group > .card-header {
    padding: 10px 10px var(--space-1);
}

.inv-search-panel .inv-results-group .card-title {
    color: var(--color-text-subtle);
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.inv-search-panel .inv-results-group > .card-flush {
    margin-top: 0;
    border-top: 0;
}

.inv-search-panel .inv-result {
    min-height: 48px;
    padding: 6px 10px;
    border-top: 0;
    border-radius: var(--radius-sm);
}

.inv-search-panel .inv-result > .icon:last-child {
    display: none;
}

.inv-search-panel .inv-result.is-active {
    background: var(--color-surface-selected);
}

@media (hover: hover) {
    .inv-search-panel .inv-result:hover {
        background: var(--color-surface-selected);
    }
}

.inv-search-panel .inv-result:focus-visible {
    outline-offset: -2px;
}

.inv-search-panel .inv-results-more {
    padding: var(--space-1) 10px var(--space-2);
    border-top: 0;
}

.inv-search-panel .empty-state {
    align-items: flex-start;
    padding: 14px 10px;
    text-align: left;
}

.inv-search-panel .empty-state-icon {
    display: none;
}

/* ------------------------------------------------------------------------
   Keeping it honest and the pictures (milestone M3): a check that is
   overdue, on the phone wall and on a phone's page; and the Picture card of
   a model's page and a person's page, the picture beside its form.
   [Phase 4, sections 7.2, 8.6, 8.9 and 8.15]
   ------------------------------------------------------------------------ */

.inv-phone-check,
.inv-check-due {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--color-warning-text);
}

.inv-phone-check {
    font-size: var(--text-sm);
}

.inv-phone-check .icon,
.inv-check-due .icon {
    flex: none;
    width: 14px;
    height: 14px;
}

.inv-avatar-xl {
    width: 72px;
    height: 72px;
    font-size: var(--text-2xl);
}

