import SwiftUI struct RootView: View { @EnvironmentObject private var app: AppModel var body: some View { ZStack { McColors.bg.ignoresSafeArea() switch app.phase { case .boot: SplashView() case .server: ServerChoiceScreen() case .auth: AuthChoiceScreen() case .password: PasswordLoginScreen() case .link: LinkScreen() case .profiles: ProfilesScreen() case .main: MainShell() } } .animation(.easeInOut(duration: 0.28), value: app.phase) .sheet(item: approveSheetBinding) { item in DeviceApproveSheet(code: item.code) .environmentObject(app) .presentationDetents([.medium, .large]) } } private var approveSheetBinding: Binding { Binding( get: { guard let code = app.pendingApproveCode, app.phase == .main else { return nil } return ApproveCodeItem(code: code) }, set: { newValue in if newValue == nil { app.clearPendingApprove() } } ) } } private struct ApproveCodeItem: Identifiable { let code: String var id: String { code } } struct SplashView: View { @State private var pulse = false var body: some View { VStack(spacing: 18) { Text("VMC") .font(McFonts.brand) .foregroundStyle(McColors.accent) .scaleEffect(pulse ? 1.04 : 0.96) .shadow(color: McColors.accent.opacity(0.45), radius: pulse ? 24 : 8) ProgressView() .tint(McColors.textDim) } .onAppear { withAnimation(.easeInOut(duration: 1.1).repeatForever(autoreverses: true)) { pulse = true } } } }