SWAMP UI / COMPONENTS / SWAMP TAROT

Swamp Tarot

15 archetypes from the bog. tap the deck.

Pull a card. The bog answers. Each card is an archetype of the swamp — The Heron, The Fog, The Frog King, The Lantern — with a short reading. The name spins into place via split-flap. Use as a daily oracle, a decision aid, or a quiet "I'm stuck, give me a metaphor" button.

No dependencies
15 archetypes
Split-flap reveal
Daily-seed mode
Get deck as JSON
LIVE PREVIEW · TAP THE DECK
SWAMP
TAROT

tap the deck to pull a card

— · —

When to use

Reach for it when you want a moment of structured wonder — a creative block, a stuck decision, a journal prompt, a daily ritual. Drop it on a "/oracle" page, a 404, a sidebar of a blog. Use the daily mode so the same visitor sees the same card each day (and a new one tomorrow).

Skip it when the page is task-focused and timed (checkouts, signups) — the whole point of the card is patience. The swamp does not rush.

The 15 cards

Click any to draw it directly.

Skip to

1. HTML

A deck container and a drawn-card container. Toggle one or the other based on state.

<div class="tarot" id="tarot">

  <!-- deck (visible until first draw) -->
  <div class="tarot-deck" id="deck">
    <div class="tarot-back s3"></div>
    <div class="tarot-back s2"></div>
    <div class="tarot-back top">
      <div class="tarot-glyph">☾ SWAMP TAROT</div>
    </div>
  </div>

  <!-- drawn card (filled in by JS) -->
  <div class="tarot-drawn" id="drawn" hidden>
    <div class="tarot-card">
      <div class="tc-num"></div>
      <div class="tc-art"></div>
      <div class="tc-name"></div>
      <div class="tc-mean"></div>
    </div>
    <p class="tc-read"></p>
    <button class="tc-btn">PULL ANOTHER</button>
  </div>

</div>

2. CSS

The card uses a 3D flip-in. Three stacked card backs make the deck feel like it has weight.

.tarot-back {
  width: 200px; height: 280px; border-radius: 14px;
  background: linear-gradient(160deg, #2a1530, #0e0a1a);
  border: 1px solid rgba(255, 77, 141, .35);
  cursor: pointer;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .7);
}
.tarot-back.s2 { transform: translate(4px, 4px) rotate(1.2deg); }
.tarot-back.s3 { transform: translate(8px, 8px) rotate(2.4deg); }

.tarot-card {
  width: 240px; height: 336px; border-radius: 16px;
  background: linear-gradient(160deg, #1c4a34, #0e2b1f);
  animation: flip-in .9s cubic-bezier(.34, 1.56, .64, 1);
}

@keyframes flip-in {
  0%   { transform: rotateY(180deg); opacity: 0; }
  50%  { transform: rotateY(90deg);  opacity: .6; }
  100% { transform: rotateY(0);       opacity: 1; }
}

/* name slot — one .ch per character for split-flap */
.tc-name     { display: flex; gap: 1px; font-family: 'Bungee'; }
.tc-name .ch { display: inline-block; min-width: .55em; text-align: center; }

3. JavaScript

draw() picks a random card (or daily-seeded one), renders SVG art, flips the card, then spins the name into place character by character (split-flap).

// Swamp Tarot — pull a card, flip + split-flap name reveal
(function(){
  const POOL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ';
  const tarot = document.getElementById('tarot');
  const deck  = document.getElementById('deck');
  const drawn = document.getElementById('drawn');

  // Pick: random by default, daily if data-daily on container
  function pick(){
    if (tarot.dataset.mode === 'daily') {
      const d = new Date();
      const seed = d.getFullYear()*1000 + d.getMonth()*40 + d.getDate();
      return DECK[seed % DECK.length];
    }
    return DECK[Math.floor(Math.random() * DECK.length)];
  }

  // Split-flap name reveal (lifted from the Split-Flap component)
  function flapName(el, text){
    el.innerHTML = '';
    const spans = [...text].map(target => {
      const s = document.createElement('span');
      s.className = 'ch';
      s.textContent = POOL[Math.floor(Math.random()*POOL.length)];
      s.dataset.target = target;
      el.appendChild(s);
      return s;
    });
    spans.forEach((s, i) => {
      let ticks = 8 + i*3;
      const iv = setInterval(() => {
        s.textContent = POOL[Math.floor(Math.random()*POOL.length)];
        if (--ticks <= 0) { s.textContent = s.dataset.target; clearInterval(iv); }
      }, 45);
    });
  }

  function draw(card){
    card = card || pick();
    deck.hidden = true;
    drawn.hidden = false;
    drawn.querySelector('.tc-num').textContent = 'CARD · ' + card.n;
    drawn.querySelector('.tc-art').innerHTML = card.svg;
    drawn.querySelector('.tc-mean').textContent = card.meaning;
    drawn.querySelector('.tc-read').textContent = card.reading;
    flapName(drawn.querySelector('.tc-name'), card.name);
  }

  deck.addEventListener('click', () => draw());
  drawn.querySelector('.tc-btn').addEventListener('click', () => draw());

  // expose for #-link draws
  window.swampTarotDraw = draw;
})();

4. The deck (data)

15 archetypes. Each has a name, a one-line meaning, a paragraph reading, and an inline SVG so the whole component stays self-contained.

💡 Building your own thing? The same deck is available as a public JSON at sophieren.com/swamp-tarot/deck.json — fetch it directly, no need to copy the array below.

const DECK = [
  { n:'I',    name:'THE HERON',    meaning:'patience that catches',
    reading:'You are not slow. You are waiting for the fish that the louder ones never see.' },
  { n:'II',   name:'THE BOG',      meaning:'the work is heavy on purpose',
    reading:'Stuck is not the failure. The pull is the muscle. Walk slower, lift higher.' },
  { n:'III',  name:'THE LURE',     meaning:'bait wears the face of fortune',
    reading:'The thing that shines may be a hook. Ask who is pulling, not just what glitters.' },
  { n:'IV',   name:'THE MIRROR',   meaning:'still water sees you',
    reading:'You came for an answer; you found a face. Look anyway. The face was the answer.' },
  { n:'V',    name:'FROG KING',    meaning:'claim it',
    reading:'The throne is a leaf. The crown is a sound. Take both. No one is coming to crown you.' },
  { n:'VI',   name:'THE LILY',     meaning:'the offering that floats',
    reading:'Give without proof. The lily has no agenda and still everything orbits it.' },
  { n:'VII',  name:'THE FOG',      meaning:'you cannot see; that is the answer',
    reading:'Stop deciding. The fog will lift in its own hour. Until then, breathe shallow and stand still.' },
  { n:'VIII', name:'THE CROAK',    meaning:'say the thing',
    reading:'The swamp is listening. The frog who calls finds the frog who answers. Silence finds only silence.' },
  { n:'IX',   name:'THE TIDE',     meaning:'the next you is on the way',
    reading:'Something is coming. Do not name it yet. Open the door wider, that is your only job.' },
  { n:'X',    name:'THE MOSS',     meaning:'slow growth is growth',
    reading:'One millimeter a year is a kingdom by the time anyone notices. Keep going.' },
  { n:'XI',   name:'THE REED',     meaning:'bend, hollow, sing',
    reading:'What broke you is what makes you sound. Stop refusing the wind; start being the flute.' },
  { n:'XII',  name:'THE SNAKE',    meaning:'cunning is not cruelty',
    reading:'Take the long way. The shortcut bites. You are allowed to be patient and clever at once.' },
  { n:'XIII', name:'THE LANTERN',  meaning:'a small light, repeated',
    reading:'Be the firefly. One blink will not light the swamp. A hundred thousand of them do.' },
  { n:'XIV',  name:'THE DRAGONFLY',meaning:'transformation',
    reading:'The version of you that flies is not the version that crawled. Stop apologizing for the molt.' },
  { n:'XV',   name:'THE STUMP',    meaning:'what was felled became home',
    reading:'The thing you mourn is now a habitat. Loss did not end the story; it changed the renters.' }
];

5. Parameters you can tweak

WhereDefaultEffect
HTML data-mode="daily"randomSame card all day for the same visitor (seeded by date). Tomorrow rotates.
DECK array15 cardsAdd your own archetypes. Each card needs n / name / meaning / reading / svg.
CSS @keyframes flip-in.9sFlip duration. Shorter = quicker reveal; longer = more theatre.
JS flapName tick speed45msHow fast each character cycles. Lower = snappier reveal.
JS flapName ticks per char8 + i·3Each character locks 3 ticks later than the last. Higher = longer cascade.

Liked this card?

Feed the cats who keep the bog tidy. (And tip the witch who wrote the deck.)

🧋 TREAT THE SWAMP →
More in the garden → Split-Flap Text, Pond Ripple, Firefly Cursor, Curious Companion, Frog Hop.
Browse all →