/* === module_sankey-assistant.css ====================================
 * 2026-05-29 — Sankey (rule-based assistant) FAB + panel + transcript.
 * Loaded via mu-plugins/018-gspc-sankey-assistant.php enqueue.
 * ==================================================================== */

.gspc-sankey-fab {
    position: fixed;
    right: 1.25rem;
    bottom: 1.25rem;
    width: 56px; height: 56px;
    border-radius: 50%;
    background: var(--gspc-primary-blue, #1e5799);
    color: #ffffff;
    border: 0;
    box-shadow: 0 6px 20px rgba(15, 35, 60, 0.28);
    /* Above everything — breadcrumb sticky is 990, modals at 10000+, so use 100001
       to ensure the assistant is always on top. Lesson learnt from 2nite DAIna. */
    z-index: 100001;
    display: grid; place-items: center;
    cursor: pointer;
    transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.gspc-sankey-fab:hover { transform: scale(1.06); background: var(--gspc-accent-orange, #b54708); }
.gspc-sankey-fab:focus-visible { outline: 3px solid var(--gspc-focus-ring, #f7941d); outline-offset: 3px; }
.gspc-sankey-fab { overflow: visible; isolation: isolate; }
.gspc-sankey-fab > svg:not(.claire-fab-sparkles) { width: 28px; height: 28px; }
.gspc-sankey-fab > svg.claire-fab-sparkles { width: 100%; height: 100%; }

@keyframes gspc-sankey-pulse {
    0%   { box-shadow: 0 6px 20px rgba(15, 35, 60, 0.28), 0 0 0 0   rgba(30, 87, 153, 0.55); }
    70%  { box-shadow: 0 6px 20px rgba(15, 35, 60, 0.28), 0 0 0 16px rgba(30, 87, 153, 0); }
    100% { box-shadow: 0 6px 20px rgba(15, 35, 60, 0.28), 0 0 0 0   rgba(30, 87, 153, 0); }
}
.gspc-sankey-fab[data-state="idle"] { animation: gspc-sankey-pulse 2.4s ease-out 4s 3; }

@media (prefers-reduced-motion: reduce) {
    .gspc-sankey-fab { animation: none !important; transition: none !important; }
    .gspc-sankey-fab:hover { transform: none; }
}
@media print { .gspc-sankey-fab, .gspc-sankey-panel { display: none !important; } }

/* Panel */
.gspc-sankey-panel {
    position: fixed;
    right: 1.25rem;
    bottom: 5.5rem;
    width: min(400px, calc(100vw - 2.5rem));
    height: min(580px, calc(100vh - 8rem));
    background: #ffffff;
    border: 1px solid rgba(15, 35, 60, 0.10);
    border-radius: 16px;
    box-shadow: 0 24px 64px rgba(15, 35, 60, 0.30);
    z-index: 100002;
    flex-direction: column;
    overflow: hidden;
    color: var(--gspc-dark-gray, #1a2533);
}
.gspc-sankey-panel[hidden] { display: none; }
.gspc-sankey-panel[data-open="1"] { display: flex; }

/* 2026-11-05 (PASS 2) — MAXIMISE state (desktop) = a BOUNDED, CENTRED modal.
   claire_logic adds `is-maximised` to #gspc-sankey-panel + toggles the
   .gspc-sankey-panel__tool--maximise button. Previously this merely grew the
   bottom-right corner popover (min(900px) anchored bottom-right); the owner
   wanted a proper centred modal that is clearly NOT full-screen and NOT a
   corner popover. We therefore detach it from the default right/bottom anchor
   (right/bottom:auto) and centre it with left/top:50% + translate(-50%,-50%),
   bounded to min(860px) wide × 80vh tall with a 2rem gutter on every side.
   The panel is a flex column, so its header (ClAire logo + toolbar) stays
   pinned at the top and fully visible; the transcript scrolls inside. The
   grey scrim (.gspc-sankey-backdrop, shown on body.gspc-sankey-open) sits
   behind it and a click on it closes ClAire (ensureBackdrop() in
   gspc-sankey.js). The non-maximised default (width:min(400px…)/
   height:min(580px…)) is untouched. Mobile MAXIMISE = full-screen, in the
   @media(max-width:600px) block below, which overrides this at <=600px. */
#gspc-sankey-panel.is-maximised {
    right: auto;
    bottom: auto;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: min(860px, calc(100vw - 4rem));
    height: min(80vh, calc(100vh - 4rem));
    max-height: calc(100vh - 4rem);
}

@media (max-width: 600px) {
    /* 2026-06-01 — mobile bottom-sheet pattern (mirrors 2nite DAIna).
       Panel is NOT full height — caps at 80vh so the user can still
       see the greyed page behind it + the close affordance + the FAB
       to dismiss. Rounded top corners only. */
    .gspc-sankey-panel {
        left: 0; right: 0; bottom: 0;
        width: 100vw;
        height: auto;
        max-height: 80vh;
        border-radius: 18px 18px 0 0;
        border-left: 0; border-right: 0; border-bottom: 0;
    }
    /* 2026-11-05 — MAXIMISE on mobile = full screen. Overrides the 80vh
       bottom-sheet cap so ClAire fills the viewport. 100dvh handles the
       mobile browser URL-bar so the panel isn't clipped. Non-maximised
       default (the bottom-sheet above) is unchanged. */
    #gspc-sankey-panel.is-maximised {
        inset: 0;
        /* reset the desktop centred-modal transform/anchor so mobile
           MAXIMISE fills the viewport from top-left, not shifted -50%. */
        transform: none;
        left: 0; top: 0; right: 0; bottom: 0;
        width: 100vw;
        height: 100dvh;
        max-height: none;
        border-radius: 0;
    }
    /* 2026-11-05 — compact quick-action pills on phones (desktop sizing
       in .gspc-sankey-chip / .gspc-sankey-panel__chips is unchanged). */
    .gspc-sankey-panel__chips {
        gap: 5px;
        padding: 8px 12px 5px;
    }
    .gspc-sankey-chip {
        padding: 3px 9px;
        font-size: calc(11px * var(--gspc-textsize-scale, 1));
    }
    .gspc-sankey-fab { bottom: 1rem; right: 1rem; }
    /* Lock body scroll under the panel — matches DAIna behaviour. */
    body.gspc-sankey-open { overflow: hidden; }
    /* 2026-06-01 — hide bottom-right FABs while the hero CTA row is in
       view (mobile only). Hero already exposes Activities + Ask ClAire
       buttons so the floating duplicates are noise. JS in mu-plugin
       021 toggles `body.gspc-hero-cta-visible` via IntersectionObserver. */
    body.gspc-hero-cta-visible .gspc-sankey-fab,
    body.gspc-hero-cta-visible #gspc-saved-fab {
        opacity: 0;
        pointer-events: none;
        transform: translateY(20px);
    }
    .gspc-sankey-fab,
    #gspc-saved-fab {
        transition: opacity .25s ease, transform .25s ease;
    }
}

/* 2026-06-01 — backdrop scrim. Injected by gspc-sankey.js on first
   open. Body class toggles visibility + pointer-events so tap-outside
   closes the panel. Always present once open, regardless of viewport
   (desktop also gets a subtle dim so the focus is on ClAire). */
.gspc-sankey-backdrop {
    position: fixed;
    inset: 0;
    z-index: 100000;
    background: rgba(7, 9, 16, 0.62);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
}
body.gspc-sankey-open .gspc-sankey-backdrop {
    opacity: 1;
    pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
    .gspc-sankey-backdrop { transition: none; }
}

.gspc-sankey-panel__head {
    position: relative;
    padding: 16px 140px 12px 20px;
    background: var(--gspc-primary-blue, #1e5799);
    color: #ffffff;
}
.gspc-sankey-panel__head h2 { margin: 0; font-size: calc(18px * var(--gspc-textsize-scale, 1)); color: #ffffff; }
/* When-next badges in the "My saved" reply. */
.gspc-sankey-when { display: inline-block; margin-top: 4px; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; line-height: 1.4; }
.gspc-sankey-when--now      { background: #16a34a; color: #ffffff; }
.gspc-sankey-when--today    { background: #f59e0b; color: #ffffff; }
.gspc-sankey-when--soon     { background: #2563eb; color: #ffffff; }
.gspc-sankey-when--upcoming { background: #e2e8f0; color: #1a2533; }
.gspc-sankey-when--missed   { background: #fef3c7; color: #7c2d12; }

.gspc-sankey-saved-row { display: flex; align-items: flex-start; gap: 8px; }
.gspc-sankey-saved-row__icon { flex-shrink: 0; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; background: #ffffff; border: 1px solid #d6dbe2; border-radius: 6px; color: #1e5799; }
.gspc-sankey-saved-row__body { flex: 1; min-width: 0; }
.gspc-sankey-saved-row--stale .gspc-sankey-saved-row__body { opacity: .7; text-decoration: line-through; text-decoration-color: #d97706; }
.gspc-sankey-saved-row--stale .gspc-sankey-saved-row__body .gspc-sankey-when { text-decoration: none; }
/* ===========================================================
   Ask ClAire CTA — twinkling AI sparkle layer (2026-05-29 v9)
   Mirrors the DAIna FAB sparkles. Eight 4-point stars sit
   BEHIND the icon + label. pointer-events:none so the <a>
   stays clickable. Static at 55% opacity under
   prefers-reduced-motion.
   =========================================================== */
.gspc-sankey-cta {
	position: relative;
	overflow: visible;
	isolation: isolate;
}
.claire-cta-sparkles,
.claire-fab-sparkles {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
	z-index: 0;
	overflow: visible;
}
.gspc-sankey-cta > *:not(.claire-cta-sparkles) {
	position: relative;
	z-index: 1;
}
.gspc-sankey-fab > *:not(.claire-fab-sparkles) {
	position: relative;
	z-index: 1;
}
/* 2026-05-30 v13 — sparkles default to VISIBLE (opacity .7) so they
   show even without animation. Keyframes scale + rotate; opacity floats
   between .4 and 1 so the dim baseline always reads. Previous baseline
   was 0 which made the layer invisible when keyframes hadn't started. */
.claire-spk {
	transform-box: fill-box;
	transform-origin: center;
	animation: claire-spk-twinkle 2.8s ease-in-out infinite;
	opacity: 0.8;
	stroke: #ffffff;
	stroke-width: 0.5;
	stroke-linejoin: round;
	paint-order: stroke;
}
.claire-spk-1 { animation-delay: 0s;    }
.claire-spk-2 { animation-delay: 0.35s; }
.claire-spk-3 { animation-delay: 0.7s;  }
.claire-spk-4 { animation-delay: 1.05s; }
.claire-spk-5 { animation-delay: 1.4s;  }
.claire-spk-6 { animation-delay: 1.75s; }
.claire-spk-7 { animation-delay: 2.1s;  }
.claire-spk-8 { animation-delay: 0.5s; animation-duration: 3.4s; }
@keyframes claire-spk-twinkle {
	0%,100% { opacity: .4;   transform: scale(.7)  rotate(0deg); }
	35%     { opacity: 1;    transform: scale(1.25) rotate(35deg); }
	65%     { opacity: .7;   transform: scale(1.0) rotate(-15deg); }
}
@media (prefers-reduced-motion: reduce) {
	.claire-spk { animation: none; opacity: .7; transform: scale(1); }
}

.gspc-sankey-tm {
    font-size: 0.55em;
    vertical-align: super;
    margin-left: 1px;
    line-height: 1;
    opacity: 0.9;
    font-weight: 600;
}
.gspc-sankey-panel__subhead { margin: 2px 0 0; font-size: calc(12px * var(--gspc-textsize-scale, 1)); color: rgba(255, 255, 255, 0.82); }
.gspc-sankey-panel__tools {
    position: absolute; top: 12px; right: 12px;
    display: flex; gap: 6px; align-items: center;
}
.gspc-sankey-panel__tool,
.gspc-sankey-panel__close {
    width: 32px; height: 32px;
    background: rgba(255, 255, 255, 0.18);
    color: #ffffff;
    border: 0; border-radius: 50%;
    line-height: 1;
    cursor: pointer;
    display: grid; place-items: center;
    padding: 0;
    transition: background .15s ease;
}
.gspc-sankey-panel__close { width: 36px; height: 36px; font-size: 22px; }
.gspc-sankey-panel__tool:hover,
.gspc-sankey-panel__close:hover { background: rgba(255, 255, 255, 0.32); }
.gspc-sankey-panel__tool:focus-visible,
.gspc-sankey-panel__close:focus-visible {
    outline: 2px solid var(--gspc-focus-ring, #f7941d);
    outline-offset: 2px;
}
.gspc-sankey-panel__tool svg { display: block; }
/* 2026-11-05 — maximise toggle. Inherits size/shape/hover/focus from
   .gspc-sankey-panel__tool; only constrain the icon + give a filled
   "on" state when the panel is maximised so the toggle reads as active.
   claire_logic adds/removes is-maximised on #gspc-sankey-panel. */
.gspc-sankey-panel__tool--maximise svg { width: 16px; height: 16px; }
#gspc-sankey-panel.is-maximised .gspc-sankey-panel__tool--maximise {
    background: rgba(255, 255, 255, 0.34);
}

/* 2026-06-13d — Settings modal (in-chat overlay).
   The topbar cog (.gspc-sankey-panel__tool--settings) now opens this
   modal instead of toggling response mode. The modal overlays the
   transcript and dims it behind a scrim; the transcript sits behind the
   scrim with pointer-events:none so it's visibly disabled. role=dialog,
   focus-trapped, Esc / scrim / X close (all wired in gspc-sankey.js). */
.gspc-sankey-settings {
    position: absolute;
    inset: 0;
    z-index: 20;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 18px;
}
.gspc-sankey-settings[aria-hidden="false"] { display: flex; }
.gspc-sankey-settings[hidden] { display: none; }
/* Scrim — dims ONLY the chat panel behind the modal (the panel is the
   positioning context, not the page). Clicking it closes the modal. */
.gspc-sankey-settings__scrim {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    cursor: pointer;
}
.gspc-sankey-settings__card {
    position: relative;
    z-index: 1;
    background: #ffffff;
    color: var(--gspc-dark-gray, #1a2533);
    border-radius: 14px;
    box-shadow: 0 12px 36px rgba(15, 35, 60, 0.42);
    max-width: 340px;
    width: 100%;
    max-height: 100%;
    overflow-y: auto;
}
.gspc-sankey-settings__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 14px 16px 10px;
    border-bottom: 1px solid rgba(15, 35, 60, 0.08);
}
.gspc-sankey-settings__title {
    margin: 0;
    font-size: calc(17px * var(--gspc-textsize-scale, 1));
    font-weight: 700;
    color: var(--gspc-primary-blue, #1e5799);
}
.gspc-sankey-settings__close {
    flex-shrink: 0;
    width: 34px; height: 34px;
    border: 0; border-radius: 50%;
    background: rgba(15, 35, 60, 0.08);
    color: var(--gspc-dark-gray, #1a2533);
    font-size: 22px; line-height: 1;
    cursor: pointer;
    display: grid; place-items: center;
}
.gspc-sankey-settings__close:hover { background: rgba(15, 35, 60, 0.16); }
.gspc-sankey-settings__close:focus-visible {
    outline: 3px solid var(--gspc-focus-ring, #f7941d);
    outline-offset: 2px;
}
.gspc-sankey-settings__body { padding: 14px 16px 16px; }
.gspc-sankey-settings__group {
    margin: 0;
    padding: 0;
    border: 0;
}
.gspc-sankey-settings__legend {
    padding: 0;
    margin: 0 0 4px;
    font-weight: 700;
    font-size: calc(14px * var(--gspc-textsize-scale, 1));
    color: var(--gspc-dark-gray, #1a2533);
}
.gspc-sankey-settings__hint {
    margin: 0 0 10px;
    font-size: calc(12px * var(--gspc-textsize-scale, 1));
    color: var(--gspc-medium-gray, #5b6b7d);
}
.gspc-sankey-settings__opt {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 10px;
    border: 1.5px solid rgba(15, 35, 60, 0.14);
    border-radius: 10px;
    margin-bottom: 8px;
    cursor: pointer;
}
.gspc-sankey-settings__opt:hover { border-color: rgba(30, 87, 153, 0.45); }
.gspc-sankey-settings__opt input { margin-top: 3px; flex-shrink: 0; accent-color: var(--gspc-primary-blue, #1e5799); }
.gspc-sankey-settings__opt:focus-within {
    border-color: var(--gspc-primary-blue, #1e5799);
    box-shadow: 0 0 0 3px rgba(247, 148, 29, 0.30);
}
.gspc-sankey-settings__opt-text { display: flex; flex-direction: column; line-height: 1.35; }
.gspc-sankey-settings__opt-text strong { font-size: calc(14px * var(--gspc-textsize-scale, 1)); }
.gspc-sankey-settings__opt-text small { color: var(--gspc-medium-gray, #5b6b7d); font-size: calc(12px * var(--gspc-textsize-scale, 1)); }
.gspc-sankey-settings__rm-note {
    margin: 2px 0 0;
    font-size: calc(12px * var(--gspc-textsize-scale, 1));
    color: #b54708;
}
.gspc-sankey-settings__meta {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid rgba(15, 35, 60, 0.08);
}
.gspc-sankey-settings__version {
    margin: 0 0 4px;
    font-size: calc(12px * var(--gspc-textsize-scale, 1));
    font-weight: 600;
    color: var(--gspc-dark-gray, #1a2533);
}
.gspc-sankey-settings__copy {
    margin: 0;
    font-size: calc(11px * var(--gspc-textsize-scale, 1));
    color: var(--gspc-medium-gray, #5b6b7d);
    line-height: 1.5;
}
/* Disable the transcript behind the scrim so it's visibly inert. */
.gspc-sankey-panel:has(.gspc-sankey-settings[aria-hidden="false"]) .gspc-sankey-panel__transcript {
    pointer-events: none;
}

/* Inline confirm overlay (used by Reset). Sits ON TOP of the panel
   transcript via z-index, full-cover so the user can't keep typing
   during the confirm step. */
.gspc-sankey-panel__confirm {
    position: absolute;
    inset: 0;
    background: rgba(15, 35, 60, 0.55);
    display: none;
    align-items: center;
    justify-content: center;
    padding: 16px;
    z-index: 10;
}
.gspc-sankey-panel__confirm[aria-hidden="false"] { display: flex; }
.gspc-sankey-panel__confirm[hidden] { display: none; }
.gspc-sankey-panel__confirm-card {
    background: #ffffff;
    border-radius: 12px;
    padding: 18px 18px 14px;
    max-width: 320px;
    width: 100%;
    box-shadow: 0 8px 28px rgba(15, 35, 60, 0.40);
    color: var(--gspc-dark-gray, #1a2533);
}
.gspc-sankey-panel__confirm-title { margin: 0 0 6px; font-weight: 700; font-size: calc(16px * var(--gspc-textsize-scale, 1)); }
.gspc-sankey-panel__confirm-body  { margin: 0 0 14px; font-size: calc(13px * var(--gspc-textsize-scale, 1)); color: #455064; }
.gspc-sankey-panel__confirm-actions { display: flex; gap: 8px; justify-content: flex-end; }
.gspc-sankey-panel__confirm-yes,
.gspc-sankey-panel__confirm-cancel {
    padding: 8px 14px;
    border-radius: 8px;
    border: 0;
    font-size: calc(13px * var(--gspc-textsize-scale, 1));
    cursor: pointer;
    line-height: 1.2;
}
.gspc-sankey-panel__confirm-yes    { background: var(--gspc-primary-blue, #1e5799); color: #ffffff; }
.gspc-sankey-panel__confirm-yes:hover    { background: var(--gspc-accent-orange, #b54708); }
.gspc-sankey-panel__confirm-cancel { background: #e6ecf3; color: #1a2533; }
.gspc-sankey-panel__confirm-cancel:hover { background: #d4dce6; }
.gspc-sankey-panel__confirm-yes:focus-visible,
.gspc-sankey-panel__confirm-cancel:focus-visible {
    outline: 3px solid var(--gspc-focus-ring, #f7941d);
    outline-offset: 1px;
}

/* 2026-06-13e — scroll wrapper. Wraps the transcript so the scroll-down
   arrow can be absolutely positioned against the bottom of the scroll
   viewport (not the variable-height chips/form below it). The wrapper is
   the flex item; the transcript fills it and owns the scroll. */
.gspc-sankey-panel__scrollwrap {
    position: relative;
    flex: 1; min-height: 0;
    display: flex; flex-direction: column;
}
.gspc-sankey-panel__transcript {
    flex: 1; min-height: 0;
    overflow-y: auto;
    /* 2026-11-05 — finger/touch scroll fix. Owner reported the ClAire
       content couldn't be scrolled by touch on mobile. Momentum scroll
       for iOS Safari + allow vertical pan + contain overscroll so the
       inner scroll doesn't chain to the body (which is locked via
       body.gspc-sankey-open{overflow:hidden}). */
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
    overscroll-behavior: contain;
    padding: 16px 18px;
    background: #f7f9fc;
    display: flex; flex-direction: column; gap: 10px;
}

/* 2026-06-13e — scroll-to-latest chevron. Anchored bottom-right of the
   scroll viewport. Hidden (no paint, no pointer, no AT) until JS adds
   .is-visible, which fades it in. Clicking smooth-scrolls the transcript
   to the bottom (JS handles the smooth/instant choice). */
.gspc-sankey-scrolldown {
    position: absolute;
    right: 12px;
    bottom: 12px;
    z-index: 6;
    width: 36px; height: 36px;
    border: 0;
    border-radius: 50%;
    background: var(--gspc-primary-blue, #1e5799);
    color: #ffffff;
    box-shadow: 0 4px 14px rgba(15, 35, 60, 0.32);
    display: grid; place-items: center;
    padding: 0;
    cursor: pointer;
    opacity: 0;
    transform: translateY(8px) scale(0.92);
    pointer-events: none;
    transition: opacity .22s ease, transform .22s ease, background .15s ease;
}
.gspc-sankey-scrolldown.is-visible {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}
.gspc-sankey-scrolldown:hover { background: var(--gspc-accent-orange, #b54708); }
.gspc-sankey-scrolldown:focus-visible {
    outline: 3px solid var(--gspc-focus-ring, #f7941d);
    outline-offset: 2px;
}
.gspc-sankey-scrolldown svg { display: block; }
@media (prefers-reduced-motion: reduce) {
    .gspc-sankey-scrolldown { transition: opacity .22s ease, background .15s ease; transform: none; }
    .gspc-sankey-scrolldown.is-visible { transform: none; }
}
.gspc-sankey-msg {
    padding: 10px 14px;
    border-radius: 12px;
    font-size: calc(14px * var(--gspc-textsize-scale, 1));
    line-height: 1.5;
    max-width: 100%;
}
.gspc-sankey-msg p { margin: 0 0 8px; }
.gspc-sankey-msg p:last-child { margin: 0; }
.gspc-sankey-msg ul, .gspc-sankey-msg ol { margin: 6px 0; padding-left: 22px; }
.gspc-sankey-msg li { margin-bottom: 4px; }
.gspc-sankey-msg a { color: var(--gspc-primary-blue, #1e5799); }
.gspc-sankey-msg--bot { background: #ffffff; border: 1px solid rgba(15, 35, 60, 0.08); }
.gspc-sankey-msg--user { background: var(--gspc-primary-blue, #1e5799); color: #ffffff; align-self: flex-end; max-width: 85%; }
.gspc-sankey-msg--user a { color: #ffffff; text-decoration: underline; }
.gspc-sankey-msg--bot small { color: var(--gspc-medium-gray, #5b6b7d); font-size: 11px; }

.gspc-sankey-msg__citations { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.gspc-sankey-citation {
    display: inline-flex; align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: calc(11px * var(--gspc-textsize-scale, 1));
    font-weight: 600;
    text-decoration: none;
    background: rgba(30, 87, 153, 0.10);
    color: var(--gspc-primary-blue, #1e5799);
    border: 1.5px solid rgba(30, 87, 153, 0.20);
}
.gspc-sankey-citation:hover { background: rgba(30, 87, 153, 0.20); }
.gspc-sankey-citation--faith,
.gspc-sankey-citation--meeting    { background: rgba(247, 148, 29, 0.12); color: #b54708; border-color: rgba(247, 148, 29, 0.30); }
.gspc-sankey-citation--councillor { background: rgba(22, 163, 74, 0.12);  color: #15803d; border-color: rgba(22, 163, 74, 0.30); }
.gspc-sankey-citation--info       { background: rgba(99, 102, 241, 0.12); color: #4f46e5; border-color: rgba(99, 102, 241, 0.30); }
.gspc-sankey-citation--centre     { background: rgba(5, 150, 105, 0.12);  color: #047857; border-color: rgba(5, 150, 105, 0.30); }
.gspc-sankey-citation--faq        { background: rgba(124, 58, 237, 0.12); color: #6d28d9; border-color: rgba(124, 58, 237, 0.30); }

.gspc-sankey-list { list-style: none; padding: 0; margin: 6px 0; display: flex; flex-direction: column; gap: 6px; }
.gspc-sankey-list li { padding: 6px 10px; background: rgba(15, 35, 60, 0.04); border-radius: 6px; }
/* 2026-06-01 — saveable rows inside ClAire replies: heart on the left,
   text on the right, single-line baseline alignment. The heart reuses
   .gspc-fav--mini.gspc-fav--inline so the global gspc-saved-activities.js
   click handler picks it up unchanged. */
.gspc-sankey-list--saveable .gspc-sankey-list__row { display: flex; align-items: flex-start; gap: 8px; padding: 6px 8px; }
.gspc-sankey-list--saveable .gspc-sankey-list__main { flex: 1; min-width: 0; line-height: 1.4; }
.gspc-sankey-list--saveable .gspc-fav { flex-shrink: 0; }
.gspc-sankey-list__hint { margin: 6px 0 0; color: rgba(15, 35, 60, 0.65); font-size: 12px; }
.gspc-sankey-related { font-size: 12px; margin: 10px 0 4px; color: var(--gspc-medium-gray, #5b6b7d); }
.gspc-sankey-related-list { list-style: none; padding: 0; margin: 0; }
.gspc-sankey-related-list li { padding: 4px 0; }
.gspc-sankey-handoff-btn { display: inline-block; padding: 8px 16px; border-radius: 30px; background: var(--gspc-accent-orange, #b54708); color: #ffffff; text-decoration: none; font-weight: 600; }
.gspc-sankey-handoff-btn:hover { background: #8a3a08; color: #ffffff; }

/* Typing indicator */
.gspc-sankey-typing { display: inline-flex; gap: 4px; }
.gspc-sankey-typing span {
    width: 6px; height: 6px; background: var(--gspc-medium-gray, #5b6b7d);
    border-radius: 50%;
    animation: gspc-sankey-bounce 1.2s infinite;
}
.gspc-sankey-typing span:nth-child(2) { animation-delay: .15s; }
.gspc-sankey-typing span:nth-child(3) { animation-delay: .3s; }
@keyframes gspc-sankey-bounce {
    0%, 80%, 100% { transform: scale(0.7); opacity: 0.5; }
    40%           { transform: scale(1);   opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .gspc-sankey-typing span { animation: none; }
}

/* Chat-response (streaming) reveal. Each top-level block of the reply is
   appended with .gspc-sankey-reveal then flipped to .is-in on the next
   frame to fade + rise into place, simulating a live chatbot stream.
   prefers-reduced-motion strips the transition (the JS already forces the
   instant path under reduced motion, this is belt-and-braces). */
.gspc-sankey-msg--streaming { min-height: 1.5em; }
.gspc-sankey-reveal {
    opacity: 0;
    transform: translateY(4px);
    transition: opacity .28s ease, transform .28s ease;
}
.gspc-sankey-reveal.is-in {
    opacity: 1;
    transform: none;
}
@media (prefers-reduced-motion: reduce) {
    .gspc-sankey-reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* Quick-prompt chips */
.gspc-sankey-panel__chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 16px 6px; background: #ffffff; border-top: 1px solid rgba(15, 35, 60, 0.06); }
.gspc-sankey-chip {
    background: rgba(30, 87, 153, 0.08);
    color: var(--gspc-primary-blue, #1e5799);
    border: 1.5px solid rgba(30, 87, 153, 0.20);
    border-radius: 999px;
    padding: 4px 12px;
    font-size: calc(12px * var(--gspc-textsize-scale, 1));
    font-weight: 600;
    cursor: pointer;
}
.gspc-sankey-chip:hover { background: rgba(30, 87, 153, 0.18); }

/* 2026-08-03 (#55) — chat-trigger pills carry a trailing speech-bubble icon
   so a "send ClAire a question" pill is visually distinct from a "go to a
   page" link pill. Sized to the chip text; inherits the pill's currentColor. */
.gspc-sankey-chip__bubble {
    width: 1em;
    height: 1em;
    margin-left: 0.4em;
    vertical-align: -0.14em;
    flex: 0 0 auto;
    pointer-events: none;
}

/* Input form */
.gspc-sankey-panel__form { display: flex; gap: 8px; padding: 12px 16px 16px; background: #ffffff; }
.gspc-sankey-panel__form input {
    flex: 1; min-width: 0;
    padding: 10px 14px;
    border-radius: 999px;
    border: 1.5px solid rgba(15, 35, 60, 0.18);
    font-size: calc(14px * var(--gspc-textsize-scale, 1));
    background: #ffffff;
}
.gspc-sankey-panel__form input:focus-visible { outline: 3px solid var(--gspc-focus-ring, #f7941d); outline-offset: 1px; border-color: var(--gspc-primary-blue, #1e5799); }
.gspc-sankey-panel__send {
    background: var(--gspc-primary-blue, #1e5799); color: #ffffff;
    border: 0; border-radius: 50%;
    width: 40px; height: 40px;
    display: grid; place-items: center;
    cursor: pointer;
}
.gspc-sankey-panel__send:hover { background: var(--gspc-accent-orange, #b54708); }

/* FAQ page */
.gspc-faq-page { max-width: 1180px; margin: 0 auto; padding: 30px 16px 60px; }
.gspc-faq-intro { background: #ffffff; border-radius: 16px; box-shadow: 0 6px 20px rgba(15, 35, 60, 0.06); padding: 22px 26px; margin-bottom: 24px; }
.gspc-faq-intro h2 { color: var(--gspc-primary-blue, #1e5799); margin-top: 0; }
.gspc-faq-counter strong { color: var(--gspc-accent-orange, #b54708); font-size: 18px; }
.gspc-faq-section { margin: 0 0 30px; }
.gspc-faq-section__title { font-size: 22px; color: var(--gspc-primary-blue, #1e5799); border-bottom: 3px solid var(--gspc-accent-orange, #b54708); padding-bottom: 6px; display: inline-block; margin: 0 0 16px; }
.gspc-faq-section__count { display: inline-block; margin-left: 10px; background: rgba(247, 148, 29, 0.18); color: var(--gspc-accent-orange, #b54708); border-radius: 999px; padding: 2px 12px; font-size: 13px; }
.gspc-faq-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.gspc-faq-item details { background: #ffffff; border-radius: 12px; box-shadow: 0 3px 12px rgba(15, 35, 60, 0.06); padding: 14px 20px; }
.gspc-faq-item summary { cursor: pointer; font-weight: 600; font-size: 16px; color: var(--gspc-primary-blue, #1e5799); list-style-position: outside; }
.gspc-faq-item summary::marker { color: var(--gspc-accent-orange, #b54708); }
.gspc-faq-item__answer { margin-top: 12px; color: var(--gspc-dark-gray, #1a2533); line-height: 1.6; }

/* Homepage hero "Ask SandAI" CTA — sits next to "Meet Your Councillors"
   inside .hero-buttons. White-on-dark ghost button. */
.hero-buttons .gspc-sankey-cta--hero-home {
    color: #fff !important;
    border: 2px solid rgba(255, 255, 255, .85);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--gspc-primary-blue);
}
.hero-buttons .gspc-sankey-cta--hero-home:hover {
    background: var(--gspc-accent-orange, #b54708);
    border-color: var(--gspc-accent-orange, #b54708);
    color: #ffffff !important;
}
/* 2026-06-01 — sparkles SVG must span the FULL button (mirrors the FAB
   pattern at line 27). Without :not() the universal `svg` selector also
   matched .claire-cta-sparkles and collapsed it to 18px, leaving the
   stars off-centre + zoomed wrong. Fixed via :not() + explicit override. */
.hero-buttons .gspc-sankey-cta--hero-home svg:not(.claire-cta-sparkles) { width: 18px; height: 18px; }
.hero-buttons .gspc-sankey-cta--hero-home svg.claire-cta-sparkles {
    width: 100%;
    height: 100%;
    opacity: 0.6;
}

/* 2026-06-01 — hero CTA only: tinted blue scrim sits BETWEEN sparkles
   (z:0, SVG first child) and text/icon (z:1, .gspc-sankey-cta > *
   rule). ::after is painted after the SVG in source order, both at
   z:0, so it stacks above the sparkles but below the label. Blue
   matches the FAB primary; 50% opacity lets sparkles glint through. */
.hero-buttons .gspc-sankey-cta--hero-home::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--gspc-primary-blue, #1e5799);
	opacity: 0.5;
	border-radius: inherit;
	z-index: 0;
	pointer-events: none;
}

/* 2026-06-13 — in-reply onward actions (no-dead-ends rule).
   .gspc-sankey-followups wraps follow-up chips ClAire emits at the foot
   of a reply; each chip is an <a> reusing the base .gspc-sankey-chip pill
   but must render as an inline-block (anchors are inline by default) and
   never show the default underline. Mirrors the look of the static
   footer prompt chips so reply chips and footer chips are visually one
   family. Also styles the .gspc-sankey-cta-btn primary button used by the
   councillor / centres / saved replies. */
.gspc-sankey-followups {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 10px 0 0;
}
.gspc-sankey-followups__label {
	font-size: calc(12px * var(--gspc-textsize-scale, 1));
	font-weight: 600;
	color: var(--gspc-medium-gray, #5b6b7d);
}
.gspc-sankey-msg a.gspc-sankey-chip,
.gspc-sankey-followups a.gspc-sankey-chip,
.gspc-sankey-ward-chips a.gspc-sankey-chip {
	display: inline-block;
	text-decoration: none;
	line-height: 1.4;
}
.gspc-sankey-msg a.gspc-sankey-chip:hover,
.gspc-sankey-followups a.gspc-sankey-chip:hover {
	background: rgba(30, 87, 153, 0.18);
	text-decoration: none;
}
/* 2026-06-14 — context-aware reopen suggestions block.
   Rendered as a bot bubble at the foot of the transcript on (re)open. It
   reuses .gspc-sankey-panel__chips for the chip flex layout, but that base
   class also paints the white footer-bar background + border-top + extra
   padding meant for the docked footer — neutralise those inside the bubble
   so the chips sit flush within the message. */
.gspc-sankey-suggestions__lead { margin: 0 0 8px; }
.gspc-sankey-suggestions__chips,
.gspc-sankey-explore-tier .gspc-sankey-panel__chips {
	padding: 0;
	background: transparent;
	border-top: none;
	margin: 4px 0 0;
}
.gspc-sankey-suggestions__actions { margin: 10px 0 0; }
.gspc-sankey-suggestions__reset {
	background: transparent;
	border: 1.5px solid rgba(30, 87, 153, 0.30);
}
.gspc-sankey-suggestions__reset:hover { background: rgba(30, 87, 153, 0.10); }
.gspc-sankey-explore-chip { font-weight: 700; }
.gspc-sankey-suggestions__reset:focus-visible,
.gspc-sankey-suggestions__chips a.gspc-sankey-chip:focus-visible {
	outline: 3px solid var(--gspc-focus-ring, #f7941d);
	outline-offset: 2px;
}
.gspc-sankey-ward-chips { margin: 8px 0 0; }
.gspc-sankey-ward-chips__label {
	font-size: calc(12px * var(--gspc-textsize-scale, 1));
	font-weight: 600;
	color: var(--gspc-medium-gray, #5b6b7d);
	margin-right: 4px;
}
.gspc-sankey-saved-cta { margin: 12px 0 0; }
a.gspc-sankey-cta-btn,
button.gspc-sankey-cta-btn {
	display: inline-block;
	background: var(--gspc-primary-blue, #1e5799);
	color: #ffffff;
	border: none;
	border-radius: 999px;
	padding: 7px 16px;
	font-size: calc(13px * var(--gspc-textsize-scale, 1));
	font-weight: 700;
	text-decoration: none;
	cursor: pointer;
}
a.gspc-sankey-cta-btn:hover,
button.gspc-sankey-cta-btn:hover { background: #17467d; color: #ffffff; }

/* 2026-11-05 — PDF-sourced data rendering (CONTRACT with claire_logic).
   claire_logic emits tabular PDF data as a <table class="gspc-sankey-data-table">
   inside a <div class="gspc-sankey-data-table-wrap"> wrapper, and non-tabular
   extracted content inside .gspc-sankey-pdf-data. These sit inside a bot
   message bubble (.gspc-sankey-msg--bot). */
.gspc-sankey-data-table-wrap {
    /* Wide tables scroll horizontally on mobile instead of breaking the
       bubble layout. -webkit momentum for iOS. */
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin: 10px 0;
    border-radius: 8px;
    border: 1px solid rgba(15, 35, 60, 0.12);
}
.gspc-sankey-data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: calc(13px * var(--gspc-textsize-scale, 1));
    line-height: 1.45;
    color: var(--gspc-dark-gray, #1a2533);
}
.gspc-sankey-data-table th,
.gspc-sankey-data-table td {
    padding: 7px 10px;
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid rgba(15, 35, 60, 0.10);
    white-space: nowrap;
}
.gspc-sankey-data-table thead th {
    background: rgba(30, 87, 153, 0.10);
    color: var(--gspc-primary-blue, #1e5799);
    font-weight: 700;
    white-space: normal;
}
.gspc-sankey-data-table tbody tr:last-child td { border-bottom: 0; }
.gspc-sankey-data-table tbody tr:nth-child(even) td { background: rgba(15, 35, 60, 0.025); }

/* Non-tabular extracted PDF content — generous spacing so it isn't cramped. */
.gspc-sankey-pdf-data {
    margin: 10px 0;
    line-height: 1.6;
}
.gspc-sankey-pdf-data p { margin: 0 0 10px; }
.gspc-sankey-pdf-data p:last-child { margin: 0; }
.gspc-sankey-pdf-data h3,
.gspc-sankey-pdf-data h4 {
    margin: 14px 0 6px;
    font-size: calc(14px * var(--gspc-textsize-scale, 1));
    font-weight: 700;
    color: var(--gspc-primary-blue, #1e5799);
}
.gspc-sankey-pdf-data h3:first-child,
.gspc-sankey-pdf-data h4:first-child { margin-top: 0; }
.gspc-sankey-pdf-data ul,
.gspc-sankey-pdf-data ol { margin: 8px 0; padding-left: 22px; }
.gspc-sankey-pdf-data li { margin-bottom: 6px; }
a.gspc-sankey-cta-btn:focus-visible,
button.gspc-sankey-cta-btn:focus-visible,
.gspc-sankey-followups a.gspc-sankey-chip:focus-visible {
	outline: 3px solid var(--gspc-focus-ring, #f7941d);
	outline-offset: 2px;
}
