import SwiftUI // Calm 2.0: one insight at a time instead of a chip carousel — a quiet, // glanceable line under the check-in zone. Tap to cycle through the rest. struct InsightsRow: View { let insights: [PortfolioInsight] @State private var index = 0 private var current: PortfolioInsight? { guard !insights.isEmpty else { return nil } return insights[index % insights.count] } var body: some View { if let insight = current { Button { withAnimation(.snappy) { index = (index + 1) % insights.count } } label: { HStack(spacing: 12) { Image(systemName: insight.systemImage) .font(.subheadline.weight(.semibold)) .foregroundColor(insight.accentColor) .frame(width: 30, height: 30) .background(insight.accentColor.opacity(0.12)) .clipShape(Circle()) VStack(alignment: .leading, spacing: 1) { Text(insight.title) .font(.caption) .foregroundColor(.secondary) Text(insight.value) .font(.subheadline.weight(.semibold)) .foregroundColor(.primary) .lineLimit(2) if let detail = insight.detail { Text(detail) .font(.caption2) .foregroundColor(.secondary) .lineLimit(1) } } Spacer() if insights.count > 1 { HStack(spacing: 4) { ForEach(insights.indices, id: \.self) { i in Circle() .fill(i == index % insights.count ? Color.secondary : Color.secondary.opacity(0.25)) .frame(width: 5, height: 5) } } } } .padding(14) .background(Color(.secondarySystemGroupedBackground)) .cornerRadius(AppConstants.UI.cornerRadius) } .buttonStyle(.plain) .id(insight.id) .transition(.opacity) } } }