/* ===========================================================================
   AI Chat (/chat) — Genie-style conversational analytics
   Dark theme, glassy bubbles, gradient AI accents (accent3 = #a06bff).
   Companion page to assets/chat.css references in src/pages/chat.py.
   =========================================================================== */

.chat-page {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 980px;
    margin: 0 auto;
    /* Fill the viewport below the app header so the input bar can sit at the
       bottom while the message list scrolls independently. --app-header-h is
       the REAL rendered header height (assets/chat_ux.js) — the old fixed
       96px guess clipped the composer whenever the nav wrapped to two rows.
       100dvh (where supported) tracks the mobile browser chrome so the
       composer isn't hidden behind the iOS/Android toolbar. */
    height: calc(100vh - var(--app-header-h, 96px));
    height: calc(100dvh - var(--app-header-h, 96px));
    min-height: 540px;
    padding: 0 16px 8px;
    box-sizing: border-box;
}

/* --------------------------------------------------------------------------- */
/* Header                                                                       */
/* --------------------------------------------------------------------------- */
.chat-header {
    flex: 0 0 auto;
    padding: 18px 4px 14px;
    border-bottom: 1px solid var(--border-color, #232830);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
}

.chat-header-title {
    display: flex;
    align-items: center;
    gap: 14px;
}

.chat-header-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    font-size: 1.05rem;
    color: #fff;
    background: linear-gradient(135deg, rgba(var(--accent3-rgb), 1) 0%, rgba(var(--accent-rgb), 1) 100%);
    box-shadow: 0 6px 18px rgba(var(--accent3-rgb), 0.35);
    flex: 0 0 auto;
}

.chat-title {
    margin: 0;
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--text-primary, #e8eaed);
}

.chat-subtitle {
    margin: 2px 0 0;
    font-size: 0.85rem;
    color: var(--text-secondary, #9ba1ad);
}

/* --------------------------------------------------------------------------- */
/* Roster upload control                                                         */
/* --------------------------------------------------------------------------- */
.chat-roster {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 8px 16px;
    flex: 0 1 auto;
    min-width: 0;
}

.chat-roster-controls {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.chat-roster-help {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
}

.chat-roster-help-toggle {
    background: none;
    border: none;
    padding: 0;
    font-size: 0.72rem;
    color: var(--text-secondary, #9ba1ad);
    text-decoration: underline;
    cursor: pointer;
}

.chat-roster-help-toggle:hover {
    color: var(--accent3-color, #a06bff);
}

.chat-roster-help-text {
    font-size: 0.72rem;
    color: var(--text-secondary, #9ba1ad);
    max-width: 320px;
    text-align: right;
    line-height: 1.4;
}

.chat-roster-upload {
    cursor: pointer;
    user-select: none;
}

.chat-roster-upload > span {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    border-radius: 10px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--accent3-color, #a06bff);
    border: 1px solid rgba(var(--accent3-rgb), 0.45);
    background: rgba(var(--accent3-rgb), 0.10);
    transition: background 0.15s ease, border-color 0.15s ease;
}

.chat-roster-upload:hover > span {
    background: rgba(var(--accent3-rgb), 0.18);
    border-color: rgba(var(--accent3-rgb), 0.7);
}

/* Fantrax league-id input + Load button (replaces the old CSV upload control) */
.chat-league-input {
    padding: 7px 14px;
    border-radius: 10px;
    font-size: 0.82rem;
    color: var(--text-primary, #e8eaed);
    border: 1px solid rgba(var(--accent3-rgb), 0.45);
    background: rgba(var(--accent3-rgb), 0.06);
    min-width: 220px;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.chat-league-input:focus {
    outline: none;
    border-color: rgba(var(--accent3-rgb), 0.8);
    background: rgba(var(--accent3-rgb), 0.1);
}
.chat-league-input::placeholder {
    color: var(--text-secondary, #9ba1ad);
}
.chat-league-load-btn {
    display: inline-flex;
    align-items: center;
    padding: 7px 14px;
    border-radius: 10px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--accent3-color, #a06bff);
    border: 1px solid rgba(var(--accent3-rgb), 0.45);
    background: rgba(var(--accent3-rgb), 0.10);
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.chat-league-load-btn:hover {
    background: rgba(var(--accent3-rgb), 0.18);
    border-color: rgba(var(--accent3-rgb), 0.7);
}
.chat-league-input--inline {
    display: inline-block;
    margin-right: 8px;
}

/* Inline roster-upload prompt rendered inside an assistant message */
.chat-artifact--roster-prompt {
    margin-top: 10px;
}

.chat-roster-upload--inline {
    display: inline-block;
}

.chat-roster-status {
    font-size: 0.8rem;
    color: var(--text-secondary, #9ba1ad);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 280px;
}

.chat-roster-status:empty {
    display: none;
}

.chat-roster-clear {
    display: none;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    border: 1px solid var(--border-color, #232830);
    background: transparent;
    color: var(--text-secondary, #9ba1ad);
    cursor: pointer;
    font-size: 0.8rem;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.chat-roster-clear:hover {
    color: var(--danger-color, #e15759);
    border-color: rgba(var(--danger-rgb, 225, 87, 89), 0.6);
}

.chat-roster:has(.chat-roster-status:not(:empty)) .chat-roster-clear {
    display: inline-flex;
}

@media (max-width: 640px) {
    .chat-roster-status { max-width: 160px; }
}

/* --------------------------------------------------------------------------- */
/* Message list                                                                 */
/* --------------------------------------------------------------------------- */
.chat-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 18px 4px 8px;
    display: flex;
    flex-direction: column;
    gap: 18px;
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--text-secondary-rgb), 0.35) transparent;
}

/* When the thread is empty (and nothing is in flight), vertically center the
   welcome/empty state. */
.chat-scroll:has(.chat-empty):has(.chat-live:empty) {
    justify-content: center;
}

/* Once a question is in flight, hide the welcome hero so only the in-flight
   bubble shows (the first answer then replaces the empty state entirely). */
.chat-scroll:has(.chat-live:not(:empty)) .chat-empty {
    display: none;
}

.chat-messages,
.chat-live {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

/* Hide the in-flight container when there's no pending message. */
.chat-live:empty {
    display: none;
}

.chat-scroll::-webkit-scrollbar {
    width: 8px;
}

.chat-scroll::-webkit-scrollbar-thumb {
    background: rgba(var(--text-secondary-rgb), 0.30);
    border-radius: 8px;
}

.chat-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
    animation: chat-fade-in 0.25s ease both;
}

.chat-row--user {
    justify-content: flex-end;
}

.chat-row--assistant {
    justify-content: flex-start;
}

@keyframes chat-fade-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* AI avatar */
.chat-avatar {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.85rem;
    color: #fff;
    margin-top: 2px;
    background: linear-gradient(135deg, rgba(var(--accent3-rgb), 1) 0%, rgba(var(--accent-rgb), 1) 100%);
    box-shadow: 0 4px 12px rgba(var(--accent3-rgb), 0.30);
}

/* Bubbles */
.chat-bubble {
    border-radius: 16px;
    padding: 12px 16px;
    font-size: 0.95rem;
    line-height: 1.55;
    max-width: 100%;
    width: fit-content; /* short messages hug their text (uiux-audit P2-13) */
    word-wrap: break-word;
    overflow-wrap: anywhere;
}

.chat-bubble--user {
    background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.95) 0%, rgba(var(--accent3-rgb), 0.92) 100%);
    color: #fff;
    border-bottom-right-radius: 6px;
    max-width: 78%;
    box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.25);
}

.chat-bubble--assistant {
    background: rgba(var(--card-bg-rgb), 0.92);
    border: 1px solid var(--border-color, #232830);
    color: var(--text-primary, #e8eaed);
    border-bottom-left-radius: 6px;
    /* Assistant answers can carry wide tables/charts. */
    flex: 1 1 auto;
    min-width: 0;
    max-width: calc(100% - 46px);
}

/* Markdown content inside assistant bubble */
.chat-markdown p {
    margin: 0 0 10px;
}

.chat-markdown p:last-child {
    margin-bottom: 0;
}

.chat-markdown ul,
.chat-markdown ol {
    margin: 6px 0 10px;
    padding-left: 20px;
}

.chat-markdown li {
    margin: 6px 0;
    line-height: 1.5;
}

/* Give each list entry clear vertical separation so ranked lists never read as
   one bunched block (especially on mobile, where entries wrap across lines). */
.chat-markdown li + li {
    margin-top: 8px;
}

.chat-markdown strong {
    color: #fff;
    font-weight: 600;
}

.chat-markdown a {
    color: var(--accent2-color, #22d3ee);
    text-decoration: none;
}

.chat-markdown a:hover {
    text-decoration: underline;
}

.chat-markdown code {
    background: rgba(var(--text-secondary-rgb), 0.18);
    padding: 1px 5px;
    border-radius: 4px;
    font-size: 0.85em;
}

/* Markdown tables: keep them legible on ANY width. A narrow table sits inline;
   a wide one scrolls horizontally as a single unit instead of squeezing every
   column until the header text breaks character-by-character on mobile.
   (display:block + width:max-content + overflow-x:auto is the GitHub-markdown
   approach — the thead/tbody/tr/td keep their table display, so it still lays
   out as a real table while the <table> itself becomes a scroll container.) */
.chat-markdown table {
    display: block;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-collapse: collapse;
    margin: 10px 0 12px;
    font-size: 0.86rem;
    line-height: 1.4;
    border: 1px solid var(--border-color, #232830);
    border-radius: 8px;
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--text-secondary-rgb), 0.35) transparent;
}

.chat-markdown th,
.chat-markdown td {
    padding: 7px 11px;
    border-bottom: 1px solid var(--border-color, #232830);
    /* Never let a header/value break mid-word into an unreadable stack. */
    white-space: nowrap;
    vertical-align: top;
}

.chat-markdown thead th {
    background: rgba(var(--text-secondary-rgb), 0.12);
    color: #fff;
    font-weight: 600;
    text-align: left;
}

.chat-markdown tbody tr:nth-child(even) td {
    background: rgba(var(--text-secondary-rgb), 0.05);
}

.chat-markdown tbody tr:last-child td {
    border-bottom: none;
}

/* Let the first column (usually a Player/label) wrap onto two lines so long
   names don't force the whole table into horizontal scroll; numeric columns
   stay nowrap so their values never break apart. */
.chat-markdown th:first-child,
.chat-markdown td:first-child {
    white-space: normal;
    min-width: 7.5em;
}

/* Typing indicator */
.chat-typing {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 2px;
}

.chat-typing span {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent3-color, #a06bff);
    opacity: 0.45;
    animation: chat-typing-bounce 1.2s infinite ease-in-out;
}

.chat-typing span:nth-child(2) { animation-delay: 0.18s; }
.chat-typing span:nth-child(3) { animation-delay: 0.36s; }

@keyframes chat-typing-bounce {
    0%, 80%, 100% { transform: translateY(0); opacity: 0.45; }
    40%           { transform: translateY(-5px); opacity: 1; }
}

/* Thinking indicator (staged, intent-aware "what the agent is doing") */
.chat-bubble--thinking {
    padding: 11px 15px;
}

.chat-thinking {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 210px;
}

.chat-thinking-orb {
    position: relative;
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 0.72rem;
    background: linear-gradient(135deg, rgba(var(--accent3-rgb), 1) 0%, rgba(var(--accent-rgb), 1) 100%);
    animation: chat-thinking-pulse 1.8s infinite ease-in-out;
}

/* Rotating gradient ring around the orb */
.chat-thinking-orb::before {
    content: "";
    position: absolute;
    inset: -4px;
    border-radius: 50%;
    background: conic-gradient(from 0deg,
        rgba(var(--accent3-rgb), 0) 0deg,
        rgba(var(--accent3-rgb), 0.9) 140deg,
        rgba(var(--accent-rgb), 0.95) 230deg,
        rgba(var(--accent3-rgb), 0) 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
            mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
    animation: chat-thinking-spin 1.1s linear infinite;
}

.chat-thinking-orb i {
    position: relative;
    z-index: 1;
}

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

@keyframes chat-thinking-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent3-rgb), 0.40); }
    50%      { box-shadow: 0 0 0 7px rgba(var(--accent3-rgb), 0); }
}

.chat-thinking-body {
    display: flex;
    flex-direction: column;
    gap: 7px;
    min-width: 0;
    flex: 1 1 auto;
}

/* Stacked stage labels — exactly one fades in at a time, on a loop */
.chat-thinking-stages {
    position: relative;
    height: 1.2rem;
    min-width: 150px;
}

.chat-thinking-stage {
    position: absolute;
    left: 0;
    top: 0;
    white-space: nowrap;
    font-size: 0.9rem;
    font-weight: 500;
    opacity: 0;
    background: linear-gradient(90deg,
        rgba(var(--text-secondary-rgb), 0.85) 0%,
        var(--text-primary, #e8eaed) 45%,
        rgba(var(--text-secondary-rgb), 0.85) 90%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
    animation:
        chat-thinking-cycle 8s infinite both,
        chat-thinking-shimmer 2.4s linear infinite;
}

@keyframes chat-thinking-cycle {
    0%   { opacity: 0; transform: translateY(5px); }
    3%   { opacity: 1; transform: translateY(0); }
    22%  { opacity: 1; transform: translateY(0); }
    25%  { opacity: 0; transform: translateY(-5px); }
    100% { opacity: 0; transform: translateY(-5px); }
}

@keyframes chat-thinking-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* Live agent progress (real tool trace / streamed answer polled from the
   server). When it has content it replaces the generic CSS stage cycle. */
.chat-thinking-live {
    min-width: 0;
}

.chat-thinking-live:empty { display: none; }

.chat-thinking-body:has(.chat-thinking-live:not(:empty)) .chat-thinking-stages {
    display: none;
}

/* Short stage labels ("Querying player stats…") get the shimmer treatment */
.chat-thinking-live-label {
    display: block;
    font-size: 0.9rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background: linear-gradient(90deg,
        rgba(var(--text-secondary-rgb), 0.85) 0%,
        var(--text-primary, #e8eaed) 45%,
        rgba(var(--text-secondary-rgb), 0.85) 90%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: chat-thinking-shimmer 2.4s linear infinite;
}

/* The final answer streaming in as markdown — inherits the full .chat-markdown
   treatment (incl. mobile-safe tables); this only tunes the in-progress look. */
.chat-stream-md {
    font-size: 0.95rem;
    line-height: 1.5;
    color: var(--text-primary, #e8eaed);
    opacity: 0.92;
}

.chat-stream-md p { margin: 0 0 0.45rem; }
.chat-stream-md p:last-child { margin-bottom: 0; }
.chat-stream-md ul, .chat-stream-md ol { margin: 0 0 0.45rem; padding-left: 1.2rem; }

/* Indeterminate progress shimmer */
.chat-thinking-bar {
    position: relative;
    height: 3px;
    width: 100%;
    max-width: 220px;
    border-radius: 999px;
    background: rgba(var(--text-secondary-rgb), 0.16);
    overflow: hidden;
}

.chat-thinking-bar-fill {
    position: absolute;
    top: 0;
    left: -40%;
    height: 100%;
    width: 40%;
    border-radius: 999px;
    background: linear-gradient(90deg,
        rgba(var(--accent-rgb), 0.15) 0%,
        rgba(var(--accent3-rgb), 1) 50%,
        rgba(var(--accent-rgb), 0.15) 100%);
    animation: chat-thinking-slide 1.5s infinite ease-in-out;
}

@keyframes chat-thinking-slide {
    0%   { left: -40%; }
    100% { left: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    .chat-thinking-orb,
    .chat-thinking-orb::before,
    .chat-thinking-bar-fill {
        animation: none;
    }
    .chat-thinking-bar-fill { left: 0; width: 100%; opacity: 0.7; }
    .chat-thinking-stage { animation: none; }
    .chat-thinking-stage:first-child { opacity: 1; transform: none; }
    .chat-thinking-live-label { animation: none; }
}

/* --------------------------------------------------------------------------- */
/* Artifacts (tables / charts / query panel)                                    */
/* --------------------------------------------------------------------------- */
.chat-artifact {
    margin-top: 14px;
    background: rgba(var(--card-bg-rgb), 0.55);
    border: 1px solid var(--border-color, #232830);
    border-radius: 12px;
    padding: 12px;
    overflow: hidden;
}

.chat-artifact:first-child {
    margin-top: 0;
}

.chat-artifact-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-primary, #e8eaed);
    margin-bottom: 10px;
    padding-left: 2px;
}

.chat-figure {
    width: 100%;
}

/* Ag-Grid sizing inside chat */
.chat-grid {
    width: 100%;
    --ag-font-size: 13px;
    --ag-grid-size: 5px;
    --ag-row-height: 36px;
    --ag-header-height: 38px;
}

/* Full Explorer grid reused inside chat: allow horizontal scroll for the
   broad column set rather than squeezing every column to fit. */
.chat-explorer-grid {
    min-height: 360px;
}

/* "My team" selector — appears once a Fantrax league is loaded (home hero +
   chat header). Matches the accent3 league-input pill aesthetic. Sizing must
   survive tight rows: the wrap can take a full row and the dropdown grows. */
.guru-team-wrap {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 0 1 auto;
    min-width: 0;
}

.guru-team-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-secondary, #9ba1ad);
    white-space: nowrap;
}

.guru-team-label-icon {
    color: var(--accent3-color, #a06bff);
    font-size: 0.75rem;
}

.guru-team-dd {
    /* Hard readability floor: the collapsed pill must always be wide enough
       to show a real team name, never shrink-to-content ("S..▾"). */
    min-width: min(230px, 62vw) !important;
    flex: 1 1 230px;
    max-width: 340px;
    font-size: 0.82rem;
}

/* The league dropdown doubles as the type-a-league-id box (creatable search),
   so it gets a wider track than the team pill — ids are ~16 chars. */
.guru-league-dd {
    flex: 1 1 300px;
    max-width: 420px;
}

/* The react-select root and control must fill the dash-dropdown wrapper AND
   inherit its readability floor (both the legacy v1 `.Select` and the v5
   `.Select__*` class generations, so the styling holds across Dash versions). */
.guru-team-dd .Select,
.guru-team-dd .Select__container {
    width: 100%;
    min-width: inherit;
}

.guru-team-dd .Select-control,
.guru-team-dd .Select__control {
    width: 100%;
    min-width: min(230px, 62vw);
    border-radius: 10px;
    border: 1px solid rgba(var(--accent3-rgb), 0.45) !important;
    background: rgba(var(--accent3-rgb), 0.06) !important;
    min-height: 34px;
    height: 34px;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.guru-team-dd .Select-control:hover,
.guru-team-dd.is-focused .Select-control,
.guru-team-dd .Select-control:focus-within,
.guru-team-dd .Select__control:hover,
.guru-team-dd .Select__control--is-focused {
    border-color: rgba(var(--accent3-rgb), 0.8) !important;
    background: rgba(var(--accent3-rgb), 0.1) !important;
}

.guru-team-dd .Select-placeholder,
.guru-team-dd .Select-value-label,
.guru-team-dd .Select__single-value {
    line-height: 32px !important;
    color: var(--text-primary, #e8eaed) !important;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.guru-team-dd .Select-placeholder,
.guru-team-dd .Select__placeholder {
    color: var(--text-secondary, #9ba1ad) !important;
}

/* The typed search text (creatable league-id entry) must sit on the same
   vertical center as the pill's value/placeholder — react-select's default
   input padding pushed it to the bottom of the 34px control. Covers both the
   legacy v1 (.Select-input) and v5 (.Select__input) class generations. */
.guru-team-dd .Select-input,
.guru-team-dd .Select__input-container {
    height: 32px;
    margin: 0;
    padding: 0;
    display: inline-flex;
    align-items: center;
}

.guru-team-dd .Select-input > input,
.guru-team-dd .Select__input input {
    line-height: 32px !important;
    height: 32px;
    padding: 0 !important;
    margin: 0 !important;
    color: var(--text-primary, #e8eaed) !important;
}

.guru-team-dd .Select-menu-outer,
.guru-team-dd .Select__menu {
    border-radius: 10px;
    border: 1px solid rgba(var(--accent3-rgb), 0.35);
    overflow: hidden;
    z-index: 60;
    /* Menu must stay readable even if the control is narrow. */
    min-width: 230px;
    width: max-content;
    max-width: min(320px, 92vw);
}

.guru-team-dd .Select__option,
.guru-team-dd .VirtualizedSelectOption {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.guru-team-wrap--chat {
    /* Sits to the RIGHT of the league-ID controls when the header row has
       room (flex-wrap on .chat-roster); wraps below them, centered, when it
       doesn't. */
    justify-content: center;
}

@media (max-width: 767.98px) {
    .guru-team-wrap {
        flex: 1 1 100%;
        min-width: 100%;
    }

    /* The LEAGUE wrap shares its row with the small clear-X button instead of
       pushing it onto a lonely overflow line (which grew the hero vertically).
       :has(.guru-league-dd) targets only the league selector wrap. The inner
       dropdown keeps a readability floor but flexes to fill the row. */
    .guru-hero-roster .guru-team-wrap:has(.guru-league-dd),
    .chat-roster-controls .guru-team-wrap:has(.guru-league-dd) {
        flex: 1 1 calc(100% - 42px);
        min-width: calc(100% - 42px);
    }

    .guru-team-wrap:has(.guru-league-dd) .guru-team-dd {
        min-width: min(220px, 58vw) !important;
        flex: 1 1 auto;
        width: 100%;
    }

    .guru-team-wrap:has(.guru-league-dd) .guru-team-dd .Select-control,
    .guru-team-wrap:has(.guru-league-dd) .guru-team-dd .Select__control {
        min-width: min(220px, 58vw);
        width: 100%;
    }

    .guru-team-dd {
        flex: 1 1 auto;
        min-width: min(250px, 74vw) !important;
        max-width: none;
        width: 100%;
    }

    .guru-team-dd .Select-control,
    .guru-team-dd .Select__control {
        min-width: min(250px, 74vw);
    }

    .guru-team-wrap--chat {
        justify-content: center;
    }
}

/* Fantasy Team Analyzer widgets reused inside chat (positional-rank heat grid,
   category strength bars, analyzer AG-grids, trade standings cards). */
.chat-analyzer {
    width: 100%;
    overflow-x: auto;
}

.chat-analyzer .ag-cell {
    display: flex;
    align-items: center;
}

.chat-analyzer .ag-cell.ag-right-aligned-cell {
    justify-content: flex-end;
}

.chat-analyzer--trade {
    overflow: visible;
}


/* Vertically center cell values. Heat-shaded numeric columns (e.g. Avg Pctl
   Score) otherwise render bottom-aligned and clipped because they rely on
   AG Grid's line-height centering, which breaks under the mobile transform
   zoom-out. Flex centering is robust regardless of row height / scale.
   Preserve each column's horizontal alignment. */
.chat-explorer-grid .ag-cell {
    display: flex;
    align-items: center;
}

.chat-explorer-grid .ag-cell.ag-right-aligned-cell {
    justify-content: flex-end;
}

.chat-artifact-empty {
    padding: 12px 14px;
    color: var(--text-secondary, #9ba1ad);
    font-size: 0.85rem;
}

/* Query-used disclosure */
.chat-query-panel {
    margin-top: 10px;
    font-size: 0.82rem;
}

.chat-query-panel > summary {
    cursor: pointer;
    color: var(--text-secondary, #9ba1ad);
    list-style: none;
    user-select: none;
    padding: 4px 2px;
    transition: color 0.15s ease;
}

.chat-query-panel > summary:hover {
    color: var(--accent3-color, #a06bff);
}

.chat-query-panel > summary::-webkit-details-marker {
    display: none;
}

.chat-q-body {
    margin-top: 8px;
    padding: 10px 12px;
    background: rgba(var(--dark-bg-rgb, 11, 13, 17), 0.5);
    border: 1px solid var(--border-color, #232830);
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.chat-q-row {
    display: flex;
    gap: 6px;
}

.chat-q-key {
    color: var(--text-secondary, #9ba1ad);
    min-width: 84px;
}

.chat-q-val {
    color: var(--text-primary, #e8eaed);
    font-weight: 500;
}

/* Backend / offline note */
.chat-backend-note {
    margin-top: 12px;
    font-size: 0.78rem;
    color: var(--text-secondary, #9ba1ad);
    display: flex;
    align-items: center;
    opacity: 0.85;
}

/* Deep-link action chips */
.chat-artifact--links {
    background: transparent;
    border: none;
    padding: 4px 0 0;
}

.chat-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.chat-link-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 13px;
    border-radius: 10px;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--text-primary, #e8eaed);
    text-decoration: none;
    background: rgba(var(--card-bg-rgb), 0.9);
    border: 1px solid var(--border-color, #232830);
    transition: border-color 0.15s ease, background 0.15s ease, transform 0.12s ease;
}

.chat-link-chip:hover {
    transform: translateY(-1px);
    text-decoration: none;
    border-color: rgba(var(--accent-rgb), 0.7);
    background: rgba(var(--accent-rgb), 0.12);
}

.chat-link-chip-icon {
    font-size: 0.8rem;
    color: var(--accent-color, #6b8aff);
}

/* Distinct accents per destination */
.chat-link-chip--profile .chat-link-chip-icon { color: var(--accent2-color, #22d3ee); }
.chat-link-chip--profile:hover {
    border-color: rgba(var(--accent2-rgb), 0.7);
    background: rgba(var(--accent2-rgb), 0.12);
}
.chat-link-chip--trends .chat-link-chip-icon { color: var(--accent3-color, #a06bff); }
.chat-link-chip--trends:hover {
    border-color: rgba(var(--accent3-rgb), 0.7);
    background: rgba(var(--accent3-rgb), 0.12);
}
.chat-link-chip--explorer .chat-link-chip-icon { color: var(--accent-color, #6b8aff); }

/* --------------------------------------------------------------------------- */
/* Grid interaction hint (under chat Explorer grids)                            */
/* --------------------------------------------------------------------------- */
.chat-grid-hint {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 10px;
    padding: 8px 12px;
    border-radius: 10px;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--text-secondary, #9ba1ad);
    background: rgba(var(--accent3-rgb), 0.07);
    border: 1px solid rgba(var(--accent3-rgb), 0.22);
}

.chat-grid-hint-icon {
    margin-top: 2px;
    font-size: 0.82rem;
    color: var(--accent3-color, #a06bff);
    flex: 0 0 auto;
}

.chat-grid-hint-emoji {
    font-style: normal;
}

/* --------------------------------------------------------------------------- */
/* Dynamic follow-up suggestion chips                                           */
/* --------------------------------------------------------------------------- */
.chat-followups {
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid rgba(var(--text-secondary-rgb, 155, 161, 173), 0.14);
}

.chat-followups-label {
    display: flex;
    align-items: center;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-secondary, #9ba1ad);
    margin-bottom: 9px;
    opacity: 0.85;
}

.chat-followups-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.chat-followup-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 999px;
    font-size: 0.83rem;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    color: var(--text-primary, #e8eaed);
    background: rgba(var(--card-bg-rgb), 0.9);
    border: 1px solid var(--border-color, #232830);
    transition: border-color 0.15s ease, background 0.15s ease, transform 0.12s ease;
}

.chat-followup-chip:hover {
    transform: translateY(-1px);
    border-color: rgba(var(--accent-rgb), 0.7);
    background: rgba(var(--accent-rgb), 0.12);
}

.chat-followup-chip-text {
    line-height: 1.3;
}

.chat-followup-chip-icon {
    font-size: 0.72rem;
    opacity: 0.55;
    color: var(--accent-color, #6b8aff);
    transition: transform 0.15s ease, opacity 0.15s ease;
}

.chat-followup-chip:hover .chat-followup-chip-icon {
    opacity: 1;
    transform: translateX(2px);
}

/* --------------------------------------------------------------------------- */
/* Empty state                                                                  */
/* --------------------------------------------------------------------------- */
.chat-empty {
    margin: auto;
    text-align: center;
    max-width: 620px;
    padding: 24px 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.chat-empty-icon {
    width: 64px;
    height: 64px;
    border-radius: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.6rem;
    color: #fff;
    margin-bottom: 18px;
    background: linear-gradient(135deg, rgba(var(--accent3-rgb), 1) 0%, rgba(var(--accent-rgb), 1) 100%);
    box-shadow: 0 10px 30px rgba(var(--accent3-rgb), 0.35);
}

.chat-empty-title {
    margin: 0 0 8px;
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--text-primary, #e8eaed);
}

.chat-empty-sub {
    margin: 0 0 22px;
    font-size: 0.95rem;
    color: var(--text-secondary, #9ba1ad);
    line-height: 1.5;
}

.chat-suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
}

.chat-suggestion-chip {
    display: inline-block;
    padding: 10px 16px;
    border-radius: 999px;
    font-size: 0.875rem;
    color: var(--text-primary, #e8eaed);
    text-decoration: none;
    background: rgba(var(--card-bg-rgb), 0.85);
    border: 1px solid var(--border-color, #232830);
    transition: border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
}

.chat-suggestion-chip:hover {
    border-color: rgba(var(--accent3-rgb), 0.7);
    background: rgba(var(--accent3-rgb), 0.12);
    transform: translateY(-2px);
    text-decoration: none;
}

/* --------------------------------------------------------------------------- */
/* Input bar                                                                    */
/* --------------------------------------------------------------------------- */
.chat-input-bar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 10px;
    padding: 8px 8px 8px 18px;
    border-radius: 16px;
    background: rgba(var(--card-bg-rgb), 0.92);
    border: 1px solid var(--border-color, #232830);
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.35);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.chat-input-bar:focus-within {
    border-color: rgba(var(--accent3-rgb), 0.65);
    box-shadow: 0 0 0 3px rgba(var(--accent3-rgb), 0.18), 0 6px 22px rgba(0, 0, 0, 0.35);
}

.chat-input {
    flex: 1 1 auto;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-primary, #e8eaed);
    /* Never below 16px: sub-16px inputs trigger iOS focus-zoom, which
       shoves the composer offscreen mid-conversation. */
    font-size: 1rem;
    padding: 10px 0;
    min-width: 0;
}

.chat-input::placeholder {
    color: var(--text-secondary, #9ba1ad);
}

.chat-send-btn {
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    border: none;
    cursor: pointer;
    color: #fff;
    font-size: 0.95rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, rgba(var(--accent3-rgb), 1) 0%, rgba(var(--accent-rgb), 1) 100%);
    box-shadow: 0 4px 14px rgba(var(--accent3-rgb), 0.35);
    transition: transform 0.12s ease, filter 0.12s ease;
}

.chat-send-btn:hover {
    filter: brightness(1.08);
    transform: translateY(-1px);
}

.chat-send-btn:active {
    transform: translateY(0);
}

.chat-disclaimer {
    flex: 0 0 auto;
    text-align: center;
    font-size: 0.78rem; /* was 11.5px at 0.7 opacity — illegible (P2-13) */
    color: var(--text-secondary, #9ba1ad);
    opacity: 0.95;
    padding: 8px 0 2px;
}

/* The global footer below a viewport-height chat column just adds a dead
   scroll region and pushes the composer around — suppress it on /chat
   (body.on-chat is set by assets/chat_ux.js). */
body.on-chat #app-footer {
    display: none;
}

/* "Open in Player Explorer" hand-off under chat-rendered Explorer grids. */
.chat-open-explorer {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 8px 12px;
    min-height: 40px;
    border-radius: 10px;
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--text-secondary, #9ba1ad);
    border: 1px solid rgba(var(--accent-rgb), 0.25);
    background: rgba(var(--accent-rgb), 0.06);
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.chat-open-explorer:hover {
    color: var(--text-primary, #e8eaed);
    border-color: rgba(var(--accent-rgb), 0.5);
    background: rgba(var(--accent-rgb), 0.12);
}

/* --------------------------------------------------------------------------- */
/* Homepage "The Guru" minimal ask widget                                       */
/* --------------------------------------------------------------------------- */
.guru-hero {
    position: relative;
    border-radius: 16px;
    padding: 30px 28px;
    border: 1px solid rgba(var(--accent3-rgb), 0.16);
    background:
        radial-gradient(120% 160% at 50% -30%, rgba(var(--accent3-rgb), 0.07) 0%, transparent 60%),
        rgba(var(--card-bg-rgb), 0.45);
}

.guru-hero-inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    max-width: 900px;
    margin: 0 auto;
}

.guru-hero-title {
    margin: 0 0 16px;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.01em;
    color: var(--text-primary, #e8eaed);
}

.guru-hero-name {
    background: linear-gradient(90deg, rgba(var(--accent3-rgb), 1) 0%, rgba(var(--accent2-rgb), 1) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--accent3-color, #a06bff);
}

/* Ask input — transparent shell with a soft gradient border */
.guru-hero-ask {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    max-width: 640px;
    padding: 9px 9px 9px 18px;
    border-radius: 14px;
    border: 1px solid transparent;
    background:
        linear-gradient(rgba(var(--dark-bg-2-rgb, 14, 17, 23), 0.55),
                        rgba(var(--dark-bg-2-rgb, 14, 17, 23), 0.55)) padding-box,
        linear-gradient(95deg,
                        rgba(var(--accent3-rgb), 0.50) 0%,
                        rgba(var(--accent2-rgb), 0.40) 50%,
                        rgba(var(--accent-rgb), 0.50) 100%) border-box;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.22);
    transition: box-shadow 0.18s ease;
}

.guru-hero-ask:focus-within {
    box-shadow: 0 0 0 3px rgba(var(--accent3-rgb), 0.16),
                0 8px 26px rgba(0, 0, 0, 0.28);
}

.guru-hero-ask-icon {
    color: var(--text-secondary, #9ba1ad);
    font-size: 0.95rem;
    flex: 0 0 auto;
}

.guru-hero-input {
    flex: 1 1 auto;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-primary, #e8eaed);
    font-size: 0.98rem;
    padding: 11px 2px;
    min-width: 0;
}

.guru-hero-input::placeholder {
    color: var(--text-secondary, #9ba1ad);
    opacity: 0.85;
}

/* Circular send button inside the field */
.guru-hero-go-btn {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    padding: 0;
    border-radius: 12px;
    border: none;
    cursor: pointer;
    color: #fff;
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, rgba(var(--accent3-rgb), 1) 0%, rgba(var(--accent-rgb), 1) 100%);
    box-shadow: 0 4px 14px rgba(var(--accent3-rgb), 0.40);
    transition: transform 0.12s ease, filter 0.12s ease;
}

.guru-hero-go-btn:hover {
    filter: brightness(1.08);
    transform: translateY(-1px);
}

/* Row holding the ask pill (the roster-upload control sits on its own row below) */
.guru-hero-ask-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
}

/* Roster upload control — sits centered below the ask input, sharing the ask
   pill's 640px track so the league-id field stays proportional to it.
   flex-wrap lets the 'My team' selector drop to its own full-width row on
   small screens instead of squashing the dropdown to a sliver. */
.guru-hero-roster {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex: 0 0 auto;
    width: 100%;
    max-width: 640px;
    margin: 12px auto 0;
}

/* Match the height/feel of the ask pill's send button area */
.guru-hero-roster-upload > span {
    padding: 10px 16px;
    font-size: 0.84rem;
    border-radius: 12px;
}

/* Fantrax league-id input + Load button (replaces the old CSV upload control).
   The input holds ~50% of the ask pill's width at every screen size — the row
   itself is centered, so the field sits on the page's central axis. */
.guru-hero-league-input {
    padding: 10px 16px;
    font-size: 0.84rem;
    border-radius: 12px;
    color: var(--text-primary, #e8eaed);
    border: 1px solid rgba(var(--accent3-rgb), 0.45);
    background: rgba(var(--accent3-rgb), 0.06);
    flex: 0 1 50%;
    width: 50%;
    max-width: 320px;
    min-width: 140px;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.guru-hero-league-input:focus {
    outline: none;
    border-color: rgba(var(--accent3-rgb), 0.8);
    background: rgba(var(--accent3-rgb), 0.1);
}
.guru-hero-league-input::placeholder {
    color: var(--text-secondary, #9ba1ad);
}
.guru-hero-league-load-btn {
    display: inline-flex;
    align-items: center;
    padding: 10px 16px;
    font-size: 0.84rem;
    font-weight: 600;
    border-radius: 12px;
    color: var(--accent3-color, #a06bff);
    border: 1px solid rgba(var(--accent3-rgb), 0.45);
    background: rgba(var(--accent3-rgb), 0.10);
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.guru-hero-league-load-btn:hover {
    background: rgba(var(--accent3-rgb), 0.18);
    border-color: rgba(var(--accent3-rgb), 0.7);
}

/* Status + helper line shown beneath the ask row */
.guru-hero-roster-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 6px 14px;
    margin-top: 10px;
    width: 100%;
}

.guru-hero-roster-status {
    max-width: 420px;
}

.guru-hero-roster-meta .chat-roster-help-text {
    flex-basis: 100%;
    text-align: center;
    max-width: 520px;
    margin: 0 auto;
}

/* Reveal the clear button once a roster status is present */
.guru-hero-roster:has(~ .guru-hero-roster-meta .chat-roster-status:not(:empty)) .chat-roster-clear {
    display: inline-flex;
}

/* Small screens: keep the league-id input at ~half the ask width (never
   full-bleed); the team selector drops to a full-width row (via .guru-team-wrap
   media rule). */
@media (max-width: 640px) {
    .guru-hero-league-input {
        flex: 0 1 50%;
        width: 50%;
        min-width: 140px;
    }
}

/* Quick-start sample question chips under the hero input */
.guru-hero-samples {
    display: flex;
    flex-wrap: nowrap;
    align-items: stretch;
    justify-content: center;
    gap: 12px;
    margin-top: 18px;
    width: 100%;
}

.guru-hero-sample {
    flex: 1 1 0;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10px 14px;
    border-radius: 14px;
    font-size: 0.82rem;
    line-height: 1.3;
    text-align: center;
    text-decoration: none;
    color: var(--text-secondary, #9ba1ad);
    border: 1px solid rgba(var(--accent3-rgb), 0.22);
    background: rgba(var(--dark-bg-2-rgb, 14, 17, 23), 0.45);
    transition: color 0.16s ease, border-color 0.16s ease,
                background 0.16s ease, transform 0.12s ease;
}

.guru-hero-sample:hover {
    color: var(--text-primary, #e8eaed);
    border-color: rgba(var(--accent3-rgb), 0.5);
    background: rgba(var(--accent3-rgb), 0.12);
    transform: translateY(-1px);
}

/* --------------------------------------------------------------------------- */
/* Responsive                                                                   */
/* --------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
    /* Header compaction (uiux-audit P2-13): the subtitle + full-size badge
       spent ~90px of a phone screen before the first message. */
    .chat-subtitle {
        display: none;
    }

    .chat-header {
        padding: 10px 4px 8px;
    }

    .chat-header-badge {
        width: 32px;
        height: 32px;
        font-size: 0.85rem;
    }

    .chat-page {
        /* Height comes from the shared --app-header-h calc above. */
        padding: 0 10px 6px;
        min-height: 0;
    }

    .chat-bubble--user {
        max-width: 88%;
    }

    .chat-bubble--assistant {
        max-width: calc(100% - 44px);
    }

    .chat-title {
        font-size: 1.15rem;
    }

    .guru-hero {
        padding: 24px 16px;
    }

    .guru-hero-title {
        font-size: 1.3rem;
    }

    /* Stack the ask pill and roster-upload control on small screens. */
    .guru-hero-roster {
        justify-content: center;
        width: 100%;
    }

    .guru-hero-roster-upload {
        flex: 1 1 auto;
    }

    .guru-hero-roster-upload > span {
        justify-content: center;
        width: 100%;
    }

    .guru-hero-league-input {
        flex: 0 1 50%;
        width: 50%;
        min-width: 140px;
    }

    /* Quick-start samples: scrollable chip row on phones instead of
       deleting the page's best onboarding affordance (uiux-audit P2-7). */
    .guru-hero-samples {
        display: flex;
        flex-wrap: nowrap;
        justify-content: flex-start; /* centered overflow hides the left half (R0-15) */
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        gap: 8px;
        padding-bottom: 4px;
        scroll-snap-type: x proximity;
        max-width: 100%;
    }

    .guru-hero-sample {
        flex: 0 0 auto;
        max-width: 78vw;
        scroll-snap-align: start;
        /* Wrap to two lines instead of tail-ellipsizing the question (R0-15). */
        white-space: normal;
        text-align: left;
    }

    /* Tighten artifact chrome so charts/tables get more usable width. */
    .chat-artifact {
        padding: 8px;
        border-radius: 10px;
    }

    .chat-artifact-title {
        font-size: 0.82rem;
        margin-bottom: 6px;
    }

    /* Slightly smaller inline markdown tables on phones; they still scroll
       horizontally rather than squeezing/wrapping their headers. */
    .chat-markdown table {
        font-size: 0.8rem;
    }

    .chat-markdown th,
    .chat-markdown td {
        padding: 6px 9px;
    }

    /* Compact the data grid and let it scroll horizontally instead of
       squeezing every metric column to an unreadable width. */
    .chat-grid {
        --ag-font-size: 11px;
        --ag-grid-size: 4px;
        --ag-row-height: 30px;
        --ag-header-height: 32px;
    }

    /* Reused full Player Explorer grid (uiux-audit P0-5): NO transform
       scaling — the old scale(0.55) produced ~7px text inside a nested
       scroll trap. Phones get a curated tier-1 column set (the metric the
       question asked about first; applied by assets/chat_ux.js from the
       grid context's mobileCols) at readable native sizes, with horizontal
       scroll for the rest and an "Open in Player Explorer" hand-off below. */
    .chat-explorer-grid {
        --ag-font-size: 13px;
        --ag-row-height: 44px;
        --ag-header-height: 36px;
    }

    .chat-explorer-grid.ag-theme-alpine-dark .ag-header-cell {
        font-size: 0.75rem;
    }

    .chat-explorer-grid.ag-theme-alpine-dark .ag-cell {
        font-size: 0.8125rem;
    }

    /* Smaller headshot + tighter spacing in the player-name cell. */
    .chat-explorer-grid .pe-player-name-link + img,
    .chat-explorer-grid img.w-6.h-6 {
        width: 20px !important;
        height: 20px !important;
        margin-right: 6px !important;
    }

    /* Drop the page-size selector — no room for it on a phone. */
    .chat-explorer-grid .ag-paging-panel .ag-paging-page-size {
        display: none;
    }

    /* Plotly is re-laid-out clientside for phones; keep the container fluid. */
    .chat-figure,
    .chat-figure .js-plotly-plot,
    .chat-figure .plot-container {
        width: 100% !important;
    }
}

/* Stop control for the in-flight exchange (uiux-audit P1-9). */
.chat-stop-btn {
    align-self: flex-start;
    margin: 4px 0 0 44px;
    padding: 8px 14px;
    min-height: 40px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.15);
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-secondary);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
}

.chat-stop-btn:hover {
    color: var(--text-primary);
    border-color: rgba(255, 255, 255, 0.3);
}

.chat-send-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
    filter: grayscale(0.4);
}

/* New-chat control (uiux-audit P1-8). */
.chat-new-btn {
    display: inline-flex;
    align-items: center;
    margin-left: 10px;
    padding: 8px 14px;
    min-height: 40px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-secondary, #9ba1ad);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.chat-new-btn:hover {
    color: var(--text-primary, #e8eaed);
    border-color: rgba(255, 255, 255, 0.3);
}

/* F3-15: the pending row's avatar carries the thinking pulse (the in-bubble
   orb duplicated the same wand icon right next to it). */
.chat-row--assistant:has(.chat-bubble--thinking) .chat-avatar {
    animation: chat-thinking-pulse 1.8s infinite ease-in-out;
}
