@manufosela/card-rain-section

@manufosela/card-rain-section

Scroll-driven card rain animation section with drop and zoom modes

Card Rain Section

Scroll-driven card rain animation section with drop and zoom modes.

Basic Usage (Drop Mode)

Scroll down through the section to see cards fall into view one by one. The default animation mode is "drop".

Scroll down to see the card rain effect
Our
Services

Design

We craft beautiful interfaces that delight users and drive engagement through thoughtful design principles.

Development

Modern web applications built with cutting-edge technologies for performance and scalability.

Strategy

Data-driven strategies that align technology with business goals for measurable results.

<card-rain-section scroll-height="300"> <span slot="title">Our<br>Services</span> <div slot="card"> <div class="sample-card"> <h3>Design</h3> <p>Description text...</p> </div> </div> <div slot="card">...</div> <div slot="card">...</div> <button slot="actions">Learn More</button> </card-rain-section>

Zoom Mode

Set fall-mode="zoom" to make cards scale down from a large size with a blur-to-sharp transition.

Scroll down to see the zoom effect
Featured
Work

Project Alpha

A comprehensive platform redesign that increased user retention by 40%.

Project Beta

E-commerce solution handling millions of transactions with 99.9% uptime.

Project Gamma

Mobile-first application serving users across 30 countries worldwide.

<card-rain-section scroll-height="300" fall-mode="zoom"> <span slot="title">Featured<br>Work</span> <div slot="card">...</div> <div slot="card">...</div> <div slot="card">...</div> <button slot="actions">View Portfolio</button> </card-rain-section>

Custom Styles

Customize the appearance using CSS custom properties.

Scroll down to see custom-styled cards
Tech
Stack

Frontend

Lit, Web Components, Astro, modern CSS with custom properties and container queries.

Backend

Node.js, Firebase Cloud Functions, REST APIs with comprehensive documentation.

Infrastructure

Firebase Hosting, Cloud Storage, CI/CD pipelines with automated testing.

<card-rain-section scroll-height="300" style=" --crs-bg: #0a192f; --crs-card-bg: #112240; --crs-card-radius: 4px; --crs-card-padding: 32px; --crs-title-color: rgba(100, 255, 218, 0.8); --crs-title-size: 8rem; " > <span slot="title">Tech<br>Stack</span> <div slot="card">...</div> <div slot="card">...</div> <div slot="card">...</div> </card-rain-section>

CSS Custom Properties

All available CSS custom properties for styling the component.

Property Default Description
--crs-bg #1a1618 Background color of the canvas area
--crs-card-bg var(--accent-gold, #bfa15f) Card background color
--crs-card-radius 16px Card border radius
--crs-card-width 440px Card width
--crs-card-padding 48px Card inner padding
--crs-title-size 10rem Title font size
--crs-title-color rgba(255, 255, 255, 1) Title text color
Demo code (CodePen-ready HTML, CSS, JS)
HTML (html)
<h1>Card Rain Section</h1>
  <p class="subtitle">Scroll-driven card rain animation section with drop and zoom modes.</p>
  <div class="demo-links">
    <a href="https://manufosela.dev/ui-components/">&larr; Back to components</a>
    <a href="https://github.com/manufosela/ui-components/tree/main/packages/card-rain-section" target="_blank" rel="noopener">GitHub Repo</a>
    <a href="playground.html">Playground</a>
    <a href="https://www.npmjs.com/package/@manufosela/card-rain-section" target="_blank" rel="noopener">npm</a>
  </div>
  <div class="demo-theme-toggle">
    <theme-toggle theme="dark"></theme-toggle>
  </div>

  <!-- Basic Usage -->
  <div class="demo-section">
    <h2>Basic Usage (Drop Mode)</h2>
    <p>Scroll down through the section to see cards fall into view one by one. The default animation mode is "drop".</p>
  </div>

  <div class="scroll-spacer">Scroll down to see the card rain effect</div>

  <card-rain-section scroll-height="300">
    <span slot="title">Our<br>Services</span>

    <div slot="card">
      <div class="sample-card">
        <h3>Design</h3>
        <p>We craft beautiful interfaces that delight users and drive engagement through thoughtful design principles.</p>
      </div>
    </div>

    <div slot="card">
      <div class="sample-card">
        <h3>Development</h3>
        <p>Modern web applications built with cutting-edge technologies for performance and scalability.</p>
      </div>
    </div>

    <div slot="card">
      <div class="sample-card">
        <h3>Strategy</h3>
        <p>Data-driven strategies that align technology with business goals for measurable results.</p>
      </div>
    </div>

    <button slot="actions" class="cta-button">Learn More</button>
  </card-rain-section>

  <div class="code-block">&lt;card-rain-section scroll-height="300"&gt;
  &lt;span slot="title"&gt;Our&lt;br&gt;Services&lt;/span&gt;

  &lt;div slot="card"&gt;
    &lt;div class="sample-card"&gt;
      &lt;h3&gt;Design&lt;/h3&gt;
      &lt;p&gt;Description text...&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div slot="card"&gt;...&lt;/div&gt;
  &lt;div slot="card"&gt;...&lt;/div&gt;

  &lt;button slot="actions"&gt;Learn More&lt;/button&gt;
&lt;/card-rain-section&gt;</div>

  <div class="scroll-spacer"></div>

  <!-- Zoom Mode -->
  <div class="demo-section">
    <h2>Zoom Mode</h2>
    <p>Set <code>fall-mode="zoom"</code> to make cards scale down from a large size with a blur-to-sharp transition.</p>
  </div>

  <div class="scroll-spacer">Scroll down to see the zoom effect</div>

  <card-rain-section scroll-height="300" fall-mode="zoom">
    <span slot="title">Featured<br>Work</span>

    <div slot="card">
      <div class="sample-card">
        <h3>Project Alpha</h3>
        <p>A comprehensive platform redesign that increased user retention by 40%.</p>
      </div>
    </div>

    <div slot="card">
      <div class="sample-card">
        <h3>Project Beta</h3>
        <p>E-commerce solution handling millions of transactions with 99.9% uptime.</p>
      </div>
    </div>

    <div slot="card">
      <div class="sample-card">
        <h3>Project Gamma</h3>
        <p>Mobile-first application serving users across 30 countries worldwide.</p>
      </div>
    </div>

    <button slot="actions" class="cta-button">View Portfolio</button>
  </card-rain-section>

  <div class="code-block">&lt;card-rain-section scroll-height="300" fall-mode="zoom"&gt;
  &lt;span slot="title"&gt;Featured&lt;br&gt;Work&lt;/span&gt;
  &lt;div slot="card"&gt;...&lt;/div&gt;
  &lt;div slot="card"&gt;...&lt;/div&gt;
  &lt;div slot="card"&gt;...&lt;/div&gt;
  &lt;button slot="actions"&gt;View Portfolio&lt;/button&gt;
&lt;/card-rain-section&gt;</div>

  <div class="scroll-spacer"></div>

  <!-- Custom Styles -->
  <div class="demo-section">
    <h2>Custom Styles</h2>
    <p>Customize the appearance using CSS custom properties.</p>
  </div>

  <div class="scroll-spacer">Scroll down to see custom-styled cards</div>

  <card-rain-section
    scroll-height="300"
    style="
      --crs-bg: #0a192f;
      --crs-card-bg: #112240;
      --crs-card-radius: 4px;
      --crs-card-padding: 32px;
      --crs-title-color: rgba(100, 255, 218, 0.8);
      --crs-title-size: 8rem;
    "
  >
    <span slot="title">Tech<br>Stack</span>

    <div slot="card">
      <div class="sample-card">
        <h3>Frontend</h3>
        <p>Lit, Web Components, Astro, modern CSS with custom properties and container queries.</p>
      </div>
    </div>

    <div slot="card">
      <div class="sample-card">
        <h3>Backend</h3>
        <p>Node.js, Firebase Cloud Functions, REST APIs with comprehensive documentation.</p>
      </div>
    </div>

    <div slot="card">
      <div class="sample-card">
        <h3>Infrastructure</h3>
        <p>Firebase Hosting, Cloud Storage, CI/CD pipelines with automated testing.</p>
      </div>
    </div>
  </card-rain-section>

  <div class="code-block">&lt;card-rain-section
  scroll-height="300"
  style="
    --crs-bg: #0a192f;
    --crs-card-bg: #112240;
    --crs-card-radius: 4px;
    --crs-card-padding: 32px;
    --crs-title-color: rgba(100, 255, 218, 0.8);
    --crs-title-size: 8rem;
  "
&gt;
  &lt;span slot="title"&gt;Tech&lt;br&gt;Stack&lt;/span&gt;
  &lt;div slot="card"&gt;...&lt;/div&gt;
  &lt;div slot="card"&gt;...&lt;/div&gt;
  &lt;div slot="card"&gt;...&lt;/div&gt;
&lt;/card-rain-section&gt;</div>

  <div class="scroll-spacer"></div>

  <!-- CSS Custom Properties Reference -->
  <div class="demo-section">
    <h2>CSS Custom Properties</h2>
    <p>All available CSS custom properties for styling the component.</p>
    <table class="props-table">
      <thead>
        <tr>
          <th>Property</th>
          <th>Default</th>
          <th>Description</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td><code>--crs-bg</code></td>
          <td><code>#1a1618</code></td>
          <td>Background color of the canvas area</td>
        </tr>
        <tr>
          <td><code>--crs-card-bg</code></td>
          <td><code>var(--accent-gold, #bfa15f)</code></td>
          <td>Card background color</td>
        </tr>
        <tr>
          <td><code>--crs-card-radius</code></td>
          <td><code>16px</code></td>
          <td>Card border radius</td>
        </tr>
        <tr>
          <td><code>--crs-card-width</code></td>
          <td><code>440px</code></td>
          <td>Card width</td>
        </tr>
        <tr>
          <td><code>--crs-card-padding</code></td>
          <td><code>48px</code></td>
          <td>Card inner padding</td>
        </tr>
        <tr>
          <td><code>--crs-title-size</code></td>
          <td><code>10rem</code></td>
          <td>Title font size</td>
        </tr>
        <tr>
          <td><code>--crs-title-color</code></td>
          <td><code>rgba(255, 255, 255, 1)</code></td>
          <td>Title text color</td>
        </tr>
      </tbody>
    </table>
  </div>
CSS (css)
:root {
  --bg: #0c0f14;
  --bg-elevated: #141923;
  --bg-panel: #171d28;
  --border: #262f3f;
  --text: #f4f6fb;
  --text-muted: #a7b0c2;
  --text-dim: #7d879b;
  --accent: #ff8a3d;
  --accent-strong: #ff6a00;
  --accent-soft: rgba(255, 138, 61, 0.16);
  --shadow: 0 20px 50px rgba(5, 8, 14, 0.45);
  --radius-lg: 22px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --max-width: 1160px;
}

h1 { color: #1d1d1f; }
    .demo-section {
      background: white;
      padding: 2rem;
      border-radius: 12px;
      margin-bottom: 2rem;
      box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    }
    h2 { margin-top: 0; color: #1d1d1f; }
    p { color: #86868b; line-height: 1.6; }
    a { color: #3b82f6; }
    .code-block {
      background: #1d1d1f;
      color: #f5f5f7;
      padding: 1rem;
      border-radius: 8px;
      font-family: monospace;
      font-size: 0.8rem;
      margin-top: 1rem;
      overflow: auto;
      max-height: 300px;
      white-space: pre;
    }
    footer {
      text-align: center;
      margin-top: 3rem;
      padding-top: 2rem;
      border-top: 1px solid #d2d2d7;
      color: #86868b;
      font-size: 0.9rem;
    }
    footer a { color: #1d1d1f; text-decoration: none; }
    footer a:hover { text-decoration: underline; }

    /* Sample card content styles */
    .sample-card {
      padding: 1.5rem;
      color: #fff;
    }
    .sample-card h3 {
      margin: 0 0 0.5rem;
      font-size: 1.25rem;
    }
    .sample-card p {
      margin: 0;
      color: rgba(255, 255, 255, 0.85);
      font-size: 0.9rem;
    }

    /* Spacer to allow scroll */
    .scroll-spacer {
      height: 50vh;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #86868b;
      font-size: 1.1rem;
    }

    /* CSS properties table */
    .props-table {
      width: 100%;
      border-collapse: collapse;
      font-size: 0.85rem;
    }
    .props-table th,
    .props-table td {
      text-align: left;
      padding: 0.5rem 0.75rem;
      border-bottom: 1px solid #e5e7eb;
    }
    .props-table th {
      background: #f9fafb;
      color: #1d1d1f;
      font-weight: 600;
    }
    .props-table td {
      color: #374151;
    }
    .props-table code {
      background: #f3f4f6;
      padding: 0.15rem 0.35rem;
      border-radius: 4px;
      font-size: 0.8rem;
    }

    /* Action button style */
    .cta-button {
      display: inline-block;
      padding: 0.75rem 2rem;
      background: #fff;
      color: #1d1d1f;
      border-radius: 8px;
      text-decoration: none;
      font-weight: 600;
      font-size: 0.95rem;
      border: none;
      cursor: pointer;
    }
    .cta-button:hover {
      background: #e5e5ea;
    }
  


@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&display=swap');

:root {
  --bg: #f5f5f7;
  --bg-2: #ffffff;
  --bg-spot-1: #f8e9d0;
  --bg-spot-2: #e8eef8;
  --card: #ffffff;
  --text: #1d1d1f;
  --muted: #6b7280;
  --line: #e5e7eb;
  --accent: #ffb000;
  --accent-2: #00a7d6;
  --accent-soft: rgba(255, 176, 0, 0.18);
  --surface-1: #f3f4f6;
  --surface-2: #eef2f7;
  --code-bg: #111827;
  --code-text: #f9fafb;
  --panel-bg: rgba(255, 255, 255, 0.85);
  --overlay-bg: rgba(255, 255, 255, 0.98);
}

:root.dark {
  --bg: #0f1117;
  --bg-2: #151a26;
  --bg-spot-1: #1a2136;
  --bg-spot-2: #1d1b34;
  --card: #1c2233;
  --text: #f3f6ff;
  --muted: #b8c0d9;
  --line: #2b3247;
  --accent: #ffb000;
  --accent-2: #00d0ff;
  --accent-soft: rgba(255, 176, 0, 0.25);
  --surface-1: #0b0f1a;
  --surface-2: #263046;
  --code-bg: #0b0f1a;
  --code-text: #d6d9e6;
  --panel-bg: rgba(28, 34, 51, 0.8);
  --overlay-bg: rgba(15, 17, 23, 0.98);
}

* {
  box-sizing: border-box;
}

a {
  color: var(--accent);
}

h1 {
  color: var(--accent);
}

.demo-links {
  margin-top: 12px;
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

.demo-links a {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 12px;
  color: var(--muted);
  text-decoration: none;
  font-size: 0.85rem;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.demo-links a:hover {
  color: var(--text);
  border-color: var(--accent-2);
}

.demo-theme-toggle {
  margin-top: 12px;
  display: flex;
  justify-content: center;
}

header {
  border-bottom: 1px solid var(--line);
}

.demo-card,
.section,
.demo-section,
.panel,
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 16px;
  color: var(--text);
  box-shadow: 0 18px 36px rgba(6, 10, 24, 0.45);
}

.demo-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.demo-card .code-block {
  margin-top: auto;
}

.demo-grid,
.grid {
  align-items: stretch;
}

.demo-card h2,
.demo-card h3,
.section h2,
.demo-section h2,
.panel-header {
  color: var(--text);
}

.label,
.stat-label,
.category-title,
.subtitle,
.hint,
.note {
  color: var(--muted);
}

.info-item,
.capability,
.preference,
.option-group,
.output,
.current-url,
.event-log,
.result-card,
.log,
.stat {
  background: var(--surface-1);
  border: 1px solid var(--line);
  color: var(--text);
}

.info-item .label,
.capability .name {
  color: var(--muted);
}

.panel-header,
.options,
.topbar,
.top-links {
  background: var(--panel-bg);
  border-bottom: 1px solid var(--line);
  color: var(--text);
}

.subtitle,
.hint,
.note,
.demo-card p,
.section p,
.demo-section p {
  color: var(--muted);
}

.code-block,
pre,
code {
  background: var(--code-bg);
  color: var(--code-text);
  border-radius: 8px;
}

.value-display,
.output,
.result,
.demo-output {
  background: var(--surface-1);
  border: 1px solid var(--line);
  color: var(--text);
}

button {
  background: linear-gradient(120deg, var(--accent), #ff6a00);
  color: #111;
  border: none;
}

button:hover {
  filter: brightness(1.05);
}

input,
select,
textarea {
  background: var(--surface-1);
  color: var(--text);
  border: 1px solid var(--line);
}

footer {
  color: var(--muted);
}

footer a {
  color: var(--text);
}

arc-slider {
  --arc-slider-text-color: var(--text);
  --arc-slider-value-bg: var(--surface-1);
  --arc-slider-value-border: var(--line);
  --arc-slider-value-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
}

rich-select {
  --caller-background: var(--card);
  --caller-color: var(--text);
  --caller-border: 1px solid var(--line);
  --caller-hover-background: var(--surface-2);
  --caller-hover-color: var(--text);
  --caller-hover-border-color: var(--line);
  --caller-focus-border-color: var(--accent-2);
  --caller-focus-shadow: 0 0 0 3px rgba(0, 208, 255, 0.25);
  --caller-disabled-background: var(--surface-1);
  --caller-disabled-color: #6b7280;
  --caller-disabled-border-color: var(--line);
  --arrow-color: var(--muted);
  --selectOptions-background: var(--card);
  --selectOptions-border: 1px solid var(--line);
  --selectOptions-shadow: 0 10px 22px rgba(0, 0, 0, 0.45);
  --input-background: var(--surface-1);
  --input-border: 1px solid var(--line);
  --input-color: var(--text);
  --input-placeholder-color: #6b7280;
  --option-color: var(--text);
  --option-hover-background: var(--surface-2);
  --option-hover-color: var(--text);
  --option-active-background: var(--accent);
  --option-active-color: #111;
  --option-selected-background: var(--accent-soft);
  --option-selected-color: var(--text);
  --option-disabled-background: var(--surface-1);
  --option-disabled-color: #6b7280;
}

multi-select {
  --multi-select-bg: var(--card);
  --multi-select-border-color: var(--line);
  --multi-select-border-hover: var(--line);
  --multi-select-border-focus: var(--accent-2);
  --multi-select-text-color: var(--text);
  --multi-select-placeholder-color: #6b7280;
  --multi-select-arrow-color: var(--muted);
  --multi-select-dropdown-bg: var(--card);
  --multi-select-shadow: 0 10px 22px rgba(0, 0, 0, 0.45);
  --multi-select-option-hover-bg: var(--surface-2);
  --multi-select-option-selected-bg: var(--accent-soft);
}

tab-nav {
  --tab-bg: var(--card);
  --tab-border: var(--line);
  --tab-text: var(--muted);
  --tab-active-text: var(--text);
  --tab-hover-bg: var(--surface-2);
  --tab-active-border: var(--accent);
  --tab-disabled: #9ca3af;
}

slider-underline {
  --slider-track: var(--surface-2);
  --slider-fill: var(--accent);
  --slider-thumb: var(--accent);
  --slider-label-color: var(--text);
  --slider-tick-color: #9ca3af;
  --slider-tick-value-color: var(--muted);
}

header-nav {
  --header-bg: var(--card);
  --header-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
  --header-link-color: var(--text);
  --header-link-hover: var(--accent);
  --header-mobile-hover-bg: var(--surface-2);
}

calendar-inline {
  --calendar-bg: var(--card);
  --calendar-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
  --calendar-text: var(--text);
  --calendar-accent: var(--accent);
  --calendar-today: var(--accent-soft);
  --calendar-selected: var(--accent);
  --calendar-hover-bg: var(--surface-2);
  --calendar-muted: var(--muted);
  --calendar-muted-strong: #9ca3af;
  --calendar-other-month: #9ca3af;
  --calendar-disabled: #cbd5e1;
  --calendar-holiday: #ef4444;
  --calendar-holiday-selected: #111;
}

marked-calendar {
  --calendar-bg: var(--card);
  --calendar-border: var(--line);
  --calendar-title: var(--text);
  --calendar-muted: var(--muted);
  --calendar-surface: var(--surface-1);
  --calendar-accent: var(--accent);
  --calendar-accent-hover: #ff7a1a;
  --calendar-border-strong: var(--line);
  --calendar-contrast: #111;
  --calendar-nav-bg: var(--surface-1);
  --calendar-nav-hover: var(--surface-2);
}

radar-chart {
  --radar-bg: var(--card);
  --radar-grid-color: var(--line);
  --radar-axis-color: #94a3b8;
  --radar-label-color: var(--muted);
}

multi-carousel {
  --carousel-bg: var(--card);
  --carousel-arrow-bg: var(--surface-1);
  --carousel-arrow-color: var(--text);
  --carousel-arrow-hover-bg: var(--surface-2);
  --carousel-arrow-hover-color: var(--text);
  --carousel-nav-bg: var(--surface-1);
  --carousel-nav-color: var(--muted);
  --carousel-nav-hover: #9ca3af;
  --carousel-nav-active: var(--accent);
  --carousel-focus-color: var(--accent-2);
}

nav-list {
  --nav-list-bg: var(--card);
  --nav-list-border-color: var(--line);
  --nav-list-selected-border-color: var(--accent);
  --nav-list-selected-bg: var(--surface-2);
  --nav-list-hover-bg: var(--surface-2);
  --nav-list-selected-color: var(--text);
}

theme-toggle {
  --theme-toggle-bg: var(--card);
  --theme-toggle-icon-color: var(--muted);
  --theme-toggle-hover-bg: var(--surface-2);
  --theme-toggle-active-bg: var(--surface-1);
  --theme-toggle-active-color: var(--text);
  --theme-toggle-dark-bg: var(--card);
  --theme-toggle-dark-border: var(--line);
  --theme-toggle-dark-icon-color: var(--muted);
  --theme-toggle-dark-active-bg: var(--surface-1);
  --theme-toggle-dark-active-color: var(--text);
  --theme-toggle-dark-hover-bg: var(--surface-2);
}

qr-code {
  --qr-fg: #0f1117;
  --qr-bg: #f3f6ff;
}

click-clock {
  --clock-color: var(--text);
  --clock-bg: var(--card);
  --clock-muted-color: var(--muted);
}

historical-line {
  --title-color: var(--text);
  --border-color: var(--line);
  --year-bg: var(--surface-1);
}

circle-steps {
  --steps-muted: var(--muted);
  --steps-text: var(--text);
  --steps-pending: var(--surface-2);
}

rich-inputfile {
  --input-border: var(--line);
  --input-border-focus: var(--accent-2);
  --input-bg: var(--card);
  --input-label-color: var(--text);
  --input-hover-bg: var(--surface-2);
  --input-drag-bg: var(--accent-soft);
  --input-disabled-bg: var(--surface-1);
  --input-success-border: #22c55e;
  --input-success-bg: rgba(34, 197, 94, 0.12);
  --input-icon-color: #94a3b8;
  --input-text-color: var(--muted);
  --input-accent-color: var(--accent-2);
  --input-file-bg: var(--surface-1);
  --input-preview-bg: var(--surface-1);
  --input-file-name-color: var(--text);
  --input-file-size-color: var(--muted);
  --input-error-color: #ef4444;
  --input-hint-color: var(--muted);
}

data-card {
  --data-card-bg: var(--card);
  --data-card-border-color: var(--line);
  --data-card-title-color: var(--text);
  --data-card-desc-color: var(--muted);
  --data-card-info-bg: var(--overlay-bg);
  --data-card-info-close-bg: var(--surface-2);
  --data-card-info-close-color: var(--text);
  --data-card-info-close-hover-bg: var(--surface-1);
  --data-card-info-text: var(--text);
  --data-card-loading-color: var(--muted);
  --data-card-info-trigger-hover: var(--accent);
}

app-modal {
  --app-modal-bg: var(--card);
  --app-modal-body-color: var(--text);
  --app-modal-standalone-bg: rgba(255, 176, 0, 0.35);
  --app-modal-standalone-color: #111;
  --app-modal-standalone-hover-bg: rgba(255, 176, 0, 0.6);
}
JS (js)
document.querySelectorAll('.footer-year').forEach(el => el.textContent = new Date().getFullYear());
  

    import "https://esm.sh/@manufosela/card-rain-section";
  

    import '../../theme-toggle/src/theme-toggle.js';

    const root = document.documentElement;
    root.classList.add('dark');

    const toggle = document.querySelector('theme-toggle');
    if (toggle) {
      toggle.theme = root.classList.contains('dark') ? 'dark' : 'light';
      toggle.addEventListener('theme-changed', (event) => {
        const theme = event.detail?.theme;
        if (!theme) return;
        root.classList.toggle('dark', theme === 'dark');
      });
    }