/* ============================================================
   SAFi Chatbot — v1.7.0
   Clean & Premium Design
   ============================================================ */

:root {
    --safi-brand:          #16a34a;
    --safi-brand-mid:      #15803d;
    --safi-brand-dark:     #14532d;
    --safi-brand-xlight:   #f0fdf4;
    --safi-brand-glow:     rgba(22, 163, 74, 0.28);

    --safi-surface:        #ffffff;
    --safi-messages-bg:    #f9f9f9;
    /* One step darker than the message canvas, so the header reads as a band
       without a colour change doing the work. */
    --safi-header-bg:      #f3f4f6;
    --safi-border:         #e5e7eb;
    --safi-border-light:   #f3f4f6;

    --safi-text-primary:   #111827;
    --safi-text-secondary: #374151;
    --safi-text-muted:     #6b7280;
    --safi-text-faint:     #9ca3af;

    --safi-radius-window:  20px;
    --safi-radius-bubble:  18px;
    --safi-radius-input:   24px;

    --safi-shadow-window:  0 24px 64px rgba(0, 0, 0, 0.16), 0 6px 20px rgba(0, 0, 0, 0.08);
    --safi-shadow-bubble:  0 1px 4px rgba(0, 0, 0, 0.07);
    --safi-shadow-button:  0 4px 18px var(--safi-brand-glow), 0 2px 6px rgba(0, 0, 0, 0.14);
    --safi-shadow-send:    0 2px 10px var(--safi-brand-glow);

    --safi-header-gradient: linear-gradient(150deg, var(--safi-brand-mid) 0%, var(--safi-brand-dark) 100%);
}


/* ============================================================
   TOGGLE BUTTON
   ============================================================ */

#safi-chat-container {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 9999;
}

/* Pulse ring — fires 3× on load, then stops */
#safi-chat-container::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--safi-brand);
    animation: safi-ring-pulse 2.2s ease-out 3;
    pointer-events: none;
}

@keyframes safi-ring-pulse {
    0%   { transform: scale(1);    opacity: 0.55; }
    70%  { transform: scale(1.55); opacity: 0; }
    100% { transform: scale(1.55); opacity: 0; }
}

.safi-chat-button {
    position: relative;
    background: var(--safi-header-gradient);
    color: white;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    border: none;
    box-shadow: var(--safi-shadow-button);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.2s ease;
}

.safi-chat-button:hover {
    transform: scale(1.1);
    box-shadow: 0 6px 24px var(--safi-brand-glow), 0 3px 8px rgba(0,0,0,0.18);
}

.safi-chat-button svg { width: 28px; height: 28px; }

.safi-chat-icon-close { display: none; }
.safi-chat-button.active .safi-chat-icon-open  { display: none; }
.safi-chat-button.active .safi-chat-icon-close { display: block; }


/* ============================================================
   CHAT WINDOW
   ============================================================ */

/* Backdrop. A centered panel only reads as a modal if the page behind it
   recedes, so the dim layer is part of the component, not decoration. */
#safi-chat-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    z-index: 9997;
}

#safi-chat-backdrop.active {
    display: block;
    animation: safi-backdrop-in 0.2s ease both;
}

@keyframes safi-backdrop-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Centered modal. Sized in one place: a comfortable reading column that grows
   with the viewport but never runs to the edges on a laptop. */
.safi-chat-window {
    display: none;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(94vw, 560px);
    height: min(84vh, 720px);
    background: var(--safi-surface);
    border-radius: var(--safi-radius-window);
    box-shadow: var(--safi-shadow-window);
    flex-direction: column;
    z-index: 9998;
    font-family: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;
    overflow: hidden;
    border: 1px solid rgba(0, 0, 0, 0.06);
}

/* Rise-and-settle from the centre. The keyframes MUST carry the centering
   translate: `forwards` holds the final frame, so a bare scale() here would
   drop the panel to the top-left corner once the animation ended. */
@keyframes safi-reveal {
    from { opacity: 0; transform: translate(-50%, -46%) scale(0.96); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

.safi-chat-window.active {
    display: flex;
    animation: safi-reveal 0.26s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@media (prefers-reduced-motion: reduce) {
    .safi-chat-window.active { animation: none; }
    #safi-chat-backdrop.active { animation: none; }
}

/* Fullscreen has to unset the centering, transform included. */
.safi-chat-window.fullscreen {
    top: 0;
    left: 0;
    transform: none;
    width: 100vw;
    height: 100vh;
    max-width: 100%;
    max-height: 100%;
    border-radius: 0;
    border: none;
    animation: none;
}

/* While the modal is open the page behind it must not scroll under the
   backdrop. Set on <html> by the script and removed on close. */
html.safi-chat-open,
html.safi-chat-open body {
    overflow: hidden;
}

/* The launcher sits above the backdrop, so leaving it up would park a green
   circle on the dimmed page beside the modal. Fade it out while open: the
   header's close button, the backdrop and Escape all close the dialog. */
#safi-chat-container {
    transition: opacity 0.18s ease;
}

html.safi-chat-open #safi-chat-container {
    opacity: 0;
    pointer-events: none;
}

/* Phones: a near-full-height sheet, clear of the notch and the home indicator.
   A 560px-wide centered card on a small screen wastes the edges. */
@media (max-width: 640px) {
    .safi-chat-window {
        width: 100vw;
        height: 100%;
        max-width: 100%;
        border-radius: 0;
        border: none;
        padding-top: env(safe-area-inset-top);
        padding-bottom: env(safe-area-inset-bottom);
    }
}


/* ============================================================
   HEADER
   ============================================================ */

/* A neutral grey band instead of the dark green gradient. The saturated header
   dominated a centered modal and fought the message area below it. Grey keeps
   the chrome quiet and leaves green to mean something: the status dot, the send
   button, the agent name. The hairline separates it from the messages now that
   there is no strong colour step. */
.safi-chat-header {
    background: var(--safi-header-bg);
    border-bottom: 1px solid var(--safi-border);
    padding: 14px 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
}

.safi-chat-header-content {
    display: flex;
    align-items: center;
    gap: 11px;
}

/* Title + subtitle on one line */
/* Name over tagline, both flush left on the same edge. */
.safi-chat-header-content > div {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
    min-width: 0;
}

/* Dark type on the pale band. The name carries the branding now that the logo
   is gone, so it gets the brand's darkest green rather than plain black. */
.safi-chat-title {
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--safi-brand-dark);
    margin: 0;
    padding: 0;
    letter-spacing: -0.01em;
    line-height: 1.1;
}

/* Flush with the name above it. This was a flex row with a leading status dot,
   which indented the tagline ~11px past the "S" in SAFi. The dot is gone: it
   implied a human agent's presence on a service that is always available, and it
   was the one green mark in the header doing no work. */
.safi-chat-subtitle {
    font-size: 0.72rem;
    color: var(--safi-text-muted);
    margin: 0;
    padding: 0;
    line-height: 1.2;
}

.safi-chat-header-buttons {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* Quiet by default on the pale band, filling in on hover. The old translucent
   white pills are invisible on a light background. */
.safi-chat-header-button {
    background: transparent;
    border: none;
    padding: 6px;
    border-radius: 8px;
    cursor: pointer;
    color: var(--safi-text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, color 0.15s;
}

.safi-chat-header-button:hover {
    background: rgba(0, 0, 0, 0.06);
    color: var(--safi-brand-dark);
}

.safi-chat-header-button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(22, 163, 74, 0.35);
}

.safi-chat-header-button svg { width: 17px; height: 17px; }

.safi-icon-shrink { display: none; }
.fullscreen .safi-icon-expand { display: none; }
.fullscreen .safi-icon-shrink { display: block; }
.fullscreen .safi-chat-header { border-radius: 0; }


/* ============================================================
   MESSAGES AREA
   ============================================================ */

.safi-chat-messages {
    flex: 1;
    padding: 20px 16px 12px;
    overflow-y: auto;
    background: var(--safi-messages-bg);
    display: flex;
    flex-direction: column;
}

/* Thin, styled scrollbar */
.safi-chat-messages::-webkit-scrollbar { width: 4px; }
.safi-chat-messages::-webkit-scrollbar-track { background: transparent; }
.safi-chat-messages::-webkit-scrollbar-thumb {
    background: #d1d5db;
    border-radius: 999px;
}
.safi-chat-messages::-webkit-scrollbar-thumb:hover { background: #9ca3af; }


/* ============================================================
   MESSAGE BUBBLES
   ============================================================ */

.safi-message {
    display: flex;
    gap: 10px;
    margin-bottom: 14px;
    max-width: 88%;
}

.safi-ai   { align-self: flex-start; }
.safi-user { align-self: flex-end; flex-direction: row-reverse; }

/* Avatar */
.safi-avatar {
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    border-radius: 50%;
    overflow: hidden;
    margin-top: 2px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.12);
}

.safi-avatar img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border-radius: 50%;
}

/* ── Thinking state: the avatar itself carries the "in flight" signal ────────
   Same technique the main SAFi app uses on its own avatar: a rotating
   conic-gradient sits on a ::before behind the image, oversized (inset
   beyond 0) so the circular clip never shows a gap as it spins, with a
   thin surface-colour ring around the image itself to keep the two marks
   visually separate rather than blending into one blob.

   Scoped to the loading indicator only (showLoadingIndicator() adds this
   class), and that whole element is removed once the reply arrives or the
   request fails, so there is no teardown here and no way to leave a ring
   spinning after the turn ends. Status text stays a plain timed sequence
   (see showLoadingIndicator in the script) — this only changes what the
   avatar looks like while that text cycles. */
.safi-avatar.is-thinking {
    position: relative;
    padding: 3px;
    background: var(--safi-brand);
}

.safi-avatar.is-thinking::before {
    content: '';
    position: absolute;
    inset: -35%;
    background: conic-gradient(from 0turn,
        rgba(22, 163, 74, 0.15) 0turn,
        rgba(22, 163, 74, 0.95) 0.5turn,
        rgba(22, 163, 74, 0.15) 1turn);
    animation: safi-avatar-ring-sweep 1.15s linear infinite;
}

.safi-avatar.is-thinking img {
    position: relative;
    z-index: 1;
    box-shadow: 0 0 0 1.5px var(--safi-surface);
}

@keyframes safi-avatar-ring-sweep {
    to { transform: rotate(1turn); }
}

/* Rotation is the exact pattern that triggers vestibular symptoms, so it is
   replaced with a still ring that breathes, which still reads as "working". */
@media (prefers-reduced-motion: reduce) {
    .safi-avatar.is-thinking::before {
        animation: safi-avatar-ring-breathe 1.8s ease-in-out infinite;
    }

    @keyframes safi-avatar-ring-breathe {
        0%, 100% { opacity: 0.35; }
        50%      { opacity: 1; }
    }
}

/* Content wrapper */
.safi-content-wrapper {
    display: flex;
    flex-direction: column;
}

.safi-user .safi-content-wrapper { align-items: flex-end; }

/* The bubble itself */
.safi-chat-bubble {
    padding: 12px 16px;
    border-radius: var(--safi-radius-bubble);
    line-height: 1.6;
    word-break: break-word;
    /* 0.92rem -> 1rem. Nudged the padding with it so the bubble does not feel
       tighter at the larger size, and eased line-height slightly because 1.65
       reads loose once the text is bigger. */
    font-size: 1rem;
}

/* AI bubble — white card with soft shadow */
.safi-ai .safi-chat-bubble {
    background: var(--safi-surface);
    color: var(--safi-text-primary);
    border: 1px solid var(--safi-border);
    box-shadow: var(--safi-shadow-bubble);
    border-top-left-radius: 4px;
}

/* User bubble — rich gradient green */
.safi-user .safi-chat-bubble {
    background: linear-gradient(145deg, var(--safi-brand-mid) 0%, var(--safi-brand-dark) 100%);
    color: #ffffff;
    box-shadow: 0 2px 8px var(--safi-brand-glow);
    border-top-right-radius: 4px;
}

/* Markdown in bubbles */
.safi-chat-bubble p, .safi-chat-bubble ul, .safi-chat-bubble ol { margin-bottom: 0.5em; }
.safi-chat-bubble > *:last-child  { margin-bottom: 0; }
.safi-chat-bubble > *:first-child { margin-top: 0; }
.safi-chat-bubble ul { list-style-type: disc; padding-left: 20px; }
.safi-chat-bubble ol { padding-left: 20px; }

/* Links */
.safi-ai .safi-chat-bubble a   { color: var(--safi-brand); text-decoration: underline; }
.safi-user .safi-chat-bubble a { color: #ffffff; font-weight: 600; text-decoration: underline; }

/* Blockquote */
.safi-chat-bubble blockquote {
    border-left: 3px solid var(--safi-border);
    padding-left: 14px;
    margin: 0.5em 0;
    font-style: italic;
    color: var(--safi-text-muted);
}

/* Code blocks */
.safi-chat-bubble pre {
    background: #171717;
    color: #e5e7eb;
    padding: 14px 16px;
    border-radius: 10px;
    overflow-x: auto;
    font-family: "Fira Code", "Cascadia Code", ui-monospace, monospace;
    font-size: 0.85em;
    margin: 0.75em 0;
    line-height: 1.6;
}

.safi-chat-bubble code {
    background: #f3f4f6;
    color: #111827;
    padding: 2px 6px;
    border-radius: 5px;
    font-family: "Fira Code", "Cascadia Code", ui-monospace, monospace;
    font-size: 0.875em;
}

.safi-chat-bubble pre code {
    background: transparent;
    color: inherit;
    padding: 0;
    border-radius: 0;
}

/* Headings */
.safi-chat-bubble h1,
.safi-chat-bubble h2,
.safi-chat-bubble h3,
.safi-chat-bubble h4,
.safi-chat-bubble h5,
.safi-chat-bubble h6 {
    font-weight: 600;
    color: var(--safi-text-primary);
    margin-top: 1.1em;
    margin-bottom: 0.5em;
    line-height: 1.3;
}
.safi-chat-bubble h1 { font-size: 1.4rem; }
.safi-chat-bubble h2 { font-size: 1.2rem; }
.safi-chat-bubble h3 { font-size: 1.1rem; }
.safi-chat-bubble h4 { font-size: 1rem; }
.safi-chat-bubble h5 { font-size: 0.9rem; }
.safi-chat-bubble h6 { font-size: 0.82rem; }

/* Tables */
.safi-chat-bubble table {
    width: 100%;
    border-collapse: collapse;
    margin: 0.75em 0;
    font-size: 0.88em;
    border-radius: 8px;
    overflow: hidden;
}
.safi-chat-bubble th,
.safi-chat-bubble td { border: 1px solid var(--safi-border); padding: 8px 12px; text-align: left; }
.safi-chat-bubble th { background: #f9f9f9; font-weight: 600; }
.safi-chat-bubble tr:nth-child(even) { background: #fcfcfc; }


/* ============================================================
   INPUT FOOTER
   ============================================================ */

.safi-chat-footer {
    padding: 12px 14px 6px;
    border-top: 1px solid var(--safi-border-light);
    display: flex;
    align-items: flex-end;
    background: var(--safi-surface);
}

/* One bar holding the field and the send control, split by a divider rather
   than a gap. A gap between a rounded textarea and a floating circle still
   reads as two separate controls sitting near each other; a shared border
   reads as one control with two zones.

   align-items: stretch (not flex-end) is what makes the divider, the send
   control's left border set below, run the bar's full height automatically
   as the textarea grows for multi-line text, instead of staying a
   fixed-height line floating inside a taller bar.

   The bar owns the outer border and the focus ring; the textarea inside is
   transparent and ring-less, so focus lights the whole control rather than a
   box inside a box. */
.safi-chat-composer {
    flex: 1;
    display: flex;
    align-items: stretch;
    padding: 4px;
    background: var(--safi-surface);
    border: 1.5px solid var(--safi-border);
    border-radius: var(--safi-radius-input);
    transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.safi-chat-composer:focus-within {
    border-color: var(--safi-brand);
    box-shadow: 0 0 0 3px rgba(22, 163, 74, 0.12);
}

/* EU AI Act Art. 50(1) — permanent AI-interaction disclosure */
.safi-chat-disclosure {
    margin: 0;
    padding: 4px 14px 10px;
    background: var(--safi-surface);
    color: var(--safi-text-faint);
    font-size: 11px;
    line-height: 1.4;
    text-align: center;
}

/* The field itself: no chrome of its own, the capsule carries it. */
.safi-chat-input {
    flex: 1;
    min-width: 0;
    resize: none;
    border: none;
    background: transparent;
    padding: 8px 6px 8px 8px;
    font-size: 0.9375rem;
    font-family: inherit;
    max-height: 120px;
    line-height: 1.5;
    color: var(--safi-text-primary);
}

.safi-chat-input:focus {
    outline: none;
    box-shadow: none;
}

.safi-chat-input::placeholder { color: var(--safi-text-faint); }
.safi-chat-input:disabled { opacity: 0.5; cursor: not-allowed; }

/* Send control: the bar's end-cap, not a floating circle. A flat,
   transparent version of this read as too quiet to register as a button at
   all, so it is filled solid brand green instead. The fill itself is the
   divider now, no separate border-left needed; the right corners pick up a
   radius nested inside the bar's own (input radius minus the bar's own
   A round button floating at the right end of the bar. align-self: center
   overrides the composer's align-items: stretch so the circle keeps its
   shape while the textarea grows for multi-line text. */
.safi-chat-send {
    flex-shrink: 0;
    align-self: center;
    width: 34px;
    height: 34px;
    margin-left: 6px;
    padding: 0;
    background: var(--safi-brand);
    color: #ffffff;
    border: none;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color 0.18s ease;
}

.safi-chat-send:hover:not(:disabled) {
    background: var(--safi-brand-mid);
}

.safi-chat-send:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.5);
}

/* Disabled is the resting state until something is typed, so it has to look
   deliberate rather than broken: a neutral fill, no shadow, no motion. */
.safi-chat-send:disabled {
    background: #d1d5db;
    color: #ffffff;
    cursor: default;
}

.safi-chat-send svg {
    width: 17px;
    height: 17px;
}


/* ============================================================
   v1.6.0+ COMPONENTS
   ============================================================ */

/* Flex utility */
.safi-flex-1 { flex: 1; min-width: 0; }

/* --- Suggestion chips ------------------------------------ */
.safi-suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin: -4px 0 14px 40px;
}

.safi-suggestion-chip {
    background: var(--safi-brand-xlight);
    border: 1px solid #bbf7d0;
    color: var(--safi-brand-mid);
    border-radius: 999px;
    padding: 6px 13px;
    font-size: 0.8rem;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.1s;
    line-height: 1.4;
    font-weight: 500;
}

.safi-suggestion-chip:hover {
    background: #dcfce7;
    border-color: #86efac;
    transform: translateY(-1px);
}

/* --- Message timestamps ---------------------------------- */
.safi-timestamp {
    display: block;
    font-size: 0.68rem;
    color: var(--safi-text-faint);
    margin-top: 5px;
    line-height: 1;
    padding: 0 2px;
}

.safi-user .safi-timestamp { text-align: right; }

/* --- Phase-aware loading indicator ---------------------- */
/* No bubble chrome: matches the main app's own .thinking-container, which
   is background: transparent in light theme (only a faint tint in dark
   theme, not replicated here since this widget's dots/text already carry
   plenty of colour on their own). Overrides the background/border/shadow
   .safi-chat-bubble normally gives every AI message, so the dots and text
   just sit in the message row rather than inside a pill. With no visible
   bubble shape, a tail pointing at one no longer means anything, so the
   speech-bubble tail this element briefly had is gone along with it. */
.safi-loading-bubble {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 2px 0;
    background: transparent;
    border: none;
    box-shadow: none;
}

/* Matches the main app's #thinking-status: a slow opacity breathe rather
   than a flat static label, so the text itself reads as still in progress
   between one phase word and the next. */
.safi-loading-text {
    font-size: 0.82rem;
    color: var(--safi-text-muted);
    font-style: italic;
    white-space: nowrap;
    transition: opacity 0.3s ease;
    animation: safi-text-breathe 2s infinite ease-in-out;
}

@keyframes safi-text-breathe {
    0%, 100% { opacity: 0.6; }
    50%      { opacity: 0.9; }
}

/* Matches the main app's .thinking-pulse-wave exactly: a scale-and-fade
   wave rather than popping from nothing to full size, staggered with
   negative delays so all three dots are already mid-cycle on the very
   first frame instead of starting in lockstep. */
.safi-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    background: var(--safi-brand);
    border-radius: 50%;
    opacity: 0.4;
    animation: safi-pulse 1.4s infinite ease-in-out both;
}

.safi-dot:nth-child(1) { animation-delay: -0.32s; }
.safi-dot:nth-child(2) { animation-delay: -0.16s; }

@keyframes safi-pulse {
    0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
    40%           { transform: scale(1.1); opacity: 1; }
}

/* Matches the main app's .thinking-container: the whole bubble bobs gently
   while a turn is in flight, an ambient, slower-paced echo of the ring
   spinning on the avatar and the text breathing beside it. */
.safi-loading-bubble {
    animation: safi-float-gentle 4s ease-in-out infinite;
}

@keyframes safi-float-gentle {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-2px); }
}

/* --- Retry button ---------------------------------------- */
.safi-retry-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-top: 9px;
    background: none;
    border: 1px solid var(--safi-border);
    border-radius: 8px;
    padding: 5px 11px;
    font-size: 0.78rem;
    color: var(--safi-text-muted);
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.safi-retry-btn:hover {
    background: #f3f4f6;
    color: var(--safi-text-secondary);
    border-color: #9ca3af;
}

/* --- New chat + header icon sizing ---------------------- */
#safi-chat-new svg      { width: 16px; height: 16px; }

/* ── Dark mode ────────────────────────────────────────────────────────────────
   Follows the visitor's OS setting.

   Palette per the SAFi branding standard: green is the only accent, and the
   surfaces run down the NEUTRAL black-to-white axis. This block previously used
   a warm cream text (#F8F6F1) on cool blue-slate surfaces (#1E2432 / #161B26),
   two off-palette families in one widget, justified as matching the marketing
   site's dark theme. That claim did not hold up: the site theme's own palette is
   navy and orange, so the values matched nothing and only made the widget read
   as a different product from the app it represents.

   Mostly a token swap — the widget was already built on custom properties. The
   rules after the :root block are the handful of places that hardcode a light
   value and therefore cannot be reached by swapping tokens.

   The brand greens are deliberately unchanged: #16a34a on #171717 clears 4.5:1,
   and the header gradient reads well on dark, so the widget keeps its identity.
------------------------------------------------------------------------------ */
@media (prefers-color-scheme: dark) {
    :root {
        /* Panel sits slightly lifted off the page; the message area drops back
           to the page colour so the header and footer frame it. */
        --safi-surface:        #171717;
        --safi-messages-bg:    #0a0a0a;
        /* Lifted a step above the panel surface, the same relationship the light
           theme has in reverse. */
        --safi-header-bg:      #1f1f1f;

        --safi-border:         rgba(255, 255, 255, 0.14);
        --safi-border-light:   rgba(255, 255, 255, 0.08);

        --safi-text-primary:   #f5f5f5;
        --safi-text-secondary: #d4d4d4;
        --safi-text-muted:     #a3a3a3;
        --safi-text-faint:     #737373;

        /* Was a near-white green tint; needs to become a dark green tint. */
        --safi-brand-xlight:   rgba(22, 163, 74, 0.16);

        /* Soft light-mode shadows are invisible on dark — deepen them. */
        --safi-shadow-window:  0 24px 64px rgba(0, 0, 0, 0.55), 0 6px 20px rgba(0, 0, 0, 0.35);
        --safi-shadow-bubble:  0 1px 4px rgba(0, 0, 0, 0.35);
    }

    /* --- the hardcoded exceptions --- */

    .safi-chat-window {
        border-color: rgba(255, 255, 255, 0.12);
    }

    /* The field is transparent now; the capsule around it carries the surface. */
    .safi-chat-composer {
        background: #0a0a0a;
    }

    /* The pale-green header inverts to a dark green tint via --safi-brand-xlight,
       but the type and controls on it are set for a light band: brand-dark green
       and a black hover tint are both invisible here. */
    .safi-chat-title {
        color: #4ade80;
    }

    .safi-chat-header-button:hover {
        background: rgba(255, 255, 255, 0.10);
        color: #86efac;
    }

    .safi-chat-messages::-webkit-scrollbar-thumb {
        background: rgba(255, 255, 255, 0.18);
    }

    /* Inline code was dark-on-light; invert it. `pre` blocks are already dark in
       light mode, so they are left alone. */
    .safi-chat-bubble code {
        background: rgba(255, 255, 255, 0.10);
        color: #f5f5f5;
    }

    .safi-suggestion-chip {
        border-color: rgba(134, 239, 172, 0.30);
    }

    .safi-suggestion-chip:hover {
        background: rgba(22, 163, 74, 0.20);
        border-color: rgba(134, 239, 172, 0.55);
    }

    .safi-retry-btn:hover {
        background: rgba(255, 255, 255, 0.08);
        border-color: rgba(255, 255, 255, 0.35);
    }

    /* The base dot is already var(--safi-brand), which is fine in light mode
       but reads a little dim against a near-black bubble; the main app
       makes the same call for its own dark-mode dots (#4ade80 in place of
       the resting #16a34a). */
    .safi-dot {
        background: #4ade80;
    }

    /* The disabled fill is a plain light grey, which reads as a jarring
       bright block on a dark window; softened to a translucent white tint
       instead of a solid colour. */
    .safi-chat-send:disabled {
        background: rgba(255, 255, 255, 0.18);
    }
}
