What it is
A spa site, complete: a full-screen hero, a logo marquee, a treatments accordion, animated figures, a three-step journey, a team carousel, reviews, memberships, an FAQ, a journal, a footer. One page, one HTML file.
The design follows that of a commercial template, of which only the
photos have been kept. All the code has been rewritten: the original came to 192 kB of minified CSS, 159 opaque identifiers, 147 inline style= attributes, a proprietary animation engine and four external libraries — unreadable, and therefore useless for learning from. Here, every section is preceded by a comment saying what it is.
That's the whole point: this template isn't here to be admired, it's here to be read, broken and rebuilt.
What you change first
The colours — seven lines
Right at the top of assets/css/style.css:
--color-surface: #fdf8f0; /* page background, cream */
--color-surface-2: #ffffff; /* cards, navigation bar */
--color-surface-3: #f0e8dc; /* filled boxes */
--color-clay: #6b4423; /* brand colour: headings, dark sections */
--color-sand: #d4c5b0; /* dotted rules, borders */
--color-ink: #33261a; /* body text */
One thing to grasp before touching anything else: a custom property is substituted where it's declared, not where it's used. Redefining --color-ink further down isn't enough: --color-muted, which derives from it, keeps the value computed on :root. That's why the featured membership card redeclares both — and it's exactly the kind of bug that costs twenty minutes when you don't know the rule.
The name
Search for “Lunaris” in index.html. No CSS class carries the brand name: a find-and-replace can't break anything. The logo is an SVG plus a word written in HTML, not outlined text.
The sizes
The type scale is declared once, then redeclared at every breakpoint. So a heading never gets its own media query: you change --h2-size and the whole page follows.
The thirteen effects, and how they're built
All taken from the data of the original's animation engine (147 active triggers, 31 sequences), measured in the browser, then rewritten as readable CSS and JavaScript.
| Effect | Where | How |
|---|---|---|
| Scroll reveal | 50 blocks | IntersectionObserver, firing at 15% of the block, 1000 ms |
| Sideways reveal | 12 blocks | same mechanism, 100 px horizontal translation |
| Rule that draws itself | 14 rules | width 0 → 100% in 1500 ms, in CSS alone |
| Counters | 3 figures | two columns of digits in a one-digit window |
| Framed photo | 4 images | zoom 1.3 → 1 while a scrim slides out of the frame |
| Journey line | steps | height driven by the scroll, target measured on the dots |
| Sticky carousel | team | panel sticky over 300 vh, track translated by the scroll |
| Marquees | logos, opening hours | 59 px/s, copies counted on load, a loop with no jump |
| Buttons | everywhere | the label rises, its copy arrives from below, the icon leaves diagonally |
| Treatments accordion | 4 cards | flex-basis animated: 40.8% for the open card, 28% for the others |
| Social icons | team | the two states swap on hover, the disc fills |
| Dropdowns | navigation | animated height, chevron at 180°, keyboard and Escape handled |
| FAQ | questions | <details> native, animated height, delayed close |
What you should know
- No external requests. Self-hosted fonts, local photos, no CDN, no tracker. The original export made five.
- Scroll reveals can't hide the content. The hidden state only exists once the JavaScript has run. Checked: with JavaScript switched off, the page renders 6,059 characters of text and no block is invisible.
- Zero inline styles, zero inline scripts. The template honours the site's strict security policy, the very one the course teaches you not to weaken.
- Accessibility: skip link, menu states announced, native FAQ, visible focus, decorations hidden from screen readers, animations switched off if the system asks.
- Responsive checked at 390, 768, 1440 and 2560 px, with no horizontal overflow — the original had 9 px of it at 768 px.
What isn't perfect
Better said here than left for you to find out.
- One flaw in the original has been fixed, not reproduced. Its logo marquee jumped back from −1169 px to −10 px while the pattern measures 1320 px: a 140 px jump on every lap. Here the loop covers exactly one pattern width, measured on load, at the same speed of 59 px/s. It's the only deliberate departure.
- The page is 1.6% taller than the reference. A few sections breathe a little more. Nothing overlaps.
- The links point to anchors on this page. The original is a multi-page site; here everything leads back to an existing section rather than to a 404.
- The six partner logos are placeholders drawn for this template. To be replaced with real logos.
- The photos come from the original template. The code is yours; for the visuals, check the licence or replace them. The fonts themselves are free to redistribute.
It's waiting for you in the library.
Lunaris comes with the subscription, alongside the other two templates, the sixteen components and the full course.
Immediate access · No commitment · Cancel in one click