Narrative Codex
Codex II — for long stories, archives, and song

Break the text wall.
Keep the spell.

You asked for accordions that don’t feel like FAQs, button grids that feel like a guild hall, and long narratives that breathe — plus glowing stars and floating music notes. This is your second codex. Same mix-and-match idea as the Layout Codex, but tuned for story pages like Echorin, Harrowmere, and the Whispering Way.

accordionsbutton gridslong narrative breathersglowing starsfloating notes
01. Accordions

Let readers choose the depth

Accordions are for progressive disclosure — lore, map keys, timelines, guild laws. Use short titles, keep each panel scan-friendly. Don’t hide the only important thing.

Clean Exclusive Accordion

Best for: lore entries • FAQs • codex pages

One panel open at a time. Feels tidy, like turning a page. Use for canon, glossary, or your “Four Sisters” breakdowns.

Truth before comfort. Aevraya shows you what you hid from yourself, in your own voice. First mercy is seeing without distortion. Without this, no other current can move.

Forgiveness is motion, not absolution. Warm water appears where you confess. Tend both wounds — yours and your enemy’s — or the flame gutters.

To create is to remember. In the silence after loss, make something — song, word, gesture — and let the river echo it back larger than grief.

Integration over denial. Everything you cast away stands up and walks toward you. The current drowns fighters, crowns those who embrace.

<div class="accordion">
  <div class="acc-item open">
    <button class="acc-btn">Section title <span>⌄</span></button>
    <div class="acc-panel">Hidden content...</div>
  </div>
</div>

<style>
.accordion{border:1px solid rgba(255,255,255,.14);border-radius:12px;overflow:hidden}
.acc-panel{max-height:0;overflow:hidden;transition:max-height .35s ease}
.acc-item.open .acc-panel{max-height:400px;padding:12px 16px}
</style>
<script>
document.querySelectorAll('.acc-btn').forEach(btn=>{
 btn.addEventListener('click',()=>{
  const item=btn.parentElement;
  const wasOpen=item.classList.contains('open');
  document.querySelectorAll('.acc-item').forEach(i=>i.classList.remove('open'));
  if(!wasOpen) item.classList.add('open');
 });
});
</script>

Simple Details Accordion (no JS)

Best for: quick entries • patch notes • map keys

Native HTML — <details> — zero JavaScript. Multiple panels can be open. Paste this anywhere when you want zero fuss.

The Map Key — How the floor guides youtap to open

Blue-Green Tide-Threads → portal pools. Silver-Gold lines → canopy sky-docks. Earthy Spore-Tracks → root-barges. The floor *is* the signage.

The Silver Needle Ruletap to open

Leave the seam open so real-world time bleeds into the map. Closed seam = 10 years of emotion in hours. Harrowmere taught this.

Syrenae — why the sung words are gibberishtap to open

No PA speakers work in Atheria — resonance only. Tide-Readers and Echo-Weavers sing in First Language. The chest hum guides you, not the words.

<details class="card">
  <summary>The Map Key</summary>
  <p>Blue-Green Tide-Threads → portals. Silver-Gold → sky-docks. Spore-Tracks → roots.</p>
</details>

<style>
details{border:1px solid rgba(255,255,255,.12);border-radius:12px;padding:12px}
details summary{list-style:none;display:flex;justify-content:space-between;cursor:pointer}
details[open]{background:rgba(77,216,200,.06)}
</style>
02. Button grids

Make choices feel playable

Button grids turn navigation into action. Use them for chapter selects, guild permits, trial choices, filters, and map terminals. Keep labels short, icons legible, and give the active state real contrast.

Chapter / Trial Select Grid

Best for: 3–6 story options • trials • routes

Selected: Reflection — Aevraya • Truth before comfort

<div class="btn-grid cols-3">
  <button class="g-btn active">
    <span>☾</span><b>Reflection</b><small>Headwaters</small>
  </button>
  <button class="g-btn">...</button>
</div>

<style>
.btn-grid{ display:grid; gap:10px; grid-template-columns:repeat(3, minmax(0,1fr)); }
.g-btn{ border:1px solid rgba(255,255,255,.14); border-radius:12px; padding:14px; text-align:left; }
.g-btn.active{ background:linear-gradient(135deg,#4dd8c8,#e9b44c); color:#0c1a1d; }
@media(max-width:700px){ .btn-grid{ grid-template-columns:1fr 1fr; } }
</style>

Guild Permit Grid — Auto-fit

Best for: many options • filters • terminals

Auto-fit grids choose column count for you based on available width. Ideal for your Canopy guild cards and nation terminals. Resize the window to see it reflow.

<div class="btn-grid auto">
  <button class="g-btn"><b>Bards</b><small>Permitted</small></button>
  <button class="g-btn"><b>Couriers</b><small>Permitted</small></button>
  <button class="g-btn"><b>Locked guilds...</b></button>
</div>

<style>
.btn-grid.auto{ display:grid; gap:10px; grid-template-columns:repeat(auto-fit, minmax(140px, 1fr)); }
</style>

Chip / Filter Grid

Best for: tags • moods • quick filters

Use chips when the choice is soft — filter, mood, perspective — not a hard branch.

<div class="chip-grid">
  <button class="chip active">All currents</button>
  <button class="chip">Reflection</button>
</div>

<style>
.chip-grid{display:flex;flex-wrap:wrap;gap:8px}
.chip{border:1px solid rgba(255,255,255,.14);border-radius:999px;padding:7px 12px;font-size:11px}
.chip.active{background:#f6f1e7;color:#0c1a1d}
</style>
03. Long narrative without the wall

Give the eye places to rest

Same words, different rhythm. Break long text with five breathers: drop caps, pull quotes, side notes, reveals, and timelines. Paste your own Syrenae directly into the demo.

Story Page Demo — Paste Your Text Here

Editable demo • Replace me
The Whispering WaySource → Sea • 4 Trials

The river was not water at first, but a pulse made flesh — Lysera, whom Alezion named Beloved, who laughed the Solari into sky and then poured herself into water so raw essence could learn to speak. You were told balance is the absence of chaos. It isn’t. Balance is the act of integrating it. Paste your own paragraph here — this drop cap stays.

“To ignore the storm is to be drowned by it; to embrace the current is to sing with the river.”

At Headwaters, Aevraya does not judge, she reveals. The pool shows Mirael the seam she left closed at Harrowmere. Not as accusation, as invitation: accept what is shown, or shatter the vision and restart lifetimes later. This is your long paragraph — use the side panel to keep facts handy so the main text stays dreamy.

↳ Syrenae note (tap to reveal gibberish)

Shae’lún vari, Harrow nóra, loe thirra sel — the sung version of “I left the door open.” Keep this hidden until the reader is ready.

Truth before comfort — breath over still water. The reflection speaks in your voice, saying what you hid.

Forgiveness is motion — warm water where you confess. Tend both wounds or the flame gutters.

To create is to remember — make something from grief, let the river echo it larger than sorrow.

Integration over denial — everything you cast away stands up. Current drowns fighters, crowns embracers.

Headwaters — Mirror Pools

Biolucent cliff, glassy pools, ripples on dry ground. Aevraya shows the hidden thread.

Middle Currents — Hand Domain

Golden reeds, steam spirits, hot springs where regrets are painted on stones.

Delta — Shell Domain

Tide-pools like open hands, shells that hum when held to the heart. Endings become beginnings.

Subterranean — Stone Domain

Silver-veined stone, cold water, heartbeat echoing back unfamiliar. Vaeloria waits.

Paste your own writing here: click any paragraph above — they’re all contenteditable. Type your Syrenae, your Harrowmere beach, your Mael canal. The styles hold.
<article class="story">
  <p class="dropcap">The river was not water at first...</p>
  <blockquote class="pull">“To ignore the storm...”</blockquote>
  <div class="sidenote-grid">
    <div>Main text... <details><summary>Syrenae</summary>...</details></div>
    <aside class="sidenote">At a glance...</aside>
  </div>
  <div class="tabs">...</div>
  <div class="timeline">...</div>
</article>

<style>
.dropcap::first-letter{ float:left; font-size:3.2em; line-height:.8; padding:6px 8px 0 0; color:#1a8d91; }
.pull{ border-left:3px solid #e9b44c; background:rgba(233,180,76,.08); padding:16px; font-style:italic; font-size:1.35em; }
.sidenote-grid{ display:grid; grid-template-columns:1.55fr 220px; gap:18px; }
.sidenote{ border:1px solid rgba(12,26,29,.12); background:#f0ece0; border-radius:12px; padding:12px; }
.timeline{ border-left:2px solid rgba(12,26,29,.12); padding-left:18px; }
@media(max-width:700px){ .sidenote-grid{ grid-template-columns:1fr; } }
</style>
04. Atmosphere — Stars & Notes

Glowing stars. Floating music.

Yes — both are possible with pure HTML/CSS/JS, no libraries. Use them as light layers behind story sections. Not everywhere. Like scent: enough to notice, not enough to choke.

✦ Glowing Stars Field

Best for: Auralith • Oneiroi • night • delta sky
The sky remembers too.

Tiny stars twinkle with CSS, one shooting star crosses every ~3.5s. This sits behind your text — place the stage as a position:absolute layer inside a section.

<div class="star-stage">
  <div class="starry"> <!-- JS fills 60 stars --> </div>
  <div class="content">Your text...</div>
</div>

<style>
.star-stage{ position:relative; overflow:hidden; background:linear-gradient(180deg,#0b1f24,#0a1519); }
.starry{ position:absolute; inset:0; pointer-events:none; }
.star{ position:absolute; width:2px; height:2px; background:white; border-radius:50%;
  box-shadow:0 0 8px white, 0 0 14px rgba(77,216,200,.6);
  animation:twinkle 2.8s infinite; }
@keyframes twinkle{ 0%,100%{opacity:.15} 50%{opacity:1} }
.shoot{ position:absolute; height:1px; width:120px;
  background:linear-gradient(to right, transparent, white, transparent);
  animation:shoot 3.5s linear infinite; }
@keyframes shoot{ 0%{transform:translateX(-140px) translateY(60px) rotate(-18deg);opacity:0}
  10%{opacity:1} 100%{transform:translateX(520px) translateY(-40px) rotate(-18deg);opacity:0}}
</style>
<script>
const starry=document.getElementById('starry');
for(let i=0;i<60;i++){
 const s=document.createElement('div'); s.className='star';
 s.style.left=Math.random()*100+'%'; s.style.top=Math.random()*100+'%';
 s.style.animationDelay=(Math.random()*3)+'s'; s.style.animationDuration=(2+Math.random()*2)+'s';
 starry.appendChild(s);
}
</script>

♪ Floating Music Notes

Best for: Sung Announcements • Echorin • Bards • Confluence
Echorin teaches you how to listen.

Notes drift upward, swaying with a wobble. They are pure text — ♪ ♫ ♩ ♬ — so they never need images. Trigger a burst or leave a gentle stream.

Tip: pair notes with backdrop-filter: blur() text cards so the music feels “behind the veil.”

<div class="note-stage">
  <div id="notesLayer"></div>
  <div class="content">Your story...</div>
</div>

<style>
.note-stage{ position:relative; overflow:hidden; }
.note{ position:absolute; font-size:18px; color:rgba(246,241,231,.9);
  text-shadow:0 0 12px rgba(233,180,76,.6);
  animation:floatNote linear forwards; }
@keyframes floatNote{
  0%{ transform:translateY(40px) translateX(0) rotate(0deg); opacity:0 }
  10%{opacity:1}
  100%{ transform:translateY(-260px) translateX(var(--drift)) rotate(var(--spin)); opacity:0 }
}
</style>
<script>
function spawnNote(){
 const el=document.createElement('div'); el.className='note';
 el.textContent=['♪','♫','♩','♬'][Math.floor(Math.random()*4)];
 el.style.left=(10+Math.random()*80)+'%';
 el.style.bottom='10%';
 el.style.setProperty('--drift',(Math.random()*60-30)+'px');
 el.style.setProperty('--spin',(Math.random()*40-20)+'deg');
 el.style.animationDuration=(3+Math.random()*3)+'s';
 notesLayer.appendChild(el);
 setTimeout(()=>el.remove(), 6000);
}
setInterval(spawnNote, 420); // gentle stream
</script>

○ Spore / Firefly Drift — bonus

Best for: Mycelians • lagoon • market
Luminous Spore-Tracks

Soft green motes that tell you which way to walk.

<div id="sporeLayer"></div>

<style>
.spore{ position:absolute; width:6px; height:6px; border-radius:50%;
  background:radial-gradient(circle at 30% 30%, #d9ffe6, #4dd8c8);
  box-shadow:0 0 12px rgba(77,216,200,.6);
  animation:drift linear infinite; }
@keyframes drift{ 0%{transform:translateY(20px)} 100%{transform:translateY(-280px)} }
</style>

How to layer effects without ruining readability

The 3 rules
1. Effects are backgrounds

Put the star/note layer at position:absolute; inset:0; pointer-events:none; opacity:.7 and your text card at position:relative; z-index:1; backdrop-filter:blur(8px).

2. Less is sacred

Use effects on one section, not every section. A single star field on the hero + occasional note bursts on a Sung Announcement reads intentional.

3. Honor reduced motion

Wrap heavy animation with @media (prefers-reduced-motion:reduce){.star,.note,.spore{animation:none}}.

05. Recipes — put it together

Three ready story page combos

Start here when you’re staring at a blank page and have *words* but no shape.

RECIPE A — CODEX LORE

The Archivist Page

Exclusive accordion + Chip filters on top + Sidenote grid for sources + Star field only on title.

  • Accordion per sister / guild
  • Chips to filter by domain
  • Side notes for citations
  • One shooting star, rarely
RECIPE B — PILGRIMAGE

The Walk Page

Dropcap + Pull quote + Tabs per trial + Timeline at the end + gentle note stream.

  • Button grid as chapter select
  • Tabs for 4 sisters
  • Timeline for source→sea
  • Notes drift in Creation section only
RECIPE C — MARKET EVENT

The Living Hub

Auto-fit guild grid + <details> for rules + Spore drift in root section.

  • Auto-fit for 7 nation terminals
  • Details for permit law
  • Spores tracing the floor
  • Notes on Sung Announcements
You wrote “This too:” — I left the narrative demo editable so you can paste that text directly. If you send it, I’ll lay it out in one of these recipes for you.
Atheria Narrative Codex — plain HTML + CSS, no framework. Effects are CSS + ~20 lines of JS. Pair with Layout Codex for page structure.
Copied