:root {
    --bg: #ffffff;
    --bg-soft: #f7f7fb;
    --bg-raised: #ffffff;
    --border: #e6e6ef;
    --border-strong: #d5d5e2;
    --text: #16161d;
    --text-soft: #5a5a6e;
    --text-faint: #8a8a9c;
    --accent: #5b4ae0;
    --accent-soft: #efecff;
    --accent-text: #4a3ad0;
    --on-accent: #fff;
    --code-bg: #f5f4fb;
    --shadow: 0 1px 2px rgba(20, 20, 40, .05), 0 8px 24px rgba(20, 20, 40, .06);
    --radius: 12px;
    --radius-sm: 8px;
    --header-height: 60px;
    --sidebar-width: 268px;
    --toc-width: 232px;
    --measure: 74ch;
    --ease: cubic-bezier(.2, .7, .3, 1);
    color-scheme: light;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg: #0f0f14;
        --bg-soft: #16161d;
        --bg-raised: #1a1a23;
        --border: #26262f;
        --border-strong: #34343f;
        --text: #ececf2;
        --text-soft: #a5a5b8;
        --text-faint: #7c7c90;
        --accent: #a99bff;
        --accent-soft: #211d3d;
        --accent-text: #b9adff;
        --on-accent: #14121f;
        --code-bg: #16161f;
        --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px rgba(0, 0, 0, .35);
        color-scheme: dark;
    }
}

:root[data-theme="dark"] {
    --bg: #0f0f14;
    --bg-soft: #16161d;
    --bg-raised: #1a1a23;
    --border: #26262f;
    --border-strong: #34343f;
    --text: #ececf2;
    --text-soft: #a5a5b8;
    --text-faint: #7c7c90;
    --accent: #a99bff;
    --accent-soft: #211d3d;
    --accent-text: #b9adff;
    --on-accent: #14121f;
    --code-bg: #16161f;
    --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px rgba(0, 0, 0, .35);
    color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }

[tabindex="-1"]:focus { outline: none; }

html { scroll-behavior: smooth; scroll-padding-top: calc(var(--header-height) + 16px); }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Helvetica Neue", Arial, "Noto Sans JP", "Noto Sans SC", "Noto Sans KR", sans-serif;
    font-size: 16px;
    line-height: 1.7;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

code, pre {
    font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: .88em;
}

.skip {
    position: absolute;
    left: -9999px;
    top: 8px;
    padding: 10px 16px;
    background: var(--accent);
    color: #fff;
    border-radius: var(--radius-sm);
    z-index: 100;
}
.skip:focus { left: 12px; }

.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    height: var(--header-height);
    background: color-mix(in srgb, var(--bg) 82%, transparent);
    -webkit-backdrop-filter: saturate(160%) blur(12px);
    backdrop-filter: saturate(160%) blur(12px);
    border-bottom: 1px solid var(--border);
}

.header-inner {
    max-width: 1400px;
    margin: 0 auto;
    height: 100%;
    padding: 0 24px;
    display: flex;
    align-items: center;
    gap: 20px;
}

/* A wordmark and nothing else. It carries the header on its own now, so it is a little larger and
   tighter than it was beside an icon. */
.brand {
    display: flex;
    align-items: center;
    color: var(--text);
    flex: none;
    font-size: 1.15rem;
    letter-spacing: -.02em;
}
.brand:hover { text-decoration: none; }
.brand-name {
    font-weight: 660;
    color: var(--text);
    transition: color .25s var(--ease);
}
.brand:hover .brand-name { color: var(--accent-text); }




.search {
    position: relative;
    /* Fills whatever is between the brand and the header actions. It used to be capped at 460px
       and pushed right by an auto margin, which left a gap beside the logo that grew with the
       window - the wider the screen, the more empty header. */
    flex: 1;
    min-width: 0;
}
.search-icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 17px;
    height: 17px;
    fill: none;
    stroke: var(--text-faint);
    stroke-width: 1.8;
    stroke-linecap: round;
    pointer-events: none;
}
.search input[type="search"] {
    width: 100%;
    height: 38px;
    padding: 0 14px 0 36px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg-soft);
    color: var(--text);
    font: inherit;
    font-size: .92rem;
    transition: border-color .18s var(--ease), box-shadow .18s var(--ease), background .18s var(--ease);
}
.search input[type="search"]:focus {
    outline: none;
    background: var(--bg-raised);
    border-color: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-soft);
}

.header-actions { display: flex; align-items: center; gap: 10px; flex: none; }

.menu { position: relative; }
.menu-button {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 34px;
    padding: 0 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-soft);
    font: inherit;
    font-size: .88rem;
    cursor: pointer;
    transition: background .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
.menu-button:hover { background: var(--bg-soft); color: var(--text); }
.chevron { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: transform .2s var(--ease); }
.menu.open .chevron { transform: rotate(180deg); }

.menu-panel {
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    min-width: 190px;
    padding: 6px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    opacity: 0;
    transform: translateY(-6px) scale(.98);
    pointer-events: none;
    transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.menu.open .menu-panel { opacity: 1; transform: none; pointer-events: auto; }
.menu-panel a {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: .9rem;
}
.menu-panel a:hover { background: var(--bg-soft); text-decoration: none; }
.menu-panel a.active { color: var(--accent-text); font-weight: 600; }
.menu-note { color: var(--text-faint); font-size: .78rem; }

.flag { width: 20px; height: 14px; display: block; border-radius: 2px; }

.menu-button .flag { width: 22px; height: 15px; }

.menu-panel.flags {
    display: flex;
    gap: 4px;
    min-width: 0;
    padding: 5px;
}
.menu-panel.flags a {
    display: grid;
    place-items: center;
    padding: 6px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    transition: background .16s var(--ease), border-color .16s var(--ease), transform .16s var(--ease);
}
.menu-panel.flags a:hover { background: var(--bg-soft); transform: translateY(-1px); }
.menu-panel.flags a.active { border-color: var(--accent); background: var(--accent-soft); }

.icon-link {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    color: var(--text-faint);
    transition: color .18s var(--ease), background .18s var(--ease);
}
.icon-link svg { width: 17px; height: 17px; fill: currentColor; }
.icon-link:hover { color: var(--text); background: var(--bg-soft); text-decoration: none; }


.suggestions {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 8px);
    padding: 6px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    max-height: 60vh;
    overflow-y: auto;
    z-index: 60;
}
.suggestions a {
    display: block;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    color: var(--text);
}
.suggestions a:hover, .suggestions a.active { background: var(--bg-soft); text-decoration: none; }
.suggestions .s-where { display: block; color: var(--text-faint); font-size: .74rem; }
.suggestions .s-title { display: block; font-weight: 560; font-size: .92rem; }
.suggestions .s-desc { display: block; color: var(--text-soft); font-size: .82rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggestions .s-empty { padding: 12px; color: var(--text-faint); font-size: .88rem; }
.suggestions mark { background: var(--accent-soft); color: var(--accent-text); border-radius: 3px; padding: 0 1px; }

.theme-toggle {
    display: flex;
    padding: 3px;
    gap: 2px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.theme-toggle button {
    display: grid;
    place-items: center;
    width: 28px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text-faint);
    cursor: pointer;
    transition: background .18s var(--ease), color .18s var(--ease);
}
.theme-toggle button svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.theme-toggle button:hover { color: var(--text); }
.theme-toggle button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); }

main { min-height: calc(100vh - var(--header-height) - 90px); }

.hub { max-width: 1000px; margin: 0 auto; padding: 72px 24px 96px; }
.hub-lede { max-width: 620px; }
.hub h1 {
    margin: 0 0 14px;
    font-size: clamp(2.1rem, 4.5vw, 2.9rem);
    line-height: 1.15;
    letter-spacing: -.025em;
    font-weight: 680;
}
.hub-lede p { margin: 0; color: var(--text-soft); font-size: 1.12rem; }

.install {
    margin-top: 40px;
    padding: 26px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.install h2 { margin: 0 0 8px; font-size: 1.12rem; letter-spacing: -.015em; }
.install p { margin: 0 0 18px; color: var(--text-soft); font-size: .95rem; max-width: 62ch; }

.install-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.install-row code {
    flex: 1;
    min-width: 260px;
    padding: 10px 14px;
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: .86rem;
    overflow-x: auto;
    white-space: nowrap;
}
.install-row .copy {
    height: 40px;
    padding: 0 16px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-soft);
    color: var(--text);
    font: inherit;
    font-size: .88rem;
    cursor: pointer;
    transition: background .18s var(--ease), border-color .18s var(--ease);
}
.install-row .copy:hover { border-color: var(--border-strong); }
.install-row .cta {
    display: inline-flex;
    align-items: center;
    height: 40px;
    padding: 0 18px;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: #fff;
    font-weight: 580;
    font-size: .9rem;
    transition: filter .18s var(--ease), transform .18s var(--ease);
}
.install-row .cta:hover { text-decoration: none; filter: brightness(1.08); transform: translateY(-1px); }
:root[data-theme="dark"] .install-row .cta { color: #14121f; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .install-row .cta { color: #14121f; } }

.product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 18px;
    margin-top: 28px;
}

.product-card {
    display: block;
    padding: 24px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    transition: transform .22s var(--ease), border-color .22s var(--ease), box-shadow .22s var(--ease);
}
.product-card:hover {
    text-decoration: none;
    transform: translateY(-3px);
    border-color: var(--border-strong);
    box-shadow: var(--shadow);
}
.product-card h2 { margin: 0 0 8px; font-size: 1.18rem; letter-spacing: -.015em; }
.product-card p { margin: 0 0 16px; color: var(--text-soft); font-size: .95rem; }
.product-meta { display: flex; align-items: center; gap: 8px; color: var(--text-faint); font-size: .82rem; }
.product-cta { color: var(--accent-text); font-weight: 560; font-size: .9rem; }
.product-card:hover .product-cta .arrow { transform: translateX(3px); }
.arrow { display: inline-block; transition: transform .22s var(--ease); }

.badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--accent-soft);
    color: var(--accent-text);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .02em;
}

.docs-shell {
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 24px;
    display: grid;
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--toc-width);
    gap: 48px;
    align-items: start;
}

.sidebar {
    position: sticky;
    top: var(--header-height);
    max-height: calc(100vh - var(--header-height));
    overflow-y: auto;
    padding: 32px 0 48px;
    font-size: .92rem;
}
.sidebar-product { margin-bottom: 22px; padding-left: 14px; font-weight: 640; letter-spacing: -.01em; }
.sidebar h3 {
    margin: 22px 0 8px;
    padding-left: 14px;
    font-size: .74rem;
    font-weight: 640;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--text-faint);
}
.sidebar ul { list-style: none; margin: 0; padding: 0; }
.sidebar li a {
    display: block;
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    color: var(--text-soft);
    transition: color .16s var(--ease), background .16s var(--ease);
}
.sidebar li a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.sidebar li a:hover { color: var(--text); background: var(--bg-soft); text-decoration: none; }
.sidebar li a.active { color: var(--accent-text); background: var(--accent-soft); font-weight: 560; }

.doc { padding: 40px 0 88px; min-width: 0; animation: rise .32s var(--ease) both; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.crumbs { display: flex; gap: 8px; color: var(--text-faint); font-size: .85rem; margin-bottom: 14px; }
.crumbs a { color: var(--text-faint); }
.crumbs a:hover { color: var(--text-soft); }

.doc h1 {
    margin: 0 0 10px;
    font-size: clamp(1.9rem, 3.4vw, 2.4rem);
    line-height: 1.18;
    letter-spacing: -.025em;
    font-weight: 680;
}
.doc-lede { margin: 0 0 8px; color: var(--text-soft); font-size: 1.08rem; }
.doc-meta { color: var(--text-faint); font-size: .82rem; margin-bottom: 32px; }

.lang-tag {
    flex: none;
    padding: 1px 5px;
    border: 1px solid var(--border-strong);
    border-radius: 4px;
    color: var(--text-faint);
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .06em;
    line-height: 1.5;
}

.notice-lang { display: flex; align-items: center; gap: 10px; }
.notice-lang .lang-tag { border-color: var(--accent); color: var(--accent-text); }

.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 16px;
}
.doc-body .tag {
    display: inline-flex;
    align-items: center;
    padding: 5px 12px;
    background: var(--bg-soft);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: .86rem;
    color: var(--text-soft);
    line-height: 1.3;
}
.doc-body .tag code {
    padding: 0;
    background: none;
    border: 0;
    color: inherit;
    font-weight: inherit;
    font-size: .95em;
}

.notice {
    padding: 12px 16px;
    margin: 0 0 28px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--bg-soft);
    color: var(--text-soft);
    font-size: .9rem;
}

.doc-body > *:first-child { margin-top: 0; }
.doc-body > p,
.doc-body > ul,
.doc-body > ol,
.doc-body > blockquote,
.doc-body > h2,
.doc-body > h3,
.doc-body > h4 { max-width: var(--measure); }
.doc-body > pre,
.doc-body > .table-wrap,
.doc-body > img { max-width: 100%; }
.doc-body h2 {
    margin: 44px 0 14px;
    padding-top: 8px;
    font-size: 1.42rem;
    letter-spacing: -.02em;
    font-weight: 660;
}
.doc-body h3 { margin: 32px 0 10px; font-size: 1.12rem; font-weight: 640; letter-spacing: -.01em; }
.doc-body h4 { margin: 26px 0 8px; font-size: 1rem; font-weight: 640; }
.doc-body p { margin: 0 0 18px; }
.doc-body ul, .doc-body ol { margin: 0 0 18px; padding-left: 24px; }
.doc-body li { margin-bottom: 7px; }
.doc-body li::marker { color: var(--text-faint); }

.doc-body h2 a.anchor, .doc-body h3 a.anchor { opacity: 0; margin-left: 8px; color: var(--text-faint); transition: opacity .16s var(--ease); }
.doc-body h2:hover a.anchor, .doc-body h3:hover a.anchor { opacity: 1; }

.doc-body code {
    padding: .15em .4em;
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: 5px;
}
.doc-body pre {
    margin: 0 0 22px;
    padding: 16px 18px;
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow-x: auto;
    line-height: 1.6;
}
.doc-body pre code { padding: 0; background: none; border: 0; tab-size: 4; }

.t-keyword { color: #8250df; }
.t-string { color: #0a7d55; }
.t-comment { color: #7c7c90; font-style: italic; }
.t-number { color: #a8480a; }
.t-type { color: #1f6feb; }
.t-attribute { color: #a8480a; }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .t-keyword { color: #c9a3ff; }
    :root:not([data-theme="light"]) .t-string { color: #7ee0a8; }
    :root:not([data-theme="light"]) .t-comment { color: #6f6f85; }
    :root:not([data-theme="light"]) .t-number { color: #ffb37a; }
    :root:not([data-theme="light"]) .t-type { color: #7cc4ff; }
    :root:not([data-theme="light"]) .t-attribute { color: #ffb37a; }
}

:root[data-theme="dark"] .t-keyword { color: #c9a3ff; }
:root[data-theme="dark"] .t-string { color: #7ee0a8; }
:root[data-theme="dark"] .t-comment { color: #6f6f85; }
:root[data-theme="dark"] .t-number { color: #ffb37a; }
:root[data-theme="dark"] .t-type { color: #7cc4ff; }
:root[data-theme="dark"] .t-attribute { color: #ffb37a; }

.doc-body blockquote {
    margin: 0 0 22px;
    padding: 2px 18px;
    border-left: 3px solid var(--border-strong);
    color: var(--text-soft);
}

.table-wrap {
    margin: 0 0 26px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow-x: auto;
    background: var(--bg-raised);
}
.doc-body table { width: 100%; border-collapse: collapse; margin: 0; font-size: .92rem; }
.doc-body thead { background: var(--bg-soft); }
.doc-body th {
    padding: 10px 16px;
    text-align: left;
    font-weight: 620;
    color: var(--text-faint);
    font-size: .74rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
}
.doc-body td {
    padding: 11px 16px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}
.doc-body tbody tr:last-child td { border-bottom: 0; }
.doc-body tbody tr { transition: background .14s var(--ease); }
.doc-body tbody tr:hover { background: var(--bg-soft); }
.doc-body td code {
    padding: .1em .35em;
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: 5px;
    white-space: nowrap;
}
.doc-body td:first-child { color: var(--text-soft); }

.doc-body .note,
.doc-body .tip,
.doc-body .warning {
    margin: 0 0 24px;
    padding: 14px 18px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--bg-soft);
    max-width: var(--measure);
}
.doc-body .note > *:last-child,
.doc-body .tip > *:last-child,
.doc-body .warning > *:last-child { margin-bottom: 0; }
.doc-body .warning { border-left-color: #d97706; }
.doc-body .tip { border-left-color: #0a7d55; }
:root[data-theme="dark"] .doc-body .warning { border-left-color: #f59e0b; }
:root[data-theme="dark"] .doc-body .tip { border-left-color: #4ade80; }

.doc-body hr { border: 0; border-top: 1px solid var(--border); margin: 36px 0; }

.pager { display: flex; gap: 14px; margin-top: 56px; padding-top: 28px; border-top: 1px solid var(--border); }
.pager a {
    flex: 1;
    padding: 14px 18px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    transition: border-color .2s var(--ease), transform .2s var(--ease);
}
.pager a:hover { text-decoration: none; border-color: var(--border-strong); transform: translateY(-2px); }
.pager .dir { display: block; color: var(--text-faint); font-size: .78rem; margin-bottom: 3px; }
.pager .next { text-align: right; }

.toc { position: sticky; top: var(--header-height); padding: 44px 0 48px; font-size: .87rem; }
.toc h2 { margin: 0 0 10px; font-size: .74rem; font-weight: 640; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); }
.toc ul { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--border); }
.toc li a {
    display: block;
    padding: 4px 0 4px 14px;
    margin-left: -1px;
    border-left: 1px solid transparent;
    color: var(--text-faint);
    transition: color .16s var(--ease), border-color .16s var(--ease);
}
.toc li a:hover { color: var(--text); text-decoration: none; }
.toc li a.active { color: var(--accent-text); border-left-color: var(--accent); }
.toc .lvl-3 { padding-left: 26px; }

.results { max-width: 760px; margin: 0 auto; padding: 48px 24px 88px; }
.results h1 { margin: 0 0 6px; font-size: 1.9rem; letter-spacing: -.02em; }
.results-count { color: var(--text-faint); margin-bottom: 28px; }
.result {
    display: block;
    padding: 18px 20px;
    margin-bottom: 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    transition: border-color .2s var(--ease), transform .2s var(--ease);
}
.result:hover { text-decoration: none; border-color: var(--border-strong); transform: translateY(-2px); }
.result .where { color: var(--text-faint); font-size: .78rem; }
.result h2 { margin: 3px 0 6px; font-size: 1.05rem; }
.result p { margin: 0; color: var(--text-soft); font-size: .9rem; }

/* Header profile control */

.avatar-button {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
    transition: box-shadow .18s var(--ease);
}
.avatar-button:hover { box-shadow: 0 0 0 3px var(--accent-soft); text-decoration: none; }

.avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: block;
    object-fit: cover;
    border: 1px solid var(--border);
    background: var(--bg-soft);
}
.avatar-initial {
    display: grid;
    place-items: center;
    color: var(--accent-text);
    background: var(--accent-soft);
    font-size: .82rem;
    font-weight: 640;
    border-color: transparent;
}
.avatar-anon {
    fill: none;
    stroke: var(--text-faint);
    stroke-width: 1.6;
    stroke-linecap: round;
    padding: 3px;
}
.avatar-button:hover .avatar-anon { stroke: var(--text); }

/* Account dashboard */

.app-shell {
    max-width: 1200px;
    margin: 0 auto;
    padding: 44px 24px 88px;
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    gap: 40px;
    align-items: start;
}

.app-nav {
    position: sticky;
    top: calc(var(--header-height) + 44px);
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.app-identity {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 10px 16px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border);
    min-width: 0;
}
.app-avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--border);
    background: var(--bg-soft);
    flex: none;
}
.app-avatar.avatar-initial { font-size: 1.1rem; }
.app-identity-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.35; }
.app-identity-name {
    font-weight: 620;
    letter-spacing: -.01em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.app-identity-login { color: var(--text-faint); font-size: .84rem; }
a.app-identity-login:hover { color: var(--accent-text); }

.app-links { display: flex; flex-direction: column; gap: 2px; }
.app-links a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text-soft);
    font-size: .93rem;
    transition: background .16s var(--ease), color .16s var(--ease);
}
.app-links a svg {
    width: 17px;
    height: 17px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.app-links a:hover { background: var(--bg-soft); color: var(--text); text-decoration: none; }
.app-links a.active { background: var(--accent-soft); color: var(--accent-text); font-weight: 560; }

.app-signout { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.app-signout button {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-faint);
    font: inherit;
    font-size: .93rem;
    cursor: pointer;
    transition: background .16s var(--ease), color .16s var(--ease);
}
.app-signout button svg {
    width: 17px;
    height: 17px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.app-signout button:hover { background: var(--bg-soft); color: var(--text); }

.app-body { min-width: 0; animation: rise .32s var(--ease) both; }

.app-head { margin-bottom: 28px; }
.app-head h1 {
    margin: 0 0 6px;
    font-size: 1.85rem;
    font-weight: 680;
    letter-spacing: -.025em;
}
.app-head p { margin: 0; color: var(--text-soft); max-width: 62ch; }

.app-section-title {
    margin: 34px 0 14px;
    font-size: .78rem;
    font-weight: 640;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--text-faint);
}

.app-cards { display: grid; gap: 16px; }
.app-endpoints { display: grid; gap: 22px; }

.app-card {
    padding: 22px 24px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}
.app-card + .app-card { margin-top: 22px; }
.app-cards .app-card + .app-card, .app-endpoints .app-card + .app-card { margin-top: 0; }

/* The rule above only matches two cards that are siblings. Every list page puts an "add" card
   directly before a div of results, so nothing applied between them and they sat flush. These
   cover the block-level neighbours a page actually produces. */
.app-card + .app-endpoints,
.app-card + .app-cards,
.app-endpoints + .app-card,
.app-cards + .app-card,
.app-endpoints + .app-endpoints { margin-top: 22px; }
.app-card + .app-section-title,
.app-endpoints + .app-section-title,
.app-cards + .app-section-title { margin-top: 30px; }
.app-card p { margin: 0 0 16px; color: var(--text-soft); font-size: .95rem; max-width: 66ch; }
.app-card p:last-child { margin-bottom: 0; }
.app-card pre {
    margin: 0;
    padding: 14px 16px;
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    overflow-x: auto;
    font-size: .84rem;
    line-height: 1.6;
}
.app-card code { font-size: .86em; }

.app-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
}
.app-card-head h2, .app-card-head h3 {
    margin: 0;
    font-size: 1.08rem;
    font-weight: 640;
    letter-spacing: -.015em;
}

.pill {
    flex: none;
    padding: 3px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text-faint);
    font-size: .76rem;
    font-weight: 560;
    white-space: nowrap;
}
.pill-on { border-color: transparent; background: var(--accent-soft); color: var(--accent-text); }
.pill-off { border-color: transparent; background: var(--bg-soft); color: var(--text-faint); }

.app-muted { color: var(--text-faint) !important; font-size: .86rem !important; }
.app-note {
    max-width: none;
    padding: 12px 14px;
    background: var(--bg-soft);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    color: var(--text-soft);
    font-size: .9rem;
}
.app-error {
    padding: 11px 14px;
    background: color-mix(in srgb, #d64545 12%, transparent);
    border-left: 3px solid #d64545;
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: .9rem;
}

.app-copy-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.app-copy-row code {
    flex: 1 1 260px;
    min-width: 0;
    padding: 9px 12px;
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    overflow-x: auto;
    white-space: nowrap;
}
.app-copy-row { margin-bottom: 8px; }
.app-copy-row .copy {
    flex: none;
    height: 36px;
    min-width: 92px;
    justify-content: center;
    padding: 0 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-soft);
    font: inherit;
    font-size: .86rem;
    cursor: pointer;
    transition: border-color .18s var(--ease), color .18s var(--ease);
}
.app-copy-row .copy:hover { border-color: var(--border-strong); color: var(--text); }

.app-form { display: grid; gap: 14px; margin-bottom: 14px; }
.app-form label { display: flex; flex-direction: column; gap: 6px; }
/* Needed because the rule above outranks the user-agent [hidden] { display: none }, which is
   how the guard fields ended up staying visible after theme.js had correctly hidden them. */
.app-form label[hidden] { display: none; }
.app-form label span { font-size: .84rem; font-weight: 560; color: var(--text-soft); }
.app-form input {
    height: 38px;
    padding: 0 12px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    font: inherit;
    font-size: .92rem;
    transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.app-form input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-soft);
}
.app-form input::placeholder { color: var(--text-faint); }
.app-form .cta { justify-self: start; }

.cta {
    display: inline-flex;
    align-items: center;
    height: 38px;
    padding: 0 18px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: #fff;
    font: inherit;
    font-size: .9rem;
    font-weight: 580;
    cursor: pointer;
    transition: filter .18s var(--ease), transform .18s var(--ease);
}
.cta:hover { text-decoration: none; filter: brightness(1.08); transform: translateY(-1px); }
:root[data-theme="dark"] .cta { color: #14121f; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .cta { color: #14121f; } }
.cta-quiet {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text) !important;
}
.cta-quiet:hover { border-color: var(--border-strong); filter: none; }

.app-danger {
    height: 32px;
    padding: 0 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-faint);
    font: inherit;
    font-size: .85rem;
    cursor: pointer;
    transition: border-color .18s var(--ease), color .18s var(--ease), background .18s var(--ease);
}
.app-danger:hover { border-color: #d64545; color: #fff; background: #d64545; }

.app-endpoint.is-revoked { opacity: .62; }
.app-field { margin-bottom: 14px; }
.app-field-label {
    display: block;
    margin-bottom: 6px;
    font-size: .78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-faint);
}

.app-meta { display: flex; flex-wrap: wrap; gap: 28px; margin: 0 0 16px; }
.app-meta div { display: flex; flex-direction: column; gap: 2px; }
.app-meta dt {
    font-size: .74rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-faint);
}
.app-meta dd { margin: 0; font-size: .9rem; color: var(--text); }

.app-empty { text-align: center; }
.app-empty p { margin: 0 auto; color: var(--text-faint); }

.app-table-wrap { overflow-x: auto; }
.app-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.app-table th {
    padding: 0 14px 10px 0;
    border-bottom: 1px solid var(--border);
    text-align: left;
    font-size: .76rem;
    font-weight: 640;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-faint);
    white-space: nowrap;
}
.app-table td {
    padding: 12px 14px 12px 0;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}
.app-table tbody tr:last-child td { border-bottom: 0; }
.app-table tr.is-revoked { opacity: .55; }
.app-table .app-num { font-variant-numeric: tabular-nums; }

@media (max-width: 940px) {
    .app-shell { grid-template-columns: minmax(0, 1fr); gap: 24px; padding-top: 28px; }
    .app-nav { position: static; }
    .app-links { flex-direction: row; flex-wrap: wrap; }
    .app-links a { padding: 7px 12px; border: 1px solid var(--border); }
    .app-signout { border-top: 0; padding-top: 0; margin-top: 0; }
    .app-signout button { width: auto; padding: 7px 12px; }
}

.nav-toggle { display: none; }

.site-footer { border-top: 1px solid var(--border); background: var(--bg-soft); }
.footer-inner {
    /* One line of text and nothing else, so it is centred on the same measure the content uses
       rather than pushed to the left edge by a layout built for a row of links. */
    max-width: 1400px;
    margin: 0 auto;
    padding: 22px 24px;
    text-align: center;
    color: var(--text-faint);
    font-size: .85rem;
}
.footer-inner a { color: var(--text-soft); }

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 12px 20px;
    background: #ffe8a3;
    color: #3b2f00;
    z-index: 200;
}

@media (min-width: 1600px) {
    :root {
        --sidebar-width: 288px;
        --toc-width: 256px;
        --measure: 80ch;
    }
    .docs-shell { max-width: 1580px; gap: 56px; }
    .hub { max-width: 1120px; }
}

@media (min-width: 1920px) {
    :root {
        --sidebar-width: 304px;
        --toc-width: 272px;
        --measure: 86ch;
    }
    .docs-shell { max-width: 1780px; gap: 64px; }
    .hub { max-width: 1240px; padding-top: 88px; }
}

@media (max-width: 1180px) {
    .docs-shell { grid-template-columns: var(--sidebar-width) minmax(0, 1fr); gap: 40px; }
    .toc { display: none; }
}

@media (max-width: 860px) {
    .docs-shell { grid-template-columns: minmax(0, 1fr); gap: 0; }
    .sidebar {
        position: fixed;
        inset: var(--header-height) auto 0 0;
        width: 280px;
        padding: 24px;
        background: var(--bg-raised);
        border-right: 1px solid var(--border);
        transform: translateX(-100%);
        transition: transform .26s var(--ease);
        z-index: 40;
    }
    body.nav-open .sidebar { transform: none; }
    body:has(.sidebar) .nav-toggle {
        display: grid;
        place-items: center;
        flex: none;
        width: 34px;
        height: 34px;
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        background: var(--bg-soft);
        color: var(--text-soft);
        cursor: pointer;
    }
    body:has(.sidebar) .nav-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
    .icon-link { display: none; }
    .header-inner { gap: 12px; padding: 0 16px; }
    .doc { padding-top: 24px; }
    .pager { flex-direction: column; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
    html { scroll-behavior: auto; }
}

.app-deliveries { margin-bottom: 16px; }
.app-deliveries summary {
    cursor: pointer;
    padding: 8px 0;
    color: var(--text-soft);
    font-size: .86rem;
    font-weight: 560;
    list-style-position: inside;
}
.app-deliveries summary:hover { color: var(--text); }
.app-deliveries[open] summary { margin-bottom: 6px; }
.app-deliveries .app-table { font-size: .85rem; }
.app-deliveries .app-table td:last-child {
    max-width: 42ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The reference tables under the add-key form. Collapsed by default so the form stays the
   first thing you see, but sitting with the form rather than on a separate docs page - the
   question "what is a guard" only occurs while looking at the dropdown. */
.app-help { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 12px; }
.app-help summary {
    cursor: pointer;
    padding: 6px 0;
    color: var(--text-soft);
    font-size: .86rem;
    font-weight: 560;
    list-style-position: inside;
}
.app-help summary:hover { color: var(--text); }
.app-help[open] summary { margin-bottom: 10px; }
.app-help .app-table { font-size: .85rem; }
.app-help .app-table td:first-child { white-space: nowrap; }
.app-help .app-table-wrap + .app-table-wrap { margin-top: 14px; }
.app-help .app-note { margin-top: 14px; }

/* Actions inside a card: a blue confirm and a red destructive, the same size as each other so a
   row of them lines up instead of stepping. Both were previously outlined and the same colour,
   which made "Save" and "Delete" look like the same kind of button. */
.app-card .cta,
.app-card .app-danger {
    height: 36px;
    min-width: 104px;
    justify-content: center;
    font-size: .88rem;
}
.app-card .app-danger {
    border-color: #d64545;
    color: #d64545;
    background: transparent;
}
.app-card .app-danger:hover {
    background: #d64545;
    border-color: #d64545;
    color: #fff;
}

/* A bare checkbox rendered at the form control's font size, which made it enormous next to its
   label. This puts it back to a normal box with the label beside it. */
.app-check {
    display: flex !important;
    flex-direction: row !important;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-soft);
    cursor: pointer;
}
.app-check:hover { border-color: var(--border-strong); }
.app-check input[type="checkbox"] {
    width: 16px;
    height: 16px;
    flex: none;
    margin: 0;
    accent-color: var(--accent);
}
.app-check span { font-size: .92rem; color: var(--text); font-weight: 500; }

/* What each URL is for, sitting with the URL rather than in a legend somewhere else. */
.app-url-purpose {
    display: block;
    margin: 0 0 2px;
    color: var(--text-faint);
    font-size: .8rem;
    font-weight: 560;
}

/* The relay test form. The previewed URL grows as you type, so it takes a full row of its own -
   sharing a wrapping flex row with the delete button moved that button around under the cursor. */
.app-test { margin-bottom: 16px; }
.app-test .app-copy-row code { flex: 1 1 100%; }

/* A best score over a wide range produced a wall of full URLs. The pattern is shown once and the
   values become small numbered buttons, each copying its own complete URL. */
/* A call to action needs room from the prose under it, or it reads as part of the paragraph. */
.app-card .cta + .app-meta,
.app-card .app-actions + .app-meta { margin-top: 20px; }
.app-card p + .cta { margin-top: 4px; }
.app-card p + .app-actions { margin-top: 18px; }
.app-card .cta + p { margin-top: 14px; }

/* Free beside supporter, with the column you are on marked. A single column of your own limits
   answers "what do I have" and not "what would change", which is the question being asked. */
/* A post that waits on every webhook behind a destination can take seconds. The button stops
   taking clicks and becomes a spinner, rather than looking like nothing happened. */
.cta.is-busy, .cta:disabled {
    cursor: default;
    pointer-events: none;
}
.cta:disabled { opacity: .75; }

/* Full strength while it works: this button is busy, not unavailable, and dimming the spinner
   made the one moving thing on the page the faintest. The label is cleared by script and the box
   frozen at the size it had, so the spinner sits where the text was and nothing reflows. */
.cta.is-busy {
    position: relative;
    opacity: 1;
}
.cta.is-busy::before {
    content: "";
    position: absolute;
    inset: 0;
    margin: auto;
    width: 17px;
    height: 17px;
    border: 2px solid color-mix(in srgb, currentColor 26%, transparent);
    border-top-color: currentColor;
    border-radius: 50%;
    animation: udonite-spin .65s linear infinite;
}
@keyframes udonite-spin { to { transform: rotate(360deg); } }

.app-count { display: block; margin-top: -4px; font-size: .78rem; font-variant-numeric: tabular-nums; }
.app-count.is-full { color: #d64545; font-weight: 600; }

/* Carded like the tables in the docs: a bordered, rounded surface with a tinted header row and
   rules between rows, rather than figures floating on the card behind them. */

/* Dashboard buttons light up rather than move. A hover that shifts the element nudges what you
   are aiming at out from under the cursor, and on a row of buttons the whole row appears to
   twitch. The glow is derived from each button's own colour through --glow, so a destructive
   button glows red and an accent one glows accent, without a separate hover rule per variant.

   Scoped to the dashboard shell rather than applied to every button: the site header's language
   menu and avatar sit above every page, and lighting those up made the chrome compete with
   whatever the page was showing. They keep the hovers they always had. */
.app-shell .cta,
.app-shell .cta-quiet,
.app-shell .app-danger,
.app-shell .copy {
    --glow: var(--accent);
    transition: box-shadow .3s var(--ease), background .18s var(--ease),
                border-color .18s var(--ease), color .18s var(--ease);
}

.app-shell .app-danger { --glow: #d64545; }

.app-shell .cta:hover,
.app-shell .cta-quiet:hover,
.app-shell .app-danger:hover,
.app-shell .copy:hover {
    /* Cancels the lift the same buttons keep outside the dashboard. */
    transform: none;
    filter: none;
    box-shadow:
        0 0 0 3px color-mix(in srgb, var(--glow) 14%, transparent),
        0 0 12px color-mix(in srgb, var(--glow) 26%, transparent);
}

/* Keyboard focus gets the same treatment, so the affordance is not mouse-only. */
.app-shell .cta:focus-visible,
.app-shell .cta-quiet:focus-visible,
.app-shell .app-danger:focus-visible,
.app-shell .copy:focus-visible {
    outline: none;
    box-shadow:
        0 0 0 3px color-mix(in srgb, var(--glow) 24%, transparent),
        0 0 14px color-mix(in srgb, var(--glow) 32%, transparent);
}

/* A busy button is not interactive, so it should not look it. */
.app-shell .cta.is-busy:hover, .app-shell .cta:disabled:hover { box-shadow: none; }

@media (prefers-reduced-motion: reduce) {
    .app-shell .cta, .app-shell .cta-quiet, .app-shell .app-danger, .app-shell .copy { transition: none; }
}

.app-plans-wrap {
    /* The table is a separate reading from the buttons above it - what supporting costs, then
       what it changes - so it starts further down rather than looking like their caption. */
    margin: 26px 0 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg-raised);
}
.app-plans { width: 100%; border-collapse: collapse; margin: 0; font-size: .92rem; }
.app-plans thead { background: var(--bg-soft); }
.app-plans th {
    padding: 10px 16px;
    text-align: left;
    font-weight: 620;
    color: var(--text-faint);
    font-size: .74rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
}
.app-plans td {
    padding: 11px 16px;
    text-align: left;
    border-bottom: 1px solid var(--border);
}
.app-plans tbody tr:last-child td { border-bottom: 0; }
.app-plans td:first-child { color: var(--text-soft); width: 55%; }
.app-plans th.app-num, .app-plans td.app-num { text-align: right; font-variant-numeric: tabular-nums; }

/* The column you are on is tinted straight down, so it reads as one block rather than as a
   highlight bleeding across each row. */
.app-plans .is-yours { background: var(--accent-soft); }
.app-plans th.is-yours { color: var(--accent-text); }

.app-plan-you {
    display: inline-block;
    margin-right: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--accent);
    color: #fff;
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    vertical-align: middle;
}

.app-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.app-chip .copy {
    min-width: 42px;
    height: 30px;
    padding: 0 8px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-soft);
    color: var(--text);
    font: inherit;
    font-size: .82rem;
    cursor: pointer;
}
.app-chip .copy:hover { border-color: var(--accent); color: var(--accent-text); }

/* Messages are prose, so they get room and a preview rather than a one-line value field. */
.app-message {
    width: 100%;
    min-height: 96px;
    padding: 9px 12px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    font: inherit;
    line-height: 1.6;
    resize: vertical;
}
.app-tmp-preview {
    min-height: 48px;
    padding: 12px 14px;
    margin-bottom: 8px;
    background: #10101a;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    /* Light on dark, because that is what text over a world usually sits on. */
    color: #f2f2f7;
    line-height: 1.5;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.app-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.app-actions .cta { height: 32px; padding: 0 14px; font-size: .85rem; }

.app-usage { margin-top: 8px !important; line-height: 1.6; }
.app-usage code {
    display: block;
    margin-top: 4px;
    padding: 6px 10px;
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    /* Wrapping beats a scrollbar for a one-line example: the bar sat under the paragraph and
       made the card look broken, and a URL is readable broken across lines. */
    overflow-wrap: anywhere;
    white-space: normal;
}

.app-form select,
.app-form textarea {
    padding: 9px 12px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    font: inherit;
    font-size: .92rem;
    transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.app-form select { height: 38px; }
.app-form textarea { resize: vertical; min-height: 72px; line-height: 1.5; }
.app-form select:focus,
.app-form textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-soft);
}

/* A webhook inside a destination: the tick that mutes it and the button that takes it out, on one
   row. The checkbox stretches so a row of short names still lines its buttons up on the right. */
.app-hook-row { display: flex; align-items: center; gap: 10px; }
.app-hook-row .app-check { flex: 1; }
.app-hook-row .app-danger { flex: none; }

.app-hint { margin: -6px 0 0; color: var(--text-faint); font-size: .85rem; }

/* Adding a webhook to a destination is one field and one button, which reads better beside each
   other than stacked like the multi-field forms above it. */
.app-form-row { grid-template-columns: 1fr auto; align-items: end; }
.app-form-row .cta { justify-self: start; }

/* The confirmation dialog. window.confirm rendered in the browser's own chrome, which is the one
   thing on these pages that looked like it came from somewhere else - and on a destructive step,
   looking unfamiliar is exactly wrong. */
.app-dialog {
    width: min(440px, calc(100vw - 32px));
    padding: 0;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    color: var(--text);
}
.app-dialog::backdrop { background: rgba(12, 12, 20, .46); backdrop-filter: blur(2px); }
.app-dialog-body { padding: 22px 24px 20px; }
.app-dialog h2 { margin: 0 0 10px; font-size: 1.05rem; font-weight: 620; letter-spacing: -.01em; }
.app-dialog p { margin: 0; color: var(--text-soft); font-size: .93rem; line-height: 1.55; }
.app-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding: 14px 24px;
    border-top: 1px solid var(--border);
    background: var(--bg-soft);
    border-radius: 0 0 var(--radius) var(--radius);
}
.app-dialog-actions .cta-quiet,
.app-dialog-actions .app-danger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    min-width: 104px;
    font-size: .88rem;
}
.app-dialog-actions .app-danger {
    border-color: #d64545;
    color: #fff;
    background: #d64545;
    font-weight: 560;
}
.app-dialog-actions .app-danger:hover { background: #c23c3c; border-color: #c23c3c; color: #fff; }

@media (prefers-reduced-motion: no-preference) {
    .app-dialog[open] { animation: app-dialog-in .16s var(--ease); }
    @keyframes app-dialog-in {
        from { opacity: 0; transform: scale(.97); }
        to { opacity: 1; transform: none; }
    }
}

/* Every dashboard button fills on hover. An outline button that only picked up a glow read as
   unfinished: the glow implies a lit surface, and the surface behind it was still empty. Same
   scope as the glow, so a docs page's copy button is untouched. */
.app-shell .cta-quiet:hover,
.app-shell .copy:hover,
.app-shell .app-copy-row .copy:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent) !important;
}

/* Deleting is separated from the controls above it. On a card whose rows each end in a Remove
   button, the one button that destroys the whole thing sat in the same rhythm as the rest. */
.app-card .app-meta + .app-actions {
    margin-top: 20px;
    padding-top: 18px;
    border-top: 1px solid var(--border);
}

/* The marketing page. It reuses the documentation hub's shell so the two do not look like separate
   products, with a larger lede and cards that state rather than link. */
.landing .hub-lede { max-width: 680px; }
.landing .hub-lede p { font-size: 1.16rem; line-height: 1.6; }
.landing-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }

/*
 * The packages, and the only part of the landing page that moves.
 *
 * Cards settle in rather than appear, staggered by a few tens of milliseconds so the eye reads
 * them as one group arriving instead of three unrelated events. The distance is small on purpose:
 * a landing page that throws its content around reads as a slideshow, and the second visit is
 * where a big entrance turns into a wait.
 *
 * `both` holds the opening frame, so a card cannot flash at full opacity before its delay starts.
 */
.landing-packages { margin-top: 48px; }
.landing-packages-head { max-width: 62ch; margin-bottom: 20px; }
.landing-packages-head h2 { margin: 0 0 6px; font-size: 1.35rem; letter-spacing: -.02em; }
.landing-packages-head p { margin: 0; color: var(--text-soft); }

/*
 * Set by script, never by the stylesheet. The card is visible until something is in a position to
 * make it visible again - see reveals() in theme.js.
 */
.will-reveal { opacity: 0; transform: translateY(14px); }
.will-reveal.is-revealed {
    opacity: 1;
    transform: none;
    transition: opacity .5s var(--ease), transform .5s var(--ease);
}

/* Sixty milliseconds apart, so a row reads as one group settling rather than three separate
   events. Only within a row: the delay is per position in the grid, so a card further down the
   page still starts the moment it is reached. */
.product-grid > :nth-child(2).is-revealed { transition-delay: .06s; }
.product-grid > :nth-child(3).is-revealed { transition-delay: .12s; }

/* The supporter block at the foot of the page is the only place it is asked for. A corner link
   was tried here and taken out again: on a page this short it read as a second ask rather than a
   quieter one. */

/* The package cards are links, so they lift on hover through .product-card already. This is the
   one thing they add: the accent edge, which says the whole card is the target rather than the
   words at the bottom of it. */
/*
 * The link sits on the floor of the card rather than under the text.
 *
 * A grid row already stretches its cards to a common height, so the only thing out of place was
 * the link itself: a two-line description put it higher than a three-line one beside it, and
 * three "Read the docs" at three different heights read as three unrelated boxes rather than one
 * set. The column pushes it down, so they line up whatever is written above them.
 */
.landing-packages .product-card {
    display: flex;
    flex-direction: column;
}
.landing-packages .product-card .product-cta { margin-top: auto; }

.landing-packages .product-card:hover { border-color: var(--accent); }

/*
 * Asked for motion to be left alone, so it is - every animation on the site, not only the ones
 * above. Some people get motion sickness from it and some are simply on a machine where it
 * stutters; either way the page is complete without any of it.
 */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* A card that is not a link: no hover lift, no arrow, and it must not look clickable. */
.product-card.is-static { cursor: default; }
.product-card.is-static:hover { border-color: var(--border); transform: none; box-shadow: var(--shadow); }
.product-card.is-static p:last-child { margin-bottom: 0; }


/* The documentation hub. A directory of what is written rather than a second landing page:
   the install block lives on the landing page and again in Getting started, and a third copy
   here made the two pages read as the same page. */
.doc-product { margin-top: 34px; }
.doc-product-head { display: flex; align-items: center; gap: 10px; }
.doc-product-head h2 { margin: 0; font-size: 1.24rem; letter-spacing: -.015em; }
.doc-product-head h2 a { color: var(--text); }
.doc-product-head h2 a:hover { color: var(--accent-text); text-decoration: none; }
/* The bottom margin is what separates a section's one-line description from the cards under
   it. Without it the lede and the first card touch, and the description reads as a caption
   belonging to that card rather than to the section. */
.doc-product-lede { margin: 8px 0 18px; color: var(--text-soft); font-size: .98rem; max-width: 68ch; }

.doc-product h3 {
    margin: 26px 0 10px;
    font-size: .74rem;
    font-weight: 640;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--text-faint);
}

.doc-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    /* auto-fill, not auto-fit: a section holding one page would otherwise stretch that page
       across the full width while the sections under it sat in pairs, and the ragged edge read
       as a mistake. A capped track keeps every card the same width whatever a section holds.
       The min() is what stops the 300px floor overflowing a viewport narrower than the card. */
    grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 460px));
    justify-content: start;
    gap: 10px;
}
/* The row already stretches to its tallest card; without this the link inside only takes the
   height of its own text, so a two-line description sat beside a three-line one left a card
   visibly short of the row. */
.doc-list li { display: flex; }
.doc-list li a {
    flex: 1 1 auto;
    display: block;
    padding: 14px 16px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    transition: transform .22s var(--ease), border-color .22s var(--ease), box-shadow .22s var(--ease);
}
.doc-list li a:hover {
    text-decoration: none;
    transform: translateY(-2px);
    border-color: var(--border-strong);
    box-shadow: var(--shadow);
}
.doc-list-title { display: flex; align-items: center; gap: 8px; font-weight: 560; }
.doc-list-note { display: block; margin-top: 4px; color: var(--text-soft); font-size: .9rem; }

.landing-faq { margin-top: 56px; }
.landing-faq h2 { margin: 0 0 20px; font-size: 1.35rem; letter-spacing: -.015em; }
.landing-faq dl { margin: 0; display: grid; gap: 14px; }
.faq-item { padding: 18px 20px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-raised); }
.faq-item dt { margin: 0 0 8px; font-weight: 600; font-size: 1.02rem; }
.faq-item dd { margin: 0; color: var(--text-soft); line-height: 1.6; max-width: 72ch; }

.landing-demo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: 40px; align-items: center; margin-top: 56px; }
.landing-demo-copy h2 { margin: 0 0 12px; font-size: 1.35rem; letter-spacing: -.015em; }
.landing-demo-copy p { margin: 0 0 18px; color: var(--text-soft); line-height: 1.6; }
.landing-code-points { margin: 0 0 20px; padding: 0; list-style: none; display: grid; gap: 12px; color: var(--text-soft); font-size: .95rem; line-height: 1.55; transition: color .3s var(--ease); }
.landing-code-points code { color: var(--text); font-size: .86em; }
.landing-code-points li { padding-left: 12px; border-left: 2px solid transparent; transition: border-color .3s var(--ease), color .3s var(--ease); }
.landing-code-points li.is-live { border-left-color: var(--accent); color: var(--text); }

.landing-demo-stage { display: grid; gap: 14px; }
.demo-screens { display: grid; grid-template-columns: minmax(0, 1fr) 44px minmax(0, 1fr) minmax(0, 1fr); gap: 10px; align-items: stretch; }
.demo-screen {
    position: relative;
    display: grid;
    justify-items: center;
    align-content: center;
    gap: 10px;
    padding: 18px 12px 14px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.demo-name { position: absolute; top: 8px; left: 10px; font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; color: var(--text-faint); }
.demo-cube {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: linear-gradient(160deg, var(--accent), var(--accent-soft));
    box-shadow: 0 6px 16px -8px var(--accent);
    transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.demo-screen.is-pressing .demo-cube { transform: scale(.86); box-shadow: 0 0 0 6px var(--accent-soft); }
.demo-label { font-family: "JetBrains Mono", ui-monospace, Consolas, monospace; font-size: 1.5rem; font-weight: 600; line-height: 1; }
.demo-label.is-changed { animation: demo-pop .5s var(--ease); }
@keyframes demo-pop { 0% { transform: translateY(6px); opacity: .2; } 100% { transform: none; opacity: 1; } }
.demo-link { position: relative; align-self: center; height: 2px; background: var(--border); border-radius: 1px; }
.demo-pulse { position: absolute; top: -4px; left: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--accent); opacity: 0; }
.demo-pulse.is-travelling { animation: demo-travel .9s var(--ease) forwards; }
.is-reversed .demo-pulse.is-travelling { animation-direction: reverse; }
@keyframes demo-travel { 0% { left: 0; opacity: 0; } 15% { opacity: 1; } 85% { opacity: 1; } 100% { left: calc(100% - 10px); opacity: 0; } }
.demo-joiner .demo-name { color: var(--accent-text); }
.demo-joiner.is-away { border-style: dashed; background: transparent; }
.demo-joiner.is-away .demo-cube, .demo-joiner.is-away .demo-label { opacity: 0; transform: translateY(6px); }
.demo-joiner .demo-cube, .demo-joiner .demo-label { transition: opacity .45s var(--ease), transform .45s var(--ease); }
.demo-joiner.is-arriving .demo-cube, .demo-joiner.is-arriving .demo-label { opacity: 1; transform: none; }

.demo-code { display: grid; gap: 8px; }
.demo-line {
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-left: 3px solid var(--border);
    border-radius: var(--radius-sm);
    overflow-x: auto;
    transition: border-color .3s var(--ease), opacity .3s var(--ease);
}
.demo-line pre { margin: 0; padding: 10px 14px; font-size: .78rem; line-height: 1.45; background: none; border: 0; }
.demo-line pre code { padding: 0; background: none; border: 0; tab-size: 4; }
.landing-demo.is-animated .demo-line:not(.is-live) { opacity: .55; }
.demo-line.is-live { border-left-color: var(--accent); opacity: 1; }
@media (max-width: 820px) {
    .landing-demo { grid-template-columns: 1fr; }
    .demo-screens { grid-template-columns: minmax(0, 1fr) 30px minmax(0, 1fr) minmax(0, 1fr); }
    /* The narrower columns leave too little width for the absolutely-positioned name to sit
       above the cube without overlapping it - put it back in normal flow instead. */
    .demo-name { position: static; margin: 0 0 2px; }
    .demo-screen { padding-top: 14px; }
}
.faq-item dd a { color: var(--accent-text); text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 3px; }
.faq-item dd a:hover { text-decoration-color: currentColor; }
.product-card.is-static .product-cta { display: inline-block; margin-top: 12px; }
