html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    background: #111;
    color: #eee;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  }

  .chat-container {
    flex: 1;
    min-width: 0;
    background: #111;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
  }

  .chat-header {
    background-color: #000;
    color: white;
    padding: 16px;
    text-align: center;
    font-size: 22px;
    font-weight: bold;
    border-bottom: 1px solid #d9a441;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }

  .chat-title-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.3;
  }

  #chatHeaderSubtitle {
    font-size: 11px;
    font-weight: bold;
    letter-spacing: 0.5px;
    color: #d9a441;
    margin-top: 2px;
  }

  #backToSiteBtn {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
  }

  #backToSiteBtn:hover {
    opacity: 0.8;
  }

  #backLogo {
    height: 38px;
    width: auto;
    display: block;
    transition: transform 0.3s ease;
  }

  /* Extra hover feedback on top of the idle breathing animation, since
     this specific logo is a real button (navigates back to the main
     site) -- a slight lift + tilt makes that interactivity obvious. */
  #backToSiteBtn:hover #backLogo {
    transform: scale(1.08) rotate(-4deg);
  }

  .app-layout {
    display: flex;
    width: 100vw;
    height: 100dvh;
    height: 100vh;
    height: 100dvh;
  }

  .sidebar {
    width: 130px;
    min-width: 100px;
    max-width: 400px;
    flex-shrink: 0;
    background: #000;
    display: flex;
    flex-direction: column;
    height: 100%;
    box-sizing: border-box;
  }

  /* Draggable divider between the sidebar and the chat -- a thin
     invisible-until-hovered strip, widened slightly beyond its visual
     border so it's actually easy to grab with a mouse, not just the
     literal 1px line. */
  #sidebarResizeHandle {
    width: 5px;
    flex-shrink: 0;
    background: #d9a441;
    opacity: 0.4;
    cursor: col-resize;
    transition: opacity 0.15s ease;
  }

  #sidebarResizeHandle:hover,
  #sidebarResizeHandle.resizing {
    opacity: 1;
  }

  /* On mobile the sidebar switches to a full-width stacked layout (see
     the max-width:768px block below) where horizontal drag-resizing
     doesn't make sense -- hide the handle there entirely. */
  @media (max-width: 768px) {
    #sidebarResizeHandle {
      display: none;
    }
  }

  .sidebar-top {
    padding: 8px;
    border-bottom: 1px solid #2a2a2a;
    display: flex;
    justify-content: center;
  }

  #sidebarNewChatBtn {
    width: 112px; /* fixed instead of 100% -- stays this size regardless of how wide the sidebar is dragged, per the resize feature added above */
    padding: 8px 4px;
    background: #d9a441;
    color: #111;
    border: none;
    border-radius: 8px;
    font-weight: bold;
    font-size: 12px;
    cursor: pointer;
  }

  #sidebarNewChatBtn:hover {
    opacity: 0.9;
  }

  .chat-history-list {
    flex: 1;
    overflow-y: auto;
    padding: 6px;
  }

  .chat-history-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 3px;
    padding: 7px 6px;
    border-radius: 7px;
    color: #ddd;
    font-size: 11px;
    cursor: pointer;
    margin-bottom: 3px;
  }

  .chat-history-item:hover {
    background: #1c1c1c;
  }

  .chat-history-item.active-chat {
    background: #262626;
    border: 1px solid #d9a441;
  }

  .chat-history-item.pending-chat {
    border: 1px dashed #666;
    color: #999;
    cursor: default;
  }

  .chat-history-item-title {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .chat-history-delete-btn {
    background: none;
    border: none;
    color: #888;
    cursor: pointer;
    font-size: 12px;
    padding: 1px 3px;
    flex-shrink: 0;
  }

  .chat-history-delete-btn:hover {
    color: #e05252;
  }

  .chat-history-empty {
    color: #666;
    font-size: 11px;
    padding: 8px 4px;
    text-align: center;
  }

  .sidebar-bottom {
    border-top: 1px solid #2a2a2a;
    padding: 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .sidebar-owner-name {
    width: 112px; /* fixed instead of relying on the parent's full width -- keeps text truncation and centering consistent regardless of sidebar width */
    color: #ddd;
    font-size: 11.5px;
    font-weight: bold;
    text-align: center;
    margin-bottom: 6px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .account-wrapper {
    position: relative;
    width: 100%; /* spans the full sidebar width so the dropdown below (positioned against this) resizes along with the sidebar drag -- the button itself stays fixed-size via #accountBtn below */
    margin-bottom: 6px;
    display: flex;
    justify-content: center;
  }

  #accountBtn {
    width: 36px; /* fixed regardless of sidebar width, unlike the wrapper around it */
    padding: 6px 4px;
    background: rgba(255, 255, 255, 0.08);
    color: #ccc;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 7px;
    font-size: 16px;
    cursor: pointer;
  }

  #accountBtn:hover {
    background: rgba(255, 255, 255, 0.15);
  }

  .account-dropdown {
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    margin-bottom: 6px;
    background: #2a2a2a;
    border: 1px solid #d9a441;
    border-radius: 8px;
    padding: 10px 8px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.5);
    z-index: 20;
  }

  .account-dropdown-name {
    color: white;
    font-size: 12px;
    font-weight: bold;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .account-dropdown-email {
    color: #999;
    font-size: 10.5px;
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .account-dropdown hr {
    border: none;
    border-top: 1px solid #333;
    margin: 8px 0;
  }

  .account-dropdown-link {
    display: block;
    color: #d9a441;
    font-size: 11px;
    text-decoration: none;
    margin-bottom: 6px;
  }

  .account-dropdown-link:hover {
    text-decoration: underline;
  }

  .account-dropdown-privacy-note {
    color: #777;
    font-size: 10px;
    line-height: 1.4;
  }

  #sidebarLogoutBtn {
    width: 112px; /* fixed, matching the other sidebar-bottom controls above */
    padding: 7px;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 7px;
    font-size: 11px;
    cursor: pointer;
  }

  #sidebarLogoutBtn:hover {
    background: rgba(255, 255, 255, 0.2);
  }

  /* Shared positioned container for chat-box and liveChatVisualizer --
     see the HTML comment at liveChatVisualizer for the real bug this
     fixes. min-height:0 is required here (not just cosmetic) --
     without it, a nested flex child defaults to min-height:auto, which
     silently breaks chat-box's own overflow-y:auto scrolling by letting
     content push this wrapper taller instead of scrolling within it. */
  .chat-box-wrapper {
    position: relative;
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .chat-box {
    flex: 1;
    padding: 18px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    scroll-behavior: smooth;
    position: relative;
    background-color: #111;
    transition: background-color 0.4s ease;
  }

  /* MODELS overlay -- fills exactly the visible chat area (not the
     header, not the input bar) and centers its content, so choosing a
     model feels like a distinct screen rather than a popup menu or a
     permanent chat bubble. */
  .models-overlay {
    display: none;
    position: absolute;
    inset: 0;
    background: rgba(10, 10, 10, 0.94);
    align-items: center;
    justify-content: center;
    z-index: 20;
    padding: 24px;
  }

  .models-overlay-content {
    width: 100%;
    max-width: 560px;
    text-align: center;
    position: relative;
  }

  .models-overlay-close {
    position: absolute;
    top: -12px;
    right: -4px;
    background: none;
    border: none;
    color: #888;
    font-size: 18px;
    cursor: pointer;
    padding: 6px;
  }

  .models-overlay-close:hover {
    color: #eee;
  }

  .models-overlay .models-card-title {
    font-size: 18px;
    font-weight: 700;
  }

  .models-overlay .model-box {
    padding: 24px 14px;
  }

  .models-overlay .model-box-icon {
    font-size: 36px;
  }

  .message {
    margin: 10px 0;
    padding: 10px 16px;
    border-radius: 12px;
    max-width: 80%;
    word-wrap: break-word;
    line-height: 1.5;
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }

  /* Holds the timestamp (left) and copy/edit/retry/save (right) --
     placed as the LAST child of .message so it sits below the actual
     content (text, chart, images) rather than floating vertically-
     centered mid-bubble regardless of how tall the content is, which is
     how these previously behaved under .message's old row-flex +
     align-items:center layout. */
  .message-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
  }

  .message-actions-buttons {
    display: flex;
    align-items: center;
    gap: 6px;
  }

  .message-timestamp {
    font-size: 10.5px;
    opacity: 0.55;
    white-space: nowrap;
  }

  .user-message {
    background-color: #d9a441;
    color: #111;
    align-self: flex-end;
    text-align: right;
  }

  .bot-message {
    background-color: #222;
    align-self: flex-start;
    text-align: left;
  }

  /* .message.rtl-message (two classes) deliberately used for guaranteed
     specificity over the single-class .bot-message/.user-message rules
     above, regardless of CSS source order. */
  .message.rtl-message {
    text-align: right;
  }

  /* Code and math notation are conventionally left-to-right even inside
     an RTL document (this is standard practice, not a stylistic
     choice) -- flipping actual code syntax or mathematical formulas
     would make them genuinely harder to read, not just look unusual. */
  .rtl-message .code-block,
  .rtl-message .code-block pre,
  .rtl-message .code-block code,
  .rtl-message .katex,
  .rtl-message .math-display {
    direction: ltr;
    text-align: left;
  }

  .copy-btn {
    background: none;
    border: none;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.2s, transform 0.2s;
  }

  .copy-btn svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: white;
    stroke-width: 2;
  }

  /* A confirmed real contrast bug this fixes: the copy button on user
     messages was using the same hardcoded white stroke as on bot
     messages -- fine against the dark bot-message background, but
     nearly invisible against the light gold user-message background,
     while the edit button right next to it (dark #111) was clearly
     visible. Matches the edit button's color here instead. */
  .user-message .copy-btn svg {
    stroke: #111;
  }

  .copy-btn:hover {
    opacity: 1;
    transform: scale(1.1);
  }

  .message-listen-btn {
    background: none;
    border: none;
    cursor: pointer;
    opacity: 0.7;
    color: white;
    transition: opacity 0.2s, transform 0.2s, color 0.2s;
  }

  /* Same contrast reasoning already applied to copy/edit -- white reads
     fine on the dark bot-message background but is nearly invisible on
     the light gold user-message background. */
  .user-message .message-listen-btn {
    color: #111;
  }

  .message-listen-btn svg {
    width: 20px;
    height: 20px;
  }

  .message-listen-btn:hover {
    opacity: 1;
    transform: scale(1.1);
  }

  /* Active while this specific message is actually being read aloud --
     gold accent on bot messages (dark background, gold reads clearly
     there). A confirmed real bug this fixes: that same gold was ALSO
     being used on user messages, whose background is that same gold
     color -- making the button effectively invisible/blended into the
     background the whole time it was actually reading, exactly when
     it most needs to be visible. */
  .message-listen-btn.speaking {
    color: #d9a441;
    opacity: 1;
  }

  .user-message .message-listen-btn.speaking {
    color: #0e7c66;
  }

  .attachment-preview {
    flex-wrap: wrap;
    gap: 6px;
    padding: 8px 12px;
    background: #000;
    border-top: 1px solid #333;
  }

  .attachment-chip {
    display: flex;
    align-items: center;
    gap: 6px;
    background: #1a1a1a;
    border: 1px solid #333;
    border-radius: 8px;
    padding: 4px 6px;
  }

  .attachment-chip img {
    width: 32px;
    height: 32px;
    object-fit: cover;
    border-radius: 5px;
    flex-shrink: 0;
  }

  .attachment-chip span {
    color: #ccc;
    font-size: 12px;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .attachment-remove-btn {
    background: none;
    border: none;
    color: #888;
    cursor: pointer;
    font-size: 14px;
    padding: 2px 6px;
    flex-shrink: 0;
  }

  .attachment-remove-btn:hover {
    color: #e05252;
  }

  .chat-input {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-top: 1px solid #333;
    background: #000;
    padding: 8px 12px;
  }

  .ai-disclaimer {
    text-align: center;
    font-size: 11px;
    color: #666;
    background: #000;
    padding: 2px 12px 8px 12px;
  }

  .options {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
  }

  .options button {
    background: #333;
    color: white;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    font-size: 20px;
    padding: 6px 10px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .options button.active {
    background: #d9a441;
    color: #111;
  }

  .options button:hover {
    background: #444;
  }

  .chat-input input {
    flex: 1;
    margin: 0 12px;
    border: none;
    padding: 12px;
    font-size: 16px;
    outline: none;
    background: #000;
    color: white;
    border-radius: 8px;
  }

  .chat-input input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }

  .chat-input input[type="search"]::-webkit-search-cancel-button,
  .chat-input input[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
  }

  /* Real-time autofill detection: browsers apply a distinct internal
     style (:-webkit-autofill) the instant they autofill a field. Tying
     a harmless CSS animation to that pseudo-class lets JS listen for the
     animationstart event and react IMMEDIATELY when autofill happens,
     rather than guessing at timing with setTimeout -- the actual fix for
     autofill that kept re-appearing after our earlier timed clears. */
  @keyframes onAutoFillStart {
    from { opacity: 1; }
    to { opacity: 1; }
  }
  #user-input:-webkit-autofill {
    animation-name: onAutoFillStart;
  }

  .options button:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }

  .attach-wrapper {
    position: relative;
  }

  #attachBtn {
    background: #333;
    color: white;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    padding: 6px 10px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  #attachBtn:hover {
    background: #444;
  }

  #attachBtn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }

  /* Overrides modelsBtn's own inline background (set directly in the
     HTML) while Live Chat is active -- uses an explicit class rather
     than relying solely on the :disabled pseudo-class, and !important
     since an inline style attribute otherwise always wins over any
     external stylesheet rule regardless of selector specificity. A
     genuinely dimmed/desaturated BLUE (not grey) -- still recognizably
     the same button, just visibly faded/inactive. */
  #modelsBtn.live-chat-dimmed {
    background: #5b6478 !important;
    color: #c7cdd9 !important;
    opacity: 1 !important;
    cursor: not-allowed;
  }

  .attach-menu {
    position: absolute;
    bottom: 100%;
    left: 0;
    margin-bottom: 6px;
    width: 190px; /* definite width, not auto -- lets the buttons' width:100% below resolve against something concrete instead of an ambiguous shrink-to-fit parent */
    background: #2a2a2a;
    border: 1px solid #d9a441;
    border-radius: 8px;
    padding: 6px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.5);
    z-index: 20;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
  }

  .attach-menu button {
    width: 100%;
    box-sizing: border-box;
    background: none;
    border: none;
    color: #ddd;
    font-size: 13px;
    text-align: left;
    padding: 8px 10px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: flex-start; /* .options button (an ancestor, since .attach-menu lives inside .attach-wrapper inside .options) sets justify-content:center for its own icon-only square buttons -- same CSS specificity as this rule, so without an explicit override here that value was winning and centering every row instead of left-aligning it */
    white-space: nowrap;
  }

  .attach-menu-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    min-width: 22px; /* flex items default to min-width:auto, which would otherwise let content override the explicit width -- kept as a safeguard even though the SVGs below are already a fixed 16x16 */
    margin-right: 6px;
    flex-shrink: 0;
    color: #ddd; /* the SVGs use stroke="currentColor" -- inherits normally, but set explicitly here since this span sits between the button's own color and the SVG */
  }

  .attach-menu button:hover {
    background: rgba(255, 255, 255, 0.1);
  }

  .message-retry-btn {
    background: none;
    border: none;
    color: white;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.2s, transform 0.2s;
  }

  .message-retry-btn:hover {
    opacity: 1;
    color: #d9a441;
    transform: rotate(-45deg);
  }

  .message-retry-btn svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
  }

  .message-edit-btn {
    background: none;
    border: none;
    color: #111;
    cursor: pointer;
    opacity: 0.6;
    transition: opacity 0.2s, transform 0.2s;
  }

  .message-edit-btn:hover {
    opacity: 1;
    transform: scale(1.1);
  }

  .message-edit-btn svg {
    width: 18px;
    height: 18px;
  }

  .message-edit-textarea {
    width: 100%;
    min-width: 220px;
    background: rgba(0, 0, 0, 0.12);
    color: #111;
    border: 1px solid rgba(0, 0, 0, 0.3);
    border-radius: 8px;
    padding: 8px 10px;
    font-family: inherit;
    font-size: inherit;
    line-height: 1.5;
    resize: none;
    overflow: hidden;
  }

  .message-edit-hint {
    font-size: 11px;
    color: #333;
    opacity: 0.75;
    margin-top: 4px;
    text-align: right;
  }

  /* Only shown on bot messages that actually contain a chart or images
     (see addMessage) -- downloads the chart as a PNG, or each image in
     a web-images gallery, to the user's device. */
  .message-save-btn {
    background: none;
    border: none;
    color: white;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.2s, transform 0.2s;
  }

  .message-save-btn:hover {
    opacity: 1;
    color: #d9a441;
    transform: scale(1.15);
  }

  .message-save-btn svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
  }

  #sendBtn {
    background: #d9a441;
    color: #111;
    border: none;
    border-radius: 50%;
    width: 40px;
    height: 40px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 0.15s ease, transform 0.15s ease;
  }

  #sendBtn:hover {
    opacity: 0.9;
    transform: scale(1.05);
  }

  /* Applied via JS while a message is being sent -- swaps the button
     into a "stop" affordance (red, square icon) instead of disabling
     it outright, since clicking it in this state actually cancels the
     in-flight request rather than doing nothing. */
  #sendBtn.stop-state {
    background: #e05252;
    color: white;
  }

  .thinking-logo {
    width: 22px;
    height: 22px;
    display: inline-block;
    vertical-align: middle;
    background: transparent;
    animation: logoThinkingPulse 1.8s ease-in-out infinite;
  }

  /* Faster and punchier than the idle logoBreathe animation -- this one
     needs to read clearly as "actively working" in a small, glanceable
     size, not just gently alive. */
  @keyframes logoThinkingPulse {
    0%, 100% {
      transform: scale(0.85);
      opacity: 0.7;
    }
    50% {
      transform: scale(1.3);
      opacity: 1;
    }
  }

  .message.thinking {
    background: transparent;
    padding: 4px 0;
  }

  .thinking-row {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  @media (max-width: 768px) {
    .chat-header {
      font-size: 17px;
      padding: 12px 8px;
    }
    #backToSiteBtn {
      font-size: 11px;
      padding: 5px 8px;
    }
    .app-layout {
      flex-direction: column;
    }
    .sidebar {
      width: 100%;
      height: 40vh;
      border-right: none;
      border-bottom: 1px solid #d9a441;
    }
  }

  .bot-message a {
    color: #d9a441;
    font-weight: bold;
    text-decoration: underline;
  }

  .bot-message h1 {
    font-size: 21px;
    font-weight: bold;
    margin: 4px 0 10px 0;
    line-height: 1.3;
  }

  .bot-message h2 {
    font-size: 18px;
    font-weight: bold;
    margin: 10px 0 6px 0;
    line-height: 1.3;
  }

  .bot-message h3 {
    font-size: 15.5px;
    font-weight: bold;
    margin: 8px 0 4px 0;
    line-height: 1.3;
    opacity: 0.95;
  }

  .bot-message p {
    font-size: 15px;
    margin: 6px 0;
  }

  .bot-message ul, .bot-message ol {
    margin: 6px 0;
    padding-left: 22px;
  }

  .price-chart {
    width: 100%;
    max-width: 640px;
    height: 280px;
    margin: 10px 0;
    position: relative;
  }

  /* MODELS card contents (title/grid/boxes) -- shared by the MODELS
     overlay's top-level model grid and its Prediction Model submarket
     grid (see .models-overlay above for the overlay/positioning
     itself). */
  .models-card-title {
    font-size: 15px;
    font-weight: 700;
    color: #aaa;
    margin-bottom: 10px;
  }

  .models-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(157px, 1fr));
    gap: 8px;
  }

  .model-box {
    border-radius: 10px;
    padding: 14px 12px;
    text-align: center;
    border: 1px solid #333;
    background: #1a1a1a;
    transition: transform 0.15s, border-color 0.15s;
  }

  .model-box-active {
    cursor: pointer;
    border-color: #2a4a8a;
  }

  .model-box-active:hover {
    transform: translateY(-2px);
    border-color: #1d4ed8;
  }

  .model-box-disabled {
    cursor: not-allowed;
    opacity: 0.45;
  }

  .model-box-icon {
    font-size: 26px;
    margin-bottom: 8px;
  }

  .model-box-name {
    font-size: 15px;
    font-weight: 700;
    color: #eee;
  }

  .model-box-status {
    font-size: 13px;
    color: #888;
    margin-top: 3px;
  }

  /* Coming Soon banner -- shown as a message in the chat feed when a
     not-yet-built model is selected from the AI MODELS picker. Large
     and centered on purpose (a real "banner"), sitting against that
     model's own dedicated chat-area background color. */
  .coming-soon-banner {
    width: 100%;
    max-width: 480px;
    margin: 12px auto;
    padding: 32px 24px;
    text-align: center;
    border: 1px solid #333;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.03);
  }

  .coming-soon-icon {
    font-size: 46px;
    margin-bottom: 10px;
  }

  .coming-soon-name {
    font-size: 17px;
    font-weight: 700;
    color: #eee;
    margin-bottom: 12px;
  }

  .coming-soon-badge {
    display: inline-block;
    background: #1d4ed8;
    color: #fff;
    font-weight: 700;
    font-size: 14px;
    letter-spacing: 0.5px;
    padding: 8px 20px;
    border-radius: 20px;
    margin-bottom: 14px;
  }

  .coming-soon-note {
    font-size: 13px;
    color: #999;
    line-height: 1.5;
  }

  .response-table-wrap {
    max-width: 100%;
    overflow-x: auto;
    margin: 10px 0;
  }

  .code-block {
    margin: 10px 0;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #333;
    background: #282c34; /* matches highlight.js's atom-one-dark theme background, so the header bar and code body blend seamlessly */
  }

  .code-block-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 12px;
    background: #21252b;
    border-bottom: 1px solid #333;
    font-size: 12px;
  }

  .code-block-lang {
    color: #999;
    text-transform: lowercase;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  }

  .code-block-copy-btn {
    background: none;
    border: none;
    color: #999;
    cursor: pointer;
    font-size: 12px;
    padding: 2px 6px;
    border-radius: 4px;
    transition: background 0.15s ease, color 0.15s ease;
  }

  .code-block-copy-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: #eee;
  }

  .code-block pre {
    margin: 0;
    padding: 0;
  }

  .code-block pre code.hljs {
    padding: 12px;
    font-size: 13px;
    line-height: 1.5;
    font-family: "Consolas", "Monaco", "Courier New", monospace;
    overflow-x: auto;
    display: block;
    background: transparent; /* the .code-block container already provides the background */
  }

  .project-zip {
    margin: 10px 0;
    padding: 12px 14px;
    border-radius: 8px;
    border: 1px solid #333;
    background: #1e1e1e;
    max-width: 400px;
  }

  .project-zip-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 8px;
  }

  .project-zip-title {
    font-weight: bold;
    color: #eee;
  }

  .project-zip-count {
    font-size: 11.5px;
    color: #999;
    white-space: nowrap;
  }

  .project-zip-files {
    background: #1a1a1a;
    border: 1px solid #333;
    border-radius: 6px;
    padding: 8px 10px;
    margin-bottom: 10px;
    max-height: 160px;
    overflow-y: auto;
  }

  .project-zip-file {
    font-family: "Consolas", "Monaco", "Courier New", monospace;
    font-size: 12.5px;
    color: #ccc;
    padding: 2px 0;
  }

  .project-zip-download-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    background: #d9a441;
    color: #111;
    border: none;
    border-radius: 6px;
    padding: 8px 14px;
    font-size: 13px;
    font-weight: bold;
    cursor: pointer;
    transition: opacity 0.15s ease;
  }

  .project-zip-download-btn:hover {
    opacity: 0.9;
  }

  /* KaTeX renders with a default black text color, invisible against
     this app's dark bot-message background -- forces it to inherit the
     surrounding light text color instead. */
  .bot-message .katex {
    color: #eee;
  }

  .math-display {
    margin: 10px 0;
    overflow-x: auto;
    text-align: center;
  }

  .response-table {
    border-collapse: collapse;
    width: 100%;
    font-size: 13.5px;
  }

  .response-table th,
  .response-table td {
    border: 1px solid #333;
    padding: 6px 10px;
    text-align: left;
    white-space: nowrap;
  }

  .response-table th {
    background: #2a2a2a;
    color: #d9a441;
    font-weight: bold;
  }

  .response-table tr:nth-child(even) td {
    background: rgba(255, 255, 255, 0.03);
  }

  .web-images {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 8px;
    max-width: 640px;
    margin: 10px 0;
  }

  .web-images a {
    display: block;
    position: relative;
    border-radius: 8px;
    overflow: hidden;
    aspect-ratio: 1 / 1;
    background: #1a1a1a;
    text-decoration: none;
  }

  .web-images img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.15s ease;
  }

  .web-images a:hover img {
    transform: scale(1.05);
  }

  .web-images .web-image-source {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(transparent, rgba(0,0,0,0.75));
    color: #fff;
    font-size: 10px;
    padding: 12px 6px 4px 6px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .venn-chart {
    max-width: 560px;
    margin: 10px 0;
  }

  .venn-chart svg {
    display: block;
    max-width: 100%;
    height: auto;
    margin: 0 auto;
  }

  .venn-chart-title {
    font-weight: bold;
    text-align: center;
    margin-bottom: 6px;
    color: #ddd;
  }

  .venn-chart-legend {
    margin-top: 10px;
    font-size: 12.5px;
    color: #ccc;
  }

  .venn-chart-legend-row {
    display: flex;
    gap: 6px;
    margin: 3px 0;
    line-height: 1.4;
  }

  .venn-chart-legend-swatch {
    flex-shrink: 0;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    margin-top: 2px;
  }

  .auth-gate {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: #111;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow-y: auto;
    padding: 20px;
    box-sizing: border-box;
  }

  .edit-account-modal {
    position: fixed;
    inset: 0;
    z-index: 10001;
    background: rgba(0,0,0,0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow-y: auto;
    padding: 20px;
    box-sizing: border-box;
  }

  .edit-account-modal .auth-box {
    background: #1a1a1a;
    border: 1px solid #d9a441;
    border-radius: 12px;
  }

  .privacy-row {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: 8px;
    text-align: left;
  }

  .privacy-row input {
    margin-top: 2px;
    flex-shrink: 0;
  }

  .privacy-row label {
    color: #aaa;
    font-size: 10px;
    line-height: 1.4;
    cursor: pointer;
  }

  .auth-box {
    text-align: center;
    max-width: 360px;
    width: 100%;
    padding: 20px;
  }

  .auth-logo {
    width: 64px;
    height: auto;
    margin-bottom: 12px;
    animation: logoBreathe 2.4s ease-in-out infinite;
  }

  /* A clearly visible scale+glow pulse -- an earlier, more subtle
     version (4% over 4s) turned out to be too faint to actually
     notice, so this uses a bigger swing (12%) and a shorter cycle
     (2.5s) instead. Paused automatically for anyone with
     motion-sensitivity preferences set at the OS level, see
     prefers-reduced-motion below. */
  @keyframes logoBreathe {
    0%, 100% {
      transform: scale(1);
      filter: brightness(1);
    }
    50% {
      transform: scale(1.25);
      filter: brightness(1.3);
    }
  }

  .auth-box h2 {
    color: white;
    margin: 0 0 20px 0;
  }

  #micBtn {
    background: #d9a441;
    color: #111;
    border: none;
    border-radius: 50%;
    width: 40px;
    height: 40px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    margin-right: 8px;
    transition: background 0.15s ease, transform 0.15s ease;
  }

  #micBtn:hover {
    opacity: 0.9;
    transform: scale(1.05);
  }

  #micBtn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    transform: none;
  }

  /* Pill-shaped rather than round (the mic button) since it shows an
     actual word, not just an icon. */
  #liveChatBtn {
    background: #3b7dd8;
    color: white;
    border: none;
    border-radius: 20px;
    height: 40px;
    padding: 0 14px;
    font-size: 12px;
    font-weight: bold;
    letter-spacing: 0.5px;
    cursor: pointer;
    flex-shrink: 0;
    margin-right: 8px;
    transition: background 0.15s ease, transform 0.15s ease;
  }

  #liveChatBtn:hover {
    background: #4a8be5;
  }

  #liveChatBtn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }

  /* Stays the same blue while active (not switching to red) -- the
     pulsing animation alone is enough to show it's live, so the
     always-blue identity of this specific button stays consistent
     whether idle or running. */
  #liveChatBtn.live-active {
    animation: liveChatBtnPulse 1.6s ease-in-out infinite;
  }

  @keyframes liveChatBtnPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(59, 125, 216, 0.6); }
    50% { box-shadow: 0 0 0 8px rgba(59, 125, 216, 0); }
  }

  /* Sits directly over the chat box ONLY while live chat is active (see
     toggleLiveChat) -- a dark scrim with the animated logo reacting to
     real mic input, so the chat log underneath isn't competing for
     attention while a live conversation is actually happening. inset:0
     resolves against .chat-box-wrapper (its nearest positioned
     ancestor, see the HTML) -- confirmed real bug this fixes: it used
     to resolve against .chat-container instead, which also spans the
     input bar row below, so the scrim visually covered AND functionally
     blocked clicks on the text input, attach button, and MODELS/mic/
     LIVE buttons for the entire duration of every live session. */
  #liveChatVisualizer {
    position: absolute;
    inset: 0;
    background: rgba(10, 10, 10, 0.94);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    z-index: 20;
    border-radius: inherit;
  }

  #liveChatCloseBtn {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border: none;
    font-size: 16px;
    cursor: pointer;
    transition: background 0.15s ease;
  }

  #liveChatCloseBtn:hover {
    background: rgba(255, 255, 255, 0.2);
  }

  #liveChatMuteBtn {
    position: absolute;
    top: 16px;
    left: 16px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease;
  }

  #liveChatMuteBtn:hover {
    background: rgba(255, 255, 255, 0.2);
  }

  /* Applied while the mic is actually muted (JS sets this alongside
     disabling the real audio track, not just as decoration) -- red, the
     same "something is off/paused" visual language used elsewhere. */
  #liveChatMuteBtn.muted {
    background: #e05252;
  }

  /* transform-origin centered so the pulse (applied via JS, scaling
     this element based on real mic volume) grows/shrinks evenly from
     the middle rather than drifting toward a corner. */
  #liveChatLogoSvg {
    width: 55%;
    max-width: 220px;
    transform-origin: center;
    transition: transform 0.15s ease-out;
  }

  /* Base fill is overridden per-frame by JS (see drawLiveChatVisualizer)
     -- this is just the fallback shown for one instant before the first
     animation frame runs. Transition smooths the color changes between
     frames into a continuous shift rather than a hard flicker. */
  .live-logo-square {
    fill: #b7decc;
    transition: fill 0.2s ease-out, filter 0.2s ease-out;
  }

  #liveChatStatusLabel {
    color: #d9a441;
    font-size: 14px;
    font-weight: bold;
    letter-spacing: 0.5px;
  }

  /* Applied via JS the instant recording actually starts (real
     MediaRecorder state, not just a click) -- red + pulsing, the same
     visual language as a phone's native recording indicator. */
  #micBtn.mic-recording {
    background: #e05252;
    color: white;
    animation: micPulse 1.2s ease-in-out infinite;
  }

  @keyframes micPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(224, 82, 82, 0.5); }
    50% { box-shadow: 0 0 0 8px rgba(224, 82, 82, 0); }
  }

  /* Each bar's height is set directly from real mic volume via JS
     (see updateMicWaveform) -- the transition here is what turns those
     discrete updates into a smooth, organic-looking wave motion rather
     than a jumpy bar chart. */
  .mic-wave-bar {
    width: 4px;
    height: 6px;
    border-radius: 2px;
    background: #3b82f6;
    transition: height 0.09s ease-out;
  }

  /* Applied while the recorded/uploaded audio is being sent to the
     backend for transcription -- distinct from mic-recording so the
     person can tell "still capturing" from "now processing" apart. */
  #micBtn.mic-transcribing {
    background: #666;
    cursor: wait;
  }

  .auth-panel input[type="email"],
  .auth-panel input[type="password"],
  .auth-panel input[type="text"] {
    width: 100%;
    box-sizing: border-box;
    padding: 12px;
    font-size: 15px;
    border: 1px solid #444;
    border-radius: 8px;
    background: #000;
    color: white;
    margin-bottom: 10px;
  }

  .auth-panel select {
    width: 100%;
    box-sizing: border-box;
    padding: 12px;
    font-size: 15px;
    border: 1px solid #444;
    border-radius: 8px;
    background: #000;
    color: white;
    margin-bottom: 10px;
  }

  .auth-panel hr {
    border: none;
    border-top: 1px solid #333;
    margin: 18px 0;
  }

  .name-fields-row {
    display: flex;
    gap: 10px;
  }

  .name-fields-row input[type="text"] {
    width: 50%;
  }

  .password-field-row {
    display: flex;
    gap: 8px;
    margin-bottom: 10px;
  }

  .password-field-row input[type="password"],
  .password-field-row input[type="text"] {
    flex: 1;
    min-width: 0; /* without this, flex items refuse to shrink below their content's natural width, letting the Show/Hide button crowd the input down to almost nothing */
    margin-bottom: 0;
  }

  .password-field-row button.show-password-btn {
    flex-shrink: 0;
    width: 44px; /* overrides .auth-panel button's width:100%, which otherwise wins here due to higher CSS specificity and was crowding out the password input next to it */
    height: 44px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.1);
    color: #ccc;
    border: 1px solid #444;
    border-radius: 8px;
    font-weight: normal;
    margin-top: 0;
    cursor: pointer;
  }

  .show-password-btn:hover {
    background: rgba(255, 255, 255, 0.2);
  }

  .auth-panel button {
    width: 100%;
    padding: 12px;
    font-size: 16px;
    font-weight: bold;
    background: #d9a441;
    color: #111;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    margin-top: 4px;
  }

  .auth-panel button:hover {
    opacity: 0.9;
  }

  .auth-instructions {
    color: #ccc;
    font-size: 13px;
    margin: 0 0 14px 0;
  }

  .terms-check {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    text-align: left;
    color: #ccc;
    font-size: 13px;
    margin: 6px 0 12px 0;
    cursor: pointer;
  }

  .terms-check input {
    margin-top: 3px;
    flex-shrink: 0;
  }

  .terms-check a {
    color: #d9a441;
  }

  .auth-error {
    color: #e05252;
    font-size: 13px;
    min-height: 16px;
    margin: 8px 0 0 0;
  }

  .auth-success {
    color: #6fbf6f;
    font-size: 13px;
    min-height: 16px;
    margin: 4px 0 0 0;
  }

  .auth-links {
    text-align: right;
    margin: 8px 0 0 0;
  }

  .auth-links a, .auth-switch a {
    color: #d9a441;
    font-size: 13px;
    text-decoration: none;
  }

  .auth-links a:hover, .auth-switch a:hover {
    text-decoration: underline;
  }

  .auth-switch {
    color: #999;
    font-size: 13px;
    margin: 16px 0 0 0;
  }
