DocDoeAI / src /components /landing /RealClassProof.tsx
asnannp's picture
deploy: sync backend to Space root (learn-lesson HF cache fix)
65d68f5
Raw History Blame Contribute Delete
9.22 kB
"use client";
/**
* Trust section: real board frames from the current teaching pipeline.
* No promo video. Proof is the board the student will actually study from.
*/
import Image from "next/image";
import { motion, useReducedMotion, type Variants } from "framer-motion";
const revealEase = [0.16, 1, 0.3, 1] as const;
const reveal: Variants = {
hidden: { opacity: 0, y: 16 },
visible: (step = 0) => ({
opacity: 1,
y: 0,
transition: { duration: 0.6, delay: step * 0.07, ease: revealEase },
}),
};
const classFacts = [
{
value: "41 min",
label: "full chapter class",
detail: "Sound Waves taught end to end: concept, formula, numericals, exam answers, revision.",
},
{
value: "11 steps",
label: "every single class",
detail: "Session plan through teach, board, practice, correction, quiz, and revision.",
},
{
value: "Board answers",
label: "exam keywords",
detail: "2-mark and 5-mark answers with the scoring words examiners look for.",
},
{
value: "Honest beta",
label: "one chapter ready",
detail: "Sound Waves is complete. The rest of Physics is marked clearly as next.",
},
];
const teachingFrames = [
{
src: "/demo/board/02-concept.jpg",
alt: "DocDoe board teaching longitudinal wave concept",
caption: "Concepts labelled for understanding, not scrolling.",
tag: "Concept",
},
{
src: "/demo/board/03-formula.jpg",
alt: "DocDoe board showing wave formula derivation",
caption: "Formulas appear with the derivation path, not only the final line.",
tag: "Formula",
},
{
src: "/demo/board/04-mistakes.jpg",
alt: "DocDoe board calling out common exam mistakes",
caption: "Common mistakes called out before the exam, not after.",
tag: "Mistakes",
},
{
src: "/demo/board/05-exam-answer.jpg",
alt: "DocDoe board-style exam answer with scoring keywords",
caption: "Board-style answers with the exact scoring keywords.",
tag: "Exam answer",
},
{
src: "/demo/board/06-practice.jpg",
alt: "DocDoe practice question board frame",
caption: "You attempt first. The answer comes after thinking time.",
tag: "Practice",
},
{
src: "/demo/board/07-revision.jpg",
alt: "DocDoe revision recap board frame",
caption: "Revision is saved so tomorrow continues from tonight.",
tag: "Revision",
},
];
export function RealClassProof() {
const reduceMotion = Boolean(useReducedMotion());
return (
<section
id="real-class"
className="relative isolate overflow-hidden px-5 py-24 font-sans sm:px-8 sm:py-32"
aria-label="Real DocDoe board frames from class"
>
<div className="relative z-10 mx-auto w-full max-w-[1180px]">
<motion.div
initial={reduceMotion ? false : "hidden"}
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
className="grid gap-8 lg:grid-cols-[1fr_auto] lg:items-end"
>
<div className="max-w-[720px]">
<motion.p
className="text-[11px] font-semibold uppercase tracking-[0.2em] text-white/45"
variants={reduceMotion ? undefined : reveal}
>
Proof, not promises
</motion.p>
<motion.h2
className="font-display mt-4 text-balance text-[clamp(2.15rem,5.2vw,3.4rem)] font-semibold leading-[1.02] tracking-[-0.04em] text-[#F2F4F1]"
variants={reduceMotion ? undefined : reveal}
custom={1}
>
This is the board students study from.
</motion.h2>
<motion.p
className="mt-5 max-w-[54ch] text-base font-normal leading-relaxed text-[rgba(242,244,241,0.58)] sm:text-[17px]"
variants={reduceMotion ? undefined : reveal}
custom={2}
>
Frames from the real Sound Waves class render. Same teaching engine
that runs inside tuition. No stock photos. No fake studio footage.
</motion.p>
</div>
<motion.p
className="max-w-[220px] text-right text-[12px] leading-relaxed text-white/35 lg:pb-1"
variants={reduceMotion ? undefined : reveal}
custom={3}
>
Kerala SSLC Class 10 Physics
<br />
Rendered by DocDoe
</motion.p>
</motion.div>
{/* Featured frame */}
<motion.figure
className="mt-12"
initial={reduceMotion ? false : "hidden"}
whileInView="visible"
viewport={{ once: true, amount: 0.15 }}
variants={reduceMotion ? undefined : reveal}
custom={1}
>
<div className="docdoe-board-stage">
<div className="docdoe-board-stage-chrome">
<div className="flex items-center gap-2">
<span className="docdoe-board-live-dot" aria-hidden="true" />
<span className="text-[10px] font-semibold uppercase tracking-[0.18em] text-white/55">
Real class board
</span>
</div>
<span className="text-[10px] font-medium uppercase tracking-[0.14em] text-white/30">
Sound Waves · concept
</span>
</div>
<div className="docdoe-board-frame relative aspect-video overflow-hidden bg-[#0B0F0E]">
<Image
src="/demo/board/hero-frame.jpg"
alt="DocDoe class board teaching Sound Waves with longitudinal wave diagram"
fill
className="object-cover"
sizes="(min-width: 1180px) 1180px, 100vw"
priority
/>
</div>
<figcaption className="docdoe-board-stage-caption">
<div className="min-w-0">
<p className="text-sm font-semibold text-white/80">
Longitudinal waves · understanding label on the board
</p>
<p className="mt-0.5 text-xs text-white/40">
From the current Physics course render, not a marketing edit
</p>
</div>
</figcaption>
</div>
</motion.figure>
<motion.dl
className="mt-14 grid grid-cols-1 gap-x-8 gap-y-8 border-t border-white/10 pt-10 sm:grid-cols-2 lg:grid-cols-4"
initial={reduceMotion ? false : "hidden"}
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
aria-label="Facts from the DocDoe teaching engine"
>
{classFacts.map((fact, i) => (
<motion.div key={fact.label} variants={reduceMotion ? undefined : reveal} custom={i}>
<dt className="sr-only">{fact.label}</dt>
<dd>
<p className="font-display text-2xl font-semibold tracking-tight text-white sm:text-3xl">
{fact.value}
</p>
<p className="mt-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-white/50">
{fact.label}
</p>
<p className="mt-2.5 text-sm font-normal leading-relaxed text-white/45">
{fact.detail}
</p>
</dd>
</motion.div>
))}
</motion.dl>
<motion.div
className="mt-16"
initial={reduceMotion ? false : "hidden"}
whileInView="visible"
viewport={{ once: true, amount: 0.12 }}
>
<motion.h3
className="font-display text-xl font-semibold tracking-tight text-white sm:text-2xl"
variants={reduceMotion ? undefined : reveal}
>
Six moments from the same class
</motion.h3>
<div className="mt-8 grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
{teachingFrames.map((frame, i) => (
<motion.figure
key={frame.src}
className="group"
variants={reduceMotion ? undefined : reveal}
custom={i}
>
<div className="overflow-hidden rounded-xl border border-white/10 bg-[#0B0F0E] transition-[border-color] duration-200 group-hover:border-white/20">
<div className="relative aspect-video">
<Image
src={frame.src}
alt={frame.alt}
fill
className="object-cover"
sizes="(min-width: 1024px) 360px, (min-width: 640px) 50vw, 100vw"
/>
</div>
</div>
<figcaption className="mt-3">
<span className="text-[10px] font-semibold uppercase tracking-[0.16em] text-white/35">
{frame.tag}
</span>
<p className="mt-1 text-sm font-normal leading-relaxed text-white/55">
{frame.caption}
</p>
</figcaption>
</motion.figure>
))}
</div>
</motion.div>
</div>
</section>
);
}