Your complete reference for making layouts work on phones, tablets, laptops, and desktop iMacs. Everything here is designed so you can change your whole site's look in one place — no code editing needed.
1. Page Shells
Layout Containers
Sections and containers manage vertical flow and width on the page. Use opero-section to add generous top and bottom spacing between major page blocks so each chapter of the page has room to breathe. Use opero-container to keep the content centered and prevent text or grids from stretching too wide on large monitors.
Container Width Comparison
.opero-container--sm
.opero-container
.opero-container--lg
<!-- Major section with vertical rhythm -->
<section class="opero-section">
<div class="opero-container">
<h1 class="opero-display">Section Title</h1>
<p>Your content here stays at a comfortable reading width.</p>
</div>
</section>
<!-- Narrow container for focused content -->
<section class="opero-section">
<div class="opero-container opero-container--sm">
<h2>Focused Story</h2>
<p>This container is narrower, so long paragraphs are easier to read.</p>
</div>
</section>
<!-- Wide container for gallery grids -->
<section class="opero-section">
<div class="opero-container opero-container--lg">
<div class="opero-grid gap-6">
<article class="opero-card span-12 md:span-6 lg:span-4">...</article>
<article class="opero-card span-12 md:span-6 lg:span-4">...</article>
<article class="opero-card span-12 md:span-6 lg:span-4">...</article>
</div>
</div>
</section>
Class
Max Width
Best For
.opero-container--sm
860px
Reading-focused pages (Bio, Statement)
.opero-container
1280px
Standard pages (Gallery, CV)
.opero-container--lg
1480px
Wide editorial layouts
.opero-container--full
100% viewport
Edge-to-edge immersive views
Glass Box Cards
Cards are how you break up content into digestible chunks. The regular opero-card is a simple container with subtle shadow. The opero-spotlight card has a blurred background behind it, making it pop off the page. Use spotlight cards for featured work, highlighted testimonials, or anything you want to emphasize.
Regular Card
Clean container with consistent spacing. Use for portfolios, service descriptions, or any grouped content.
Spotlight Card
Blurred background draws attention. Perfect for featured work, testimonials, or call-outs you want to emphasize.
<!-- Simple card -->
<article class="opero-card p-6">
<h3>Project Title</h3>
<p>Description of your work.</p>
</article>
<!-- Spotlight card with background blur -->
<article class="opero-spotlight p-6">
<h3>Featured Testimonial</h3>
<p>"Your work changed how I see design."</p>
<p class="opero-muted">— Client Name</p>
</article>
Component
Styling
Best For
.opero-card
White background, subtle shadow
Work portfolios, testimonials, content blocks
.opero-spotlight
Blurred background, elevated shadow
Featured work, highlight quotes, calls-to-action
Marketing Heroes
The foundation for every hero section and header on the page. Combine a kicker, a display heading, and a lead paragraph to form the top-of-page introduction. This three-layer hierarchy works for portfolio landing pages, exhibition introductions, and section openers.
Featured Exhibition
Translucence & Light
A year-long exploration of how layered materials create new visual languages when light passes through them. Featuring glass, resin, and cast acrylic works from the past decade.
<section class="opero-section">
<div class="opero-container">
<p class="opero-kicker">Highlighted Project</p>
<h1 class="opero-display">Your Hero Title</h1>
<p class="opero-lead">Your introductory paragraph explaining the context, mood, or story of this section.</p>
</div>
</section>
Component
Purpose
Scales Responsively
.opero-kicker
Eyebrow label above the heading
Yes
.opero-display
Hero heading that carries the main message
Yes
.opero-lead
Subtitle or introduction paragraph
Yes
2. Grids & Structure
The Armature Grid
The grid system is explicit: opero-grid creates a 12-lane parent and each child uses span-* classes to declare its width. Combine responsive spans like span-12 md:span-6 lg:span-3 to reshape the same layout across devices.
Opero supports four screen sizes so your portfolio adapts from phones to large desktop monitors. sm is for large phones, md is for tablets, lg is for laptops, and xl is for desktop monitors. Use span prefixes like span-12 md:span-6 lg:span-3 xl:span-2 to reshape the same grid as the screen grows.
Item
Item
Item
Item
md: activates at 768 px · lg: activates at 1024 px
All the gaps, padding, and margins on your site follow one simple system. Change the spacing scale in the admin panel once, and every card, section, and gap updates instantly across your entire portfolio. Use classes like p-4 for interior padding, mb-6 for breathing room underneath a block, and gap-4 for consistent space between grid items.
Hover over the boxes to see padding and margin space
Masonry layout flows items into columns like a magazine layout. Taller items sit lower than short ones, filling space efficiently. Add filter buttons if you want visitors to click a category and narrow the view without leaving the page.
Registers container with the JS filter engine observer
data-category="value"
Each item
Declares item category; comma-separated for multi-category items
data-armature-filter="*"
Filter button
Wildcard — shows all items and resets active state
data-armature-filter="slug"
Filter button
Shows only items whose data-category includes this slug
aria-pressed
Filter button
Managed automatically by armature.js for screen reader state
Visibility Forms
Show and hide elements at different screen sizes when a page needs a simpler mobile version or a richer desktop version. Hide something on all screens with d-none, then bring it back at a breakpoint like md:d-block when there is enough room.
Hidden on small screens · visible from md (768 px) upward
Always visible — no display modifier applied.
<!-- Show only at md and wider -->
<div class="d-none md:d-block">Visible from 768 px upward</div>
<!-- Show as flex only at lg and wider -->
<div class="d-none lg:d-flex">Visible from 1024 px upward as flex</div>
<!-- Hide at md and wider (mobile-only element) -->
<div class="md:d-none">Hidden from 768 px upward</div>
Class
CSS Output
Effective Range
d-none
display: none !important
All breakpoints
d-block
display: block !important
All breakpoints
d-flex
display: flex !important
All breakpoints
d-grid
display: grid !important
All breakpoints
md:d-none
display: none !important
768 px and wider
md:d-block
display: block !important
768 px and wider
lg:d-none
display: none !important
1024 px and wider
lg:d-flex
display: flex !important
1024 px and wider
3. Placing Content
Aspect Ratios & Fit
Aspect-ratio wrappers help your images mount cleanly inside the grid, even when the source files all have different dimensions. Pair them with object-cover when you want the frame filled, or object-contain when you want the full image visible.
square
video
portrait
landscape
golden
object-cover
object-contain
<!-- Aspect ratio containers — wrap the media element -->
<div class="aspect-square"><img src="..." class="object-cover" /></div>
<div class="aspect-video"><img src="..." class="object-cover" /></div>
<div class="aspect-portrait"><img src="..." class="object-cover" /></div>
<div class="aspect-landscape"><img src="..." class="object-cover" /></div>
<div class="aspect-golden"><img src="..." class="object-cover" /></div>
<!-- Object-fit applied directly to the media element -->
<img class="object-cover w-full h-full" src="..." alt="..." />
<img class="object-contain w-full h-full" src="..." alt="..." />
Class
aspect-ratio Value
Ideal Usage
aspect-square
1 / 1
Avatar thumbnails, grid tile icons
aspect-video
16 / 9
Video embeds, cinematic stills
aspect-portrait
3 / 4
Work detail images, artist headshots
aspect-landscape
4 / 3
Exhibition photography, studio shots
aspect-golden
1.618 / 1
Curated editorial feature panels
object-cover
object-fit: cover
Fill frame completely; crops to fit
object-contain
object-fit: contain
Show the entire image; letterboxes if needed
Magazine Typography
Armature gives you a ready-made hierarchy for headlines, intros, and editorial text. Use opero-display for the main statement, opero-lead for the opening paragraph, and drop caps or columns when you want a more magazine-like reading experience.
Kicker label — above the heading
Display Heading
This is an opero-lead paragraph. It uses a slightly larger font size and softer color to serve as a subtitle or introduction before body text begins.
Armature editorial columns let you flow long-form artist statements, biographical text, or press content into responsive two-column layouts without custom CSS. The drop cap anchors the first paragraph with editorial gravity and signals the start of a new section.
Subsequent paragraphs flow naturally in the column layout. Line height, measure, and rhythm are calibrated for comfortable reading at typical body sizes on screen.
Muted text for secondary metadata and auxiliary information.
Caption text for image labels, dates, and provenance notes.
<p class="opero-kicker">Section label</p>
<h1 class="opero-display">Display Heading</h1>
<p class="opero-lead">Introductory lead paragraph.</p>
<div class="md:columns-2">
<p class="opero-drop-cap">First paragraph with drop cap anchor...</p>
<p>Continuation flowing in column layout...</p>
</div>
<p class="opero-muted">Secondary metadata text.</p>
<p class="opero-caption">Image caption or provenance note.</p>
<!-- Rich text container for rendered Markdown output -->
<div class="opero-richtext">
<h2>...</h2><p>...</p><blockquote>...</blockquote>
</div>
Class
Font Token
Usage
.opero-display
--opero-font-display
Hero headings, section titles, editorial anchors
.opero-kicker
--opero-font-body
Category labels appearing above headings
.opero-lead
--opero-font-body
Subtitle or intro paragraph below a heading
.opero-muted
--opero-font-body
Secondary metadata, auxiliary copy
.opero-caption
--opero-font-body
Image captions, provenance notes, dates
.opero-drop-cap
--opero-font-display
First paragraph of editorial blocks; large initial letter
.md:columns-2
—
Two-column CSS flow for long-form text at ≥768 px
.opero-richtext
both tokens
Container for rendered Markdown or HTML content blocks
Timeline Lists
Auto-numbered lists are useful when the content has a sequence: a career timeline, a studio process, or the stages of an exhibition. Each item gets its number automatically and stays in order if you add or remove a step.
First milestone
Timeline lists auto-number starting from 01. Perfect for career arcs or step-by-step processes.
Second milestone
Each item is its own card with subtle styling and spacing rhythm built in.
Third milestone
The glass-frosted background adapts to your surface color from the design settings.
<div class="opero-list-group">
<div class="opero-list-item">
<h3>1987 – Born in Florence</h3>
<p>Childhood years spent in Italian hill towns.</p>
</div>
<div class="opero-list-item">
<h3>2010 – BFA from RISD</h3>
<p>Focus on sculpture and spatial design.</p>
</div>
<div class="opero-list-item">
<h3>2015 – First solo show</h3>
<p>Brooklyn gallery, featuring site-specific installations.</p>
</div>
</div>
Component
Element(s)
Purpose
.opero-list-group
Container
Wrapper that manages list spacing and counter styles
.opero-list-item
Item (repeats)
Individual timeline card with auto-numbering and glass background
counter(opero-step, decimal-leading-zero)
Pseudo-element
Displays 01, 02, 03 automatically as items are added
4. Interactive Details
Interactive Buttons
Buttons signal where the visitor should click next. The base opero-button is neutral. Add opero-button--primary when the action should stand out most, and opero-button--primary-alt when you want a softer secondary action.
<button class="opero-button">Default</button>
<button class="opero-button opero-button--primary">Primary action</button>
<button class="opero-button opero-button--primary-alt">Secondary option</button>
<!-- Links that look like buttons -->
<a href="/work" class="opero-button opero-button--primary">View My Work</a>
<a href="/about" class="opero-button opero-button--primary-alt">About Me</a>
Class
Appearance
When to Use
.opero-button
Neutral surface button
Secondary actions, navigation options
.opero-button--primary
Your brand color, bold presence
Main call-to-action
.opero-button--primary-alt
Soft brand color with light background
Supporting actions
Token Definitions
One place controls your entire visual identity. Change your primary color in the admin panel, and it updates every button, link, card, and decoration across your whole site instantly. If you want a one-off override, you can also use tokens directly inline on a single element.
--opero-primary
--opero-secondary
--opero-accent
--opero-background
--opero-surface
--opero-text
bg-surface
bg-alt
<div style="background: var(--opero-primary)">Primary</div>
<div style="color: var(--opero-text-soft)">Soft copy</div>
<div style="color: var(--opero-text-muted)">Muted copy</div>
<div style="background: var(--opero-primary); color: white; padding: 1rem; border-radius: 1rem;">Single element override</div>
Token
Source Key (admin config)
Usage
--opero-primary
visual.primaryColor
Brand identity, buttons, active states
--opero-secondary
visual.secondaryColor
Gradients, hover states, accents
--opero-accent
visual.accentColor
Highlights, focus rings, chips
--opero-background
visual.backgroundColor
Page canvas behind all content
--opero-surface
visual.surfaceColor
Cards, panels, modals sitting on canvas
--opero-text
visual.textColor
Primary reading text
--opero-text-soft
derived
Secondary copy, subheadings
--opero-text-muted
derived
Captions, metadata, placeholders
--opero-font-body
visual.bodyFontFamily
Paragraphs, UI labels, controls
--opero-font-display
visual.headingFontFamily
Headings, hero titles, display text
--opero-btn-radius
visual.buttonRadius
Border-radius applied to all buttons
--opero-panel-radius
visual.panelRadius
Card and panel corner radius
--opero-input-radius
visual.inputRadius
Form input corner radius
--opero-shadow-base
visual.shadowIntensity
Default component shadow
--opero-shadow-hover
visual.shadowIntensity
Elevated shadow on hover/focus
Fullscreen Lightbox
The Armature lightbox intercepts clicks on any <a> tagged with data-armature="lightbox" and opens a fullscreen cinematic overlay instead of leaving the page. All registered links in the page are collected into a sequence so visitors can move through the work one image at a time.
Cursor zones: ← left half = previous · right half = next → · Esc = close
Registers link as a lightbox trigger; prevents default navigation
href
<a>
Full-resolution image URL shown inside the overlay
data-src
<a>
Alternative image URL; fallback chain: data-src → href
data-caption
<a>
Caption text displayed below the image in the overlay
alt
<img> inside link
Fallback caption text when data-caption is absent
Magnetic Interaction
Hover over a magnetic button and your cursor pulls it slightly toward the center of the button. It is a premium micro-interaction that makes the page feel responsive and alive without changing the structure of the layout.
Activates cursor-follow translate transform on mousemove
Proximity zone
Automatic
1.4× the element's largest dimension
Max displacement
Automatic
Capped at ±10 px in both axes
Reset
Automatic on mouseleave
transform returns to translate(0, 0)
Easing
CSS transition
180 ms ease
Grid Filtering
Armature's filtering engine connects filter buttons to any data-armature-filterable container. Each button declares a category with data-armature-filter, and each item declares its categories with data-category. When a filter activates, non-matching items fade out and leave the layout.
Shows only items where data-category includes this slug
aria-pressed
Button
Managed automatically by armature.js for accessibility
data-armature-filterable
Container
Opts the container into filter engine observation
data-category="a, b"
Item
Comma-separated list of categories; item matches any in the list
Scroll Reveals
As visitors scroll down, cards and sections fade in and float up smoothly. By default everything appears at once, but you can stagger the reveals so cards come in one after another for a more dramatic entrance.
Reveal 01Reveal 02Reveal 03
<!-- Base reveal: triggers when 18% of element enters viewport -->
<article class="opero-reveal">...</article>
<!-- Staggered reveal sequence with incremental delays -->
<article class="opero-reveal" data-armature-delay="0ms">First</article>
<article class="opero-reveal" data-armature-delay="120ms">Second</article>
<article class="opero-reveal" data-armature-delay="240ms">Third</article>
Class / Attribute
Element
Function
.opero-reveal
Any element
Sets initial state: opacity 0 + translateY(40px); registers with observer
.is-revealed
Added by JS
Triggers transition to opacity 1 + translateY(0)
data-armature-delay="Xms"
Reveal element
Sets transition-delay for staggered entrance sequences
Threshold
Automatic
18% of element must enter viewport before revealing
Root margin
Automatic
−6% bottom offset — triggers slightly before element reaches bottom edge
Fallback
Automatic
All elements revealed immediately if IntersectionObserver unavailable