// Step 7 / Final — Generate timetable result page.
const STEP7_FRAME = { x: 96, y: 32, w: 1728, h: 1016 };

// Beat plan (~11s):
//  0.0 – 0.4   Scene fades in
//  0.4 – 1.0   "Generating…" spinner state
//  1.0 – 1.8   Spinner → "Generation complete" card pops in (check + summary)
//  1.8 – 2.7   5 stat tiles cascade (numbers count up)
//  2.7 – 3.3   Tip banner + View controls appear
//  3.3 – 5.8   Timetable grid cells fill in row-by-row, period-by-period (colorful cascade)
//  5.8 – 7.5   Hold on completed grid
//  7.5 – 8.4   Cursor glides to "Save timetable"
//  8.4 – 8.7   Click + halo + confetti
//  8.7 – 9.7   Saved confirmation
//  9.7 – 11    Fade

// Schedule data — Class 7-A week
const TT_DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
const TT_PERIODS = 10; // includes 2 breaks at indices 3, 7
const TT_SCHEDULE = [
  // Mon
  [{s:'Hindi', t:'Ranjana'}, {s:'Social', t:'Bhavna'}, {s:'English', t:'Bhavna'}, 'break-short', {s:'English', t:'Bhavna'}, {s:'Science', t:'Riya'}, {s:'Math', t:'Kavita'}, 'break-lunch', {s:'Social', t:'Bhavna'}, {s:'Punjabi', t:'Seema'}],
  // Tue
  [{s:'Dance', t:'Manish'}, {s:'Social', t:'Bhavna'}, {s:'GK', t:'Meera'}, 'break-short', {s:'Math', t:'Kavita'}, {s:'Music', t:'Devika'}, {s:'Stem', t:'Riya'}, 'break-lunch', {s:'PE', t:'Hitesh'}, {s:'PE', t:'Hitesh'}],
  // Wed
  [{s:'Science', t:'Riya'}, {s:'Hindi', t:'Ranjana'}, {s:'Punjabi', t:'Seema'}, 'break-short', {s:'Dance', t:'Manish'}, {s:'Math', t:'Kavita'}, {s:'English', t:'Bhavna'}, 'break-lunch', {s:'Math', t:'Kavita'}, {s:'Social', t:'Bhavna'}],
  // Thu
  [{s:'French', t:'Neelam'}, {s:'Art', t:'Pooja'}, {s:'IT', t:'Tarun'}, 'break-short', {s:'Value', t:'Latha'}, {s:'Science', t:'Riya'}, {s:'English', t:'Bhavna'}, 'break-lunch', {s:'IT', t:'Tarun'}, {s:'Hindi', t:'Ranjana'}],
  // Fri
  [{s:'Science', t:'Riya'}, {s:'Social', t:'Bhavna'}, {s:'Music', t:'Devika'}, 'break-short', {s:'Value', t:'Latha'}, {s:'Art', t:'Pooja'}, {s:'Punjabi', t:'Seema'}, 'break-lunch', {s:'Hindi', t:'Ranjana'}, {s:'Library', t:'Meera'}],
];

const TT_COLORS = {
  Hindi: { bg: '#e2f2ea', bar: '#10b981', text: '#065f46' },
  Social: { bg: '#ece4f8', bar: '#8b5cf6', text: '#5b21b6' },
  English: { bg: '#e7edff', bar: '#6366f1', text: '#3730a3' },
  Math: { bg: '#e8efff', bar: '#3b82f6', text: '#1e3a8a' },
  Science: { bg: '#fde8e6', bar: '#ef4444', text: '#991b1b' },
  Dance: { bg: '#e7e5ff', bar: '#818cf8', text: '#3730a3' },
  GK: { bg: '#ece2f0', bar: '#a855f7', text: '#6b21a8' },
  Music: { bg: '#ece2f0', bar: '#a855f7', text: '#6b21a8' },
  Stem: { bg: '#fde6e1', bar: '#fb7185', text: '#9f1239' },
  PE: { bg: '#e3f1e7', bar: '#22c55e', text: '#15803d' },
  Punjabi: { bg: '#fde4ee', bar: '#ec4899', text: '#9d174d' },
  French: { bg: '#e2ecff', bar: '#3b82f6', text: '#1e3a8a' },
  Art: { bg: '#fce7e2', bar: '#ef4444', text: '#9b2c2c' },
  IT: { bg: '#fdf3dd', bar: '#d97706', text: '#92400e' },
  Value: { bg: '#fdf0d6', bar: '#d97706', text: '#92400e' },
  Library: { bg: '#dff4ee', bar: '#14b8a6', text: '#115e59' },
};

const SUBJECT_FULL = {
  Social: 'Social Scie...', Math: 'Mathematics', Stem: 'Stem', PE: 'PE',
  Value: 'Value Educ...', Library: 'Library', GK: 'GK',
};

function GenerationSceneChrome() {
  return (
    <div style={{
      height: 80, padding: '0 36px',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      borderBottom: `1px solid ${BRAND.borderSoft}`,
      background: BRAND.bg,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: BRAND.greenSoft,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M3 21h18M5 21V7l7-4 7 4v14M9 9h.01M15 9h.01M9 13h.01M15 13h.01M9 17h.01M15 17h.01"/>
          </svg>
        </div>
        <div>
          <div style={{ fontSize: 18, fontWeight: 700, color: BRAND.ink, lineHeight: 1.1 }}>Sunridge Academy</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 4 }}>
            <span style={{ fontSize: 12, color: BRAND.inkSoft, whiteSpace: 'nowrap' }}>2025-26</span>
            <span style={{
              fontSize: 11, fontWeight: 600,
              padding: '2px 7px', borderRadius: 6,
              background: '#fef3c7', color: '#92400e',
              whiteSpace: 'nowrap',
            }}>Admin</span>
          </div>
        </div>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        <div style={{
          padding: '7px 14px', borderRadius: 999,
          background: BRAND.greenSoft, color: BRAND.green,
          fontSize: 13, fontWeight: 600,
          display: 'flex', alignItems: 'center', gap: 8,
          whiteSpace: 'nowrap',
        }}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M2 6l5 4 5-7 5 7 5-4-2 13H4z"/></svg>
          Growth
        </div>
        <div style={{ width: 30, height: 30, borderRadius: 999, border: `1px solid ${BRAND.border}`, display: 'flex', alignItems: 'center', justifyContent: 'center', color: BRAND.inkSoft }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79z"/></svg>
        </div>
        <div style={{ width: 30, height: 30, borderRadius: 999, background: BRAND.green, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 600 }}>C</div>
      </div>
    </div>
  );
}

function StatTile({ icon, label, value, opacity, scale }) {
  return (
    <div style={{
      opacity, transform: `scale(${scale})`,
      background: '#fff', border: `1px solid ${BRAND.border}`,
      borderRadius: 12, padding: '16px 18px',
      display: 'flex', alignItems: 'center', gap: 14,
      boxShadow: BRAND.shadow,
      transition: 'opacity 240ms, transform 240ms',
    }}>
      <div style={{
        width: 38, height: 38, borderRadius: 10,
        background: BRAND.greenSofter,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        flexShrink: 0,
      }}>{icon}</div>
      <div>
        <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: BRAND.inkSub, whiteSpace: 'nowrap' }}>{label}</div>
        <div style={{ fontSize: 22, fontWeight: 700, color: BRAND.ink, letterSpacing: '-0.02em', marginTop: 2, fontVariantNumeric: 'tabular-nums' }}>{value}</div>
      </div>
    </div>
  );
}

function Step7Video({ start = 0 }) {
  const t = useTime();
  const lt = t - start;

  const fadeIn = interpolate([0, 0.4], [0, 1], Easing.easeOutCubic)(lt);
  const fadeOut = interpolate([10.4, 11.0], [1, 0], Easing.easeInCubic)(lt);
  const sceneOp = fadeIn * fadeOut;

  // Phase: 0-1.0 = generating, 1.0+ = complete
  const isGenerating = lt < 1.0;
  const completeOp = interpolate([1.0, 1.6], [0, 1], Easing.easeOutCubic)(lt);
  const completeScale = interpolate([1.0, 1.6], [0.92, 1], Easing.easeOutBack)(lt);

  // Stat tiles cascade 1.8-2.7
  const tileT = (i) => interpolate([1.8 + i*0.12, 2.2 + i*0.12], [0, 1], Easing.easeOutBack)(lt);

  // Banner + view controls appear 2.7
  const ctrlOp = interpolate([2.7, 3.3], [0, 1], Easing.easeOutCubic)(lt);

  // Grid cells cascade — by day then by period
  const gridStart = 3.3;
  const gridEnd = 5.8;
  const cellStaggerStep = (gridEnd - gridStart) / (5 * TT_PERIODS); // ~0.05s per cell
  const cellT = (day, period) => {
    const ct = gridStart + (day * TT_PERIODS + period) * cellStaggerStep;
    return interpolate([ct, ct + 0.3], [0, 1], Easing.easeOutCubic)(lt);
  };

  // Save click
  const saveClickT = 8.4;
  const saveHot = lt > 8.0 && lt < 8.7;
  const clkT = (lt - saveClickT) / 0.18;
  const clickSquish = clkT > 0 && clkT < 1 ? 0.05 * Math.sin(clkT * Math.PI) : 0;
  const haloOp = interpolate([saveClickT, saveClickT + 0.3, saveClickT + 0.9], [0, 0.8, 0], Easing.easeOutCubic)(lt);
  const haloScale = interpolate([saveClickT, saveClickT + 0.9], [1, 2.0], Easing.easeOutCubic)(lt);

  // Cursor — moves to Save button at top right
  const path = [
    { t: 6.8, x: 1900, y: 1100 },
    { t: 8.2, x: 1700, y: 440 },  // Save timetable button
    { t: 8.4, x: 1700, y: 440 },
    { t: 11.0, x: 1700, y: 440 },
  ];
  const cur = (() => {
    if (lt < path[0].t) return { x: path[0].x, y: path[0].y, op: 0 };
    if (lt >= path[path.length-1].t) return { x: path[path.length-1].x, y: path[path.length-1].y, op: 1 };
    for (let i = 0; i < path.length - 1; i++) {
      if (lt >= path[i].t && lt <= path[i+1].t) {
        const seg = (lt - path[i].t) / (path[i+1].t - path[i].t || 1);
        const e = Easing.easeInOutCubic(seg);
        return { x: path[i].x + (path[i+1].x - path[i].x) * e, y: path[i].y + (path[i+1].y - path[i].y) * e, op: 1 };
      }
    }
    return { x: path[0].x, y: path[0].y, op: 1 };
  })();
  const cursorFadeOut = interpolate([9.5, 10.0], [1, 0], Easing.easeInCubic)(lt);
  const cursorOp = cur.op * cursorFadeOut;
  const settle = lt > saveClickT && lt < saveClickT + 0.4
    ? Math.sin((lt - saveClickT) * 30) * 1.5 * Math.exp(-(lt - saveClickT) * 8) : 0;

  // Spinner rotation
  const spinnerAngle = (lt * 360 * 1.5) % 360;

  // Confetti
  const confetti = React.useMemo(() => {
    const arr = [];
    for (let i = 0; i < 30; i++) {
      const angle = (i / 30) * Math.PI * 2 + Math.random() * 0.3;
      const dist = 240 + Math.random() * 240;
      const colors = ['#10b981', '#3b82f6', '#f59e0b', '#ec4899', '#8b5cf6', '#ef4444', '#14b8a6'];
      arr.push({
        angle, dist,
        size: 5 + Math.random() * 8,
        color: colors[Math.floor(Math.random() * colors.length)],
        delay: Math.random() * 0.15,
      });
    }
    return arr;
  }, []);
  const saved = lt > saveClickT;

  return (
    <div style={{ position: 'absolute', inset: 0, opacity: sceneOp }}>
      <AppFrame x={STEP7_FRAME.x} y={STEP7_FRAME.y} width={STEP7_FRAME.w} height={STEP7_FRAME.h}>
        <GenerationSceneChrome/>

        <div style={{ padding: '28px 48px' }}>
          <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', color: BRAND.inkSub }}>Schedule</div>
          <div style={{ fontSize: 38, fontWeight: 700, color: BRAND.ink, letterSpacing: '-0.02em', marginTop: 6 }}>Generate timetable</div>
          <div style={{ fontSize: 14, color: BRAND.inkSoft, marginTop: 6, maxWidth: 900 }}>
            Build the schedule for <span style={{ fontWeight: 700, color: BRAND.ink }}>Draft 2025-26</span>. You can preview before saving — nothing is committed until you confirm.
          </div>

          {/* Status card — switches from generating to complete */}
          <div style={{
            marginTop: 18,
            background: '#fff', border: `1px solid ${BRAND.border}`,
            borderRadius: 14, padding: '20px 24px',
            boxShadow: BRAND.shadow,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            minHeight: 92,
          }}>
            {isGenerating ? (
              <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2.4" strokeLinecap="round" style={{ transform: `rotate(${spinnerAngle}deg)` }}>
                  <path d="M21 12a9 9 0 11-6.219-8.56"/>
                </svg>
                <div>
                  <div style={{ fontSize: 22, fontWeight: 700, color: BRAND.ink, letterSpacing: '-0.01em' }}>Generating timetable…</div>
                  <div style={{ fontSize: 13, color: BRAND.inkSoft, marginTop: 4 }}>Placing 696 slots across 13 classes</div>
                </div>
              </div>
            ) : (
              <React.Fragment>
                <div style={{ display: 'flex', alignItems: 'center', gap: 14, opacity: completeOp, transform: `scale(${completeScale})`, transformOrigin: 'left center' }}>
                  <div style={{
                    width: 44, height: 44, borderRadius: 999,
                    background: BRAND.greenSoft,
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                  }}>
                    <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M4 12l5 5 11-12"/></svg>
                  </div>
                  <div>
                    <div style={{ fontSize: 22, fontWeight: 700, color: BRAND.ink, letterSpacing: '-0.01em' }}>{saved ? 'Timetable saved!' : 'Generation complete'}</div>
                    <div style={{ fontSize: 13, color: BRAND.inkSoft, marginTop: 4 }}>
                      All <span style={{ fontWeight: 700, color: BRAND.ink }}>696</span> slots placed cleanly. Review the preview below and save when ready.
                    </div>
                  </div>
                </div>
                {/* Action buttons */}
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, opacity: completeOp }}>
                  <div style={{
                    display: 'inline-flex', alignItems: 'center', gap: 6,
                    padding: '9px 14px', borderRadius: 8,
                    fontSize: 13, fontWeight: 600, color: BRAND.inkSoft,
                    border: `1px solid transparent`,
                  }}>
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9"/><path d="M9 9l6 6M15 9l-6 6"/></svg>
                    Discard
                  </div>
                  <div style={{
                    display: 'inline-flex', alignItems: 'center', gap: 6,
                    padding: '9px 14px', borderRadius: 8,
                    border: `1px solid ${BRAND.border}`, background: '#fff',
                    fontSize: 13, fontWeight: 600, color: BRAND.ink,
                  }}>
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M23 4v6h-6M1 20v-6h6"/><path d="M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"/></svg>
                    Regenerate
                  </div>
                  <div style={{ position: 'relative' }}>
                    {/* Confetti */}
                    {saved && confetti.map((p, i) => {
                      const pt = (lt - saveClickT - p.delay) / 1.2;
                      if (pt <= 0 || pt >= 1) return null;
                      const ease = Easing.easeOutCubic(pt);
                      const x = Math.cos(p.angle) * p.dist * ease;
                      const y = Math.sin(p.angle) * p.dist * ease + (pt * pt * 240);
                      return (
                        <div key={i} style={{
                          position: 'absolute',
                          left: '50%', top: '50%',
                          width: p.size, height: p.size,
                          background: p.color, borderRadius: 2,
                          transform: `translate(${x}px, ${y}px) rotate(${pt * 720}deg)`,
                          opacity: 1 - pt,
                          pointerEvents: 'none',
                        }}/>
                      );
                    })}
                    <div style={{
                      position: 'absolute', inset: 0, borderRadius: 8,
                      background: BRAND.greenSoft,
                      opacity: haloOp, transform: `scale(${haloScale})`,
                      pointerEvents: 'none',
                    }}/>
                    <div style={{
                      position: 'relative',
                      display: 'inline-flex', alignItems: 'center', gap: 6,
                      padding: '9px 16px', borderRadius: 8,
                      background: BRAND.green, color: '#fff',
                      fontSize: 13, fontWeight: 600,
                      transform: `scale(${1 - clickSquish})`,
                      boxShadow: saveHot ? `0 0 0 6px ${BRAND.greenSoft}, 0 8px 20px rgba(4,120,87,0.28)` : '0 2px 6px rgba(4,120,87,0.18)',
                      transition: 'box-shadow 200ms',
                      whiteSpace: 'nowrap',
                    }}>
                      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                        {saved ? <path d="M4 12l5 5 11-12"/> : <path d="M19 21H5a2 2 0 01-2-2V5a2 2 0 012-2h11l5 5v11a2 2 0 01-2 2zM17 21v-8H7v8M7 3v5h8"/>}
                      </svg>
                      {saved ? 'Saved' : 'Save timetable'}
                    </div>
                  </div>
                </div>
              </React.Fragment>
            )}
          </div>

          {/* Tip banner */}
          <div style={{
            marginTop: 14, opacity: ctrlOp,
            background: BRAND.greenSofter, border: `1px solid ${BRAND.greenMid}`,
            borderRadius: 12, padding: '14px 18px',
            display: 'flex', alignItems: 'flex-start', gap: 10,
          }}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, marginTop: 2 }}>
              <path d="M9 18h6M10 22h4M12 2a7 7 0 00-4 12.7c.6.4 1 1 1 1.6V18h6v-1.7c0-.6.4-1.2 1-1.6A7 7 0 0012 2z"/>
            </svg>
            <div style={{ fontSize: 13, color: BRAND.inkSoft, lineHeight: 1.55 }}>
              <span style={{ fontWeight: 700, color: BRAND.ink }}>Need to tweak the schedule?</span> Save the timetable, then open the <span style={{ fontWeight: 700, color: BRAND.ink }}>Timetable</span> page and click <span style={{ fontWeight: 700, color: BRAND.ink }}>Edit timetable</span>. Drag any cell to swap.
            </div>
          </div>

          {/* Stat tiles */}
          <div style={{
            marginTop: 14,
            display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 12,
          }}>
            {[
              { label: 'Slots placed',    value: '696',  icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/></svg> },
              { label: 'Fill rate',       value: '100%', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><path d="M22 4L12 14.01l-3-3"/></svg> },
              { label: 'Unfilled cells',  value: '0',    icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><path d="M12 9v4M12 17h.01"/></svg> },
              { label: 'Teacher clashes', value: '0',    icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><path d="M12 9v4M12 17h.01"/></svg> },
              { label: 'Time',            value: '57 s', icon: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={BRAND.green} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg> },
            ].map((s, i) => {
              const op = tileT(i);
              const scale = 0.92 + 0.08 * op;
              return <StatTile key={s.label} icon={s.icon} label={s.label} value={s.value} opacity={op} scale={scale}/>;
            })}
          </div>

          {/* View controls */}
          <div style={{
            marginTop: 14, opacity: ctrlOp,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            border: `1px solid ${BRAND.border}`, background: '#fff',
            borderRadius: 12, padding: '14px 18px',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 24 }}>
              <div>
                <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: BRAND.inkSub, marginBottom: 6 }}>View</div>
                <div style={{ display: 'flex', gap: 6 }}>
                  <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '6px 12px', borderRadius: 8, border: `1px solid ${BRAND.border}`, background: '#fff', fontSize: 12, fontWeight: 600, color: BRAND.ink, whiteSpace: 'nowrap' }}>
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="3"/><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z"/></svg>
                    Class
                  </div>
                  <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '6px 12px', borderRadius: 8, fontSize: 12, fontWeight: 500, color: BRAND.inkSoft, whiteSpace: 'nowrap' }}>
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="3"/><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z"/></svg>
                    Teacher
                  </div>
                </div>
              </div>
              <div>
                <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: BRAND.inkSub, marginBottom: 6 }}>Class</div>
                <div style={{ padding: '6px 12px', borderRadius: 8, border: `1px solid ${BRAND.border}`, background: '#fff', fontSize: 12, fontWeight: 600, color: BRAND.ink, minWidth: 120, whiteSpace: 'nowrap', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                  Class 7
                  <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke={BRAND.inkSub} strokeWidth="2"><path d="M6 9l6 6 6-6"/></svg>
                </div>
              </div>
              <div>
                <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: BRAND.inkSub, marginBottom: 6 }}>Section</div>
                <div style={{ padding: '6px 12px', borderRadius: 8, border: `1px solid ${BRAND.border}`, background: '#fff', fontSize: 12, fontWeight: 600, color: BRAND.ink, minWidth: 70, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                  A
                  <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke={BRAND.inkSub} strokeWidth="2"><path d="M6 9l6 6 6-6"/></svg>
                </div>
              </div>
            </div>
            <div style={{ fontSize: 13, color: BRAND.inkSoft }}>
              <span style={{ fontWeight: 700, color: BRAND.ink }}>45</span> cells in this view
            </div>
          </div>

          {/* Timetable grid */}
          <div style={{ marginTop: 14, opacity: ctrlOp, display: 'flex', flexDirection: 'column', gap: 4 }}>
            {/* Period header row */}
            <div style={{ display: 'flex', gap: 4, marginLeft: 70 }}>
              {Array.from({ length: TT_PERIODS }).map((_, p) => {
                const isShort = p === 3;
                const isLunch = p === 7;
                const periodNum = p < 3 ? p + 1 : p < 7 ? p : p - 1;
                return (
                  <div key={p} style={{
                    flex: isShort || isLunch ? '0.5' : '1',
                    height: 44,
                    background: isShort || isLunch ? '#fef3c7' : '#fff',
                    border: `1px solid ${isShort || isLunch ? '#fde68a' : BRAND.border}`,
                    borderRadius: 6,
                    display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
                  }}>
                    {(isShort || isLunch) ? (
                      <React.Fragment>
                        <div style={{ fontSize: 8, fontWeight: 700, color: '#92400e', letterSpacing: '0.1em' }}>BREAK</div>
                        <div style={{ fontSize: 10, fontWeight: 600, color: '#92400e' }}>{isShort ? 'Short' : 'Lunch'}</div>
                      </React.Fragment>
                    ) : (
                      <React.Fragment>
                        <div style={{ fontSize: 8, fontWeight: 700, color: BRAND.inkSub, letterSpacing: '0.1em' }}>PERIOD</div>
                        <div style={{ fontSize: 14, fontWeight: 700, color: BRAND.ink }}>{periodNum}</div>
                      </React.Fragment>
                    )}
                  </div>
                );
              })}
            </div>

            {/* Day rows */}
            {TT_DAYS.map((day, d) => (
              <div key={day} style={{ display: 'flex', gap: 4 }}>
                <div style={{
                  width: 66, height: 64,
                  background: '#fff', border: `1px solid ${BRAND.border}`, borderRadius: 6,
                  display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
                }}>
                  <div style={{ fontSize: 8, fontWeight: 700, color: BRAND.inkSub, letterSpacing: '0.1em' }}>DAY</div>
                  <div style={{ fontSize: 13, fontWeight: 700, color: BRAND.ink }}>{day}</div>
                </div>
                {TT_SCHEDULE[d].map((entry, p) => {
                  const isBreak = typeof entry === 'string';
                  const op = cellT(d, p);
                  const flex = (p === 3 || p === 7) ? '0.5' : '1';
                  if (isBreak) {
                    const isShort = entry === 'break-short';
                    return (
                      <div key={p} style={{
                        flex, height: 64,
                        opacity: op,
                        background: '#fef3c7',
                        border: '1px dashed #fde68a',
                        borderRadius: 6,
                        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
                      }}>
                        <div style={{ fontSize: 9, fontWeight: 700, color: '#92400e', letterSpacing: '0.08em' }}>BREAK</div>
                        <div style={{ fontSize: 10, color: '#92400e' }}>{isShort ? 'Short' : 'Lunch'}</div>
                        <div style={{ fontSize: 9, color: '#92400e' }}>{isShort ? '15m' : '20m'}</div>
                      </div>
                    );
                  }
                  const c = TT_COLORS[entry.s] || { bg: '#f1efe8', bar: BRAND.inkSub, text: BRAND.ink };
                  const displayName = SUBJECT_FULL[entry.s] || entry.s;
                  return (
                    <div key={p} style={{
                      flex, height: 64,
                      opacity: op,
                      transform: `scale(${0.85 + 0.15 * op})`,
                      background: c.bg,
                      borderLeft: `4px solid ${c.bar}`,
                      borderRadius: 6,
                      padding: '6px 8px',
                      display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
                      transition: 'opacity 240ms',
                    }}>
                      <div style={{ fontSize: 12, fontWeight: 700, color: c.text, lineHeight: 1.1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{displayName}</div>
                      <div style={{ fontSize: 10, color: BRAND.inkSoft, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{entry.t}</div>
                    </div>
                  );
                })}
              </div>
            ))}
          </div>
        </div>

        {/* Cursor */}
        {cursorOp > 0 && (
          <div style={{
            position: 'absolute',
            left: cur.x - STEP7_FRAME.x,
            top: cur.y - STEP7_FRAME.y + settle,
            pointerEvents: 'none',
          }}>
            <Cursor x={0} y={0} opacity={cursorOp}/>
          </div>
        )}
      </AppFrame>
    </div>
  );
}

function Step7App({ loop = true, persistKey = "step7video" }) {
  return (
    <Stage width={1920} height={1080} duration={11} background={BRAND.bg} loop={loop} persistKey={persistKey}>
      <Step7Video start={0}/>
    </Stage>
  );
}

Object.assign(window, { Step7Video, Step7App });

if (!window.__STEP7_NO_AUTOMOUNT) {
  ReactDOM.createRoot(document.getElementById('root')).render(<Step7App/>);
}
