moonlantern1 commited on
Commit
1ceabda
·
verified ·
1 Parent(s): 63dbea1

Add hero typing animation

Browse files
Files changed (1) hide show
  1. app.py +40 -1
app.py CHANGED
@@ -554,6 +554,8 @@ INDEX_HTML = r"""<!DOCTYPE html>
554
  .eyebrow { font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold); font-weight: 500; margin-bottom: 16px; }
555
  .hero-title { font-family: 'Cormorant Garamond', serif; font-size: clamp(2rem, 5vw, 3.6rem); font-weight: 500; line-height: 1.15; color: var(--ink); max-width: 620px; margin-bottom: 12px; }
556
  .hero-title em { font-style: italic; color: var(--gold); }
 
 
557
  .hero-sub { font-size: 0.95rem; color: var(--ink-muted); margin-bottom: 48px; font-weight: 300; }
558
  .input-card { background: var(--white); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 36px; width: 100%; max-width: 520px; box-shadow: 0 8px 32px rgba(42,31,14,0.07); }
559
  .mode-tabs { display: flex; background: var(--surface); border-radius: 10px; padding: 4px; margin-bottom: 28px; gap: 4px; }
@@ -668,7 +670,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
668
  </nav>
669
  <div class="screen active" id="screen-input">
670
  <div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:calc(100vh - 65px);padding:40px 20px;text-align:center;">
671
- <h1 class="hero-title">Convert your long video to <em>short clips</em> for social media</h1>
672
  <p class="hero-sub">Upload a file - we handle the rest</p>
673
  <div class="input-card">
674
  <div class="input-section" id="mode-yt" style="display:none">
@@ -755,6 +757,43 @@ INDEX_HTML = r"""<!DOCTYPE html>
755
  let pollFailures = 0;
756
  let lastJobSnapshot = null;
757
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
  function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
759
 
760
  function showProcessingScreen() {
 
554
  .eyebrow { font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold); font-weight: 500; margin-bottom: 16px; }
555
  .hero-title { font-family: 'Cormorant Garamond', serif; font-size: clamp(2rem, 5vw, 3.6rem); font-weight: 500; line-height: 1.15; color: var(--ink); max-width: 620px; margin-bottom: 12px; }
556
  .hero-title em { font-style: italic; color: var(--gold); }
557
+ .typing-text { display: inline-block; min-width: 4.4em; white-space: nowrap; border-right: 0.05em solid var(--gold); }
558
+ @media (prefers-reduced-motion: reduce) { .typing-text { border-right: 0; } }
559
  .hero-sub { font-size: 0.95rem; color: var(--ink-muted); margin-bottom: 48px; font-weight: 300; }
560
  .input-card { background: var(--white); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 36px; width: 100%; max-width: 520px; box-shadow: 0 8px 32px rgba(42,31,14,0.07); }
561
  .mode-tabs { display: flex; background: var(--surface); border-radius: 10px; padding: 4px; margin-bottom: 28px; gap: 4px; }
 
670
  </nav>
671
  <div class="screen active" id="screen-input">
672
  <div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:calc(100vh - 65px);padding:40px 20px;text-align:center;">
673
+ <h1 class="hero-title">Convert your long video to <em class="typing-text" id="hero-typed">short clips</em> for social media</h1>
674
  <p class="hero-sub">Upload a file - we handle the rest</p>
675
  <div class="input-card">
676
  <div class="input-section" id="mode-yt" style="display:none">
 
757
  let pollFailures = 0;
758
  let lastJobSnapshot = null;
759
 
760
+ function startHeroTyping() {
761
+ const el = document.getElementById('hero-typed');
762
+ if (!el || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
763
+ const text = 'short clips';
764
+ const typeMs = 3000;
765
+ const eraseMs = 3000;
766
+ const holdMs = 650;
767
+ let index = text.length;
768
+ let deleting = true;
769
+
770
+ function step() {
771
+ const delay = (deleting ? eraseMs : typeMs) / text.length;
772
+ if (deleting) {
773
+ index = Math.max(0, index - 1);
774
+ el.textContent = text.slice(0, index) || '\u00a0';
775
+ if (index === 0) {
776
+ deleting = false;
777
+ setTimeout(step, holdMs);
778
+ return;
779
+ }
780
+ } else {
781
+ index = Math.min(text.length, index + 1);
782
+ el.textContent = text.slice(0, index);
783
+ if (index === text.length) {
784
+ deleting = true;
785
+ setTimeout(step, holdMs);
786
+ return;
787
+ }
788
+ }
789
+ setTimeout(step, delay);
790
+ }
791
+
792
+ setTimeout(step, holdMs);
793
+ }
794
+
795
+ startHeroTyping();
796
+
797
  function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
798
 
799
  function showProcessingScreen() {