/*
 * Pi Pocket's theme: soft tiles over an Omarchy palette. The palette is the Omarchy theme's colors.toml (theme.js sets
 * the --o-* variables, from a bundled theme or the desktop's own); everything else mixes from it the way omarchy-shell
 * does: the foreground over the background at a few percent for fills and hairlines. Windows still tile like
 * Hyprland's, with rounded corners, 1px hairlines, and a soft accent ring on the one in focus. Geist sets the words;
 * JetBrains Mono only code, paths, branches, numbers, counts, and keys. Motion keeps Hyprland's curves.
 */
/*
 * Contents, in the order the cascade reads them. Search for "─── " and a name to jump to a section. A rule later in
 * the file wins over an earlier one of the same specificity, and some later sections restyle earlier ones on purpose:
 * move a rule only after checking what it crosses.
 *
 *   Fonts, tokens, and the reset   the palette's variables, light themes, scrollbars, base elements
 *   Motion                         Hyprland's curves, reduced motion, the theme reveal
 *   Loaders                        the boot screen, the spinner
 *   Layout                         windows on a desktop, the sidebar's edge
 *   Top bar
 *   Transcript                     messages, Pi's replies, code blocks, answer actions, arrivals, chevrons
 *   Tool cards                     what Pi did: activity groups and their timelines, approvals, the live line
 *   Composer                       the queue, slash commands, file mentions, the message box, the bar under it
 *   Extensions                     extension cards, and the switch every sheet uses
 *   Sessions                       the sidebar: tabs, groups, rows, selection, its foot
 *   The rail, The home screen
 *   Sheets                         sheets on phones, popups on wide screens, the drawer
 *   Pop-up menus                   the model and branch pickers
 *   Sheet parts and controls       sheet heads and bodies, menu rows, fields, buttons, segmented choices, checks,
 *                                  providers, invites
 *   Artifact viewer, Images
 *   Notices, sign-in, plain pages  also the server's own pages (sign-in, invites)
 *   People                         who is here, typing, the side chat
 *   Collaboration                  activity, quotes, mentions, pins, notes, reactions, take turns
 *   Parts of sheets                share, schedules, goals, running now, changes, spend
 *   Launcher, Appearance
 *   Sign in                        the app's sign-in screen
 *   Small glue                     the sheet host, viewers leaving, search keys, unread dots
 *   People panel, Peek tiles
 *   Diff viewer, Review            one file's diff, and every change in the folder file by file
 *   Files tile, Browser            the docked panels
 *   Files, commands, and find      file paths and mentions, `!` commands and notes, changes, the file viewer, find,
 *                                  messages sent before
 *   Syntax and rich markdown       code colors, and pages, images, and diffs drawn in replies
 */

/* ─── Fonts, tokens, and the reset ───────────────────────────── */

@font-face {
    font-family: "Pocket Mono";
    src: url("/fonts/JetBrainsMono.woff2") format("woff2");
    font-weight: 100 800;
    font-display: swap;
}

@font-face {
    font-family: "Pocket Sans";
    src: url("/fonts/Geist.woff2") format("woff2");
    font-weight: 100 900;
    font-display: swap;
}

:root {
    /* The palette. These defaults are Tokyo Night; theme.js replaces them. */
    --o-bg: #1a1b26;
    --o-bg-dark: #13141c;
    --o-bg-darker: #0e0e14;
    --o-bg-light: #24283b;
    --o-fg: #a9b1d6;
    --o-fg-dim: #565f89;
    --o-fg-light: #b4bee6;
    --o-fg-bright: #c0caf5;
    --o-accent: #7aa2f7;
    --o-selection: #292e42;
    --o-red: #f7768e;
    --o-yellow: #e0af68;
    --o-orange: #eb927b;
    --o-green: #9ece6a;
    --o-cyan: #449dab;
    --o-blue: #7aa2f7;
    --o-magenta: #ad8ee6;

    /* Surfaces, after omarchy-shell's control states: the foreground laid over the background. */
    --desk: var(--o-bg-darker);
    --bg: var(--o-bg);
    --panel: var(--bg);
    --card: color-mix(in srgb, var(--body) 4%, var(--bg));
    --card-2: color-mix(in srgb, var(--body) 8%, var(--bg));
    /* A selected segment, raised from its track. */
    --raised: color-mix(in srgb, var(--body) 12%, var(--bg));
    --hover: color-mix(in srgb, var(--body) 7%, transparent);
    --pressed: color-mix(in srgb, var(--body) 18%, transparent);
    --line: color-mix(in srgb, var(--body) 13%, var(--bg));
    --line-strong: color-mix(in srgb, var(--body) 26%, var(--bg));
    --edge: color-mix(in srgb, var(--body) 25%, transparent);
    /* Hairlines: the usual 1px line, and a stronger one (fields, a switch's track while off). */
    --hair: color-mix(in srgb, var(--body) 10%, transparent);
    --hair-2: color-mix(in srgb, var(--body) 17%, transparent);
    --text: var(--o-fg-bright);
    --body: var(--o-fg);
    /* Quieter text at 4.5:1 or more on the ground (WCAG AA) with every palette that comes with the app. */
    --muted: color-mix(in oklab, var(--body) 76%, var(--bg));
    --faint: color-mix(in oklab, var(--body) 42%, var(--bg));
    --accent: var(--o-accent);
    --accent-ink: var(--bg);
    /* The accent as a fill under text (buttons, badges): darker in light themes, so text on it stays readable. */
    --accent-fill: var(--accent);
    --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
    --accent-line: color-mix(in srgb, var(--accent) 50%, transparent);
    /* The keyboard's focus ring: keep it visible (a theme may change its color, never take it away). */
    --focus-ring: var(--accent);
    /* The second color of loaders and thoughts. */
    --spark: var(--o-magenta);
    /* A second accent, for what a theme draws in two colors (Hyprland's active border is a gradient): the app uses none. */
    --accent-2: var(--spark);
    --brand: var(--o-orange);
    --ok: var(--o-green);
    --ok-soft: color-mix(in srgb, var(--o-green) 14%, transparent);
    --warn: var(--o-yellow);
    --warn-soft: color-mix(in srgb, var(--o-yellow) 10%, transparent);
    --warn-line: color-mix(in srgb, var(--o-yellow) 42%, transparent);
    --err: var(--o-red);
    --err-soft: color-mix(in srgb, var(--o-red) 14%, transparent);
    --err-line: color-mix(in srgb, var(--o-red) 50%, transparent);
    --code-bg: var(--o-bg-dark);
    /* Syntax colors, from the theme's own palette so every Omarchy theme colors code its way. */
    --hl-kw: var(--o-magenta);
    --hl-str: var(--o-green);
    --hl-num: var(--o-orange);
    --hl-fn: var(--o-blue);
    --hl-type: var(--o-yellow);
    --hl-op: var(--o-cyan);
    --hl-tag: var(--o-red);
    --scrim: color-mix(in srgb, var(--desk) 55%, transparent);
    /* Shadows: a soft lift (the message box), and what floats over the page (popovers, sheets, the launcher, PiP). */
    --sh: rgba(0, 0, 0, 0.5);
    --shadow: 0 18px 40px -18px var(--sh), 0 2px 6px -2px var(--sh);
    --pop: 0 24px 60px -16px var(--sh), 0 0 0 1px var(--hair-2);
    /*
     * Corners, from small to large: state squares; inline code, keys, and small tags; a segment in its track; small
     * buttons and list rows; icon buttons, fields, and segmented tracks; cards and primary buttons; windows, approval
     * cards, and peek tiles; the message box, sheets, and the launcher; PiP. Pills and avatars are round (999px).
     */
    --r-mark: 3px;
    --r-tag: 5px;
    --r-seg: 7px;
    --r-row: 9px;
    --r-control: 10px;
    --r-card: 12px;
    --r-window: 14px;
    --r-sheet: 18px;
    --r-float: 20px;
    --r-pill: 999px;
    /* Fields and plain controls that name no corner of their own. */
    --radius: var(--r-control);
    /* Hyprland's layout, softened: gaps_out 8, gaps_in 4, border_size 1. */
    --gap-out: 8px;
    --gap-in: 4px;
    --border: 1px;
    /* The conversation's column, and the message box under it, at their widest; room before the conversation's turns. */
    --transcript-width: clamp(720px, 72%, 1200px);
    --composer-width: calc(var(--transcript-width) + 48px);
    --transcript-gutter: 0px;
    /* The timeline in an activity group: where its rule and the centers of its marks are, the marks' size, and the gap
     * from a mark to its words (and to what a step shows under them). */
    --timeline-x: 22.5px;
    --step-mark-size: 19px;
    --step-gap: 10px;
    /* Tiled windows' border, the one in focus, and the ring around that one. */
    --window-border: var(--hair);
    --window-border-active: var(--accent-line);
    --window-ring: 0 0 0 3px var(--accent-soft);
    /* What shows in the gaps between tiled windows: the desktop's wallpaper when Appearance asks for it (inline), else this. */
    --wallpaper: none;
    /*
     * Density, from Appearance (`data-density`): how much room the spacing takes. Padding and gaps from top to bottom
     * scale by --space-y, and from side to side by --space-x; --leading is the conversation's line height. Rows that
     * are tap targets keep a floor on touch screens. Font sizes, corners, and colors stay as they are.
     */
    --space-y: 1;
    --space-x: 1;
    --leading: 1.65;

    /* Motion: Omarchy's Hyprland curves, and its speeds in milliseconds. */
    --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* easeOutQuint */
    --ease-in-out: cubic-bezier(0.65, 0.05, 0.36, 1); /* easeInOutCubic */
    --ease-almost: cubic-bezier(0.5, 0.5, 0.75, 1); /* almostLinear */
    --t-in: 410ms; /* windowsIn */
    --t-out: 150ms; /* windowsOut */
    --t-fade: 175ms; /* fadeIn */
    --t-border: 540ms; /* border */
    --t-hover: 140ms;

    /* Ligatures: none, as in a terminal. A theme may turn on a font's own (`contextual`, `normal`). */
    --ligatures: none;
    --mono:
        "Pocket Mono", "JetBrains Mono", "JetBrainsMono Nerd Font", ui-monospace, "SF Mono", Menlo,
        Consolas, monospace;
    --sans: "Pocket Sans", "Geist", ui-sans-serif, system-ui, sans-serif;
    color-scheme: dark;
}

:root[data-density="compact"] {
    --space-y: 0.7;
    --space-x: 0.85;
    --leading: 1.5;
}

:root[data-density="tight"] {
    --space-y: 0.45;
    --space-x: 0.7;
    --leading: 1.4;
}

/* Light themes: quieter text and the status colors darken toward the foreground, so they stay readable on light grounds. */
:root[data-mode="light"] {
    color-scheme: light;
    --sh: rgba(40, 40, 70, 0.14);
    --accent-ink: #fff;
    --scrim: color-mix(in srgb, var(--desk) 55%, transparent);
    --line: color-mix(in srgb, var(--body) 15%, var(--bg));
    --muted: color-mix(in oklab, var(--body) 87%, var(--bg));
    --faint: color-mix(in oklab, var(--body) 58%, var(--bg));
    --warn: color-mix(in oklab, var(--o-yellow) 62%, var(--o-fg));
    --ok: color-mix(in oklab, var(--o-green) 78%, var(--o-fg));
    --err: color-mix(in oklab, var(--o-red) 85%, var(--o-fg));
    --accent-fill: color-mix(in oklab, var(--accent) 76%, var(--body));
    /* Code's colors further still: halfway, yellow (the lightest) more, so each reads at 3:1 or better. */
    --hl-kw: color-mix(in oklab, var(--o-magenta) 50%, var(--o-fg));
    --hl-str: color-mix(in oklab, var(--o-green) 50%, var(--o-fg));
    --hl-num: color-mix(in oklab, var(--o-orange) 50%, var(--o-fg));
    --hl-fn: color-mix(in oklab, var(--o-blue) 50%, var(--o-fg));
    --hl-type: color-mix(in oklab, var(--o-yellow) 40%, var(--o-fg));
    --hl-op: color-mix(in oklab, var(--o-cyan) 50%, var(--o-fg));
    --hl-tag: color-mix(in oklab, var(--o-red) 50%, var(--o-fg));
}

* {
    box-sizing: border-box;
    /* No ligatures, as in a terminal: code shows the characters it has (=== stays three). Important, because each
     * `font` shorthand would reset it; a theme changes it through --ligatures (`contextual` for a font's `calt`). */
    font-variant-ligatures: var(--ligatures) !important;
}

html,
body {
    margin: 0;
    height: 100%;
    background: var(--desk);
    color: var(--body);
    font: 14px / 1.55 var(--sans);
    -webkit-text-size-adjust: 100%;
    -webkit-tap-highlight-color: transparent;
}

#app {
    height: 100dvh;
}

button,
input,
textarea,
select {
    font: inherit;
    color: inherit;
}

button {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
}

/* iOS zooms into any text field smaller than 16px when it takes focus. Important, so a theme's size for a field (in a
 * later layer, which beats this one) does not bring the zoom back on touch screens. */
@media (pointer: coarse) {
    input,
    textarea,
    select {
        font-size: 16px !important;
    }
}

input,
textarea,
select {
    background: var(--card);
    border: 1px solid var(--hair-2);
    border-radius: var(--radius);
    padding: 0.6rem 0.75rem;
    width: 100%;
    outline: none;
    color: var(--text);
    transition:
        border-color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    input:hover,
    textarea:hover,
    select:hover {
        border-color: var(--edge);
    }
}

input:focus,
textarea:focus,
select:focus {
    border-color: var(--accent-line);
}

::placeholder {
    color: var(--muted);
    opacity: 1;
}

::selection {
    background: color-mix(in srgb, var(--accent) 35%, transparent);
    color: var(--text);
}

:focus-visible {
    outline: 1px solid var(--focus-ring);
    outline-offset: 1px;
}

/* A field's ring lies on its own border, not a second line beside it. */
input:not([type="checkbox"], [type="radio"]):focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline-offset: -1px;
}

a {
    color: var(--accent);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

/* Thin round scrollbars, on hairline thumbs. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--hair-2) transparent;
}

::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-thumb {
    background: var(--hair-2);
    border: 2px solid transparent;
    border-radius: var(--r-pill);
    background-clip: padding-box;
}

@media (hover: hover) {
    ::-webkit-scrollbar-thumb:hover {
        background-color: var(--muted);
    }
}

::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
    background: transparent;
}

kbd {
    display: inline-grid;
    place-items: center;
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    font: 600 11px/1 var(--mono);
    color: var(--text);
    background: var(--card);
    border: 1px solid var(--hair-2);
    border-bottom-width: 2px;
    border-radius: calc(var(--r-tag) + 1px);
    vertical-align: middle;
}

.mono {
    font-family: var(--mono);
}

.muted {
    color: var(--muted);
}

.small {
    font-size: 0.8rem;
}

.grow {
    flex: 1;
}

.meter {
    display: inline-flex;
    height: 4px;
    border-radius: calc(var(--r-mark) - 1px);
    overflow: hidden;
    background: var(--hair-2);
}

.meter > span {
    background: var(--accent);
}

.meter.warn > span {
    background: var(--warn);
}

.meter.err > span {
    background: var(--err);
}

.warn {
    color: var(--warn);
}

.ok {
    color: var(--ok);
}

.err {
    color: var(--err);
}

.pi {
    font-family: Georgia, "Times New Roman", serif;
    color: var(--brand);
}

/* ─── Motion ───────────────────────────────────────────────── */

/* Hyprland's popin 87%: what opens grows from 87% and fades in. */
@keyframes popin {
    from {
        opacity: 0;
        transform: scale(0.87);
    }
}

@keyframes popout {
    to {
        opacity: 0;
        transform: scale(0.87);
    }
}

@keyframes fade {
    from {
        opacity: 0;
    }
}

@keyframes fade-out {
    to {
        opacity: 0;
    }
}

@keyframes rise-in {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
}

/* What floats over the page (popovers, sheets, the launcher) rises a little and grows from 98% as it fades in. */
@keyframes pop {
    from {
        opacity: 0;
        transform: translateY(6px) scale(0.98);
    }
}

@keyframes pop-out {
    to {
        opacity: 0;
        transform: translateY(6px) scale(0.98);
    }
}

/* Reduced motion (the system's, or Appearance's): no movement, apart from what says something is working. */
:root[data-motion="reduced"] *,
:root[data-motion="reduced"] *::before,
:root[data-motion="reduced"] *::after {
    animation-duration: 1ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0s !important;
}

:root[data-motion="reduced"] .spinner::before {
    transform: translate(calc(100% + 2px), 0);
}

:root[data-motion="reduced"] .boot-bar span {
    width: 70%;
}

/* Theme changes: the new look grows as a circle from where it was chosen (theme.js sets the place). */
:root.theme-vt::view-transition-old(root),
:root.theme-vt::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
}

:root.theme-vt::view-transition-new(root) {
    animation: theme-reveal 0.75s var(--ease-out);
}

@keyframes theme-reveal {
    from {
        clip-path: circle(0 at var(--vt-x, 50%) var(--vt-y, 50%));
    }
    to {
        clip-path: circle(var(--vt-r, 150vmax) at var(--vt-x, 50%) var(--vt-y, 50%));
    }
}

/* ─── Loaders, after Omarchy's ───────────────────────────────── */

/* The boot screen: π over a flat square bar (Omarchy's boot screen) that eases toward 70% while it waits. */
.boot {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.1rem;
    height: 100dvh;
    padding: 1.5rem;
    font-family: var(--mono);
    color: var(--muted);
    text-align: center;
    background: var(--bg);
    animation: fade 0.3s var(--ease-almost);
}

.boot.inline {
    height: 100%;
    min-height: 16rem;
    background: none;
}

.boot-mark {
    font:
        4.5rem/1 Georgia,
        "Times New Roman",
        serif;
    color: var(--brand);
    animation: boot-breathe 2.4s var(--ease-in-out) infinite;
}

@keyframes boot-breathe {
    50% {
        opacity: 0.55;
    }
}

.boot.inline .boot-mark {
    font-size: 3rem;
}

.boot-bar {
    width: min(300px, 64vw);
    height: 8px;
    background: var(--line);
    overflow: hidden;
}

.boot-bar span {
    display: block;
    width: 0;
    height: 100%;
    background: var(--body);
    animation: boot-fill 15s cubic-bezier(0.12, 0.6, 0.3, 1) forwards;
}

@keyframes boot-fill {
    to {
        width: 70%;
    }
}

.boot-caption {
    font-size: 0.75rem;
    letter-spacing: 0.14em;
    text-transform: lowercase;
}

.boot-detail {
    max-width: 32ch;
    font-size: 0.75rem;
    line-height: 1.5;
    opacity: 0.8;
}

/* The inline spinner: one lit quadrant stepping around a square (▖▘▝▗), from the accent toward the spark. */
.spinner {
    position: relative;
    display: inline-block;
    flex: none;
    width: 0.85em;
    height: 0.85em;
    min-width: 11px;
    min-height: 11px;
    vertical-align: -0.1em;
    background:
        linear-gradient(var(--line), var(--line)) 0 0 / calc(50% - 1px) calc(50% - 1px) no-repeat,
        linear-gradient(var(--line), var(--line)) 100% 0 / calc(50% - 1px) calc(50% - 1px) no-repeat,
        linear-gradient(var(--line), var(--line)) 0 100% / calc(50% - 1px) calc(50% - 1px) no-repeat,
        linear-gradient(var(--line), var(--line)) 100% 100% / calc(50% - 1px) calc(50% - 1px)
            no-repeat;
}

.spinner::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: calc(50% - 1px);
    height: calc(50% - 1px);
    background: var(--accent);
    animation: quadrant 0.8s steps(1, end) infinite;
}

@keyframes quadrant {
    0% {
        transform: translate(0, calc(100% + 2px));
        background: var(--accent);
    }
    25% {
        transform: translate(0, 0);
        background: color-mix(in oklab, var(--accent) 67%, var(--spark));
    }
    50% {
        transform: translate(calc(100% + 2px), 0);
        background: color-mix(in oklab, var(--accent) 33%, var(--spark));
    }
    75% {
        transform: translate(calc(100% + 2px), calc(100% + 2px));
        background: var(--spark);
    }
}

.loader {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.6rem 0.1rem;
    font-size: 0.85rem;
    color: var(--muted);
}

@media (prefers-reduced-motion: reduce) {
    :root:not([data-motion="full"]) .pulse,
    :root:not([data-motion="full"]) .live-dot,
    :root:not([data-motion="full"]) .agents-dot.working,
    :root:not([data-motion="full"]) .session-working,
    :root:not([data-motion="full"]) .session-placeholder span {
        animation: none !important;
    }
}

.icon {
    flex: none;
}

/* ─── Layout: windows on a desktop ─────────────────────────── */

.layout {
    display: flex;
    height: 100dvh;
    background: var(--bg);
}

/* The sidebar and the conversation are windows. On wide screens with tiling on, they tile like Hyprland's, softened:
 * gaps over the desktop (or its wallpaper), rounded corners and a hairline, and a soft accent ring on the one in focus. */
.window {
    position: relative;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg);
}

/* The sidebar: the rail and the session list beside it, cut off rather than squeezed while it folds and unfolds. Wider
 * than usual, it takes 40% of the screen at most (`sessions.js` drags to the same), so the conversation keeps room. */
.sidebar {
    display: none;
    width: min(var(--sidebar-w, 312px), max(312px, 40vw));
    flex: none;
    flex-direction: row;
    border-right: 1px solid var(--hair);
    background: var(--panel);
    transition: width var(--t-in) var(--ease-out);
}

.sidebar-clip {
    flex: 1;
    min-width: 0;
    display: flex;
    overflow: hidden;
}

:root.resizing .sidebar {
    transition: none;
}

:root.resizing,
:root.resizing * {
    cursor: col-resize !important;
    user-select: none;
}

.pane {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    height: 100dvh;
}

/* The home screen scrolls inside the window: the window itself must not clip its active border. */
.layout.home .pane {
    min-height: 0;
}

.home-list {
    width: 100%;
    flex: 1;
    min-height: 0;
    display: flex;
}

/* The rail at the screen's edge, as the sidebar's is; the list beside it no wider than reads well, centered. */
.home-list > .sessions {
    max-width: 584px;
    margin: 0 auto;
}

/* A short screen (a phone on its side): the rail drops its marks (Pi, and the sessions it is on) so its buttons fit,
 * and the home list puts its search and tabs side by side, so more sessions show (where they fit). */
@media (max-height: 500px) {
    .rail {
        gap: 2px;
    }
    .rail > :is(span.rail-brand, span.rail-brand + .rail-gap, span.rail-button) {
        display: none;
    }
}

/* Side by side only where both fit: a short window that is also narrow keeps them stacked. */
@media (max-height: 500px) and (min-width: 600px) {
    .home-list > .sessions {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        grid-template-rows: auto auto minmax(0, 1fr);
        column-gap: 8px;
    }
    .home-list > .sessions > * {
        grid-column: 1 / -1;
    }
    .home-list > .sessions > .search {
        grid-column: 1;
    }
    .home-list > .sessions > .session-tabs {
        grid-column: 2;
        margin-top: 12px;
    }
}

.splash {
    display: none;
}

@media (min-width: 960px) {
    .sidebar {
        display: flex;
    }
    .layout.home .home-list {
        display: none;
    }
    .splash {
        display: flex;
    }
    .topbar > .icon-button:first-child {
        display: none;
    }
    /* Folded: the rail alone, and the sidebar's border. */
    :root[data-rail="on"] .sidebar {
        width: 57px;
    }
    :root[data-tiling="on"][data-rail="on"] .sidebar {
        width: calc(56px + 2 * var(--border));
    }

    :root[data-tiling="on"] .layout {
        padding: var(--gap-out);
        gap: calc(var(--gap-in) * 2);
        background: var(--desk) var(--wallpaper, none) center / cover no-repeat;
    }
    /* Rounded, so what they hold is cut to their corners; the edges to drag sit inside them. */
    :root[data-tiling="on"] .window {
        border: var(--border) solid var(--window-border);
        border-radius: var(--r-window);
        overflow: hidden;
        height: auto;
        animation: popin var(--t-in) var(--ease-out) backwards;
        transition:
            border-color var(--t-border) var(--ease-out),
            box-shadow var(--t-border) var(--ease-out);
    }
    :root[data-tiling="on"] .pane {
        animation-delay: 60ms;
    }
    :root[data-tiling="on"][data-focus="sidebar"] .sidebar,
    :root[data-tiling="on"][data-focus="browser-panel"] .browser,
    :root[data-tiling="on"][data-focus="files-panel"] .files-tile,
    :root[data-tiling="on"][data-focus="people-panel"] .people,
    :root[data-tiling="on"]:not([data-focus="sidebar"]):not([data-focus="browser-panel"]):not(
            [data-focus="files-panel"]
        ):not([data-focus="people-panel"]):not([data-focus="peeks"])
        .pane {
        border-color: var(--window-border-active);
        box-shadow: var(--window-ring);
    }
}

/* Drag the sidebar's edge to resize it; double-click puts it back. Inside the window, which cuts off what is past it. */
.resize-handle {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 8px;
    cursor: col-resize;
    z-index: 7;
    touch-action: none;
}

/* A sidebar a theme put on the right: its handle is on its left edge (`useSide`). */
.resize-handle.at-left {
    left: 0;
    right: auto;
}

.resize-handle::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 3px;
    width: 2px;
    height: 36px;
    margin-top: -18px;
    border-radius: 1px;
    background: var(--accent);
    opacity: 0;
    transform: scaleY(0.4);
    transition:
        opacity var(--t-hover) var(--ease-out),
        transform var(--t-in) var(--ease-out);
}

:root.resizing .resize-handle::before {
    opacity: 1;
    transform: none;
}

@media (hover: hover) {
    .resize-handle:hover::before {
        opacity: 1;
        transform: none;
    }
}

:root[data-rail="on"] .resize-handle {
    display: none;
}

/* ─── Top bar ──────────────────────────────────────────────── */

/*
 * The session's title over its folder and branch, what changed, the toggles, who is here, and the menu. The bar is as
 * wide as its pane and answers to that width, not the screen's: the room left decides which buttons show.
 */
.topbar {
    container: topbar / inline-size;
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: calc(46px + 12px * var(--space-y) + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 0 0;
    border-bottom: 1px solid var(--hair);
    background: var(--bg);
}

/* Its room is the container's: the margins, not padding, keep the buttons off the edges. */
.topbar > :last-child {
    margin-right: 10px;
}

/*
 * The top bar keeps only the buttons with something to say (a page open, artifacts made, people here): the menu's
 * tiles open the rest. The peek and Files toggles always show where there is room (`top-toggle`, below).
 */
.topbar .quiet {
    display: none;
}

/*
 * On a phone a few more go to the places by the message box, which show the same (artifacts made, a page open): the
 * top bar's buttons are a thumb wide each and must leave room for the title and the menu.
 */
@media (max-width: 699px) {
    .topbar .quiet-phone {
        display: none;
    }
}

/* Its buttons: quiet, and lit in the accent while what they open is open. */
.topbar .icon-button {
    width: 36px;
    height: 36px;
    color: var(--muted);
}

@media (hover: hover) {
    .topbar .icon-button:hover {
        color: var(--text);
    }
}

.topbar .icon-button.on {
    background: var(--accent-soft);
    color: var(--accent);
}

/* Who is here: an avatar with its online mark, and how many more, in a pill that lights while the panel is open. */
.topbar .people-button {
    height: 36px;
    min-width: 36px;
    padding: 0 4px;
    border-radius: var(--r-pill);
    color: var(--muted);
}

.topbar .people-button.on {
    background: var(--accent-soft);
    color: var(--accent);
}

.topbar .online-mark {
    width: 8px;
    height: 8px;
}

.topbar .avatar,
.rail .avatar {
    font-size: 11px;
}

/* Below the sidebar's width the top bar leads back to the session list, each button a thumb wide. */
@media (max-width: 959px) {
    .topbar {
        gap: 2px;
    }
    .topbar > :first-child {
        margin-left: 4px;
    }
    .topbar > :last-child {
        margin-right: 6px;
    }
    .topbar > .title {
        margin-left: -8px;
    }
    .topbar > .icon-button {
        width: 44px;
        min-width: 44px;
        height: 44px;
    }
    /* As wide as who is here: an avatar, and how many more. */
    .topbar > .people-button {
        min-width: 44px;
        height: 44px;
    }
    /* Over the title's button, whose box reaches a little under it. */
    .topbar > .topbar-back {
        z-index: 1;
        color: var(--text);
    }
    /* Out past the chevron's tip, so it covers neither the arrow nor the title. */
    .topbar > .topbar-back .badge {
        top: -2px;
        right: 0;
    }
}

/* The room in the pane: the changes lose their count of files under 560px, the toggles go under 480px, then the
 * avatars under 420px. The widths are the pane's less its 2px of border (tiled windows). */
@container topbar (max-width: 557px) {
    .changes-button .changes-files {
        display: none;
    }
}

@container topbar (max-width: 477px) {
    .topbar .top-toggle {
        display: none;
    }
}

@media (min-width: 700px) {
    @container topbar (max-width: 417px) {
        .topbar .people-button {
            display: none;
        }
    }
}

/* The title and its line under it open the menu, all but the branch, which opens the branch picker. */
.title {
    position: relative;
    flex: 1;
    min-width: 120px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: calc(4px * var(--space-y)) 8px;
    margin-left: 12px;
    border-radius: var(--r-row);
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .title:has(> .title-open:hover) {
        background: var(--hover);
    }
}

/* Over the whole title, under the branch. */
.title-open {
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

.title-open:focus-visible {
    outline-offset: -1px;
}

.title-main {
    font-weight: 600;
    font-size: 15px;
    line-height: 1.3;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The folder's color and last part, then the branch. Keep its row while loading so the title stays put. */
.title-sub {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    min-height: 20px;
    font-size: 12px;
    line-height: 20px;
    color: var(--muted);
    white-space: nowrap;
}

.title-sub > span {
    flex: none;
}

.title-sub > .folder-mark {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--folder, var(--accent));
}

/* The folder's name stays whole (up to a share of the line); the branch gives way first. */
.title-sub > .title-folder {
    flex: none;
    max-width: 55%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* A subagent's line names its parent session instead, which may take the whole line. */
.title-sub > .title-folder.title-parent {
    flex: 0 1 auto;
    max-width: none;
    min-width: 0;
}

/* The branch: a small tag with the fork mark, cut short from its end when the room is short. */
.title-sub > .title-branch {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex: 0 1 auto;
    min-width: 0;
    height: 20px;
    padding: 0 7px;
    border-radius: calc(var(--r-tag) + 1px);
    background: var(--card);
    font: 11px / 1 var(--mono);
    color: var(--muted);
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

.title-branch-name {
    min-width: 2ch;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Over the title's button, which takes the taps around it. */
.title-sub > button.title-branch {
    position: relative;
    z-index: 1;
}

@media (hover: hover) {
    .title-sub > button.title-branch:hover {
        color: var(--accent);
        background: var(--card-2);
    }
}

.title-sub > .title-worktree {
    font-size: 11.5px;
    color: var(--faint);
}

/* A phone shows the branch as plain mono text, as the design's phone board does. */
@media (max-width: 699px) {
    .title-sub > .title-branch {
        padding: 0;
        background: none;
        color: var(--faint);
    }
    .title-branch .icon {
        display: none;
    }
    @media (hover: hover) {
        .title-sub > button.title-branch:hover {
            background: none;
        }
    }
}

/*
 * A thumb's height on a touch screen, with its look kept: a layer past the branch takes the tap. The line under the
 * title is a little taller there, so that room stays in the top bar; the layer reaches into the bottom of the title's
 * line above (its descenders), and the rest of the title opens the menu.
 */
@media (pointer: coarse) {
    .title {
        padding-block: 0;
    }
    .title-sub {
        min-height: 24px;
    }
    .title-sub > button.title-branch::after {
        content: "";
        position: absolute;
        inset: -10px -8px -9px;
    }
}

/* What changed in the session's folder: lines added and removed, and how many files. */
.changes-button {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 30px;
    padding: 0 12px;
    border: 1px solid var(--hair);
    border-radius: var(--r-pill);
    background: var(--card);
    font-size: 12px;
    color: var(--muted);
    transition: border-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .changes-button:hover {
        border-color: var(--hair-2);
    }
}

.changes-button .added,
.changes-button .removed {
    font-family: var(--mono);
}

.changes-button .added {
    color: var(--ok);
}

.changes-button .removed {
    margin-left: -3px;
    color: var(--err);
}

@media (max-width: 959px) {
    .changes-button {
        margin-right: 4px;
    }
}

/* A phone: the counts alone, in a slimmer pill. */
@media (max-width: 699px) {
    .changes-button {
        height: 28px;
        padding: 0 10px;
        font-size: 11.5px;
    }
}

.icon-button {
    width: 40px;
    height: 40px;
    display: inline-grid;
    place-items: center;
    border-radius: var(--r-control);
    color: var(--muted);
    position: relative;
    flex: none;
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        transform 90ms var(--ease-out);
}

/* Not on touch screens, where a tapped button would keep the fill. */
@media (hover: hover) {
    .icon-button:hover {
        background: var(--hover);
        color: var(--text);
    }
}

.icon-button:active {
    background: var(--pressed);
    transform: scale(0.94);
}

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

.badge-host .badge,
.icon-button .count {
    position: absolute;
    top: 3px;
    right: 2px;
    min-width: 17px;
    height: 17px;
    border-radius: var(--radius);
    background: var(--accent-fill);
    color: var(--accent-ink);
    font-size: 0.68rem;
    font-weight: 700;
    display: grid;
    place-items: center;
    padding: 0 4px;
    animation: popin var(--t-in) var(--ease-out);
}

.badge.warn {
    background: var(--warn);
    color: var(--accent-ink);
    border-radius: var(--radius);
    min-width: 18px;
    display: inline-grid;
    place-items: center;
    font-weight: 700;
    font-size: 0.7rem;
}

/* ─── Transcript ───────────────────────────────────────────── */

.scroller {
    flex: 1;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Room for the scrollbar on both sides, kept whether or not it shows: the column stays put, centered over the
     * message box, when a session long enough to scroll opens. */
    scrollbar-gutter: stable both-edges;
    position: relative;
}

/* A column of turns: a person's message, what Pi did, Pi's reply, an approval, the live line. Its text size is
 * Appearance's; the cards inside keep fixed sizes. */
.transcript {
    max-width: var(--transcript-width);
    margin: 0 auto;
    padding: calc(28px * var(--space-y)) calc(28px * var(--space-x)) calc(24px * var(--space-y));
    padding-inline-start: calc(28px * var(--space-x) + var(--transcript-gutter));
    display: flex;
    flex-direction: column;
    gap: calc(16px * var(--space-y));
    font-size: var(--text-size, 15px);
    line-height: var(--leading);
    animation: rise-in 0.36s var(--ease-out);
}

/* Turns stand apart: 10px more before each message or report (less at a tighter density). */
.transcript > :is(.user-row, .report, .report-group):not(:first-child) {
    margin-top: calc(10px * var(--space-y));
}

@media (max-width: 699px) {
    .transcript {
        padding: calc(18px * var(--space-y)) calc(16px * var(--space-x)) calc(14px * var(--space-y));
        padding-inline-start: calc(16px * var(--space-x) + var(--transcript-gutter));
    }
}

/* What arrives while the session is open slides up into place: a message sent, or Pi starting to answer. */
.enter {
    animation: rise-in 0.42s var(--ease-out) backwards;
}

.empty {
    display: grid;
    place-items: center;
    gap: 0.6rem;
    padding: 3rem 1rem;
    text-align: center;
    color: var(--muted);
}

.empty .pi {
    font-size: 3.2rem;
    opacity: 0.8;
}

.breadcrumb {
    align-self: flex-start;
    text-align: left;
    color: var(--accent);
    font-size: 13px;
    display: inline-flex;
    gap: 0.25rem;
    align-items: center;
}

.linked-sessions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

.linked-sessions .breadcrumb {
    min-height: 40px;
    max-width: 100%;
    overflow-wrap: anywhere;
}

/* The explicit parent route stays beside the message box on every layout, even when the dock scrolls. */
.parent-session {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 44px;
    padding: 8px 12px;
    margin-bottom: 6px;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--card);
    color: var(--accent);
    font-size: 12.5px;
    text-align: left;
}

@media (hover: hover) {
    .parent-session:hover {
        background: var(--hover);
    }
}

.parent-session > :not(.parent-session-title) {
    flex-shrink: 0;
}

.parent-session-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--muted);
}

/* A person's message: a card, with who and when over what they wrote. Scoped to its row: the launcher's input has a
 * `.prompt` of its own. */
.user-row > .prompt {
    display: flex;
    flex-direction: column;
    gap: calc(4px * var(--space-y));
    padding: calc(12px * var(--space-y)) calc(16px * var(--space-x)) calc(14px * var(--space-y));
    border: 1px solid var(--hair);
    border-radius: var(--r-window);
    background: var(--card);
    color: var(--text);
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (max-width: 699px) {
    .user-row > .prompt {
        padding: calc(12px * var(--space-y)) calc(14px * var(--space-x)) calc(13px * var(--space-y));
        border-radius: calc(var(--r-window) + 2px);
    }
}

.user-row > .prompt.tappable {
    cursor: pointer;
}

@media (hover: hover) {
    .user-row > .prompt.tappable:hover {
        background: var(--card-2);
    }
}

.prompt-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 8px;
    min-width: 0;
    font-size: 12.5px;
    line-height: 22px;
}

/* Yours takes the accent, someone else's their color (`--who`), anyone else a quiet one. */
.prompt-avatar {
    flex: none;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--who) 20%, transparent);
    color: var(--who);
    font-size: 9.5px;
    font-weight: 600;
    line-height: 1;
}

.prompt-author {
    font-weight: 600;
    color: var(--text);
}

.prompt-time {
    color: var(--faint);
}

.prompt-body {
    min-width: 0;
    padding-left: 30px;
}

.user-text {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    text-wrap: pretty;
}

/* What a PR watch or a webhook fenced for Pi (a check's log, a post): a block of its own, scrolling past a few lines. */
.fenced-data {
    margin: 0.4rem 0;
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    background: var(--code-bg);
    overflow: hidden;
}

.fenced-label {
    padding: 4px 12px;
    border-bottom: 1px solid var(--hair);
    color: var(--muted);
    font-size: 12px;
}

.fenced-data pre {
    margin: 0;
    padding: 8px 12px;
    max-height: 14rem;
    overflow: auto;
    font: 12px / 1.55 var(--mono);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.attachments,
.files {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.35rem;
}

/* Pi's words: plain prose, without a container. */
.reply {
    display: flex;
    flex-direction: column;
    gap: calc(10px * var(--space-y));
    min-width: 0;
    color: var(--body);
}

.reply > .md {
    display: flex;
    flex-direction: column;
    gap: calc(12px * var(--space-y));
}

.reply > .md > *,
.reply > .md > .md-part > * {
    margin: 0;
}

.reply > .md :is(h1, h2, h3, h4) {
    margin-top: calc(6px * var(--space-y));
}

.reply > .md li + li {
    margin-top: calc(4px * var(--space-y));
}

.reply > .md p {
    text-wrap: pretty;
}

.md {
    overflow-wrap: anywhere;
}

.md > :first-child {
    margin-top: 0;
}

.md > :last-child {
    margin-bottom: 0;
}

.md p,
.md ul,
.md ol {
    margin: 0.45rem 0;
}

/* Real lists, with a 20px column for the marker (`1.` or `•`), quiet. */
.md ul,
.md ol {
    padding-left: 20px;
}

.md li::marker {
    color: var(--muted);
    font-size: 13px;
}

.md h1,
.md h2,
.md h3,
.md h4 {
    margin: 0.9rem 0 0.4rem;
    color: var(--text);
    font-weight: 600;
    line-height: 1.4;
}

.md h1 {
    font-size: 1.2em;
}

.md h2 {
    font-size: 1.1em;
}

.md h3,
.md h4 {
    font-size: 1em;
}

.md code {
    padding: 2px 6px;
    border-radius: var(--r-tag);
    background: var(--card-2);
    color: var(--text);
    font: 12.5px var(--mono);
}

.md strong {
    color: var(--text);
    font-weight: 600;
}

/*
 * A reply's code blocks and tables may run wider than its words, up to the pane's room (--pane-room, which
 * transcript.js measures) less the column's padding. A code block as wide as its longest line, at least the column's
 * width, centered on the column; a table as wide as its cells, from the column's start toward the pane's edge. On a
 * phone, and in a pane no wider than the column, the room is the column, so nothing changes.
 */
.transcript {
    --wide-room: max(
        100%,
        calc(var(--pane-room, 100%) - 56px * var(--space-x) - var(--transcript-gutter))
    );
}

[data-part~="reply"] :is(.md, .md-part) > .code {
    position: relative;
    left: 50%;
    width: max-content;
    min-width: 100%;
    max-width: var(--wide-room);
    translate: -50%;
}

/* Words in a code block (a draft to copy, say) wrap in the column, as a reply's words do: a paragraph on one line would
 * otherwise run the pane's width and still scroll sideways. A block with no language is text too, as its label says,
 * unless the app draws it (a page or a picture: `data-kind`). */
.code:not([data-kind])
    > pre:is(
        :not([data-lang]),
        [data-lang="text" i],
        [data-lang="txt" i],
        [data-lang="plaintext" i],
        [data-lang="markdown" i],
        [data-lang="md" i]
    ) {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

[data-part~="reply"]
    :is(.md, .md-part)
    > .code:not([data-kind]):has(
        > pre:is(
                :not([data-lang]),
                [data-lang="text" i],
                [data-lang="txt" i],
                [data-lang="plaintext" i],
                [data-lang="markdown" i],
                [data-lang="md" i]
            )
    ) {
    left: 0;
    width: auto;
    max-width: 100%;
    translate: none;
}

[data-part~="reply"] :is(.md, .md-part) > table:not(.dv-table) {
    width: max-content;
    max-width: calc(100% + (var(--wide-room) - 100%) / 2);
}

/* A reply's own tables, in a card; a diff it shows draws its table itself. */
.md table:not(.dv-table) {
    display: block;
    max-width: fit-content;
    overflow-x: auto;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.93em;
}

.md table:not(.dv-table) :is(td, th) {
    padding: 6px 12px;
    text-align: left;
    /* Words break only when longer than the cell can be, and a cell keeps room for a few words: a crowded table
     * scrolls sideways instead of crushing its columns. */
    overflow-wrap: break-word;
    min-width: 12ch;
}

.md table:not(.dv-table) th {
    background: var(--card);
    color: var(--text);
    font-weight: 600;
}

.md table:not(.dv-table) :is(td, th):not(:last-child) {
    border-right: 1px solid var(--hair);
}

.md table:not(.dv-table) tr:not(:last-child) > :is(td, th) {
    border-bottom: 1px solid var(--hair);
}

.md hr {
    height: 0;
    margin: 1.1em 0;
    border: 0;
    border-top: 1px solid var(--hair);
}

.md blockquote {
    margin: 0.5rem 0;
    padding-left: 0.8rem;
    border-left: 2px solid var(--hair-2);
    color: var(--muted);
}

/* A code block: a bar with its file or language and Copy, then the code. */
.code {
    position: relative;
    margin: 0.5rem 0;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--code-bg);
    overflow: hidden;
}

.code-head {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 34px;
    padding: 0 6px 0 14px;
    border-bottom: 1px solid var(--hair);
    font-size: 12px;
    color: var(--muted);
}

.code-lang {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: lowercase;
}

.code-head .copy {
    flex: none;
    height: 24px;
    margin-left: auto;
    padding: 0 9px;
    border-radius: var(--r-seg);
    font-size: 12px;
    color: var(--muted);
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .code-head .copy:hover {
        color: var(--text);
        background: var(--hover);
    }
}

.md pre {
    margin: 0;
    padding: 12px 14px;
    overflow-x: auto;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--code-bg);
    font: 12.5px / 1.6 var(--mono);
}

.code pre {
    border: 0;
    border-radius: 0;
    background: none;
}

.md pre code {
    background: none;
    padding: 0;
    font-size: inherit;
    color: var(--body);
}

/* In the conversation, code follows Appearance's text size, as the prose does: 12.5px at the usual 15px. */
.transcript .md code,
.transcript .md pre {
    font-size: calc(var(--text-size, 15px) * 5 / 6);
}

.md.streaming > :last-child:not(.md-part)::after {
    content: "█";
    margin-left: 1px;
    color: var(--accent);
    animation: blink 1s steps(2) infinite;
}

@keyframes blink {
    50% {
        opacity: 0;
    }
}

/* Chevrons turn instead of swapping: closed points right, open points down. */
.chev {
    transition: transform 0.3s var(--ease-out);
}

.open > button > .chev,
.chev.open {
    transform: rotate(90deg);
}

/* A panel opening below its header: revealed from the top down. */
@keyframes unroll {
    from {
        clip-path: inset(0 0 100% 0);
        opacity: 0.3;
    }
    to {
        clip-path: inset(0 0 0 0);
    }
}

/* Under Pi's answers: reactions, then React, Discuss, Pin, Copy, and More. */
.answer-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    min-height: 26px;
    font-size: 12.5px;
    line-height: 1.6;
}

.reaction {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 26px;
    padding: 0 10px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-pill);
    color: var(--text);
    white-space: nowrap;
    transition:
        border-color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

.reaction > span {
    font: 11.5px var(--mono);
}

@media (hover: hover) {
    .reaction:hover {
        border-color: var(--edge);
    }
}

.reaction.mine {
    border-color: var(--accent-line);
    background: var(--accent-soft);
}

.answer-actions > button.answer-tool,
.reaction.add {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: none;
    height: 26px;
    padding: 0 8px;
    border: 0;
    border-radius: var(--r-seg);
    color: var(--muted);
    white-space: nowrap;
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out),
        opacity var(--t-fade) var(--ease-out);
}

@media (hover: hover) {
    .answer-actions > button.answer-tool:hover,
    .reaction.add:hover {
        color: var(--text);
        background: var(--hover);
    }
}

/* With a mouse they show while the reply is hovered; touch screens always show them. */
@media (hover: hover) and (pointer: fine) {
    .reply .answer-actions > .answer-tool {
        opacity: 0;
        transition: opacity var(--t-fade) var(--ease-out);
    }
    .reply:hover .answer-actions > .answer-tool,
    .answer-actions:focus-within > .answer-tool,
    .answer-actions.picking > .answer-tool {
        opacity: 1;
    }
}

.reaction-host {
    position: relative;
    display: inline-flex;
}

/* The six emoji, in a popover over the button. */
.reaction-picker {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    z-index: 5;
    display: flex;
    gap: 2px;
    padding: 4px;
    border-radius: var(--r-card);
    background: var(--panel);
    box-shadow: var(--pop);
    animation: pop 0.2s var(--ease-out);
}

.reaction-picker button {
    width: 32px;
    height: 32px;
    border-radius: var(--r-row);
    font-size: 17px;
    line-height: 1;
}

@media (hover: hover) {
    .reaction-picker button:hover {
        background: var(--hover);
    }
}

/* ─── Tool cards ───────────────────────────────────────────── */

/* What Pi did between its words: a card with one line ("Read 2 files, ran 1 command · 18s") that opens into a
 * timeline. */
.activity {
    min-width: 0;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    overflow: hidden;
}

.entry-anchor {
    display: block;
    height: 0;
}

/* One between rows takes no room: the gap before it is taken back. */
.entry-mark {
    margin-top: calc(-16px * var(--space-y));
}

.activity-head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    /* 40px, 35px, and 30px; a thumb's 34px at least on a touch screen. */
    min-height: calc(22px + 18px * var(--space-y));
    padding: 0 calc(12px * var(--space-x));
    text-align: left;
    font-size: 13px;
    line-height: 1.5;
    color: var(--muted);
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

.activity.open > .activity-head {
    border-bottom: 1px solid var(--hair);
}

@media (hover: hover) {
    .activity-head:hover {
        color: var(--text);
        background: var(--hover);
    }
}

/* Inside a card that cuts off what is past it. */
:is(.activity-head, .step-head):focus-visible {
    outline-offset: -2px;
}

.activity-summary {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.activity-failed {
    flex: none;
    padding: 1px 7px;
    border-radius: var(--r-pill);
    background: var(--err-soft);
    color: var(--err);
    font: 500 11px var(--sans);
}

.activity-time {
    flex: none;
    font: 11.5px var(--mono);
    font-variant-numeric: tabular-nums;
    color: var(--faint);
}

.activity-time.live {
    color: var(--accent);
}

/* The timeline: a line per call, each with its mark on a thin rule. */
.timeline {
    position: relative;
    padding: calc(6px * var(--space-y)) 0;
    animation: unroll var(--t-in) var(--ease-out);
}

/* A group that is one thought alone: its words, under the line that names it. */
.activity-thought {
    padding: calc(10px * var(--space-y)) calc(12px * var(--space-x)) calc(12px * var(--space-y));
    animation: unroll var(--t-in) var(--ease-out);
}

.timeline::before {
    content: "";
    position: absolute;
    left: calc(var(--timeline-x) - 0.5px);
    top: 20px;
    bottom: 20px;
    width: 1px;
    background: var(--hair-2);
}

.step {
    position: relative;
    min-width: 0;
}

.step-line {
    display: flex;
    align-items: center;
    min-width: 0;
}

.step-head {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: var(--step-gap);
    min-height: 34px;
    padding: 0 14px 0 calc(var(--timeline-x) - var(--step-mark-size) / 2);
    text-align: left;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .step-head:hover {
        background: var(--hover);
    }
}

/* Just finished: the line flashes its success color once. */
.step.settled > .step-line > .step-head {
    animation: settle 0.9s var(--ease-out);
}

@keyframes settle {
    from {
        background-color: color-mix(in srgb, var(--ok) 14%, transparent);
    }
}

/* How the call went, in a circle on the rule: its tint over the window's color, so the rule does not show through. */
.step-mark {
    --tint: var(--card-2);
    flex: none;
    display: grid;
    place-items: center;
    width: var(--step-mark-size);
    height: var(--step-mark-size);
    border-radius: 50%;
    background: linear-gradient(var(--tint), var(--tint)), var(--bg);
    box-shadow: 0 0 0 3px var(--bg);
    color: var(--muted);
    font: 600 10px / 1 var(--mono);
    transition:
        background-color var(--t-border) var(--ease-out),
        color var(--t-border) var(--ease-out);
}

.step-mark.done {
    --tint: var(--ok-soft);
    color: var(--ok);
}

.step-mark.error {
    --tint: var(--err-soft);
    color: var(--err);
}

.step-mark.approval {
    --tint: var(--warn-soft);
    color: var(--warn);
    box-shadow:
        inset 0 0 0 1px var(--warn-line),
        0 0 0 3px var(--bg);
}

.step-mark.running,
.step-mark.agent {
    --tint: var(--accent-soft);
    color: var(--accent);
}

.step-mark.thought {
    --tint: color-mix(in srgb, var(--spark) 16%, transparent);
    color: var(--spark);
}

/* Light themes' magenta can be faint as text on their ground: toward the foreground, as code's colors are. */
:root[data-mode="light"] .step-mark.thought {
    color: color-mix(in oklab, var(--spark) 60%, var(--body));
}

.step-label {
    flex: none;
    max-width: 45%;
    font: 600 12.5px var(--mono);
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.step-subject {
    flex: 1;
    min-width: 0;
    font: 12.5px var(--mono);
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.step-meta {
    flex: none;
    max-width: 40%;
    font: 12px var(--mono);
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-variant-numeric: tabular-nums;
}

.step-meta.ok {
    color: var(--ok);
}

.step-meta.warn {
    color: var(--warn);
}

.step-meta.err {
    color: var(--err);
}

/* A subagent's line goes to it. */
.step-open {
    flex: none;
    height: 28px;
    margin-right: 8px;
    padding: 0 8px;
    border-radius: var(--r-seg);
    font-size: 12px;
    color: var(--accent);
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .step-open:hover {
        background: var(--hover);
    }
}

/* Who allowed or denied a call Lancet Guard asked about. */
.step-decision {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 14px 6px calc(var(--timeline-x) + var(--step-mark-size) / 2 + var(--step-gap));
    font-size: 12px;
    color: var(--muted);
}

.step-decision.allowed .icon {
    color: var(--ok);
}

.step-decision.denied .icon {
    color: var(--err);
}

/* Under a line, in line with its words: what the call made, and once tapped, its input and output. */
.step-extras,
.step-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    margin: 2px 14px 10px calc(var(--timeline-x) + var(--step-mark-size) / 2 + var(--step-gap));
}

.step-extras + .step-body {
    margin-top: 0;
}

.step-body {
    animation: unroll var(--t-in) var(--ease-out);
}

.step-extras > .thumbs {
    margin-top: 0;
}

.step-extras > .artifact-preview {
    max-width: min(100%, 420px);
}

.step-extras > .artifact-preview img {
    max-height: 240px;
}

.thought-body {
    max-height: 50vh;
    overflow: auto;
    padding: 10px 12px;
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    background: var(--code-bg);
    font-size: 13px;
    line-height: 1.55;
    color: var(--muted);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.tool-note {
    white-space: pre-wrap;
    font-size: 13px;
    color: var(--muted);
}

.step-body .dv-block {
    border-radius: var(--r-control);
    overflow: hidden;
    font-size: 0.76rem;
    line-height: 1.6;
}

pre.output,
pre.cmd,
pre.diff {
    margin: 0;
    padding: 10px 12px;
    max-height: 45vh;
    overflow: auto;
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    background: var(--code-bg);
    color: var(--body);
    font: 12px / 1.55 var(--mono);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

pre.cmd {
    color: var(--ok);
}

pre.output.error {
    color: var(--err);
}

pre.diff .add {
    color: var(--ok);
}

pre.diff .del {
    color: var(--err);
}

.cmd-sign {
    color: var(--faint);
}

/* An artifact a call made, or the browser it used: a way there. */
.artifact-link {
    align-self: flex-start;
    max-width: 100%;
    min-height: 30px;
    padding: 0 8px;
    margin-left: -8px;
    border-radius: var(--r-seg);
    text-align: left;
    font-size: 12.5px;
    color: var(--accent);
    overflow-wrap: anywhere;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .artifact-link:hover {
        background: var(--hover);
    }
}

/* A subagent's report: a card. */
.report {
    padding: 12px 14px;
    border: 1px solid var(--hair);
    border-radius: var(--r-window);
    background: var(--card);
}

.report.failed {
    border-color: var(--err-line);
}

/* Reports that arrived together, as one message to Pi: a card each. */
.report-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.report-head {
    display: flex;
    gap: 0.4rem;
    align-items: center;
    margin-bottom: 4px;
    font-size: 13px;
    color: var(--muted);
}

.report-name {
    color: var(--text);
    font-weight: 600;
    font-family: var(--mono);
}

.report-why {
    color: var(--err);
    font-size: 13px;
    overflow-wrap: anywhere;
}

/* Lancet Guard asks before a call: at the end of the turn, until someone answers. */
.approval {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    border: 1px solid var(--warn-line);
    border-radius: calc(var(--r-window) + 2px);
    background: var(--warn-soft);
    animation: pop 0.35s var(--ease-out);
}

.approval-head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}

.approval-shield {
    flex: none;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: var(--r-row);
    background: color-mix(in srgb, var(--o-yellow) 16%, transparent);
    color: var(--warn);
}

.approval-title {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.approval-ask {
    font-size: 14.5px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--text);
}

.approval-reason {
    font-size: 13px;
    line-height: 1.5;
    color: var(--muted);
}

.approval pre.cmd {
    padding: 10px 12px;
    border: 0;
    font-size: 12.5px;
    line-height: 1.5;
}

.approval-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

.approval-actions .button {
    height: 36px;
    padding: 0 16px;
    border-radius: var(--r-control);
    font-size: 13.5px;
}

.approval-actions .button.primary {
    padding: 0 18px;
}

/* The shared button's least height is 38px; touch screens keep their thumb height. */
@media not (pointer: coarse) {
    .approval-actions .button {
        min-height: 0;
    }
}

.approval-actions .button.deny {
    border-color: transparent;
    background: var(--card-2);
    color: var(--text);
}

@media (hover: hover) {
    .approval-actions .button.deny:hover {
        color: var(--err);
    }
}

/* On a phone: the answers share the width, thumb-tall. */
@media (max-width: 699px) {
    .approval {
        padding: 14px;
    }

    .approval-shield {
        width: 30px;
        height: 30px;
    }

    .approval-ask {
        font-size: 14px;
    }

    .approval-actions {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }

    .approval-actions .button {
        height: 42px;
        border-radius: calc(var(--r-control) + 1px);
        font-size: 14px;
    }
}

/* The live turn's last line: what Pi does now, for how long, and how to stop it. */
.live-line {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
    padding: 2px 2px 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--muted);
    animation: fade var(--t-fade) var(--ease-almost);
}

/* A dot with a soft ring, pulsing; the warning color while a call waits for an approval. */
.live-dot {
    flex: none;
    width: 8px;
    height: 8px;
    margin-inline: 4px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-soft);
    animation: pulse 1.4s infinite;
}

.live-line.waiting .live-dot {
    background: var(--warn);
    box-shadow: 0 0 0 4px var(--warn-soft);
}

.live-state {
    flex: none;
    color: var(--accent);
}

.live-line.waiting .live-state {
    color: var(--warn);
}

.live-time {
    flex: none;
    font: 11.5px var(--mono);
    font-variant-numeric: tabular-nums;
    color: var(--faint);
}

.live-why {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.live-esc {
    flex: none;
    margin-left: auto;
    font: 11px var(--mono);
    color: var(--faint);
}

/*
 * Show thinking adds the timeline's bare chevron before the dot. It turns up when open, toward the thought above the
 * line. Its hit area reaches past the glyph without drawing a box, and the gap after it stays the line's own.
 */
.live-fold {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 14px;
    height: 14px;
    margin-right: -4px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--faint);
    position: relative;
    transition: color var(--t-hover) var(--ease-out);
}

.live-fold::before {
    content: "";
    position: absolute;
    inset: -8px;
}

.live-fold.open {
    color: var(--muted);
}

.live-fold.open > .chev {
    transform: rotate(-90deg);
}

@media (hover: hover) {
    .live-fold:hover {
        color: var(--body);
    }
}

@media (pointer: coarse) {
    .live-fold::before {
        inset: -13px;
    }
}

/* A quiet reading area, not another timeline card. The existing Thought steps and their boxes are unchanged. */
.live-thought {
    min-width: 0;
    padding: 10px 14px 12px;
    border-radius: var(--r-card);
    background: var(--card);
    animation: fade var(--t-fade) var(--ease-almost);
}

.live-thought-label {
    margin-bottom: 4px;
    color: var(--faint);
    font-size: 11.5px;
}

.live-thought-text {
    max-height: min(32vh, 260px);
    overflow-y: auto;
    overscroll-behavior: contain;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
    font-size: 13px;
    line-height: 1.65;
    color: var(--muted);
}

.live-thought-text.is-empty {
    color: var(--faint);
}

.live-thought-text.streaming::after {
    content: "";
    display: inline-block;
    width: 2px;
    height: 1em;
    margin-left: 3px;
    vertical-align: -2px;
    background: var(--accent);
    animation: blink 1s steps(2) infinite;
}

.error-box {
    padding: 10px 14px;
    border: 1px solid var(--err-line);
    border-radius: var(--r-card);
    background: var(--err-soft);
    color: var(--err);
    font-size: 13.5px;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.divider {
    text-align: center;
    color: var(--muted);
    font-size: 13px;
    border-top: 1px solid var(--hair);
    padding-top: 0.5rem;
}

.divider-body {
    text-align: left;
    margin-top: 0.5rem;
    font-size: 13.5px;
}

.history {
    display: flex;
    flex-direction: column;
    gap: 16px;
    opacity: 0.75;
}

.history > :is(.user-row, .report, .report-group):not(:first-child) {
    margin-top: 10px;
}

.pulse {
    width: 7px;
    height: 7px;
    border-radius: var(--radius);
    background: var(--accent);
    display: inline-block;
    animation: pulse 1.4s infinite;
}

@keyframes pulse {
    50% {
        opacity: 0.35;
    }
}

/* The way back to the newest message. */
.jump {
    position: sticky;
    bottom: 0.8rem;
    left: 100%;
    margin-right: 0.8rem;
    width: 40px;
    height: 40px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-pill);
    background: var(--bg);
    box-shadow: var(--shadow);
    color: var(--body);
    display: grid;
    place-items: center;
    float: right;
    animation: popin var(--t-in) var(--ease-out);
    transition:
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        transform 90ms var(--ease-out);
}

@media (hover: hover) {
    .jump:hover {
        border-color: var(--accent-line);
        color: var(--accent);
    }
}

.jump:active {
    transform: scale(0.92);
}

/* ─── Composer ─────────────────────────────────────────────── */

.composer-wrap {
    padding: 4px calc(24px * var(--space-x))
        calc(env(safe-area-inset-bottom) + 12px * var(--space-y));
    max-width: var(--composer-width);
    width: 100%;
    margin: 0 auto;
}

@media (max-width: 699px) {
    .composer-wrap {
        padding-inline: calc(12px * var(--space-x));
    }
}

/*
 * What is above the message box: who is typing, the queue, and the bars. `dock.js` shares its room: the bars show
 * whole, and the queue and the subagents' list take what is left of its share, and scroll.
 */
.inbox-count {
    display: none;
    height: 1.25rem;
    line-height: 1.25rem;
    margin: 0 0 0.25rem 0.1rem;
    color: var(--muted);
    font-size: 12px;
}

/* How many wait, when the queue does not show them all. */
.dock[data-count="on"] > .inbox-count {
    display: block;
}

/* Folded for the subagents' list: out of sight, its rows still laid out for `dock.js` to measure. */
.dock[data-queue="folded"] > .inbox {
    visibility: hidden;
}

/* Too little room even so (a phone on its side with every bar up): the dock stops, and scrolls. */
.dock[data-capped] {
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* There, a swipe on the queue that reaches its end goes on to scroll the dock, to the bars below it. */
.dock[data-capped] > .inbox {
    overscroll-behavior: auto;
}

/* Little room for the conversation: each bar keeps one line, its words cut short, its buttons whole. */
.dock[data-compact] > :is(.plan-bar, .goal-bar, .watch-bar, .trust-bar) {
    flex-wrap: nowrap;
}

.dock[data-compact] > :is(.plan-bar, .goal-bar, .watch-bar, .trust-bar) > .grow {
    flex: 1 1 0;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dock[data-compact] > :is(.plan-bar, .goal-bar, .watch-bar, .trust-bar) > :not(.grow) {
    flex: none;
    white-space: nowrap;
}

.dock[data-compact] .trust-actions {
    gap: 0.5rem;
}

/* Messages waiting for Pi: a few rows' height at most, so the conversation stays in view; more scroll inside. */
.inbox {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 6px;
    max-height: min(28vh, 12rem);
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* A message waiting for Pi: Steer or Queue, what it says, and a way to take it back. */
.queued {
    /* Its own height in a queue that scrolls: shrunk, the dock would measure it smaller and let it grow again. */
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 34px;
    padding: 0 4px 0 12px;
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    background: var(--card);
    font-size: 13px;
}

.queued-mode {
    color: var(--accent);
    font-weight: 600;
    flex: none;
}

.queued-text {
    flex: 1;
    min-width: 0;
    align-self: stretch;
    padding: 0;
    color: var(--text);
    font: inherit;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Tapped: what the queue holds of the message (its start), wrapped (the queue scrolls past a few lines), with who sent it
   and its × at its top. */
.queued-text.open {
    padding: 8px 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.queued:has(> .queued-text.open) {
    align-items: flex-start;
}

.queued:has(> .queued-text.open) > .queued-mode {
    padding-top: 8px;
}

.queued:has(> .queued-text.open) > .queued-remove {
    margin-top: 4px;
}

.queued .queued-remove {
    width: 26px;
    height: 26px;
    color: var(--muted);
}

/* A thumb's room around the small mark. */
@media (pointer: coarse) {
    .queued .queued-remove::after {
        content: "";
        position: absolute;
        inset: -8px -4px;
    }
}

/* Slash commands: suggestions while typing a name, then a hint for the one that will run. */
.commands {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 6px;
    padding: 4px;
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    max-height: 40vh;
    overflow-y: auto;
    animation: rise-in 0.3s var(--ease-out);
}

.command {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    width: 100%;
    text-align: left;
    padding: 7px 10px;
    border-radius: var(--r-row);
    font-size: 13px;
    transition: background-color var(--t-hover) var(--ease-out);
}

.command.on {
    background: var(--hover);
}

@media (hover: hover) {
    .command:hover {
        background: var(--hover);
    }
}

.command-name {
    color: var(--accent);
    flex: none;
}

.command-args {
    color: var(--muted);
    flex: none;
}

.command-description {
    color: var(--muted);
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* File mentions: an icon, the name with what matched marked, then its folder. */
.file-option {
    align-items: center;
}

.file-icon {
    flex: none;
    color: var(--muted);
}

.file-option.on .file-icon {
    color: var(--accent);
}

.file-name {
    flex: none;
    max-width: 60%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.file-option mark {
    background: none;
    color: var(--accent);
    font-weight: 700;
}

.file-note {
    font-size: 12.5px;
    color: var(--muted);
    padding: 7px 10px;
}

.command-hint.wraps {
    white-space: normal;
}

.command-hint {
    font-size: 12.5px;
    padding: 0 10px 6px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The message box: a card that takes the accent's line while it has the focus. */
.composer {
    container: composer / inline-size;
    position: relative;
    background: var(--card);
    border: 1px solid var(--hair-2);
    border-radius: var(--r-sheet);
    box-shadow: var(--shadow);
    transition: border-color var(--t-border) var(--ease-out);
}

.composer:focus-within {
    border-color: var(--accent-line);
}

@media (max-width: 699px) {
    .composer {
        border-radius: var(--r-float);
    }
}

.composer .files {
    margin: 0;
    padding: 10px 14px 0;
}

/* One line to start with, growing with the text (`fitBox`). */
.composer textarea {
    display: block;
    border: 0;
    border-radius: 0;
    outline: none;
    background: none;
    color: var(--text);
    resize: none;
    padding: calc(14px * var(--space-y)) calc(16px * var(--space-x)) 2px;
    max-height: 40vh;
    font-size: 15px;
    line-height: 1.5;
}

/* Touch screens keep 16px, below which iOS zooms into the field. */
@media (pointer: coarse) {
    .composer textarea {
        padding: calc(13px * var(--space-y)) calc(15px * var(--space-x)) 2px;
        font-size: 16px;
    }
    /* The status line's own room below it is enough. */
    .composer-wrap {
        padding-bottom: calc(env(safe-area-inset-bottom) + 2px);
    }
}

.composer-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: calc(6px * var(--space-y)) calc(10px * var(--space-x)) calc(4px + 6px * var(--space-y));
}

/* On a phone its bottom keeps 5px or more at every density: the status line's guard reaches up into it for a thumb's
 * tap. */
@media (max-width: 699px) {
    .composer-row {
        gap: 4px;
        padding: calc(6px * var(--space-y)) calc(8px * var(--space-x))
            calc(3px + 5px * var(--space-y));
    }
}

.composer-row .attach-button {
    width: 32px;
    height: 32px;
    border-radius: var(--r-control);
    color: var(--muted);
}

/* The model and its thinking level: opens the model menu. */
.model-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    height: 30px;
    padding: 0 10px 0 11px;
    border-radius: var(--r-pill);
    background: var(--hover);
    font-size: 13px;
    color: var(--text);
    white-space: nowrap;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .model-chip:hover {
        background: var(--card-2);
    }
}

.model-chip .model-spark {
    color: var(--accent);
}

.model-chip .model-name {
    min-width: 4ch;
    overflow: hidden;
    text-overflow: ellipsis;
}

.model-chip .model-level {
    color: var(--muted);
}

/* The chevron points down: the menu opens up from it, over the conversation. */
.model-chip .model-caret {
    color: var(--faint);
    transform: rotate(90deg);
}

.model-chip.warn {
    color: var(--warn);
}

/* A narrow message box (a narrow pane, or a phone) gives up the level first, then, while Pi works and Steer and Queue
 * take room, Plan and the sparkle: the model's name stays. */
@container composer (max-width: 340px) {
    .model-chip .model-level {
        display: none;
    }
}

@container composer (max-width: 540px) {
    .composer.busy .model-chip .model-level {
        display: none;
    }
}

@container composer (max-width: 400px) {
    .composer.busy :is(.plan-chip, .model-caret) {
        display: none;
    }
}

@container composer (max-width: 355px) {
    .composer.busy .model-chip .model-spark {
        display: none;
    }
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    border: 1px solid var(--line);
    background: var(--card-2);
    border-radius: var(--radius);
    padding: 0.2rem 0.55rem;
    font-size: 0.78rem;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition:
        background-color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

/* An attachment: a long name gives way, never its size or the button that removes it. */
.files .chip > * {
    flex: none;
}

.files .chip > .chip-name {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (hover: hover) {
    button.chip:hover {
        border-color: var(--edge);
        color: var(--text);
    }
}

.chip.toggle.on {
    color: var(--accent);
    border-color: var(--accent-line);
    background: var(--accent-soft);
}

/* Plan mode: an outlined pill, filled softly in the accent while it is on. */
.composer-row .plan-chip {
    flex: none;
    height: 30px;
    padding: 0 12px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-pill);
    font-size: 13px;
    color: var(--muted);
    white-space: nowrap;
    transition:
        background-color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .composer-row .plan-chip:hover {
        color: var(--text);
    }
}

.composer-row .plan-chip.on {
    border-color: var(--accent-line);
    background: var(--accent-soft);
    color: var(--accent);
}

/* While Pi works: whether a message steers the run or waits for its end. */
.mode-switch {
    flex: none;
    display: flex;
    padding: 2px;
    border-radius: var(--r-pill);
    background: var(--hover);
}

.mode-switch button {
    height: 28px;
    padding: 0 10px;
    border-radius: var(--r-pill);
    font-size: 12.5px;
    font-weight: 500;
    color: var(--muted);
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

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

.mode-switch button.on {
    color: var(--text);
    background: var(--raised);
}

.stop-button,
.send-button {
    flex: none;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        transform 90ms var(--ease-out);
}

.stop-button:active,
.send-button:active:not(:disabled) {
    transform: scale(0.92);
}

/* Stop: a square in the failure color, on its soft tint. */
.stop-button {
    background: var(--err-soft);
}

@media (hover: hover) {
    .stop-button:hover {
        background: color-mix(in srgb, var(--o-red) 22%, transparent);
    }
}

.stop-square {
    width: 11px;
    height: 11px;
    border-radius: var(--r-mark);
    background: var(--err);
}

/* Send: the accent with something to send, quiet without; then a tap on it goes to the text (composer.js). */
.send-button {
    background: var(--card-2);
    color: var(--faint);
    cursor: default;
}

.send-button:disabled {
    pointer-events: none;
}

.send-button.ready {
    background: var(--accent-fill);
    color: var(--accent-ink);
    cursor: pointer;
}

@media (hover: hover) {
    .send-button.ready:hover {
        background: color-mix(in oklab, var(--accent-fill) 85%, var(--text));
    }
}

.send-button.ready .icon {
    transition: transform var(--t-in) var(--ease-out);
}

@media (hover: hover) {
    .send-button.ready:hover .icon {
        transform: translateY(-2px);
    }
}

/* Dictation (voice.js): a quiet mic beside Send; while it listens, the accent and a ring that breathes. */
.composer-row .composer-mic {
    width: 32px;
    height: 32px;
    border-radius: var(--r-control);
    color: var(--muted);
}

.mic-button.listening {
    color: var(--accent);
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 1px var(--accent-line);
}

.mic-button.listening::after {
    content: "";
    position: absolute;
    inset: 0;
    border: 1px solid var(--accent);
    border-radius: var(--r-control);
    pointer-events: none;
    animation: listening 1.6s var(--ease-out) infinite;
}

@keyframes listening {
    from {
        opacity: 0.9;
        transform: scale(1);
    }
    to {
        opacity: 0;
        transform: scale(1.35);
    }
}

/* Still, the inset ring alone says it listens. */
:root[data-motion="reduced"] .mic-button.listening::after {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    :root:not([data-motion="full"]) .mic-button.listening::after {
        display: none;
    }
}

/* Square buttons elsewhere: the chat's send. */
.round {
    width: 36px;
    height: 36px;
    border-radius: var(--radius);
    display: grid;
    place-items: center;
    flex: none;
    animation: popin 0.3s var(--ease-out);
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        transform 90ms var(--ease-out);
}

.round:active:not(:disabled) {
    transform: scale(0.9);
}

.round.send {
    background: var(--accent-fill);
    color: var(--accent-ink);
}

@media (hover: hover) {
    .round.send:not(:disabled):hover {
        background: color-mix(in oklab, var(--accent-fill) 85%, var(--text));
    }
}

.round.send:not(:disabled) .icon {
    transition: transform var(--t-in) var(--ease-out);
}

@media (hover: hover) {
    .round.send:not(:disabled):hover .icon {
        transform: translateY(-2px);
    }
}

.round.send:disabled {
    background: var(--raised);
    color: var(--muted);
    cursor: default;
}

/* Under the message box: who is here, how fast the last answer came, the context, the cache, the spend, and Lancet
 * Guard. Its numbers are in mono. */
.status-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 4px 14px;
    padding-top: calc(3px + 5px * var(--space-y));
    font-size: 11.5px;
    line-height: 16px;
    color: var(--muted);
    white-space: nowrap;
}

.status-line .num {
    font: 11px var(--mono);
    font-variant-numeric: tabular-nums;
}

.status-line .context {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.status-line .meter {
    width: 36px;
}

/* Lancet Guard: a pill that opens Extensions, green while it guards and yellow while it does not. */
.status-line .guard {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: var(--r-pill);
    background: var(--ok-soft);
    color: var(--ok);
    font: inherit;
}

.status-line .guard.off {
    background: var(--warn-soft);
    color: var(--warn);
}

/* How fast the last answer came, once Appearance turns it on: its two halves spaced like the line's items. */
.status-line .speed {
    display: inline-flex;
    align-items: center;
    column-gap: inherit;
}

.status-line .speed .short {
    display: none;
}

/* A line too narrow for one row takes shorter forms, one after another, until it fits (`fitStatus`, composer.js). */
.status-line[data-short~="words"] {
    column-gap: 8px;
}

.status-line[data-short~="words"] .speed {
    column-gap: 1ch;
}

.status-line[data-short~="words"] .speed .long,
.status-line[data-short~="here"] .here.alone,
.status-line[data-short~="guard"] .guard .word,
.status-line[data-short~="cache"] .cache,
.status-line[data-short~="wait"] .speed .wait,
.status-line[data-short~="wait"] .speed.wait-only {
    display: none;
}

.status-line[data-short~="words"] .speed .short {
    display: inline;
}

/* Words that go from sight but not from a screen reader: "77%" is still the context's, "1.2s" the first token's. */
.status-line[data-short~="words"] .speed .rate + .wait .word,
.status-line[data-short~="context"] .context .word {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Narrow, the wait has no words of its own: "42 tok/s · 1.2s". */
.status-line[data-short~="words"] .speed .rate + .wait::before {
    content: "·";
    margin-right: 1ch;
}

/* ─── Extensions ───────────────────────────────────────────── */

.extension {
    display: flex;
    gap: 14px;
    padding: 12px 14px;
    background: var(--bg);
}

.notifications-sheet .extension,
.message-worktree {
    align-items: center;
}

.guard-confirm {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 8px;
    padding: 10px 12px;
    border-radius: var(--r-control);
    border: 1px solid var(--warn-line);
    background: var(--warn-soft);
    color: var(--text);
    font-size: 12.5px;
}

.guard-confirm .primary {
    background: var(--warn);
    border-color: transparent;
}

.extension-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    overflow-wrap: anywhere;
}

.extension-title {
    font-size: 14px;
    color: var(--text);
}

.extension.off .extension-title {
    color: var(--muted);
}

.extension-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.45rem;
}

/* The on and off switch (`Switch` in ui.js), in every sheet that has one. */
.switch {
    position: relative;
    width: 38px;
    height: 22px;
    flex: none;
    padding: 3px;
    border-radius: var(--r-pill);
    background: var(--hair-2);
    border: 0;
    transition:
        background-color var(--t-in) var(--ease-out),
        border-color var(--t-in) var(--ease-out);
}

.switch span {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 16px;
    height: 16px;
    border-radius: var(--r-pill);
    background: var(--text);
    box-shadow: 0 1px 2px var(--sh);
    transition:
        transform var(--t-in) var(--ease-out),
        background-color var(--t-in) var(--ease-out);
}

.switch.on {
    background: var(--accent-fill);
}

.switch.on span {
    transform: translateX(16px);
    background: var(--accent-ink);
}

@media (pointer: coarse) {
    .switch::before {
        content: "";
        position: absolute;
        inset: -10px -3px;
    }
}

.switch:disabled {
    opacity: 0.45;
    cursor: default;
}

/* ─── The rail: Pi, the tools, and you; folded, the sessions too ─── */

.rail {
    width: 56px;
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    min-height: 0;
    padding: calc(env(safe-area-inset-top) + 12px) 0 calc(env(safe-area-inset-bottom) + 12px);
    border-right: 1px solid var(--hair);
    /* A short screen (a phone on its side) scrolls the rail rather than cut off its last buttons. */
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-width: none;
}

.rail-brand,
.rail-button {
    position: relative;
    flex: none;
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    border-radius: var(--r-control);
}

/* Phones and touch screens: a thumb's size. */
@media (max-width: 959px), (pointer: coarse) {
    .rail-brand,
    .rail-button {
        width: 44px;
        height: 44px;
    }
}

.rail-brand {
    font:
        22px/1 Georgia,
        serif;
    color: var(--brand);
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    button.rail-brand:hover {
        background: var(--hover);
    }
}

.rail-button {
    color: var(--muted);
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .rail-button:hover {
        background: var(--hover);
        color: var(--text);
    }
}

.rail-gap {
    flex: none;
    height: 6px;
}

.rail-fill {
    flex: 1;
}

/* The sessions, while the list shows. */
.rail-button.on {
    color: var(--text);
    background: var(--card-2);
}

/* A tool whose window is open (peek tiles, PiP, the subagents board, an extension's page): the accent's soft fill. */
.rail-button.open {
    color: var(--accent);
    background: var(--accent-soft);
}

.rail-new,
.rail-running.lit,
.rail-agents.lit,
.rail-pip.lit {
    color: var(--accent);
}

.rail-new .icon {
    stroke-width: 2.4;
}

/* How many: sessions where Pi works, or subagents that work or wait. */
.rail-count {
    position: absolute;
    top: 1px;
    right: 0;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    display: grid;
    place-items: center;
    border-radius: var(--r-pill);
    background: var(--accent-fill);
    color: var(--accent-ink);
    box-shadow: 0 0 0 2px var(--bg);
    font: 600 9.5px/1 var(--mono);
    animation: popin var(--t-in) var(--ease-out);
}

/* A dot at a button's corner: something new in PiP, or a subagent that failed or waits for an approval. */
.rail-trouble,
.rail-news {
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    box-shadow: 0 0 0 2px var(--bg);
}

.rail-trouble {
    background: var(--err);
}

.rail-news {
    right: 5px;
    bottom: 5px;
    background: var(--accent);
}

@media (max-width: 959px), (pointer: coarse) {
    .rail-count {
        top: 4px;
        right: 3px;
    }
    .rail-trouble {
        right: 8px;
        bottom: 8px;
    }
    .rail-news {
        right: 9px;
        bottom: 9px;
    }
}

/* You: a round avatar, a little apart from the tools. */
.rail-me {
    margin-top: 4px;
    border-radius: 50%;
}

/* Folded: the sessions as numbered tiles, like Waybar's workspaces, between New and the tools. */
.rail-items {
    position: relative;
    flex: 1;
    min-height: 0;
    width: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 6px 0;
    border-top: 1px solid var(--hair);
    border-bottom: 1px solid var(--hair);
    scrollbar-width: none;
}

.rail:has(.rail-items) {
    overflow-y: hidden;
}

/* The open session's tile is lit by a soft fill that slides from tile to tile, under the numbers. */
.rail-items .slide-y {
    left: 50%;
    width: 36px;
    margin-left: -18px;
    border-radius: var(--r-control);
    background: var(--accent-soft);
    z-index: 0;
}

.ws {
    position: relative;
    z-index: 1;
    flex: none;
    width: 36px;
    height: 32px;
    display: grid;
    place-items: center;
    border-radius: var(--r-row);
    font: 600 12.5px var(--mono);
    color: var(--muted);
    animation: rise-in 0.38s var(--ease-out) backwards;
    animation-delay: calc(min(var(--i, 0), 14) * 18ms);
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

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

.ws.active {
    color: var(--accent);
}

.ws.waiting {
    color: var(--warn);
}

/* A working session's tile: a still underline, accent to spark. */
.ws.busy::after {
    content: "";
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: 3px;
    height: 2px;
    border-radius: 1px;
    background: linear-gradient(90deg, var(--accent), var(--spark));
}

.ws .unread-dot {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
}

/* ─── Sessions: the list beside the rail ───────────────────────── */

.sessions {
    flex: 1;
    /* Narrower, as the sidebar unfolds, it is cut off rather than squeezed. */
    min-width: 204px;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: calc(env(safe-area-inset-top) + 14px) 12px calc(env(safe-area-inset-bottom) + 10px);
    container: sessions / inline-size;
}

.sessions-head {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 32px;
    padding-left: 4px;
    flex: none;
}

.sessions-name {
    font-weight: 600;
    font-size: 15px;
    color: var(--text);
}

.sessions-count {
    margin-right: auto;
    font: 11px var(--mono);
    color: var(--faint);
}

.new-button {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 30px;
    padding: 0 11px 0 9px;
    border-radius: calc(var(--r-row) - 1px);
    background: var(--accent-fill);
    color: var(--accent-ink);
    font-weight: 600;
    font-size: 13px;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .new-button:hover {
        background: color-mix(in oklab, var(--accent-fill) 85%, var(--text));
    }
}

.new-button .icon {
    stroke-width: 2.4;
}

/* A search field: the sheets' (providers, a message's, the pickers') and the session list's. */
.search {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 36px;
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    padding: 0 12px;
    color: var(--muted);
    margin-bottom: 0;
    transition:
        border-color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

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

.search:has(input:focus) {
    border-color: var(--accent-line);
    color: var(--muted);
}

.search input {
    flex: 1;
    border: 0;
    border-radius: 0;
    background: none;
    padding: 7px 0;
    min-width: 0;
    font-size: 13.5px;
}

.search input:focus-visible {
    outline: none;
}

@media (pointer: coarse) {
    .search input {
        font-size: 16px;
    }
}

.search kbd {
    cursor: pointer;
    flex: none;
    border: 1px solid var(--hair);
    border-radius: var(--r-tag);
    font-size: 10.5px;
    color: var(--faint);
}

.sessions .search {
    flex: none;
    margin: 12px 0 0;
    display: flex;
    align-items: center;
    gap: 8px;
    height: 34px;
    min-height: 34px;
    padding: 0 6px 0 10px;
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    color: var(--muted);
    transition:
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .sessions .search:hover {
        border-color: var(--hair-2);
    }
}

.sessions .search:has(input:focus) {
    border-color: var(--accent-line);
    background: var(--card);
    color: var(--muted);
}

.sessions .search.filled {
    border-color: var(--accent-line);
    color: var(--accent);
}

/* The field's frame shows the focus. */
.sessions .search input:focus-visible,
.board-search input:focus-visible {
    outline: none;
}

.sessions .search input {
    flex: 1;
    min-width: 0;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    font-size: 13px;
    color: var(--text);
}

/* "Ctrl K": a small tag at the field's end. */
.sessions .search-keys {
    padding: 4px 6px;
    border: 1px solid var(--hair);
    border-radius: var(--r-tag);
    font: 10.5px / 1 var(--mono);
    color: var(--faint);
    white-space: nowrap;
    opacity: 1;
}

.search-clear {
    position: relative;
    flex: none;
    width: 22px;
    height: 22px;
    display: grid;
    place-items: center;
    color: var(--muted);
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .search-clear:hover {
        background: var(--hover);
        color: var(--text);
    }
}

/* Touch screens have no Ctrl K: the launcher's button takes its place. */
.search-launcher {
    position: relative;
    flex: none;
    width: 22px;
    height: 22px;
    display: none;
    place-items: center;
    color: var(--muted);
}

@media (pointer: coarse) {
    .search-launcher {
        display: grid;
    }
    .search-launcher::before {
        content: "";
        position: absolute;
        inset: -9px;
    }
}

/* Recent, Folders, Archived: a segmented track, its raised segment sliding to the one chosen. */
.session-tabs {
    position: relative;
    flex: none;
    margin-top: 10px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    padding: 3px;
    border-radius: var(--r-control);
    background: var(--card);
}

.session-tabs button {
    position: relative;
    z-index: 1;
    height: 26px;
    display: grid;
    place-items: center;
    padding: 0 6px;
    border-radius: var(--r-seg);
    font-size: 12.5px;
    color: var(--muted);
    transition: color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .session-tabs button:hover {
        color: var(--text);
    }
}

.session-tabs button.on {
    color: var(--text);
    font-weight: 500;
}

.slide-x {
    position: absolute;
    left: 0;
    top: 3px;
    bottom: 3px;
    border-radius: var(--r-seg);
    background: var(--raised);
    transition:
        transform var(--t-in) var(--ease-out),
        width var(--t-in) var(--ease-out);
}

.session-items {
    position: relative;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
    margin: 4px -4px 0;
    padding: 0 4px 4px;
}

/* A bar that slides from item to item: the folded rail's open session. */
.slide-y {
    position: absolute;
    left: 0.3rem;
    top: 0;
    width: 2px;
    background: var(--accent);
    z-index: 2;
    pointer-events: none;
    transition:
        transform var(--t-in) var(--ease-out),
        height var(--t-in) var(--ease-out),
        opacity var(--t-fade) var(--ease-almost);
}

.slide-x.instant,
.slide-y.instant {
    transition: none;
}

.session-group {
    display: flex;
    flex-direction: column;
}

.group-head {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: calc(4px + 10px * var(--space-y)) 8px calc(6px * var(--space-y));
    font-size: 12px;
    font-weight: 500;
    color: var(--muted);
    text-align: left;
    transition: color var(--t-hover) var(--ease-out);
}

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

.group-head:focus-visible {
    color: var(--text);
}

.group-name {
    flex: 0 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.group-name b {
    font-weight: inherit;
}

/* A folder's group: its path quiet, its last part bold, and the path cut short first when it is long. */
.group-name:has(.last) {
    display: flex;
}

.group-name .first,
.group-name .last {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.group-name .first {
    flex: 0 1 auto;
}

.group-name .last {
    flex: none;
    max-width: 100%;
    color: var(--text);
    font-weight: 600;
}

/* How many, in mono, beside the name; the fold's chevron at the end. */
.group-count {
    flex: 1;
    font: 11px var(--mono);
    color: var(--faint);
}

/* A dot on a folded group: a session inside needs you, or failed. */
.group-trouble {
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--warn);
}

.group-trouble.failed {
    background: var(--err);
}

.group-head .icon {
    color: var(--faint);
    transition: transform var(--t-in) var(--ease-out);
}

.session-group.closed .group-head .icon {
    transform: rotate(-90deg);
}

/* Groups fold smoothly: a one-row grid whose row goes from 1fr to 0fr. */
.group-body {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--t-in) var(--ease-out);
}

.group-body > div {
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.session-group.closed .group-body {
    grid-template-rows: 0fr;
}

.session-row {
    position: relative;
    padding-inline-start: calc(var(--linked-depth, 0) * 14px);
    animation: rise-in 0.38s var(--ease-out) backwards;
    animation-delay: calc(min(var(--i, 0), 14) * 18ms);
}

/*
 * Linked-session branches are decorative; each row keeps its own button and actions. Each line runs down from the middle
 * of its parent's mark, and turns with a soft corner to the row's own.
 */
.session-branches {
    position: absolute;
    inset: 0 auto 0 15px;
    display: flex;
    pointer-events: none;
    color: color-mix(in srgb, var(--muted) 60%, transparent);
}

.session-branches > span {
    position: relative;
    width: 14px;
}

.session-branches > .continues::before,
.session-branches > .elbow::before {
    content: "";
    position: absolute;
    left: 0;
    top: -1px;
    bottom: -1px;
    border-left: 1.5px solid currentColor;
}

.session-branches > .elbow::after {
    content: "";
    position: absolute;
    left: 0;
    top: -1px;
    bottom: 50%;
    width: 8px;
    border-bottom: 1.5px solid currentColor;
    border-left: 1.5px solid currentColor;
    border-bottom-left-radius: calc(var(--r-tag) + 1px);
}

/* The last child: only the corner, no line on down. */
.session-branches > .elbow:not(.continues)::before {
    display: none;
}

/* One line: the folder's color, the title, and what goes on there on the right. */
.session {
    display: grid;
    grid-template-columns: 8px minmax(0, 1fr) auto;
    align-items: center;
    gap: 0 11px;
    width: 100%;
    /* 36px, 32px, and 29px. */
    height: calc(24px + 12px * var(--space-y));
    padding: 0 10px;
    border-radius: var(--r-row);
    text-align: left;
    border: 1px solid transparent;
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .session:hover {
        background: var(--hover);
    }
}

/* Keep focus outlines inside list controls: scrolling and folding groups clip their edges. */
.group-head:focus-visible,
.session:focus-visible {
    outline-offset: -1px;
}

/* The open session: the accent's soft fill, and its title in bold. */
.session-row.active .session {
    background: var(--accent-soft);
}

.session-row.active .session-title {
    font-weight: 600;
}

/* Selected rows (Ctrl/⌘+click or drag, Shift+click): the soft fill, a border, and a check for the folder's mark. */
.session-row.selected .session {
    background: var(--accent-soft);
    border-color: var(--accent-line);
}

/* A finger held on a row, before its actions open: after the open and selected rows' fills, so it shows on them too. */
.session-row.pressing .session {
    background: var(--hover);
}

.session-mark {
    display: grid;
    place-items: center;
    width: 8px;
    height: 8px;
}

/*
 * A session's square: its folder's color (--folder), 8px with softly rounded corners, in the shape of its state. Solid:
 * finished, not read yet. Hollow and dim: read, or never run. Quadrants with one lit: working. Two bars: waiting for
 * you. A cross: failed, cut out of a solid square while not read, drawn once read.
 */
.state-mark {
    --line-w: 1.5px;
    --cut: 2px;
    --q: 3.5px;
    position: relative;
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: calc(var(--r-mark) - 0.5px);
    color: var(--folder, var(--muted));
}

.state-mark.fresh {
    background: currentColor;
}

.state-mark.seen {
    box-shadow: inset 0 0 0 var(--line-w) currentColor;
    opacity: 0.55;
}

/* Pi Pocket's spinner, in the folder's color: one lit quadrant stepping around the four. */
.state-mark.working {
    overflow: hidden;
    --dim: color-mix(in oklab, currentColor 28%, transparent);
    background:
        linear-gradient(var(--dim), var(--dim)) 0 0 / var(--q) var(--q) no-repeat,
        linear-gradient(var(--dim), var(--dim)) 100% 0 / var(--q) var(--q) no-repeat,
        linear-gradient(var(--dim), var(--dim)) 0 100% / var(--q) var(--q) no-repeat,
        linear-gradient(var(--dim), var(--dim)) 100% 100% / var(--q) var(--q) no-repeat;
}

/* Still (reduced motion), the top left quadrant stays lit. */
.state-mark.working::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: var(--q);
    height: var(--q);
    background: currentColor;
    animation: state-quadrant 1.6s steps(1, end) infinite;
}

@keyframes state-quadrant {
    0% {
        transform: translate(0, calc(var(--q) + 1px));
    }
    25% {
        transform: translate(0, 0);
    }
    50% {
        transform: translate(calc(var(--q) + 1px), 0);
    }
    75% {
        transform: translate(calc(var(--q) + 1px), calc(var(--q) + 1px));
    }
}

.state-mark.waiting {
    background: linear-gradient(90deg, currentColor 0 3px, transparent 0 5px, currentColor 0);
}

.state-mark.failed {
    background: currentColor;
    -webkit-mask:
        linear-gradient(
            45deg,
            #000 calc(50% - var(--cut) / 2),
            transparent 0 calc(50% + var(--cut) / 2),
            #000 0
        ),
        linear-gradient(
            135deg,
            #000 calc(50% - var(--cut) / 2),
            transparent 0 calc(50% + var(--cut) / 2),
            #000 0
        );
    -webkit-mask-composite: source-in;
    mask:
        linear-gradient(
            45deg,
            #000 calc(50% - var(--cut) / 2),
            transparent 0 calc(50% + var(--cut) / 2),
            #000 0
        ),
        linear-gradient(
            135deg,
            #000 calc(50% - var(--cut) / 2),
            transparent 0 calc(50% + var(--cut) / 2),
            #000 0
        );
    mask-composite: intersect;
}

.state-mark.failed.seen {
    box-shadow: none;
    background:
        linear-gradient(
            45deg,
            transparent calc(50% - var(--line-w) / 2),
            currentColor 0 calc(50% + var(--line-w) / 2),
            transparent 0
        ),
        linear-gradient(
            135deg,
            transparent calc(50% - var(--line-w) / 2),
            currentColor 0 calc(50% + var(--line-w) / 2),
            transparent 0
        );
    -webkit-mask: none;
    mask: none;
}

.folder-mark {
    flex: none;
    width: 7px;
    height: 7px;
    background: var(--folder, var(--muted));
}

.state-check {
    flex: none;
    display: grid;
    place-items: center;
    width: 11px;
    height: 11px;
    border-radius: var(--r-mark);
    background: var(--accent-fill);
    color: var(--accent-ink);
    animation: popin 0.16s var(--ease-out);
}

.state-check .icon {
    stroke-width: 3.5;
}

.session-title {
    font-size: 13.5px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color var(--t-hover) var(--ease-out);
}

/* A search that matched the folder or model, not the title: it shows after the title, which keeps its room first. */
.session-title.with-hit {
    display: flex;
    gap: 8px;
}

.session-name {
    flex: none;
    max-width: 65%;
    overflow: hidden;
    text-overflow: ellipsis;
}

.session-hit {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 12px;
    color: var(--muted);
}

/* New chat messages there, in a session not open. */
.session.unread .session-title {
    font-weight: 600;
}

/* Marked unread, or finished since this browser last looked: the title reads bold, like the dot beside the time says. */
.session-row.marked-unread .session-title,
.session-row.unseen .session-title {
    font-weight: 600;
}

.session-title mark,
.launcher mark {
    background: none;
    color: var(--accent);
    font-weight: 800;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

.session-side {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 7px;
    font: 11px var(--mono);
    color: var(--faint);
    transition: opacity var(--t-hover) var(--ease-out);
}

/* Subagents at work there (or failed ones, in red): ⑂ and how many, in a small pill. */
.session-fork {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    height: 18px;
    padding: 0 6px;
    border-radius: var(--r-pill);
    background: var(--accent-soft);
    font-weight: 600;
    color: var(--accent);
}

.session-fork.failed {
    background: var(--err-soft);
    color: var(--err);
}

.session-fork .icon {
    stroke-width: 2.4;
}

/* A call waits for you there. */
.session-needs {
    display: grid;
    place-items: center;
    height: 18px;
    padding: 0 7px;
    border-radius: var(--r-pill);
    background: var(--warn-soft);
    color: var(--warn);
    font: 500 11px var(--sans);
}

/* Pi works there. */
.session-working {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    animation: pulse 1.4s ease-in-out infinite;
}

.session-side .avatar {
    font-size: 8px;
}

.session-side .unread-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
}

/* A call waiting says more than how long ago: the title keeps the room. */
.session-needs ~ .session-time {
    display: none;
}

.session-time {
    min-width: 22px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Hold Alt: each of the first nine rows shows the number that jumps to it, in the time's place. */
.session-num {
    display: none;
}

:root[data-alt="on"] .session-num {
    display: inline-grid;
    animation: popin 0.2s var(--ease-out);
}

:root[data-alt="on"] .session-time:has(~ .session-num) {
    display: none;
}

/* Archive, pin, and mark unread: on the row's right, shown on hover or while the row has focus. */
.session-actions {
    position: absolute;
    top: 50%;
    right: 6px;
    margin-top: -13px;
    display: flex;
    gap: 4px;
}

.session-act {
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    color: var(--muted);
    background: var(--card-2);
    border: 1px solid var(--hair);
    border-radius: var(--r-seg);
    opacity: 0;
    transform: translateX(4px);
    transition:
        opacity var(--t-hover) var(--ease-out),
        transform var(--t-in) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .session-act:hover {
        color: var(--accent);
        border-color: var(--accent-line);
    }
}

.session-act + .session-act {
    transition-delay: 25ms;
}

.session-pin.on {
    color: var(--brand);
}

.session-unread.on {
    color: var(--accent);
}

/* Touch screens archive, pin, and mark-unread from a long press on the row instead: an unseen button would take taps meant for it. */
@media (hover: none) {
    .session-actions {
        display: none;
    }
}

/* The buttons take the right side's place, widened so a long title ends before them (one to three 26px buttons). */
@media (hover: hover) {
    .session-row:hover .session-act,
    .session-act:focus-visible {
        opacity: 1;
        transform: none;
    }
    .session-row:not(.no-acts):hover .session-side {
        opacity: 0;
        min-width: 56px;
    }
    .session-row.one-act:hover .session-side {
        min-width: 26px;
    }
    /* Three live buttons: archive, pin, and mark-unread. */
    .session-row.three-acts:hover .session-side {
        min-width: 86px;
    }
    /* Keyboard focus in the row shows them too, not the focus a click leaves on the open session's row. Kept apart
       from the rules above: a browser without :has() drops only these. */
    .session-row:has(:focus-visible) .session-act {
        opacity: 1;
        transform: none;
    }
    .session-row:not(.no-acts):has(:focus-visible) .session-side {
        opacity: 0;
        min-width: 56px;
    }
    .session-row.one-act:has(:focus-visible) .session-side {
        min-width: 26px;
    }
    .session-row.three-acts:has(:focus-visible) .session-side {
        min-width: 86px;
    }
    /* While Ctrl/⌘ drags a selection, rows do not show their buttons. */
    :root.selecting .session-row .session-act {
        opacity: 0;
    }
    :root.selecting .session-row .session-side {
        opacity: 1;
        min-width: 0;
    }
}

/* On its way into or out of the archive: dimmed until the server's list moves it. */
.session-row.moving {
    opacity: 0.4;
    pointer-events: none;
    transition: opacity var(--t-hover) var(--ease-out);
}

:root.selecting,
:root.selecting * {
    user-select: none;
}

/* A finger held on a row: nothing selects, the sheet that press opens rising under the finger included. */
:root.holding,
:root.holding * {
    -webkit-user-select: none;
    user-select: none;
}

/* What to do with the selected sessions: docked under the list. */
.select-bar {
    container-type: inline-size;
    flex: none;
    margin-top: 6px;
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    padding: 4px 4px 4px 9px;
    border: 1px solid var(--accent-line);
    border-radius: var(--r-control);
    background: var(--accent-soft);
    animation: rise-in var(--t-in) var(--ease-out);
}

.select-count {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    font-size: 0.76rem;
    color: var(--muted);
    white-space: nowrap;
}

.select-count b {
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

/* A narrow bar (a narrow list, or larger text) shows just the count, so the buttons fit. */
@container (max-width: 14rem) {
    .select-word {
        display: none;
    }
}

.select-bar .button {
    padding: 0.2rem 0.5rem;
    font-size: 0.76rem;
}

.select-clear {
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: var(--r-seg);
    display: grid;
    place-items: center;
    color: var(--body);
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .select-clear:hover {
        background: var(--hover);
        color: var(--text);
    }
}

/* A thumb's size on a touch screen, where a long press starts a selection. */
@media (pointer: coarse) {
    .select-bar .button {
        min-height: 36px;
        padding-inline: 0.8rem;
    }
    .select-clear {
        width: 36px;
        height: 36px;
    }
}

.sessions-empty {
    padding: 1.2rem 0.6rem;
    color: var(--muted);
    font-size: 0.85rem;
    animation: fade var(--t-fade) var(--ease-almost);
}

/* A session row's shape while the list loads: a title bar, pulsing one row after another. */
.session-placeholder {
    display: flex;
    align-items: center;
    height: 36px;
    padding: 0 10px 0 29px;
}

.session-placeholder span {
    height: 0.6rem;
    width: var(--width);
    border-radius: var(--r-mark);
    background: var(--line);
    animation: placeholder 1.4s ease-in-out var(--delay) infinite;
}

@keyframes placeholder {
    50% {
        opacity: 0.35;
    }
}

/* ─── The home screen on wide screens: a fastfetch for Pi Pocket ─── */

/* One centered column, 640px at most. */
.splash {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    align-items: center;
    justify-content: safe center;
    flex-direction: column;
    gap: 28px;
    padding: 40px;
}

.splash > * {
    width: min(640px, 100%);
    flex: none;
}

.fetch {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 36px;
}

.fetch-logo {
    margin: 0;
    font: 13px / 1.15 var(--mono);
    color: var(--brand);
    user-select: none;
    animation: popin 0.6s var(--ease-out) backwards;
}

.fetch-info {
    flex: 1;
    min-width: 260px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fetch-info > * {
    animation: rise-in 0.42s var(--ease-out) backwards;
    animation-delay: calc(var(--i, 0) * 45ms + 120ms);
}

.fetch-title {
    margin-bottom: 8px;
    font: 600 15px var(--mono);
    color: var(--text);
}

.fetch-title b {
    color: var(--accent);
}

.fetch-row {
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 12px;
    margin: 0;
    font-size: 13.5px;
    line-height: 1.75;
}

.fetch-row dt {
    color: var(--muted);
}

.fetch-row dd {
    margin: 0;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fetch-colors {
    display: flex;
    gap: 6px;
    margin-top: 10px;
}

.fetch-colors span {
    width: 16px;
    height: 16px;
    border-radius: var(--r-tag);
    transition: transform var(--t-in) var(--ease-out);
}

@media (hover: hover) {
    .fetch-colors span:hover {
        transform: translateY(-3px);
    }
}

/* New session, the launcher, and Appearance: 38px buttons, set in full here. */
.splash-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    animation: rise-in 0.5s var(--ease-out) 0.45s backwards;
}

.splash-actions .button {
    height: 38px;
    padding: 0 14px;
    gap: 8px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-control);
    background: var(--card);
    color: var(--text);
    font-size: 13.5px;
    font-weight: 500;
}

@media (hover: hover) {
    .splash-actions .button:hover {
        border-color: var(--hair-2);
        background: var(--card-2);
    }
}

.splash-actions .button.primary {
    border-color: transparent;
    background: var(--accent-fill);
    color: var(--accent-ink);
    font-weight: 600;
}

@media (hover: hover) {
    .splash-actions .button.primary:hover {
        border-color: transparent;
        background: color-mix(in oklab, var(--accent-fill) 85%, var(--text));
    }
}

/* The key's name, in mono beside the label. */
.splash-actions .button kbd {
    min-width: 0;
    height: auto;
    padding: 0;
    border: 0;
    background: none;
    font: 400 11px var(--mono);
    color: var(--faint);
    opacity: 1;
}

.splash-actions .button.primary kbd {
    color: inherit;
    opacity: 0.7;
}

/* Jump back in: a row per recent session, numbered as Alt+1…9 number them. */
.splash-recent {
    display: flex;
    flex-direction: column;
    gap: 4px;
    animation: rise-in 0.5s var(--ease-out) 0.55s backwards;
}

.splash-heading {
    padding: 0 4px 6px;
    font-size: 12px;
    font-weight: 500;
    color: var(--muted);
}

.splash-row {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 40px;
    padding: 0 12px;
    border-radius: var(--r-control);
    text-align: left;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .splash-row:hover {
        background: var(--hover);
    }
}

.splash-key {
    flex: none;
    width: 20px;
    height: 20px;
    display: grid;
    place-items: center;
    border: 1px solid var(--hair-2);
    border-radius: calc(var(--r-tag) + 1px);
    font: 11px / 1 var(--mono);
    color: var(--muted);
}

.splash-title {
    flex: 1;
    min-width: 0;
    font-size: 14px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.splash-meta {
    flex: none;
    font: 11.5px var(--mono);
    color: var(--faint);
}

/* ─── Sheets ───────────────────────────────────────────────── */

/* omarchy-shell's scrim: the desktop's darkest color over everything, at about half. */
.overlay {
    position: fixed;
    inset: 0;
    background: var(--scrim);
    z-index: 20;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    animation: fade var(--t-fade) var(--ease-almost);
}

/* Phones: a sheet from the bottom edge, rounded on top. Wide screens: a rounded popup near the top that floats. */
.sheet {
    background: var(--panel);
    width: 100%;
    max-width: 560px;
    max-height: 86dvh;
    border-radius: calc(var(--r-sheet) + 8px) calc(var(--r-sheet) + 8px) 0 0;
    box-shadow:
        0 -1px 0 var(--hair-2),
        0 -20px 40px -20px var(--sh);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    animation: sheet-up var(--t-in) var(--ease-out);
    padding-bottom: env(safe-area-inset-bottom);
    outline: none;
}

@keyframes sheet-up {
    from {
        transform: translateY(100%);
    }
}

@keyframes sheet-down {
    to {
        transform: translateY(100%);
    }
}

/* Closing: Hyprland's windowsOut, short and linear. */
.leaving {
    pointer-events: none;
}

.leaving .overlay {
    animation: fade-out var(--t-out) linear forwards;
}

.leaving .sheet {
    animation: sheet-down 0.2s var(--ease-in-out) forwards;
}

@media (min-width: 700px) {
    .overlay {
        align-items: flex-start;
        padding: 7vh 16px 16px;
    }
    .sheet {
        max-width: 500px;
        border-radius: var(--r-sheet);
        box-shadow: var(--pop);
        animation: pop 0.28s var(--ease-out);
    }
    .sheet.wide {
        max-width: 760px;
    }
    .leaving .sheet {
        animation: pop-out var(--t-out) linear forwards;
    }
}

/* The drawer: the session list sliding in from the left on narrow screens. Over `.overlay`'s place for sheets. */
.overlay.drawer-overlay {
    align-items: stretch;
    justify-content: flex-start;
}

.drawer {
    display: flex;
    width: min(86vw, 340px);
    height: 100dvh;
    background: var(--panel);
    border-radius: 0 var(--r-sheet) var(--r-sheet) 0;
    box-shadow:
        1px 0 0 var(--hair-2),
        20px 0 40px -20px var(--sh);
    overflow: hidden;
    animation: drawer-in var(--t-in) var(--ease-out);
}

@keyframes drawer-in {
    from {
        transform: translateX(-100%);
    }
}

.leaving .drawer {
    animation: drawer-out 0.2s var(--ease-in-out) forwards;
}

@keyframes drawer-out {
    to {
        transform: translateX(-100%);
    }
}

/* ─── Pop-up menus: the model and branch pickers ───────────── */

/* A menu up from the control that opens it (the model chip, the branch), over the conversation without dimming it. */
.pop-overlay {
    background: none;
    animation: none;
}

.pop-menu {
    position: fixed;
    display: flex;
    flex-direction: column;
    background: var(--panel);
    border-radius: var(--r-window);
    box-shadow: var(--pop);
    overflow: hidden;
    outline: none;
    animation: pop 0.25s var(--ease-out);
}

/* No chip to open from: in the middle of the screen. */
.pop-menu.free {
    position: relative;
    width: min(420px, calc(100vw - 16px));
    max-height: 80dvh;
    margin: auto;
}

.leaving .pop-menu {
    animation: pop-out var(--t-out) linear forwards;
}

/* A menu down from a control near the top (the branch in the top bar): it comes and goes from above. */
.pop-menu.down {
    animation-name: pop-menu-down;
}

.leaving .pop-menu.down {
    animation: pop-menu-up var(--t-out) linear forwards;
}

@keyframes pop-menu-down {
    from {
        opacity: 0;
        transform: translateY(-8px);
    }
}

@keyframes pop-menu-up {
    to {
        opacity: 0;
        transform: translateY(-8px);
    }
}

.pop-menu-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.55rem 0.8rem;
    border-bottom: 1px solid var(--line);
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--text);
}

.pop-menu-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--muted);
    transition: color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .pop-menu-link:hover {
        color: var(--accent);
    }
}

.pop-menu-search {
    margin: 0.5rem 0.6rem 0.25rem;
}

/* The field's frame shows the focus. */
.pop-menu-search input:focus-visible {
    outline: none;
}

.pop-menu-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.pop-menu-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.5rem 0.8rem;
    text-align: left;
    border-bottom: 1px solid var(--line);
    color: var(--text);
}

.pop-menu-row:last-child {
    border-bottom: 0;
}

.pop-menu-row.on {
    background: var(--card-2);
    box-shadow: inset 0 0 0 1px var(--edge);
}

.pop-menu-row-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.pop-menu-row-name {
    font-size: 0.86rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pop-menu-row-sub {
    font-size: 0.7rem;
    color: var(--muted);
}

.pop-menu-row .icon {
    color: var(--accent);
}

.pop-menu-note {
    margin: 0;
    padding: 0.6rem 0.8rem;
}

.pop-menu-foot {
    padding: 0.4rem 0.8rem 0.7rem;
    border-top: 1px solid var(--line);
}

.pop-menu-foot p {
    margin: 0.2rem 0 0;
}

/* Under the thinking levels: the owner's Make default, or in the default's picker, how the default works. */
.pop-menu-default {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.3rem 0.8rem;
    padding-block: 0.55rem;
    font-size: 0.75rem;
}

.pop-menu-foot + .pop-menu-default {
    border-top: 0;
    padding-top: 0;
}

.pop-menu-default-mark {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    color: var(--ok);
}

.pop-menu-head-sub {
    margin-left: 0.4rem;
    font-weight: 400;
    color: var(--muted);
}

/* A heading between a menu's groups of rows. */
.pop-menu-label {
    padding: 10px 10px 4px;
    font-size: 12px;
    font-weight: 500;
    color: var(--faint);
}

/* The branch picker: what is checked out beside its title, and how far each branch is from its remote one. */
.branch-picker {
    background: var(--bg);
}

.branch-picker.down {
    animation-name: pop;
}

.branch-picker .pop-menu-head {
    padding: 12px 14px;
    border-color: var(--hair);
    font-size: 13px;
    font-weight: 600;
}

.branch-picker .pop-menu-list {
    padding: 6px;
}

.branch-picker .pop-menu-foot {
    border-color: var(--hair);
    font-size: 12px;
}

.branch-picker .pop-menu-row {
    border: 0;
    border-radius: var(--r-row);
    padding: 8px 10px;
}

.branch-picker .pop-menu-row.on {
    background: var(--card);
    box-shadow: none;
    color: var(--text);
}

.branch-picker .pop-menu-row-name {
    font-size: 13px;
}

.branch-picker .pop-menu-row-sub {
    font-size: 11.5px;
    color: var(--faint);
}

.branch-head {
    display: inline-flex;
    padding: 2px 8px;
    border-radius: calc(var(--r-tag) + 1px);
    background: var(--card);
    font-size: 12px;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
    overflow: hidden;
    font-weight: 400;
    color: var(--muted);
    white-space: nowrap;
    text-overflow: ellipsis;
}

.branch-track {
    flex: none;
    font: 0.7rem var(--mono);
    color: var(--muted);
}

.branch-track.warn {
    color: var(--warn);
}

/* A branch checked out in another worktree: listed, but switched to only there. */
.pop-menu-row.elsewhere {
    color: var(--muted);
}

/*
 * The model picker, above the model chip: a header with the way to Providers, a row per model (its provider under its
 * name, a check on the current one), and Thinking's levels in one track.
 */
.model-menu .pop-menu-head {
    padding: 12px 14px 8px;
    border-bottom: 0;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--muted);
}

.model-menu .pop-menu-link {
    gap: 5px;
    font-size: 12.5px;
    color: var(--accent);
}

.model-menu .pop-menu-list {
    padding: 0 6px 6px;
}

.model-menu .pop-menu-row {
    gap: 10px;
    padding: 8px 10px;
    border-bottom: 0;
    border-radius: var(--r-row);
}

.model-menu .pop-menu-row.current {
    background: var(--card);
}

.model-menu .pop-menu-row.on {
    background: var(--hover);
    box-shadow: none;
}

.model-menu .pop-menu-row-text {
    line-height: 1.35;
}

.model-menu .pop-menu-row-name {
    font-size: 13.5px;
}

.model-menu .pop-menu-row.current .pop-menu-row-name {
    font-weight: 500;
}

.model-menu .pop-menu-row-sub {
    font: 11px var(--mono);
    color: var(--faint);
}

.model-menu .pop-menu-foot {
    padding: 10px 14px 14px;
    border-top: 1px solid var(--hair);
}

.model-menu .pop-menu-foot .label {
    margin-bottom: 8px;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--muted);
}

.model-scope {
    display: inline-flex;
    align-items: center;
    margin-left: 5px;
    font-size: 11px;
    font-weight: 400;
    white-space: nowrap;
}

.model-scope button {
    padding: 6px 3px;
    color: var(--muted);
    font: inherit;
}

.model-scope button.on {
    color: var(--accent);
}

/*
 * On a touch screen scoped and all keep their size; each one's hit area reaches out to about 45px high, away from the
 * other and within the header. Providers stays on top where the two meet on a narrow phone.
 */
@media (pointer: coarse) {
    .model-scope button,
    .model-menu .pop-menu-head > .pop-menu-link {
        position: relative;
    }
    .model-scope button::before {
        content: "";
        position: absolute;
        inset: -8px -1px -8px -14px;
    }
    .model-scope button:last-of-type::before {
        inset: -8px -18px -8px -1px;
    }
}

/* Thinking: the levels in one track, the chosen one raised. Past the general segmented rules, which come later. */
.segmented.model-levels {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 0;
    padding: 3px;
    border: 0;
    border-radius: var(--r-control);
    background: var(--card);
}

.segmented.model-levels button {
    height: 26px;
    min-width: 0;
    padding: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    border: 0;
    border-radius: var(--r-seg);
    background: none;
    color: var(--muted);
    font-size: 11.5px;
    font-weight: 500;
}

.segmented.model-levels button.on {
    background: var(--raised);
    color: var(--text);
}

@media (hover: hover) {
    .segmented.model-levels button:not(.on):hover {
        color: var(--text);
    }
}

/* ─── Sheet parts and controls ───────────────────────────────── */

.sheet-head {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: calc(42px + 14px * var(--space-y));
    flex: none;
    padding: 0 10px 0 calc(20px * var(--space-x));
    border-bottom: 1px solid var(--hair);
    position: relative;
}

.sheet-head > .icon-button {
    width: 34px;
    height: 34px;
}

.sheet-head > .sheet-back {
    width: 32px;
    height: 32px;
    margin-left: -10px;
}

@media (max-width: 699px) {
    .sheet-head {
        padding-top: 14px;
        min-height: calc(56px + 14px * var(--space-y));
    }
    .sheet-head > .icon-button {
        width: 40px;
        height: 40px;
    }
}

.grip {
    display: none;
    position: absolute;
    top: 8px;
    left: 50%;
    width: 36px;
    height: 5px;
    margin-left: -18px;
    border-radius: var(--r-mark);
    background: var(--hair-2);
}

@media (max-width: 699px) {
    .grip {
        display: block;
    }
    /* A menu a swipe closes: its grip at the edge it goes from, with room. */
    .pop-menu > .grip + .pop-menu-head {
        padding-top: 20px;
    }
    .pop-menu.down {
        padding-bottom: 16px;
    }
    .pop-menu.down > .grip {
        top: auto;
        bottom: 6px;
    }
}

.sheet-head h2 {
    flex: 1;
    min-width: 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--text);
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sheet-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    padding: calc(16px * var(--space-y)) calc(20px * var(--space-x)) calc(20px * var(--space-y));
    display: flex;
    flex-direction: column;
    gap: calc(14px * var(--space-y));
}

.sheet-body > * {
    flex-shrink: 0;
}

.sheet-body p {
    margin: 0;
}

.sheet-body .small {
    font-size: 12px;
}

.sheet-list {
    overflow: hidden;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--bg);
}

.sheet-list > :not(:first-child) {
    border-top: 1px solid var(--hair);
}

.sheet-list > .list-item {
    border-radius: 0;
    margin: 0;
}

/* Rows that are controls themselves: the ring inside the list, which cuts off what is past its edges. */
.sheet-list > :is(button, .list-item):focus-visible {
    outline-offset: -2px;
}

.sheet-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* Shared menu rows: inset groups in sheets, quiet standalone rows elsewhere. */
.list-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    width: 100%;
    /* 44px, 40px, and 37px. */
    min-height: calc(32px + 12px * var(--space-y));
    text-align: left;
    padding: calc(12px * var(--space-y)) calc(14px * var(--space-x));
    border-radius: var(--r-row);
    background: var(--bg);
    border: 0;
    font-size: 13.5px;
    color: var(--text);
    text-decoration: none;
    margin-bottom: 2px;
    transition:
        background-color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        padding var(--t-in) var(--ease-out);
}

@media (hover: hover) {
    .list-item:hover {
        background: var(--card);
    }
}

.list-item:active {
    background: var(--pressed);
}

.list-item > span:first-child {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

.list-item.active {
    background: var(--accent-soft);
    color: var(--accent);
}

.group-title,
.label {
    font-size: 12px;
    font-weight: 500;
    color: var(--faint);
    margin: calc(4px * var(--space-y)) 2px calc(6px * var(--space-y));
}

.field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.field > .label {
    margin: 0;
    color: var(--muted);
    font-size: 12.5px;
}

.field input,
.field textarea {
    font-size: 14.5px;
    border-radius: calc(var(--r-control) + 1px);
}

@media (pointer: coarse) {
    .field input,
    .field textarea {
        font-size: 16px;
    }
}

/* Native checkbox semantics and label targets, drawn in the shared sheet palette. */
.check input[type="checkbox"],
.subagent-model input[type="checkbox"] {
    appearance: none;
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 14px;
    height: 14px;
    margin: 0;
    padding: 0;
    border: 1.5px solid var(--hair-2);
    border-radius: calc(var(--r-tag) - 1px);
    background: var(--card);
    color: var(--accent-ink);
    cursor: pointer;
}

.check input[type="checkbox"]::before,
.subagent-model input[type="checkbox"]::before {
    content: "";
    width: 4px;
    height: 7px;
    margin-top: -2px;
    border: solid currentColor;
    border-width: 0 1.5px 1.5px 0;
    transform: rotate(45deg);
    opacity: 0;
}

.check input[type="checkbox"]:checked,
.subagent-model input[type="checkbox"]:checked {
    border-color: var(--accent-fill);
    background: var(--accent-fill);
}

.check input[type="checkbox"]:checked::before,
.subagent-model input[type="checkbox"]:checked::before {
    opacity: 1;
}

.check input[type="checkbox"]:disabled,
.subagent-model input[type="checkbox"]:disabled {
    opacity: 0.5;
    cursor: default;
}

.row {
    display: flex;
    gap: 0.45rem;
    align-items: center;
}

.row input {
    flex: 1;
}

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    min-height: 38px;
    border: 1px solid transparent;
    background: var(--card-2);
    border-radius: var(--r-control);
    padding: 7px 16px;
    font-size: 13.5px;
    font-weight: 500;
    text-decoration: none;
    color: var(--text);
    white-space: nowrap;
    transition:
        background-color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        transform 90ms var(--ease-out);
}

@media (hover: hover) {
    .button:hover {
        background: var(--raised);
    }
}

.button:active:not(:disabled) {
    transform: scale(0.97);
}

.button.primary {
    background: var(--accent-fill);
    border-color: var(--accent-fill);
    color: var(--accent-ink);
    font-weight: 600;
}

@media (hover: hover) {
    .button.primary:hover {
        background: color-mix(in oklab, var(--accent-fill) 85%, var(--text));
    }
}

.button kbd {
    background: transparent;
    color: inherit;
    opacity: 0.7;
    border-color: currentColor;
}

.button.ghost {
    background: none;
    border-color: var(--hair-2);
    color: var(--muted);
}

@media (hover: hover) {
    .button.ghost:hover {
        background: var(--hover);
        color: var(--err);
    }
}

.button.sheet-footer {
    min-height: 40px;
    border-radius: calc(var(--r-control) + 1px);
}

/* Away from Save, in the color of what cannot be undone here. */
.button.sheet-footer.signout {
    margin-top: 14px;
    color: var(--err);
}

.button.small {
    min-height: 30px;
    padding: 4px 11px;
    border-radius: calc(var(--r-row) - 1px);
    font-size: 12.5px;
}

.button.wide {
    width: 100%;
}

.button:disabled {
    opacity: 0.5;
}

.link {
    color: var(--accent);
    font-size: 0.85rem;
}

.segmented {
    display: flex;
    flex-wrap: wrap;
    align-self: flex-start;
    gap: 0;
    padding: 3px;
    border-radius: var(--r-control);
    background: var(--card);
}

.segmented button {
    min-height: 28px;
    border: 0;
    border-radius: var(--r-seg);
    padding: 4px 11px;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--muted);
    background: none;
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .segmented button:hover {
        background: var(--hover);
        color: var(--text);
    }
}

.segmented button.on {
    background: var(--raised);
    color: var(--text);
}

/*
 * The folder picker, laid out as a desktop's file dialog: the path and New folder on top, places beside the folders,
 * and the folder Open takes with Cancel and Open at the bottom. A fixed height: only the places and the folders scroll.
 */
.sheet.folder-sheet {
    height: min(86dvh, 600px);
}

.folder-sheet .sheet-body {
    flex: 1;
    min-height: 0;
    gap: 0.5rem;
    padding-bottom: 0.75rem;
}

.fp-bar {
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
}

.fp-bar > .icon-button,
.fp-new {
    background: var(--card);
    border-radius: var(--r-row);
}

.fp-bar > .icon-button:disabled {
    opacity: 0.35;
    pointer-events: none;
}

.fp-new {
    flex: none;
    gap: 0.3rem;
}

.fp-crumbs {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    overflow-x: auto;
    scrollbar-width: none;
    white-space: nowrap;
    min-height: 34px;
    padding: 0 6px;
    border-radius: var(--r-row);
    background: var(--card);
    font: 13px var(--mono);
}

.fp-crumbs::-webkit-scrollbar {
    display: none;
}

/* A path too long for the field fades in from its start rather than being cut there (folder.js marks it cut). */
.fp-crumbs.cut::before {
    content: "";
    position: sticky;
    left: 0;
    z-index: 1;
    flex: none;
    align-self: stretch;
    width: 28px;
    margin: 0 -22px 0 -6px;
    background: linear-gradient(to right, var(--card) 6px, transparent);
    pointer-events: none;
}

.fp-crumb {
    flex: none;
    padding: 0.3rem 0.35rem;
    border-radius: var(--radius);
    color: var(--muted);
}

@media (hover: hover) {
    .fp-crumb:hover {
        background: var(--hover);
        color: var(--accent);
    }
}

.fp-crumb.here {
    color: var(--text);
    font-weight: 600;
}

.fp-sep {
    flex: none;
    color: var(--line-strong);
}

/* A path or a new folder's name being typed. */
.fp-line {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.fp-line input {
    flex: 1;
    min-width: 0;
    height: 34px;
    padding: 0.3rem 0.5rem;
    font-size: 0.85rem;
}

.fp-line .icon-button {
    width: 32px;
    height: 32px;
    color: var(--muted);
}

.fp-path-input {
    flex: 1;
    min-width: 0;
}

.fp-naming {
    padding: 0.35rem 0.4rem 0.35rem 0.6rem;
    border-bottom: 1px solid var(--line);
    background: var(--accent-soft);
}

/* A small phone's folder list is narrow: the name takes the whole line, OK and Cancel go under it. */
@media (max-width: 480px) {
    .fp-naming {
        flex-wrap: wrap;
        justify-content: flex-end;
    }
    .fp-naming input {
        flex-basis: 100%;
    }
}

/* A typed path that is not there, with Create it. */
.folder-missing {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.3rem 0.6rem;
    padding: 0.3rem 0.3rem 0.3rem 0.6rem;
    border: 1px solid var(--warn-line);
    background: var(--warn-soft);
    font-size: 0.82rem;
    color: var(--body);
    overflow-wrap: anywhere;
}

.fp-missing-actions {
    display: flex;
    align-items: center;
    gap: 0.2rem;
}

.fp-missing-actions .icon-button {
    width: 32px;
    height: 32px;
}

/* Places beside the folders, as in a file dialog's sidebar. */
.fp-main {
    flex: 1;
    min-height: 0;
    display: flex;
    gap: 12px;
    overflow: hidden;
}

.fp-places {
    flex: none;
    width: clamp(7rem, 28%, 11rem);
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 0.3rem;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--bg);
}

.fp-place {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    width: 100%;
    min-height: 2rem;
    padding: 0.25rem 0.45rem;
    border-radius: var(--radius);
    text-align: left;
    font-size: 0.82rem;
    color: var(--body);
}

.fp-place span {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fp-place .icon {
    flex: none;
    color: var(--muted);
}

@media (hover: hover) {
    .fp-place:hover {
        background: var(--hover);
    }
}

.fp-place.on {
    background: var(--accent-soft);
    color: var(--accent);
}

.fp-place.on .icon {
    color: var(--accent);
}

/* A favorite's shortcut, Ctrl/⌘+1…9, at the end of its place. */
.fp-key {
    flex: none;
    margin-left: auto;
    font: 11px var(--mono);
    color: var(--faint);
}

.fp-places-title {
    margin: 10px 10px 4px;
    font-size: 12px;
    font-weight: 500;
    color: var(--faint);
}

.fp-pi {
    margin: auto 0.45rem 0.2rem;
    padding-top: 0.6rem;
    text-align: left;
    font-size: 0.78rem;
}

.fp-list {
    flex: 1;
    min-width: 0;
    padding: 4px;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--bg);
}

.fp-list:focus-visible {
    outline: none;
}

.fp-row {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    width: 100%;
    min-height: 34px;
    padding: 6px 10px;
    border-radius: calc(var(--r-row) - 1px);
    text-align: left;
    font: 13px var(--mono);
    color: var(--body);
    user-select: none;
}

@media (hover: hover) {
    .fp-row:hover {
        background: var(--hover);
    }
}

/* The selected folder: what Open takes. */
.fp-row.on {
    background: var(--accent-soft);
    color: var(--accent);
}

.fp-row .icon {
    flex: none;
    color: var(--accent);
}

.fp-row .fp-chev {
    margin-left: auto;
    color: var(--muted);
}

.fp-name {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fp-note {
    margin: 0;
    padding: 0.8rem;
    font-size: 0.82rem;
    color: var(--muted);
}

/* The bottom: the folder Open takes, the options, then Cancel and Open, as a file dialog's. */
.fp-foot {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.9rem;
}

.fp-target {
    flex: 1 0 100%;
    min-width: 0;
    display: flex;
    gap: 0.4rem;
    font-size: 0.82rem;
    white-space: nowrap;
}

.fp-target .mono {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text);
}

/* Star the folder Open takes, to keep it among the places as a favorite. */
.fp-target .fp-star {
    flex: none;
    width: 28px;
    height: 28px;
    margin: -6px 0;
    color: var(--muted);
}

.fp-star.on {
    color: var(--accent);
}

.fp-star.on .icon {
    fill: currentColor;
}

@media (pointer: coarse) {
    .fp-target .fp-star {
        width: 40px;
        height: 40px;
        margin: -12px 0;
    }
}

.fp-options {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem 0.9rem;
}

.fp-options .check {
    margin-bottom: 0;
}

.fp-buttons {
    display: flex;
    gap: 0.5rem;
    margin-left: auto;
}

.fp-buttons .button {
    min-width: 6.5rem;
    justify-content: center;
}

/* Phones: the buttons share the width, under the options. */
@media (max-width: 699px) {
    .fp-new {
        padding-inline: 0.6rem;
    }
    .fp-buttons {
        flex: 1 0 100%;
    }
    .fp-buttons .button {
        flex: 1;
    }
    .fp-places {
        width: 8.5rem;
    }
    .fp-row,
    .fp-place {
        min-height: 40px;
    }
}

.check {
    display: flex;
    gap: 0.4rem;
    align-items: center;
    font-size: 0.82rem;
    color: var(--muted);
    margin-bottom: 0.35rem;
}

.provider {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    background: var(--bg);
}

.provider > :first-child {
    flex: 1;
    min-width: 0;
}

.provider .provider-needs {
    display: inline-block;
    padding: 1px 7px;
    border-radius: var(--r-pill);
    background: var(--warn-soft);
    font-size: 11.5px;
    font-weight: 500;
}

@media (max-width: 699px) {
    .provider {
        flex-direction: column;
        align-items: stretch;
    }
}

.provider-actions {
    display: flex;
    gap: 0.35rem;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* What a provider said when it would not renew a sign-in. */
.provider-why {
    overflow-wrap: anywhere;
}

/* Shared refresh feedback stays visible after a request and wraps provider messages as plain text. */
.model-refresh {
    margin-block: 0.5rem;
    min-width: 0;
}

.model-refresh .button.model-refresh-button {
    min-height: 40px;
}

.model-refresh-status {
    max-height: 22dvh;
    overflow-y: auto;
    overflow-wrap: anywhere;
    overscroll-behavior: contain;
}

.model-refresh-status p {
    margin: 0.35rem 0 0;
}

/* The owner's choice of models for subagents, above the providers. */
.subagent-models {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.6rem 0 0.8rem;
    margin-bottom: 0.4rem;
    border-bottom: 1px solid var(--line);
}

.subagent-models p {
    margin: 0;
}

/* What is allowed, on one line: the list under it stays put while models are checked one after another. */
.subagent-models-chosen {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.subagent-models .search {
    margin-bottom: 0;
}

/* Every model, by provider. A long list scrolls in its own box, so the providers stay near. */
.subagent-models-list {
    max-height: min(22rem, 45dvh);
    overflow-y: auto;
    overscroll-behavior: contain;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
}

.subagent-models-list > p {
    padding: 0.6rem;
}

.subagent-models-head {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 6px 12px;
    background: var(--card);
    font-size: 12px;
    font-weight: 500;
    color: var(--faint);
}

.subagent-model {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-height: 44px;
    padding: 8px 12px;
    border-top: 1px solid var(--hair);
    cursor: pointer;
}

.subagent-model > span {
    min-width: 0;
    overflow-wrap: anywhere;
}

.subagent-model .muted {
    display: block;
}

.invite {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    align-items: stretch;
}

.qr {
    background: #fff;
    border-radius: var(--radius);
    padding: 0.6rem;
    /* Smaller on short screens, so the invite sheet fits a laptop window without scrolling. */
    width: min(70vw, clamp(160px, 25dvh, 260px));
    align-self: center;
}

.qr svg {
    display: block;
    width: 100%;
    height: auto;
}

/* The invite code, for typing on the other device: easy to spot and to read out. */
.invite-details {
    display: flex;
    align-items: center;
    gap: 16px;
}

.invite-details .qr {
    flex: none;
    width: 150px;
    border-radius: var(--r-window);
}

.invite-code {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

@media (max-width: 480px) {
    .invite-details {
        flex-direction: column;
    }
    .invite-code {
        align-self: stretch;
    }
}

.invite-code-head {
    align-self: stretch;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 12px;
    font-weight: 500;
    color: var(--muted);
}

.invite-code-value {
    display: flex;
    gap: 0.6em;
    font: 600 24px var(--mono);
    letter-spacing: 0.08em;
    color: var(--text);
    user-select: all;
}

.code-big {
    font: 600 22px var(--mono);
    letter-spacing: 0.12em;
    text-align: center;
    padding: 6px;
    border-radius: var(--r-control);
    background: var(--bg);
}

.auth-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    border-radius: var(--r-window);
    border: 1px solid var(--accent-line);
    background: var(--accent-soft);
}

.auth-inline {
    padding: 16px;
    border-radius: var(--r-window);
    border: 1px solid var(--accent-line);
    background: var(--accent-soft);
}

.auth-inline-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 12px;
    color: var(--text);
}

.auth-inline-head strong {
    font-size: 14px;
    font-weight: 600;
}

.auth-inline .auth-card {
    padding: 0;
    border: 0;
    background: none;
}

.auth-event {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

/* ─── Artifact viewer ──────────────────────────────────────── */

.viewer {
    position: fixed;
    inset: 0;
    z-index: 30;
    background: var(--bg);
    display: flex;
    flex-direction: column;
}

.viewer-head {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 58px;
    padding: calc(env(safe-area-inset-top) + 8px) 10px 8px 20px;
    border-bottom: 1px solid var(--hair);
}

.artifact-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

.artifact-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--hair);
    border-radius: var(--r-window);
    text-align: left;
}

@media (hover: hover) {
    .artifact-card:hover {
        border-color: var(--accent-line);
    }
}

.artifact-cover {
    height: 120px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 8px;
    background: var(--card);
    color: var(--faint);
    font: 11px var(--mono);
}

.artifact-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    padding: 10px 12px;
    overflow-wrap: anywhere;
}

.artifact-name {
    color: var(--text);
    font-size: 13.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.message-actions > .group-title {
    margin: 0;
    padding: 8px 14px;
    background: var(--card);
}

/* A viewer has nothing to do with a message of files alone: no empty box. */
.message-actions:empty {
    display: none;
}

.message-model-search {
    padding: 8px 14px;
}

.message-preview {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
    /* Room as a clear border, not padding: the clamp clips at the padding's edge, so a fourth line would show in it. */
    border: solid transparent;
    border-width: 12px 14px;
    border-radius: var(--r-card);
    background: var(--card);
    color: var(--body);
    font-size: 13.5px;
}

@media (max-width: 480px) {
    .viewer-head {
        flex-wrap: wrap;
    }
    .viewer-title {
        flex-basis: calc(100% - 50px);
    }
    .artifact-grid {
        grid-template-columns: 1fr;
    }
}

.viewer-title {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.viewer-title strong {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.viewer select {
    width: auto;
    padding: 0.3rem 0.4rem;
}

.viewer iframe {
    flex: 1;
    border: 0;
    width: 100%;
    background: #fff;
}

/* ─── Images ───────────────────────────────────────────────── */

.thumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.4rem;
}

.prompt-body > .thumbs:first-child {
    margin-top: 0;
}

.thumb {
    display: block;
    padding: 0;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    overflow: hidden;
    background: var(--card);
    cursor: zoom-in;
    max-width: 100%;
}

.thumb img {
    display: block;
    width: auto;
    max-width: min(180px, 100%);
    height: 140px;
    object-fit: cover;
}

.thumb:only-child img {
    max-width: 100%;
    height: auto;
    max-height: 320px;
    object-fit: contain;
}

.md img {
    max-width: 100%;
    height: auto;
    max-height: 460px;
    border-radius: var(--r-card);
    border: 1px solid var(--hair);
    background: var(--card);
    cursor: zoom-in;
    vertical-align: middle;
}

.md a img {
    cursor: pointer;
}

.md img.broken {
    display: none;
}

.image-missing {
    display: inline-block;
    font-size: 0.8rem;
    color: var(--muted);
    border: 1px dashed var(--line-strong);
    border-radius: var(--radius);
    padding: 0.25rem 0.55rem;
}

.artifact-preview {
    display: block;
    width: 100%;
    padding: 0.5rem;
    border: 1px solid var(--line);
    background: #fff;
    cursor: zoom-in;
}

.artifact-preview img {
    display: block;
    width: 100%;
    height: auto;
    max-height: 360px;
    object-fit: contain;
}

.chip.with-thumb {
    padding-left: 0.2rem;
}

.chip-thumb {
    width: 22px;
    height: 22px;
    border-radius: var(--radius);
    object-fit: cover;
    flex: none;
}

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 35;
    background: color-mix(in srgb, var(--desk) 95%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: calc(env(safe-area-inset-top) + 3.2rem) 0.5rem
        calc(env(safe-area-inset-bottom) + 0.5rem);
    animation: fade var(--t-fade) var(--ease-almost);
    cursor: zoom-out;
}

.lightbox > img {
    animation: pop var(--t-in) var(--ease-out);
}

.lightbox img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--radius);
    background: #fff;
}

.lightbox-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: calc(env(safe-area-inset-top) + 0.4rem) 0.4rem 0.4rem 0.9rem;
    background: linear-gradient(color-mix(in srgb, var(--desk) 80%, transparent), transparent);
    cursor: default;
}

.lightbox-title {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 0.85rem;
    color: var(--muted);
}

/* ─── Notices, sign-in, plain pages ────────────────────────── */

/* Notices: small tiles that hang from the top edge, a state square in their level's color (the accent, a warning's
 * yellow, an error's red) and a countdown line until they go. A tap dismisses one, or does what it offers (a chevron
 * says so); on a phone, a swipe up puts it away. */
.notices {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    top: calc(env(safe-area-inset-top) + 0.6rem);
    z-index: 40;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: min(calc(100vw - 20px), 440px);
    pointer-events: none;
}

@media (min-width: 700px) {
    .notices {
        width: min(92vw, 400px);
    }
}

.notice {
    --level: var(--accent);
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: flex-start;
    gap: 11px;
    min-height: 44px;
    padding: 12px 12px 13px 14px;
    border-radius: var(--r-card);
    background:
        linear-gradient(100deg, color-mix(in srgb, var(--level) 9%, transparent), transparent 48%),
        var(--panel);
    box-shadow: var(--pop);
    color: var(--text);
    text-align: left;
    font-size: 13.5px;
    font-weight: 500;
    line-height: 1.4;
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
    animation: toast-in 0.28s var(--ease-out);
}

.notice.warning {
    --level: var(--warn);
}

.notice.error {
    --level: var(--err);
}

/* The level, as the session list's state squares say a session's: a lit square with a soft halo. */
.notice-mark {
    flex: none;
    width: 8px;
    height: 8px;
    margin: 6px 1px 0;
    border-radius: calc(var(--r-mark) - 0.5px);
    background: var(--level);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--level) 18%, transparent);
}

.notice-text {
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
}

.notice > .icon {
    flex: none;
    margin-top: 2px;
    color: var(--faint);
    transition: color var(--t-hover) var(--ease-out);
}

.notice.acts > .icon {
    color: var(--muted);
}

@media (hover: hover) {
    .notice:hover {
        background:
            linear-gradient(
                100deg,
                color-mix(in srgb, var(--level) 12%, transparent),
                transparent 55%
            ),
            var(--card);
    }

    .notice:hover > .icon {
        color: var(--text);
    }
}

.notice:active {
    scale: 0.985;
}

.notice:focus-visible {
    outline: 2px solid var(--accent-line);
    outline-offset: 2px;
}

/* How long until it goes: a hairline in its level's color, shrinking from the right. */
.notice::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: color-mix(in srgb, var(--level) 55%, transparent);
    transform-origin: left;
    animation: countdown var(--life, 4.5s) linear forwards;
}

.notice.held::after {
    animation-play-state: paused;
}

@keyframes countdown {
    to {
        transform: scaleX(0);
    }
}

/* Like the popovers' pop, but from above: the notice hangs from the top edge. `translate`, not `transform`, so one
 * swiped away goes on up from where the finger left it. */
@keyframes toast-in {
    from {
        opacity: 0;
        translate: 0 -8px;
        scale: 0.97;
    }
}

@keyframes toast-out {
    to {
        opacity: 0;
        translate: 0 -8px;
        scale: 0.97;
    }
}

.notice.leaving {
    pointer-events: none;
    animation: toast-out var(--t-out) linear forwards;
}

.signin,
.plain {
    max-width: 440px;
    margin: 0 auto;
    padding: 3rem 1.2rem;
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

.signin .pi.big {
    font-size: 4rem;
    text-align: center;
}

.signin h1,
.plain h1 {
    margin: 0;
    text-align: center;
    font-size: 1.4rem;
}

.plain form {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
}

.plain label {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    color: var(--muted);
}

.plain button {
    min-height: 42px;
    background: var(--accent-fill);
    color: var(--accent-ink);
    font-weight: 600;
    border-radius: calc(var(--r-control) + 1px);
    padding: 10px 16px;
}

.plain h1,
.signin h1 {
    color: var(--text);
    font-weight: 600;
}

body.plain-page {
    height: auto;
}

/* ─── People: who is here, typing, and the side chat ───────── */

/* Who else is here, in the top bar: an avatar with an online mark, and how many more. */
.people-button {
    height: 40px;
    min-width: 40px;
    padding: 0 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    position: relative;
    flex: none;
    color: var(--body);
    border-radius: var(--r-control);
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .people-button:hover {
        background: var(--hover);
        color: var(--text);
    }
}

.people-here {
    position: relative;
    display: inline-grid;
}

.online-mark {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--ok);
    box-shadow: 0 0 0 2px var(--bg);
}

.online-mark.away {
    background: var(--faint);
}

.people-more {
    font: 11px var(--mono);
    color: var(--muted);
}

.avatar {
    display: inline-grid;
    place-items: center;
    flex: none;
    background: color-mix(in srgb, var(--who, var(--accent)) 20%, transparent);
    color: var(--who, var(--accent));
    border: 0;
    border-radius: 50%;
    font-size: 0.62rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0;
}

.avatar.typing {
    animation: avatar-typing 1.2s ease-in-out infinite;
}

@keyframes avatar-typing {
    50% {
        background: var(--accent-soft);
    }
}

.typing-line {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 12px;
    color: var(--muted);
    padding: 0 0.2rem 0.3rem;
}

.typing-dots {
    display: inline-flex;
    gap: 3px;
}

.typing-dots span {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--accent);
    animation: typing-dot 1.2s infinite ease-in-out;
}

.typing-dots span:nth-child(2) {
    animation-delay: 0.15s;
}

.typing-dots span:nth-child(3) {
    animation-delay: 0.3s;
}

@keyframes typing-dot {
    0%,
    60%,
    100% {
        opacity: 0.3;
    }
    30% {
        opacity: 1;
    }
}

.chat-label {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px;
    color: var(--faint);
    font-size: 11.5px;
}

.chat-log {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex: 1;
    min-height: 80px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 4px 2px 8px;
}

.chat-log::before {
    content: "";
    margin-top: auto;
}

.chat-msg {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
}

.chat-msg.mine {
    align-items: flex-end;
}

.chat-msg:not(.grouped) {
    margin-top: 10px;
}

.chat-msg:first-child {
    margin-top: 0;
}

.chat-meta {
    font-size: 11.5px;
    display: flex;
    gap: 6px;
    padding: 0 4px;
    align-items: baseline;
    color: var(--faint);
}

.chat-meta .muted {
    color: var(--faint);
}

.chat-name {
    color: var(--who, var(--accent));
    font-weight: 600;
}

.chat-text {
    max-width: 85%;
    padding: 8px 12px;
    border-radius: calc(var(--r-window) + 2px) calc(var(--r-window) + 2px)
        calc(var(--r-window) + 2px) var(--r-tag);
    background: var(--card-2);
    color: var(--text);
    font-size: 13.5px;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.chat-msg.mine .chat-text {
    border-radius: calc(var(--r-window) + 2px) calc(var(--r-window) + 2px) var(--r-tag)
        calc(var(--r-window) + 2px);
    background: var(--accent-soft);
}

.chat-compose {
    display: flex;
    gap: 6px;
    align-items: flex-end;
    background: var(--card);
    border: 1px solid var(--hair-2);
    border-radius: var(--r-sheet);
    padding: 4px 4px 4px 14px;
}

.chat-compose:focus-within {
    border-color: var(--accent-line);
}

.chat-compose textarea {
    flex: 1;
    min-width: 0;
    border: 0;
    outline: 0;
    background: none;
    color: var(--text);
    resize: none;
    padding: 5px 0;
    max-height: 30vh;
    overflow-x: hidden;
    font: 13.5px/1.45 var(--sans);
}

.chat-compose .round.send {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    flex: none;
}

.chat-compose .round.send:disabled {
    background: var(--card-2);
    color: var(--faint);
    opacity: 1;
}

@media (pointer: coarse) {
    .chat-compose textarea {
        font-size: 16px;
    }

    .chat-compose .round.send {
        width: 40px;
        height: 40px;
    }
}

/* Codemode: the tool calls a script made, under its code. */
.nested-calls {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    margin: 0.35rem 0;
    font-size: 0.8rem;
}

.nested-call {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.45rem;
}

.nested-status {
    width: 1rem;
    text-align: center;
    color: var(--ok);
}

.nested-call.error .nested-status,
.nested-error {
    color: var(--err);
}

.nested-call.running .nested-status,
.nested-call.cancelled .nested-status {
    color: var(--muted);
}

.nested-error {
    flex-basis: 100%;
    padding-left: 1.45rem;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ─── Collaboration: activity, quotes, mentions, pins, notes, reactions, take turns ─── */

.avatar.away {
    opacity: 0.45;
}

.tabs {
    flex-wrap: nowrap;
}

.tabs button {
    flex: 1;
    white-space: nowrap;
}

.chat-event {
    text-align: center;
    font-size: 11.5px;
    color: var(--faint);
    margin: 5px 0;
}

.chat-msg.open .chat-text,
.chat-msg.mentions-me .chat-text {
    box-shadow: inset 0 0 0 1px var(--accent-line);
}

.chat-text {
    cursor: default;
}

.chat-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    padding: 2px 4px 4px;
}

.chat-quote {
    max-width: 85%;
    text-align: left;
    border: 1px solid var(--hair);
    border-radius: var(--r-row);
    background: var(--card);
    color: var(--muted);
    font-size: 12px;
    padding: 5px 10px;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}

.quote-draft {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-radius: var(--r-row);
    background: var(--card);
    color: var(--muted);
    font-size: 12px;
}

.quote-draft .quote-text {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mention {
    color: var(--accent);
    font-weight: 700;
}

.mention.me {
    background: var(--accent-soft);
    padding: 0 0.15rem;
}

.mention-list {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line);
    background: var(--panel);
}

.mention-list .list-item {
    margin: 0;
    border: 0;
    border-bottom: 1px solid var(--line);
}

.pin-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    overflow-y: auto;
}

.pin {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: calc(var(--r-control) + 1px);
    padding: 9px 8px 9px 12px;
}

.pin-main {
    flex: 1;
    min-width: 0;
    text-align: left;
}

.pin-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    font-size: 11.5px;
}

.pin-text {
    color: var(--text);
    font-size: 13px;
    overflow-wrap: anywhere;
}

textarea.notes {
    min-height: 12rem;
    resize: vertical;
    line-height: 1.5;
}

/* Bars above the message box: who drives (take turns), plan mode, a goal, a PR watch, and project trust. The dot says
   which: the accent for plan mode, a goal, and a watch, the warning color for a question (who drives, whether to
   trust) and for a watch that had to stop. */
.driver-bar,
.plan-bar,
.goal-bar,
.watch-bar,
.trust-bar,
.view-only {
    --tone: var(--warn);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding: 6px 10px 6px 14px;
    margin-bottom: 5px;
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    font-size: 13px;
    line-height: 1.4;
}

.driver-bar::before,
.plan-bar::before,
.goal-bar::before,
.watch-bar::before,
.trust-bar::before,
.view-only::before {
    content: "";
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--tone);
}

.plan-bar,
.goal-bar,
.watch-bar:is(.watching, .merged, .closed) {
    --tone: var(--accent);
}

.watch-bar a {
    color: inherit;
}

/* The trust question keeps its words a readable width: on a phone its answers go under them, together, to the right. */
.trust-bar > .grow {
    flex: 1 1 15rem;
}

/* The plan bar's words keep a readable width too: its buttons go under them when they would squeeze them. */
.plan-bar > .grow {
    flex: 1 1 18rem;
}

.plan-bar > .link {
    margin-left: auto;
}

/* Trust choices keep the three existing decisions, with a selected radio and soft accent card. */
.trust-choice {
    justify-content: flex-start;
    gap: 12px;
    padding: 14px;
    margin-bottom: 8px;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
}

.trust-choice.active {
    border-color: var(--accent-line);
}

.trust-radio {
    width: 18px;
    height: 18px;
    flex: none;
    border-radius: var(--r-pill);
    border: 1.5px solid var(--hair-2);
}

.active > .trust-radio {
    border: 5px solid var(--accent);
}

.trust-choice-text {
    flex: 1;
}

/* An answer in the trust sheet: what it does over the folder it is about, which wraps rather than squeezes it. */
.list-item > span.trust-choice-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
    min-width: 0;
    text-align: left;
}

.trust-choice-text > .mono {
    overflow-wrap: anywhere;
}

.trust-current {
    flex: none;
    color: var(--accent);
    font-size: 0.78rem;
}

.trust-actions {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin-left: auto;
}

.driver-bar.mine {
    --tone: var(--ok);
}

.driver-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--text);
    font-weight: 600;
}

.driver-label > .icon {
    color: var(--tone, var(--muted));
}

.driver-ask {
    color: var(--warn);
}

.driver-pick {
    flex-basis: 100%;
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.view-only {
    --tone: var(--muted);
}

.view-only > span {
    flex: 1;
}

.composer-row.stop-only {
    padding: 4px 6px;
}

.unread-dot {
    width: 8px;
    height: 8px;
    background: var(--accent);
}

.person-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
}

@media (max-width: 480px) {
    .person-row {
        flex-wrap: wrap;
    }
    .person-actions {
        flex-basis: 100%;
    }
}

.person-main {
    flex: 1;
    min-width: 0;
}

.person-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.3rem;
}

.flash {
    animation: flash 1.6s ease-out;
}

@keyframes flash {
    0%,
    30% {
        background: var(--accent-soft);
        outline: 1px solid var(--accent-line);
    }
}

/* ─── Parts of sheets: share, schedules, goals, running now, changes, spend ─── */

/* Share to Pi: what another app shared, before it goes into a message box. */
.share-text {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    max-height: 9rem;
    overflow-y: auto;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--card);
    padding: 12px 14px;
    margin: 0;
    font-size: 13.5px;
}

/* A switch with its label, inside a card such as an extension's. */
.setting {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.4rem;
}

/* A choice under its words when the two do not fit side by side, as on a phone. */
.setting.wrap {
    flex-wrap: wrap;
}

.setting.wrap > .grow {
    flex: 1 1 14rem;
}

/* A scheduled message in its sheet: what Pi gets, when, and who set it. */
.schedule {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 14px;
    font-size: 13.5px;
}

.schedule > .icon {
    flex: none;
    box-sizing: content-box;
    padding: 8px;
    border-radius: var(--r-row);
    background: var(--accent-soft);
    color: var(--accent);
}

/* A change to a lesson that waits for the owner, under the lesson it would change. */
.lesson-proposal {
    margin-top: 0.35rem;
    padding-left: 0.6rem;
    border-left: 2px solid var(--accent);
}

/* Under Pi's memory call: the lesson's state, and Approve and Discard while it waits. */
.lesson-call {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.6rem;
    margin-top: 0.3rem;
}

.lesson-call.waiting {
    padding: 0.35rem 0.5rem;
    background: var(--card);
    border: 1px solid var(--line);
    border-left: 2px solid var(--accent);
    font-size: 0.82rem;
}

/* The words that wait keep a readable width: where Approve and Discard would squeeze them, they go below. */
.lesson-call.waiting > .grow {
    flex: 1 1 16rem;
}

/* Memory: a lesson Pi keeps, who saved it and where, and what can be done with it. */
.lesson {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 11px 14px;
    font-size: 13.5px;
}

.sheet-list:has(> .lesson.pending) {
    border-color: var(--warn-line);
}

.lesson-text {
    overflow-wrap: anywhere;
}

.lesson-source a {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: var(--line-strong);
    overflow-wrap: anywhere;
}

.lesson-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.3rem 0.6rem;
}

.lesson-source {
    flex: 1 1 10rem;
    min-width: 0;
}

.lesson-actions {
    justify-content: flex-end;
    flex-wrap: wrap;
    margin-left: auto;
}

.lesson-actions .button.danger {
    border-color: var(--err);
    color: var(--err);
}

.lesson-add {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    border-radius: var(--r-window);
    border: 1px solid var(--hair);
    background: var(--card);
}

.lesson-add textarea {
    border: 0;
    background: none;
    resize: vertical;
    padding: 2px 4px;
}

.lesson-add > .row {
    flex-wrap: wrap;
}

.lesson-add .segmented {
    background: var(--bg);
    flex: 1 0 auto;
    flex-wrap: nowrap;
}

.lesson-add .segmented button {
    flex: 1;
    white-space: nowrap;
}

/* Done when: a goal met, or one Pi gave up on. */
.goal-bar.met {
    --tone: var(--ok);
}

.goal-bar.gave-up {
    --tone: var(--warn);
}

/* Running now: a session, then what is at work in it. */
.running {
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    overflow: hidden;
}

.running-head,
.running-task {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.running-head {
    padding: 10px 12px 10px 14px;
    background: var(--card);
}

.running-head > .folder-mark {
    width: 8px;
    height: 8px;
    border-radius: calc(var(--r-mark) - 0.5px);
}

.running-head .link {
    min-width: 0;
    text-align: left;
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.running-head .warn {
    padding: 1px 8px;
    border-radius: var(--r-pill);
    background: var(--warn-soft);
}

.running-head .button {
    background: var(--err-soft);
    color: var(--err);
}

.running-task {
    font-size: 13px;
    padding: 9px 14px;
    border-top: 1px solid var(--hair);
}

.running-task > .grow {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Spend: a person or a session, what Pi spent for it, and its limit. */
.spend-total {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 10px;
    color: var(--muted);
    font-size: 13px;
}

.spend-total strong {
    color: var(--text);
    font: 600 30px var(--mono);
    letter-spacing: -0.02em;
}

.spend-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 12px;
    min-height: 48px;
    padding: 10px 14px;
    font-size: 13.5px;
    color: var(--text);
}

.spend-row > .grow {
    min-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.spend-row > .mono {
    width: 64px;
    text-align: right;
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}

.spend-row > .muted {
    width: 100px;
    text-align: right;
}

.spend-change {
    width: 56px;
    flex: none;
    text-align: right;
}

.spend-usage {
    width: 80px;
    height: 5px;
    flex: none;
    overflow: hidden;
    border-radius: var(--r-mark);
    background: var(--hair-2);
    color: var(--accent);
}

.spend-usage.warn {
    color: var(--warn);
}

.spend-usage > span {
    display: block;
    width: var(--usage);
    height: 100%;
    background: currentColor;
}

@media (max-width: 480px) {
    .spend-row > .grow {
        flex-basis: calc(100% - 180px);
    }
    .spend-row > .muted {
        width: auto;
        margin-left: auto;
    }
    .spend-usage {
        width: 64px;
    }
}

.limit-edit {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.limit-edit input {
    width: 72px;
    min-height: 30px;
    padding: 4px 8px;
    border-radius: var(--r-seg);
    font-family: var(--mono);
}

/* ─── Launcher: sessions, actions, and themes, with visible search modes ─── */

.launcher-overlay {
    position: fixed;
    inset: 0;
    z-index: 45;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding: calc(env(safe-area-inset-top) + 11vh) 10px 10px;
    background: var(--scrim);
    animation: fade var(--t-fade) var(--ease-almost);
}

.launcher {
    width: min(640px, 100%);
    max-height: 74dvh;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    border-radius: var(--r-sheet);
    box-shadow: var(--pop);
    overflow: hidden;
    animation: pop 0.28s var(--ease-out);
    outline: none;
}

.leaving.launcher-overlay {
    animation: fade-out var(--t-out) linear forwards;
    pointer-events: none;
}

.leaving .launcher {
    animation: pop-out var(--t-out) linear forwards;
}

.launcher kbd {
    padding: 4px 6px;
    border: 1px solid var(--hair);
    border-radius: var(--r-tag);
    background: none;
    font-size: 10.5px;
    color: var(--faint);
}

.launcher-input {
    display: flex;
    flex: none;
    align-items: center;
    gap: 10px;
    height: 58px;
    padding: 0 12px 0 18px;
    border-bottom: 1px solid var(--hair);
    color: var(--accent);
}

.launcher-input .prompt {
    font: 600 15px var(--mono);
}

.launcher-input input {
    min-width: 0;
    flex: 1;
    border: 0;
    background: none;
    padding: 0;
    font-size: 16px;
    color: var(--text);
}

.launcher-input input:focus-visible {
    outline: none;
}

.launcher-input input::placeholder {
    color: var(--muted);
}

.launcher-escape {
    color: var(--muted);
}

.launcher-close {
    display: grid;
    place-items: center;
    flex: none;
    width: 32px;
    height: 32px;
    border-radius: var(--r-control);
    color: var(--muted);
}

@media (hover: hover) {
    .launcher-close:hover {
        background: var(--hover);
    }
}

.launcher-types {
    display: flex;
    flex: none;
    flex-wrap: wrap;
    gap: 4px;
    padding: 10px 14px 4px;
}

.launcher-types button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 28px;
    padding: 0 11px;
    border: 1px solid transparent;
    border-radius: var(--r-pill);
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 500;
}

.launcher-types button[aria-pressed="true"] {
    background: var(--card-2);
    border-color: var(--hair-2);
    color: var(--text);
}

@media (hover: hover) {
    .launcher-types button:hover {
        background: var(--card-2);
        border-color: var(--hair-2);
        color: var(--text);
    }
}

.launcher-types kbd {
    padding: 0;
    border: 0;
    background: none;
    font-size: 11px;
    color: var(--faint);
}

.launcher-summary {
    display: flex;
    flex: none;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 4px 18px 0;
    min-height: 36px;
    color: var(--faint);
    font-size: 12px;
}

.launcher-summary .launcher-group {
    flex: 1;
    padding: 0;
}

.launcher-summary button {
    min-height: 36px;
    padding: 0.4rem;
    color: var(--text);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.launcher-list {
    position: relative;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 4px 8px 8px;
    scroll-padding: 8px;
}

.launcher-list:empty {
    flex: none;
    padding: 0;
}

.launcher-group {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 10px 5px;
    font-size: 12px;
    font-weight: 500;
    color: var(--faint);
}

.launcher-count {
    font: 400 11px var(--mono);
}

.launcher-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 42px;
    padding: 6px 10px;
    border-radius: var(--r-control);
    text-align: left;
    color: var(--text);
}

.launcher-item.on {
    background: var(--card-2);
}

.launcher-item .glyph {
    width: 28px;
    height: 28px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: calc(var(--r-row) - 1px);
    background: var(--card);
    color: var(--muted);
}

.launcher-item .main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.35;
}

.launcher-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 14px;
    font-weight: 400;
}

.launcher-item .detail {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
    font-size: 12px;
    color: var(--muted);
}

.launcher-path {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.launcher-path.session-path {
    font-family: var(--mono);
}

.launcher-state {
    flex: none;
    max-width: 50%;
    height: 20px;
    padding: 0 8px;
    line-height: 20px;
    border-radius: var(--r-pill);
    background: var(--card);
    color: var(--muted);
    font-size: 11.5px;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.launcher-state.waiting {
    background: var(--warn-soft);
    color: var(--warn);
}

.launcher-state.working {
    background: var(--accent-soft);
    color: var(--accent);
}

.launcher-folder {
    width: 9px;
    height: 9px;
    border-radius: var(--r-mark);
    background: var(--folder);
}

.launcher-match-note {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-style: italic;
}

.launcher mark {
    color: var(--text);
    text-decoration-color: var(--accent);
}

.launcher-item .hint {
    flex: none;
    display: flex;
    gap: 4px;
    align-items: center;
    font-size: 11px;
    color: var(--faint);
}

.launcher-item .hint kbd {
    color: inherit;
}

.launcher-item .swatch {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 28px;
    height: 28px;
    flex: none;
    border-radius: calc(var(--r-row) - 1px);
    overflow: hidden;
    box-shadow: 0 0 0 1px var(--hair-2);
}

.launcher-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.65rem;
    min-height: 0;
    overflow-y: auto;
    padding: 1.6rem 1rem;
    color: var(--muted);
    text-align: center;
    font-size: 0.9rem;
}

.launcher-empty strong {
    color: var(--text);
    overflow-wrap: anywhere;
}

.launcher-empty .button {
    min-height: 44px;
    flex: none;
    margin-top: 0.45rem;
}

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

.launcher-foot {
    display: flex;
    flex: none;
    flex-wrap: wrap;
    gap: 8px 16px;
    padding: 10px 18px;
    border-top: 1px solid var(--hair);
    font-size: 12px;
    color: var(--faint);
}

.launcher-foot span {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.launcher-foot kbd {
    padding: 0;
    border: 0;
    color: inherit;
}

.launcher-prefix-help {
    margin-left: auto;
}

.launcher-foot .launcher-touch-help {
    display: none;
}

@media (pointer: coarse) {
    .launcher-overlay {
        padding: calc(env(safe-area-inset-top) + 16px) 8px calc(env(safe-area-inset-bottom) + 16px);
    }
    .launcher {
        max-height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 32px);
    }
    .launcher-input {
        padding: 0.5rem 0.7rem;
        gap: 0.6rem;
    }
    .launcher-escape,
    .launcher-types kbd,
    .launcher-item .hint:has(kbd) {
        display: none;
    }
    .launcher-types {
        gap: 0.3rem;
        padding: 0.5rem;
    }
    .launcher-close {
        width: 44px;
        height: 44px;
    }
    .launcher-types button {
        height: auto;
        flex: 1;
        min-height: 44px;
        padding-inline: 0.5rem;
    }
    .launcher-summary,
    .launcher-summary button {
        min-height: 44px;
    }
    .launcher-item {
        min-height: 60px;
        gap: 0.6rem;
        padding-inline: 0.6rem;
    }
    .launcher-item .detail {
        gap: 0.4rem;
    }
    .launcher-foot .launcher-key-help,
    .launcher-foot .launcher-prefix-help {
        display: none;
    }
    .launcher-foot .launcher-touch-help {
        display: block;
    }
}

/* ─── Appearance ───────────────────────────────────────────── */

.theme-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
}

/* A theme card draws a tiny Hyprland desktop in its own palette: the card sets the --o-* colors it uses. */
.theme-card {
    position: relative;
    display: flex;
    flex-direction: column;
    text-align: left;
    gap: 8px;
    padding: 8px 8px 10px;
    border-radius: var(--r-window);
    background: var(--o-bg);
    color: var(--o-fg);
    border: 1px solid color-mix(in srgb, var(--o-fg) 17%, transparent);
    transition:
        border-color var(--t-hover) var(--ease-out),
        box-shadow var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .theme-card:hover {
        border-color: var(--o-accent);
    }
}

.theme-card:active {
    transform: scale(0.97);
}

.theme-card.on {
    border-color: var(--o-accent);
    box-shadow:
        0 0 0 2px var(--o-bg),
        0 0 0 4px var(--o-accent);
}

.tc-desk {
    display: flex;
    gap: 5px;
    height: 62px;
    padding: 6px;
    border-radius: 9px;
    background: var(--o-bg-darker);
}

.tc-win {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px;
    border-radius: 5px;
    background: var(--o-bg);
    border: 1px solid color-mix(in srgb, var(--o-fg) 13%, transparent);
}

.tc-win:first-child {
    width: 34%;
}

.tc-win:last-child {
    flex: 1;
    border-color: var(--o-accent);
}

.tc-win i {
    height: 4px;
    border-radius: 2px;
    background: var(--o-fg);
    opacity: 0.4;
}

.tc-win i:nth-child(1) {
    width: 80%;
}

.tc-win i:nth-child(2) {
    width: 55%;
}

.tc-win i.lit {
    margin-top: auto;
    align-self: flex-end;
    height: 8px;
    border-radius: 3px;
    background: var(--o-accent);
    opacity: 1;
    width: 30%;
}

.tc-name {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 13px;
    font-weight: 500;
    color: var(--o-fg-bright, var(--o-fg));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tc-name small {
    font-weight: 400;
    font-size: 11px;
    color: inherit;
    opacity: 0.6;
}

.tc-dots {
    display: flex;
    gap: 4px;
}

.tc-dots i {
    width: 10px;
    height: 10px;
    border-radius: 3px;
}

.theme-desktop {
    grid-column: 1 / -1;
    flex-direction: row;
}

.theme-desktop .tc-desk {
    width: 42%;
    flex: none;
    height: auto;
    min-height: 70px;
}

.theme-desktop .tc-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
}

.theme-desktop .tc-note {
    padding: 0 0 0.45rem;
    font-size: 0.68rem;
    color: var(--o-fg);
    opacity: 0.75;
}

.setting-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: calc(12px * var(--space-y)) calc(14px * var(--space-x));
    background: var(--o-bg);
    font-size: 14px;
}

.setting-row .segmented {
    align-self: center;
    flex: none;
}

@media (max-width: 480px) {
    .setting-row:has(.segmented) {
        flex-wrap: wrap;
        gap: 8px;
    }
    .setting-row:has(.segmented) .setting-text {
        flex-basis: 100%;
    }
}

.setting-row .setting-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.setting-row .setting-text span:first-child {
    color: var(--text);
}

.setting-row .setting-text span + span {
    font-size: 12px;
    color: var(--muted);
}

.shortcuts {
    display: grid;
    grid-template-columns: 9.5rem 1fr;
    gap: 8px 18px;
    margin: 0;
    font-size: 13.5px;
    align-items: baseline;
}

.shortcuts dt {
    display: flex;
    gap: 0.2rem;
    justify-content: flex-end;
}

.shortcuts dd {
    margin: 0;
    color: var(--body);
}

/* The theme: a card for each theme folder, in the app's own colors (a theme cannot be drawn small, as colors can). */
.look-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 10px;
}

.look-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    min-height: 64px;
    padding: 10px 12px;
    text-align: left;
    border-radius: var(--r-card);
    background: var(--card);
    border: 1px solid var(--hair-2);
    transition: border-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .look-card:not(:disabled):hover {
        border-color: var(--accent-line);
    }
}

.look-card.on {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent);
}

.look-card.broken {
    cursor: default;
    opacity: 0.8;
}

.look-name {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--text);
}

.look-name small {
    font: 10.5px var(--mono);
    color: var(--faint);
}

.look-detail {
    font-size: 12px;
    color: var(--muted);
}

.look-problem {
    font-size: 12px;
    color: var(--err);
}

.look-tools,
.look-duplicate {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 10px 0 4px;
}

.look-duplicate input {
    flex: 1;
    min-width: 160px;
}

/* ─── Sign in: the app's screen (the server's pages are under Notices) ─── */

.signin {
    animation: rise-in 0.5s var(--ease-out);
}

.signin .row {
    padding: 6px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-window);
    background: var(--card);
    box-shadow: var(--shadow);
}

.signin .row:focus-within {
    border-color: var(--accent-line);
}

.signin .row input {
    min-width: 0;
    border: 0;
    background: none;
}

.signin .row input:focus-visible {
    outline: none;
}

/* ─── Small glue: the sheet host, viewers leaving, search keys, unread dots ─── */

.sheet-host {
    display: contents;
}

.leaving .viewer,
.leaving .lightbox {
    animation: fade-out var(--t-out) linear forwards;
}

.viewer {
    animation: pop 0.28s var(--ease-out);
}

.search-keys {
    display: inline-flex;
    gap: 2px;
    flex: none;
    cursor: pointer;
    opacity: 0.8;
    transition: opacity var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .search-keys:hover {
        opacity: 1;
    }
}

.search:has(input:focus) .search-keys {
    opacity: 0;
}

/* A narrow list keeps the search's words whole: its keys give way. */
@container sessions (max-width: 200px) {
    .search-keys {
        display: none;
    }
}

@media (pointer: coarse) {
    .search-keys,
    .splash-actions kbd,
    .launcher-item .hint kbd {
        display: none;
    }
}

/* Subagents at work, in the top bar: marked, not blinking. */
.topbar .pulse {
    animation: none;
}

.unread-dot {
    animation: popin var(--t-in) var(--ease-out);
}

.empty.hint .pi {
    animation: boot-breathe 3s var(--ease-in-out) infinite;
}

/* ─── People panel ─────────────────────────────────────────── */

/* Wide screens: the chat, pinned, and notes in a window beside the conversation, sliding in from the right. Narrower
 * ones show them as a sheet instead, so the panel exists only where it fits. */
.people {
    flex: 0 0 var(--people-w, 320px);
    height: 100dvh;
    border-left: 1px solid var(--hair);
    background: var(--bg);
}

/* Past the tiled windows' pop-in, which would otherwise win. */
:root .layout > .people.window {
    animation: people-in var(--t-in) var(--ease-out) backwards;
}

:root .layout > .people.window.leaving {
    animation: people-out var(--t-out) linear forwards;
}

@keyframes people-in {
    from {
        opacity: 0;
        transform: translateX(48px);
    }
}

@keyframes people-out {
    to {
        opacity: 0;
        transform: translateX(48px);
    }
}

.people-head {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 58px;
    flex: none;
    padding: 0 10px 0 16px;
    border-bottom: 1px solid var(--hair);
}

.people-head h2 {
    margin: 0;
    color: var(--text);
    font-size: 15px;
    font-weight: 600;
}

.people-count {
    flex: 1;
    font: 11px var(--mono);
    color: var(--faint);
}

.people-head .icon-button {
    width: 32px;
    height: 32px;
    border-radius: var(--r-row);
}

.people .sheet-body,
.people-sheet .sheet-body {
    flex: 1;
    min-height: 0;
    padding: 0;
    overflow: hidden;
}

.people-sheet {
    height: 86dvh;
}

.people-sheet .sheet-head h2 {
    flex: none;
}

.people-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    gap: 6px;
    padding: 8px 10px 10px;
    overflow-y: auto;
}

.people-content > :not(.chat-log, .pin-list, .notes) {
    flex-shrink: 0;
}

.people-roster {
    max-height: 176px;
    overflow-y: auto;
}

.people-person {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px;
    border-radius: var(--r-row);
}

.people-person-info {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    line-height: 1.3;
}

.people-person-name {
    color: var(--text);
    font-size: 13.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.people-person-state {
    font-size: 12px;
    color: var(--muted);
}

.people-person-state.typing {
    color: var(--accent);
}

.people-role {
    font-size: 11.5px;
    color: var(--faint);
}

.people-turns {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 2px 2px;
    padding: 10px 12px;
    border-radius: calc(var(--r-control) + 1px);
    background: var(--card);
}

.people-turns-title,
.people-turns-hint {
    display: block;
    line-height: 1.35;
}

.people-turns-title {
    font-size: 13px;
    color: var(--text);
}

.people-turns-hint {
    font-size: 11.5px;
    color: var(--muted);
}

.people-turns .button {
    min-height: 28px;
    border-radius: calc(var(--r-row) - 1px);
    padding: 0 11px;
    font-size: 12px;
    flex: none;
}

.people-pin {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin: 0 2px;
    padding: 9px 12px;
    border: 1px solid var(--hair);
    border-radius: calc(var(--r-control) + 1px);
    text-align: left;
    font-size: 12.5px;
    color: var(--body);
}

.people-pin > .icon {
    color: var(--accent);
    flex: none;
    margin-top: 3px;
}

.people-pin > span {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.people-pin b {
    font-weight: 600;
    color: var(--text);
}

.people-content .mention-list {
    border: 1px solid var(--hair-2);
    border-radius: var(--r-card);
    overflow: hidden;
    background: var(--bg);
    box-shadow: var(--shadow);
}

.people-content textarea.notes {
    flex: 1;
    min-height: 160px;
    resize: none;
    border-radius: var(--r-card);
    font-size: 13.5px;
}

.people-button.on {
    color: var(--accent);
    background: var(--accent-soft);
}

@media (pointer: coarse) {
    .people-head .icon-button,
    .people-turns .button {
        min-height: 40px;
        min-width: 40px;
    }

    .people-content textarea.notes {
        font-size: 16px;
    }
}

/* ─── Peek tiles ───────────────────────────────────────────── */

/* Other sessions beside the conversation, one tile each: a column on wide screens, scrolling, and a strip under the
 * top bar on narrow ones. With tiling, the column is bare and each tile a card of its own; the column takes the focus
 * ring. Turned on or off, the column slides like the People panel; the tiles in it then change without motion: only
 * the conversation moves. */
.peeks {
    flex: 0 0 var(--peeks-w, clamp(260px, 21vw, 340px));
    height: 100dvh;
    min-height: 0;
    border-left: 1px solid var(--hair);
    background: var(--panel);
}

:root .layout > .peeks.window {
    animation: people-in var(--t-in) var(--ease-out) backwards;
}

:root .layout > .peeks.window.leaving {
    animation: people-out var(--t-out) linear forwards;
}

/* Turned on with nothing to show yet: what will show here. */
.peeks-empty {
    margin: auto 0;
    padding: 24px 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    text-align: center;
    color: var(--muted);
    font-size: 13px;
}

.peeks-empty p {
    margin: 0;
}

.peeks-empty .icon {
    color: var(--faint);
}

/* The top bar's switch, while off: another session waits for you. */
.peek-dot {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--warn);
    box-shadow: 0 0 0 2px var(--bg);
}

.peeks-list {
    position: relative;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px;
    scroll-snap-type: y proximity;
    scrollbar-width: thin;
}

.peek {
    position: relative;
    flex: none;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--hair);
    border-radius: var(--r-window);
    background: var(--card);
    scroll-snap-align: start;
    transition: border-color var(--t-hover) var(--ease-out);
}

.peek.waiting {
    border-color: var(--warn-line);
}

/* Its header opens the session: its folder's square and title, and its path. */
.peek-head {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding: 12px 14px 8px;
    /* The tile's corners, inside its border: the hover fill and the focus ring follow them. */
    border-radius: calc(var(--r-window) - 1px) calc(var(--r-window) - 1px) 0 0;
    text-align: left;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .peek-head:hover {
        background: var(--hover);
    }
}

/* Inside the tile, which cuts off what is past its rounded edge. */
.peek-head:focus-visible {
    outline-offset: -2px;
}

.peek-name {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.peek-title,
.peek-cwd {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.peek-title {
    flex: 1;
    min-width: 0;
    color: var(--text);
    font-size: 13.5px;
    font-weight: 500;
}

.peek-cwd {
    padding-left: 16px;
    color: var(--faint);
    font-size: 11px;
}

/* The last few lines: a mark for who or what, then the words, two lines at most. */
.peek-lines {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 2px 14px 10px;
    cursor: pointer;
}

.peek-line {
    display: flex;
    gap: 7px;
    min-width: 0;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--body);
}

.peek-mark {
    flex: none;
    width: 14px;
    font: 600 11px / 18px var(--mono);
    color: var(--faint);
}

.peek-line.user .peek-mark {
    color: var(--accent);
}

/* Pi's own words: its mark in Georgia, as everywhere. */
.peek-mark.pi {
    color: var(--brand);
    font:
        13px / 1.5 Georgia,
        serif;
}

.peek-text {
    min-width: 0;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.peek-line.user .peek-text {
    color: var(--muted);
}

.peek-line.user b {
    color: var(--o-cyan);
    font-weight: 600;
}

.peek-line.cmd .peek-text {
    font: 12px / 1.5 var(--mono);
}

.peek-line.err,
.peek-line .err {
    color: var(--err);
}

.peek-line.faint {
    color: var(--faint);
}

.peek-run {
    color: var(--accent);
}

.peek-skeleton i {
    display: block;
    height: 0.45rem;
    margin: 0.3rem 0;
    border-radius: var(--r-mark);
    background: var(--card-2);
}

.peek-skeleton i:nth-child(2) {
    width: 80%;
}

.peek-skeleton i:nth-child(3) {
    width: 60%;
}

/* The call a session waits on: the whole command when it is short enough to allow from here, and the guard's reason. */
.peek-ask {
    flex: none;
    margin: 0 10px 10px;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    border: 1px solid var(--warn-line);
    border-radius: var(--r-control);
    background: var(--warn-soft);
}

.peek-ask-tool {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--warn);
}

.peek-ask-what {
    font-size: 12px;
    line-height: 1.45;
    color: var(--text);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    overflow: hidden;
}

/* A command short enough to allow from here shows whole, never clamped. */
.peek-ask-what.whole {
    display: block;
    -webkit-line-clamp: unset;
    line-clamp: none;
    overflow: visible;
}

.peek-ask-why {
    font-size: 12px;
    color: var(--muted);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

/* The state in words (needs you, working, done, new), and Deny and Allow where a call waits. */
.peek-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 10px 0 14px;
    border-top: 1px solid var(--hair);
}

.peek-status {
    flex: 1;
    min-width: 0;
    color: var(--faint);
    font-size: 12.5px;
    font-weight: 500;
    white-space: nowrap;
}

.peek-status::first-letter {
    text-transform: uppercase;
}

.peek.working .peek-status {
    color: var(--accent);
}

.peek.waiting .peek-status {
    color: var(--warn);
}

.peek.done .peek-status {
    color: var(--ok);
}

/* The command a tile asks about opens its session too, as the rest of the tile does: there it shows whole. */
.peek-ask-host {
    display: contents;
    cursor: pointer;
}

.peek-actions {
    display: inline-flex;
    gap: 8px;
}

.peek-actions .button.small {
    min-height: 30px;
    padding: 0 12px;
    border: 0;
    border-radius: calc(var(--r-row) - 1px);
    background: var(--card-2);
    color: var(--text);
    font-size: 12.5px;
    font-weight: 500;
}

@media (hover: hover) {
    .peek-actions .button.small:hover:not(:disabled) {
        color: var(--err);
    }
}

.peek-actions .button.small.primary {
    padding: 0 14px;
    background: var(--accent-fill);
    color: var(--accent-ink);
    font-weight: 600;
}

@media (hover: hover) {
    .peek-actions .button.small.primary:hover:not(:disabled) {
        background: color-mix(in oklab, var(--accent-fill) 85%, var(--text));
        color: var(--accent-ink);
    }
}

.peek-seen {
    width: 30px;
    height: 30px;
    color: var(--ok);
}

/* Calls waiting for approval out of view: a way to them, at the column's edge. */
.peeks-jump {
    position: absolute;
    left: 50%;
    z-index: 2;
    transform: translateX(-50%);
    padding: 5px 12px;
    border-radius: var(--r-pill);
    background: var(--warn);
    box-shadow: var(--pop);
    color: var(--accent-ink);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
}

.peeks-jump.up {
    top: 8px;
}

.peeks-jump.down {
    bottom: 8px;
}

.peek-strip {
    flex: none;
    animation: peek-strip-in var(--t-in) var(--ease-out) backwards;
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    padding: 8px 12px;
    border-bottom: 1px solid var(--hair);
    scroll-snap-type: x proximity;
    scrollbar-width: none;
}

.peek-strip::-webkit-scrollbar {
    display: none;
}

@keyframes peek-strip-in {
    from {
        opacity: 0;
        transform: translateY(-8px);
    }
}

.peek-strip .peek {
    width: 240px;
    border-radius: var(--r-card);
}

.peek-strip .peek-head {
    padding: 8px 12px 2px;
    border-radius: calc(var(--r-card) - 1px) calc(var(--r-card) - 1px) 0 0;
}

.peek-strip .peek-cwd {
    display: none;
}

.peek-strip .peek-lines {
    padding: 0 12px 8px;
}

.peek-strip .peek-ask {
    margin: 0 8px 8px;
    padding: 8px 10px;
}

.peek-strip .peek-foot {
    min-height: 0;
    padding: 0 8px 8px 12px;
    border-top: 0;
}

@media (min-width: 960px) {
    /* Bare: the tiles are the cards, and the column's ring shows the focus. */
    :root[data-tiling="on"] .peeks.window {
        height: auto;
        border: 0;
        border-radius: var(--r-window);
        overflow: visible;
        background: none;
    }
    :root[data-tiling="on"][data-focus="peeks"] .peeks.window {
        outline: 1px solid var(--window-border-active);
        outline-offset: 2px;
    }
    :root[data-tiling="on"] .peeks-list {
        padding: 0;
    }
    :root[data-tiling="on"] .peeks .peek {
        background: var(--bg);
    }
}

/* ─── Diff viewer ──────────────────────────────────────────── */

/* One file's diff, a rounded card: a header that sticks while its lines scroll by, then the lines in a table, one or
 * two sides. (`clip`, not `hidden`: the header must still stick to the scroller that holds the card.) */
.dv {
    --dv-n: 40px;
    --dv-add: color-mix(in srgb, var(--ok) 11%, transparent);
    --dv-del: color-mix(in srgb, var(--err) 11%, transparent);
    min-width: 0;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--code-bg);
    overflow: clip;
}

@media (max-width: 520px) {
    .dv {
        --dv-n: 34px;
    }
}

.dv-head {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 9px;
    min-height: 42px;
    padding: 0 10px;
    background: var(--card);
    border-bottom: 1px solid var(--hair);
    font-size: 12.5px;
}

.dv.folded .dv-head {
    border-bottom: 0;
}

.dv.viewed .dv-name {
    color: var(--muted);
}

.dv-fold {
    display: inline-grid;
    place-items: center;
    width: 24px;
    height: 24px;
    flex: none;
    border-radius: calc(var(--r-tag) + 1px);
    color: var(--muted);
}

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

/* What kind of change: M, A, D, R in a small tile. */
.change-kind {
    flex: none;
    display: grid;
    place-items: center;
    width: 18px;
    height: 18px;
    border-radius: var(--r-tag);
    background: var(--warn-soft);
    color: var(--warn);
    font: 600 10px/1 var(--mono);
}

.change-kind.added,
.change-kind.new {
    background: var(--ok-soft);
    color: var(--ok);
}

.change-kind.deleted {
    background: var(--err-soft);
    color: var(--err);
}

.change-kind.renamed {
    background: var(--accent-soft);
    color: var(--accent);
}

.dv-title {
    flex: 1;
    min-width: 0;
    display: flex;
    text-align: left;
    color: inherit;
}

/* A renamed file's old path, before its new one. */
.dv-was {
    margin-right: 0.5ch;
}

/* A long path gives up its folders before its name. */
.dv-path {
    display: flex;
    min-width: 0;
    font-family: var(--mono);
    white-space: nowrap;
}

.dv-dir {
    min-width: 1ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--faint);
    font-family: var(--mono);
}

.dv-name {
    flex: none;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text);
    font-weight: 600;
}

.dv-counts {
    display: inline-flex;
    gap: 6px;
    flex: none;
    font: 11.5px var(--mono);
}

.dv-chip {
    flex: none;
    height: 18px;
    padding: 0 6px;
    border-radius: var(--r-tag);
    font-size: 11px;
}

.dv-chip.warn {
    color: var(--warn);
    border-color: var(--warn-line);
}

.dv-tool.icon-button {
    width: 28px;
    height: 28px;
    border-radius: calc(var(--r-row) - 1px);
    font-size: 13px;
    color: var(--muted);
}

@media (hover: hover) {
    .dv-tool.icon-button:hover {
        color: var(--text);
    }
}

/* On touch, the icons a size up. */
@media (pointer: coarse) {
    .dv-tool .icon,
    .file-tools .icon-button .icon {
        width: 18px;
        height: 18px;
    }
}

.dv-tool.danger {
    width: auto;
    padding: 0 8px;
    color: var(--err);
}

/* Viewed: a checkbox in a small button. Checking it folds the file away. */
.dv-viewed {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: none;
    height: 26px;
    padding: 0 9px 0 7px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-seg);
    font-size: 12px;
    font-weight: 500;
    color: var(--muted);
    cursor: pointer;
    user-select: none;
    transition:
        background-color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

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

.dv-viewed.on {
    border-color: var(--accent-line);
    background: var(--accent-soft);
    color: var(--accent);
}

.dv-viewed:has(:focus-visible) {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.dv-viewed input {
    appearance: none;
    position: relative;
    flex: none;
    width: 13px;
    height: 13px;
    margin: 0;
    padding: 0;
    border: 1.5px solid currentColor;
    border-radius: calc(var(--r-tag) - 1px);
    background: none;
    cursor: pointer;
}

.dv-viewed input:checked {
    background: var(--accent);
    border-color: var(--accent);
}

.dv-viewed input:checked::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--accent-ink);
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5L20 7'/%3E%3C/svg%3E")
        center / 9px no-repeat;
}

@media (max-width: 520px) {
    .dv-viewed span {
        display: none;
    }
}

.dv-scroll {
    overflow-x: auto;
    padding: 4px 0 8px;
}

.dv-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font: 12px/1.7 var(--mono);
    color: var(--body);
    tab-size: 4;
}

/* Without wrapping, a long line scrolls the diff sideways instead of breaking. */
.dv:not(.wrap) .dv-table {
    width: max-content;
    min-width: 100%;
}

/* Side by side, the two halves stay as wide as each other however long their lines. */
.dv:not(.wrap) .dv-table.split col:not(.dv-col-n) {
    width: 50%;
}

.dv:not(.wrap) .dv-table.split .dv-n {
    min-width: var(--dv-n);
}

.dv-col-n {
    width: var(--dv-n);
}

.dv-n {
    padding: 0 8px 0 0;
    text-align: right;
    vertical-align: top;
    color: var(--faint);
    user-select: none;
    white-space: nowrap;
}

/* Numbers are drawn, not written: copying lines leaves them out. */
.dv-n::before {
    content: attr(data-n);
}

.dv-n.go {
    cursor: pointer;
}

@media (hover: hover) {
    .dv-n.go:hover {
        color: var(--accent);
        text-decoration: underline;
    }
}

/* The code, with the sign of an added or removed line in an 18px column of its own. */
.dv-code {
    position: relative;
    padding: 0 12px 0 18px;
    vertical-align: top;
    white-space: pre;
}

.dv.wrap .dv-code {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.dv-code::before {
    content: attr(data-sign);
    position: absolute;
    left: 0;
    width: 18px;
    text-align: center;
    user-select: none;
}

.dv-code:empty::after {
    content: " ";
}

.dv-code.add,
.dv-n.add,
.dv-row.add > .dv-n.none {
    background: var(--dv-add);
}

.dv-code.del,
.dv-n.del,
.dv-row.del > .dv-n.none {
    background: var(--dv-del);
}

.dv-code.add::before {
    color: var(--ok);
}

.dv-code.del::before {
    color: var(--err);
}

.dv-code.add mark {
    background: color-mix(in srgb, var(--ok) 32%, transparent);
    color: inherit;
}

.dv-code.del mark {
    background: color-mix(in srgb, var(--err) 32%, transparent);
    color: inherit;
}

/* A comment's words that changed: the comment's faint color is too weak on the change's highlight. */
.dv-code .hl-com mark,
.dv-code mark .hl-com {
    color: var(--muted);
}

/* The side of a split row with no line: hatched, as an absence rather than an empty line. */
.dv-code.none,
.dv-n.none {
    background: repeating-linear-gradient(
        -45deg,
        transparent 0 5px,
        color-mix(in srgb, var(--body) 4%, transparent) 5px 6px
    );
}

.dv-table.split .dv-code + .dv-n {
    border-left: 1px solid var(--hair);
}

.dv-hunk td {
    padding: 6px 12px;
    color: var(--accent);
    font-size: 11.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dv-context {
    margin-left: 0.8em;
    color: var(--muted);
}

.dv-gap td {
    padding: 2px 8px;
    background: var(--hover);
    text-align: center;
}

.dv-gap button {
    padding: 2px 10px;
    border-radius: calc(var(--r-tag) + 1px);
    color: var(--accent);
    font: 11.5px var(--mono);
}

@media (hover: hover) {
    .dv-gap button:hover {
        background: var(--hover);
    }
}

.dv-reading {
    color: var(--muted);
    font: 11.5px var(--mono);
}

/* A note under a line ("No newline at end of file") starts where the code does: past the numbers, and the sign. */
.dv-note td {
    padding: 0 12px 0 calc(2 * var(--dv-n) + 18px);
    color: var(--muted);
    font-style: italic;
}

.dv-table.split .dv-note td {
    padding-left: calc(var(--dv-n) + 18px);
}

.dv-note span {
    font-size: 11.5px;
}

.dv-empty {
    margin: 0;
    padding: 10px 14px;
    color: var(--muted);
    font-size: 13px;
}

.dv-empty.err {
    color: var(--err);
}

.dv-empty .link {
    margin-left: 0.4rem;
}

.dv-wait {
    padding: 6px 14px;
}

/* A diff in a tool card or a reply: it scrolls inside a bound, like the card's other output. */
.dv-block {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-height: 60vh;
    overflow: auto;
}

.dv-block .dv-head {
    position: static;
}

/* ─── Review ─────────────────────────────────────────────── */

.dr {
    display: flex;
    flex-direction: column;
    outline: none;
    min-width: 0;
}

/* "N files", the counts, how many are viewed, then the layout and Look again. */
.dr-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
    padding: 12px 14px;
    font-size: 13px;
    color: var(--muted);
}

/* The folder gives way when there is no room; the branch, a way to switch it, stays in sight. */
.dr-where {
    flex: 0 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11px;
}

.dr-path {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--faint);
}

.dr-branch {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 20px;
    padding: 0 7px;
    border-radius: calc(var(--r-tag) + 1px);
    background: var(--card);
    color: var(--muted);
}

@media (hover: hover) {
    button.dr-branch:hover {
        background: var(--card-2);
        color: var(--accent);
    }
}

.dr-stats {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.dr-stats strong {
    color: var(--text);
    font-weight: 500;
}

.dr-stats .dv-counts {
    font-size: 12px;
}

.dr-viewed {
    font-size: 12.5px;
}

/* The layout and Look again, together at the end of the row, or of the next one when there is no room. */
.dr-actions {
    flex: none;
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
}

.dr-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    padding: 0 12px 10px;
}

.dr-filter,
.ft-filter {
    flex: 1;
    min-width: 7rem;
    height: 30px;
    padding: 0 10px;
    border-color: var(--hair);
    border-radius: calc(var(--r-row) - 1px);
}

@media (pointer: fine) {
    .dr-filter,
    .ft-filter {
        font-size: 12.5px;
    }
}

.dr-tools .chip {
    height: 30px;
    padding: 0 10px;
    border-radius: calc(var(--r-row) - 1px);
    background: none;
    font-size: 12px;
}

.dr-main {
    display: grid;
    gap: 10px;
    min-width: 0;
    padding: 0 12px 14px;
}

.dr.wide .dr-main {
    grid-template-columns: minmax(170px, 240px) minmax(0, 1fr);
    align-items: start;
}

.dr-tree {
    padding: 6px;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--card);
    max-height: 40vh;
    overflow: auto;
}

.dr.wide .dr-tree {
    position: sticky;
    top: 0;
    max-height: calc(100dvh - 10rem);
}

/* A row of a tree of files, the changed ones and the folder's: a rounded 28px row in mono. */
.dr-row,
.ft-row {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    min-height: 28px;
    padding: 0 8px 0 calc(8px + var(--depth, 0) * 14px);
    border-radius: var(--r-seg);
    text-align: left;
    color: var(--body);
    font: 12.5px var(--mono);
    white-space: nowrap;
}

.ft-entry {
    display: flex;
    align-items: center;
    min-width: 0;
}

.ft-entry > .ft-row {
    flex: 1;
    min-width: 0;
}

.ft-entry > .ft-copy {
    flex: none;
    width: 28px;
    height: 28px;
    color: var(--muted);
}

.ft-row.muted {
    color: var(--muted);
}

@media (hover: hover) {
    .dr-row:hover,
    .ft-row:hover {
        background: var(--hover);
    }
}

.dr-row.on,
.ft-row.on {
    background: var(--accent-soft);
    color: var(--accent);
}

.dr-row.dir,
.ft-row.dir {
    color: var(--text);
}

.dr-row .chev,
.ft-row .chev {
    flex: none;
    width: 12px;
    color: var(--faint);
}

.dr-row.seen .dr-name {
    color: var(--muted);
}

.dr-name,
.ft-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dr-pi {
    color: var(--spark);
    font-size: 11px;
}

.dr-tail {
    margin-left: auto;
    padding-left: 6px;
    color: var(--ok);
}

.dr-tail .dv-counts {
    font-size: 11px;
}

.dr-files {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.dr-file {
    scroll-margin-top: 0.3rem;
}

/* Going to a change (n, p) leaves room for the file's header, which sticks at the top. */
.dr .dv-row,
.dr .dv-hunk {
    scroll-margin-top: 2.6rem;
}

.dr-clean {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    padding: 2.5rem 1rem;
    color: var(--ok);
    font-size: 0.85rem;
}

.dr-clean p {
    margin: 0;
    color: var(--muted);
}

.dr-pionly {
    padding: 0 12px 14px;
}

.dr-pionly .list-item {
    font-size: 0.8rem;
}

/* ─── Files tile ───────────────────────────────────────────── */

/* Phones and narrow windows: over the conversation, as the Browser panel is. Wide screens: a window beside it. */
.files-tile {
    position: fixed;
    inset: 0;
    z-index: 15;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    animation: popin var(--t-in) var(--ease-out);
}

.files-resize {
    display: none;
}

/* Over the conversation, below 1100px: no frame of its own. */
@media (max-width: 1099px) {
    :root[data-tiling="on"] .files-tile.window {
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }
}

@media (min-width: 1100px) {
    .layout.filing .files-tile {
        position: relative;
        inset: auto;
        z-index: auto;
        flex: 0 0 var(--files-w, 44%);
        max-width: calc(100% - 440px);
        height: 100dvh;
        border-left: 1px solid var(--hair);
        animation-delay: 90ms;
    }
    :root[data-tiling="on"] .layout.filing .files-tile {
        height: auto;
    }
    .files-resize {
        display: block;
        left: 0;
        right: auto;
    }
}

/* The bar: Files and Changes as a switch, the folder, and close. */
.files-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
    height: calc(58px + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 10px 0 14px;
    border-bottom: 1px solid var(--hair);
}

.files-bar .icon-button {
    width: 34px;
    height: 34px;
    color: var(--muted);
}

@media (hover: hover) {
    .files-bar .icon-button:hover {
        color: var(--text);
    }
}

.files-root {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--faint);
    font: 11.5px var(--mono);
}

/* The switch between Files and Changes, and the review's layout: a track with the chosen one raised. */
.files-tabs,
.dr-layout {
    display: flex;
    flex: none;
    padding: 3px;
    border-radius: var(--r-control);
    background: var(--card);
}

.files-tabs button,
.dr-layout button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    padding: 0 12px;
    border-radius: var(--r-seg);
    font-size: 13px;
    font-weight: 500;
    color: var(--muted);
    transition:
        background-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .files-tabs button:hover,
    .dr-layout button:hover {
        color: var(--text);
    }
}

.files-tabs button.on,
.dr-layout button.on {
    background: var(--raised);
    color: var(--text);
}

.dr-layout {
    padding: 2px;
    border-radius: var(--r-row);
}

.dr-layout button {
    height: 26px;
    padding: 0 10px;
    font-size: 12px;
}

.files-count {
    display: grid;
    place-items: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: var(--r-pill);
    background: var(--accent-soft);
    color: var(--accent);
    font: 600 10px/1 var(--mono);
}

.files-body {
    flex: 1;
    min-height: 0;
    overflow: auto;
    overscroll-behavior: contain;
}

/* As wide as the tile, never as wide as what is inside: a long line or a wide page scrolls within it instead. */
.files-bar,
.files-body {
    width: 100%;
}

.files-body[hidden] {
    display: none;
}

/* Files: the tree, and the open file beside it when the tile is wide enough, or instead of it when not. */
.ft {
    display: flex;
    height: 100%;
    min-height: 0;
}

.ft-pane {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
}

.ft.side .ft-pane {
    flex: 0 0 220px;
    border-right: 1px solid var(--hair);
}

.ft-tools {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 10px 8px 6px 10px;
}

.ft-tools .icon-button {
    width: 28px;
    height: 28px;
    border-radius: calc(var(--r-row) - 1px);
    color: var(--muted);
}

@media (hover: hover) {
    .ft-tools .icon-button:hover {
        color: var(--text);
    }
}

.ft-tree {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: 2px 6px 10px;
}

.ft-spacer {
    width: 12px;
    flex: none;
}

.ft-row.dot .ft-name {
    color: var(--muted);
}

.ft-row.changed.deleted .ft-name {
    color: var(--err);
    text-decoration: line-through;
}

/* M, A, D: what changed in a file, at the row's end; a folder with changes inside has a dot. */
.ft-kind {
    margin-left: auto;
    padding-left: 6px;
    font: 600 10px var(--mono);
}

.ft-kind.modified,
.ft-kind.renamed {
    color: var(--warn);
}

.ft-kind.new,
.ft-kind.added {
    color: var(--ok);
}

.ft-kind.deleted {
    color: var(--err);
}

.ft-dot {
    width: 6px;
    height: 6px;
    margin-left: auto;
    border-radius: 50%;
    background: var(--warn);
    flex: none;
}

/* Matches for what was typed in Go to file: an icon, the name, then its folder. */
.ft-row.match {
    padding-left: 8px;
}

.ft-row.match .icon {
    flex: none;
    color: var(--muted);
}

.ft-row mark {
    background: none;
    color: var(--accent);
    font-weight: 800;
}

.ft-parent {
    min-width: 0;
    margin-left: auto;
    padding-left: 0.6rem;
    color: var(--faint);
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;
}

.ft-note {
    padding: 0.5rem 0.8rem;
}

.ft-view {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    overflow: auto;
}

.ft-view-head {
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
    min-height: 42px;
    padding: 0 10px 0 14px;
    background: var(--bg);
    border-bottom: 1px solid var(--hair);
}

.ft-view-head .icon-button {
    width: 28px;
    height: 28px;
    border-radius: calc(var(--r-row) - 1px);
    color: var(--muted);
}

.ft-view-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font: 600 12.5px var(--mono);
    color: var(--text);
}

/* In the tile, the file's code fills the view on the code's ground; the bar above it is the viewer's own buttons. */
.ft-view .file-viewer {
    flex: 1;
    gap: 0;
}

.ft-view .file-viewer > :not(.file-tools, .file-view) {
    margin: 10px 14px;
}

.ft-view .file-tools {
    padding: 6px 10px 6px 14px;
}

.ft-view .file-view {
    flex: 1;
    border: 0;
    border-radius: 0;
}

.ft-empty {
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    color: var(--faint);
}

/* The file viewer, in the tile and the sheet: a bar of what the file is and what can be done with it, then the file. */
.file-viewer {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

.file-tools {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.file-tools .file-path {
    flex: 1;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.file-tools .icon-button {
    width: 32px;
    height: 32px;
}

/* ─── Browser ──────────────────────────────────────────────── */

/* Phones and narrow windows: the page full screen, over the conversation and under sheets. Wide screens: a window
 * beside the conversation, tiled like the others. */
.browser {
    position: fixed;
    inset: 0;
    z-index: 15;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    animation: popin var(--t-in) var(--ease-out);
}

.browser-resize {
    display: none;
}

/* Over the conversation, below 1100px: no frame of its own. */
@media (max-width: 1099px) {
    :root[data-tiling="on"] .browser.window {
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }
}

@media (min-width: 1100px) {
    .layout.browsing .browser {
        position: relative;
        inset: auto;
        z-index: auto;
        flex: 0 0 var(--browser-w, clamp(420px, 36vw, 520px));
        max-width: calc(100% - 440px);
        height: 100dvh;
        border-left: 1px solid var(--line);
        animation-delay: 90ms;
    }
    :root[data-tiling="on"] .layout.browsing .browser {
        height: auto;
    }
    .browser-resize {
        display: block;
        left: 0;
        right: auto;
    }
}

.browser-bar {
    display: flex;
    align-items: center;
    gap: 4px;
    min-height: 58px;
    flex: none;
    padding: env(safe-area-inset-top) 8px 0 10px;
    border-bottom: 1px solid var(--hair);
    background: var(--bg);
}

.browser-bar .icon-button {
    width: 30px;
    height: 30px;
    flex: none;
    border-radius: calc(var(--r-row) - 1px);
    color: var(--muted);
}

.browser-bar .badge {
    border-radius: var(--r-pill);
    font: 600 9.5px var(--mono);
}

.browser-bar .badge.err {
    background: var(--warn-soft);
    color: var(--warn);
}

.browser-bar .icon-button:disabled {
    opacity: 0.35;
    cursor: default;
    background: none;
    transform: none;
}

.browser-bar .icon-button.on {
    color: var(--accent);
    background: var(--accent-soft);
}

.browser-address {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
    height: 34px;
    margin: 0 4px;
    padding: 0 12px;
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    background: var(--card);
}

.browser-address:focus-within {
    border-color: var(--accent-line);
}

.browser-live {
    width: 7px;
    height: 7px;
    flex: none;
    border-radius: 50%;
    background: var(--ok);
}

.browser-address input {
    height: 32px;
    min-width: 0;
    border: 0;
    border-radius: 0;
    outline: 0;
    padding: 0;
    background: transparent;
    font: 12.5px var(--mono);
    text-overflow: ellipsis;
}

.browser-address input[readonly] {
    color: var(--muted);
}

@media (pointer: coarse) {
    .browser-address {
        height: 40px;
    }

    .browser-address input {
        font-size: 16px;
    }
}

@media (max-width: 480px) {
    .browser-forward {
        display: none !important;
    }
}

.badge-host .badge.err {
    background: var(--err);
    color: var(--accent-ink);
}

/* The topbar's mark while the session has a page open. */
.browser-dot {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 6px;
    height: 6px;
    border-radius: var(--radius);
    background: var(--accent);
    animation: popin var(--t-in) var(--ease-out);
}

/* Loading: a short bar sweeping under the address bar. */
.browser-progress {
    position: relative;
    height: 2px;
    flex: none;
    overflow: hidden;
}

.browser-progress.on::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 35%;
    background: var(--accent);
    animation: browser-load 1.1s var(--ease-in-out) infinite;
}

@keyframes browser-load {
    from {
        transform: translateX(-100%);
    }
    to {
        transform: translateX(300%);
    }
}

.browser-stage {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    background: var(--code-bg);
    overflow: hidden;
}

.browser-frame {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: flex-start;
}

/* The frame keeps its shape: it is as large as fits, so a tap's place on it is its place on the page. */
.browser-screen {
    display: block;
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    background: #fff;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    touch-action: none;
    outline: none;
}

.browser-screen.live:focus {
    outline: 1px solid var(--accent);
    outline-offset: -1px;
}

/* A page that crashed keeps its last frame, with the news over it. */
.browser-crashed {
    position: absolute;
    top: 0.6rem;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 0.6rem;
    max-width: calc(100% - 1.2rem);
    padding: 0.45rem 0.6rem 0.45rem 0.8rem;
    background: var(--panel);
    border: 1px solid var(--err-line);
    color: var(--err);
    animation: popin var(--t-in) var(--ease-out);
}

.browser-note {
    margin: auto;
    max-width: 30rem;
    padding: 2rem 1.5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.7rem;
    text-align: center;
    color: var(--muted);
}

.browser-note p {
    margin: 0;
}

.browser-start {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: 14px;
    padding: 24px;
    overflow-y: auto;
    text-align: left;
    color: var(--muted);
    background: var(--code-bg);
    animation: fade var(--t-fade) var(--ease-almost);
}

.browser-start > * {
    width: 100%;
    max-width: 372px;
    margin-left: auto;
    margin-right: auto;
    flex-shrink: 0;
}

.browser-start h2 {
    color: var(--text);
    font-size: 15px;
    font-weight: 600;
    margin-top: 0;
    margin-bottom: -10px;
}

.browser-note .browser-start {
    position: static;
    background: none;
    padding: 0;
}

.browser-start p {
    margin-top: 0;
    margin-bottom: 0;
    font-size: 13px;
    text-wrap: pretty;
}

.browser-servers {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.browser-servers-label {
    font-size: 12px;
    font-weight: 500;
    color: var(--faint);
}

.browser-server-list {
    display: flex;
    flex-direction: column;
    gap: 1px;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    overflow: hidden;
    background: var(--hair);
}

.browser-server {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 14px;
    background: var(--bg);
    color: var(--text);
    text-align: left;
}

@media (hover: hover) {
    .browser-server:hover {
        background: var(--card);
    }
}

.browser-server .mono {
    font-size: 13px;
    flex: none;
}

.browser-server-title {
    min-width: 0;
    margin-left: auto;
    font-size: 12px;
    color: var(--faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Typing on touch screens: a field of the app's own, whose keyboard sends text to the page. */
.browser-type {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.4rem 0.4rem calc(env(safe-area-inset-bottom) + 0.4rem);
    border-top: 1px solid var(--line);
    background: var(--panel);
}

/* Hidden, it stays focusable (not display: none), so the tap that shows it can open the phone's keyboard. */
.browser-type.hidden {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    opacity: 0;
    pointer-events: none;
    transform: translateY(100%);
}

.browser-type input {
    flex: 1;
    min-width: 0;
    padding: 0.4rem 0.6rem;
}

.browser-type .key {
    min-width: 34px;
    height: 34px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--card);
    color: var(--text);
}

.browser-type .key:active {
    background: var(--pressed);
}

.browser-console {
    flex: none;
    height: min(42%, 150px);
    display: flex;
    flex-direction: column;
    border-top: 1px solid var(--line);
    background: var(--panel);
    animation: fade var(--t-fade) var(--ease-almost);
}

.browser-console header {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
    padding: 0 8px 0 12px;
    font-size: 12px;
    border-bottom: 1px solid var(--hair);
}

.browser-console header strong {
    font-weight: 500;
}

.browser-console .spacer {
    flex: 1;
}

.browser-console-lines {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: 6px 0;
    font-size: 11.5px;
    line-height: 1.7;
}

.console-line {
    display: flex;
    gap: 0.6rem;
    padding: 0 12px;
    white-space: pre-wrap;
    word-break: break-word;
}

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

.console-source {
    flex: none;
    max-width: 40%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--faint);
}

.console-line.error {
    color: var(--err);
    background: var(--err-soft);
}

.console-line.warn {
    color: var(--warn);
    background: var(--warn-soft);
}

.console-line.dialog {
    color: var(--accent);
}

.console-line.debug {
    color: var(--faint);
}

.console-nav {
    margin-top: 4px;
    padding: 2px 12px;
    border-bottom: 1px solid var(--hair);
    color: var(--faint);
    font-size: 11px;
}

.browser-foot {
    padding: 0.3rem 0.8rem calc(env(safe-area-inset-bottom) + 0.3rem);
    border-top: 1px solid var(--line);
    text-align: center;
}

/* ─── Files, commands, and find ──────────────────────────────── */

/* File paths in replies (inline code that names a file) open the viewer. */
.md code[data-path] {
    cursor: pointer;
    text-decoration: underline dotted color-mix(in srgb, var(--accent) 60%, transparent);
    text-underline-offset: 3px;
}

@media (hover: hover) {
    .md code[data-path]:hover {
        color: var(--accent);
    }
}

/* @mentions of files in messages, and the files sent along. */
.file-mention {
    color: var(--accent);
    font: inherit;
    padding: 0;
    text-decoration: underline dotted;
    text-underline-offset: 3px;
}

.skill-chip {
    margin-bottom: 0.3rem;
}

.tool-open {
    align-self: flex-start;
}

/* `!` commands people ran, and notes about what people did. */
.shell-row {
    animation: rise-in 0.3s var(--ease-out);
}

.shell-card {
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    padding: 10px 14px;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.shell-card > .link {
    align-self: flex-start;
}

.shell-card.failed {
    border-color: var(--err-line);
}

.shell-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.6rem;
    font-size: 13px;
}

.shell-command {
    color: var(--ok);
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

.shell-card:not(.open) .shell-command {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.note-line {
    text-align: center;
    font-size: 12.5px;
    color: var(--muted);
}

.link.danger {
    color: var(--err);
    font-weight: 700;
}

/* The file viewer: line numbers, the line asked for marked, long lines wrapped. */
.file-path {
    overflow-wrap: anywhere;
    margin-top: 0;
}

.file-view {
    font: 12px/1.7 var(--mono);
    background: var(--code-bg);
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    padding: 10px 0;
    overflow-x: auto;
}

.file-line {
    display: flex;
    min-width: 0;
}

.file-line .ln {
    flex: none;
    width: 42px;
    padding-right: 14px;
    text-align: right;
    color: var(--faint);
    user-select: none;
}

.file-line .lt {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    min-width: 0;
    color: var(--body);
    padding-right: 12px;
}

.file-line.on {
    background: var(--accent-soft);
}

.file-line.on .ln {
    color: var(--accent);
}

.file-image {
    max-width: 100%;
    border: 1px solid var(--hair);
    border-radius: var(--radius);
}

.file-entry {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

/* Find in session. */
.find-input {
    width: 100%;
    min-height: 42px;
    border-radius: calc(var(--r-control) + 1px);
}

.find-search .find-input {
    min-height: 40px;
}

.find-count {
    color: var(--faint);
    font-size: 11.5px;
}

.find-results {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.find-result {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    text-align: left;
    padding: 9px 12px;
    border-radius: var(--r-control);
    border: 0;
    transition: background-color var(--t-hover) var(--ease-out);
}

.find-result.on {
    background: var(--hover);
}

@media (hover: hover) {
    .find-result:hover {
        background: var(--hover);
    }
}

.find-who {
    font-size: 12px;
    color: var(--faint);
}

.find-snippet {
    font-size: 13.5px;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.find-snippet mark {
    padding: 0 2px;
    border-radius: var(--r-mark);
    background: var(--accent-soft);
    color: var(--accent);
}

/* Ctrl+R: messages sent before. */
.history-text {
    color: var(--text);
}

/* ─── Syntax and rich markdown ─────────────────────────────── */

/* Syntax colors: the --hl- colors, darker in light themes. */
.hl-kw {
    color: var(--hl-kw);
}

.hl-str {
    color: var(--hl-str);
}

.hl-com {
    color: var(--faint);
    font-style: italic;
}

.hl-num,
.hl-lit {
    color: var(--hl-num);
}

.hl-fn {
    color: var(--hl-fn);
}

.hl-type,
.hl-attr {
    color: var(--hl-type);
}

.hl-op,
.hl-prop,
.hl-meta {
    color: var(--hl-op);
}

.hl-tag,
.hl-re,
.hl-var {
    color: var(--hl-tag);
}

/* A run of HTML between the blocks the app draws itself: its children lay out as the reply's own. */
.md-part {
    display: contents;
}

.md > .md-part:first-child > :first-child {
    margin-top: 0;
}

.md > .md-part:last-child > :last-child {
    margin-bottom: 0;
}

.md.streaming > .md-part:last-child > :last-child::after {
    content: "█";
    margin-left: 1px;
    color: var(--accent);
    animation: blink 1s steps(2) infinite;
}

/* A code block that shows more than code: its bar also has what it can show, and Run. */
.rich-tabs {
    display: inline-flex;
    margin-left: 0.4rem;
    padding: 2px;
    border-radius: var(--r-row);
    background: var(--hover);
}

.rich-tabs button,
.rich-run {
    height: 22px;
    padding: 0 8px;
    border-radius: var(--r-seg);
    font: inherit;
    color: var(--muted);
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .rich-tabs button:hover,
    .rich-run:hover {
        color: var(--text);
    }
}

.rich-tabs button.on {
    color: var(--text);
    background: var(--raised);
}

.rich-run {
    background: var(--ok-soft);
    color: var(--ok);
}

@media (hover: hover) {
    .rich-run:hover {
        color: var(--ok);
    }
}

.rich-run.on {
    background: var(--err-soft);
    color: var(--err);
}

/* A page and an image, drawn as a browser would: on white, whatever the theme. */
.html-preview,
.run-frame {
    display: block;
    width: 100%;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: #fff;
}

/* Inside a code block's frame, its own border is the frame's. */
.code > :is(.html-preview, .run-frame, .rich-svg, .rich-note) {
    border: 0;
    border-radius: 0;
}

.rich-svg {
    display: block;
    max-width: 100%;
    max-height: 70vh;
    padding: 0.6rem;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: #fff;
    cursor: zoom-in;
}

.code.rich > .dv-block {
    max-height: none;
}

.rich-note {
    margin: 0;
    padding: 0.6rem;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
}

/* A long code block, folded to its first lines until asked for the rest. */
.code.long:not(.open) pre {
    max-height: 22em;
    overflow: hidden;
    mask-image: linear-gradient(#000 75%, transparent);
}

.code-more {
    display: block;
    width: 100%;
    padding: 6px;
    border-top: 1px solid var(--hair);
    background: var(--card);
    color: var(--accent);
    font: 12px var(--mono);
}

@media (hover: hover) {
    .code-more:hover {
        background: var(--hover);
    }
}

.file-tools .button.on {
    color: var(--err);
}

/* ─── Phones: places, pushed screens, and going back ───────── */

/* Keep the anchored menu out of the layout's flex row, including its gap. */
.nav-menu-host {
    display: contents;
}

/* The menu and the phone's places share a three-column grid of soft tiles. */
.places {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 6px;
    padding: 8px 12px 12px;
}

.nav-menu .sheet-body,
.places-sheet .sheet-body {
    padding: 0;
    gap: 0;
}

.nav-menu :is(.menu-session, .group) {
    margin: 0;
    padding: 6px 6px 8px;
    border-top: 1px solid var(--hair);
}

.nav-menu .menu-session:empty {
    display: none;
}

.nav-menu .group-title {
    margin: 0;
    padding: 8px 10px 4px;
    color: var(--faint);
    font-size: 12px;
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
}

.nav-menu .list-item,
.places-sheet .list-item {
    display: flex;
    align-items: baseline;
    gap: 10px;
    min-height: 36px;
    margin: 0;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--r-row);
    background: none;
    color: var(--text);
    font-size: 13.5px;
}

@media (hover: hover) {
    .nav-menu .list-item:hover,
    .places-sheet .list-item:hover {
        background: var(--hover);
    }
}

@media (hover: hover) {
    .nav-menu .list-item:hover > span:first-child,
    .places-sheet .list-item:hover > span:first-child {
        color: var(--text);
    }
}

.nav-menu .list-item > :first-child,
.places-sheet .list-item > :first-child {
    flex: none;
    white-space: nowrap;
}

.nav-menu .list-item > :last-child:not(:first-child),
.places-sheet .list-item > :last-child:not(:first-child) {
    flex: 1;
    min-width: 0;
    text-align: right;
    font-size: 12px;
    color: var(--faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.places-sheet .list-item {
    width: auto;
    margin: 0 6px 8px;
}

.nav-menu .menu-signout {
    color: var(--err);
}

@media (min-width: 700px) {
    /* Sheet still owns focus and Esc; its existing sheet trail owns Back, even from a child sheet. */
    .nav-menu-host .overlay {
        padding: 0;
        background: none;
    }
    .nav-menu {
        position: fixed;
        left: var(--menu-left, calc(100vw - 368px));
        top: var(--menu-top, 64px);
        width: 360px;
        max-height: var(--menu-height, calc(100dvh - 72px));
        border-radius: calc(var(--r-window) + 2px);
        box-shadow: var(--pop);
        animation: pop 0.25s var(--ease-out);
    }
    .nav-menu .sheet-head {
        height: auto;
        min-height: 0;
        padding: 10px 12px 2px 16px;
        border: 0;
    }
    .nav-menu .grip,
    .nav-menu .sheet-head h2::before {
        display: none;
    }
    .nav-menu .sheet-head h2 {
        margin: 0;
        font-size: 13px;
        font-weight: 600;
    }
    .nav-menu .sheet-head .icon-button {
        width: 28px;
        height: 28px;
    }
}

@media (pointer: coarse) {
    .nav-menu .list-item,
    .places-sheet .list-item {
        min-height: 44px;
    }
}

.place {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
    gap: 5px;
    height: 66px;
    padding: 8px 4px;
    border-radius: var(--r-card);
    background: var(--card);
    border: 1px solid var(--hair);
    color: var(--body);
    transition:
        background-color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out),
        transform 90ms var(--ease-out);
}

@media (hover: hover) {
    .place:hover {
        border-color: var(--hair-2);
        background: var(--card-2);
        color: var(--text);
    }
}

.place:active {
    background: var(--pressed);
    transform: scale(0.96);
}

.place.on {
    color: var(--accent);
    background: var(--accent-soft);
    border-color: var(--accent-line);
}

.place-icon {
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    position: static;
}

.place-icon .badge {
    top: 7px;
    right: 8px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: var(--r-pill);
    background: var(--accent-fill);
    color: var(--accent-ink);
    font: 600 9.5px/1 var(--mono);
    box-shadow: none;
}

.place-icon .browser-dot {
    top: 10px;
    right: 10px;
}

.place-label {
    max-width: 100%;
    font-size: 12px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * Phones: a session opened slides in from the right, and going back brings the list (or the session before) in from
 * the left, so where back goes is where things came from. `data-route` is set while it slides (back.js).
 */
@media (max-width: 959px) {
    /* Held inside the window: a scroller sliding in from the right (a route, a swipe's lean) would make the page wider
     * than the screen, and a phone's browser widen and pan its view to fit. */
    .pane {
        overflow-x: clip;
    }
    :root[data-route="forward"] .pane > .scroller {
        animation: route-forward 0.32s var(--ease-out);
    }
    :root[data-route="back"] .pane > .scroller,
    :root[data-route="back"] .home-list {
        animation: route-back 0.32s var(--ease-out);
    }
}

@keyframes route-forward {
    from {
        opacity: 0;
        transform: translateX(24%);
    }
}

@keyframes route-back {
    from {
        opacity: 0;
        transform: translateX(-24%);
    }
}

/* Back the browser already showed with its own slide: what it closes goes at once (back.js). */
:root[data-back-shown] .leaving {
    display: none !important;
}

/* Phones: the places, beside the message box where a thumb reaches (composer.js). Elsewhere the menu has them. */
.composer-row .places-button {
    display: none;
}

@media (max-width: 699px) {
    .composer-row .places-button {
        display: inline-grid;
        width: 32px;
        height: 36px;
        color: var(--muted);
    }
    .composer-row .places-button .browser-dot {
        top: 6px;
        right: 5px;
        width: 7px;
        height: 7px;
        box-shadow: 0 0 0 2px var(--card);
    }
    /* Room for it: the model's name gives way first. */
    .composer-row .model-chip {
        flex: 0 1 auto;
        padding-inline: 6px;
    }
    /* While Pi works, Steer and Queue take the plan chip's place (`/plan` still turns plan mode on or off). */
    .composer.busy .plan-chip,
    .composer.busy .model-caret {
        display: none;
    }
    .mode-switch button {
        padding-inline: 8px;
    }
    /* While Pi works the row is full, and Stop holds the end of it: Send shows once there is something to send, in the
       mic's place (the mic stays while it listens, to stop it). */
    .composer.busy:not(.filled):has(.composer-mic) .send-button,
    .composer.busy.filled .composer-mic:not(.listening) {
        display: none;
    }
}

/* A swipe's mark: back, or the place a swipe on the conversation opens, following the finger in from its side. */
.swipe-mark {
    position: fixed;
    top: 0;
    z-index: 60;
    height: 44px;
    min-width: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0 0.8rem;
    background: var(--panel);
    border: 1px solid var(--line-strong);
    color: var(--muted);
    font-size: 0.82rem;
    box-shadow: 0 6px 20px rgb(0 0 0 / 0.35);
    pointer-events: none;
    opacity: 0;
    transition:
        color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

.swipe-mark[data-side="left"] {
    left: 0;
}

.swipe-mark[data-side="right"] {
    right: 0;
}

.swipe-mark.armed {
    background: var(--accent-fill);
    color: var(--accent-ink);
}

.swipe-mark.going {
    transition:
        transform 0.2s var(--ease-out),
        opacity 0.2s var(--ease-out);
}

/* The Files tile's way back to the conversation, where the tile covers it. */
.files-bar .files-back {
    width: 44px;
    height: 44px;
    margin-left: -8px;
    color: var(--text);
}

/* Focus lands on the whole tile or panel where it covers the conversation: no ring around the screen. */
.layout > :is(.files-tile, .browser):focus-visible {
    outline: none;
}

/*
 * Where they cover the conversation, the Files tile and the Browser panel are screens pushed over it: they slide in
 * from the right, as a phone's screens do. So does a file opened in the tile over its tree.
 */
@media (max-width: 1099px) {
    /* Past the tiled windows' pop-in, which would otherwise win. */
    :root .layout > .files-tile.window,
    :root .layout > .browser.window {
        animation: push-in 0.36s var(--ease-out);
    }
    :root .layout > .files-tile.window.leaving,
    :root .layout > .browser.window.leaving {
        animation: push-out 0.24s var(--ease-in-out) forwards;
    }
}

@keyframes push-in {
    from {
        transform: translateX(100%);
    }
}

@keyframes push-out {
    to {
        transform: translateX(100%);
    }
}

/*
 * A file open where the tile is too narrow for it beside the tree is a screen of its own, over the whole tile (the
 * tile is the nearest positioned box): its header, with the way back to the tree, is the only one. The tree stays
 * underneath as it was, scrolled where it was.
 */
.ft:not(.side) > .ft-view {
    position: absolute;
    inset: 0;
    z-index: 4;
    background: var(--bg);
    animation: push-in 0.32s var(--ease-out);
}

.ft:not(.side) > .ft-view.leaving {
    animation: push-out 0.24s var(--ease-in-out) forwards;
}

/* Under a file that covers the whole tile, the tile's bar is out of reach of taps, keys, and screen readers too. */
@media (max-width: 1099px) {
    .files-tile:has(> .files-body:not([hidden]) > .ft:not(.side) > .ft-view:not(.leaving))
        > .files-bar {
        visibility: hidden;
    }
}

.ft:not(.side) > .ft-view > .ft-view-head {
    padding-top: env(safe-area-inset-top);
}

/* Docked beside the conversation, the tile keeps its tabs and its close button above the file. */
@media (min-width: 1100px) {
    .layout.filing .ft {
        position: relative;
    }
    .layout.filing .ft:not(.side) > .ft-view > .ft-view-head {
        padding-top: 0;
    }
}

/* Touch: rows and controls a thumb tall. */
@media (pointer: coarse) {
    .files-tabs button {
        height: 40px;
        padding: 0 14px;
        font-size: 14px;
    }
    .ft-tools .icon-button,
    .ft-view-head .icon-button,
    .ft-entry > .ft-copy,
    .files-bar .copy-path {
        width: 44px;
        height: 44px;
    }
    .ft-view-head {
        min-height: 48px;
        padding-left: 6px;
    }
    .ft-view-name {
        font-size: 14px;
    }
    .ft-filter {
        min-height: 42px;
    }
    .ft-row {
        min-height: 44px;
        gap: 8px;
        padding-left: calc(10px + var(--depth, 0) * 16px);
        font-size: 14px;
    }
    .ft-row .icon {
        width: 16px;
        height: 16px;
    }
    .ft-row .chev {
        width: 14px;
        height: 14px;
    }
    .ft-spacer {
        width: 14px;
    }
    .dr-row {
        min-height: 40px;
    }
    .browser-bar .icon-button {
        width: 40px;
        height: 40px;
    }
    .browser-address input {
        height: 40px;
    }
}

/*
 * Phones: the Browser panel's bar as an in-app browser's. Close and the address on the first row, the page's tools
 * spread a thumb apart on the second.
 */
@media (max-width: 700px) {
    .browser-bar {
        flex-wrap: wrap;
        justify-content: space-between;
        row-gap: 0.2rem;
        padding-bottom: 0.2rem;
    }
    .browser-bar > .browser-close {
        order: -2;
    }
    .browser-bar > .browser-address {
        order: -1;
        flex: 1 1 calc(100% - 52px);
        margin-right: 0;
    }
}

/*
 * Touch: every control a thumb can hit, at least about 40px each way. Buttons, tabs, and chips grow where there is
 * room. Inline controls (a code block's Copy, a reply's actions, the status line's branch) keep their look and get a
 * taller hit area instead: padding with a matching negative margin, so nothing around them moves.
 */
@media (pointer: coarse) {
    .button {
        min-height: 44px;
    }
    .button.small {
        min-height: 38px;
        padding-inline: 0.8rem;
    }
    .segmented button {
        min-height: 42px;
        min-width: 40px;
    }
    /* iOS zooms into a text field under 16px as it takes focus. (The board's field is styled after this: hence
     * the board in its selector.) */
    .sessions .search input,
    .board .board-search input,
    .fp-line input,
    .launcher-input input {
        font-size: 16px;
    }
    /* Rows a thumb can take, and that answer the press: 40px, 37px, and 34px. */
    .session {
        height: calc(30px + 10px * var(--space-y));
    }
    .session:active {
        background: var(--pressed);
    }
    /* The session list keeps its look; its tabs, folds, and clear button take a taller tap. */
    .session-tabs button::after,
    .search-clear::before {
        content: "";
        position: absolute;
        inset: -10px -8px -4px;
    }
    /* 40px square, as 0.11 made the search's buttons. */
    .search-clear::before {
        inset: -9px;
    }
    /* New and the board's filters keep their look and take a thumb-tall tap. */
    .new-button,
    .board-filter,
    .agents-held .link {
        position: relative;
    }
    .new-button::before,
    .board-filter::before,
    .agents-held .link::before {
        content: "";
        position: absolute;
    }
    .agents-held .link::before {
        inset: -12px -8px;
    }
    .new-button::before {
        inset: -6px -3px;
    }
    /* Rows of filters far enough apart that their taps do not overlap (after the board's own gap, hence .board). */
    .board .board-legend {
        row-gap: 16px;
    }
    .board-filter::before {
        inset: -8px -4px;
    }
    .group-head {
        position: relative;
    }
    .group-head::after {
        content: "";
        position: absolute;
        inset: -4px 0 -2px;
    }
    .search .icon-button.small {
        width: 40px;
        height: 40px;
    }
    /* Thumb-sized already: a hit area past it would take taps meant for the end of the search. */
    .search .icon-button.small::before {
        content: none;
    }
    .composer-row .attach-button {
        width: 32px;
        height: 36px;
    }
    .composer-row .composer-mic {
        width: 32px;
        height: 36px;
    }
    .composer-row .stop-button,
    .composer-row .send-button {
        width: 36px;
        height: 36px;
    }
    /* Kept small to fit one line on a phone; a layer past each takes a tap about 40px wide and tall. */
    .composer-row
        :is(
            .places-button,
            .attach-button,
            .model-chip,
            .plan-chip,
            .composer-mic,
            .stop-button,
            .send-button
        ) {
        position: relative;
    }
    .composer-row
        :is(
            .places-button,
            .attach-button,
            .model-chip,
            .plan-chip,
            .composer-mic,
            .stop-button,
            .send-button
        )::before {
        content: "";
        position: absolute;
        inset: -4px -2px;
    }
    /* The chips are shorter: their layers reach further up and down. */
    .composer-row :is(.model-chip, .plan-chip)::before {
        inset: -5px -2px;
    }
    /* Where the row has room, the icon buttons are as wide as a thumb's tap (their look is the icon alone). */
    @container composer (min-width: 360px) {
        .composer-row :is(.places-button, .attach-button, .composer-mic) {
            width: 36px;
        }
    }
    /* Steer and Queue too, taller only: side by side, their layers must not take each other's taps. */
    .mode-switch button {
        position: relative;
    }
    .mode-switch button::before {
        content: "";
        position: absolute;
        inset: -6px 0;
    }
    /* A call's line, a little taller for a thumb; a group's line keeps a thumb's height at every density. */
    .step-head {
        min-height: 36px;
    }
    .activity-head {
        min-height: max(34px, calc(22px + 18px * var(--space-y)));
    }
    .browser-servers .chip,
    .dr-tools .chip {
        min-height: 38px;
    }
    .dr-filter {
        min-height: 40px;
    }
    .dv-tool.icon-button,
    .file-tools .icon-button {
        width: 40px;
        height: 40px;
    }
    .dv-fold {
        width: 36px;
        height: 36px;
        margin-left: -0.3rem;
    }
    .dv-title {
        align-self: stretch;
        align-items: center;
    }
    .dv-viewed {
        min-height: 36px;
        /* Its label hides on a phone: the checkbox alone, centered in a thumb's width. */
        min-width: 42px;
        justify-content: center;
        padding-inline: 10px;
    }
    .check {
        min-height: 40px;
    }
    /* Boxed ones (Copy, tabs, Run, a reaction, the top bar's changes) keep their box; an invisible layer past it
     * takes the tap. */
    .code-head .copy,
    .rich-tabs button,
    .rich-run,
    .answer-actions .reaction,
    .changes-button {
        position: relative;
        /* Above what follows (a preview's frame), so the layer past the box takes the tap there too. */
        z-index: 1;
    }
    /* Taller only: its neighbours touch it, and must keep their own edges. */
    .changes-button::after {
        content: "";
        position: absolute;
        inset: -8px 0;
    }
    /* Over them, as they scroll by: the way to the bottom keeps its taps. */
    .jump {
        z-index: 2;
    }
    .code-head .copy::after,
    .rich-tabs button::after,
    .rich-run::after,
    .answer-actions .reaction::after {
        content: "";
        position: absolute;
        inset: -12px -2px;
    }
    /* The status line's guard sits low: room below it, so its hit area stays on the screen, and above the message
     * box's bottom edge, which its hit area reaches into. */
    .status-line {
        position: relative;
        z-index: 1;
        padding-bottom: 0.6rem;
    }
    .answer-actions > button.answer-tool {
        height: auto;
    }
    .answer-actions > button:not(.reaction),
    .link.small,
    .running-head .link {
        padding-block: 11px;
        margin-block: -11px;
    }
    /* A task's Stop or Cancel, at the end of its row: wider too. */
    .running-task .link.small {
        padding-inline: 7px;
        margin-inline: -7px;
    }
    .answer-actions > button:not(.reaction) {
        min-width: 40px;
        justify-content: center;
        padding-inline: 6px;
        margin-inline: -6px;
    }
    /* The guard and the review's branch keep their small pills; an invisible layer past each takes a thumb's tap. */
    .status-line .guard,
    .dr-branch {
        position: relative;
    }
    .status-line .guard::after,
    .dr-branch::after {
        content: "";
        position: absolute;
        inset: -9px -6px;
    }
    .answer-actions .reaction.add {
        min-width: 40px;
        justify-content: center;
    }
    .answer-actions {
        gap: 0.6rem 1rem;
    }
    /* A switch and a small icon button (a chip's ×, Stop quoting) keep their size; their hit area reaches past it. */
    .switch::before,
    .icon-button.small::before {
        content: "";
        position: absolute;
        inset: -10px -4px;
    }
    .icon-button.small::before {
        inset: -8px;
    }
    .command,
    .artifact-link {
        min-height: 42px;
    }
    /* A peek tile's header opens its session; Allow, Deny, and Open answer from the tile. */
    .peek-strip .peek-head {
        min-height: 40px;
    }
    .peek-actions .button.small {
        min-height: 38px;
    }
    .peek-seen {
        width: 38px;
        height: 38px;
    }
    .pop-menu-link {
        padding-block: 11px;
        margin-block: -11px;
    }
}

/*
 * Phones: a diff's header in two lines when it would squeeze the file's name. The first line is the fold, the kind,
 * the name, and Viewed; the counts and the file's tools take the second, which a break between the two keeps.
 */
@media (max-width: 480px) {
    .dv-head {
        flex-wrap: wrap;
        row-gap: 0;
        padding-block: 3px;
    }
    .dv-head::after {
        content: "";
        order: 1;
        flex: 0 0 100%;
    }
    .dv-head > :is(.dv-chip, .dv-counts, .dv-tool) {
        order: 2;
    }
    /* Under the name: the first of them starts where the kind's tile does. */
    .dv-head > :is(.dv-chip, .dv-counts) {
        margin-left: 2.9rem;
    }
    .dv-head > .dv-chip ~ :is(.dv-chip, .dv-counts) {
        margin-left: 0;
    }
    .dv-head > .dv-counts {
        margin-right: auto;
    }
    /* Compact, with the tap reaching to 40px past the button, but not up into Viewed above it. */
    .dv-head > .dv-tool.icon-button {
        width: 36px;
        height: 36px;
    }
    .dv-head > .dv-tool.icon-button::before {
        content: "";
        position: absolute;
        inset: 0 -4px -4px;
    }
    /* Going to a change (n, p) clears the header's two lines. */
    .dr .dv-row,
    .dr .dv-hunk {
        scroll-margin-top: 5.6rem;
    }
}

/*
 * Pi's sessions from the terminal. The list: a card per folder, a row per session (its title over how long and how
 * recent, a tag when it continues here). One of them: what it worked with, then its last messages as a conversation,
 * then Continue, kept in sight at the foot of the sheet.
 */
.pi-folder {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    animation: rise-in 0.34s var(--ease-out) backwards;
}

.pi-folder-head {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    min-width: 0;
    padding: 0 0.15rem;
    color: var(--muted);
    font-size: 0.78rem;
}

.pi-folder-head .icon {
    align-self: center;
}

.pi-folder-name {
    flex: none;
    max-width: 60%;
    color: var(--text);
    font-family: var(--mono);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pi-folder-parent {
    min-width: 0;
    font-family: var(--mono);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pi-folder-list {
    display: flex;
    flex-direction: column;
    background: var(--bg);
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    overflow: hidden;
}

.pi-session {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    min-height: 3.2rem;
    padding: 0.55rem 0.6rem 0.55rem 0.75rem;
    background: none;
    border: 0;
    border-top: 1px solid var(--hair);
    color: var(--text);
    font: inherit;
    font-size: 13.5px;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--t-hover) var(--ease-out);
}

.pi-session:first-child {
    border-top: 0;
}

@media (hover: hover) {
    .pi-session:hover {
        background: var(--card-2);
    }
}

@media (hover: hover) {
    .pi-session:hover .pi-session-title {
        color: var(--accent);
    }
}

.pi-session > .icon {
    color: var(--muted);
}

.pi-session-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

.pi-session-title,
.pi-session-meta {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pi-session-meta {
    color: var(--muted);
    font-size: 0.76rem;
}

.pi-tag {
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: var(--r-pill);
    padding: 0.05rem 0.5rem;
    font-size: 0.72rem;
    white-space: nowrap;
}

.pi-tag.behind {
    color: var(--warn);
    background: var(--warn-soft);
}

.pi-facts {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 0.3rem 0.9rem;
    margin: 0;
    padding: 0.6rem 0.75rem;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: 0.82rem;
}

.pi-facts > div {
    display: contents;
}

.pi-facts dt {
    color: var(--muted);
}

.pi-facts dd {
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* The session's whole title, however long: the sheet's own title is short. */
.pi-title {
    margin: 0;
    font-size: 1rem;
    color: var(--text);
    overflow-wrap: anywhere;
}

.pi-results {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
}

.pi-note {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.3rem 0.6rem;
    font-size: 0.85rem;
}

.pi-convo {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}

.pi-convo > .label {
    margin-bottom: 0;
}

.pi-ask {
    display: flex;
    justify-content: flex-end;
}

.pi-ask > div,
.pi-reply {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 6;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 0.88rem;
}

.pi-ask > div {
    max-width: 85%;
    background: var(--card-2);
    border: 1px solid var(--line);
    border-radius: calc(var(--r-window) + 2px) calc(var(--r-window) + 2px) var(--r-tag)
        calc(var(--r-window) + 2px);
    padding: 10px 14px;
}

.pi-reply {
    color: var(--body);
}

/* Continue stays in sight as the conversation scrolls under it. */
.pi-continue {
    position: sticky;
    bottom: -20px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0 -20px -20px;
    padding: 14px 20px 20px;
    background: var(--bg);
    border-top: 1px solid var(--hair);
}

.pi-continue > p {
    margin: 0;
}

/*
 * The subagents bar, above the message box. Folded: a dot per subagent (pulsing while it works), the counts, and what the
 * newest one does. Unfolded: a row each, which opens it.
 */
.agents-bar {
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    margin-bottom: 6px;
    font-size: 13px;
    overflow: hidden;
}

.agents-top {
    display: flex;
    align-items: center;
    padding-right: 0.2rem;
}

.agents-summary {
    flex: 1;
    min-width: 0;
    min-height: 36px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 12px;
    background: none;
    border: 0;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.agents-dots {
    display: inline-flex;
    gap: 3px;
    flex: none;
}

.agents-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--ok);
}

.agents-dot.working {
    background: var(--accent);
    animation: pulse 1.4s infinite;
}

.agents-dot.failed {
    background: var(--err);
}

.agents-dot.stopped {
    background: var(--muted);
}

.agents-more {
    margin-left: 2px;
    color: var(--muted);
    font-size: 0.7rem;
    line-height: 7px;
}

.agents-count {
    flex: 0 1 auto;
    min-width: 0;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.agents-lead {
    flex: 1;
    min-width: 0;
    color: var(--muted);
    font-family: var(--mono);
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.agents-chevron {
    display: inline-flex;
    flex: none;
    margin-left: auto;
    color: var(--muted);
    transform: rotate(-90deg);
    transition: transform var(--t-in) var(--ease-out);
}

.agents-bar.open .agents-chevron {
    transform: rotate(90deg);
}

/* Reports a spend limit holds back: why, and the way to raise it (subagents.js). */
.agents-held {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.6rem;
    padding: 0.35rem 0.75rem 0.45rem;
    border-top: 1px solid var(--hair);
    color: var(--warn);
    font-size: 12.5px;
    line-height: 1.4;
}

.agents-held .link {
    font-size: inherit;
}

.agents-bar:has(.agents-held) {
    border-color: var(--warn-line);
}

.agents-list {
    max-height: min(40vh, 22rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    border-top: 1px solid var(--hair);
}

.agent-row {
    display: flex;
    align-items: center;
    border-bottom: 1px solid var(--hair);
}

.agent-row:last-child {
    border-bottom: 0;
}

.agent-open {
    flex: 1;
    min-width: 0;
    min-height: 2.75rem;
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.5rem 0.6rem;
    background: none;
    border: 0;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .agent-open:hover {
        background: var(--hover);
    }
}

.agent-mark {
    flex: none;
    width: 1rem;
    padding-top: 0.05rem;
    color: var(--ok);
    font-weight: 700;
    text-align: center;
}

.agent-row.failed .agent-mark {
    color: var(--err);
}

.agent-row.stopped .agent-mark {
    color: var(--muted);
}

.agent-error {
    color: var(--err);
    font-size: 0.78rem;
    overflow-wrap: anywhere;
}

.agent-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.agent-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.2rem 0.5rem;
}

.agent-name {
    font-family: var(--mono);
    font-weight: 600;
}

.agent-when {
    color: var(--muted);
    font-size: 0.76rem;
    font-variant-numeric: tabular-nums;
}

.agent-chip {
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: var(--r-pill);
    padding: 0 0.45rem;
    font-size: 0.72rem;
    white-space: nowrap;
}

.agent-now,
.agent-asked {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.agent-now {
    font-family: var(--mono);
    font-size: 12px;
}

.agent-asked {
    color: var(--muted);
    font-size: 0.76rem;
}

.agent-stop {
    flex: none;
    margin-right: 0.2rem;
}

/* ─── Extensions' pages ──────────────────────────────────────── */

/*
 * A page an extension's browser module added, in the conversation's place as the subagents board is: the board's
 * header, and what the extension draws below it, scrolling.
 */
.ext-page {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    animation: fade var(--t-fade) var(--ease-almost);
}

.ext-page-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 1rem 1rem calc(env(safe-area-inset-bottom) + 1rem);
}

/*
 * Extensions' rail buttons, together: four buttons' height at most, past which they scroll rather than push the app's
 * own buttons away. Beside the session list it keeps that height, and a short window scrolls the whole rail, as it does
 * the app's own buttons; in the folded rail it gives way first (to one button), so the sessions' tiles keep their room.
 */
.rail-exts {
    flex: none;
    max-height: calc(4 * 44px + 3 * 4px);
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
}

.rail:has(.rail-items) .rail-exts {
    flex: 0 1 auto;
    min-height: 44px;
    max-height: max(44px, min(4 * 44px + 3 * 4px, 22vh));
}

/* Inside the button, where the group's edge does not cut it off. */
.rail-exts .rail-button:focus-visible {
    outline-offset: -1px;
}

/* An extension's badge may be text: it stays within its button, cut with an ellipsis. */
.rail-ext .rail-count {
    display: block;
    max-width: 32px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: center;
    line-height: 15px;
}

/* Safe mode, in the Extensions sheet: this tab loads no extension's browser part. */
.safe-mode {
    margin: 0 0 0.75rem;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--warn);
}

/* ─── Subagents board ─────────────────────────────────────────── */

/*
 * Every subagent in every session, in the conversation's place: a square each, a row per session, the bar of states
 * that filters by one, what needs you, and the one selected. Phones: one column, and a bar at the bottom.
 */
.board {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    animation: fade var(--t-fade) var(--ease-almost);
}

.board-head {
    flex: none;
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 62px;
    padding: env(safe-area-inset-top) 12px 0 22px;
    border-bottom: 1px solid var(--hair);
}

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

.board-title h2 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--text);
}

.board-sub {
    font-size: 12px;
    color: var(--muted);
}

.board-search {
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
    width: 240px;
    height: 34px;
    padding: 0 10px;
    border-radius: var(--r-control);
    background: var(--card);
    border: 1px solid var(--hair);
    color: var(--muted);
    transition: border-color var(--t-hover) var(--ease-out);
}

.board-search.filled,
.board-search:focus-within {
    border-color: var(--accent-line);
}

.board-search input {
    flex: 1;
    min-width: 0;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    font-size: 13px;
    color: var(--text);
}

.board-search-row {
    flex: none;
    padding: 10px 12px 0;
}

.board-search-row .board-search {
    width: 100%;
}

/* A state's color drives the mark, cell, and detail pill. */
.board-mark,
.board-cell,
.board-detail-state {
    --state: var(--muted);
}

:is(.board-mark, .board-cell, .board-detail-state).waiting {
    --state: var(--warn);
}
:is(.board-mark, .board-cell, .board-detail-state).failed {
    --state: var(--err);
}
:is(.board-mark, .board-cell, .board-detail-state).working {
    --state: var(--accent);
}
:is(.board-mark, .board-cell, .board-detail-state).done {
    --state: var(--ok);
}

.board-mark {
    flex: none;
    width: 10px;
    height: 10px;
    display: grid;
    place-items: center;
    border-radius: var(--r-mark);
    background: var(--state);
    color: var(--accent-ink);
    font: 600 8px/1 var(--mono);
}

/* How many are in each state, as one bar, and a legend that filters by one. */
.board-summary-bar {
    flex: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px 22px 0;
}

.board-states {
    display: flex;
    gap: 3px;
    height: 8px;
    border-radius: calc(var(--r-tag) - 1px);
    overflow: hidden;
}

.board-state {
    flex-basis: 0;
    transition: opacity var(--t-fade) var(--ease-almost);
}

.board-state.waiting {
    background: var(--warn);
}

.board-state.failed {
    background: var(--err);
}

.board-state.working {
    background: var(--accent);
}

.board-state.stopped {
    background: var(--line-strong);
}

.board-state.done {
    background: var(--ok);
}

.board-state.dim {
    opacity: 0.25;
}

.board-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.board-filter {
    position: relative;
    display: flex;
    align-items: center;
    gap: 7px;
    height: 30px;
    padding: 0 11px;
    border: 1px solid var(--hair);
    border-radius: var(--r-pill);
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text);
    transition: background-color var(--t-hover) var(--ease-out);
}

.board-filter.on {
    background: var(--card-2);
    border-color: var(--hair-2);
}

@media (hover: hover) {
    .board-filter:hover {
        background: var(--card-2);
        border-color: var(--hair-2);
    }
}

.board-filter .board-mark {
    width: 8px;
    height: 8px;
    border-radius: calc(var(--r-mark) - 0.5px);
}

.board-filter-count {
    font: 400 11px var(--mono);
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}

.board-body {
    flex: 1;
    min-height: 0;
    display: flex;
    gap: 16px;
    padding: 16px 22px 22px;
}

.board-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.board-map {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 4px;
    scroll-padding: 4px;
}

.board-empty {
    padding: 1.2rem 0;
    color: var(--muted);
    font-size: 0.85rem;
}

/* A session: its title and how its subagents are, then a square for each. */
.board-row {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 8px;
    padding: 12px 14px;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    transition: opacity var(--t-fade) var(--ease-almost);
}

.board-session {
    flex: 1;
    min-width: 100px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-align: left;
}

.board-session-title {
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 9px;
}

.board-session-name {
    min-width: 0;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .board-session:hover .board-session-name {
        color: var(--accent);
    }
}

.board-summary {
    max-width: 100%;
    padding-left: 17px;
    font-size: 12px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.board-summary.waiting {
    color: var(--warn);
}

.board-summary.failed {
    color: var(--err);
}

.board-summary.working {
    color: var(--accent);
}

.board-cells {
    flex: 0 1 auto;
    max-width: 60%;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    justify-content: flex-end;
    gap: 6px;
}

/* A session's finished subagents left off the board, counted: "+12". */
.board-older {
    align-self: center;
    margin-left: 3px;
    color: var(--muted);
    font: 11px var(--mono);
}

.board-cell {
    flex: none;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border: 1px solid color-mix(in srgb, var(--state) 40%, transparent);
    border-radius: calc(var(--r-row) - 1px);
    background: color-mix(in srgb, var(--state) 14%, transparent);
    outline-offset: 2px;
    transition: opacity var(--t-fade) var(--ease-almost);
}

@media (hover: hover) {
    .board-cell:hover {
        border-color: var(--state);
    }
}

.board-cell.on {
    outline: 2px solid var(--state);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--state) 14%, transparent);
}

.board-cell.dim {
    opacity: 0.25;
}

.board-cell-core {
    width: 8px;
    height: 8px;
    border-radius: calc(var(--r-mark) - 0.5px);
    background: var(--state);
    color: var(--accent-ink);
    font: 600 8px/1 var(--mono);
}

.board-cell.working .board-cell-core {
    animation: pulse 1.4s ease-in-out infinite;
}

/* What the square under the mouse does, or the selected one's. */
.board-status {
    flex: none;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 30px;
    padding: 0 4px;
    font-size: 11.5px;
    white-space: nowrap;
    overflow: hidden;
}

.board-status .board-mark {
    width: 8px;
    height: 8px;
}

.board-status-name {
    font: 600 11.5px var(--mono);
    color: var(--text);
}

.board-status-when {
    color: var(--muted);
}

.board-status-line {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--muted);
}

.board-status-line.working,
.board-status-line.stopped,
.board-status-line.done {
    color: var(--body);
}

.board-status-line.waiting {
    color: var(--warn);
}

.board-status-line.failed {
    color: var(--err);
}

.board-keys {
    flex: none;
    margin-left: auto;
    color: var(--faint);
}

/* The side: what needs you, then the one selected. */
.board-side {
    flex: none;
    width: 300px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    overflow-y: auto;
}

.board-needs {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.board-needs .label {
    margin: 0 0 2px;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: normal;
    text-transform: none;
}

.board-needs-count {
    font-family: var(--mono);
    color: var(--warn);
}

.board-need {
    display: grid;
    grid-template-columns: 14px minmax(0, 1fr);
    align-items: center;
    gap: 0 8px;
    padding: 8px;
    border-radius: var(--r-row);
    text-align: left;
    border: 1px solid transparent;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .board-need:hover {
        background: var(--hover);
    }
}

.board-need.on {
    background: var(--accent-soft);
    border-color: var(--accent-line);
}

.board-need-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.board-need-head {
    font-size: 13px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.board-need-head b {
    font-weight: 600;
}

.board-need.waiting .board-need-what {
    color: var(--warn);
}

.board-need.failed .board-need-what {
    color: var(--err);
}

.board-need-session {
    font-size: 12px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.board-detail {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 16px;
    border: 1px solid var(--hair);
    border-radius: var(--r-window);
    background: var(--card);
}

.board-detail-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px;
    min-width: 0;
}

.board-detail-name {
    min-width: 0;
    font: 600 14px var(--mono);
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.board-detail-state {
    flex: none;
    margin-left: auto;
    padding: 2px 9px;
    border-radius: var(--r-pill);
    background: color-mix(in srgb, var(--state) 14%, transparent);
    color: var(--state);
    font-size: 12px;
    font-weight: 500;
}

.board-facts {
    display: grid;
    grid-template-columns: 72px minmax(0, 1fr);
    gap: 8px 12px;
    font-size: 13px;
}

.board-facts > span:not([class]) {
    color: var(--muted);
}

.board-link {
    min-width: 0;
    text-align: left;
    color: var(--accent);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (hover: hover) {
    .board-link:hover {
        text-decoration: underline;
        text-underline-offset: 2px;
    }
}

.board-when {
    font-family: var(--mono);
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.board-asked {
    color: var(--body);
    text-wrap: pretty;
    overflow-wrap: anywhere;
}

.board-now {
    color: var(--text);
    overflow-wrap: anywhere;
}

.board-now.waiting {
    color: var(--warn);
}

.board-error {
    font: 12px/1.5 var(--mono);
    color: var(--err);
    overflow-wrap: anywhere;
}

.board-detail .agent-chip {
    align-self: flex-start;
}

.board-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.board-actions .button {
    min-height: 36px;
    padding: 0 14px;
    font-size: 13px;
}

@media (hover: hover) {
    .board-stop:hover {
        border-color: var(--err);
        color: var(--err);
    }
}

.board-actions .button.primary {
    flex: 1;
}

/* Phones: one column, what needs you first, thumb-sized squares, and the one selected in a bar at the bottom. */
.board-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 12px 12px 16px;
}

/* Room under the last row for the bar over it. */
.board-list.with-bar {
    padding-bottom: 200px;
}

.board.phone .board-needs {
    gap: 2px;
    padding: 12px 0;
    border-bottom: 1px solid var(--hair);
}

.board.phone .board-needs .label {
    margin-bottom: 4px;
}

.board.phone .board-need {
    gap: 0 10px;
    min-height: 44px;
    padding: 4px 8px;
}

.board.phone .board-need-head {
    font-size: 0.84rem;
}

.board.phone .board-need-session {
    font-size: 0.7rem;
}

.board.phone .board-row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 12px;
}

.board.phone .board-session {
    min-height: 24px;
    justify-content: center;
}

.board.phone .board-session-title {
    gap: 8px;
}

.board.phone .board-session-name {
    font-size: 0.84rem;
}

.board.phone .board-summary {
    flex: none;
    margin-left: auto;
    padding-left: 0;
    font-size: 0.68rem;
}

.board.phone .board-cells {
    max-width: none;
    justify-content: flex-start;
    gap: 6px;
}

.board.phone .board-cell {
    width: 40px;
    height: 40px;
}

.board-bar {
    position: absolute;
    left: 8px;
    right: 8px;
    bottom: 8px;
    z-index: 3;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 12px calc(env(safe-area-inset-bottom) + 14px);
    border: 1px solid var(--hair-2);
    border-radius: var(--r-sheet);
    background: var(--bg);
    box-shadow: var(--pop);
    animation: pop var(--t-in) var(--ease-out);
}

.board-bar-head {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.board-bar .board-detail-name {
    font-size: 14px;
}

.board-bar .board-detail-state {
    margin-left: 0;
    font-size: 11px;
}

.board-bar-when {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.board-bar-close {
    flex: none;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    border-radius: var(--r-row);
    margin: -6px -6px -6px 0;
    color: var(--body);
}

.board-bar-session {
    font-size: 0.74rem;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.board-bar-line {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 13px;
    color: var(--body);
    overflow-wrap: anywhere;
}

.board-bar-line.waiting {
    color: var(--warn);
}

.board-bar-line.failed {
    color: var(--err);
}

.board-bar-actions {
    display: flex;
    gap: 6px;
}

.board-bar-actions .button {
    height: 44px;
    font-size: 0.86rem;
}

.board-bar-actions .button.primary {
    flex: 1;
}

.board-bar-actions .button:not(.primary) {
    flex: none;
    width: 96px;
}

/* ─── PiP ──────────────────────────────────────────────────── */

/*
 * PiP's window: anchored to the bottom right corner, wherever the app is and however tall the message box grows, over
 * the conversation and its panels and under sheets, the launcher, and notices. It never reaches up over a session's top
 * bar (`--topbar-h`, which app.js publishes): on a short screen it is shorter instead. It grows from 92% at its
 * corner. On phones it is a sheet from the bottom edge, over a light scrim.
 */
.pip-panel {
    --pip-top: max(
        calc(var(--gap-out) + env(safe-area-inset-top)),
        calc(var(--topbar-h, 0px) + 6px)
    );
    position: fixed;
    right: calc(16px + env(safe-area-inset-right));
    bottom: calc(16px + env(safe-area-inset-bottom));
    width: min(420px, calc(100vw - 32px));
    height: min(620px, calc(100dvh - max(90px, var(--pip-top) + 16px)));
    max-height: calc(100dvh - var(--pip-top) - 16px - env(safe-area-inset-bottom));
    z-index: 18;
    display: flex;
    flex-direction: column;
    background: var(--o-bg-dark);
    border: 1px solid var(--hair);
    border-radius: var(--r-float);
    box-shadow: var(--pop);
    font: 14.5px/1.6 var(--sans);
    transform-origin: bottom right;
    animation: pip-in 0.32s var(--ease-out);
}

@keyframes pip-in {
    from {
        opacity: 0;
        transform: scale(0.92);
    }
}

.pip-panel.leaving {
    animation: pop-out var(--t-out) linear forwards;
}

.pip-resize {
    display: none;
}

@media (min-width: 768px) {
    .pip-panel {
        width: var(--pip-width, 420px);
        height: var(--pip-height, min(620px, calc(100dvh - 90px)));
        max-width: min(
            800px,
            calc(100vw - 32px - env(safe-area-inset-left) - env(safe-area-inset-right))
        );
        max-height: calc(100dvh - var(--pip-top) - 16px - env(safe-area-inset-bottom));
    }

    .pip-resize {
        display: block;
        position: absolute;
        touch-action: none;
        user-select: none;
        z-index: 1;
    }

    .pip-resize-left {
        left: -12px;
        top: 12px;
        bottom: 0;
        width: 16px;
        cursor: ew-resize;
    }

    .pip-resize-top {
        top: -12px;
        left: 12px;
        right: 0;
        height: 16px;
        cursor: ns-resize;
    }

    .pip-resize-corner {
        left: -12px;
        top: -12px;
        width: 24px;
        height: 24px;
        cursor: nwse-resize;
    }
}

@media (min-width: 768px) and (any-pointer: coarse) {
    .pip-resize-left {
        left: -34px;
        top: 22px;
        width: 44px;
    }

    .pip-resize-top {
        top: -34px;
        left: 22px;
        height: 44px;
    }

    .pip-resize-corner {
        left: -22px;
        top: -22px;
        width: 44px;
        height: 44px;
    }
}

.pip-head {
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr) auto repeat(4, 40px);
    align-items: center;
    gap: 2px;
    padding: 10px 8px 10px 16px;
    position: relative;
    flex: none;
    border-bottom: 1px solid var(--hair);
}

.pip-head .grip {
    display: none;
}

.pip-heading {
    min-width: 0;
    margin-left: 8px;
    line-height: 1.3;
}

.pip-title-line {
    display: flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
}

.pip-head h2 {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
}

.pip-head .pip-model {
    display: flex;
    gap: 4px;
    width: 100%;
    min-width: 0;
    height: 22px;
    padding: 0;
    position: relative;
    border: 0;
    border-radius: var(--r-tag);
    background: transparent;
    font: 12px var(--sans);
    color: var(--muted);
    text-align: left;
    white-space: nowrap;
}

/* A quiet model label with the original thumb-sized target; its extra area covers only the title. */
.pip-head .pip-model::before {
    content: "";
    position: absolute;
    inset: -18px 0 0;
}

.pip-model .model-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pip-model .model-level {
    display: none;
}

.pip-head > .icon-button {
    width: 40px;
    height: 40px;
    min-width: 0;
    border-radius: var(--r-row);
    color: var(--muted);
}

.pip-head > .icon-button:nth-last-child(4) {
    grid-column: 4;
}

.pip-head > .icon-button:nth-last-child(3) {
    grid-column: 5;
}

.pip-head > .icon-button:nth-last-child(2) {
    grid-column: 6;
}

.pip-head > .icon-button:last-child {
    grid-column: 7;
}

.pip-status {
    min-width: 0;
    color: var(--muted);
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* How full PiP's context is, as a session's status line shows it. */
.pip-context {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-right: 4px;
    font: 11px var(--mono);
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.pip-context .meter {
    width: 28px;
}

.pip-mark {
    display: inline-grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent);
}

.pip-mark.working .icon,
.pip-bubble.busy .icon,
.rail-pip.lit .icon {
    animation: pulse 1.4s ease-in-out infinite;
}

.pip-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    overflow-x: hidden;
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.pip-body::before {
    content: "";
    margin-top: auto;
}

.pip-body > * {
    flex-shrink: 0;
}

.pip-you {
    align-self: flex-end;
    max-width: 84%;
    padding: 10px 14px;
    background: var(--accent-soft);
    border-radius: var(--r-sheet) var(--r-sheet) calc(var(--r-tag) + 1px) var(--r-sheet);
    color: var(--text);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    animation: rise-in var(--t-fade) var(--ease-out);
}

.pip-reply {
    color: var(--body);
    overflow-wrap: anywhere;
}

.pip-reply .md > :first-child {
    margin-top: 0;
}

.pip-reply .md > :last-child {
    margin-bottom: 0;
}

.pip-steps,
.pip-event {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--muted);
    font-size: 12.5px;
}

.pip-steps.working {
    color: var(--accent);
}

.pip-tick {
    width: 16px;
    height: 16px;
    flex: none;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--ok-soft);
    color: var(--ok);
}

.pip-error {
    color: var(--err);
    font-size: 0.85rem;
}

/* A report from a session PiP follows: three lines until opened. */
.pip-report {
    padding: 12px 14px;
    background: var(--card);
    border: 1px solid var(--hair);
    border-radius: var(--r-window);
    color: var(--body);
}

.pip-report-head {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
    min-height: 20px;
    margin-bottom: 6px;
    color: var(--accent);
    font-size: 12px;
    font-weight: 500;
}

.pip-report-head span {
    flex: 1;
    text-align: left;
}

.pip-report-fold {
    color: var(--muted);
    transition: transform 300ms var(--ease-out);
}

.pip-report.open .pip-report-fold {
    transform: rotate(180deg);
}

.pip-report-text {
    font-size: 13.5px;
    line-height: 1.55;
}

.pip-report-text > :first-child {
    margin-top: 0;
}

.pip-report-text > :last-child {
    margin-bottom: 0;
}

/* What a webhook posted: as it came, shown once the card is open. */
.pip-report-data {
    margin: 6px 0 0;
    padding: 6px 8px;
    max-height: 16rem;
    overflow: auto;
    background: var(--code-bg);
    border: 1px solid var(--hair);
    border-radius: var(--r-row);
    font: 12px var(--mono);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.pip-report:not(.open) .pip-report-data {
    display: none;
}

.pip-report:not(.open) .pip-report-text {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.pip-welcome {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 40px;
}

.pip-hello {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
    color: var(--text);
}

.pip-intro {
    margin: 0;
    color: var(--muted);
    font-size: 13.5px;
    text-wrap: pretty;
}

.pip-welcome .button {
    min-height: 40px;
    white-space: normal;
}

.pip-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

.pip-chip {
    min-height: 40px;
    padding: 8px 12px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-card);
    color: var(--text);
    font-size: 13px;
    text-align: left;
}

.pip-chip:disabled {
    opacity: 0.5;
    cursor: default;
}

@media (hover: hover) {
    .pip-chip:not(:disabled):hover {
        border-color: var(--accent-line);
        color: var(--text);
    }
}

.pip-loading {
    margin: auto;
}

/* A call of PiP's waits for approval, which the panel cannot give: a line that leads to where it can. */
.pip-approval {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 12px 6px;
    padding: 8px 12px;
    border: 1px solid var(--warn-line);
    border-radius: calc(var(--r-control) + 1px);
    background: var(--warn-soft);
    color: var(--warn);
    font-size: 12.5px;
}

.pip-approval .button {
    min-height: 40px;
}

/* Quick access to the owner's private all-project memory approval queue. */
.pip-memory {
    flex: none;
    margin: 0 12px 6px;
}

.pip-memory .button {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    min-height: 44px;
    padding: 8px 12px;
    border: 0;
    border-radius: calc(var(--r-control) + 1px);
    background: var(--card);
    color: var(--body);
    font-size: 12.5px;
    text-align: left;
}

@media (hover: hover) {
    .pip-memory .button:hover {
        background: var(--card-2);
    }
}

.pip-memory-count {
    flex: none;
    color: var(--muted);
    font: 11.5px var(--mono);
    font-variant-numeric: tabular-nums;
}

.pip-memory-count.waiting {
    color: var(--accent);
}

.pip-composer-wrap {
    flex: none;
    min-width: 0;
    padding: 4px 12px 12px;
}

.pip-attachments {
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-height: 144px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-bottom: 6px;
}

.pip-attachment {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    padding: 4px 6px;
    border: 1px solid var(--hair);
    border-radius: calc(var(--r-control) + 1px);
    background: var(--card);
    font-size: 12px;
}

.pip-attachment .thumb {
    flex: none;
}

.pip-attachment .thumb img {
    width: 48px;
    height: 48px;
    object-fit: cover;
}

.pip-attachment-remove {
    min-width: 44px;
    min-height: 44px;
}

.pip-attachment-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pip-attachment > .muted,
.pip-attachment > .spinner,
.pip-attachment-remove {
    flex: none;
}

.pip-you .thumbs,
.pip-you .attachments {
    margin-top: 0.3rem;
    max-width: 100%;
    white-space: normal;
}

.pip-you .attachments .chip {
    max-width: 100%;
    overflow-wrap: anywhere;
}

.pip-composer {
    display: flex;
    align-items: flex-end;
    min-height: 48px;
    gap: 4px;
    padding: 1px 5px;
    border: 1px solid var(--hair-2);
    border-radius: calc(var(--r-float) + 4px);
    background: var(--card);
}

.pip-composer:focus-within {
    border-color: var(--accent-line);
}

.pip-composer textarea {
    flex: 1;
    min-width: 0;
    max-height: 160px;
    padding: 0.55rem 0;
    resize: none;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--text);
    font: 15px/1.45 var(--sans);
}

.pip-composer > .icon-button {
    width: 44px;
    min-width: 44px;
    height: 44px;
    min-height: 44px;
    border: 4px solid transparent;
    border-radius: 50%;
    background-clip: padding-box;
}

.pip-composer .pip-send {
    background-color: var(--card-2);
    color: var(--faint);
}

/* iOS zooms into a text field smaller than 16px as it takes focus: PiP's box keeps the app's touch size. */
@media (pointer: coarse) {
    .pip-composer textarea {
        font-size: 16px;
    }

    .pip-report-head {
        min-height: 40px;
    }
}

.pip-composer .pip-send:not(:disabled) {
    color: var(--accent-ink);
    background-color: var(--accent-fill);
}

.pip-composer .pip-send[aria-label="Stop PiP"] {
    color: var(--err);
    background-color: var(--err-soft);
}

.pip-scrim {
    display: none;
}

/* The mark in the corner, while PiP works or has something new: above the message box, out of its way. */
.pip-bubble {
    position: fixed;
    right: calc(var(--gap-out) + 6px + env(safe-area-inset-right));
    bottom: calc(104px + env(safe-area-inset-bottom));
    z-index: 16;
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    background: var(--o-bg-dark);
    color: var(--accent);
    border: 1px solid var(--hair-2);
    border-radius: 50%;
    box-shadow: var(--shadow);
    animation: pip-in 0.32s var(--ease-out);
}

.pip-bubble.leaving {
    animation: popout var(--t-out) linear forwards;
}

.pip-dot {
    position: absolute;
    top: 5px;
    right: 5px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
}

@media (max-width: 699px) {
    .pip-panel {
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        height: 86dvh;
        max-height: calc(100dvh - env(safe-area-inset-top));
        border: 0;
        border-radius: calc(var(--r-sheet) + 8px) calc(var(--r-sheet) + 8px) 0 0;
        background: var(--bg);
        box-shadow:
            0 -1px 0 var(--hair-2),
            0 -20px 40px -20px var(--sh);
        padding-bottom: env(safe-area-inset-bottom);
        animation: sheet-up var(--t-in) var(--ease-out);
    }

    .pip-panel.leaving {
        animation: sheet-down 0.2s var(--ease-in-out) forwards;
    }

    .pip-head {
        padding: 23px 10px 10px 14px;
        grid-template-columns: 32px minmax(0, 1fr) repeat(4, 40px);
    }

    .pip-head h2 {
        font-size: 16px;
    }

    .pip-context {
        grid-column: 2;
        grid-row: 2;
        margin: 0 0 0 8px;
        justify-self: start;
    }

    .pip-head > .icon-button {
        grid-row: 1 / 3;
    }

    .pip-head > .icon-button:nth-last-child(4) {
        grid-column: 3;
    }

    .pip-head > .icon-button:nth-last-child(3) {
        grid-column: 4;
    }

    .pip-head > .icon-button:nth-last-child(2) {
        grid-column: 5;
    }

    .pip-head > .icon-button:last-child {
        grid-column: 6;
    }

    .pip-head .grip {
        display: block;
    }

    /* Above the message box and the jump to the newest message, both at the bottom right. */
    .pip-bubble {
        bottom: calc(176px + env(safe-area-inset-bottom));
    }

    .pip-scrim {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 17;
        background: var(--scrim);
        animation: fade var(--t-fade) var(--ease-almost);
    }

    .pip-scrim.leaving {
        animation: fade-out var(--t-out) linear forwards;
    }
}

/* A webhook in its sheet: name and where it sends, what Pi is told, its address when just made, and how it was used. */
.hook {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 14px;
    margin-top: 10px;
    border-radius: var(--r-card);
    background: var(--bg);
    border: 1px solid var(--hair);
}

.hook-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 14px;
    border-radius: var(--r-window);
    border: 1px solid var(--hair);
    background: var(--card);
}

.hook-form input,
.hook-form textarea,
.hook-form .segmented {
    background: var(--bg);
}

.hook.fresh {
    border-color: var(--accent);
}

.hook-head,
.hook-actions {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.hook-actions {
    align-items: center;
}

.hook-text {
    font-size: 0.85rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.hook-address {
    overflow-wrap: anywhere;
    user-select: all;
    color: var(--accent);
}

/* ─── Extension gallery ────────────────────────────────────── */

/* One workspace for discovery and upkeep, not a stack of narrow pickers. */
.sheet.extension-hub {
    max-width: 1280px;
}

.extension-hub-tabs {
    display: flex;
    gap: 6px;
    border-bottom: 1px solid var(--hair);
    padding-bottom: 10px;
}

.extension-hub-tab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 42px;
    padding: 9px 16px;
    border: 1px solid transparent;
    border-radius: var(--r-control);
    background: transparent;
    color: var(--muted);
    font: inherit;
    font-size: 14px;
    cursor: pointer;
}

.extension-hub-tab.on {
    background: var(--accent-soft);
    color: var(--accent);
    border-color: var(--hair);
}

.extension-hub-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}

.extension-hub-toolbar .find-input {
    flex: 1;
    min-width: 160px;
    margin: 0;
}

.extension-hub-toolbar .gallery-tags {
    flex-basis: 100%;
}

.extension-hub-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
    gap: 20px;
}

.extension-hub-list,
.extension-hub-detail {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-width: 0;
}

.extension-hub-list .gallery-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    overflow: visible;
    border: 0;
    background: transparent;
}

.gallery-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    border: 1px solid var(--hair);
    border-radius: var(--r-card);
    background: var(--bg);
    transition:
        border-color var(--t-hover) var(--ease-out),
        background-color var(--t-hover) var(--ease-out);
}

.gallery-list > .gallery-card:not(:first-child) {
    border-top: 1px solid var(--hair);
}

.gallery-card.selected,
.gallery-card[aria-current="true"] {
    border-color: var(--accent);
    background: var(--accent-soft);
}

.gallery-card-open {
    display: block;
    width: 100%;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.gallery-card .gallery-row-title {
    font-size: 15px;
    line-height: 1.4;
}

.gallery-card .gallery-row-desc {
    font-size: 13px;
    line-height: 1.6;
}

.gallery-card .gallery-row-name {
    display: none;
}

.gallery-card-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.gallery-card-actions:empty {
    display: none;
}

.gallery-card-actions .button {
    min-height: 40px;
}

.gallery-entry-content,
.extension-management {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-width: 0;
}

.gallery-entry-content .pi-title {
    font-size: 22px;
    line-height: 1.3;
}

.gallery-entry-content .gallery-description {
    font-size: 14px;
    line-height: 1.7;
}

.gallery-entry-content .gallery-actions {
    margin: 0;
}

.extension-hub-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    min-height: 220px;
    padding: 32px;
    color: var(--muted);
    text-align: center;
    line-height: 1.6;
}

.extension-hub-detail-back {
    align-self: flex-start;
    min-height: 40px;
}

.extension-hub-layout.installed .extension-hub-list > .extension-hub-empty {
    min-height: 0;
    padding: 0;
    align-items: flex-start;
    text-align: left;
    font-size: 12px;
}

.gallery-technical {
    border-top: 1px solid var(--hair);
    padding-top: 14px;
}

.gallery-technical > summary {
    padding: 6px 0;
    color: var(--muted);
    font-size: 13px;
    cursor: pointer;
}

.gallery-technical[open] > summary {
    margin-bottom: 16px;
}

.gallery-technical > .group + .group {
    margin-top: 16px;
}

@media (hover: hover) {
    .extension-hub-tab:hover {
        color: var(--text);
        background: var(--card);
    }
    .gallery-card:hover {
        border-color: var(--hair-2);
    }
    .gallery-card-open:hover .gallery-row-title {
        color: var(--accent);
    }
}

@media (min-width: 1000px) {
    .sheet.extension-hub {
        height: min(900px, 88dvh);
        max-height: 88dvh;
    }
    .extension-hub > .sheet-body {
        overflow: hidden;
        padding: 20px 24px 24px;
        gap: 18px;
    }
    .extension-hub-layout {
        flex: 1;
        flex-shrink: 1;
        grid-template-columns: minmax(320px, 0.85fr) minmax(0, 1.15fr);
        gap: 24px;
        overflow: hidden;
    }
    .extension-hub-list,
    .extension-hub-detail {
        overflow-y: auto;
        overscroll-behavior: contain;
        scrollbar-gutter: stable;
        padding-right: 8px;
    }
    .extension-hub-detail {
        border-left: 1px solid var(--hair);
        padding-left: 24px;
    }
    .extension-hub-detail-back {
        display: none;
    }
    .extension-hub-layout:is(.installed, .updates):not(.has-selection) {
        grid-template-columns: minmax(0, 1fr);
    }
    .extension-hub-layout:is(.installed, .updates):not(.has-selection) > .extension-hub-detail {
        display: none;
    }
    .extension-hub-layout:is(.installed, .updates):not(.has-selection) .gallery-list,
    .extension-hub-layout.installed:not(.has-selection) .extension-management .group > .sheet-list {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 12px;
        border: 0;
        background: transparent;
        overflow: visible;
    }
    .extension-hub-layout.installed:not(.has-selection) .extension {
        border: 1px solid var(--hair);
        border-radius: var(--r-card);
        padding: 16px;
    }
    .extension-hub-empty {
        flex: 1;
    }
    .sheet.gallery:not(.extension-hub) {
        max-width: 1000px;
    }
}

@media (max-width: 999px) {
    .extension-hub:has(.extension-hub-layout.has-selection) .extension-hub-toolbar {
        display: none;
    }
    .extension-hub-layout:not(.has-selection) .gallery-card.selected {
        border-color: var(--hair);
        background: var(--bg);
    }
    .extension-hub-layout.has-selection > .extension-hub-list,
    .extension-hub-layout:not(.has-selection) > .extension-hub-detail {
        display: none;
    }
    .extension-hub-tab {
        flex: 1;
        padding-inline: 10px;
    }
}

/* A row of the Browse list: what it is, its tags, and how it stands here. */
.gallery-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    min-height: 3.2rem;
    padding: 0.7rem 0.6rem 0.7rem 0.85rem;
    background: none;
    border: 0;
    color: var(--text);
    font: inherit;
    font-size: 13.5px;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--t-hover) var(--ease-out);
}

@media (hover: hover) {
    .gallery-row:hover {
        background: var(--card-2);
    }
    .gallery-row:hover .gallery-row-title {
        color: var(--accent);
    }
}

.gallery-row > .icon {
    color: var(--muted);
}

.gallery-row-text {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.gallery-row-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.5rem;
    min-width: 0;
}

.gallery-row-title {
    font-weight: 600;
    overflow-wrap: anywhere;
}

.gallery-row-name {
    color: var(--muted);
    font-size: 0.76rem;
    overflow-wrap: anywhere;
}

.gallery-row-desc {
    color: var(--body);
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.gallery-row-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.1rem 0.55rem;
    color: var(--muted);
    font-size: 0.76rem;
    overflow-wrap: anywhere;
}

.gallery-tag-text {
    color: var(--faint);
}

.gallery-pills,
.extension-gallery {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
}

.pi-tag.gallery-on {
    color: var(--ok);
    background: var(--ok-soft);
}

.pi-tag.gallery-bad {
    color: var(--err);
    background: var(--err-soft);
}

.pi-tag.gallery-plain {
    color: var(--muted);
    background: var(--card-2);
}

/* Tag pills: one at a time filters the list. */
.gallery-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.gallery-tag {
    min-height: 32px;
    padding: 4px 12px;
    border: 1px solid var(--hair-2);
    border-radius: var(--r-pill);
    background: none;
    color: var(--muted);
    font-size: 12.5px;
    transition:
        background-color var(--t-hover) var(--ease-out),
        border-color var(--t-hover) var(--ease-out),
        color var(--t-hover) var(--ease-out);
}

@media (pointer: coarse) {
    .gallery-tag {
        min-height: 38px;
        padding: 6px 14px;
    }
}

@media (hover: hover) {
    .gallery-tag:hover {
        background: var(--hover);
        color: var(--text);
    }
}

.gallery-tag.on {
    color: var(--accent);
    border-color: var(--accent-line);
    background: var(--accent-soft);
}

.gallery-hidden {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.3rem 0.8rem;
}

.gallery-problems,
.gallery-notes,
.gallery-warn ul {
    margin: 0;
    padding-left: 1.2rem;
    overflow-wrap: anywhere;
}

.gallery-panel > .setting {
    margin: 0;
    padding: 10px 14px;
}

.gallery-address {
    overflow-wrap: anywhere;
    color: var(--text);
}

.gallery-index-form {
    padding: 12px 14px;
}

.gallery-wrap {
    flex-wrap: wrap;
}

/* One entry. */
.gallery-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.3rem 0.6rem;
}

.gallery-description {
    overflow-wrap: anywhere;
    color: var(--body);
}

.gallery-warn {
    padding: 10px 12px;
    border: 1px solid var(--warn-line);
    border-radius: var(--r-card);
    background: var(--warn-soft);
    color: var(--text);
    overflow-wrap: anywhere;
}

.gallery-revoked .sheet-actions {
    margin-top: 8px;
    justify-content: flex-start;
}

.gallery-declares dd.mono {
    font-size: 0.78rem;
}

.gallery-file {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.6rem;
    padding: 8px 14px;
    font-size: 12.5px;
    overflow-wrap: anywhere;
}

.gallery-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

@media (pointer: coarse) {
    .gallery-actions .button {
        min-height: 40px;
    }
}

/* Code: each file under its own head, scrolling sideways inside its box on a narrow screen. */
.gallery-source {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.gallery-source-head,
.gallery-entry-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.6rem;
}

.gallery-entry-head .group-title {
    flex: 1;
}

/* Share's form: where the files are, which only their author knows. One column on a phone. */
.gallery-form {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0.75rem 0.9rem;
}

.gallery-field input[aria-invalid="true"] {
    border-color: var(--warn);
}

.gallery-source-name {
    font-size: 13px;
    color: var(--text);
    overflow-wrap: anywhere;
}

pre.gallery-code {
    margin: 0;
    padding: 10px 12px;
    max-height: 60vh;
    overflow: auto;
    border: 1px solid var(--hair);
    border-radius: var(--r-control);
    background: var(--code-bg);
    color: var(--body);
    font: 12px / 1.55 var(--mono);
    white-space: pre;
    tab-size: 4;
}

/* An update: what each file does, and what was added to or taken from its declarations. */
.gallery-change {
    color: var(--muted);
}

.gallery-change.added,
.gallery-added {
    color: var(--ok);
}

.gallery-change.removed,
.gallery-removed {
    color: var(--err);
}

.gallery-change.changed {
    color: var(--warn);
}
