GRM-3.2-Sky-Chat / app.css
DedeProGames's picture
Thinking/Error accordion bubble: always claim full width, collapsed or not
61cc64b verified
Raw
History Blame Contribute Delete
12 kB
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
.gradio-container, .main {
padding: 0 !important;
--layout-gap: 0 !important;
}
footer {
display: none !important;
}
html {
scroll-behavior: smooth;
}
html, body {
height: 100%;
overflow: hidden;
}
#main-row {
height: var(--vh, 100%);
max-height: 100%;
}
button[aria-label="Clear"] {
display: none;
}
#chat-column {
height: 100%;
display: flex;
flex-direction: column;
padding: 0;
overflow: hidden;
position: relative;
}
#chatbot {
flex: 1;
min-height: 100px;
border: 0;
}
.sidebar {
border-right: 1px solid var(--border-color-primary);
box-shadow: none;
}
.sidebar-parent:has(.sidebar.open:not(.right)) {
padding-left: 320px;
}
.sidebar-content {
position: relative;
padding: 50px 0 0 0 !important;
background: none;
}
.sidebar-content::before {
content: "";
position: absolute;
inset: 0;
background: url("/gradio_api/file=static/svg/logo.svg") no-repeat top;
background-size: 180px 52px;
pointer-events: none;
z-index: 0;
}
.toggle-button {
top: 10px;
}
/* New Conversation button - top spacing */
.sidebar > :first-child {
margin-bottom: 8px;
}
/* Sidebar buttons (New/Del) */
#main-row .sidebar button {
transition: all 0.15s ease;
}
#main-row .sidebar button:hover {
transform: translateY(-1px);
}
.sidebar-content .form {
border: 0;
background: transparent;
}
.wrap {
gap: 0;
}
/* Conversation items — card-style list */
.conv-empty-wrap {
padding: 0;
}
.conv-empty {
padding: 14px;
font-size: 12px;
opacity: 0.5;
text-align: center;
}
.conv-row {
flex-wrap: nowrap !important;
gap: 0 !important;
align-items: stretch;
border-bottom: 1px solid var(--border-color-primary);
background: transparent;
transition: background 0.15s ease;
}
.conv-row:hover {
background: var(--background-fill-secondary);
}
.conv-row-active {
background: var(--background-fill-secondary);
box-shadow: inset 2px 0 0 var(--primary-500, #ff4b4b);
}
.conv-row .conv-open {
flex: 1 1 auto;
min-width: 0;
justify-content: flex-start;
text-align: left;
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
border-radius: 0 !important;
padding: 10px 6px 10px 14px;
font-size: 13px;
font-weight: 400;
color: var(--button-secondary-text-color);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
}
.conv-row-active .conv-open {
color: var(--body-text-color);
}
/* Row actions — revealed on hover, always visible on touch devices */
.conv-row .conv-act {
flex: 0 0 auto;
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
border-radius: 0 !important;
font-size: 0;
padding: 0 8px;
opacity: 0;
color: var(--body-text-color-subdued);
transition: opacity 0.15s ease, color 0.15s ease;
}
.conv-row:hover .conv-act,
.conv-row .conv-act:focus-visible {
opacity: 0.75;
}
.conv-row .conv-act:hover {
opacity: 1;
color: var(--body-text-color);
}
.conv-row .conv-act-delete:hover {
color: var(--color-red-500, #ef4444);
}
.conv-row .conv-act::after {
font-size: 14px;
line-height: 1;
}
.conv-row .conv-act-rename::after {
content: "\270E";
}
.conv-row .conv-act-delete::after {
content: "\1F5D1";
}
@media (hover: none) {
.conv-row .conv-act {
opacity: 0.75;
}
}
label span {
margin: 0;
}
.icon-button-wrapper {
display: hidden;
}
/* --- Chat Message Animations --- */
@keyframes messageSlideIn {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Animate new messages as they appear */
#chatbot [data-testid="bot"],
#chatbot [data-testid="user"],
#chatbot [class*="message"] {
animation: messageSlideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
/* --- Input Area — Docked Bottom --- */
/* --- Send / Stop Button Micro-animations --- */
#send-btn, #stop-btn {
font-size: 0;
height: 100%;
min-width: 40px;
transition: transform 0.15s ease, opacity 0.15s ease;
cursor: pointer;
padding: 0;
}
#send-btn::after {
content: "";
display: inline-block;
width: 20px;
height: 20px;
background: url("/gradio_api/file=static/svg/send.svg") no-repeat center;
background-size: contain;
}
#stop-btn::after {
content: "";
display: inline-block;
width: 20px;
height: 20px;
background: url("/gradio_api/file=static/svg/stop.svg") no-repeat center;
background-size: contain;
}
/* --- Custom Scrollbars --- */
#chatbot::-webkit-scrollbar {
width: 6px;
}
#chatbot::-webkit-scrollbar-track {
background: transparent;
}
#chatbot::-webkit-scrollbar-thumb {
background: var(--border-color-primary);
transition: background 0.2s ease;
}
#chatbot::-webkit-scrollbar-thumb:hover {
background: var(--neutral-400);
}
/* Sidebar scrollbar — thinner, subtle */
.sidebar::-webkit-scrollbar {
width: 4px;
}
.sidebar::-webkit-scrollbar-track {
background: transparent;
}
.sidebar::-webkit-scrollbar-thumb {
background: var(--border-color-primary);
border-radius: 2px;
}
.input-container textarea {
background: var(--background-fill-secondary) !important;
}
/* The prompt field has no container, so its textarea is transparent and the
`.form` wrapper supplies the colour. Match that in the modal. */
.modal-card textarea,
.modal-card input[type="text"] {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
.bubble-wrap {
background: var(--background-fill-primary) !important;
}
/* ============================================
LANDING PAGE - Terminal-inspired Design
============================================ */
#landing-page-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background: var(--background-fill-primary);
z-index: 10;
pointer-events: auto;
}
#landing-page {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.landing-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 32px;
padding: 40px;
max-width: 600px;
width: 100%;
}
/* Logo styling */
.landing-logo {
margin-bottom: 100px !important;
}
.landing-logo svg {
height: 60px;
width: auto;
}
/* Hide landing page when chat has messages */
#landing-page-container.hidden {
display: none !important;
}
.landing-prompt {
bottom: 5%;
position: absolute;
text-align: center;
}
/* The wordmark carries its own light-theme palette (prefers-color-scheme
inside logo.svg), so it must not be inverted — inverting turned the blue
"Sky" letters brown. */
/* ============================================
INPUT ROW - Terminal-style Global
============================================ */
/* When landing page is visible, center the input row */
#chat-column.landing-active #input-row {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%);
width: 100%;
max-width: 600px;
z-index: 20;
}
#chat-column.landing-active #send-btn,
#chat-column.landing-active #stop-btn {
align-self: stretch;
min-width: 56px;
padding: 0 8px;
height: auto;
}
/* When landing page is hidden (chat active), keep input at bottom */
#chat-column:not(.landing-active) #input-row {
position: relative;
bottom: 3%;
left: auto;
transform: none;
max-width: none;
}
/* Terminal-style input row */
#input-row {
z-index: 15;
position: relative;
}
/* Shared verbatim with the rename modal's field so the two are identical. */
#input-row .form,
.modal-card .form {
background: rgba(255, 255, 255, 0.03) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
border-radius: 8px !important;
font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace !important;
transition: all 0.2s ease !important;
}
#input-row .form:focus-within,
.modal-card .form:focus-within {
border-color: rgba(255, 255, 255, 0.3) !important;
background: rgba(255, 255, 255, 0.05) !important;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.05) !important;
}
/* Terminal cursor effect on input */
#input-row textarea,
#input-row input[type="text"],
.modal-card textarea,
.modal-card input[type="text"] {
font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace !important;
caret-color: var(--body-text-color) !important;
caret-shape: block !important;
}
/* Blinking cursor animation for input */
@keyframes inputCursorBlink {
0%, 50% { border-right-color: var(--body-text-color); }
51%, 100% { border-right-color: transparent; }
}
/* Responsive adjustments */
@media (max-width: 768px) {
.landing-content {
padding: 20px;
gap: 24px;
}
.landing-logo svg {
height: 40px;
}
}
/* Center chat column on larger screens */
@media (min-width: 749px) {
#chat-column {
max-width: 748px;
margin: 0 auto;
}
}
/* Apply monospace font to body for terminal feel */
body, .gradio-container {
font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace !important;
}
/* Chatbot styling when empty */
#chatbot:empty,
#chatbot .empty-state {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
/* Ensure proper z-index stacking */
#chatbot {
z-index: 5;
}
.message-wrap {
margin-bottom: 40px;
}
/* --- Reasoning bubble --- */
.thinking-indicator {
display: inline-block;
margin-right: 4px;
}
/* Thinking / Error messages (metadata.title) render as Gradio's `.thought-group`
accordion. Its bubble is a flex item in a column ({message-wrap}), where
`align-self: flex-start` makes it shrink to the CROSS axis (horizontal)
content size — narrow while the accordion is collapsed, only reaching the
bubble's usual max-width once enough text renders to force it wider.
Overriding back to `stretch` claims that same max-width immediately,
collapsed or not. Scoped to bubbles that actually contain the accordion, so
plain-text messages keep hugging their content. */
#chatbot .bubble:has(.thought-group) {
align-self: stretch !important;
}
/* ============================================
RENAME / DELETE MODALS
Same terminal-style language as the chat UI.
============================================ */
.modal-overlay {
position: fixed;
inset: 0;
z-index: 3000;
align-items: center;
justify-content: center;
padding: 24px;
background: rgba(0, 0, 0, 0.6);
}
/* Gradio marks a hidden layout block with `.hide`, which — unlike `.hidden` —
is NOT `!important`. Every `display` rule below must therefore be gated on
`:not(.hide)`, or the closed modal leaks an empty bar over the chat. */
.modal-overlay:not(.hide):not(.hidden) {
display: flex;
flex-direction: column;
}
/* Gradio columns default to `flex-grow: 1; align-self: stretch`, which made
the card fill the whole viewport height. Pin it back to its content. */
.modal-overlay:not(.hide):not(.hidden) .modal-card {
display: flex !important;
flex-direction: column;
flex: 0 0 auto !important;
align-self: center !important;
width: 100%;
max-width: 420px;
height: auto !important;
min-height: 0 !important;
gap: 14px;
padding: 20px;
background: var(--background-fill-primary);
border: 1px solid var(--border-color-primary);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}
.modal-title {
font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
font-size: 15px;
font-weight: 600;
color: var(--body-text-color);
}
.modal-note {
font-size: 13px;
line-height: 1.5;
color: var(--body-text-color-subdued);
}
.modal-note b {
color: var(--body-text-color);
font-weight: 600;
}
.modal-actions {
gap: 8px !important;
justify-content: flex-end;
flex-wrap: nowrap !important;
}
.modal-actions .modal-btn {
flex: 0 0 auto;
min-width: 96px;
font-size: 13px;
}