/* xconversion design tokens are in tokens.css; this is the type system.
 *
 * Four families, matching the canvas: Poppins for display and headings,
 * Hanken Grotesk for body and interface, JetBrains Mono for figures, and
 * IBM Plex Sans Arabic for every Arabic role — set in its own face, never
 * the Latin one letterspaced.
 *
 * Declared here rather than interpolated through Blade: {{ }} escapes, and an
 * escaped quote inside a family name invalidates the whole declaration.
 */

body {
    margin: 0;
    font-family: 'Hanken Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
    font-size: 15px;
    line-height: 1.45;
    background: var(--bg);
    color: var(--text);
}

html[lang="ar"] body {
    font-family: 'IBM Plex Sans Arabic', system-ui, sans-serif;
}

/* Arabic reads smaller at the same nominal size, so it is set a step up. */
html[lang="ar"] {
    font-size: 15.5px;
}

h1, h2, h3 {
    font-family: Poppins, system-ui, sans-serif;
}

html[lang="ar"] :where(h1, h2, h3) {
    font-family: 'IBM Plex Sans Arabic', system-ui, sans-serif;
    letter-spacing: normal;
}

/* Figures are tabular everywhere so columns do not jitter between renders. */
:where(.tabular) {
    font-variant-numeric: tabular-nums;
}

/* shell — the app chrome.
 *
 * The canvas expressed hover states with a `style-hover` attribute, which is a
 * design-runtime feature and does nothing in a real browser. Those states are
 * re-expressed here as ordinary CSS, one class per interactive element, with
 * the same values the canvas used. Everything else in the shell stays inline,
 * exactly as the design wrote it.
 */

/* ── nav rail ─────────────────────────────────────────────────────── */

.xc-nav-btn:hover {
    background: rgba(var(--rail-ink), .07) !important;
    color: var(--rail-text) !important;
}

.xc-nav-btn:hover svg {
    stroke: var(--rail-text) !important;
}

.xc-search-btn:hover {
    border-color: var(--peri) !important;
    color: var(--rail-text) !important;
}

/* An entry's padding, wherever the rail is drawn — the phone's drawer too. */
[data-r="rail"] .xc-nav-btn { padding: 9px 10px; }
[data-r="rail"] .xc-rail-logo { padding-inline: 8px; }

/* Inside a workspace, the product's name is followed by the workspace's and
   where it stands on its plan (rail.blade.php): three lines, each kept to
   one line, so the block is the same height folded and open and nothing
   below it moves. */
.xc-planline { min-inline-size: 0; }

.xc-planline__brand {
    display: block;
    font-family: Poppins, sans-serif;
    font-weight: 600;
    font-size: 14px;
    letter-spacing: -0.01em;
    line-height: 1.25;
}

.xc-planline__name {
    display: block;
    margin-block-start: 1px;
    font-size: 12px;
    line-height: 1.3;
    color: rgba(var(--rail-ink), .6);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.xc-planline__plan { display: flex; min-inline-size: 0; margin-block-start: 6px; }

/* The rail is dark in both themes: the pill's colour lifted toward white. */
.xc-planline .xc-planpill {
    color: color-mix(in srgb, rgb(var(--tint)) 40%, #FFFFFF);
    background: rgba(var(--tint), .26);
    box-shadow: inset 0 0 0 1px rgba(var(--tint), .42);
}

/* ── the rail folds to its icons ──────────────────────────────────────
 *
 * On every desktop, whatever its width: the page gains the room the words
 * took, which it needs more than the words need to be on screen all day —
 * nobody reading a thread is reading the menu. The words come back the
 * moment the pointer reaches the rail, or the keyboard does.
 *
 * Over the page, not beside it. The rail widens and its outer margin shrinks
 * by the same amount, so the room it takes in the row never changes and
 * nothing on the page moves while it opens. Its icons stay exactly where
 * they were — every one sits on the folded rail's centre line, open or not —
 * and only the words appear beside them.
 *
 * Kept open while one of its menus is (the menu lives inside it and would be
 * cut off), and while the tour is pointing at it. Not on a phone, where the
 * same markup is the drawer (responsive.css).
 */
@media (min-width: 821px) {
    [data-r="rail"] {
        --rail-folded: 76px;
        /* Wide enough for the longest entry, "Onboarding checklist 2/4",
           with its count: at 248px the count was cut off. */
        --rail-open: 256px;

        position: relative;
        z-index: 60;
        flex: none;
        box-sizing: border-box;
        inline-size: var(--rail-folded);
        margin-block: 16px;
        margin-inline: 16px 0;
        padding: 20px 12px;
        overflow: hidden;
        transition:
            inline-size 200ms cubic-bezier(.2, .8, .25, 1),
            margin-inline-end 200ms cubic-bezier(.2, .8, .25, 1),
            box-shadow 200ms ease;
    }

    /* An icon never gives up its room to the word beside it: folded, the
       word is still there (see-through), and a flex item left to shrink
       would be the icon, squeezed to nothing. */
    [data-r="rail"] svg { flex-shrink: 0; }

    /* Folded, each icon on the centre line: the rail's inner width is 52px. */
    [data-r="rail"] .xc-rail-logo { padding-inline: 11px 8px; }
    [data-r="rail"] .xc-nav-btn { padding-block: 8px; padding-inline: 17.5px 10px; overflow: hidden; }
    [data-r="rail"] .xc-railsetup { padding-inline: 16.5px 10px; overflow: hidden; }
    [data-r="rail"] .xc-pop__on { padding-inline-start: 12px; }
    [data-r="rail"] .xc-pop__on--you { padding-inline-start: 4px; }
    [data-r="rail"] .xc-search-btn { overflow: hidden; }

    /* The words: there, and see-through, so nothing reflows when they come
       back — the rail's own edge is what hides them. */
    [data-r="rail"] .xc-nav-label,
    [data-r="rail"] .xc-rail-wide {
        opacity: 0;
        white-space: nowrap;
        transition: opacity 90ms ease;
    }

    /* A group's name gives way to a short rule between its icons and the
       next group's. The same height either way, so no icon moves. */
    [data-r="rail"] .xc-rail-group { position: relative; }

    [data-r="rail"] .xc-rail-group::before {
        content: "";
        position: absolute;
        inset-block-start: 6px;
        inset-inline-start: 17px;
        inline-size: 18px;
        block-size: 1px;
        background: rgba(var(--rail-ink), .16);
        transition: opacity 90ms ease;
    }

    /* A count folds to a dot on its icon: that something is waiting is worth
       knowing without opening the rail; how many is not. */
    [data-r="rail"] .xc-nav-n {
        position: absolute;
        inset-block-start: 6px;
        inset-inline-start: 31px;
        min-inline-size: 0;
        inline-size: 7px;
        block-size: 7px;
        padding: 0;
        font-size: 0;
        background: var(--peri);
        opacity: 1;
    }

    /* The menu scrolls up and down; sideways there is only a word being
       uncovered, never anything to scroll to. No scrollbar, open or folded:
       folded, a bar would push the icons off the centre line, and open it
       took ten pixels from every entry — on Windows a bar with arrows,
       drawn over the end of the checklist and its count. The wheel, the
       trackpad and the keyboard scroll it all the same. */
    [data-r="rail"] [data-keep-scroll="rail"] {
        overflow-x: hidden;
        scrollbar-width: none;
    }

    [data-r="rail"] [data-keep-scroll="rail"]::-webkit-scrollbar { display: none; }

    /* A label that does not fit gives way before its count does: "3/4" is
       the part of the checklist entry worth reading. */
    [data-r="rail"] .xc-railsetup__label {
        min-inline-size: 0;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

/* Open: on hover where there is a pointer to hover with; on keyboard focus,
   with a menu open, and under the tour everywhere. A short wait before it
   opens, so a pointer crossing the rail on its way somewhere does not flash
   it open; none before it closes. */
@media (min-width: 821px) and (hover: hover) {
    [data-r="rail"]:hover {
        inline-size: var(--rail-open);
        margin-inline-end: calc(var(--rail-folded) - var(--rail-open));
        box-shadow: 0 24px 60px rgba(var(--scrim), .38);
        transition-delay: 110ms;
    }

    [data-r="rail"]:hover .xc-nav-label,
    [data-r="rail"]:hover .xc-rail-wide {
        opacity: 1;
        transition: opacity 160ms ease 190ms;
    }

    [data-r="rail"]:hover .xc-rail-group::before { opacity: 0; }

    [data-r="rail"]:hover .xc-nav-n {
        position: static;
        inline-size: auto;
        block-size: auto;
        min-inline-size: 20px;
        padding: 2px 6px;
        font-size: 10.5px;
        background: rgba(var(--rail-ink), .1);
    }
}

@media (min-width: 821px) {
    [data-r="rail"]:has(:focus-visible),
    [data-r="rail"]:has(.xc-pop[open]),
    html:has(.xc-tour__card) [data-r="rail"] {
        inline-size: var(--rail-open);
        margin-inline-end: calc(var(--rail-folded) - var(--rail-open));
        box-shadow: 0 24px 60px rgba(var(--scrim), .38);
    }

    [data-r="rail"]:has(:focus-visible) :is(.xc-nav-label, .xc-rail-wide),
    [data-r="rail"]:has(.xc-pop[open]) :is(.xc-nav-label, .xc-rail-wide),
    html:has(.xc-tour__card) [data-r="rail"] :is(.xc-nav-label, .xc-rail-wide) {
        opacity: 1;
    }

    [data-r="rail"]:has(:focus-visible) .xc-rail-group::before,
    [data-r="rail"]:has(.xc-pop[open]) .xc-rail-group::before,
    html:has(.xc-tour__card) [data-r="rail"] .xc-rail-group::before {
        opacity: 0;
    }

    [data-r="rail"]:has(:focus-visible) .xc-nav-n,
    [data-r="rail"]:has(.xc-pop[open]) .xc-nav-n,
    html:has(.xc-tour__card) [data-r="rail"] .xc-nav-n {
        position: static;
        inline-size: auto;
        block-size: auto;
        min-inline-size: 20px;
        padding: 2px 6px;
        font-size: 10.5px;
        background: rgba(var(--rail-ink), .1);
    }

    /* A menu of its own reaches past its edge — the help menu is wider than
       the open rail — so nothing is cut off while one is open. */
    [data-r="rail"]:has(.xc-pop[open]) { overflow: visible; }

    /* The tour measures the rail the moment it starts, so under the tour it
       is open at once rather than on its way. */
    html:has(.xc-tour__card) [data-r="rail"],
    html:has(.xc-tour__card) [data-r="rail"] :is(.xc-nav-label, .xc-rail-wide) {
        transition: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    [data-r="rail"],
    [data-r="rail"] .xc-nav-label,
    [data-r="rail"] .xc-rail-wide {
        transition: none !important;
    }
}

/* ── header ───────────────────────────────────────────────────────── */

.xc-icon-btn:hover {
    background: rgba(var(--ink), .09) !important;
}

/* ── bottom bar (phone) ───────────────────────────────────────────── */

.xc-btm-btn:hover {
    color: var(--rail-text);
}

/* The drawer's ✕. Only the phone's drawer draws it (responsive.css): the
 * desktop rail is always there and has nothing to close. */
.xc-rail-x { display: none; }

/* ── the bell's sheet (layout/partials/notes-sheet) ──────────────────────
 * A panel down the end side of the screen on a desktop, sliding in from it.
 * responsive.css makes it a full-height sheet from the bottom on a phone.
 * [data-modal] in the selector to outrank `dialog[data-modal] { margin:auto }`,
 * which otherwise centres it like every other dialog. */
dialog[data-modal].xc-notes-host {
    margin-block: 0;
    margin-inline: auto 0;
    block-size: 100dvh;
    max-block-size: 100dvh;
    inline-size: min(420px, 100vw);
    max-inline-size: 100vw;
}

dialog.xc-notes-host .xc-sheet {
    block-size: 100%;
    max-block-size: none;
    border-start-end-radius: 0;
    border-end-end-radius: 0;
    border-inline-end: 0;
    animation: xc-notes-in 260ms cubic-bezier(.2, .8, .25, 1);
}

@keyframes xc-notes-in {
    from { transform: translateX(calc(100% * var(--xc-flip))); }
    to { transform: none; }
}

.xc-notes-host .xc-sheet__head .xc-act { flex: none; }

.xc-notes { display: flex; flex-direction: column; gap: 8px; }

.xc-notes__count {
    margin: 0;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 11px;
    letter-spacing: .08em;
    color: var(--peri);
}

.xc-notes__rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }

.xc-notes__row {
    display: flex;
    align-items: center;
    gap: 12px;
    min-block-size: 56px;
    box-sizing: border-box;
    padding: 10px;
    border-radius: 14px;
    color: var(--text);
    text-decoration: none;
}

.xc-notes__row:hover,
.xc-notes__row:focus-visible { background: rgba(var(--ink), .05); }
.xc-notes__row[data-unread] { background: rgba(var(--brand), .06); }

.xc-notes__icon {
    flex: none;
    inline-size: 36px;
    block-size: 36px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgb(var(--tint));
    background: rgba(var(--tint), .13);
}

.xc-notes__words { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; gap: 2px; }

.xc-notes__words strong {
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    unicode-bidi: plaintext;
}

.xc-notes__words span { font-size: 13.5px; color: rgba(var(--ink), .55); }

.xc-notes__row time {
    flex: none;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 11.5px;
    color: rgba(var(--ink), .4);
}

/* "2h ago" is a number and takes the mono face; "منذ أسبوع" is words. */
[dir="rtl"] .xc-notes__row time { font-family: inherit; font-size: 12.5px; }

.xc-notes__dot { flex: none; inline-size: 8px; block-size: 8px; border-radius: 50%; background: var(--peri); }

.xc-notes__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
    padding: 44px 12px;
}

.xc-notes__empty-icon {
    inline-size: 48px;
    block-size: 48px;
    border-radius: 16px;
    margin-block-end: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(var(--ink), .4);
    background: rgba(var(--ink), .05);
}

.xc-notes__empty strong { font-size: 16px; }
.xc-notes__empty > span:last-child { font-size: 14px; line-height: 1.5; color: rgba(var(--ink), .5); max-inline-size: 300px; }

/* ── who a thread is with (screens/inbox/sections/contact) ─────────────── */

/* The name in a thread's head, as a button that opens the contact. */
.xc-who {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-align: start;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 13px;
    flex: 1;
    min-inline-size: 0;
    border-radius: 14px;
}

.xc-chip-state {
    align-self: flex-start;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 11px;
    letter-spacing: .06em;
    color: rgb(var(--tint));
    background: rgba(var(--tint), .13);
    border-radius: 20px;
    padding: 4px 11px;
}

/* Label and value on one line, the mockup's contact card. */
.xc-facts { margin: 0; display: flex; flex-direction: column; }

.xc-facts > div {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding-block: 10px;
    border-block-end: 1px solid var(--line);
}

.xc-facts dt { flex: 1; font-size: 14px; color: rgba(var(--ink), .5); }
.xc-facts dd { margin: 0; font-size: 15px; text-align: end; unicode-bidi: plaintext; overflow-wrap: anywhere; }
.xc-facts__mono { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 14px !important; }

/* Chevrons point the way the reader reads.
 *
 * Four paths draw every "next", "back" and "go" chevron in the product, and
 * in Arabic all of them pointed the English way — "next" aiming back at where
 * somebody had come from. Matched on the path rather than a class so that no
 * chevron can be added without it, and flipped about its own box so it stays
 * where it was drawn. Down carets and the play triangle are not directions of
 * reading, and are left alone. */
[dir="rtl"] path:is([d="m9 6 6 6-6 6"], [d="M9 6l6 6-6 6"], [d="m15 6-6 6 6 6"], [d="M15 6l-6 6 6 6"]) {
    transform: scaleX(-1);
    transform-box: fill-box;
    transform-origin: center;
}

/* ── the checklist, as a sheet (phone) ────────────────────────────────────
 * partials/setup-sheet. One row a step: the ring, the step, and — for the
 * next one only — why it matters. */
.xc-setsheet {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.xc-setsheet__row {
    display: flex;
    align-items: center;
    gap: 12px;
    min-block-size: 56px;
    padding: 12px 14px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
}

a.xc-setsheet__row:active { background: var(--surface-2); }

.xc-setsheet__words {
    flex: 1;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.xc-setsheet__words strong { font-size: 15px; font-weight: 600; }
.xc-setsheet__row[data-done] strong { color: rgba(var(--ink), .45); }

.xc-setsheet__words em {
    font-style: normal;
    font-size: 13px;
    color: rgba(var(--ink), .45);
}

.xc-setsheet__row[data-done] em { color: var(--green); }

.xc-setsheet__why {
    font-size: 15px;
    line-height: 1.5;
    color: rgba(var(--ink), .6);
}

.xc-setsheet__go { flex: none; color: var(--peri); }

/* Skip link — the keyboard path starts here. Visually hidden until focused. */

/* Hidden by clipping it to nothing where it stands, not by parking it 9999px
 * off the start edge. In Arabic the start edge is the right-hand one, and a
 * link ten thousand pixels past it gave the page ten thousand pixels of width
 * on that side — invisible, until anything measured the page. */
.xc-skip {
    position: absolute;
    inset-inline-start: 16px;
    inset-block-start: 12px;
    z-index: 100;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 10px 16px;
    font-size: 14px;
    clip-path: inset(50%);
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    white-space: nowrap;
}

.xc-skip:focus {
    clip-path: none;
    inline-size: auto;
    block-size: auto;
    overflow: visible;
}

/* The focus ring is global rather than remembered per component. */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--peri);
    outline-offset: 2px;
    border-radius: 10px;
}

/* ── dashboard ────────────────────────────────────────────────────── */

/* The chart crosshair is pure CSS — no JS, so it works before app.js loads
 * and cannot desync from the DOM. The numbers are also in the labels row
 * beneath, so nothing is gated behind a pointer. */
.xc-chart-cell:hover .xc-chart-rule,
.xc-chart-cell:hover .xc-chart-dot,
.xc-chart-cell:hover .xc-chart-tip {
    opacity: 1;
}

/* Centring on a logical inset needs to know which way is "back".
 *
 * The dot and the tip sit at inset-inline-start:50% and pull back by half
 * their width. In Arabic that inset is measured from the right, so pulling
 * *left* by half — which is all translate() knows how to do — put the dot a
 * full width off its point and the tip beside the line instead of over it.
 * The pull is multiplied by this, so it goes the right way in both. */
:root { --xc-flip: 1; }
[dir="rtl"] { --xc-flip: -1; }

/* A tip centred on the last column hangs half its width past the end of the
 * card, which on a phone is past the edge of the screen. The two end columns
 * anchor theirs inward instead. */
.xc-chart-cell:first-child { --xc-tipx: 0%; }
.xc-chart-cell:last-child { --xc-tipx: -100%; }

.xc-thread-card:hover {
    border-color: #5B5BF0;
    background: var(--surface-2);
}

.xc-lane-row:hover {
    background: rgba(var(--ink), .07);
}

.xc-ledger-cta:hover {
    filter: brightness(1.08);
}

/* ── modals ─────────────────────────────────────────────────────────────
 * <dialog> gives us Escape, focus trapping and inertness for free. What it
 * does not give us is a backdrop worth looking at, and ::backdrop is
 * unreachable from a style attribute, so it lives here.
 */
dialog[data-modal] {
    color: var(--text);
    margin: auto;
}

dialog[data-modal]::backdrop {
    background: rgba(10, 10, 25, .45);
    backdrop-filter: blur(2px);
}

dialog[data-modal][open] {
    animation: xc-modal-in 200ms cubic-bezier(.2, .8, .25, 1) both;
}

@keyframes xc-modal-in {
    from { opacity: 0; transform: translateY(8px) scale(.98); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    dialog[data-modal][open] { animation: none; }
}

/* The `hidden` attribute loses to an inline display.
 *
 * A UA stylesheet gives [hidden] display:none, but this project sets layout in
 * style attributes, and an inline display:flex outranks it. Anything toggled
 * with el.hidden then stays on screen — silently, because the attribute is
 * there and looks right in the inspector.
 */
[hidden] { display: none !important; }

/* ── buttons ────────────────────────────────────────────────────────────
 * Action buttons were flat coloured labels: nothing said they were pressable
 * except the cursor, and "delete" sat at the same weight as "edit" beside it.
 * These give them an edge, a hover, a press, and a focus ring — and a variant
 * per intent, so destructive reads as destructive before it is clicked.
 */
.xc-act {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border-radius: 10px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: rgba(var(--ink), .72);
    font: inherit;
    font-size: 12.5px;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background 140ms, border-color 140ms, transform 140ms, box-shadow 140ms;
}

.xc-act:hover {
    background: rgba(var(--ink), .05);
    border-color: rgba(var(--ink), .22);
    transform: translateY(-1px);
}

.xc-act:active { transform: none; }

.xc-act:focus-visible {
    outline: 2px solid var(--peri);
    outline-offset: 2px;
}

.xc-act svg { flex: none; }

.xc-act[disabled] {
    opacity: .45;
    cursor: not-allowed;
    transform: none;
}

/* Going live is the one that changes what customers hear. */
.xc-act--go {
    color: #00806A;
    border-color: rgba(0, 168, 134, .34);
    background: rgba(0, 168, 134, .09);
}

.xc-act--go:hover {
    background: rgba(0, 168, 134, .16);
    border-color: rgba(0, 168, 134, .5);
}

.xc-act--hold {
    color: #C8791A;
    border-color: rgba(232, 163, 61, .38);
    background: rgba(232, 163, 61, .1);
}

.xc-act--hold:hover {
    background: rgba(232, 163, 61, .18);
    border-color: rgba(232, 163, 61, .55);
}

.xc-act--danger {
    color: #b83636;
    border-color: rgba(214, 69, 69, .28);
    background: rgba(214, 69, 69, .07);
}

.xc-act--danger:hover {
    background: rgba(214, 69, 69, .14);
    border-color: rgba(214, 69, 69, .45);
}

/* Square, label-less. For the secondary actions in a tight row, where four
 * full-width buttons wrap and the wrap reads as an accident. The label moves
 * to aria-label and title, so it is still announced and still on hover. */
.xc-act--icon {
    /*
     * `box-sizing` because there is no global reset for it here: without it
     * the 30 below is the content box, the padding and border are added on
     * top, and every icon button in the product renders at 46px. Three of them
     * then wrapped out of a column measured for three.
     */
    box-sizing: border-box;
    padding: 0;
    inline-size: 34px;
    block-size: 34px;
    justify-content: center;
}

/*
 * Tinted by what the button does, not decorated.
 *
 * Three actions sit together on a row — look at it, change it, lose it — and
 * three identical grey squares make the third one as easy to hit as the first.
 * The colour is the only thing separating them at a glance, so it carries the
 * meaning rather than the mood: green is safe, indigo is the working action,
 * red is the one you cannot undo.
 */
.xc-act--look {
    color: #00806A;
    border-color: rgba(0, 168, 134, .28);
    background: rgba(0, 168, 134, .08);
}

.xc-act--look:hover {
    background: rgba(0, 168, 134, .16);
    border-color: rgba(0, 168, 134, .45);
}

.xc-act--edit {
    color: var(--acc);
    border-color: rgba(28, 28, 210, .24);
    background: rgba(28, 28, 210, .07);
}

.xc-act--edit:hover {
    background: rgba(28, 28, 210, .13);
    border-color: rgba(28, 28, 210, .4);
}

/* A row of them, kept on one line until it genuinely cannot be. */
.xc-acts {
    display: flex;
    gap: 7px;
    flex-wrap: wrap;
    align-items: center;
}

/* ── surfaces ───────────────────────────────────────────────────────────
 * The canvas draws two kinds of box and they are not the same thing. A panel
 * holds content and sits still. A card stands for something you can pick, and
 * lifts when the pointer is over it — which is the only thing on a grid of
 * eight identical rectangles that says "these are choices".
 *
 * These were inline styles repeated across nine screens, drifting by a pixel
 * of radius at a time.
 */
.xc-panel {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    box-sizing: border-box;
}

/* ── Arriving (modules/arrive.js) ──────────────────────────────────────
 *
 * The marketing site's one signature move, brought over: a panel rises,
 * un-blurs and fades as you reach it. Same curve — it decelerates hard at the
 * end, which is what makes it read as settling rather than as sliding.
 *
 * Half the amounts, though. The landing takes 900ms, rises 34px and blurs
 * 6px, and it can: reading it is the only thing the visitor is doing. This is
 * a tool somebody is working in, where the same numbers read as lag. The
 * character survives the trim; the wait does not.
 *
 * Only under `html[data-arrive="on"]`, which arrive.js sets. Without the
 * script, with reduced motion asked for, or if the file never parses, nothing
 * here applies and every panel is simply where it ends up — a page that needs
 * a script to be visible is a page that is sometimes blank.
 * ──────────────────────────────────────────────────────────────────── */

/*
 * Hidden instantly, revealed over time — and never the other way round.
 *
 * The transition was on the element unconditionally, which meant marking a
 * block for arrival made it fade *out* over half a second before fading back
 * in. A pulse, not an arrival. The transition belongs on the arrived state
 * alone: going in is a move worth watching, going out is a state the element
 * should simply already be in.
 */
html[data-arrive='on'] [data-arrive]:not([data-arrive-in]) {
    opacity: 0;
    /* translate3d, not translateY: it keeps the block on its own layer for
       the whole move, and a card of numbers re-rasterising mid-rise is the
       shimmer this is supposed to avoid. */
    transform: translate3d(0, 16px, 0);
    filter: blur(4px);
}

html[data-arrive='on'] [data-arrive][data-arrive-in] {
    opacity: 1;
    /* `none`, so a card that lifts on hover still lifts rather than fighting
       a transform left behind by the arrival. */
    transform: none;
    filter: none;
    transition:
        opacity 520ms cubic-bezier(0.2, 0.8, 0.2, 1) var(--arrive-delay, 0ms),
        transform 520ms cubic-bezier(0.2, 0.8, 0.2, 1) var(--arrive-delay, 0ms),
        filter 520ms cubic-bezier(0.2, 0.8, 0.2, 1) var(--arrive-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
    html[data-arrive='on'] [data-arrive],
    html[data-arrive='on'] [data-arrive]:not([data-arrive-in]),
    html[data-arrive='on'] [data-arrive][data-arrive-in] {
        opacity: 1;
        transform: none;
        filter: none;
        transition: none;
    }
}

/* ── KPI tiles ──────────────────────────────────────────────────────────
 * Icon chip, mono label, a big tabular number, a line of context. Built four
 * times inline before this existed.
 */
.xc-kpis {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
}

.xc-kpi {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 16px;
    padding: 15px 16px;
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.xc-kpi__head {
    display: flex;
    align-items: center;
    gap: 9px;
}

.xc-kpi__chip {
    inline-size: 28px;
    block-size: 28px;
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.xc-kpi__label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: .13em;
    color: rgba(var(--ink), .35);
}

.xc-kpi__value {
    font-family: 'JetBrains Mono', monospace;
    font-weight: 500;
    font-size: 26px;
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.xc-kpi__sub {
    font-size: 13px;
    color: rgba(var(--ink), .45);
}

@media (max-width: 1100px) {
    .xc-kpis { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 620px) {
    .xc-kpis { grid-template-columns: 1fr; }
}

/* ── the primary call to action ─────────────────────────────────────────
 * Used as a class on nine screens and never actually defined — every one of
 * them carried the same inline styles instead.
 */
.xc-primary {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: 0;
    border-radius: 13px;
    padding: 10px 17px;
    /* The canvas's gradient, not a flat fill. It is the one place the brand
       colour moves, and a flat button beside a gradient one is the difference
       people notice without being able to name it. */
    background: linear-gradient(135deg, #1C1CD2, #5B5BF0);
    /* White in both themes. It was var(--onmine) — the text colour on your
       own chat bubbles, which turns dark in dark mode because the bubbles
       turn white. The gradient does not, so every primary button in dark
       mode read near-black on blue. */
    color: #fff;
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: transform 160ms, box-shadow 160ms, filter 160ms;
}

/* The lift exists at rest too: the canvas keeps the glow under it always, and
   only deepens it on hover. */
.xc-primary {
    box-shadow: 0 12px 28px rgba(28, 28, 210, .3);
}

.xc-primary:hover {
    transform: translateY(-2px);
    filter: brightness(1.06);
    box-shadow: 0 16px 34px rgba(28, 28, 210, .36);
}

.xc-primary:active { transform: none; }

.xc-primary:focus-visible {
    outline: 2px solid var(--peri);
    outline-offset: 3px;
}

.xc-primary[disabled] {
    opacity: .45;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* A progress rail, as the canvas draws under a segment card. */
.xc-rail {
    display: block;
    block-size: 5px;
    border-radius: 3px;
    background: rgba(var(--ink), .06);
    overflow: hidden;
}

.xc-rail > span {
    display: block;
    block-size: 100%;
    border-radius: 3px;
    transition: inline-size 400ms cubic-bezier(.2, .8, .25, 1);
}

/* ── the hero figure ────────────────────────────────────────────────────
 * The canvas paints it with a gradient clipped to the glyphs, at 42px. It was
 * rendering as small flat body text, which is why the header read as a label
 * rather than as the headline it is.
 */
.xc-hero {
    font-family: 'JetBrains Mono', monospace;
    font-weight: 500;
    font-size: 38px;
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    background: linear-gradient(90deg, #1C1CD2, #5B5BF0);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* A dash is not a figure — paint it as absent rather than as a gradient. */
.xc-hero--none {
    background: none;
    color: rgba(var(--ink), .25);
}

.xc-hero__label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    letter-spacing: .14em;
    color: rgba(var(--ink), .35);
    white-space: nowrap;
}

/* ── quick links ────────────────────────────────────────────────────────
 * A row that goes somewhere: the setup page's help links.
 */
.xc-jump {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 4px;
    text-decoration: none;
    color: var(--text);
    font-size: 14px;
    border-radius: 10px;
    transition: background 140ms, transform 140ms;
}

.xc-jump:hover {
    background: rgba(var(--ink), .04);
    transform: translateX(2px);
}

/* ── the brand gradient, available everywhere ───────────────────────────
 * `--grad`, `--glow` and `--acc` were defined only on .xc-sheet-host, so any
 * component using them outside a modal got `background: var(--grad)` with no
 * value — which silently drops the declaration while `color:#fff` survives.
 * The segmented control on the channels screen came out as white text on a
 * white ground, with the *unchecked* option looking like the selected one.
 *
 * Defined here as the defaults; a sheet still overrides them per accent.
 */
:root {
    --acc: #1C1CD2;
    --grad: linear-gradient(135deg, #1C1CD2, #5B5BF0);
    --glow: rgba(28, 28, 210, .3);
}

/* ── the canvas's panel head ────────────────────────────────────────────
 * Title, then a mono counter or period in the corner, then whatever the panel
 * lets you do. One row, wrapping, on every panel that has all three.
 */
.xc-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.xc-head__title {
    margin: 0;
    flex: 1;
    min-inline-size: 130px;
    font-family: Poppins, sans-serif;
    font-weight: 600;
    font-size: 17px;
    letter-spacing: -0.01em;
}

.xc-meta {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    letter-spacing: .12em;
    color: rgba(var(--ink), .35);
}

/* ── search, and the actions drawer beside it ───────────────────────────
 * A checkbox rather than a <details>: the drawer has to open as a full-width
 * row *below* the search, and a <details> can only ever open inside its own
 * box. The input stays focusable — moved off-screen, never display:none —
 * so the drawer opens from the keyboard.
 */

.xc-find {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-inline-size: 180px;
    background: rgba(var(--ink), .05);
    border: 1px solid transparent;
    border-radius: 12px;
    padding: 9px 12px;
}

.xc-find:focus-within { border-color: var(--peri); }

.xc-find input {
    flex: 1;
    min-inline-size: 0;
    background: transparent;
    border: 0;
    font: inherit;
    font-size: 14px;
    color: var(--text);
    outline: none;
}

/* The line under a panel that says what it does not say. */
.xc-note {
    margin: 0;
    font-size: 13.5px;
    color: rgba(var(--ink), .55);
    line-height: 1.55;
    text-wrap: pretty;
}

/* ── the sheet ──────────────────────────────────────────────────────────
 * The canvas's modal: a gradient icon, a scrolling body of grouped fields,
 * a fixed footer, and — where the form produces a thing — a preview of that
 * thing beside it, on its own tinted ground.
 */
.xc-sheet-host {
    border: 0;
    padding: 0;
    background: transparent;
    inline-size: 100%;
    max-inline-size: min(760px, 94vw);
}

.xc-sheet-host--wide { max-inline-size: min(1010px, 96vw); }

.xc-sheet {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 22px;
    overflow: hidden;
    display: flex;
    max-block-size: 88vh;
    box-shadow: 0 44px 96px rgba(0, 0, 0, .42);
}

.xc-sheet__main {
    flex: 1;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
}

.xc-sheet__head {
    flex: none;
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 19px 22px;
    border-block-end: 1px solid var(--line);
}

.xc-sheet__icon {
    inline-size: 44px;
    block-size: 44px;
    border-radius: 15px;
    background: var(--grad);
    box-shadow: 0 10px 24px var(--glow);
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.xc-sheet__badge {
    flex: none;
    background: rgba(28, 28, 210, .09);
    color: var(--acc);
    border-radius: 20px;
    padding: 5px 12px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    letter-spacing: .14em;
}

.xc-sheet__x {
    appearance: none;
    background: rgba(var(--ink), .05);
    border: 0;
    border-radius: 11px;
    padding: 8px;
    display: flex;
    cursor: pointer;
    color: rgba(var(--ink), .45);
    flex: none;
    transition: background 160ms, color 160ms;
}

.xc-sheet__x:hover { background: rgba(var(--ink), .1); color: var(--text); }

.xc-sheet__body {
    flex: 1;
    min-block-size: 0;
    overflow-y: auto;
    padding: 18px 22px 22px;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.xc-sheet__foot {
    flex: none;
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 14px 22px;
    border-block-start: 1px solid var(--line);
}

.xc-sheet__esc {
    flex: 1;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    letter-spacing: .12em;
    color: rgba(var(--ink), .3);
}

.xc-sheet__prev {
    inline-size: 314px;
    flex: none;
    border-inline-start: 1px solid var(--line);
    background: var(--surface-2);
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 20px;
    overflow-y: auto;
}

.xc-quiet {
    appearance: none;
    background: rgba(var(--ink), .05);
    border: 0;
    border-radius: 12px;
    padding: 11px 17px;
    font: inherit;
    font-size: 14.5px;
    color: rgba(var(--ink), .6);
    cursor: pointer;
    transition: color 160ms;
}

.xc-quiet:hover { color: var(--text); }

/* The quiet one, in the brand colour.

   Grey on grey is the shape a disabled control has, and beside a filled
   button that is exactly how it reads. The brand text says "this does
   something" while the ground stays quiet, which is the whole job of a
   secondary action. */
.xc-quiet--brand {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: rgb(var(--brand));
    font-weight: 500;
}

.xc-quiet--brand:hover {
    background: rgba(var(--brand), .1);
    color: rgb(var(--brand));
}

.xc-primary--lg { padding: 11px 20px; font-size: 14.5px; border-radius: 12px; }

/* One column below the width where the preview would squeeze the form. */
@media (max-width: 880px) {
    .xc-sheet { flex-direction: column; }
    .xc-sheet__prev { inline-size: auto; border-inline-start: 0; border-block-start: 1px solid var(--line); }
}

/* ── fields inside a sheet ──────────────────────────────────────────────
 * A group is a mono heading with a rule running off it; fields sit two to a
 * row, which is the canvas's shape for every form it draws.
 */
.xc-grp {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.xc-grp__head {
    display: flex;
    align-items: center;
    gap: 10px;
}

.xc-grp__title {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    letter-spacing: .16em;
    color: var(--acc);
}

.xc-grp__rule {
    flex: 1;
    block-size: 1px;
    background: var(--line);
}

.xc-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 13px;
}

.xc-f {
    display: flex;
    flex-direction: column;
    gap: 7px;
    min-inline-size: 0;
}

.xc-f--wide { grid-column: 1 / -1; }

/* Readable, not decorative.
 *
 * These were at .38 and the hints at .32, which looked calm on a mockup and
 * turned out to be the reason people fill a form in wrongly: the label is the
 * only thing saying what the box is for, and a label nobody reads is a box
 * everybody guesses at. Small and letter-spaced is still the style; faint is
 * not part of the style. */
.xc-f__label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    letter-spacing: .13em;
    color: rgba(var(--ink), .68);
}

/* As .xc-tag: joined letters, not spaced capitals — and a size Arabic can be
   read at. */
[dir="rtl"] .xc-f__label { font-family: inherit; font-size: 11px; letter-spacing: 0; }

.xc-f__hint {
    font-size: 12.5px;
    color: rgba(var(--ink), .58);
    line-height: 1.45;
}

.xc-f__err {
    font-size: 12.5px;
    color: #b83636;
}

.xc-in {
    inline-size: 100%;
    box-sizing: border-box;
    background: rgba(var(--ink), .05);
    border: 1px solid transparent;
    border-radius: 12px;
    padding: 11px 13px;
    font: inherit;
    font-size: 15px;
    color: var(--text);
    outline: none;
    transition: border-color 160ms;
}

.xc-in:focus { border-color: var(--acc); }

select.xc-in { appearance: none; cursor: pointer; }

/* A segmented control, built from radios so it submits without a line of JS. */
.xc-seg {
    display: flex;
    gap: 6px;
    background: rgba(var(--ink), .05);
    border-radius: 13px;
    padding: 4px;
}

.xc-seg label { flex: 1; cursor: pointer; }

.xc-seg input {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    opacity: 0;
    pointer-events: none;
}

.xc-seg span {
    display: block;
    border-radius: 10px;
    padding: 9px 12px;
    text-align: center;
    font-size: 14px;
    transition: background 180ms, color 180ms;
}

.xc-seg input:checked + span {
    background: var(--grad);
    color: #fff;
    font-weight: 600;
    box-shadow: 0 8px 18px var(--glow);
}

.xc-seg input:focus-visible + span {
    outline: 2px solid var(--peri);
    outline-offset: 2px;
}

/* The canvas's switch. A checkbox, so it submits and reads as one. */
.xc-switch {
    display: flex;
    align-items: center;
    gap: 11px;
    border-radius: 12px;
    padding: 9px 13px;
    background: rgba(var(--ink), .05);
    color: rgba(var(--ink), .55);
    font-size: 14px;
    cursor: pointer;
    transition: background 180ms, color 180ms;
}

.xc-switch input {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    opacity: 0;
    pointer-events: none;
}

.xc-switch__track {
    inline-size: 34px;
    block-size: 18px;
    border-radius: 12px;
    background: rgba(var(--ink), .18);
    flex: none;
    position: relative;
    transition: background 180ms;
}

.xc-switch__track::after {
    content: "";
    position: absolute;
    inset-block-start: 1px;
    inset-inline-start: 1px;
    inline-size: 16px;
    block-size: 16px;
    border-radius: 50%;
    background: #fff;
    transition: inset-inline-start 200ms cubic-bezier(.2, .8, .25, 1);
}

.xc-switch:has(input:checked) { background: rgba(28, 28, 210, .09); color: var(--acc); }
.xc-switch:has(input:checked) .xc-switch__track { background: var(--acc); }
.xc-switch:has(input:checked) .xc-switch__track::after { inset-inline-start: 17px; }
.xc-switch:has(input:focus-visible) { outline: 2px solid var(--peri); outline-offset: 2px; }

/* ── the preview card ───────────────────────────────────────────────────
 * What the form will produce, drawn as the thing itself rather than as a
 * summary of the fields.
 */
.xc-prev__label {
    flex: none;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: .16em;
    color: rgba(var(--ink), .32);
}

.xc-prev__card {
    flex: none;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.xc-prev__top {
    background: var(--grad);
    padding: 17px 18px;
    display: flex;
    align-items: center;
    gap: 11px;
}

.xc-prev__glyph {
    inline-size: 36px;
    block-size: 36px;
    border-radius: 12px;
    background: rgba(255, 255, 255, .2);
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.xc-prev__name {
    color: #fff;
    font-family: Poppins, sans-serif;
    font-weight: 600;
    font-size: 15px;
    unicode-bidi: plaintext;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.xc-prev__in {
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.xc-prev__big {
    font-family: 'JetBrains Mono', monospace;
    font-weight: 500;
    font-size: 30px;
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.xc-prev__lines { display: flex; flex-direction: column; gap: 7px; }

.xc-prev__line { display: flex; align-items: baseline; gap: 10px; }

.xc-prev__line > span:first-child { font-size: 13px; color: rgba(var(--ink), .42); flex: 1; }

.xc-prev__line > span:last-child {
    font-size: 13px;
    font-family: 'JetBrains Mono', monospace;
    text-align: end;
    unicode-bidi: plaintext;
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* ── the composer's paperclip ───────────────────────────────────────────
 * A label wrapping a hidden file input, so it is a real control: focusable,
 * announced as a file chooser, and operable from the keyboard. A div with a
 * click handler is none of those.
 */
.xc-attach {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 40px;
    block-size: 40px;
    flex: none;
    border-radius: 12px;
    color: rgba(var(--ink), .45);
    cursor: pointer;
    transition: background 160ms, color 160ms;
}

.xc-attach:hover { background: rgba(var(--ink), .06); color: var(--text); }

.xc-attach:focus-within {
    outline: 2px solid var(--peri);
    outline-offset: 2px;
}

/* Where the reply box would be, once the 24-hour window has closed: what
   WhatsApp allows now, said in the amber the header's chip wears. */
.xc-inbox-shut {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(232, 163, 61, .09);
    border: 1px solid rgba(232, 163, 61, .3);
    color: var(--amber);
}

.xc-inbox-shut > svg { flex: none; margin-block-start: 2px; }

.xc-inbox-shut > span {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-inline-size: 0;
}

.xc-inbox-shut strong { font-size: 14px; font-weight: 600; color: var(--text); }

.xc-inbox-shut span span {
    font-size: 13px;
    line-height: 1.5;
    color: rgba(var(--ink), .62);
    text-wrap: pretty;
}

/* ── the line that says a click landed ──────────────────────────────────
 *
 * Actions no longer reload the page, which removes the browser's own spinner
 * and with it the only thing that said "something is happening". On a fast
 * connection nobody sees this; on a slow one it is the difference between
 * waiting and clicking twice.
 *
 * Fixed to the top of the viewport rather than the panel: it must be visible
 * wherever the reader has scrolled to, which is the whole point of the change
 * it belongs to.
 */
.xc-busy {
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    block-size: 2px;
    z-index: 999;
    background: var(--grad);
    transform: scaleX(0);
    transform-origin: inline-start;
    opacity: 0;
    pointer-events: none;
}

html[data-busy] .xc-busy {
    /* Creeps toward the end without reaching it: the request decides when it
     * is finished, and a bar that sits full while still loading is a lie. */
    animation: xc-creep 12s cubic-bezier(.1, .8, .2, 1) forwards;
    opacity: 1;
    transition: opacity .15s linear;
}

@keyframes xc-creep {
    0% { transform: scaleX(0); }
    40% { transform: scaleX(.6); }
    100% { transform: scaleX(.92); }
}

@media (prefers-reduced-motion: reduce) {
    html[data-busy] .xc-busy {
        animation: none;
        transform: scaleX(1);
    }
}

/* ── picking a glyph or a colour ────────────────────────────────────────
 *
 * Radios, not buttons. A colour swatch is a choice of one from many, which is
 * exactly what a radio group is — and getting that for free means the keyboard
 * works, the label is read out, and the form submits without a line of script.
 *
 * The input itself is taken out of the flow rather than hidden with
 * `display:none`, which would remove it from the tab order and from the
 * accessibility tree with it.
 */
.xc-pick {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    opacity: 0;
    pointer-events: none;
}

label:has(.xc-pick:checked) {
    outline: 2px solid var(--acc);
    outline-offset: 2px;
}

/* Focus has to be visible on the tile, because the input it belongs to is
 * one pixel wide and invisible. */
label:has(.xc-pick:focus-visible) {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
}

/* ── a panel that can be put away ───────────────────────────────────────
 *
 * <details> carries the behaviour; this only removes the browser's own marker
 * and turns the caret to say which way the panel will move.
 */
.xc-fold > summary::-webkit-details-marker { display: none; }
.xc-fold > summary::marker { content: ''; }

.xc-fold > summary:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: -2px;
    border-radius: 18px;
}

/* ── the wizard ─────────────────────────────────────────────────────────
 *
 * One form, several panels, one visible at a time. The steps are not separate
 * requests: a half-made agent saved across four posts is four chances to end
 * up with a row nobody finished.
 */
.xc-step[hidden] { display: none !important; }

.xc-dots {
    display: flex;
    gap: 7px;
    align-items: center;
}

.xc-dot {
    inline-size: 26px;
    block-size: 4px;
    border-radius: 4px;
    background: rgba(var(--ink), .12);
    transition: background 200ms ease;
}

.xc-dot[data-on] { background: var(--acc); }

/* A part the last save was refused over, until it is put right. */
.xc-dot[data-wrong] { background: rgb(214, 69, 69); }

/* ── the agent thinking ─────────────────────────────────────────────────
 *
 * Shown while a real model is being waited on. Three dots rather than a
 * spinner, because it is a message being written and that is what a person
 * writing a message looks like in every chat app they have ever used.
 */
.xc-think {
    display: inline-flex;
    gap: 4px;
    align-items: center;
}

.xc-think span {
    inline-size: 6px;
    block-size: 6px;
    border-radius: 50%;
    background: rgba(var(--ink), .35);
    animation: xc-think 1.2s infinite ease-in-out;
}

.xc-think span:nth-child(2) { animation-delay: .16s; }
.xc-think span:nth-child(3) { animation-delay: .32s; }

@keyframes xc-think {
    0%, 60%, 100% { transform: translateY(0); opacity: .45; }
    30% { transform: translateY(-4px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .xc-think span { animation: none; }
}

/* ── the mark that means a model is involved ────────────────────────────
 *
 * A sparkle, because every product now uses one for exactly this and a
 * brokerage should not have to learn our private symbol for it. Two stars at
 * different sizes rather than one: a single sparkle reads as decoration, two
 * reading at different rhythms read as something happening.
 *
 * It sits on the agent screens and nowhere else. A mark that appears on every
 * panel stops meaning anything, and the whole point is that it tells you which
 * parts of this product are a model rather than a rule.
 */
.xc-spark {
    display: inline-flex;
    flex: none;
    color: var(--acc);
}

.xc-spark__big,
.xc-spark__sm {
    transform-origin: center;
    animation: xc-spark 3.2s ease-in-out infinite;
}

.xc-spark__sm {
    animation-delay: 1.1s;
    animation-duration: 2.6s;
}

@keyframes xc-spark {
    0%, 70%, 100% { opacity: .85; transform: scale(1); }
    18% { opacity: 1; transform: scale(1.18); }
    34% { opacity: .7; transform: scale(.96); }
}

/* The live agent, breathing. Slow enough to read as "on" rather than as an
 * alert — a card that pulses quickly is a card asking to be clicked. */
.xc-alive {
    position: relative;
}

.xc-alive::after {
    content: '';
    position: absolute;
    inset: -1.5px;
    border-radius: inherit;
    pointer-events: none;
    box-shadow: 0 0 0 0 var(--glow);
    animation: xc-alive 3.6s ease-out infinite;
}

@keyframes xc-alive {
    0% { box-shadow: 0 0 0 0 rgba(28, 28, 210, .28); }
    70% { box-shadow: 0 0 0 10px rgba(28, 28, 210, 0); }
    100% { box-shadow: 0 0 0 0 rgba(28, 28, 210, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .xc-spark__big,
    .xc-spark__sm,
    .xc-alive::after { animation: none; }
}

/* ── the beat between two steps ───────────────────────────────────────────
 *
 * A transition, not a wait: nothing is happening behind this. It covers the
 * panels only, so the dots above keep advancing in plain sight — that is the
 * difference between a pause that reads as progress and one that reads as a
 * stall.
 *
 * Every rule here is decoration. With the stylesheet gone the steps still
 * change, instantly, which is the correct way for an animation to fail.
 */
.xc-stage { position: relative; }

.xc-stage__magic {
    position: absolute;
    inset: -8px;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 16px;
    background:
        radial-gradient(60% 60% at 50% 50%, rgba(91, 91, 240, .10), transparent 70%),
        color-mix(in srgb, var(--surface) 72%, transparent);
    backdrop-filter: blur(2.5px);
    -webkit-backdrop-filter: blur(2.5px);
    animation: xc-stage-in .16s ease-out;
}

@keyframes xc-stage-in {
    from { opacity: 0; }
}

.xc-stage__spark {
    color: var(--acc);
    animation: xc-stage-spark .38s cubic-bezier(.3, .8, .3, 1);
}

.xc-stage__spark svg { display: block; }

/* Out and back: the sparkle arrives small, swells as the panel behind it is
   swapped, and is gone before it can be looked at directly. */
@keyframes xc-stage-spark {
    0% { transform: scale(.5) rotate(-24deg); opacity: 0; }
    45% { transform: scale(1.18) rotate(6deg); opacity: 1; }
    100% { transform: scale(.94) rotate(0); opacity: .5; }
}

/* The panel that just arrived, rising into place. Short, and under the veil
   for the first half of it, so it is felt more than watched. */
.xc-step--came { animation: xc-step-came .34s cubic-bezier(.2, .75, .3, 1); }

@keyframes xc-step-came {
    from { opacity: 0; transform: translateY(9px) scale(.99); }
}

@media (prefers-reduced-motion: reduce) {
    .xc-stage__magic,
    .xc-stage__spark,
    .xc-step--came { animation: none; }
}

/* ── the knowledge panel, and the parts of the form ───────────────────────
 *
 * Everything below is decoration. With the stylesheet gone the panel is a
 * list and the form is a form, which is the correct way for decoration to
 * fail.
 */

/* The label above an answer. Monospaced and small, so six of them down a
   panel read as a form rather than as six headings. */
.xc-tag {
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(var(--ink), .62);
    font-family: 'JetBrains Mono', ui-monospace, monospace;
}

/* Spaced capitals in a monospaced face pull Arabic's joined letters apart,
   and the face has no Arabic of its own: an Arabic label takes the page's. */
[dir="rtl"] .xc-tag { font-family: inherit; letter-spacing: 0; }

/* One call a connector may make. */
.xc-tool {
    font-size: 10.5px;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    color: rgba(var(--ink), .55);
    background: rgba(var(--ink), .05);
    border-radius: 6px;
    padding: 2px 7px;
    overflow-wrap: anywhere;
}

/* The empty state, which is the state this screen is really about. The glow
   behind the sparkle breathes; nothing else on the panel moves, so it is the
   one thing the eye is taken to. */
.xc-invite {
    border: 1px dashed var(--line);
    border-radius: 16px;
    padding: 26px 22px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    text-align: center;
    background: radial-gradient(70% 90% at 50% 0%, rgba(91, 91, 240, .06), transparent 70%);
}

/* An example, not an answer. Distinct from typed text and still readable —
   the forms on this product lean on worked examples to explain themselves,
   and an example nobody can read explains nothing. */
.xc-in::placeholder {
    color: rgba(var(--ink), .42);
    opacity: 1;
}

/* What was typed, at full strength. A field somebody has filled in is the
   most important text on a form and was inheriting the body colour. */
.xc-in {
    color: rgba(var(--ink), .92);
}

/* ── choosing a document ──────────────────────────────────────────────────
 *
 * The browser's own file input is a grey button and the words "no file
 * chosen", which on a panel about the documents an agent will quote reads as
 * an afterthought. The input is still underneath all of this — invisible,
 * covering the whole zone — so clicking and tabbing to it work with the
 * script and the stylesheet both gone.
 */
.xc-drop {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    padding: 26px 20px;
    border: 1.5px dashed var(--line);
    border-radius: 16px;
    background: radial-gradient(80% 100% at 50% 0%, rgba(61, 140, 232, .05), transparent 70%);
    text-align: center;
    cursor: pointer;
    transition: border-color .15s, background-color .15s;
}

.xc-drop:hover,
.xc-drop:focus-within { border-color: rgba(61, 140, 232, .55); }

/* While something is being dragged over it. */
.xc-drop[data-over] {
    border-color: rgb(61, 140, 232);
    border-style: solid;
    background: rgba(61, 140, 232, .07);
}

/* The real control. Invisible, not absent: `display:none` would take it off
   the keyboard and out of the click. */
.xc-drop__input {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    opacity: 0;
    cursor: pointer;
}

.xc-drop__icon {
    inline-size: 46px;
    block-size: 46px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(61, 140, 232, .12);
    color: rgb(61, 140, 232);
}

.xc-drop__say {
    font-size: 14px;
    font-weight: 600;
    color: rgba(var(--ink), .78);
}

.xc-drop__types {
    font-size: 12px;
    color: rgba(var(--ink), .5);
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    letter-spacing: .01em;
    text-wrap: pretty;
}

/* One chosen file, before it has been saved. */
.xc-file {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 11px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--surface);
}

.xc-file[data-bad] {
    border-color: rgba(184, 54, 54, .4);
    background: rgba(184, 54, 54, .04);
}

.xc-file__thumb {
    inline-size: 38px;
    block-size: 38px;
    border-radius: 9px;
    flex: none;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--ink), .06);
}

.xc-file__thumb img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

/* A picture shows itself; everything else shows what it is. */
.xc-file__thumb[data-ext] {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 9.5px;
    letter-spacing: .05em;
    color: rgba(var(--ink), .55);
}

.xc-file__said {
    flex: 1;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.xc-file__name {
    font-size: 13.5px;
    font-weight: 600;
    color: rgba(var(--ink), .88);
    overflow-wrap: anywhere;
}

.xc-file__meta {
    font-size: 11.5px;
    color: rgba(var(--ink), .5);
    font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.xc-file[data-bad] .xc-file__meta { color: #b83636; }

.xc-file__out {
    inline-size: 28px;
    block-size: 28px;
    border-radius: 9px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: rgba(var(--ink), .55);
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    cursor: pointer;
}

.xc-file__out:hover {
    border-color: rgba(184, 54, 54, .4);
    color: #b83636;
}

@media (prefers-reduced-motion: reduce) {
    .xc-drop { transition: none; }
}

/* A small count on a card: "installed twice". */
.xc-pill {
    font-size: 10.5px;
    letter-spacing: .04em;
    text-transform: uppercase;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    color: rgba(var(--ink), .6);
    background: rgba(var(--ink), .07);
    border-radius: 20px;
    padding: 3px 9px;
    flex: none;
    white-space: nowrap;
}

/* ── a numbered rule, and a list of words ─────────────────────────────────*/

/* One word in a list of them. */
.xc-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 6px 4px 11px;
    border-radius: 20px;
    background: rgba(91, 91, 240, .1);
    color: rgba(var(--ink), .82);
    font-size: 13px;
    unicode-bidi: plaintext;
}

.xc-chip button {
    inline-size: 18px;
    block-size: 18px;
    border-radius: 50%;
    border: 0;
    background: rgba(var(--ink), .08);
    color: rgba(var(--ink), .55);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex: none;
}

.xc-chip button:hover {
    background: rgba(184, 54, 54, .14);
    color: #b83636;
}

/* ── one of two ways of working ───────────────────────────────────────────
 *
 * A card you press, wrapping the radio that actually carries the answer. The
 * radio keeps `.xc-pick`, which is what makes it one invisible pixel and lets
 * `label:has(.xc-pick:checked)` draw the chosen state — so this is only the
 * box around it.
 */
.xc-choice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 13px 15px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface);
    cursor: pointer;
    position: relative;
    transition: border-color .15s, background-color .15s;
}

.xc-choice:hover { border-color: rgba(var(--ink), .22); }

label.xc-choice:has(.xc-pick:checked) {
    border-color: var(--acc);
    background: rgba(91, 91, 240, .05);
    /* The generic rule draws an outline; on a card a border reads better, so
       the outline is taken back off just here. */
    outline: none;
}

@media (prefers-reduced-motion: reduce) {
    .xc-choice { transition: none; }
}

/* ── a capital letter at the front ────────────────────────────────────────
 *
 * Every heading and button in this product is written in sentence case with a
 * lowercase first letter — a deliberate style that reads as casual on a chat
 * tool and as unfinished on a business one, which is the half somebody
 * noticed.
 *
 * Done in CSS with ::first-letter rather than by rewriting several hundred
 * strings in two languages. `text-transform: capitalize` was the obvious
 * alternative and is wrong: it would produce "Who A Lead Goes To", which is
 * not title case in English and is nonsense in Arabic.
 *
 * Arabic has no letter case, so this is a no-op there rather than something
 * that has to be switched off.
 *
 * ── The three that used to be in this list ───────────────────────────────
 *
 * `.xc-primary`, `.xc-act` and `.xc-abtn` were here and never did anything.
 * All three are `display: inline-flex`, and ::first-letter applies to block
 * containers only — and a flex container puts a bare text node in an
 * anonymous box, so there is not even a child left to name.
 *
 * So the product kept a stylesheet that said it capitalised every button and
 * a screen full of buttons reading "check eligibility" and "rotate secret".
 * Those labels are capitalised where they are written instead: see
 * LABEL_PATHS in scripts/genlang.py.
 *
 * What is left here is the block ones, where the selector reaches.
 */
.xc-head__title::first-letter,
.xc-quiet::first-letter,
.xc-fold > summary .xc-cap::first-letter {
    text-transform: uppercase;
}

/* The picture at the top of a template card. A fixed height so a shelf of
   cards has one horizon rather than three, and a dotted ground borrowed from
   the canvas so it reads as a diagram rather than as a photograph. */
.xc-art {
    display: block;
    block-size: 112px;
    flex: none;
    background:
        radial-gradient(rgba(var(--ink), .09) 1px, transparent 1px) 0 0 / 11px 11px,
        linear-gradient(160deg, rgba(var(--tint), .07), rgba(var(--tint), .02));
    border-block-end: 1px solid var(--line);
}

.xc-art svg {
    inline-size: 100%;
    block-size: 100%;
    display: block;
}

/* Testing is neither a save nor a publish, so it is neither grey nor brand. */
.xc-act--go {
    color: var(--green);
    border-color: rgba(0, 168, 134, .35);
    background: rgba(0, 168, 134, .08);
}

.xc-act--go:hover { background: rgba(0, 168, 134, .15); }

/* One repeatable row: an option, a rule, a header. */
.xc-row {
    display: flex;
    gap: 7px;
    align-items: center;
    flex-wrap: wrap;
}

.xc-row .xc-in { flex: 1; min-inline-size: 110px; }

/* A read-only summary: label on the left, fact on the right. */
.xc-facts {
    margin: 0;
    display: grid;
    grid-template-columns: minmax(120px, auto) 1fr;
    gap: 8px 16px;
    align-items: baseline;
}

.xc-facts dt {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 10px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: rgba(var(--ink), .5);
}

.xc-facts dd {
    margin: 0;
    font-size: 13.5px;
    color: rgba(var(--ink), .85);
    text-wrap: pretty;
    unicode-bidi: plaintext;
}

/* A share of something, as a bar. Wide enough to compare at a glance and
   short enough that the number beside it stays the thing being read. */
.xc-meter {
    flex: 1;
    min-inline-size: 60px;
    block-size: 8px;
    border-radius: 6px;
    background: rgba(var(--ink), .07);
    overflow: hidden;
}

.xc-meter__fill {
    display: block;
    block-size: 100%;
    border-radius: 6px;
}

/* ── rows arriving ────────────────────────────────────────────────────────
 *
 * A short stagger on a list that has just been drawn. Decoration, and it fails
 * correctly: with the stylesheet gone the rows are simply there.
 *
 * `--i` is the row's index, set inline, and the delay is capped by the small
 * multiplier — a workspace of forty people must not have its last row arrive
 * two seconds after its first. Past about eight rows the difference stops
 * being perceptible anyway, which is why this is 26ms and not 80.
 */
.xc-row--in {
    animation: xc-row-in .34s cubic-bezier(.2, .75, .3, 1) backwards;
    animation-delay: calc(var(--i, 0) * 26ms);
}

@keyframes xc-row-in {
    from { opacity: 0; transform: translateY(7px); }
}

/* A row that can be acted on lifts very slightly under the cursor. Enough to
   say "this is a thing", not enough to move the text somebody is reading. */
.xc-rows > .xc-row {
    transition: border-color 160ms, transform 160ms, box-shadow 160ms;
}

.xc-rows > .xc-row:hover {
    border-color: rgba(var(--ink), .18);
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(var(--ink), .05);
}

@media (prefers-reduced-motion: reduce) {
    .xc-row--in { animation: none; }
    .xc-rows > .xc-row:hover { transform: none; }
}

/* A team card's banner. Short, because a team card carries a queue count and
   a row of names under it and would otherwise be mostly picture. */
.xc-art--team {
    block-size: 72px;
    border-block-end: 0;
    border-end-start-radius: 0;
    border-end-end-radius: 0;
}

/* ── the getting-started checklist ────────────────────────────────────────
 *
 * Built on <details>, like every other fold in this product: the browser
 * already knows how to open one, reach it with a keyboard, and find text
 * inside a closed one. Without the stylesheet each step is an open disclosure
 * with a heading, which is the right way for decoration to fail.
 */
.xc-task {
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface-2);
    overflow: hidden;
    transition: border-color 160ms, background 160ms;
}

.xc-task[open] {
    border-color: rgba(var(--tint), .35);
    background: rgba(var(--tint), .045);
}

.xc-task__head {
    list-style: none;
    cursor: pointer;
    padding: 13px 15px;
    display: flex;
    align-items: center;
    gap: 12px;
}

.xc-task__head::-webkit-details-marker { display: none; }

/* The number, and then the tick. Never a control — nothing here can be
   clicked to pretend a step is finished. */
/* A ring with a tick in it, grey until the step is done and green after.
   The same shape either way on purpose: a checklist whose marks change shape
   as they complete is a checklist that moves under the reader. */
.xc-task__mark {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(var(--ink), .28);
}

.xc-task__mark[data-done] {
    color: var(--green);
    animation: xc-ticked .4s cubic-bezier(.2, .8, .3, 1);
}

@keyframes xc-ticked {
    0% { transform: scale(.4); opacity: 0; }
    60% { transform: scale(1.12); }
}

.xc-task__caret {
    flex: none;
    color: rgba(var(--ink), .35);
    transition: transform 180ms;
}

.xc-task[open] .xc-task__caret { transform: rotate(180deg); }

.xc-task__body {
    padding: 0 15px 16px 56px;
    display: flex;
    gap: 18px;
    align-items: flex-start;
    flex-wrap: wrap;
}

/* The bar filling in. Animated from nothing on first paint, so a workspace
   that has just finished a step sees it move rather than finding it moved. */
.xc-meter__fill--grow { animation: xc-grow .6s cubic-bezier(.2, .8, .3, 1); }

@keyframes xc-grow {
    from { inline-size: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .xc-task__mark[data-done],
    .xc-meter__fill--grow { animation: none; }
    .xc-task__caret { transition: none; }
}

/* On a phone the body loses the indent: 53px of empty gutter on a 360px
   screen is a third of the line length spent on alignment. */
@media (max-width: 720px) {
    /* 56px of empty gutter on a 360px screen is a sixth of the line length
       spent on alignment. */
    .xc-task__body { padding-inline-start: 15px; }
}

/* ── "connect whatsapp to go live" ────────────────────────────────────────
 *
 * One line high, on every screen, until there is a number. Deliberately slim:
 * something permanent that takes a fifth of the screen is something people
 * learn to look past, and something that takes 38px is something they
 * eventually click.
 *
 * Never WhatsApp green. The band is amber when it is asking and grey-blue
 * while it waits, because green here would read as "connected".
 */
/* A plain checkbox, sized up and tinted.

   Native rather than a drawn one: it keeps the keyboard behaviour, the
   indeterminate state, the platform's own focus ring and the screen-reader
   role, all of which a <span> pretending to be a checkbox has to reimplement
   and usually reimplements incompletely. `accent-color` is the whole styling
   budget this needs. */
.xc-check {
    inline-size: 17px;
    block-size: 17px;
    flex: none;
    accent-color: rgb(var(--brand));
    cursor: pointer;
}

/* ── saying something went wrong, so it is seen ────────────────────────── */

/* The small one, for a field. */
.xc-alarm {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin: 0;
    padding: 10px 13px;
    border-radius: 12px;
    font-size: 13px;
    line-height: 1.5;
    background: rgba(214, 69, 69, .09);
    color: #B83636;
}

/* The loud one, for a thing that stops the flow.

   The version this replaced was a line of small orange text in a summary
   column — the one place somebody who has just pressed a button is not
   looking. An error nobody sees is pressed past twice and reported as "it
   does nothing". */
.xc-alarm--big {
    gap: 11px;
    padding: 14px 16px;
    border: 1px solid rgba(214, 69, 69, .35);
    border-radius: 14px;
    background: rgba(214, 69, 69, .1);
    font-size: 14px;
    font-weight: 500;
}

/* ── the review's four totals ──────────────────────────────────────────── */

.xc-tally {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
}

.xc-tally__one {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 12px 14px;
    border-radius: 13px;
    background: rgba(var(--ink), .03);
}

/* Colour only where there is something to count. Four tinted cards, three of
   them zero, is four things claiming to be news. */
.xc-tally__one[data-any] { background: rgba(var(--tint), .1); }

.xc-tally__n {
    font-family: 'JetBrains Mono', monospace;
    font-size: 22px;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    color: rgba(var(--ink), .25);
}

.xc-tally__one[data-any] .xc-tally__n { color: rgb(var(--tint)); }

.xc-tally__say {
    font-size: 12.2px;
    color: rgba(var(--ink), .45);
}

@media (max-width: 820px) {
    .xc-tally { grid-template-columns: repeat(2, 1fr); }
}

/* ── settings ──────────────────────────────────────────────────────────── */

/* A card pointing at another screen. */
.xc-place {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 16px 17px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: var(--surface);
    text-decoration: none;
    color: inherit;
    transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}

.xc-place:hover {
    border-color: rgba(var(--tint), .5);
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(var(--scrim), .08);
    color: inherit;
}

.xc-place:hover .xc-place__go { transform: translateX(3px); color: rgb(var(--tint)); }

.xc-place__mark {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 38px;
    block-size: 38px;
    flex: none;
    border-radius: 13px;
    background: rgba(var(--tint), .12);
    color: rgb(var(--tint));
}

.xc-place__on {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    letter-spacing: .1em;
    padding: 2px 7px;
    border-radius: 20px;
    background: rgba(0, 168, 134, .14);
    color: #0F7D64;
}

.xc-place__go {
    flex: none;
    color: rgba(var(--ink), .25);
    transition: transform .16s ease, color .16s ease;
}

/* Plain facts, two columns, monospace where the value is an identifier
   somebody may have to read out or paste. */
.xc-facts {
    margin: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 26px;
}

.xc-facts__one {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-inline-size: 0;
}

.xc-facts__one dt {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: .13em;
    color: rgba(var(--ink), .38);
}

.xc-facts__one dd {
    margin: 0;
    font-size: 14px;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
}

.xc-facts__mono {
    font-family: 'JetBrains Mono', monospace;
    font-size: 12.6px !important;
    color: var(--peri) !important;
    user-select: all;
}

/* Each panel a beat after the one above it. Sixty milliseconds apart — enough
   that the eye follows the page down rather than being handed all of it at
   once, and short enough that nobody waiting on a setting notices they
   waited. Six is the ceiling; past that the last card is late. */
[data-stagger] > * { animation: xc-riseup .32s cubic-bezier(.22, .68, .3, 1) both; }
[data-stagger] > *:nth-child(2) { animation-delay: .06s; }
[data-stagger] > *:nth-child(3) { animation-delay: .12s; }
[data-stagger] > *:nth-child(4) { animation-delay: .18s; }
[data-stagger] > *:nth-child(n+5) { animation-delay: .24s; }

@keyframes xc-riseup {
    from { opacity: 0; transform: translateY(9px); }
    to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    /* The whole point of it was movement, so there is nothing left to keep. */
    [data-stagger] > * { animation: none; }
    .xc-place:hover { transform: none; }
}

@media (max-width: 820px) {
    .xc-facts { grid-template-columns: minmax(0, 1fr); }
}

/* ── a screen with questions down the side ─────────────────────────────── */

/* Used by reports, and by settings. A rail of its own rather than tabs across
   the top: seven tabs wrap on a laptop, and a wrapped tab strip is a menu
   pretending not to be one. */
.xc-subnav {
    inline-size: 214px;
    flex: none;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 8px;
    border: 1px solid var(--line);
    border-radius: 18px;
    background: var(--surface);
}

.xc-subnav__one {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 11px;
    border-radius: 12px;
    font-size: 13.8px;
    text-decoration: none;
    color: rgba(var(--ink), .58);
    transition: background .15s ease, color .15s ease;
}

.xc-subnav__one:hover {
    background: rgba(var(--ink), .04);
    color: var(--text);
}

/* The chosen one wears its own accent rather than the brand: on a screen
   whose whole job is telling seven answers apart, the colour is doing work. */
.xc-subnav__one[data-on] {
    background: rgba(var(--tint), .1);
    color: rgb(var(--tint));
    font-weight: 600;
}

.xc-subnav__mark {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 28px;
    block-size: 28px;
    flex: none;
    border-radius: 9px;
    background: rgba(var(--ink), .05);
    color: rgba(var(--ink), .45);
    transition: background .15s ease, color .15s ease;
}

.xc-subnav__one[data-on] .xc-subnav__mark {
    background: rgba(var(--tint), .16);
    color: rgb(var(--tint));
}

/* Its header: the question, what it means, and the controls that change it. */
.xc-rephead {
    display: flex;
    align-items: center;
    gap: 13px;
    flex-wrap: wrap;
    padding: 16px 20px;
}

.xc-rephead__mark {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 38px;
    block-size: 38px;
    flex: none;
    border-radius: 13px;
    background: rgba(var(--tint), .13);
    color: rgb(var(--tint));
}

@media (max-width: 900px) {
    /* The rail lies down above the content rather than squeezing beside it. */
    .xc-subnav {
        inline-size: auto;
        flex-direction: row;
        overflow-x: auto;
        gap: 6px;
    }

    .xc-subnav__one { flex: none; }
    .xc-subnav__mark { display: none; }
}

/* ── the contacts list ─────────────────────────────────────────────────── */

/* A grid, not a <table>. Five tracks, and the two carrying a person's own
   words — their name and their tags — get the room. */
.xc-rows {
    display: flex;
    flex-direction: column;
}

.xc-rows__head,
.xc-rows__one {
    display: grid;
    grid-template-columns: 38px minmax(0, 1.4fr) 170px minmax(0, 1fr) 130px 76px;
    align-items: center;
    gap: 14px;
    padding: 11px 2px;
}

.xc-rows__head {
    padding-block: 6px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: .13em;
    color: rgba(var(--ink), .35);
    border-block-end: 1px solid var(--line);
}

.xc-rows__one { border-block-end: 1px solid var(--line); }

.xc-rows__one:last-of-type { border-block-end: 0; }

.xc-rows__one:hover { background: rgba(var(--ink), .018); }

/* The one destructive control on the screen, and it stays quiet until it is
   reached. Red on hover rather than red always: a row of red buttons reads as
   a list of problems. */
.xc-rows__act {
    appearance: none;
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 30px;
    block-size: 30px;
    border: 1px solid var(--line);
    border-radius: 9px;
    background: transparent;
    color: rgba(var(--ink), .38);
    cursor: pointer;
    transition: color .14s ease, border-color .14s ease, background .14s ease;
}

.xc-rows__act:hover {
    color: rgb(var(--brand));
    border-color: rgba(var(--brand), .4);
    background: rgba(var(--brand), .07);
}

/* The destructive one, and only on hover. A row of red buttons reads as a
   list of problems; red at the moment of reaching for it is a warning. */
.xc-rows__act--bad:hover {
    color: #B83636;
    border-color: rgba(214, 69, 69, .4);
    background: rgba(214, 69, 69, .07);
}

/* A contact's own tag.

   `xc-ctag`, because `xc-tag` and `xc-chip` were both taken — by the quiet uppercase label above,
   which this flattened when it borrowed the name. A filled pill with padding,
   dropped into a flex column, stretches to the full width of its card: on a
   shelf of cards that was a grey bar across every card where a small word had
   been. */
.xc-ctag {
    font-size: 11.6px;
    padding: 2px 9px;
    border-radius: 999px;
    background: rgba(var(--brand), .08);
    color: rgb(var(--brand));
    white-space: nowrap;
    /* So it never stretches, wherever it is dropped. */
    align-self: flex-start;
}

.xc-ctag[data-more] {
    background: rgba(var(--ink), .05);
    color: rgba(var(--ink), .45);
}

/* Filter pills. Buttons rather than links: the typed search travels with the
   choice, and a link carries nothing. */
.xc-pills {
    display: flex;
    gap: 5px;
    flex: none;
    padding: 3px;
    border-radius: 999px;
    background: rgba(var(--ink), .045);
}

.xc-pills__one {
    appearance: none;
    border: 0;
    padding: 6px 14px;
    border-radius: 999px;
    background: transparent;
    font-size: 12.8px;
    color: rgba(var(--ink), .5);
    cursor: pointer;
    white-space: nowrap;
    transition: background .14s ease, color .14s ease;
}

.xc-pills__one:hover { color: var(--text); }

.xc-pills__one[data-on] {
    background: rgb(var(--brand));
    color: #FFFFFF;
    font-weight: 500;
}

/* ── the import's first step ───────────────────────────────────────────── */

/* A label wrapping a hidden input, so the whole box is the control — no
   JavaScript holding it together. drop.js adds dragging on top. */
.xc-drop {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 30px 20px;
    border: 1.5px dashed rgba(var(--brand), .35);
    border-radius: 16px;
    background: rgba(var(--brand), .025);
    color: rgb(var(--brand));
    cursor: pointer;
    text-align: center;
    transition: background .14s ease, border-color .14s ease;
}

.xc-drop:hover,
.xc-drop[data-over] {
    background: rgba(var(--brand), .06);
    border-color: rgba(var(--brand), .55);
}

/* Off-screen rather than `display:none`, which would take it out of the tab
   order and out of the accessibility tree — a file input nobody can reach by
   keyboard is a form nobody can fill in by keyboard. */
.xc-drop__input {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    opacity: 0;
    pointer-events: none;
}

.xc-drop__input:focus-visible + svg { outline: 2px solid rgb(var(--brand)); outline-offset: 4px; border-radius: 4px; }

.xc-drop__say {
    font-family: Poppins, sans-serif;
    font-weight: 600;
    font-size: 15px;
    color: var(--text);
}

.xc-drop__sub {
    font-size: 12.6px;
    line-height: 1.5;
    color: rgba(var(--ink), .45);
    max-inline-size: 42ch;
    text-wrap: pretty;
}

.xc-drop__file {
    margin-block-start: 6px;
    padding: 4px 12px;
    border-radius: 999px;
    background: rgb(var(--brand));
    color: #FFFFFF;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11.6px;
    max-inline-size: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* "or paste it", as a rule with words in the middle. */
.xc-or {
    display: flex;
    align-items: center;
    gap: 12px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: .14em;
    color: rgba(var(--ink), .3);
}

.xc-or::before,
.xc-or::after {
    content: '';
    flex: 1;
    block-size: 1px;
    background: var(--line);
}

@media (max-width: 1000px) {
    /* Tags go first: they are the only column somebody can reconstruct from
       the contact itself. */
    .xc-rows__head,
    .xc-rows__one { grid-template-columns: 34px minmax(0, 1.4fr) 150px 120px 76px; }
    /* Tags go first: they are the only column somebody can reconstruct from
       the contact itself. One later than before, because of the tick. */
    .xc-rows__head > span:nth-child(4),
    .xc-rows__one > span:nth-child(4) { display: none; }
}

/* ── the CSV import: steps, and the column table ───────────────────────── */

/* Three pills. Not links — each step is a POST carrying the file and the
   choices so far, and a link can carry neither. */
.xc-steps {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.xc-steps__one {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 13px 6px 7px;
    border-radius: 999px;
    font-size: 13.2px;
    font-weight: 500;
    background: rgba(var(--ink), .045);
    color: rgba(var(--ink), .45);
}

.xc-steps__one[data-state="now"] {
    background: rgb(var(--brand));
    color: #FFFFFF;
}

.xc-steps__one[data-state="done"] {
    background: rgba(0, 168, 134, .12);
    color: #0F7D64;
}

.xc-steps__n {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 21px;
    block-size: 21px;
    flex: none;
    border-radius: 50%;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    background: rgba(var(--ink), .07);
    color: rgba(var(--ink), .5);
}

.xc-steps__one[data-state="now"] .xc-steps__n {
    background: rgba(255, 255, 255, .22);
    color: #FFFFFF;
}

.xc-steps__one[data-state="done"] .xc-steps__n {
    background: rgba(0, 168, 134, .2);
    color: #0F7D64;
}

/* The filter. Revealed by mapcols.js — without it the rows are all there
   anyway, and a search box that searches nothing is furniture. */
.xc-mapsearch {
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
    inline-size: 250px;
    padding: 8px 12px;
    border: 1px solid var(--line);
    border-radius: 11px;
    background: var(--surface-2);
    color: rgba(var(--ink), .4);
}

.xc-mapsearch input {
    flex: 1;
    min-inline-size: 0;
    appearance: none;
    border: 0;
    outline: none;
    background: transparent;
    font-size: 13.4px;
    color: var(--text);
}

/* ── the table ─────────────────────────────────────────────────────────
   A grid rather than a <table>: the row is a <label>, so a click anywhere on
   it that is not the select toggles the column. Five tracks, and the two that
   hold a person's own words get the room. */
.xc-maptable {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line);
    border-radius: 14px;
    overflow: hidden;
    /* Inside a sheet the table is the tall part, so it scrolls rather than the
       whole body — the header row stays put and the footer button never walks
       off the bottom of a twenty-eight column file. */
    max-block-size: min(46vh, 420px);
    overflow-y: auto;
}

.xc-maprow--head {
    position: sticky;
    inset-block-start: 0;
    z-index: 2;
    /* Opaque, or the rows scroll through it. */
    background: var(--surface-2);
}

.xc-maprow {
    display: grid;
    grid-template-columns: 44px minmax(0, 1.1fr) minmax(0, 1fr) 24px 250px;
    align-items: center;
    gap: 12px;
    padding: 9px 14px 9px 4px;
    border-block-start: 1px solid var(--line);
    cursor: pointer;
    transition: background .14s ease, opacity .14s ease;
}

.xc-maprow:first-of-type { border-block-start: 0; }

.xc-maprow:hover { background: rgba(var(--ink), .022); }

.xc-maprow--head {
    cursor: default;
    padding-block: 10px;
    background: rgba(var(--ink), .035);
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: .13em;
    color: rgba(var(--ink), .42);
}

.xc-maprow--head:hover { background: rgba(var(--ink), .035); }

/* Dimmed, not hidden: a column somebody chose to leave out should still be
   visible as a column they chose to leave out. */
.xc-maprow[data-off] { opacity: .42; }

.xc-maprow__tick {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The value, first, because it is what a person recognises — `amm_numero`
   means nothing and `AMM-001` means everything. */
.xc-maprow__sample {
    font-size: 13.6px;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.xc-maprow__name {
    font-family: 'JetBrains Mono', monospace;
    font-size: 12.4px;
    color: rgba(var(--ink), .5);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.xc-maprow__arrow { color: rgba(var(--ink), .22); }

.xc-maprow__none {
    margin: 0;
    padding: 18px 14px;
    font-size: 13.2px;
    color: rgba(var(--ink), .42);
    border-block-start: 1px solid var(--line);
}

.xc-mapfield {
    appearance: none;
    inline-size: 100%;
    padding: 8px 11px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--surface-2);
    font-size: 13.2px;
    color: var(--text);
    cursor: pointer;
}

.xc-mapfield:disabled { cursor: not-allowed; }

/* Green once an identifier has been chosen, muted until then. It is a
   statement of the rule either way — never an error, because arriving on this
   screen with nothing chosen is the normal case, not a mistake. */
.xc-mapfoot__note {
    font-size: 12.6px;
    color: rgba(var(--ink), .45);
    text-wrap: pretty;
}

.xc-mapfoot__note[data-ok="1"] { color: var(--green); }

/* ── the read-back on the review step ──────────────────────────────── */
.xc-mapread {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.xc-mapread__one {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 5px 11px;
    border: 1px solid var(--line);
    border-radius: 999px;
    font-size: 12.6px;
    color: rgba(var(--ink), .3);
    max-inline-size: 100%;
}

.xc-mapread__from {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11.6px;
    color: rgba(var(--ink), .5);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.xc-mapread__to { color: var(--text); font-weight: 500; }

.xc-mapread__one[data-custom] .xc-mapread__to { color: var(--peri); }

@media (max-width: 1000px) {
    /* The header column goes before the sample does: on a narrow screen the
       value is still the half that identifies the column. */
    .xc-maprow { grid-template-columns: 40px minmax(0, 1fr) 0 0 190px; }
    .xc-maprow__name,
    .xc-maprow__arrow { display: none; }
    .xc-maprow--head > span:nth-child(3),
    .xc-maprow--head > span:nth-child(4) { display: none; }
}

/* Getting started, on the rail.

   Above the groups and outside them, because it is the only rail entry that
   disappears: after the first week there is nothing to link to. It is given
   the brand colour rather than the rail's usual muted ink — for that week it
   is the item that matters, and a nav item that looks like all the others is
   one nobody picks out. */
.xc-railsetup {
    /* Never shrinks. It sits in the rail's scrolling column with its overflow
       hidden, which takes away a flex item's floor: on a screen shorter than
       the menu it was the one entry squeezed, down to 18px of a 38px pill. */
    flex: none;
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 10px;
    border-radius: 12px;
    text-decoration: none;
    font-size: 15px;
    color: var(--rail-text);
    background: rgba(var(--rail-ink), .06);
    border: 1px solid rgba(var(--rail-ink), .12);
    transition: background 160ms, border-color 160ms;
}

.xc-railsetup:hover,
.xc-railsetup[data-on] {
    color: var(--rail-text);
    background: var(--rail-active);
    border-color: transparent;
}

.xc-railsetup[data-on] { font-weight: 600; }

.xc-railsetup svg { color: var(--peri); }

/* The count. Monospace so 1/4 and 4/4 are the same width and the label beside
   them does not shift as somebody works through the list. */
.xc-railsetup__count {
    flex: none;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: rgba(var(--rail-ink), .5);
}

/* A small pulsing dot, wherever something is in flight. It was part of the
   go-live band; the band became a card and the dot outlived it. */
.xc-pulsedot {
    flex: none;
    inline-size: 7px;
    block-size: 7px;
    border-radius: 50%;
    background: currentColor;
    animation: xc-pulse 2.4s ease-in-out infinite;
}

@keyframes xc-pulse {
    50% { opacity: .35; }
}

@media (prefers-reduced-motion: reduce) {
    .xc-pulsedot { animation: none; }
}

.xc-alert {
    flex: none;
    position: relative;
    overflow: hidden;
    display: flex;
    /* Centred, because there is one row now. It was `flex-start` when the
       button sat under the sentence and the mark had to line up with the
       first line rather than the middle. */
    align-items: center;
    gap: 12px;
    /* Inside the panel, under the title. The inline margin matches the
       padding every screen's content uses, so the card and the content below
       it share an edge.

       The top margin arrived with the header band: with the header a pale
       strip the alert could sit flush against it and read as part of the
       page, and against the night it read as stuck to the underside of it. */
    margin: 12px 16px;
    padding: 11px 14px;
    border: 1px solid var(--line);
    border-radius: 14px;
    /* A faint wash rather than the panel colour. On a page whose own panels
       are white, a white card on a white ground is a card nobody can see —
       and this one is supposed to be noticed. */
    background: rgba(var(--ink), .028);
    color: rgba(var(--ink), .85);
}

/* Amber while it is asking, grey-blue while it waits. Never WhatsApp green:
   green here reads as "connected", which is the one thing it is not. */
/* Red only when something was refused and waiting will not fix it. */
.xc-alert[data-tone="fault"] {
    border-color: rgba(214, 69, 69, .3);
    background: linear-gradient(103deg, rgba(214, 69, 69, .08), rgba(214, 69, 69, .02) 62%, transparent);
}

.xc-alert[data-tone="fault"] .xc-alert__mark { color: rgb(214, 69, 69); }

/* Its own name: `.xc-alert__go` is the go-live card's button, and a link
   style under that name once stripped "Connect number" down to its glow. */

.xc-alert[data-tone="ask"] {
    border-color: rgba(232, 163, 61, .3);
    background: linear-gradient(103deg, rgba(232, 163, 61, .08), rgba(232, 163, 61, .02) 62%, transparent);
}

.xc-alert__mark {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 32px;
    block-size: 32px;
    border-radius: 11px;
    background: rgba(var(--ink), .05);
    color: rgba(var(--ink), .5);
}

.xc-alert[data-tone="ask"] .xc-alert__mark {
    background: rgba(232, 163, 61, .16);
    color: #B77C18;
}

/* The chip that holds someone else's logo.

   WhatsApp's mark is green and the asking card is amber, and green-on-amber
   reads as two companies arguing in a 32px square. A plain light chip is what
   an app icon sits on everywhere else, so the logo is left to be the only
   coloured thing in it. */
.xc-alert__mark[data-brand] {
    background: #FFFFFF;
    border: 1px solid rgba(var(--ink), .08);
    box-shadow: 0 1px 2px rgba(var(--ink), .06);
}

.xc-alert[data-tone="ask"] .xc-alert__mark[data-brand] {
    background: #FFFFFF;
}

.xc-alert__say {
    flex: 1;
    /* Enough room that the artwork never crowds the sentence, and the
       sentence wins when there is not enough for both. */
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.xc-alert__title {
    font-family: Poppins, sans-serif;
    font-weight: 600;
    font-size: 14px;
    letter-spacing: -0.01em;
}

.xc-alert__sub {
    font-size: 12.6px;
    line-height: 1.45;
    color: rgba(var(--ink), .52);
    /* One line. A permanent notice that wraps to three is a paragraph, and a
       paragraph on every screen is something people learn to scroll past. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── a screen that is announced and not open yet (screens/soon) ───────── */
.xc-soon {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 56px 24px;
    border: 1px dashed var(--line);
    border-radius: 18px;
    background: var(--surface);
    text-align: center;
}

.xc-soon__mark {
    display: grid;
    place-items: center;
    inline-size: 64px;
    block-size: 64px;
    border-radius: 20px;
    color: var(--brand);
    background: rgba(91, 91, 240, .12);
}

.xc-soon__tag {
    padding: 4px 12px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--amber);
    background: rgba(232, 163, 61, .16);
}

.xc-soon h2 {
    margin: 0;
    font-family: Poppins, system-ui, sans-serif;
    font-size: 24px;
    font-weight: 600;
    letter-spacing: -0.015em;
}

.xc-soon p {
    margin: 0;
    max-inline-size: 54ch;
    font-size: 14.5px;
    line-height: 1.55;
    color: rgba(var(--ink), .62);
    text-wrap: pretty;
}

.xc-soon .xc-soon__note { font-size: 13px; color: rgba(var(--ink), .45); margin-block-end: 8px; }

/* A plan's lock says what stays and what needs the plan (x-plan-lock): read
   whole, on a second line where it takes one. */
.xc-alert[data-plan-lock] .xc-alert__sub {
    overflow: visible;
    white-space: normal;
    text-wrap: pretty;
}

.xc-alert__act {
    flex: none;
    /* Above the artwork, which is absolutely placed behind everything. */
    position: relative;
}

/* The component inside brings its own column layout, which is right in a
   panel and wrong here. Flattened rather than given a second variant: one
   connect button, four places, and the places do the arranging. */
.xc-alert__go,
.xc-alert__act > div {
    flex-direction: row !important;
    align-items: center;
    gap: 10px !important;
}

/* The small print under the button belongs in a panel, not on a nudge. */
.xc-alert__act > div > span:last-of-type,
.xc-alert noscript { display: none; }

.xc-alert__link {
    font-size: 13px;
    font-weight: 600;
    color: rgba(var(--ink), .7);
    text-decoration: underline;
    text-underline-offset: 3px;
    white-space: nowrap;
}

.xc-alert__link:hover { color: rgb(var(--brand)); }

@media (max-width: 720px) {
    .xc-alert { margin-inline: 12px; padding: 10px 12px; gap: 10px; }
    .xc-alert__mark { inline-size: 28px; block-size: 28px; border-radius: 9px; }
    .xc-alert__title { font-size: 13.4px; }
    .xc-alert__sub { display: none; }
}

/* ── the picture beside an open checklist step ────────────────────────────
 *
 * One gradient and one glyph, themed from the step's own tint. Gone below
 * 900px, where the paragraph already fills the width and a decoration would
 * push the button under the fold.
 */
.xc-stepart {
    flex: 0 0 210px;
    align-self: stretch;
    min-block-size: 132px;
    border-radius: 14px;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(145deg, rgba(var(--tint), .30), rgba(var(--tint), .10));
}

.xc-stepart__glow {
    position: absolute;
    inset-block-start: -30%;
    inset-inline-start: -14%;
    inline-size: 74%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: rgba(255, 255, 255, .22);
}

.xc-stepart__mark {
    position: relative;
    inline-size: 60px;
    block-size: 60px;
    border-radius: 50%;
    background: var(--surface);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8px 22px rgba(var(--tint), .28);
}

@media (max-width: 900px) {
    .xc-stepart { display: none; }
}

/* ── the welcome ──────────────────────────────────────────────────────────
 *
 * Its own sheet rather than the shared one. `.xc-sheet` is the chrome for a
 * form — a header rule, an icon tile, a footer with cancel and submit — and
 * that frame is right for "new campaign" and wrong for the one screen in this
 * product whose entire job is to be glad somebody arrived.
 *
 * Both borders are deliberately absent: the black outline a <dialog> draws by
 * default, and the hairline the shared sheet puts round itself. A welcome in a
 * box reads as a system message.
 */
.xc-welcome {
    border: 0;
    outline: 0;
    padding: 0;
    background: transparent;
    inline-size: 100%;
    max-inline-size: min(520px, 94vw);
    color: var(--text);
}

.xc-welcome::backdrop {
    /* Darker than the shared sheet's, because there is nothing behind this
       worth reading yet and the contrast is what makes the banner sing. */
    background: rgba(10, 10, 24, .58);
    backdrop-filter: blur(3px);
}

.xc-welcome__sheet {
    position: relative;
    background: var(--surface);
    border-radius: 24px;
    overflow: hidden;
    box-shadow: 0 40px 90px rgba(10, 10, 40, .45);
    animation: xc-welcome-in .42s cubic-bezier(.2, .8, .3, 1);
}

@keyframes xc-welcome-in {
    from { opacity: 0; transform: translateY(14px) scale(.985); }
}

/* The banner. One gradient — the only one on this screen. */
.xc-welcome__top {
    position: relative;
    block-size: 132px;
    background: linear-gradient(135deg, #1C1CD2, #5B5BF0 55%, #7A5BF0);
    display: flex;
    align-items: center;
    justify-content: center;
}

.xc-welcome__confetti {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
}

.xc-welcome__pop {
    position: relative;
    inline-size: 74px;
    block-size: 74px;
    border-radius: 50%;
    background: var(--surface);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 36px;
    line-height: 1;
    box-shadow: 0 10px 28px rgba(10, 10, 60, .28);
    animation: xc-pop-in .5s .1s cubic-bezier(.2, 1.3, .4, 1) backwards;
}

@keyframes xc-pop-in {
    from { opacity: 0; transform: scale(.4) rotate(-18deg); }
}

.xc-welcome__body {
    padding: 22px 26px 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-block-size: calc(88vh - 132px);
    overflow-y: auto;
}

/* The one thing being asked for, on its own ground so the eye lands there
   rather than on the paragraph above it. */
.xc-welcome__do {
    background: var(--surface-2);
    border-radius: 15px;
    padding: 15px 17px;
}

.xc-welcome__foot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-block-start: 14px;
    border-block-start: 1px solid var(--line);
}

/* Over the banner, so it is visible without a rule to sit on. */
.xc-welcome__x {
    position: absolute;
    inset-block-start: 14px;
    inset-inline-end: 14px;
    inline-size: 32px;
    block-size: 32px;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 160ms;
}

.xc-welcome__x:hover { background: rgba(255, 255, 255, .32); }

.xc-welcome__x:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* On a phone it is the whole bottom of the screen. A dialog with 30px of
   backdrop either side of a 360px viewport looks like one that failed. */
@media (max-width: 560px) {
    .xc-welcome {
        max-inline-size: 100%;
        inset: auto 0 0 0;
        margin: 0;
    }

    .xc-welcome__sheet {
        border-end-start-radius: 0;
        border-end-end-radius: 0;
    }

    .xc-welcome__top { block-size: 104px; }
    .xc-welcome__pop { inline-size: 62px; block-size: 62px; font-size: 30px; }
}

@media (prefers-reduced-motion: reduce) {
    .xc-welcome__sheet,
    .xc-welcome__pop { animation: none; }
}

/* ── the channel catalogue ────────────────────────────────────────────────
 *
 * A card per thing that can be connected. One today, and the grid is built
 * for more rather than for one, because the day there are three is not the
 * day to rewrite this.
 *
 * The tint is the channel's, never its brand colour: a WhatsApp-green card
 * reads as an official WhatsApp surface, and what we are is a business built
 * on their API — a true and much smaller claim.
 */
.xc-chan {
    display: flex;
    flex-direction: column;
    gap: 13px;
    padding: 17px 18px 15px;
    border: 1px solid var(--line);
    border-radius: 17px;
    background: var(--surface-2);
    color: inherit;
    text-decoration: none;
    transition: border-color 160ms, transform 160ms, box-shadow 160ms;
}

.xc-chan:hover {
    border-color: rgba(var(--tint), .45);
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(var(--tint), .13);
}

.xc-chan:focus-visible {
    outline: 2px solid rgb(var(--tint));
    outline-offset: 2px;
}

.xc-chan__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
}

.xc-chan__mark {
    flex: none;
    inline-size: 48px;
    block-size: 48px;
    border-radius: 15px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgb(var(--tint));
    background: rgba(var(--tint), .12);
}

.xc-chan__go {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13.2px;
    font-weight: 600;
    color: rgb(var(--tint));
}

.xc-chan:hover .xc-chan__go svg { transform: translateX(2px); }

.xc-chan__go svg { transition: transform 160ms; }

@media (prefers-reduced-motion: reduce) {
    .xc-chan,
    .xc-chan__go svg { transition: none; }
    .xc-chan:hover { transform: none; }
}

/* ── a password you can look at ──────────────────────────────────────────
 *
 * The button sits inside the field's box rather than beside it, so the field
 * keeps its full width and the control cannot be mistaken for something that
 * submits. 42px of end padding is the room it needs; without it the reveal
 * sits on top of the last characters of a long password, which is exactly
 * when somebody reaches for it.
 */
.xc-peek { position: relative; display: flex; align-items: stretch; }

.xc-peek__in {
    flex: 1;
    min-inline-size: 0;
    padding-inline-end: 42px !important;
}

.xc-peek__eye {
    position: absolute;
    inset-inline-end: 4px;
    inset-block: 4px;
    inline-size: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    border-radius: 9px;
    color: rgba(var(--ink), .42);
    cursor: pointer;
    padding: 0;
    transition: color 150ms, background 150ms;
}

.xc-peek__eye:hover { color: var(--text); background: rgba(var(--ink), .06); }

.xc-peek__eye:focus-visible {
    outline: 2px solid var(--peri);
    outline-offset: -2px;
    color: var(--text);
}

/* One icon at a time, chosen by the state the button reports. */
.xc-peek__eye .xc-peek__off { display: none; }
.xc-peek__eye[aria-pressed="true"] { color: var(--acc); }
.xc-peek__eye[aria-pressed="true"] .xc-peek__on { display: none; }
.xc-peek__eye[aria-pressed="true"] .xc-peek__off { display: block; }

/* ── toasts ─────────────────────────────────────────────────────────────
 * What just happened, said in the corner (layouts/partials/toasts,
 * modules/toast.js): a request sent, a top-up credited or turned down, a new
 * request on the console. On the surface, in the tone of what it says, with
 * the console's green, amber and red, and the brand for the rest. Below the
 * busy bar and never over a sheet: a dialog is in the top layer.
 */
.xc-toasts {
    position: fixed;
    z-index: 900;
    inset-block-end: 20px;
    inset-inline-end: 20px;
    inline-size: min(380px, calc(100vw - 32px));
    display: flex;
    flex-direction: column;
    gap: 10px;
    pointer-events: none;
}

.xc-toast {
    --tone: var(--brand);
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px 12px 14px 14px;
    border-radius: 16px;
    border: 1px solid var(--line);
    background: var(--surface);
    box-shadow: 0 18px 44px rgba(var(--scrim), .2);
    animation: xc-toast-in 220ms cubic-bezier(.2, .8, .25, 1) both;
}

.xc-toast[data-tone="go"] { --tone: 0, 128, 106; }
.xc-toast[data-tone="hold"] { --tone: 169, 108, 20; }
.xc-toast[data-tone="danger"] { --tone: 214, 69, 69; border-color: rgba(214, 69, 69, .35); }
[data-theme="dark"] .xc-toast[data-tone="go"] { --tone: 0, 168, 134; }
[data-theme="dark"] .xc-toast[data-tone="hold"] { --tone: 232, 163, 61; }

.xc-toast__mark {
    flex: none;
    inline-size: 34px;
    block-size: 34px;
    border-radius: 11px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgb(var(--tone));
    background: rgba(var(--tone), .12);
}

.xc-toast__say {
    flex: 1;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding-block-start: 1px;
    font-size: 13px;
    line-height: 1.45;
    color: rgba(var(--ink), .68);
    overflow-wrap: anywhere;
}

.xc-toast__say strong { font-size: 14px; font-weight: 600; color: var(--text); }

.xc-toast__link {
    align-self: flex-start;
    margin-block-start: 3px;
    font-weight: 600;
    color: rgb(var(--brand));
    text-decoration: none;
}

.xc-toast__link:hover { text-decoration: underline; }

.xc-toast__x {
    appearance: none;
    flex: none;
    display: flex;
    padding: 5px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: rgba(var(--ink), .45);
    cursor: pointer;
}

.xc-toast__x:hover { color: var(--text); background: rgba(var(--ink), .06); }
.xc-toast__x:focus-visible,
.xc-toast__link:focus-visible { outline: 2px solid rgb(var(--brand)); outline-offset: 2px; }
.xc-toast[data-leaving] { animation: xc-toast-out 180ms ease-in both; }

@keyframes xc-toast-in {
    from { opacity: 0; transform: translateY(10px) scale(.98); }
    to { opacity: 1; transform: none; }
}

@keyframes xc-toast-out {
    to { opacity: 0; transform: translateY(6px); }
}

@media (prefers-reduced-motion: reduce) {
    .xc-toast,
    .xc-toast[data-leaving] { animation: none; }
}

/* Above the phone's tab bar, the width of the screen. */
@media (max-width: 760px) {
    .xc-toasts { inset-inline: 16px; inset-block-end: 88px; inline-size: auto; }
}
