Spaces:
Sleeping
Sleeping
Add hero typing animation
Browse files
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() {
|