<!-- SECTION:CUSTOM_INTRO -->

## 🎯 Overview

The **marked-extended-slide** extension transforms your Markdown into interactive presentation slides using fenced code
blocks (` ```presentation `). It supports layouts, backgrounds, transitions, speaker notes, autoplay, a speaker view
popup, nested extensions, and a programmatic navigation API.

### ✨ Key Features

- 🎨 **11 Built-in Layouts**: Cover, two-cols, center, quote, statement, fact, section, image-right, image-left, full,
  and default
- 🌈 **16 Pre-built Themes**: Dark, light, Dracula, Nord, GitHub, Material, Tokyo Night, and more
- ✨ **6 Transition Effects**: Slide, fade, zoom, slide-up/down, or none
- 📐 **Responsive Design**: Auto-scaling with configurable aspect ratios
- ⌨️ **Keyboard Navigation**: Arrow keys, space, home/end, overview mode
- 📱 **Touch Navigation**: Swipe support for mobile and tablets
- 🎭 **Custom Backgrounds**: Solid colors, gradients, or images
- 📊 **Progress Tracking**: Progress bar and slide numbers
- ▶️ **Autoplay Mode**: Configurable auto-advance for kiosk and demo scenarios
- 🎙️ **Speaker View**: Popup window with current slide, speaker notes, next preview, and elapsed timer
- 🔒 **CSP-Friendly**: Configurable `scriptNonce` for Content Security Policy compatibility
- 🎪 **Nested Extensions**: Full support for other marked extensions inside slides, including custom block and inline
  extensions

### 🎪 Live Demo

Experience all layouts, themes, and transitions: [View Demo](https://fsegurai.github.io/marked-extensions)

---

<!-- SECTION:CUSTOM_TOC_USAGE -->

	- [Quick Start](#quick-start)
	- [Syntax & Usage](#syntax--usage)
	- [Slide Layouts](#slide-layouts)
	- [Themes](#themes)
	- [Transitions](#transitions)
	- [Backgrounds](#backgrounds)
	- [Navigation](#navigation)

- [Runtime Behavior in SPA Frameworks](#runtime-behavior-in-spa-frameworks)
- [Troubleshooting](#troubleshooting)
    - [Configuration Options](#configuration-options)
    - [Use Cases](#use-cases)

<!-- SECTION:CUSTOM_BASIC_USAGE -->

## Quick Start

### Basic Concept

The slide extension uses **fenced code blocks** with a `presentation` info string:

- Wrap your deck in a ` ```presentation ` / ` ``` ` block
- Separate slides with `---` on its own line
- The first section before the first `---` is the presentation front matter (optional)

Without the fenced syntax, content is rendered as normal Markdown.

<!-- SECTION:CUSTOM_USAGE_EXAMPLE -->

// Required structural styles
import '@fsegurai/marked-extended-slide/styles/slide.css';
// Optional visual theme
import '@fsegurai/marked-extended-slide/styles/slide-theme.css';

marked.use(markedExtendedSlide({
  theme: 'dark',
  transition: 'slide',
  showControls: true,
  showProgress: true,
  keyboardNavigation: true,
}));

const presentation = `
\`\`\`presentation
title: Building Modern Web Apps
author: Jane Developer
date: February 17, 2026
theme: dark
transition: slide
---
layout: cover
background: linear-gradient(to right, #667eea 0%, #764ba2 100%)

# Building Modern Web Apps

A Technical Deep Dive

**Jane Developer** | Senior Engineer
---
## Agenda

1. Architecture Overview
2. Performance Optimization
3. Security Best Practices
4. Deployment Strategies
5. Q&A
\`\`\`
`;

const html = marked.parse(presentation);
document.getElementById('presentation-container').innerHTML = html;

<!-- SECTION:CUSTOM_USAGE_NOTES -->

This extension injects navigation script behavior for interactivity by default (`injectScript: true`). Import styles
manually (`slide.css` required, `slide-theme.css` optional).

### Runtime Behavior in SPA Frameworks

In Angular/React/Vue, slide HTML is often rendered after initial page load. The extension handles this with
`MutationObserver` and re-initialization hooks.

- Use `injectScript: true` for standard interactive behavior (recommended)
- Avoid calling `window.initPresentation()` repeatedly unless you really need manual control
- Register the extension once in app bootstrap/singleton setup

#### Why `injectScript: false` can appear blank

This is expected with the current runtime model:

- `.marked-extended-slide-slide` starts hidden (`opacity: 0`)
- JavaScript initialization marks one slide as `.active`
- with `injectScript: false`, no runtime sets `.active`, so slides stay hidden

If you disable script injection, you must provide equivalent client-side activation logic.

#### Angular quick guidance (`ngx-markdown`)

```typescript
provideMarkdown({
    markedExtensions: [
        {
            provide: MARKED_EXTENSIONS,
            useFactory: () => markedExtendedSlide({injectScript: true}),
            multi: true,
        },
    ],
});
```

Use global styles (`styles.scss`) for slide styles, not component-scoped styles.

### Troubleshooting

| Symptom                            | Likely Cause                                                           | Recommended Fix                                                                             |
|------------------------------------|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
| Slides not visible                 | `slide.css` missing or `injectScript: false` without manual activation | Import `slide.css` globally and keep `injectScript: true` unless you provide custom runtime |
| Duplicate keyboard button          | Repeated presentation initialization                                   | Update to latest package and avoid manual repeated `window.initPresentation()` calls        |
| Overview mode feels glitchy        | Duplicate listeners from repeated init                                 | Ensure extension is registered once and avoid duplicate app bootstrap setup                 |
| Controls visible but no navigation | DOM replaced after init                                                | Re-render once, then call `window.initPresentation()` once only if needed                   |

### Syntax & Usage

#### Minimal Valid Presentation

````markdown
```presentation
---
# First Slide
---
# Second Slide
```
````

#### With Presentation Front Matter

````markdown
```presentation
title: My Talk
theme: dark
---
layout: cover

# Slide One

Hello slides.
---
## Slide Two

More content
```
````

#### Common Pitfalls

- Using `---` without the ` ```presentation ` fence — renders as a horizontal rule
- Forgetting the closing ` ``` `
- Not importing `slide.css` (structure/visibility issues)

### Styling Your Presentations

This extension provides structural behavior and supports theme customization through CSS classes and variables.

#### Generated HTML Structure

```html

<div class="marked-extended-slide-presentation" data-theme="dark" data-aspect-ratio="16:9" data-transition="slide">
    <div class="marked-extended-slide-controls">
        <button class="marked-extended-slide-control marked-extended-slide-prev">...</button>
        <button class="marked-extended-slide-control marked-extended-slide-next">...</button>
    </div>

    <div class="marked-extended-slide-progress">
        <div class="marked-extended-slide-progress-bar" style="width: 30%"></div>
    </div>

    <section class="marked-extended-slide-slide marked-extended-slide-layout-default">
        <div class="marked-extended-slide-content">
            <h1>Slide Title</h1>
        </div>
    </section>
</div>
```

#### CSS Classes Reference

| Class                                                    | Purpose                 | Element       |
|----------------------------------------------------------|-------------------------|---------------|
| `.marked-extended-slide-presentation`                    | Main container          | Container     |
| `.marked-extended-slide-presentation[data-theme="dark"]` | Theme variant           | Container     |
| `.marked-extended-slide-slide`                           | Individual slide        | Slide wrapper |
| `.marked-extended-slide-slide.active`                    | Current/visible slide   | Active slide  |
| `.marked-extended-slide-slide.previous`                  | Previous slide          | Previous      |
| `.marked-extended-slide-layout-default`                  | Default layout          | Slide         |
| `.marked-extended-slide-layout-cover`                    | Cover/title layout      | Slide         |
| `.marked-extended-slide-layout-center`                   | Centered content        | Slide         |
| `.marked-extended-slide-layout-two-cols`                 | Two-column layout       | Slide         |
| `.marked-extended-slide-layout-image-right`              | Image on the right      | Slide         |
| `.marked-extended-slide-layout-image-left`               | Image on the left       | Slide         |
| `.marked-extended-slide-layout-full`                     | Full-screen no padding  | Slide         |
| `.marked-extended-slide-layout-fact`                     | Key fact display        | Slide         |
| `.marked-extended-slide-layout-quote`                    | Quote layout            | Slide         |
| `.marked-extended-slide-layout-section`                  | Section divider         | Slide         |
| `.marked-extended-slide-content`                         | Slide content area      | Content       |
| `.marked-extended-slide-controls`                        | Control buttons wrapper | Nav           |
| `.marked-extended-slide-control`                         | Control button          | Button        |
| `.marked-extended-slide-speaker-toggle`                  | Speaker view button     | Button        |
| `.marked-extended-slide-progress`                        | Progress bar container  | Progress      |
| `.marked-extended-slide-progress-bar`                    | Progress bar fill       | Bar           |
| `.marked-extended-slide-slide-number`                    | Slide counter           | Number        |

#### Base Styling Example

```css
/* Presentation Container */
.marked-extended-slide-presentation {
    position: relative;
    width: 100%;
    height: 100vh;
    background: #1a1a1a;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    overflow: hidden;
}

/* Slides */
.marked-extended-slide-slide {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4rem;
    background: var(--slide-bg, #fff);
    color: var(--slide-text, #333);
    opacity: 0;
    transform: translateX(100%);
    transition: all 0.6s ease;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

.marked-extended-slide-slide.active {
    opacity: 1;
    transform: translateX(0);
    z-index: 1;
}

/* Slide Content */
.marked-extended-slide-content {
    width: 100%;
    max-width: 960px;
}

/* Layout: Cover */
.marked-extended-slide-layout-cover {
    text-align: center;
}

.marked-extended-slide-layout-cover h1 {
    font-size: 3.5rem;
    margin: 0 0 1rem 0;
    line-height: 1.2;
}

/* Layout: Two Columns */
.marked-extended-slide-layout-two-cols .marked-extended-slide-content {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 3rem;
    align-items: start;
}

/* Layout: Quote */
.marked-extended-slide-layout-quote blockquote {
    font-size: 2rem;
    font-style: italic;
    border-left: 4px solid var(--slide-accent, #0066cc);
    padding-left: 2rem;
    margin: 0;
}

/* Layout: Section Divider */
.marked-extended-slide-layout-section {
    background: var(--slide-accent, #0066cc);
    color: white;
    font-size: 3rem;
    font-weight: 700;
    text-align: center;
}

/* Controls */
.marked-extended-slide-controls {
    position: absolute;
    bottom: 2rem;
    right: 2rem;
    display: flex;
    gap: 0.5rem;
    z-index: 100;
}

.marked-extended-slide-control {
    width: 48px;
    height: 48px;
    border: none;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    border-radius: 50%;
    font-size: 1.5rem;
    cursor: pointer;
    transition: all 0.2s;
    backdrop-filter: blur(4px);
}

.marked-extended-slide-control:hover {
    background: rgba(0, 0, 0, 0.8);
    transform: scale(1.1);
}

/* Progress Bar */
.marked-extended-slide-progress {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: rgba(0, 0, 0, 0.3);
    z-index: 100;
}

.marked-extended-slide-progress-bar {
    height: 100%;
    background: var(--slide-accent, #0066cc);
    transition: width 0.3s ease;
}

/* Slide Number */
.marked-extended-slide-slide-number {
    position: absolute;
    bottom: 1rem;
    right: 1rem;
    font-size: 0.875rem;
    color: rgba(0, 0, 0, 0.5);
}

/* Overview Mode */
.marked-extended-slide-presentation.overview-mode .marked-extended-slide-slide {
    opacity: 0.8;
    transform: scale(0.25);
    transition: transform 0.2s, opacity 0.2s;
}

.marked-extended-slide-presentation.overview-mode .marked-extended-slide-slide:hover {
    opacity: 1;
    transform: scale(0.27);
    cursor: pointer;
}
```

#### Theme Examples

**Dark Theme:**

```css
.marked-extended-slide-presentation[data-theme="dark"] {
    --slide-bg: #1a1a1a;
    --slide-text: #e0e0e0;
    --slide-accent: #4a9eff;
    --slide-heading: #ffffff;
    background: #0a0a0a;
}
```

**Light Theme:**

```css
.marked-extended-slide-presentation[data-theme="light"] {
    --slide-bg: #ffffff;
    --slide-text: #333333;
    --slide-accent: #0066cc;
    --slide-heading: #1a1a1a;
    background: #f5f5f5;
}
```

**Dracula Theme:**

```css
.marked-extended-slide-presentation[data-theme="dracula"] {
    --slide-bg: #282a36;
    --slide-text: #f8f8f2;
    --slide-accent: #ff79c6;
    --slide-heading: #50fa7b;
    background: #1e1f29;
}
```

**Nord Theme:**

```css
.marked-extended-slide-presentation[data-theme="nord"] {
    --slide-bg: #2e3440;
    --slide-text: #d8dee9;
    --slide-accent: #88c0d0;
    --slide-heading: #eceff4;
    background: #242933;
}
```

**GitHub Light Theme:**

```css
.marked-extended-slide-presentation[data-theme="github-light"] {
    --slide-bg: #ffffff;
    --slide-text: #24292e;
    --slide-accent: #0366d6;
    --slide-heading: #1b1f23;
    background: #f6f8fa;
}
```

**Material Theme:**

```css
.marked-extended-slide-presentation[data-theme="material"] {
    --slide-bg: #263238;
    --slide-text: #cfd8dc;
    --slide-accent: #80cbc4;
    --slide-heading: #eceff1;
    background: #1e272e;
}
```

**Cyberpunk Theme:**

```css
.marked-extended-slide-presentation[data-theme="cyberpunk"] {
    --slide-bg: #0a0e27;
    --slide-text: #00ffff;
    --slide-accent: #ff00ff;
    --slide-heading: #ffff00;
    background: #000000;
}
```

**High Contrast Theme (Accessibility):**

```css
.marked-extended-slide-presentation[data-theme="high-contrast"] {
    --slide-bg: #000000;
    --slide-text: #ffffff;
    --slide-accent: #ffff00;
    --slide-heading: #ffffff;
    background: #000000;
}
```

#### Keyboard Navigation Styling

```css
/* Show keyboard hint */
.marked-extended-slide-keyboard-toggle {
    position: relative;
}

.marked-extended-slide-keyboard-toggle::after {
    content: 'Keyboard: Enabled';
    position: absolute;
    bottom: 100%;
    right: 0;
    background: rgba(0, 0, 0, 0.9);
    color: white;
    padding: 0.5rem 1rem;
    border-radius: 4px;
    font-size: 0.75rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
    margin-bottom: 0.5rem;
}

.marked-extended-slide-keyboard-toggle:hover::after {
    opacity: 1;
}

/* Disabled keyboard state */
.marked-extended-slide-keyboard-toggle.disabled {
    opacity: 0.5;
}
```

#### Responsive Adjustments

```css
@media (max-width: 768px) {
    .marked-extended-slide-slide {
        padding: 2rem;
    }

    .marked-extended-slide-layout-cover h1 {
        font-size: 2rem;
    }

    .marked-extended-slide-layout-two-cols .marked-extended-slide-content {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }

    .marked-extended-slide-controls {
        bottom: 1rem;
        right: 1rem;
    }

    .marked-extended-slide-control {
        width: 40px;
        height: 40px;
        font-size: 1.25rem;
    }
}
```

#### Print Styles

```css
@media print {
    .marked-extended-slide-presentation {
        height: auto;
        background: white;
    }

    .marked-extended-slide-slide {
        position: relative;
        transform: none !important;
        opacity: 1 !important;
        page-break-after: always;
        background: white !important;
        color: black !important;
        box-shadow: none !important;
    }

    .marked-extended-slide-controls,
    .marked-extended-slide-progress {
        display: none !important;
    }
}
```

#### Available Themes (16 Total)

1. **default** - Clean and professional
2. **light** - Bright white background
3. **dark** - Dark background with light text
4. **solarized-light** - Solarized light palette
5. **solarized-dark** - Solarized dark palette
6. **dracula** - Popular Dracula theme
7. **nord** - Nord color scheme
8. **monokai** - Classic Monokai
9. **github-light** - GitHub's light theme
10. **github-dark** - GitHub's dark theme
11. **one-dark** - Atom One Dark
12. **gruvbox-light** - Gruvbox light variant
13. **gruvbox-dark** - Gruvbox dark variant
14. **material** - Material Design
15. **tokyo-night** - Tokyo Night theme
16. **high-contrast** - Maximum accessibility

#### Copy Demo Theme

For all 16
themes: [slide-themes.css](https://github.com/fsegurai/marked-extensions/blob/main/demo/styles/extensions/slide-themes.css)

Check the [demo](https://fsegurai.github.io/marked-extensions) to see all themes and layouts in action.

**Keyboard Controls:**

- `→` / `Space` / `Page Down` - Next slide
- `←` / `Page Up` - Previous slide
- `Home` - First slide
- `End` - Last slide
- `O` / `Escape` - Toggle overview mode
- `F` - Toggle fullscreen

**Programmatic API:**

```javascript
window.presentation.next();        // Go to next slide
window.presentation.prev();        // Go to previous slide
window.presentation.goto(5);       // Go to slide 5
window.presentation.toggleOverview(); // Toggle overview
window.presentation.getCurrentSlide(); // Get current slide index
window.presentation.getTotalSlides();  // Get total slides
```

<!-- SECTION:CUSTOM_SECTIONS -->

### Creating Slides

Wrap your deck in a fenced code block with `presentation` info string and separate slides with `---`:

````markdown
```presentation
---
# First Slide

Content here
---
# Second Slide

More content
```
````

### Front Matter and Properties

**Presentation-level front matter** (before the first `---`):

````markdown
```presentation
title: My Presentation
author: John Doe
date: 2024-02-07
theme: dark
transition: fade
---
# First Slide
---
# Second Slide
```
````

**Slide-level properties** (after the `---` separator on subsequent slides):

````markdown
```presentation
---
layout: cover
background: "#667eea"
transition: zoom
class: custom-class
notes: Remember this point

# Slide Content
---
## Next Slide
```
````

### Slide Layouts

The extension supports multiple built-in layouts:

- **`default`** - Standard slide with content
- **`cover`** - Centered title slide
- **`center`** - Centered content
- **`two-cols`** - Two-column layout
- **`image-right`** - Image on the right, content on left
- **`image-left`** - Image on the left, content on right
- **`full`** - Full-screen content (no padding)
- **`statement`** - Large, bold statement
- **`fact`** - Highlight a key fact
- **`quote`** - Styled quote layout
- **`section`** - Section divider slide

Example:

````markdown
```presentation
---
layout: two-cols

# Two Column Layout

Left column

Right column
---
## Next Slide
```
````

### Backgrounds

Add custom backgrounds using slide properties:

**Solid colors:**

````markdown
```presentation
---
background: "#667eea"

# Slide
```
````

**Gradients:**

````markdown
```presentation
---
background: "linear-gradient(to right, #667eea 0%, #764ba2 100%)"

# Slide
```
````

**Images:**

````markdown
```presentation
---
backgroundImage: "https://example.com/image.jpg"
backgroundSize: cover
backgroundPosition: center

# Slide
```
````

### Transitions

Supported transition effects:

- `slide` (default)
- `fade`
- `slide-up`
- `slide-down`
- `zoom`
- `none`

Set globally:

```javascript
marked.use(markedExtendedSlide({
    transition: 'fade',
}));
```

Or per slide by setting `transition` in the slide front matter:

````markdown
```presentation
---
transition: zoom

# Zoom Slide
```
````

### Navigation

**Controls:**

- Navigation arrows appear in the bottom-right
- Progress bar at the bottom
- Slide numbers (optional)
- Overview mode for slide grid

**Disable controls:**

```javascript
marked.use(markedExtendedSlide({
    showControls: false,
    showProgress: false,
    showSlideNumbers: false,
}));
```

### Configuration Options

| Option                  | Type             | Default                   | Description                           |
|-------------------------|------------------|---------------------------|---------------------------------------|
| `className`             | string           | `'marked-extended-slide'` | CSS class prefix                      |
| `prefixId`              | string           | `'slide-'`                | ID prefix for slides                  |
| `transition`            | string           | `'slide'`                 | Default transition effect             |
| `transitionDuration`    | string           | `'0.6s'`                  | Transition duration                   |
| `defaultLayout`         | string           | `'default'`               | Default slide layout                  |
| `showSlideNumbers`      | boolean          | `true`                    | Show slide numbers                    |
| `showControls`          | boolean          | `true`                    | Show navigation controls              |
| `showProgress`          | boolean          | `true`                    | Show progress bar                     |
| `keyboardNavigation`    | boolean          | `true`                    | Enable keyboard shortcuts             |
| `touchNavigation`       | boolean          | `true`                    | Enable touch/swipe                    |
| `overviewMode`          | boolean          | `true`                    | Enable overview mode                  |
| `aspectRatio`           | string           | `'16:9'`                  | Slide aspect ratio                    |
| `theme`                 | string           | `'default'`               | Theme name                            |
| `template`              | string \| null   | null                      | Custom slide template                 |
| `containerTemplate`     | string \| null   | null                      | Custom container template             |
| `customizeToken`        | function \| null | null                      | Token customization function          |
| `customizePresentation` | function \| null | null                      | Presentation customization            |
| `injectScript`          | boolean          | `true`                    | Auto-inject navigation JS             |
| `autoplay`              | boolean          | `false`                   | Auto-advance slides                   |
| `autoplayInterval`      | number           | `5000`                    | Autoplay interval in milliseconds     |
| `speakerMode`           | boolean          | `false`                   | Enable speaker view button in controls|
| `scriptNonce`           | string \| null   | null                      | CSP nonce for injected script         |

**Note:** Import CSS/SCSS files manually.

### Autoplay Mode

Enable autoplay to automatically advance slides at a configurable interval — ideal for kiosks, digital signage, or
hands-free demos.

```javascript
marked.use(markedExtendedSlide({
    autoplay: true,
    autoplayInterval: 3000, // 3 seconds
}));
```

Autoplay resets on any user interaction (click, touch, keyboard navigation). The `data-autoplay` and
`data-autoplay-interval` attributes are set on the container element.

### Speaker View

The speaker view opens a popup window showing the current slide, speaker notes, a preview of the next slide, and an
elapsed timer. It synchronizes in real time via `BroadcastChannel`.

```javascript
marked.use(markedExtendedSlide({
    speakerMode: true,
}));
```

When enabled, a speaker button is added to the controls. Clicking it opens a popup that:

- Displays the current slide in a scaled frame
- Shows speaker notes (from the `notes` property)
- Previews the next slide
- Tracks elapsed time since opening
- Syncs automatically when you navigate slides in the main window

**Notes:**

- The popup must be allowed by the browser (no popup blocker)
- Uses `BroadcastChannel` API (requires modern browsers)
- Closes the channel on window close
- The speaker button only appears when `speakerMode: true`

### CSP (Content Security Policy)

If your site uses a Content Security Policy with `script-src` containing a nonce, pass it via `scriptNonce`:

```javascript
marked.use(markedExtendedSlide({
    scriptNonce: 'your-csp-nonce',
}));
```

The nonce is applied to the injected `<script>` element, allowing it to execute under your CSP rules.

### Advanced Features

**Speaker Notes:**

````markdown
```presentation
---
notes: Remember to mention the quarterly results here

# Q4 Results
```
````

**Custom Classes:**

````markdown
```presentation
---
class: special-slide highlight

# Special Slide
```
````

**Hide Slide Numbers:**

````markdown
```presentation
---
hideSlideNumber: true

# Clean Slide
```
````

**Nested Extensions:**

Slide bodies are rendered with the active Marked parser, so any registered extension can run inside a slide without
special handling.

````markdown
```presentation
---
# Slide with Accordion

::::accordion{title="Click to expand"}
Hidden content here
::::accordionend
---
# Slide with Alert

> [!NOTE]
> This is an alert inside a slide
```
````

### Responsive Design

Slides automatically scale on smaller screens while maintaining aspect ratio. The extension includes print styles for
PDF export.

### Themes

Create custom themes by overriding CSS variables:

```css
.marked-extended-slide-presentation[data-theme="custom"] {
    --slide-bg: #f0f0f0;
    --slide-text: #333;
    --slide-accent: #ff6b6b;
    --slide-border: #ddd;
}
```
