Files
resolutionflow/docs/FlowAssist_Migration/mockups/06-slide-up-banner.html
Michael Chihlas a47ce07326 docs(pilot): fix Phase 8 column + commit-SHA references
Correct the FLOWPILOT-MIGRATION.md stale references to a non-existent
ai_sessions.fix_outcome column — the actual implementation added six
columns to session_suggested_fixes. Also fix a stale first-commit SHA
(6721b84 → cdd8bb0, the former was amended away).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:42:51 -04:00

850 lines
28 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FlowPilot — Suggested Fix as slide-up composer banner</title>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=Bricolage+Grotesque:wght@500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root {
--bg-sidebar: #0e1016;
--bg-page: #16181f;
--bg-card: #1e2028;
--bg-elevated: #2a2d38;
--border-default: rgba(148, 163, 184, 0.12);
--border-hover: rgba(148, 163, 184, 0.22);
--text-heading: #f1f5f9;
--text-primary: #e2e8f0;
--text-muted-foreground: #94a3b8;
--text-muted: #64748b;
--accent: #60a5fa;
--accent-dim: rgba(96, 165, 250, 0.10);
--accent-border: rgba(96, 165, 250, 0.30);
--warning: #fbbf24;
--warning-dim: rgba(251, 191, 36, 0.10);
--warning-dim-strong: rgba(251, 191, 36, 0.16);
--warning-border: rgba(251, 191, 36, 0.32);
--success: #34d399;
--success-dim: rgba(52, 211, 153, 0.10);
--success-border: rgba(52, 211, 153, 0.28);
--danger: #f87171;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
background: var(--bg-sidebar);
color: var(--text-primary);
font-family: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
font-size: 14px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
.page {
max-width: 1680px;
margin: 0 auto;
padding: 32px 24px 72px;
}
.page-header { margin-bottom: 24px; }
.page-title {
font-family: 'Bricolage Grotesque', sans-serif;
font-weight: 600;
font-size: 22px;
color: var(--text-heading);
letter-spacing: -0.01em;
}
.page-sub {
margin-top: 6px;
color: var(--text-muted-foreground);
font-size: 13px;
max-width: 980px;
line-height: 1.55;
}
/* =================== Main frame =================== */
.frame {
background: var(--bg-page);
border: 1px solid var(--border-default);
border-radius: 14px;
overflow: hidden;
display: grid;
grid-template-columns: 1fr 380px;
height: 780px;
}
/* ------ Chat area ------ */
.chat {
display: flex;
flex-direction: column;
background: var(--bg-page);
min-width: 0;
}
.chat-head {
padding: 14px 20px;
border-bottom: 1px solid var(--border-default);
background: var(--bg-sidebar);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.chat-head-title {
font-family: 'Bricolage Grotesque', sans-serif;
font-weight: 600;
font-size: 14px;
color: var(--text-heading);
}
.chat-head-sub {
font-size: 11.5px;
color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
}
.chat-head-actions {
display: flex;
gap: 8px;
}
.chat-scroll {
flex: 1;
overflow-y: auto;
padding: 24px 28px 16px;
display: flex;
flex-direction: column;
gap: 16px;
}
.msg {
max-width: 640px;
display: flex;
gap: 10px;
align-items: flex-start;
}
.msg.user { align-self: flex-end; }
.msg-av {
width: 26px; height: 26px;
border-radius: 50%;
flex-shrink: 0;
font-size: 11px;
font-weight: 600;
display: flex; align-items: center; justify-content: center;
margin-top: 2px;
}
.msg.user .msg-av {
background: var(--accent-dim);
color: var(--accent);
border: 1px solid var(--accent-border);
}
.msg.ai .msg-av {
background: var(--warning-dim);
color: var(--warning);
border: 1px solid var(--warning-border);
}
.msg-body {
background: var(--bg-card);
border: 1px solid var(--border-default);
border-radius: 10px;
padding: 10px 13px;
font-size: 13px;
color: var(--text-primary);
line-height: 1.55;
}
.msg.user .msg-body {
background: var(--accent-dim);
border-color: var(--accent-border);
color: var(--text-heading);
}
.msg-meta {
margin-top: 4px;
font-size: 10.5px;
color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
}
/* ------ Composer area (sticky bottom of chat) ------ */
.composer-wrap {
border-top: 1px solid var(--border-default);
background: var(--bg-page);
position: relative;
}
/* ------ Slide-up banner ------ */
.proposal-banner {
margin: 0;
border-top: 1px solid var(--warning-border);
background: linear-gradient(180deg, var(--warning-dim-strong) 0%, var(--warning-dim) 100%);
padding: 12px 20px 14px;
display: flex;
gap: 14px;
align-items: flex-start;
position: relative;
animation: slideUp 320ms cubic-bezier(.22, .9, .28, 1) both;
}
.proposal-banner::before {
content: '';
position: absolute;
left: 0; top: 0; bottom: 0;
width: 3px;
background: var(--warning);
}
@keyframes slideUp {
from { transform: translateY(14px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.proposal-icon {
width: 28px; height: 28px;
border-radius: 7px;
background: var(--warning-dim-strong);
border: 1px solid var(--warning-border);
display: flex; align-items: center; justify-content: center;
color: var(--warning);
flex-shrink: 0;
margin-top: 2px;
}
.proposal-body {
flex: 1;
min-width: 0;
}
.proposal-head {
display: flex;
align-items: center;
gap: 8px;
font-size: 10px;
font-weight: 600;
letter-spacing: 1.2px;
text-transform: uppercase;
color: var(--warning);
font-family: 'Bricolage Grotesque', sans-serif;
}
.proposal-head .pill {
padding: 2px 7px;
border-radius: 999px;
background: rgba(251, 191, 36, 0.20);
color: var(--warning);
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.5px;
font-family: 'IBM Plex Sans', sans-serif;
font-variant-numeric: tabular-nums;
}
.proposal-title {
margin-top: 3px;
font-size: 14px;
font-weight: 600;
color: var(--text-heading);
line-height: 1.35;
letter-spacing: -0.005em;
}
.proposal-desc {
margin-top: 3px;
font-size: 12.5px;
color: var(--text-muted-foreground);
line-height: 1.5;
}
.proposal-hint {
margin-top: 6px;
font-size: 11.5px;
color: var(--success);
display: inline-flex;
align-items: center;
gap: 5px;
}
.proposal-actions {
display: flex;
gap: 8px;
align-items: center;
flex-shrink: 0;
padding-top: 2px;
}
.btn {
appearance: none;
border: 1px solid var(--border-default);
background: var(--bg-card);
color: var(--text-primary);
padding: 8px 12px;
border-radius: 8px;
font-family: inherit;
font-weight: 500;
font-size: 12.5px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
cursor: pointer;
transition: border-color 0.12s, background-color 0.12s, color 0.12s;
white-space: nowrap;
}
.btn:hover { border-color: var(--border-hover); background: var(--bg-elevated); }
.btn-apply {
background: var(--warning);
color: #1a1200;
border-color: transparent;
font-weight: 600;
padding: 9px 14px;
}
.btn-apply:hover { background: #ffce4f; color: #1a1200; }
.btn-ghost {
background: transparent;
color: var(--text-muted-foreground);
border-color: transparent;
padding: 8px 10px;
}
.btn-ghost:hover {
background: rgba(148, 163, 184, 0.08);
color: var(--text-primary);
border-color: transparent;
}
.icon-btn {
width: 30px; height: 30px;
padding: 0;
background: transparent;
color: var(--text-muted-foreground);
border: 1px solid transparent;
}
.icon-btn:hover {
background: rgba(148, 163, 184, 0.08);
color: var(--text-primary);
}
/* ------ Composer ------ */
.composer {
padding: 14px 20px 16px;
display: flex;
align-items: flex-end;
gap: 10px;
}
.composer-input {
flex: 1;
min-height: 44px;
background: var(--bg-card);
border: 1px solid var(--border-default);
border-radius: 10px;
padding: 10px 14px;
color: var(--text-muted-foreground);
font-size: 13px;
line-height: 1.4;
display: flex;
align-items: center;
}
.composer-send {
width: 44px; height: 44px;
border-radius: 10px;
background: var(--accent);
color: #0a0d14;
border: 0;
display: flex; align-items: center; justify-content: center;
cursor: pointer;
flex-shrink: 0;
}
/* ------ Task lane (right rail) ------ */
.lane {
border-left: 1px solid var(--border-default);
background: var(--bg-sidebar);
display: flex;
flex-direction: column;
min-height: 0;
}
.lane-head {
padding: 14px 16px;
border-bottom: 1px solid var(--border-default);
display: flex;
align-items: center;
justify-content: space-between;
}
.lane-head-label {
font-family: 'Bricolage Grotesque', sans-serif;
font-weight: 600;
font-size: 13px;
color: var(--text-heading);
}
.lane-body {
flex: 1;
overflow-y: auto;
padding: 14px 14px 10px;
display: flex;
flex-direction: column;
gap: 16px;
}
.section-label {
display: flex;
align-items: center;
gap: 8px;
font-size: 10px;
font-weight: 600;
letter-spacing: 1.2px;
text-transform: uppercase;
color: var(--text-muted-foreground);
padding: 0 2px 8px;
}
.dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
.dot-accent { background: var(--accent); }
.dot-muted { background: var(--text-muted); }
.section-meta {
color: var(--text-muted);
font-weight: 500;
letter-spacing: 0;
text-transform: none;
}
.fact {
background: var(--bg-card);
border: 1px solid var(--border-default);
border-left: 3px solid var(--accent);
border-radius: 8px;
padding: 10px 12px;
}
.fact + .fact { margin-top: 8px; }
.fact-title {
font-size: 12.5px;
font-weight: 500;
color: var(--text-heading);
line-height: 1.4;
}
.fact-meta {
margin-top: 3px;
font-size: 10.5px;
color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
}
.dismissed-pill {
padding: 8px 10px;
background: var(--bg-card);
border: 1px dashed var(--border-hover);
border-radius: 8px;
display: flex;
align-items: center;
gap: 8px;
font-size: 11.5px;
color: var(--text-muted-foreground);
cursor: pointer;
transition: border-color 0.12s, color 0.12s;
}
.dismissed-pill:hover { border-color: var(--warning-border); color: var(--warning); }
.action-bar {
border-top: 1px solid var(--border-default);
padding: 12px 14px 14px;
display: flex;
gap: 8px;
}
.btn-escalate { flex: 0 0 auto; min-width: 96px; background: transparent; color: var(--text-muted-foreground); }
.btn-resolve {
flex: 1;
background: var(--accent);
color: #0a0d14;
border-color: transparent;
font-weight: 600;
padding: 10px 12px;
}
.btn-resolve:hover { background: #7ab4fb; color: #0a0d14; }
/* =================== Callouts =================== */
.callout {
margin-top: 20px;
padding: 14px 16px;
background: var(--bg-page);
border: 1px solid var(--border-default);
border-radius: 10px;
font-size: 13px;
color: var(--text-muted-foreground);
line-height: 1.55;
border-left: 3px solid var(--warning);
}
.callout strong { color: var(--text-heading); font-weight: 600; }
/* =================== State detail row =================== */
.states-title {
margin-top: 48px;
font-family: 'Bricolage Grotesque', sans-serif;
font-weight: 600;
font-size: 18px;
color: var(--text-heading);
}
.states-sub {
margin-top: 4px;
color: var(--text-muted-foreground);
font-size: 13px;
}
.states {
margin-top: 16px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.state {
background: var(--bg-page);
border: 1px solid var(--border-default);
border-radius: 10px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.state-label {
padding: 10px 14px;
border-bottom: 1px solid var(--border-default);
font-family: 'Bricolage Grotesque', sans-serif;
font-weight: 600;
font-size: 12.5px;
color: var(--text-heading);
background: var(--bg-sidebar);
}
.state-body {
padding: 0;
background: var(--bg-page);
min-height: 220px;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.state-mini-chat {
flex: 1;
padding: 14px;
opacity: 0.55;
font-size: 11px;
color: var(--text-muted);
display: flex;
align-items: flex-end;
font-family: 'JetBrains Mono', monospace;
}
/* Collapsed banner variant */
.banner-collapsed {
border-top: 1px solid var(--warning-border);
background: var(--warning-dim);
padding: 8px 14px;
display: flex;
align-items: center;
gap: 10px;
font-size: 12px;
color: var(--text-primary);
position: relative;
}
.banner-collapsed::before {
content: '';
position: absolute;
left: 0; top: 0; bottom: 0;
width: 3px;
background: var(--warning);
}
.banner-collapsed-title {
font-weight: 500;
color: var(--text-heading);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.banner-collapsed .pill {
padding: 1px 7px;
border-radius: 999px;
background: rgba(251, 191, 36, 0.20);
color: var(--warning);
font-size: 10.5px;
font-weight: 700;
}
.banner-collapsed .expand {
color: var(--text-muted-foreground);
font-size: 11px;
}
/* mini composer for the detail states */
.mini-composer {
border-top: 1px solid var(--border-default);
padding: 10px 14px;
display: flex;
gap: 8px;
align-items: center;
}
.mini-input {
flex: 1;
background: var(--bg-card);
border: 1px solid var(--border-default);
border-radius: 8px;
padding: 7px 10px;
font-size: 11.5px;
color: var(--text-muted);
}
.mini-send {
width: 28px; height: 28px;
border-radius: 7px;
background: var(--accent);
color: #0a0d14;
border: 0;
font-size: 14px;
display: flex; align-items: center; justify-content: center;
}
/* pill in chat stream (replaced state) */
.replaced-note {
align-self: flex-end;
font-size: 10.5px;
color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
padding: 4px 8px;
background: var(--bg-card);
border: 1px dashed var(--border-hover);
border-radius: 6px;
}
/* annotation captions under each state */
.state-caption {
padding: 10px 14px 12px;
font-size: 11.5px;
color: var(--text-muted-foreground);
line-height: 1.5;
border-top: 1px solid var(--border-default);
background: var(--bg-sidebar);
}
.state-caption strong { color: var(--text-heading); font-weight: 600; }
.lane-body::-webkit-scrollbar { width: 6px; }
.lane-body::-webkit-scrollbar-thumb { background: var(--border-hover); border-radius: 3px; }
.chat-scroll::-webkit-scrollbar { width: 6px; }
.chat-scroll::-webkit-scrollbar-thumb { background: var(--border-hover); border-radius: 3px; }
</style>
</head>
<body>
<div class="page">
<div class="page-header">
<div class="page-title">Option C — Suggested Fix slides up from the chat composer</div>
<div class="page-sub">
The AI's proposal docks as a persistent banner just above the chat composer — right where the engineer's eyes already are. Apply lives on the banner (warning amber). <em>Resolve</em> stays generic at the bottom of the task lane, so there's no false-resolve risk. The Suggested Fix card is removed from the task lane entirely.
</div>
</div>
<!-- ============ MAIN: Armed + expanded ============ -->
<div class="frame">
<div class="chat">
<div class="chat-head">
<div>
<div class="chat-head-title">Outlook won't authenticate after tenant migration</div>
<div class="chat-head-sub">ticket #48213 · in progress · 14:22</div>
</div>
<div class="chat-head-actions">
<button class="btn btn-ghost">Share update</button>
<button class="btn icon-btn" aria-label="More">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></svg>
</button>
</div>
</div>
<div class="chat-scroll">
<div class="msg ai">
<div class="msg-av">AI</div>
<div>
<div class="msg-body">
A few things we know line up with a stale-credential pattern rather than an MFA or network issue. Can you confirm whether the user has other Microsoft 365 services (Teams, SharePoint) working on the same workstation?
</div>
<div class="msg-meta">14:16</div>
</div>
</div>
<div class="msg user">
<div>
<div class="msg-body">Teams works fine. SharePoint in browser is fine too. It's just Outlook.</div>
<div class="msg-meta">14:17</div>
</div>
<div class="msg-av">ME</div>
</div>
<div class="msg ai">
<div class="msg-av">AI</div>
<div>
<div class="msg-body">
That narrows it to the Outlook profile specifically. Given Credential Manager still has entries pointing at the prior tenant, the cleanest path is to clear those entries and rebuild the local Outlook profile — the client will re-auth against the current tenant from scratch.
</div>
<div class="msg-meta">14:22</div>
</div>
</div>
</div>
<!-- ============ Slide-up banner ============ -->
<div class="composer-wrap">
<div class="proposal-banner" role="region" aria-label="AI proposed fix">
<div class="proposal-icon">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>
</div>
<div class="proposal-body">
<div class="proposal-head">
<span>Suggested Fix</span>
<span class="pill">94% confidence</span>
</div>
<div class="proposal-title">Clear cached credentials + rebuild Outlook profile</div>
<div class="proposal-desc">
Remove stale Credential Manager entries referencing the prior tenant, then rebuild the local Outlook profile so the client re-authenticates cleanly against the current tenant.
</div>
<div class="proposal-hint">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
Matches an existing Script Library template — one-click apply
</div>
</div>
<div class="proposal-actions">
<button class="btn btn-ghost" aria-label="Collapse banner">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</button>
<button class="btn btn-ghost" aria-label="Dismiss fix">Dismiss</button>
<button class="btn btn-apply">
Apply fix
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
</button>
</div>
</div>
<div class="composer">
<div class="composer-input">Ask a follow-up, paste an error, drop a screenshot…</div>
<button class="composer-send" aria-label="Send">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
</div>
</div>
<!-- ============ Task lane (no Suggested Fix card) ============ -->
<div class="lane">
<div class="lane-head">
<div class="lane-head-label">Task lane</div>
</div>
<div class="lane-body">
<section>
<div class="section-label">
<span class="dot dot-accent"></span>
What we know
<span class="section-meta">· 5 facts</span>
</div>
<div class="fact">
<div class="fact-title">User cannot authenticate to Outlook; repeated 401s from Exchange Online.</div>
<div class="fact-meta">promoted 14:02 · from ticket</div>
</div>
<div class="fact">
<div class="fact-title">Credential Manager still references the prior tenant from six months ago.</div>
<div class="fact-meta">promoted 14:07 · from chat</div>
</div>
<div class="fact">
<div class="fact-title">MFA prompt appears but fails silently — no authenticator notification.</div>
<div class="fact-meta">promoted 14:11 · from chat</div>
</div>
<div class="fact">
<div class="fact-title">Other devices under same account authenticate successfully.</div>
<div class="fact-meta">promoted 14:14 · from chat</div>
</div>
<div class="fact">
<div class="fact-title">Teams + SharePoint work on same workstation — isolated to Outlook.</div>
<div class="fact-meta">promoted 14:22 · from chat</div>
</div>
</section>
</div>
<div class="action-bar">
<button class="btn btn-escalate">Escalate</button>
<button class="btn btn-resolve">Resolve</button>
</div>
</div>
</div>
<div class="callout">
<strong>How it reads.</strong> Proposal arrives with a 320ms slide-up from below the composer, docks as a persistent banner until applied, dismissed, or replaced. Apply is amber (not accent-blue) so it visually belongs to the proposal, not the chat send button. Resolve in the task lane stays generic — there's no false-resolve risk because the two actions are spatially and visually separate.
</div>
<!-- ============ State detail row ============ -->
<div class="states-title">Banner states</div>
<div class="states-sub">What the same region looks like in the other three states — collapsed to save chat space, after the engineer dismisses it, and when a new proposal replaces an existing one.</div>
<div class="states">
<!-- STATE 1: Collapsed -->
<div class="state">
<div class="state-label">Collapsed (saves chat space)</div>
<div class="state-body">
<div class="state-mini-chat">…earlier messages…</div>
<div class="banner-collapsed">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="var(--warning)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>
<span class="banner-collapsed-title">Clear cached credentials + rebuild Outlook profile</span>
<span class="pill">94%</span>
<span class="expand">▸ expand</span>
</div>
<div class="mini-composer">
<div class="mini-input">Type a message…</div>
<button class="mini-send"></button>
</div>
</div>
<div class="state-caption">
<strong>~28px strip.</strong> Auto-collapses after 30s of no interaction, or when the engineer clicks the chevron. Title + confidence still visible. Click strip → expands. Apply still reachable via the expanded state.
</div>
</div>
<!-- STATE 2: Dismissed (pill in lane) -->
<div class="state">
<div class="state-label">Dismissed — parked in the task lane</div>
<div class="state-body">
<div class="state-mini-chat">chat unobstructed · banner gone</div>
<div class="mini-composer">
<div class="mini-input">Type a message…</div>
<button class="mini-send"></button>
</div>
</div>
<div style="padding: 12px 14px; background: var(--bg-sidebar); border-top: 1px solid var(--border-default);">
<div class="section-label" style="padding-bottom: 6px">
<span class="dot dot-muted"></span>
Dismissed proposals
<span class="section-meta">· 1</span>
</div>
<div class="dismissed-pill">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="var(--warning)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>
<span style="flex:1;color:var(--text-heading)">Clear cached credentials…</span>
<span style="color:var(--text-muted)">restore ↺</span>
</div>
</div>
<div class="state-caption">
<strong>Recoverable, out of the way.</strong> Dismissing the banner parks the proposal as a pill in the task lane. Clicking restore → banner slides back in. Prevents accidental loss.
</div>
</div>
<!-- STATE 3: Replaced -->
<div class="state">
<div class="state-label">Replaced — new proposal overrides old</div>
<div class="state-body">
<div class="state-mini-chat" style="flex-direction:column;align-items:flex-end;gap:8px;justify-content:flex-end;">
<span class="replaced-note">previous: "Rebuild Outlook profile" — didn't resolve, new proposal below</span>
</div>
<div class="proposal-banner" style="padding:10px 14px;gap:10px;">
<div class="proposal-icon" style="width:22px;height:22px;border-radius:6px">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>
</div>
<div class="proposal-body">
<div class="proposal-head" style="font-size:9px">
<span>New suggested fix</span>
<span class="pill" style="font-size:9.5px;padding:1px 6px">78%</span>
</div>
<div class="proposal-title" style="font-size:12.5px">Reset Autodiscover registry entries for this user</div>
</div>
<button class="btn btn-apply" style="padding:6px 10px;font-size:11.5px">Apply</button>
</div>
<div class="mini-composer">
<div class="mini-input">Type a message…</div>
<button class="mini-send"></button>
</div>
</div>
<div class="state-caption">
<strong>Old proposal cross-fades out, new one slides in.</strong> 200ms cross-fade, same slot. A tiny footnote in chat ("previous didn't resolve") preserves the audit trail without re-stacking banners.
</div>
</div>
</div>
</div>
</body>
</html>