scn-consultation-api / src /template /slide /content_slide.html
SS-2005's picture
Upload 7 files
34bfc70 verified
Raw
History Blame Contribute Delete
15.5 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ slide_title }}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.css" integrity="sha384-WcoG4HRXMzYzfCgiyfrySxx90XSl2rxY5mnVY5TwtWE6KLrArNKn0T/mOgNL0Mmi" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.js" integrity="sha384-J+9dG2KMoiR9hqcFao0IBLwxt6zpcyN68IgwzsCSkbreXUjmNVRhPFTssqdSGjwQ" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/contrib/auto-render.min.js" integrity="sha384-hCXGrW6PitJEwbkoStFjeJxv+fSOOQKOPbJxSfM6G5sWZjAyWhXiTIIAmQqnlLlh" crossorigin="anonymous"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Arial, sans-serif;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #f5f5f5;
margin: 0;
padding: 0;
}
.slide {
width: 1920px;
height: 1080px;
position: relative;
overflow: hidden;
background: white;
}
/* Semicircle layers - initially off-screen */
.circle-large {
position: absolute;
top: 50%;
left: 0;
width: 950px;
height: 1240px;
background: {{ circle_large_color }};
border-radius: 50%;
transform: translate(-135%, -50%);
z-index: 1;
transition: transform 1s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.circle-small {
position: absolute;
top: 50%;
left: 0;
width: 830px;
height: 1130px;
background: {{ circle_small_color }};
border-radius: 50%;
transform: translate(-140%, -50%);
z-index: 2;
transition: transform 1s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s;
}
/* Animated state */
.slide.animate .circle-large {
transform: translate(-35%, -50%);
}
.slide.animate .circle-small {
transform: translate(-40%, -50%);
}
/* Title - initially hidden */
.title-container {
position: absolute;
top: 50%;
left: 250px;
transform: translate(-50%, -50%);
text-align: center;
z-index: 3;
width: 540px;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.8s ease-in 0.5s;
}
.slide.animate .title-container {
opacity: 1;
}
.title {
font-size: clamp(1.2rem, 4vh, 5rem);
font-weight: 700;
color: #000000;
line-height: 1.2;
word-break: break-word;
text-align: center;
max-width: 90%;
}
/* Content Section */
.content {
position: absolute;
top: 50%;
left: 672px;
transform: translateY(-50%);
z-index: 3;
width: 1150px;
color: #222;
max-height: 800px;
overflow: hidden;
}
.subtitle {
font-size: 34px;
color: #000000;
margin-bottom: 1.5rem;
opacity: 0;
transform: translateX(20px);
transition: all 0.6s ease-out 1s;
}
.slide.animate .subtitle {
opacity: 1;
transform: translateX(0);
}
.bullet-list {
display: flex;
flex-direction: column;
gap: 20px;
margin-top: 20px;
}
.bullet-item {
display: flex;
align-items: flex-start;
gap: 15px;
padding: 18px 0;
opacity: 0;
transform: translateX(-50px);
transition: all 0.6s ease-out;
}
.bullet-icon {
width: 10px;
height: 10px;
min-width: 10px;
background: {{ bullet_color }};
border-radius: 50%;
margin-top: 20px; /* Pushes the bullet down for better vertical alignment */
}
.bullet-text {
font-size: 28px; /* Reduced font size for more space */
color: #000000;
line-height: 1.6;
font-weight: 500;
width: 100%;
max-width: 1050px;
}
/* Individual bullet timing */
.slide.animate .bullet-item:nth-child(1) {
opacity: 1;
transform: translateX(0);
transition-delay: {{ bullet_1_delay }};
}
.slide.animate .bullet-item:nth-child(2) {
opacity: 1;
transform: translateX(0);
transition-delay: {{ bullet_2_delay }};
}
.slide.animate .bullet-item:nth-child(3) {
opacity: 1;
transform: translateX(0);
transition-delay: {{ bullet_3_delay }};
}
.slide.animate .bullet-item:nth-child(4) {
opacity: 1;
transform: translateX(0);
transition-delay: {{ bullet_4_delay }};
}
.slide.animate .bullet-item:nth-child(5) {
opacity: 1;
transform: translateX(0);
transition-delay: {{ bullet_5_delay }};
}
.slide.animate .bullet-item:nth-child(6) {
opacity: 1;
transform: translateX(0);
transition-delay: {{ bullet_6_delay }};
}
/* Inline code within bullets */
.inline-code-span {
background-color: #f0f0f0;
padding: 2px 6px;
border-radius: 3px;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 0.95em;
color: #d63384;
}
.bullet-content code {
background-color: #f0f0f0;
padding: 2px 6px;
border-radius: 3px;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 0.95em;
color: #d63384;
}
/* Inline code snippet (small code) - Styled like the dedicated code slide */
.inline-code-section {
background: #f8f9fa;
border: 2px solid #e3e8ef;
border-radius: 10px;
padding: 25px;
margin-top: 1.5rem;
box-shadow: 0 2px 8px rgba(47, 111, 236, 0.1);
opacity: 0;
transform: translateY(20px);
transition: all 0.6s ease-out {{ code_snippet_delay }};
}
.slide.animate .inline-code-section {
opacity: 1;
transform: translateY(0);
}
.inline-code-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid #e3e8ef;
}
.inline-code-title {
font-size: 20px;
font-weight: 600;
color: {{ bullet_color }};
display: flex;
align-items: center;
gap: 8px;
}
.inline-code-icon {
width: 20px;
height: 20px;
}
.inline-code-block {
font-family: 'Fira Code', 'JetBrains Mono', 'Source Code Pro', 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 19px;
line-height: 1.7;
color: #2d3748;
}
.inline-code-block .code-line {
display: block;
}
/* === PYGMENTS SYNTAX HIGHLIGHTING FOR INLINE CODE === */
{{ pygments_css }}
.corner-logo {
position: absolute;
bottom: 20px;
right: 20px;
width: 50px;
height: auto;
z-index: 4;
opacity: 0;
transition: opacity 0.5s ease-in {{ logo_delay }};
}
.slide.animate .corner-logo {
opacity: 1;
}
/* Word highlighting styles - Professional continuous highlight */
.word {
display: inline;
transition: all 0.3s ease;
padding: 2px 0px;
border-radius: 3px;
margin: 0;
background-color: transparent;
color: inherit;
font-weight: inherit;
position: relative;
}
/* Continuous professional highlight - stays until end */
/* Golden Yellow - Energetic & Positive */
.word.highlighted {
background: linear-gradient(120deg, rgba(251, 191, 36, 0.25) 0%, rgba(245, 158, 11, 0.35) 100%);
color: #78350f; /* Dark Amber */
font-weight: 500; /* Matched font-weight to prevent width change */
padding: 3px 2px; /* Adjusted padding for a better visual */
border-radius: 4px;
box-shadow: 0 2px 8px rgba(245, 158, 11, 0.2);
}
/* Active animation */
@keyframes glow {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.5); }
}
.bullet-item.active .bullet-icon {
animation: glow 0.8s ease-in-out;
}
@keyframes pulse-bg {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
.bullet-item.active {
animation: pulse-bg 0.8s ease-in-out;
}
</style>
</head>
<body>
<div class="slide" id="slide">
<!-- Semicircle shapes -->
<div class="circle-large"></div>
<div class="circle-small"></div>
<!-- Title inside semicircle -->
<div class="title-container">
<h1 class="title">{{ main_title }}</h1>
</div>
<!-- Right side content -->
<div class="content">
<p class="subtitle">{{ subtitle_text }}</p>
<div class="bullet-list">
{% if enable_word_highlighting %}
<!-- Word-by-word rendering with highlighting -->
{% for bullet_data in bullets_with_highlights %}
{% if bullet_data.text %}
{% set outer_index = loop.index0 %}
<div class="bullet-item" data-bullet-index="{{ outer_index }}">
<div class="bullet-icon"></div>
<div class="bullet-text">
{% for word_obj in bullet_data.word_data %}
<span class="word"
data-start="{{ word_obj.start }}"
data-end="{{ word_obj.end }}"
data-bullet="{{ outer_index }}"
data-word-index="{{ loop.index0 }}"
data-highlight="{{ 'true' if word_obj.highlight else 'false' }}">{{ word_obj.word | safe }}</span>{% if not loop.last %}<span> </span>{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
{% else %}
<!-- Fallback: Regular bullet rendering -->
{% if bullet_point_1 %}<div class="bullet-item"><div class="bullet-icon"></div><div class="bullet-text">{{ bullet_point_1|safe }}</div></div>{% endif %}
{% if bullet_point_2 %}<div class="bullet-item"><div class="bullet-icon"></div><div class="bullet-text">{{ bullet_point_2|safe }}</div></div>{% endif %}
{% if bullet_point_3 %}<div class="bullet-item"><div class="bullet-icon"></div><div class="bullet-text">{{ bullet_point_3|safe }}</div></div>{% endif %}
{% if bullet_point_4 %}<div class="bullet-item"><div class="bullet-icon"></div><div class="bullet-text">{{ bullet_point_4|safe }}</div></div>{% endif %}
{% if bullet_point_5 %}<div class="bullet-item"><div class="bullet-icon"></div><div class="bullet-text">{{ bullet_point_5|safe }}</div></div>{% endif %}
{% if bullet_point_6 %}<div class="bullet-item"><div class="bullet-icon"></div><div class="bullet-text">{{ bullet_point_6|safe }}</div></div>{% endif %}
{% endif %}
</div>
{% if has_code_snippet %}
<div class="inline-code-section">
<div class="inline-code-header">
<div class="inline-code-title">
<svg class="inline-code-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 6L4 10L8 14" stroke="{{ bullet_color }}" stroke-width="2" stroke-linecap="round"/>
<path d="M16 6L20 10L16 14" stroke="{{ bullet_color }}" stroke-width="2" stroke-linecap="round"/>
</svg>
{{ code_snippet_label }}
</div>
</div>
<div class="inline-code-block">
{{ code_snippet_content|safe }}
</div>
</div>
{% endif %}
</div>
<!-- Bottom-right logo -->
<img src="{{ logo_path }}" alt="Corner Logo" class="corner-logo">
</div>
<script>
// Configuration
const ENABLE_WORD_HIGHLIGHTING = {{ 'true' if enable_word_highlighting else 'false' }};
const BULLET_DELAYS = {{ bullet_highlight_delays }};
const AUDIO_START_DELAY = 2500; // 2.5 seconds - matches animation delay before narration
// Auto-play animation on page load
window.addEventListener('load', () => {
const slide = document.getElementById('slide');
// Start animation immediately
setTimeout(() => {
slide.classList.add('animate');
if (ENABLE_WORD_HIGHLIGHTING) {
// Word-level highlighting based on audio timings
highlightWordsWithTiming();
} else {
// Fallback: Bullet-level highlighting
highlightBulletsOnly();
}
}, 100);
});
function highlightWordsWithTiming() {
const wordsToHighlight = document.querySelectorAll('.word[data-highlight="true"]');
console.log(`[Word Highlighting] Found ${wordsToHighlight.length} word instances to highlight.`);
wordsToHighlight.forEach((word, index) => {
const startTime = parseFloat(word.dataset.start) * 1000; // Convert to ms from audio
// Apply audio delay for better sync
const adjustedStartTime = Math.max(0, startTime + AUDIO_START_DELAY);
// Schedule highlight
setTimeout(() => {
word.classList.add('highlighted');
// Optional: log the highlight action for debugging
// console.log(`[Highlight] "${word.textContent.trim()}" at ${(adjustedStartTime/1000).toFixed(2)}s (bullet ${word.dataset.bullet})`);
}, adjustedStartTime);
});
// Animate the bullet icons
const bullets = document.querySelectorAll('.bullet-item');
bullets.forEach((bullet, index) => {
if (index < BULLET_DELAYS.length) {
setTimeout(() => {
bullet.classList.add('active');
setTimeout(() => bullet.classList.remove('active'), 2000); // Animation duration
}, BULLET_DELAYS[index]);
}
});
}
function highlightBulletsOnly() {
// Fallback bullet highlighting logic
const bullets = document.querySelectorAll('.bullet-points li');
bullets.forEach((bullet, index) => {
if (index < BULLET_DELAYS.length) {
setTimeout(() => {
bullet.classList.add('active');
setTimeout(() => bullet.classList.remove('active'), 1500);
}, BULLET_DELAYS[index]);
}
});
}
function setHighlightTheme(theme) {
const highlightedWords = document.querySelectorAll('.word.highlighted');
highlightedWords.forEach(word => {
word.classList.remove('blue-theme', 'green-theme', 'purple-theme');
if (theme !== 'default') {
word.classList.add(`${theme}-theme`);
}
});
}
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.body, {
delimiters: [
{left: "$$", right: "$$", display: true},
{left: "$", right: "$", display: false}
]
});
});
</script>
</body>
</html>