ai-dispatch 10.38.0

Multi-AI CLI team orchestrator
// Toast notification sliding in from trailing edge.
// Exports: ToastView, ToastStack.

import SwiftUI

struct ToastView: View {
    @Environment(\.theme) private var theme
    let toast: ToastEvent

    var body: some View {
        HStack(spacing: theme.spacing.sm) {
            Text(StatusMapper.mark(for: toast.state))
                .font(theme.font(.value))
                .foregroundStyle(edgeColor)
            VStack(alignment: .leading, spacing: 2) {
                Text(toast.title)
                    .font(theme.font(.body))
                    .foregroundStyle(theme.ink)
                    .lineLimit(1)
                Text("\(toast.missionID) ยท +\(toast.xpAward) XP")
                    .font(theme.font(.caption))
                    .foregroundStyle(theme.ink2)
                    .lineLimit(1)
            }
        }
        .padding(theme.spacing.md)
        .background(theme.bg)
        .overlay(
            Rectangle()
                .fill(edgeColor)
                .frame(width: 3),
            alignment: .leading
        )
        .clipShape(PanelShape(style: theme.panelStyle))
        .shadow(color: edgeColor.opacity(0.3), radius: 8)
        .frame(maxWidth: 320, alignment: .leading)
        .fixedSize(horizontal: true, vertical: true)
    }

    private var edgeColor: Color {
        toast.state == .done ? theme.done : theme.fail
    }
}

struct ToastStack: View {
    @Environment(\.theme) private var theme
    let toasts: [ToastEvent]

    var body: some View {
        VStack(alignment: .trailing, spacing: theme.spacing.sm) {
            ForEach(toasts) { toast in
                ToastView(toast: toast)
                    .transition(.move(edge: .trailing).combined(with: .opacity))
            }
        }
        .padding(theme.spacing.lg)
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
        .allowsHitTesting(false)
        .animation(.easeOut(duration: theme.motion.crossfade), value: toasts)
    }
}