/* The two shells: the signed in app (views/layouts/app.php) and the sign in
   shell (views/layouts/auth.php), plus the page header every screen starts
   with. Loaded after components.css, because the shells place components
   and sometimes adjust them.

   Two breakpoints decide the app shell (D74). Below 640 pixels it is a
   phone's: no sidebar, the page under its own title, and a bar of glass at
   the bottom. From 640 pixels a fixed sidebar stands beside the page: up to
   1023 pixels as its rail of icons, which opens over the page for a moment
   (html.sidebar-open), and from 1024 pixels whole unless this device folded
   it (data-sidebar on <html>, from a cookie). Media queries cannot read custom properties, so
   the numbers are repeated; search for 640px and 1024px. */

/* ------------------------------------------------------------------------
   Lockup: the mark and the product name. Used in the sidebar and on the
   sign in panel.
   ------------------------------------------------------------------------ */

.lockup {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    color: var(--color-text);
    text-decoration: none;
    border-radius: var(--radius-sm);
}

/* A link on phones too: tall enough to tap, the mark centred in it. */
@media (pointer: coarse) {
    .lockup {
        min-height: 44px;
    }
}

.lockup-mark {
    display: grid;
    place-items: center;
    flex: none;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    background: var(--color-text);
    color: var(--color-surface);
}

.lockup-mark .icon {
    width: 18px;
    height: 18px;
    stroke-width: 2.5;
}

.lockup-name {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.02em;
}

/* ------------------------------------------------------------------------
   Sidebar, from 640 pixels. One element, fixed beside the page, a container
   of its own: whether it shows as a rail is read from its width (the
   container query below), so the conditions only ever set the width, and a
   fold animates the width and nothing else.

   The rows are calm: 32 pixels, 16 pixel icons, a weight between regular
   and medium, the open page a grey chip. Every row keeps its icon at the
   same place in both widths, the middle of the rail, so nothing jumps when
   it folds.
   ------------------------------------------------------------------------ */

.sidebar {
    display: none;
}

@media (min-width: 640px) {
    .sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        z-index: var(--z-sidebar);
        display: flex;
        flex-direction: column;
        width: var(--sidebar-width);
        container: sidebar / inline-size;
        background: var(--color-surface);
        border-right: 1px solid var(--color-border);
    }

    .app-content {
        margin-left: var(--sidebar-width);
    }

    /* Only a fold the person asked for moves; a page loads in its width. */
    .is-folding .sidebar,
    .is-folding .app-content {
        transition: width var(--duration-normal) var(--ease-out),
                    margin-left var(--duration-normal) var(--ease-out);
    }
}

/* Narrower than 1024 pixels the page keeps its room: the rail, which opens
   over the page rather than pushing it into a narrow column. */
@media (min-width: 640px) and (max-width: 1023px) {
    .sidebar {
        width: var(--rail-width);
    }

    .app-content {
        margin-left: var(--rail-width);
    }

    html.sidebar-open .sidebar {
        width: var(--sidebar-width);
        box-shadow: var(--shadow-lg);
    }
}

@media (min-width: 1024px) {
    html[data-sidebar="collapsed"] .sidebar {
        width: var(--rail-width);
    }

    html[data-sidebar="collapsed"] .app-content {
        margin-left: var(--rail-width);
    }
}

.sidebar-head {
    position: relative;
    display: flex;
    flex: none;
    align-items: center;
    height: 56px;
    padding: 0 var(--space-3) 0 var(--space-4);
    overflow: hidden;
}

.sidebar .lockup {
    min-width: 0;
}

.sidebar .lockup-mark {
    width: 28px;
    height: 28px;
}

.sidebar .lockup-mark .icon {
    width: 16px;
    height: 16px;
}

.sidebar .lockup-name {
    font-size: var(--text-md);
    white-space: nowrap;
    transition: opacity var(--duration-fast) var(--ease-in-out);
}

/* Fold, beside the lockup; unfold, over the mark in the rail, where the
   mark gives way to it under the pointer or the keyboard's focus. Both
   appear once app.js can act on them. */
.sidebar-fold,
.sidebar-unfold {
    position: absolute;
    top: 14px;
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--color-text-subtle);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-in-out),
                color var(--duration-fast) var(--ease-in-out),
                opacity var(--duration-fast) var(--ease-in-out);
}

.sidebar-fold {
    right: 10px;
}

.sidebar-unfold {
    left: 16px;
    visibility: hidden;
    background: var(--color-surface);
    color: var(--color-text);
    opacity: 0;
}

.sidebar-fold .icon,
.sidebar-unfold .icon {
    width: 16px;
    height: 16px;
}

.sidebar-unfold .icon {
    width: 18px;
    height: 18px;
}

@media (hover: hover) {
    .sidebar-fold:hover {
        background: var(--color-surface-hover);
        color: var(--color-text);
    }
}

.sidebar-search {
    display: flex;
    flex: none;
    align-items: center;
    gap: 9px;
    height: 32px;
    margin: 0 var(--space-3) var(--space-2);
    padding: 0 5px 0 9px;
    overflow: hidden;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-canvas);
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
    white-space: nowrap;
    text-decoration: none;
    transition: border-color var(--duration-fast) var(--ease-in-out),
                color var(--duration-fast) var(--ease-in-out),
                background-color var(--duration-fast) var(--ease-in-out);
}

.sidebar-search .icon {
    width: 16px;
    height: 16px;
}

.sidebar-search-label {
    flex: 1;
    transition: opacity var(--duration-fast) var(--ease-in-out);
}

/* The keys of a shortcut: the search's ⌘K, the search dialog's foot, the
   rail's names on hover. */
.key,
.sidebar-search-key,
.search-dialog kbd {
    display: inline-grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border: 1px solid var(--color-border);
    border-radius: 5px;
    background: var(--color-surface);
    color: var(--color-text-subtle);
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    line-height: 1;
}

@media (hover: hover) {
    .sidebar-search:hover {
        border-color: var(--color-border-strong);
        color: var(--color-text-muted);
    }
}

/* The navigation, in its groups with a gap between them, the second
   named. It fills the height the account menu leaves and scrolls on a
   short screen. */
.sidebar-nav {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-1) var(--space-3) var(--space-3);
}

.nav-group + .nav-group {
    margin-top: 18px;
}

.nav-label {
    position: relative;
    display: flex;
    align-items: center;
    height: 28px;
    padding: 0 10px;
    color: var(--color-text-subtle);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    white-space: nowrap;
}

.nav-label span {
    transition: opacity var(--duration-fast) var(--ease-in-out);
}

/* In the rail the name gives way to a line. */
.nav-label::before {
    content: '';
    position: absolute;
    top: 50%;
    right: 10px;
    left: 10px;
    height: 1px;
    background: var(--color-border-strong);
    opacity: 0;
    transition: opacity var(--duration-fast) var(--ease-in-out);
}

/* One column that may shrink below its rows' names, so a row is never
   wider than the rail. */
.nav-list,
.nav-sub {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1px;
}

.nav-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    height: 32px;
    padding: 0 9px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    font-weight: 450;
    white-space: nowrap;
    text-decoration: none;
    transition: background-color var(--duration-fast) var(--ease-in-out),
                color var(--duration-fast) var(--ease-in-out);
}

.nav-link .icon {
    width: 16px;
    height: 16px;
    color: var(--color-text-subtle);
    transition: color var(--duration-fast) var(--ease-in-out);
}

.nav-text {
    overflow: hidden;
    text-overflow: ellipsis;
    transition: opacity var(--duration-fast) var(--ease-in-out);
}

@media (hover: hover) {
    .nav-link:hover {
        background: var(--color-surface-hover);
        color: var(--color-text);
    }

    .nav-link:hover .icon {
        color: var(--color-text-muted);
    }
}

/* The current area: its chip, with text and icon in the full text colour.
   aria-current is "page" on the page the entry leads to and "true" on the
   area's other pages; both look the same. An area whose own page below it
   is open (is-ancestor) only darkens, the page below wears the chip. */
.nav-link[aria-current] {
    color: var(--color-text);
}

.nav-link[aria-current] .icon {
    color: var(--color-text);
}

.nav-link[aria-current]:not(.is-ancestor) {
    background: var(--color-surface-selected);
    font-weight: 550;
}

/* AI Copilot: the entry, the arrow beside it, and its pages under it. */
.nav-parent {
    position: relative;
}

.nav-parent > .nav-link {
    padding-right: 34px;
}

.nav-caret {
    position: absolute;
    top: 4px;
    right: 4px;
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--color-text-subtle);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-in-out),
                color var(--duration-fast) var(--ease-in-out),
                opacity var(--duration-fast) var(--ease-in-out);
}

.nav-caret .icon {
    width: 14px;
    height: 14px;
    transition: transform var(--duration-normal) var(--ease-out);
}

.nav-parent.is-open .nav-caret .icon {
    transform: rotate(90deg);
}

@media (hover: hover) {
    .nav-caret:hover {
        background: var(--color-surface-selected);
        color: var(--color-text);
    }
}

.nav-sub {
    display: none;
    margin: 2px 0 3px 17px;
    padding-left: 9px;
    border-left: 1px solid var(--color-border-strong);
}

.nav-parent.is-open > .nav-sub {
    display: grid;
}

.nav-sub .nav-link {
    height: 30px;
    font-size: var(--text-sm);
}

@media (pointer: coarse) {
    .nav-link,
    .nav-sub .nav-link {
        height: 44px;
    }

    .nav-caret {
        top: 6px;
        width: 32px;
        height: 32px;
    }
}

/* The account menu at the foot of the sidebar: the real person, always,
   also while viewing as someone else. One button, the whole row, opens a
   small menu above it with the theme, the settings and signing out; in the
   rail the menu opens beside it.

   A <details> element, so it opens and closes without script; app.js adds
   Escape and a click outside. */
.sidebar-user {
    position: relative;
    flex: none;
    padding: var(--space-2) var(--space-3) var(--space-3);
    border-top: 1px solid var(--color-border);
}

.user-menu-viewing {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    background: var(--color-surface-muted);
    color: var(--color-text);
    font-size: var(--text-sm);
    white-space: nowrap;
}

.user-menu-viewing .icon {
    flex: none;
    width: 1rem;
    height: 1rem;
    color: var(--color-text-muted);
}

.user-menu-viewing span {
    overflow: hidden;
    text-overflow: ellipsis;
}

.user-menu-button {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: var(--space-1) var(--space-2) var(--space-1) 2px;
    border-radius: var(--radius-sm);
    list-style: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--duration-fast) var(--ease-in-out);
}

/* Safari draws the disclosure triangle through its own pseudo element. */
.user-menu-button::-webkit-details-marker {
    display: none;
}

@media (hover: hover) {
    .user-menu-button:hover {
        background: var(--color-surface-hover);
    }
}

.user-menu[open] > .user-menu-button {
    background: var(--color-surface-selected);
}

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

.user-menu-text {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-width: 0;
    line-height: 1.3;
}

.user-menu-name,
.user-menu-email {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.user-menu-name {
    color: var(--color-text);
    font-size: var(--text-sm);
    font-weight: 550;
}

.user-menu-email {
    font-size: var(--text-xs);
    color: var(--color-text-subtle);
}

.user-menu-chevron {
    flex: none;
    width: 15px;
    height: 15px;
    color: var(--color-text-subtle);
}

.user-menu-panel {
    position: absolute;
    right: var(--space-3);
    bottom: calc(100% - var(--space-1));
    left: var(--space-3);
    z-index: 1;
    padding: var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-lg);
    transform-origin: bottom center;
    transition: opacity var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}

/* Rises into place when it opens. Browsers without @starting-style show it
   at once, which is just as usable. */
@starting-style {
    .user-menu[open] .user-menu-panel {
        opacity: 0;
        transform: translateY(6px) scale(0.98);
    }
}

.user-menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: 36px;
    padding: 0 var(--space-3);
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--color-text);
    font: inherit;
    font-weight: 450;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-in-out);
}

.user-menu-item .icon {
    width: 16px;
    height: 16px;
    color: var(--color-text-subtle);
}

@media (hover: hover) {
    .user-menu-item:hover {
        background: var(--color-surface-hover);
    }

    .user-menu-item:hover .icon {
        color: var(--color-text-muted);
    }
}

/* Settings, while a settings page is on screen: "page" at /settings, "true"
   on its sections, marked alike, as the sidebar's entries are. */
.user-menu-item[aria-current] {
    background: var(--color-surface-selected);
}

.user-menu-item[aria-current] .icon {
    color: var(--color-text);
}

/* The switcher's agency that cannot be entered now, a paused one: shown,
   never a button. [Phase 6, section 7.3] */
.user-menu-item.is-muted {
    color: var(--color-text-subtle);
    cursor: default;
}

.user-menu-divider {
    height: 1px;
    margin: var(--space-2) 0;
    border: 0;
    background: var(--color-border);
}

.user-menu-theme {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    min-height: 40px;
    padding: 0 var(--space-1) 0 var(--space-3);
}

.user-menu-label {
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
}

/* The same look as the segmented control of Preferences in Settings: a grey track,
   the chosen option raised on it. */
.theme-switch {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface-muted);
}

.theme-switch-button {
    display: grid;
    place-items: center;
    width: 32px;
    height: 28px;
    padding: 0;
    border: 0;
    /* Concentric with the track: its radius minus its padding. */
    border-radius: calc(var(--radius-sm) - 3px);
    background: transparent;
    color: var(--color-text-subtle);
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-in-out),
                color var(--duration-fast) var(--ease-in-out);
}

.theme-switch-button .icon {
    width: 1rem;
    height: 1rem;
}

@media (hover: hover) {
    .theme-switch-button:hover {
        color: var(--color-text);
    }
}

.theme-switch-button[aria-pressed="true"] {
    background: var(--color-surface-raised);
    color: var(--color-text);
    box-shadow: var(--shadow-sm);
}

.theme-switch-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

@media (pointer: coarse) {
    .user-menu-item {
        min-height: 44px;
    }

    .theme-switch-button {
        width: 44px;
        height: 44px;
    }
}

/* The rail: what has no room is hidden, from the sidebar's own width. The
   names stay in the page for screen readers; app.js shows each as a
   tooltip on hover and focus, and AI Copilot's pages in a menu beside it. */
@container sidebar (width < 120px) {
    .sidebar .lockup-name,
    .sidebar-search-label,
    .sidebar-search-key,
    .nav-text,
    .nav-label span {
        opacity: 0;
    }

    .nav-label::before {
        opacity: 1;
    }

    .sidebar-fold,
    .nav-caret {
        visibility: hidden;
        opacity: 0;
    }

    .nav-parent.is-open > .nav-sub,
    .user-menu-viewing,
    .user-menu-chevron {
        display: none;
    }

    /* Out of sight, still the button's name for a screen reader. */
    .user-menu-text {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .sidebar-unfold {
        visibility: visible;
    }

    .sidebar-unfold:hover,
    .sidebar-unfold:focus-visible {
        opacity: 1;
    }

    /* Square chips; the area wears its own when one of its pages is open,
       since the pages are out of sight. */
    .nav-link {
        height: 36px;
        border-radius: 10px;
    }

    .nav-parent > .nav-link {
        padding-right: 9px;
    }

    .nav-link.is-ancestor {
        background: var(--color-surface-selected);
        font-weight: 550;
    }

    .sidebar-search {
        height: 36px;
        border-color: transparent;
        border-radius: 10px;
        background: transparent;
    }

    .user-menu-panel {
        right: auto;
        bottom: 0;
        left: calc(100% + var(--space-2));
        width: 232px;
        transform-origin: bottom left;
    }
}

@container sidebar (width < 120px) {
    @media (hover: hover) {
        .sidebar-search:hover {
            background: var(--color-surface-hover);
            color: var(--color-text);
        }
    }
}

/* A name in the rail on hover and focus, and AI Copilot's pages beside
   it (app.js). Fixed, outside the sidebar, which scrolls and would cut
   them off. */
.nav-tip {
    position: fixed;
    z-index: calc(var(--z-sidebar) + 1);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 5px 9px;
    border-radius: 7px;
    background: var(--color-tooltip-bg);
    box-shadow: var(--shadow-sm);
    color: var(--color-tooltip-fg);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    white-space: nowrap;
    pointer-events: none;
}

.nav-tip .key {
    min-width: 18px;
    height: 18px;
    border-color: transparent;
    background: color-mix(in srgb, var(--color-tooltip-fg) 22%, transparent);
    color: inherit;
}

/* ------------------------------------------------------------------------
   The page beside the sidebar
   ------------------------------------------------------------------------ */

.app-content {
    min-width: 0;
}

.main {
    display: block;
    padding: var(--space-6) var(--gutter) var(--space-16);
}

.container {
    max-width: var(--content-max);
    margin: 0 auto;
}

.app-body [id] {
    scroll-margin-top: var(--space-6);
}

@media (min-width: 640px) {
    .main {
        padding: var(--space-8) var(--space-8) var(--space-16);
    }
}

@media (min-width: 1024px) {
    .main {
        padding: var(--space-10) var(--space-10) var(--space-16);
    }
}

/* Shown on every page while viewing as someone. Above the content rather
   than fixed over it, so it never covers a form on a small phone. */
.impersonation-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-4);
    padding: var(--space-2) var(--gutter);
    border-bottom: 1px solid var(--color-warning-border);
    background: var(--color-warning-bg);
    color: var(--color-warning-text);
    font-size: var(--text-sm);
}

/* The text takes what is left and wraps, so Exit stays beside it even on a
   narrow phone. */
.impersonation-text {
    display: flex;
    flex: 1 1 0;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.impersonation-text .icon {
    width: 1.125rem;
    height: 1.125rem;
}

.impersonation-banner form {
    display: flex;
    flex: none;
}

@media (min-width: 640px) {
    .impersonation-banner {
        padding: var(--space-2) var(--space-8);
    }
}

@media (min-width: 1024px) {
    .impersonation-banner {
        padding: var(--space-2) var(--space-10);
    }
}

/* ------------------------------------------------------------------------
   The phone, below 640 pixels (D74): the page under its own large title,
   no bar above it. A bar of glass floats at the bottom with the tabs and
   More, the round search button beside it; a page's way back is a round
   button in the top left corner; once the title has scrolled away it
   shows small in the middle of the top edge.

   Glass only on what floats over the page, after iOS 26 (tokens.css): a
   tint, a blur, a rim of light, a glow at the edge, a wide shadow. The
   bending of light at its edges is left out: Safari cannot do it on a web
   page.

   Search, as in iOS 26: the round button stretches into a field at the
   bottom, the tabs fold into a round X that closes it, and the results
   cover the page (html.is-searching, app.js).
   ------------------------------------------------------------------------ */

.phone-top,
.phone-search,
.tabbar,
.tabbar-search {
    display: none;
}

@media (max-width: 639px) {
    .main {
        padding: calc(env(safe-area-inset-top, 0px) + var(--space-3)) var(--gutter) calc(env(safe-area-inset-bottom, 0px) + 112px);
    }

    /* Room for the round way back above the title. */
    .main:has(.page-back) .container {
        padding-top: 52px;
    }

    .app-body [id] {
        scroll-margin-top: calc(env(safe-area-inset-top, 0px) + 68px);
    }

    .glass,
    .page-back {
        background: linear-gradient(180deg, var(--glass-tint), transparent 60%), var(--glass-bg);
        -webkit-backdrop-filter: blur(16px) saturate(1.9);
        backdrop-filter: blur(16px) saturate(1.9);
        box-shadow: var(--glass-inner), 0 0 0 0.5px var(--glass-edge), var(--glass-shadow);
    }

    /* The rim: a ring of light one pixel wide. */
    .glass::after,
    .page-back::after {
        content: '';
        position: absolute;
        inset: 0;
        padding: 1px;
        border-radius: inherit;
        background: var(--glass-rim);
        -webkit-mask: linear-gradient(black 0 0) content-box, linear-gradient(black 0 0);
        -webkit-mask-composite: xor;
        mask-composite: exclude;
        pointer-events: none;
    }

    a.page-back,
    a.page-back.settings-back {
        position: fixed;
        top: calc(env(safe-area-inset-top, 0px) + 8px);
        left: 12px;
        z-index: calc(var(--z-phone-top) + 1);
        display: grid;
        place-items: center;
        width: 44px;
        height: 44px;
        min-height: 44px;
        margin: 0;
        border-radius: var(--radius-full);
        color: var(--color-text);
    }

    /* While viewing as someone the banner stands at the top of the page:
       the way back sits below it and scrolls with the page. */
    .main {
        position: relative;
    }

    body:has(.impersonation-banner) a.page-back {
        position: absolute;
        top: var(--space-2);
    }

    .page-back .icon {
        width: 20px;
        height: 20px;
    }

    .page-back-label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .phone-top {
        position: fixed;
        top: 0;
        right: 0;
        left: 0;
        z-index: var(--z-phone-top);
        display: flex;
        align-items: center;
        justify-content: center;
        height: calc(env(safe-area-inset-top, 0px) + 60px);
        padding: calc(env(safe-area-inset-top, 0px) + 8px) 72px 8px;
        opacity: 0;
        pointer-events: none;
        transition: opacity 180ms var(--ease-in-out);
    }

    /* The edge the page fades under, blurred towards the top. */
    .phone-top::before {
        content: '';
        position: absolute;
        inset: 0 0 -16px;
        z-index: -1;
        background: linear-gradient(to bottom, var(--color-canvas) 0%, color-mix(in srgb, var(--color-canvas) 72%, transparent) 60%, transparent);
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
        -webkit-mask-image: linear-gradient(to bottom, black 55%, transparent);
        mask-image: linear-gradient(to bottom, black 55%, transparent);
    }

    html.is-scrolled .phone-top {
        opacity: 1;
    }

    .phone-top-title {
        overflow: hidden;
        font-size: var(--text-md);
        font-weight: var(--weight-semibold);
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* The page fades out under the bar instead of meeting its edge. */
    .app-body::after {
        content: '';
        position: fixed;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: calc(var(--z-tabbar) - 1);
        height: calc(env(safe-area-inset-bottom, 0px) + 96px);
        background: linear-gradient(to top, color-mix(in srgb, var(--color-canvas) 70%, transparent) 15%, transparent);
        pointer-events: none;
    }

    .tabbar {
        position: fixed;
        right: 88px;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 10px + var(--keyboard, 0px));
        left: 16px;
        z-index: var(--z-tabbar);
        display: flex;
        height: 62px;
        padding: 4px;
        border-radius: 31px;
        touch-action: none;
        -webkit-user-select: none;
        user-select: none;
        transition: right 420ms var(--ease-sheet);
    }

    /* Behind the open tab. While a tab is held it lifts into a clear drop
       that follows the finger (is-pressing, app.js). */
    .tabbar-lens {
        position: absolute;
        top: 4px;
        bottom: 4px;
        left: 0;
        width: 0;
        border-radius: 27px;
        background: var(--tabbar-lens);
        opacity: 0;
        pointer-events: none;
        transition: transform 380ms var(--ease-lens), width 380ms var(--ease-lens), scale 300ms var(--ease-lens),
                    background-color 200ms, box-shadow 200ms, opacity 160ms;
    }

    .tabbar-lens.is-on {
        opacity: 1;
    }

    .tabbar-lens::before {
        content: '';
        position: absolute;
        inset: -1px;
        padding: 1.5px;
        border-radius: inherit;
        background: var(--drop-iris);
        opacity: 0;
        -webkit-mask: linear-gradient(black 0 0) content-box, linear-gradient(black 0 0);
        -webkit-mask-composite: xor;
        mask-composite: exclude;
        transition: opacity 200ms;
    }

    .tabbar.is-pressing .tabbar-lens {
        background: var(--drop-bg);
        box-shadow: var(--drop-shadow), inset 0 0 0 1px var(--drop-ring), inset 0 0 12px var(--drop-glow);
        scale: 1.16 1.24;
        transition: transform 120ms var(--ease-out), width 300ms var(--ease-lens), scale 300ms var(--ease-lens),
                    background-color 200ms, box-shadow 200ms, opacity 160ms;
    }

    .tabbar.is-pressing .tabbar-lens::before {
        opacity: var(--drop-iris-opacity);
    }

    /* The tabs share the bar equally, and a label is never cut: a tab is
       at least as wide as its label, so a long one takes what it needs
       from the others, whatever font the phone draws it in. At 10 pixels,
       iOS's own size, "Dashboard" is 53 pixels wide in Inter: the four
       share the bar equally from 330 pixels wide (62 each at 360), and at
       320 Dashboard takes a pixel and a half from the others (measured on
       14 October 2026). */
    .tabbar-item {
        position: relative;
        z-index: 1;
        display: flex;
        flex: 1;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        min-width: max-content;
        border-radius: 27px;
        color: var(--tabbar-ink);
        font-size: 10px;
        font-weight: var(--weight-semibold);
        letter-spacing: 0.005em;
        line-height: 1.15;
        text-decoration: none;
        -webkit-touch-callout: none;
        -webkit-user-drag: none;
        transition: opacity 120ms;
    }

    .tabbar-item[aria-current] {
        color: var(--tabbar-ink-open);
    }

    .tabbar-label {
        white-space: nowrap;
        transition: transform 260ms var(--ease-lens);
    }

    .tabbar-icon {
        position: relative;
        width: 26px;
        height: 26px;
        transition: transform 260ms var(--ease-lens);
    }

    .tabbar-icon .icon {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
    }

    .tabbar-open,
    .tabbar-item[aria-current] .tabbar-closed {
        opacity: 0;
    }

    .tabbar-item[aria-current] .tabbar-open {
        opacity: 1;
    }

    .tabbar-item.is-under .tabbar-icon,
    .tabbar-item.is-under .tabbar-label {
        transform: scale(1.1);
    }

    .tabbar-close {
        position: absolute;
        inset: 0;
        display: grid;
        place-items: center;
        padding: 0;
        border: 0;
        border-radius: inherit;
        background: none;
        color: var(--tabbar-ink-open);
        opacity: 0;
        pointer-events: none;
        cursor: pointer;
        transition: opacity 120ms;
    }

    .tabbar-close .icon {
        width: 24px;
        height: 24px;
    }

    .tabbar-search {
        position: fixed;
        right: 16px;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 10px + var(--keyboard, 0px));
        z-index: var(--z-tabbar);
        display: block;
        width: 62px;
        height: 62px;
        border-radius: 31px;
        transition: width 420ms var(--ease-sheet), scale 260ms var(--ease-lens);
    }

    html:not(.is-searching) .tabbar-search:active {
        scale: 1.07;
    }

    .tabbar-search-button {
        position: absolute;
        top: 0;
        left: 0;
        display: grid;
        place-items: center;
        width: 62px;
        height: 62px;
        border-radius: 31px;
        color: var(--tabbar-ink-open);
    }

    .tabbar-search-button .icon {
        width: 24px;
        height: 24px;
    }

    /* 17 pixels, a phone's own size for typing, which no phone zooms into. */
    .tabbar-search-input {
        position: absolute;
        top: 0;
        right: 16px;
        bottom: 0;
        left: 52px;
        min-width: 0;
        border: 0;
        outline: none;
        background: none;
        color: var(--color-text);
        font: inherit;
        font-size: 17px;
        opacity: 0;
        pointer-events: none;
        transition: opacity 120ms;
    }

    .tabbar-search-input::placeholder {
        color: var(--color-text-subtle);
    }

    html.is-searching .tabbar {
        right: calc(100% - 78px);
        overflow: hidden;
    }

    html.is-searching .tabbar-item,
    html.is-searching .tabbar-lens {
        opacity: 0;
        pointer-events: none;
    }

    html.is-searching .tabbar-close {
        opacity: 1;
        pointer-events: auto;
        transition: opacity 180ms 160ms;
    }

    html.is-searching .tabbar-search {
        width: calc(100% - 104px);
    }

    html.is-searching .tabbar-search-input {
        opacity: 1;
        pointer-events: auto;
        transition: opacity 180ms 180ms;
    }

    .phone-search:not([hidden]) {
        position: fixed;
        inset: 0;
        z-index: var(--z-phone-search);
        display: block;
        padding: calc(env(safe-area-inset-top, 0px) + var(--space-2)) var(--gutter) calc(env(safe-area-inset-bottom, 0px) + 120px + var(--keyboard, 0px));
        overflow-y: auto;
        overscroll-behavior: contain;
        background: var(--color-canvas);
        opacity: 0;
        transition: opacity 220ms var(--ease-out);
    }

    html.is-searching .phone-search {
        opacity: 1;
    }

    /* The search's large title, a page's on a phone (D102). */
    .phone-search-title {
        display: flex;
        align-items: center;
        min-height: 44px;
        margin-bottom: var(--space-1);
        font-family: var(--font-display);
        font-size: var(--text-3xl);
        letter-spacing: -0.025em;
    }

    .phone-search .search-row {
        min-height: 52px;
        padding-inline: var(--space-2);
    }

    .phone-search .search-label {
        padding-inline: var(--space-2);
    }
}

/* ------------------------------------------------------------------------
   More, on a phone: the rest of the person's areas, the person, Settings,
   the theme and Sign out, in the grouped rows of the settings. The window
   of D73 as a sheet. Without script #more is the address it shows at.
   ------------------------------------------------------------------------ */

.nav-more {
    background: var(--color-canvas);
}

.nav-more-body {
    padding-top: 0;
}

.nav-more-body > .set-group + .set-group,
.nav-more-body > .set-group + .set-group-title {
    margin-top: var(--space-5);
}

.nav-more-theme {
    min-height: 52px;
}

.nav-more:target:not([open]) {
    position: fixed;
    inset: auto 0 0;
    z-index: var(--z-dialog);
    display: flex;
    flex-direction: column;
}

/* ------------------------------------------------------------------------
   Search: the dialog of a wide screen (also ⌘K) and the phone's search
   screen share their list. Before anything is typed: AI Copilot's
   question, which comes later, and every area; from two characters what
   the search of Models & Accounts finds (app.js).
   ------------------------------------------------------------------------ */

.search-dialog {
    width: min(600px, calc(100vw - 48px));
    max-width: none;
    max-height: min(540px, 76vh);
    margin: 12vh auto auto;
    padding: 0;
    overflow: hidden;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-dialog);
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: var(--shadow-dialog);
}

.search-dialog[open] {
    display: flex;
    flex-direction: column;
}

.search-dialog::backdrop {
    background: var(--color-overlay);
    -webkit-backdrop-filter: blur(var(--backdrop-blur));
    backdrop-filter: blur(var(--backdrop-blur));
}

@media (prefers-reduced-motion: no-preference) {
    .search-dialog[open] {
        animation: dialog-in 180ms var(--ease-out) backwards;
    }

    .search-dialog[open]::backdrop {
        animation: dialog-fade-in 160ms var(--ease-in-out) backwards;
    }
}

.search-field {
    display: flex;
    flex: none;
    align-items: center;
    gap: 10px;
    height: 54px;
    padding: 0 14px 0 16px;
    border-bottom: 1px solid var(--color-border);
    color: var(--color-text-subtle);
}

.search-field .icon {
    width: 18px;
    height: 18px;
}

.search-field-input {
    flex: 1;
    min-width: 0;
    border: 0;
    outline: none;
    background: none;
    color: var(--color-text);
    font: inherit;
    font-size: var(--text-md);
}

.search-field-input::placeholder {
    color: var(--color-text-subtle);
}

.search-dialog .search-list {
    flex: 1;
    min-height: 0;
    padding: 6px;
    overflow-y: auto;
}

.search-label {
    padding: 10px 10px 4px;
    color: var(--color-text-subtle);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
}

.search-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 44px;
    padding: 6px 10px;
    border-radius: var(--radius-sm);
    color: var(--color-text);
    text-decoration: none;
}

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

@media (hover: hover) {
    a.search-row:hover {
        background: var(--color-surface-selected);
    }
}

.search-row.is-soon {
    color: var(--color-text-muted);
    cursor: default;
}

.search-mark {
    display: grid;
    place-items: center;
    flex: none;
    width: 30px;
    height: 30px;
    overflow: hidden;
    border: 1px solid var(--mark-border, var(--color-border));
    border-radius: var(--radius-sm);
    background: var(--mark-bg, var(--color-surface-muted));
    color: var(--mark-fg, var(--color-text-muted));
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
}

/* An icon, or a result's platform mark from the results page, in the box,
   in its brand's colours where it has them (the mark's platform-<key>,
   which app.js carries over); a model's picture or portrait fills it. A
   platform's mark is filled, the icons stroked. */
.search-mark > svg {
    width: 16px;
    height: 16px;
}

.search-mark > .glyph {
    fill: currentColor;
}

.search-mark > .inv-avatar {
    width: 100%;
    height: 100%;
    border: 0;
    border-radius: 0;
}

.search-mark.is-ai {
    border-color: transparent;
    background: var(--color-primary);
    color: var(--color-on-primary);
}

/* "Soon" beside AI Copilot's question, an outline pill. */
.search-soon {
    flex: none;
    padding: 1px 8px;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-full);
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
}

.search-row-main {
    display: grid;
    flex: 1;
    min-width: 0;
    line-height: 1.35;
}

.search-row-title,
.search-row-line {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.search-row-title {
    font-weight: var(--weight-medium);
}

.search-row-line {
    color: var(--color-text-subtle);
    font-size: var(--text-xs);
}

.search-row-meta {
    display: flex;
    flex: none;
    gap: var(--space-1);
}

.search-empty {
    padding: var(--space-6) var(--space-3);
    color: var(--color-text-muted);
    text-align: center;
}

.search-foot {
    display: flex;
    flex: none;
    gap: var(--space-4);
    margin: 0;
    padding: 9px 14px;
    border-top: 1px solid var(--color-border);
    background: var(--color-canvas);
    color: var(--color-text-subtle);
    font-size: var(--text-xs);
}

.search-foot span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* ------------------------------------------------------------------------
   Page header: where am I, and what can I do here.
   ------------------------------------------------------------------------ */

.page-header {
    margin-bottom: var(--space-6);
}

.page-back {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-height: 32px;
    margin-bottom: var(--space-2);
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    text-decoration: none;
}

.page-back .icon {
    width: 1rem;
    height: 1rem;
}

@media (hover: hover) {
    .page-back:hover {
        color: var(--color-text);
    }
}

@media (pointer: coarse) {
    .page-back {
        min-height: 44px;
        margin-top: calc(-1 * var(--space-2));
        margin-bottom: 0;
    }
}

.page-header-row {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.page-title {
    font-size: clamp(var(--text-2xl), 1.2rem + 1vw, var(--text-3xl));
    letter-spacing: -0.025em;
    overflow-wrap: anywhere;
}

/* A phone's large title: the page starts with it, no bar above. [D74] */
@media (max-width: 639px) {
    .page-title {
        font-size: var(--text-3xl);
        line-height: 1.15;
    }
}

/* The title with badges beside it, such as "Banned" on an account's
   page. They wrap under a title too long to leave them room, and the title
   may then shrink to the row, where it breaks as it would alone. */
.page-title-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
}

.page-title-row > .page-title {
    min-width: 0;
}

.page-context {
    margin-top: var(--space-1);
    color: var(--color-text-muted);
}

.page-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* A little smaller than a form's buttons where the pointer is precise, as
   the developer chose in the mock of D74; a finger keeps its 44 pixels. */
.page-actions .btn {
    min-height: var(--control-height-sm);
    padding: 0 14px;
}

.page-actions .btn .icon {
    width: 16px;
    height: 16px;
}

/* On a phone the actions sit under the title at full width, where the
   thumb reaches them without stretching for a corner. */
@media (max-width: 639px) {
    .page-actions > .btn,
    .page-actions > form {
        flex: 1 1 auto;
    }

    .page-actions > form > .btn {
        width: 100%;
    }
}

@media (min-width: 640px) {
    .page-header-row {
        flex-direction: row;
        align-items: flex-end;
        justify-content: space-between;
    }

    .page-actions {
        flex: none;
    }
}

/* ------------------------------------------------------------------------
   Tabs: the pages of one area under its page header, such as Users,
   Invites and Roles in People (partials/tabs.php). Links, a page each. The
   current tab is in the full text colour over a 2 pixel line of the same
   colour, never a colour of its own; a 1 pixel line runs under the whole row.
   ------------------------------------------------------------------------ */

/* On phones the row runs to the edges of the screen, so it can scroll
   sideways under the thumb; the line under it is an inset shadow of the
   row itself, so it spans the full width whether or not the tabs do. */
.tabs {
    margin: var(--space-5) calc(-1 * var(--gutter)) 0;
    padding: 0 var(--gutter);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    box-shadow: inset 0 -1px 0 var(--color-border);
}

.tabs::-webkit-scrollbar {
    display: none;
}

.tabs-list {
    display: flex;
    gap: var(--space-6);
}

.tab {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    height: 40px;
    color: var(--color-text-muted);
    font-weight: var(--weight-medium);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--duration-fast) var(--ease-in-out);
}

/* The line under a tab covers the row's line, as a tab sits on it. */
.tab::after {
    content: "";
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 2px;
    border-radius: 2px 2px 0 0;
    background: transparent;
    transition: background-color var(--duration-fast) var(--ease-in-out);
}

@media (hover: hover) {
    .tab:hover {
        color: var(--color-text);
    }

    .tab:hover::after {
        background: var(--color-border-strong);
    }
}

.tab[aria-current="page"] {
    color: var(--color-text);
}

.tab[aria-current="page"]::after {
    background: var(--color-text);
}

/* The focus ring as a box around the label: the row scrolls, so it clips
   whatever sticks out above or below a tab, and a ring inset into the tab
   would touch the letters. It sticks out sideways instead, into the room
   the row keeps at its ends. A border rather than a shadow, so it survives
   forced colours. */
.tab:focus-visible {
    outline: none;
}

.tab:focus-visible::before {
    content: "";
    position: absolute;
    inset: 6px calc(-1 * var(--space-2) + 2px);
    border: 2px solid var(--color-focus);
    border-radius: var(--radius-sm);
}

/* A count beside the label, such as the open invites: a grey pill, the
   same on every tab, current or not. */
.tab-count {
    display: inline-grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: var(--radius-full);
    background: var(--color-surface-selected);
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/* A red dot after the label while something there waits for someone, such
   as an account's Needs a look (D107): no number, as the tab lists them. */
.tab-dot {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: var(--color-danger-solid);
}

/* A tab that leaves the record, an account's Analytics: its small arrow,
   in the subtle grey, after the word. */
.tab-icon {
    flex: none;
    width: 14px;
    height: 14px;
    margin-left: calc(-1 * var(--space-1));
    color: var(--color-text-subtle);
}

@media (pointer: coarse) {
    .tab {
        height: 44px;
    }
}

/* Forced colours (Windows contrast themes) drop backgrounds, which is all
   that marks the current area in the sidebar and the current tab: they get
   a line in the system's text colour instead. */
@media (forced-colors: active) {
    .nav-link[aria-current] {
        outline: 2px solid;
        outline-offset: -2px;
    }

    .tab[aria-current="page"]::after {
        border-bottom: 2px solid;
    }
}

/* Beside the page's own padding: the row keeps a little room at its ends
   for the focus ring, and the line under it is only as wide as the
   content, drawn in the content box. */
@media (min-width: 640px) {
    .tabs {
        margin-right: calc(-1 * var(--space-2));
        margin-left: calc(-1 * var(--space-2));
        padding: 0 var(--space-2);
        box-shadow: none;
        background: linear-gradient(var(--color-border), var(--color-border)) content-box bottom / 100% 1px no-repeat;
    }
}

/* ------------------------------------------------------------------------
   Long pages with section navigation. Below 1280 pixels the navigation is a
   row of links above the content that scrolls sideways; from 1280 it is a
   sticky column on the right.
   ------------------------------------------------------------------------ */

/* minmax(0, 1fr): wide content, a chart or a row of reels, scrolls inside
   its card instead of widening the page. [Phase 5, section 9.1] */
.with-section-nav {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-6);
}

.section-nav {
    margin: 0 calc(-1 * var(--gutter));
    padding: 0 var(--gutter);
    overflow-x: auto;
    scrollbar-width: none;
}

.section-nav::-webkit-scrollbar {
    display: none;
}

.section-nav-title {
    display: none;
}

.section-nav ul {
    display: flex;
    gap: var(--space-2);
    list-style: none;
}

.section-nav a {
    display: flex;
    align-items: center;
    min-height: var(--control-height-sm);
    padding: 0 var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-full);
    background: var(--color-surface);
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    text-decoration: none;
    white-space: nowrap;
}

@media (hover: hover) {
    .section-nav a:hover {
        color: var(--color-text);
        border-color: var(--color-border-strong);
    }
}

/* Inside the link: the scrolling row clips anything outside it. */
.section-nav a:focus-visible {
    outline-offset: -2px;
}

@media (min-width: 640px) {
    .section-nav {
        margin: 0;
        padding: 0;
    }
}

@media (min-width: 1280px) {
    .with-section-nav {
        grid-template-columns: minmax(0, 1fr) 200px;
        align-items: start;
        gap: var(--space-8);
    }

    .section-nav {
        position: sticky;
        top: var(--space-10);
        order: 2;
        overflow: visible;
    }

    .section-nav-title {
        display: block;
        margin-bottom: var(--space-2);
        padding-left: var(--space-3);
        font-size: var(--text-xs);
        font-weight: var(--weight-semibold);
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--color-text-subtle);
    }

    .section-nav ul {
        flex-direction: column;
        gap: 0;
        border-left: 1px solid var(--color-border);
    }

    .section-nav a {
        min-height: 32px;
        margin-left: -1px;
        border: 0;
        border-left: 2px solid transparent;
        border-radius: 0;
        background: none;
    }

    @media (hover: hover) {
        .section-nav a:hover {
            border-left-color: var(--color-border-strong);
        }
    }
}

/* ------------------------------------------------------------------------
   A record's page in the panel (components.css, D76). The panel's head
   says where the page belongs, so the page's way back goes, and what a
   link scrolls to stays clear of the sticky row of sections. The page is
   laid out by the room in the panel, its body the container "panel", not
   by the screen: narrower, the section links are a row of pills that
   stays at the top of the body while it scrolls; from 920 pixels of room
   it is the wide page again, the links a sticky column on the right with
   their title. The selectors name the body, so they outrank the page's
   own rules at every width of the screen.
   ------------------------------------------------------------------------ */

.side-panel-body .page-back {
    display: none;
}

.side-panel-body [id] {
    scroll-margin-top: 64px;
}

.side-panel-body .with-section-nav {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-5);
}

/* Across the body's whole width, on its ground, so the page scrolls
   under it. */
.side-panel-body .section-nav {
    position: sticky;
    top: calc(-1 * var(--space-2));
    z-index: 2;
    order: 0;
    margin: 0 calc(-1 * var(--space-8));
    padding: var(--space-2) var(--space-8);
    overflow-x: auto;
    background: var(--color-canvas);
}

.side-panel-body .section-nav-title {
    display: none;
}

.side-panel-body .section-nav ul {
    flex-direction: row;
    gap: var(--space-2);
    border-left: 0;
}

.side-panel-body .section-nav a {
    min-height: var(--control-height-sm);
    margin-left: 0;
    padding: 0 var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-full);
    background: var(--color-surface);
}

@container panel (min-width: 920px) {
    .side-panel-body .with-section-nav {
        grid-template-columns: minmax(0, 1fr) 200px;
        align-items: start;
        gap: var(--space-8);
    }

    .side-panel-body .section-nav {
        top: var(--space-6);
        order: 2;
        margin: 0;
        padding: 0;
        overflow: visible;
        background: none;
    }

    .side-panel-body .section-nav-title {
        display: block;
        margin-bottom: var(--space-2);
        padding-left: var(--space-3);
        font-size: var(--text-xs);
        font-weight: var(--weight-semibold);
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--color-text-subtle);
    }

    .side-panel-body .section-nav ul {
        flex-direction: column;
        gap: 0;
        border-left: 1px solid var(--color-border);
    }

    .side-panel-body .section-nav a {
        min-height: 32px;
        margin-left: -1px;
        border: 0;
        border-left: 2px solid transparent;
        border-radius: 0;
        background: none;
    }
}

/* ------------------------------------------------------------------------
   Sign in shell, adapted from MyPeptideApp: on wide screens a rounded panel
   with a mesh gradient and grain beside the form column, on phones the form
   column alone with the lockup on top. Serves sign in, invite acceptance,
   password reset and the error pages without a session.
   ------------------------------------------------------------------------ */

.auth-body {
    background: var(--color-surface);
}

.auth-shell {
    display: grid;
    grid-template-columns: 1fr;
    min-height: 100vh;
    min-height: 100svh;
}

.auth-panel {
    display: none;
}

.auth-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    padding: var(--space-4) 18px;
}

.auth-top {
    display: flex;
    align-items: center;
    min-height: 40px;
}

.auth-content {
    display: flex;
    flex: 1;
    flex-direction: column;
    padding: 26px 0 20px;
}

/* margin: auto rather than centring on the parent: when the form is taller
   than the window, auto margins collapse to zero and the page scrolls from
   the top, where centring would push the headline out of reach. */
.auth-col {
    width: 100%;
    max-width: 440px;
    margin: auto;
}

.auth-title {
    font-size: clamp(28px, 7.8vw, 32px);
    line-height: 1.12;
    letter-spacing: -0.028em;
}

.auth-subtitle {
    max-width: 40ch;
    margin-top: 9px;
    color: var(--color-text-muted);
}

.auth-col > .alert {
    margin-top: var(--space-5);
}

.auth-form {
    margin-top: var(--space-6);
}

.auth-form .btn-primary {
    margin-top: var(--space-1);
    box-shadow: var(--shadow-primary);
}

.auth-footnote {
    max-width: 38ch;
    margin: var(--space-6) auto 0;
    color: var(--color-text-subtle);
    font-size: var(--text-sm);
    line-height: 1.6;
    text-align: center;
}

.auth-panel .lockup {
    color: var(--panel-ink);
}

.auth-panel .lockup-mark {
    background: var(--panel-mark-bg);
    color: var(--panel-mark-fg);
}

/* Soft rather than saturated: the panel is a large area of colour. */
.auth-mesh {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(64% 50% at 4% 2%, var(--panel-light), transparent 62%),
        radial-gradient(92% 74% at 26% 64%, var(--panel-violet-1), transparent 74%),
        radial-gradient(80% 64% at 98% 4%, var(--panel-violet-2), transparent 72%),
        radial-gradient(86% 70% at 94% 100%, var(--panel-violet-3), transparent 74%),
        var(--panel-base);
}

/* Grain kills the banding a large soft gradient shows on cheap screens. An
   SVG noise filter as a data URI, which the content security policy allows
   for images and which costs no request. */
.auth-grain {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
    opacity: var(--panel-grain-opacity);
    mix-blend-mode: var(--panel-grain-blend);
}

.auth-panel-foot {
    max-width: 30ch;
}

.auth-eyebrow {
    font-size: 11px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--panel-ink-muted);
}

.auth-headline {
    margin-top: 11px;
    font-family: var(--font-display);
    font-size: clamp(28px, 2.6vw, 34px);
    font-weight: var(--weight-semibold);
    line-height: 1.1;
    letter-spacing: -0.03em;
    color: var(--panel-ink);
    text-wrap: balance;
}

@media (min-width: 900px) {
    /* The white page is the frame; the panel is a tile inside it. It is sized
       to the window, not to the row, and sticky, so a form taller than the
       window scrolls past a panel that stays put. */
    .auth-shell {
        grid-template-columns: 0.85fr 1fr;
        padding: 16px;
    }

    .auth-panel {
        position: sticky;
        top: 16px;
        align-self: start;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        height: calc(100vh - 32px);
        height: calc(100svh - 32px);
        overflow: hidden;
        padding: 40px;
        border-radius: var(--radius-panel);
        isolation: isolate;
    }

    .auth-panel > .lockup,
    .auth-panel-foot {
        position: relative;
        z-index: 1;
    }

    .auth-main {
        padding: 28px 40px 32px;
    }

    .auth-top {
        display: none;
    }

    .auth-content {
        padding: 32px 0 8px;
    }

    .auth-col {
        max-width: 392px;
    }
}

@media (min-width: 1280px) {
    .auth-shell {
        padding: 20px;
    }

    .auth-panel {
        top: 20px;
        height: calc(100vh - 40px);
        height: calc(100svh - 40px);
        padding: 52px;
    }

    .auth-main {
        padding: 32px 56px 36px;
    }
}

/* Past this width the form column is what should grow, not the panel. */
@media (min-width: 1600px) {
    .auth-shell {
        grid-template-columns: minmax(0, 780px) 1fr;
    }
}
