"use client" /** * ExamLockTemplate — locked assessment shell (exam / proctored delivery). * * Brand-tint canvas (`bg-sidebar`) + transparent `ExamLockAppHeader` + inset main card * (`rounded-xl`, margin, shadow) — same elevation rhythm as `SidebarInset` hubs. * * Hides workspace chrome via `App.tsx` + `SidebarAutoCollapse`. * * Reference: `@/components/exam-lock` + `components/exam-lock-showcase-client.tsx` (Design OS). */ import * as React from "react" import { ExamLockAppHeader, type ExamLockLearnerIdentity } from "@/components/exam-lock/exam-lock-app-header" import { SidebarAutoCollapse } from "@/components/sidebar" import { useScrollStuck } from "@/hooks/use-scroll-stuck" import { useSidebarReflowZoom } from "@/hooks/use-sidebar-reflow-zoom" import { cn } from "@/lib/utils" export type { ExamLockLearnerIdentity } export interface ExamLockTemplateProps { /** Exam title — rendered as the page `

` in the lock app header. */ title: string /** Optional descriptor below the title (omit for exam lock delivery). */ subtitle?: React.ReactNode /** Answered-question progress — flush at the top of the main card. */ progress?: React.ReactNode /** When true, warns on tab close / refresh via `beforeunload`. */ sessionActive: boolean /** After submit — replaces body with a no-navigation confirmation screen. */ submitted?: boolean /** Optional timer node (right-aligned in the app header). */ timer?: React.ReactNode /** Keyboard, calculator, settings — rendered before timer / submit. */ headerToolbar?: React.ReactNode /** Right-aligned header actions (default: none — caller supplies Submit in `headerActions`). */ headerActions?: React.ReactNode /** Learner identity — avatar at the far right of the app header. */ learner?: ExamLockLearnerIdentity /** * Soft session notices (sync lag, non-blocking hints) below the header. * Hard integrity pauses use `interruption` + `useExamLockSessionController`. */ sessionAlert?: React.ReactNode /** Pause surface behind the question card — revealed when the card slides down. */ interruption?: React.ReactNode /** When true, the question card slides down to reveal `interruption`. */ sessionPaused?: boolean /** Applied to the scrollable body below the header (e.g. display mode classes). */ surfaceClassName?: string maxWidthClassName?: string bodyClassName?: string contentClassName?: string /** Custom submitted screen; default copy is exam-safe (no links). */ submittedContent?: React.ReactNode children: React.ReactNode } function DefaultSubmittedScreen({ title }: { title: string }) { return (