/*
 * Agent panel — a right-hand drawer available on every page.
 *
 * Scoped entirely under .agent-* class names and fixed-position, so it cannot disturb the layout
 * of a page it is dropped onto. Nothing here sets a global style.
 */

.agent-panel {
    position: fixed;
    right: 0;
    bottom: 0;
    z-index: 1035; /* below Bootstrap modals (1050) so a dialog is never covered */
    font-size: 13px;
}

.agent-panel[hidden] {
    display: none !important;
}

/*
 * The launcher's dock: the launcher plus its hide control, and the thing that is dragged.
 *
 * right/bottom here are the resting corner. A dragged dock carries its own inline right and bottom,
 * measured from the same corner, so the stylesheet default and a remembered position are the same
 * kind of number and a window resize can clamp either without converting.
 */
.agent-dock {
    position: absolute;
    right: 20px;
    bottom: 20px;
    display: flex;
    align-items: center;
    /* The whole dock is a drag surface; without this a touch drag on it scrolls the page instead. */
    touch-action: none;
}

/* .agent-dock sets display, which would otherwise win over the attribute. The panel sets hidden on the
   dock only while it sits in the shell's floating actions, outside the panel's own [hidden]. */
.agent-dock[hidden] {
    display: none !important;
}

/* In the shell's floating actions (shell.css places it there; see agent-panel.js placeDock) a tucked tab
   still reaches the window's edge: the stack keeps its offset from the edge, the tab gives it back. */
.shell-floating-actions > .agent-dock.agent-tucked {
    margin-right: calc(-1 * var(--shell-floating-actions-offset, 20px));
}

.agent-dock.agent-dragging,
.agent-dock.agent-dragging .agent-launcher {
    cursor: grabbing;
    user-select: none;
}

.agent-dock.agent-dragging .agent-launcher {
    box-shadow: 0 6px 20px rgba(0, 0, 0, .24);
}

/*
 * Hide control. Small and on the launcher's shoulder, shown on hover or keyboard focus only, so the
 * resting launcher keeps the shape people know. Always visible on a touch screen, which has no hover.
 */
.agent-dock-hide {
    position: absolute;
    top: -8px;
    left: -8px;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 1px solid rgba(0, 0, 0, .15);
    border-radius: 50%;
    background: var(--t-surface, #fff);
    color: var(--t-ink-muted, #6c757d);
    font-size: 13px;
    line-height: 17px;
    text-align: center;
    cursor: pointer;
    opacity: 0;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .14);
    transition: opacity 120ms ease-out;
}

.agent-dock:hover .agent-dock-hide,
.agent-dock:focus-within .agent-dock-hide {
    opacity: 1;
}

.agent-dock-hide:hover,
.agent-dock-hide:focus-visible {
    color: var(--t-ink-strong, #313a46);
    background: var(--t-surface-2, #f4f6f8);
}

@media (hover: none) {
    .agent-dock-hide {
        opacity: 1;
    }
}

.agent-dock.agent-dragging .agent-dock-hide {
    opacity: 0;
}

/*
 * Tucked: a slim tab flush with the right edge, keeping only the mark and the unread badge.
 * It keeps its height on the page, so tucking never moves the tab onto something new.
 */
.agent-dock.agent-tucked {
    right: 0 !important;
}

.agent-dock.agent-tucked .agent-launcher {
    padding: 9px 8px 9px 10px;
    border-right: 0;
    border-radius: 999px 0 0 999px;
}

/* On the tab's open side: its usual corner is past the edge of the window when tucked. */
.agent-dock.agent-tucked .agent-unread {
    right: auto;
    left: -6px;
}

.agent-dock.agent-tucked .agent-launcher-label,
.agent-dock.agent-tucked .agent-dock-hide {
    display: none;
}

.agent-launcher {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border: 1px solid rgba(0, 0, 0, .15);
    border-radius: 999px;
    background: var(--t-surface, #fff);
    color: var(--t-ink-strong, #313a46);
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .16);
}

.agent-launcher:hover,
.agent-launcher:focus-visible {
    background: var(--t-surface-2, #f4f6f8);
}

/*
 * Unread count on the launcher.
 *
 * Sits on the corner rather than inline, so the button does not change width as the number
 * appears and grows - a launcher that jumps a few pixels when the assistant says something is
 * a target that moves under the cursor about to click it.
 *
 * min-width with a pill radius keeps one digit round and lets two or three digits widen into a
 * lozenge rather than clipping.
 */
.agent-unread {
    position: absolute;
    top: -6px;
    right: -4px;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    box-sizing: border-box;
    border-radius: 999px;
    background: #f5325c;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 20px;
    text-align: center;
    /* The launcher is white on the page's own background; without this the badge reads as part of
       whatever sits behind the button. */
    box-shadow: 0 0 0 2px #fff;
}

/* The badge is meaningless while the drawer is open - anything unread is on screen being read -
   and the panel clears the count then. This is the belt to that braces. */
.agent-open .agent-unread {
    display: none;
}

@media (prefers-reduced-motion: no-preference) {
    .agent-unread {
        animation: agent-unread-in 160ms ease-out;
    }
}

@keyframes agent-unread-in {
    from { transform: scale(.6); opacity: 0; }
    to   { transform: scale(1);  opacity: 1; }
}

.agent-drawer {
    position: absolute;
    right: 20px;
    bottom: 20px;
    /*
     * The starting size. A viewer who drags an edge gets an inline width and height instead, kept
     * in localStorage and reapplied on the next page load.
     *
     * The two ceilings are the same 40px margin the panel clamps to in script, so that dragging
     * stops where the stylesheet stops rather than a stylesheet limit silently arriving first.
     */
    width: 360px;
    max-width: calc(100vw - 40px);
    height: 460px;
    max-height: calc(100vh - 40px);
    display: none;
    flex-direction: column;
    background: var(--t-surface, #fff);
    border: 1px solid rgba(0, 0, 0, .15);
    border-radius: 8px;
    box-shadow: 0 6px 28px rgba(0, 0, 0, .22);
    overflow: hidden;
}

.agent-panel.agent-open .agent-drawer {
    display: flex;
}

.agent-panel.agent-open .agent-launcher,
.agent-panel.agent-open .agent-dock {
    display: none;
}

.agent-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 14px;
    border-bottom: 1px solid rgba(0, 0, 0, .1);
    font-weight: 600;
}

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

.agent-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    flex: 0 0 auto;
}

.agent-close,
.agent-action {
    border: 0;
    background: none;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    color: var(--t-ink-muted, #6c757d);
}

.agent-action {
    font-size: 15px;
    padding: 2px 7px;
    border-radius: 4px;
}

.agent-action:hover,
.agent-action:focus-visible,
.agent-close:hover,
.agent-close:focus-visible {
    background: var(--t-surface-2, #edf1f5);
    color: var(--t-ink-strong, #313a46);
}

.agent-action[hidden] {
    display: none !important;
}

/*
 * The edges the drawer grows from.
 *
 * It is anchored to the bottom right corner, so only the top and the left can move. The strips are
 * wider than they look — a two-pixel target is a border, not a handle — and sit above the header
 * without covering its buttons, which is what the corner's z-index is settling.
 */
.agent-resize {
    position: absolute;
    z-index: 2;
}

.agent-resize-top {
    top: 0;
    left: 0;
    right: 0;
    height: 6px;
    cursor: ns-resize;
}

.agent-resize-left {
    top: 0;
    bottom: 0;
    left: 0;
    width: 6px;
    cursor: ew-resize;
}

.agent-resize-corner {
    top: 0;
    left: 0;
    width: 14px;
    height: 14px;
    z-index: 3;
    cursor: nwse-resize;
}

/*
 * While a drag is running.
 *
 * Text selection is turned off for the duration: without it, dragging up across the transcript
 * selects every line it passes and leaves the panel blue when the pointer is released.
 */
.agent-panel.agent-resizing,
.agent-panel.agent-resizing .agent-drawer {
    user-select: none;
}

/*
 * The list of conversations still running on the server.
 *
 * Capped in height and scrolled rather than allowed to grow: it opens above the transcript, and a
 * list of eight would otherwise push the conversation the user is reading out of the drawer.
 */
.agent-sessions {
    flex: 0 0 auto;
    max-height: 40%;
    overflow-y: auto;
    padding: 6px;
    border-bottom: 1px solid rgba(0, 0, 0, .1);
    background: var(--t-surface-2, #f8f9fa);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.agent-sessions[hidden] {
    display: none !important;
}

.agent-session {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    border-radius: 4px;
    background: none;
    padding: 6px 8px;
    font: inherit;
    color: var(--t-ink-strong, #313a46);
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.agent-session:hover,
.agent-session:focus-visible {
    background: var(--t-fill, #e9edf1);
}

/*
 * The one being read. Marked with weight and a rule rather than with colour alone, and the panel
 * also sets aria-current on it — the styling is the second signal, not the only one.
 */
.agent-session-current {
    font-weight: 600;
    border-left: 3px solid #313a46;
    padding-left: 5px;
}

.agent-session-empty {
    padding: 6px 8px;
    color: var(--t-ink-muted, #6c757d);
    font-style: italic;
}

.agent-transcript {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.agent-line {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    line-height: 1.45;
}

.agent-line-user {
    align-self: flex-end;
    max-width: 85%;
    padding: 6px 10px;
    border-radius: 10px 10px 2px 10px;
    background: var(--t-surface-2, #edf1f5);
}

.agent-line-agent {
    max-width: 95%;
}

/*
 * A reply whose markdown has been read as structure.
 *
 * .agent-line keeps newlines with pre-wrap, which is right for a line whose text went in whole and
 * wrong here: the renderer has already consumed those newlines into paragraphs and list items, so
 * leaving pre-wrap on would add a blank line on top of every margin it produced.
 */
.agent-line-markdown {
    white-space: normal;
}

.agent-md-p,
.agent-md-list,
.agent-md-block {
    margin: 0 0 .5em;
}

/* The last block already has the transcript's own gap under it; a margin doubles it. */
.agent-line-markdown > :last-child {
    margin-bottom: 0;
}

.agent-md-list {
    padding-left: 1.25rem;
}

.agent-md-code,
.agent-md-block {
    font-family: SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
    font-size: .9em;
    background: rgba(0, 0, 0, .05);
    border-radius: 3px;
}

.agent-md-code {
    padding: .1em .3em;
}

.agent-md-block {
    padding: .5em .6em;
    /*
     * A snippet keeps its own line breaks and wraps rather than scrolling. The drawer is three
     * hundred pixels wide at its smallest, so a horizontal scrollbar would hide the end of every
     * line — and a snippet in here is something to read, not something to run.
     */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.agent-md-block > code {
    background: none;
    padding: 0;
}

.agent-line-system {
    color: var(--t-ink-muted, #6c757d);
    font-style: italic;
}

.agent-footer {
    border-top: 1px solid rgba(0, 0, 0, .1);
    padding: 10px 14px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.agent-allowance {
    font-size: 11px;
    color: var(--t-ink-muted, #6c757d);
    min-height: 14px;
}

.agent-allowance-low {
    color: #b8531f;
    font-weight: 600;
}

.agent-input-row {
    display: flex;
    gap: 8px;
}

.agent-input {
    flex: 1 1 auto;
    min-width: 0;
    resize: none;
    padding: 7px 10px;
    border: 1px solid rgba(0, 0, 0, .2);
    border-radius: 6px;
    font: inherit;
}

.agent-send {
    padding: 7px 14px;
    border: 0;
    border-radius: 6px;
    background: #313a46;
    color: #fff;
    font-weight: 600;
    cursor: pointer;
}

/*
 * The same button, while a turn is running.
 *
 * It changes colour as well as label because the two presses mean opposite things and the button
 * does not move: a user who glanced away and reaches for where "Ask" was needs the control to look
 * different before they read it. Deliberately not red — stopping the assistant is a normal thing to
 * want, not a destructive action to be warned about — so it reads as the other mode of one control
 * rather than as a danger.
 */
.agent-send.agent-send-stop {
    background: #6b7280;
}

.agent-send:disabled,
.agent-input:disabled {
    opacity: .55;
    cursor: not-allowed;
}

/*
 * The transcript stays legible while a turn runs. It used to dim to .75, which on top of a disabled
 * input read as "this panel is broken" rather than "this panel is busy" - the pending line below
 * now carries that message, and carries it in words.
 */
.agent-panel.agent-busy .agent-transcript {
    opacity: 1;
}

.agent-pending {
    display: flex;
    align-items: center;
    gap: .5rem;
}

/*
 * A step the assistant took, printed as it happened.
 *
 * Set back from the conversation on purpose: these are not things anybody said, they are work
 * being narrated, and giving them the weight of a reply would make the transcript twice as loud
 * for the same content. The rule on the left is what carries the grouping, so several steps in a
 * row read as one sequence rather than as five separate remarks.
 */
.agent-line-step {
    color: var(--t-ink-muted, #6c757d);
    font-size: 12px;
    padding-left: .75rem;
    border-left: 2px solid rgba(0, 0, 0, .12);
    margin-left: .25rem;
}

/*
 * A step that was refused. Colour alone would carry this for most people and not for everyone, so
 * the panel also writes "Could not …" in front of it — the styling is the second signal, not the
 * only one.
 */
/*
 * A lookup. Set apart from a change because it is not one: nothing on the page has moved yet, and
 * a reader scanning the transcript afterwards should be able to tell what the assistant found out
 * from what it did.
 */
.agent-line-step-lookup {
    font-style: italic;
    opacity: .85;
}

.agent-line-step-refused {
    color: #b02a37;
    border-left-color: rgba(176, 42, 55, .4);
}

.agent-spinner {
    flex: 0 0 auto;
    width: .85em;
    height: .85em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: agent-spin .7s linear infinite;
}

@keyframes agent-spin {
    to { transform: rotate(360deg); }
}

/*
 * Respect the setting. A spinner is decoration for the people it does not hurt and a problem for
 * the people it does; the wait is still described in words either way.
 */
@media (prefers-reduced-motion: reduce) {
    .agent-spinner {
        animation: none;
        border-right-color: currentColor;
        opacity: .5;
    }
}

/*
 * The citation mark. Every claim the agent makes should point at something on screen, and this is
 * what puts the reader's eye there.
 */
.agent-highlight {
    outline: 2px solid #b8531f !important;
    outline-offset: 2px;
    transition: outline-color .2s ease-in-out;
}

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

@media (max-width: 575.98px) {
    .agent-drawer {
        right: 10px;
        left: 10px;
        width: auto;
        max-width: none;
    }

    /*
     * On a phone the launcher is the mark alone, a 40px circle - the size of the page's other round
     * floating buttons - rather than a pill that covers a third of a table row. The word is hidden
     * visually, not with display: none, so it still names the button for a screen reader; the badge
     * keeps its corner.
     */
    .agent-dock:not(.agent-tucked) .agent-launcher {
        width: 40px;
        height: 40px;
        padding: 0;
        justify-content: center;
    }

    .agent-launcher-label {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
        border: 0;
    }
}

@media print {
    .agent-panel,
    .agent-dock {
        display: none !important;
    }
}

/*
 * No handles where they cannot be used.
 *
 * A resize strip is something you press and hold and move a few pixels — a finger cannot hit it,
 * and a touch drag on it reads as a scroll, so on a phone it is a dead zone over the top of the
 * panel rather than a control. The panel's script makes the same decision independently and does
 * not bind them; this is what stops them showing a resize cursor in the meantime.
 *
 * Width and pointer are asked separately on purpose: a narrow desktop window is not a touch screen,
 * and a large tablet is not a narrow window.
 */
@media (max-width: 575.98px), (pointer: coarse) {
    .agent-resize {
        display: none;
    }
}
