v1.0 — March 2026

SageFlow

Built by Sazzad Hossain — because good design deserves good defaults. Grab the tokens, steal the components, copy-paste the markup. No build tools. No drama. Just drop in the CSS & JS and ship something beautiful.

Stack: Vanilla HTML · CSS Custom Properties · IBM Plex Mono · Funnel Display · Inter · Lucide Icons

Getting Started

Download the two standalone files and add them to your project. No build tools, no dependencies — just HTML, CSS, and vanilla JS.


1 — Add to your <head>

<!-- Google Fonts (required) -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link href="https://fonts.googleapis.com/css2?family=Funnel+Display:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;600&display=swap" rel="stylesheet" />

<!-- SageFlow CSS -->
<link rel="stylesheet" href="sageflow/sageflow.css" />

2 — Add before </body>

<!-- Lucide Icons (optional, for icon support) -->
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>

<!-- SageFlow JS -->
<script src="sageflow/sageflow.js"></script>

<!-- Init Lucide icons -->
<script>lucide.createIcons();</script>

3 — Dark mode toggle

<!-- Add data-sf-dark-toggle to any button -->
<button data-sf-dark-toggle aria-pressed="false">Toggle Dark Mode</button>

<!-- Or call programmatically -->
<script>SageFlow.toggleDark();</script>

Design Tokens

All values live as CSS custom properties on :root. Dark mode overrides are applied via [data-theme="dark"] on <html>.


Primary & Accent

--color-primary #7A9E8A · Sage Green
--color-accent #EDD9A3 · Warm Gold
--color-secondary #ffb347 · Orange
--color-tertiary #a8e6cf · Mint

Backgrounds (Light Mode)

--color-bg-primary #FAF7F6
--color-bg-secondary #f5f5f0
--color-surface #ffffff
--color-border #e5e5e5

Text

--color-text-primary #2c2c2c
--color-text-secondary #6b6b6b
--color-dark #000000

Dark Mode Tokens

--color-bg-primary #0e1a14
--color-surface #1a3a2d
--color-primary (dark) #8FB4A0
--color-border (dark) #274035
/* In assets/css/main.css */
:root {
  --color-primary:        #7A9E8A;
  --color-accent:         #EDD9A3;
  --color-bg-primary:     #FAF7F6;
  --color-surface:        #ffffff;
  --color-border:         #e5e5e5;
  --color-text-primary:   #2c2c2c;
  --color-text-secondary: #6b6b6b;
  --color-dark:           #000000;

  --font-display: "Funnel Display", sans-serif;
  --font-body:    "Inter", -apple-system, sans-serif;
  --font-mono:    "IBM Plex Mono", monospace;
}

[data-theme="dark"] {
  --color-primary:        #8FB4A0;
  --color-bg-primary:     #0e1a14;
  --color-surface:        #1a3a2d;
  --color-border:         #274035;
  --color-text-primary:   #e8e8e8;
  --color-text-secondary: #9db8ab;
}

Heading Scale

Six semantic heading classes mapping to h1h6. Apply as classes on any element.


sf-h1 Display Heading
sf-h2 Section Heading
sf-h3 Subsection Heading
sf-h4 Card Title
sf-h5 Small Title
sf-h6 Label Heading
<h1 class="sf-h1">Display Heading</h1>
<h2 class="sf-h2">Section Heading</h2>
<h3 class="sf-h3">Subsection Heading</h3>
<h4 class="sf-h4">Card Title</h4>
<h5 class="sf-h5">Small Title</h5>
<h6 class="sf-h6">Label Heading</h6>

<!-- Blockquote -->
<blockquote class="sf-blockquote">
    Design is not just what it looks like — it's how it works.
    <cite>Steve Jobs</cite>
</blockquote>

<!-- Inline code -->
Use the <code class="sf-code">sf-btn</code> class to style buttons.

Typography

Three typefaces with clear roles. Funnel Display for everything structural, Inter for reading, IBM Plex Mono for labels and metadata.


.display-1 Funnel Display · clamp(42px→130px) · 600
Design
.display-2 Funnel Display · clamp(34px→100px) · 600
Experiences
.heading-1 Funnel Display · clamp(28px→58px) · 700

Selected Work

h3 / card title Funnel Display · clamp(18px→24px) · 600

BeeBack AR Platform

.section-label IBM Plex Mono · 13px · 600 · uppercase
.body-large Inter · clamp(16px→20px) · 500

15+ years designing digital products — from research and wireframes to shipped code.

body / p Inter · 16–18px · 400 · line-height 1.75–1.8

Regular body copy for paragraphs, descriptions, and longer reading content.

mono / meta IBM Plex Mono · 11–13px · uppercase
EdTech · 2015–2024

Spacing & Layout

Three container widths, consistent section padding, and a predictable grid system.


/* Containers */
.container    { max-width: 1430px; margin: 0 auto; padding: 0 40px; }
.container-xl { max-width: 1750px; margin: 0 auto; padding: 0 40px; }
.container-md { max-width: 968px;  margin: 0 auto; padding: 0 40px; }

/* Section padding (standard) */
section { padding: 100px 0; }

/* Pill section (sage background) */
.skills-section,
.testimonials-section {
    width: 94%;
    margin: 0 auto 80px;
    border-radius: 28px;
    padding: 100px 0;
}

/* Common grid templates */
.portfolio-grid    { grid-template-columns: repeat(2, 1fr); gap: 24px; }
.testimonials-grid { grid-template-columns: repeat(3, 1fr); gap: 20px; }
.toolbox-grid      { grid-template-columns: repeat(4, 1fr); gap: 14px; }
.skill-categories  { grid-template-columns: repeat(4, 1fr); gap: 24px; }

Buttons

Three button variants. All use pill shape, flex layout with icon slot, and consistent hover lift.


↑ Hover to see lift + border transitions

<!-- Primary: black fill → outlined on hover -->
<a href="#" class="btn btn-primary">
    <span>Get in Touch</span>
    <i data-lucide="arrow-right" class="btn-icon"></i>
</a>

<!-- Secondary: outlined → black fill on hover -->
<a href="#" class="btn btn-secondary">
    <span>View All Projects</span>
    <i data-lucide="arrow-right" class="btn-icon"></i>
</a>

Send Button (Contact form)

<!-- Send: mono font, pill, dark → sage on hover, gap animates -->
<button class="btn-send">
    <span>Send it over</span>
    <i data-lucide="arrow-right"></i>
</button>

Button Sizes & Variants

All buttons use the base .sf-btn class. Combine with a variant class and an optional size modifier.


Sizes

<button class="sf-btn sf-btn-primary sf-btn-sm">Small</button>
<button class="sf-btn sf-btn-primary">Default</button>
<button class="sf-btn sf-btn-primary sf-btn-lg">Large</button>
<button class="sf-btn sf-btn-primary sf-btn-xl">XL</button>

Variants

<button class="sf-btn sf-btn-primary">Primary</button>
<button class="sf-btn sf-btn-secondary">Secondary</button>
<button class="sf-btn sf-btn-sage">Sage</button>
<button class="sf-btn sf-btn-ghost">Ghost</button>
<button class="sf-btn sf-btn-danger">Danger</button>
<button class="sf-btn sf-btn-success">Success</button>

<!-- Loading state -->
<button class="sf-btn sf-btn-primary is-loading">Saving...</button>

<!-- Icon only -->
<button class="sf-btn sf-btn-secondary sf-btn-icon">
    <i data-lucide="arrow-right"></i>
</button>

Badges & Labels

Used to communicate skill level, availability, section context, and metadata.


Section Label

<p class="section-label">Portfolio</p>
/* IBM Plex Mono · 13px · uppercase · letter-spacing 2–3px · color: primary */

Tool Level Badges

Expert Proficient Familiar
<span class="tool-level tool-level--expert">Expert</span>
<span class="tool-level tool-level--proficient">Proficient</span>
<span class="tool-level tool-level--familiar">Familiar</span>

Availability Dot

Available for new roles
<div class="hero-availability">
    <span class="avail-dot"></span>
    Available for new roles
</div>
/* Green dot · 8px · pulsing box-shadow animation */

Footer Availability Status

Tags & Chips

Compact labels for categories, status, and metadata. Six color variants plus a removable chip pattern.


Default Sage Gold Green Red Blue
Design Systems UX Research
<span class="sf-tag sf-tag-default">Default</span>
<span class="sf-tag sf-tag-sage">Sage</span>
<span class="sf-tag sf-tag-gold">Gold</span>
<span class="sf-tag sf-tag-green">Green</span>
<span class="sf-tag sf-tag-red">Red</span>
<span class="sf-tag sf-tag-blue">Blue</span>

<!-- Removable chip -->
<span class="sf-tag sf-tag-sage">
    Design Systems
    <button class="sf-tag-remove"><i data-lucide="x"></i></button>
</span>

<!-- Tag list -->
<div class="sf-tag-list">
    <span class="sf-tag sf-tag-sage">UX</span>
    <span class="sf-tag sf-tag-default">Research</span>
</div>

Avatar

Five sizes, image or initials fallback, optional ring, and an overlapping group layout.


SH
SH
SH
SH
SH

XS · SM · MD · LG · XL — with ring on hover

<!-- With image -->
<div class="sf-avatar sf-avatar-lg">
    <img src="photo.jpg" alt="Sazzad Hossain" />
</div>

<!-- Initials fallback -->
<div class="sf-avatar sf-avatar-lg">SH</div>

<!-- Ring -->
<div class="sf-avatar sf-avatar--ring">SH</div>

<!-- Group (overlapping) -->
<div class="sf-avatar-group">
    <div class="sf-avatar sf-avatar-sm">AB</div>
    <div class="sf-avatar sf-avatar-sm">CD</div>
    <div class="sf-avatar sf-avatar-sm">EF</div>
</div>

<!-- Sizes: sf-avatar-xs / sm / (default) / lg / xl -->

Table

Fully styled data table with header, hover rows, optional stripes, and a compact mode. Wraps in .sf-table-wrap for overflow handling.


Name Role Status Projects
Sazzad Hossain Product Designer Active 24
Jane Smith UX Researcher Away 11
Alex Lee Frontend Dev Offline 8
<div class="sf-table-wrap">
    <table class="sf-table">
        <thead>
            <tr>
                <th>Name</th>
                <th>Role</th>
                <th class="text-right">Projects</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Sazzad Hossain</td>
                <td>Product Designer</td>
                <td class="text-right">24</td>
            </tr>
        </tbody>
    </table>
</div>

<!-- Striped -->
<table class="sf-table sf-table--striped">...</table>

<!-- Compact -->
<table class="sf-table sf-table--compact">...</table>

Cards

All cards share: surface background, 1px border, 20–24px radius, and a lift + left sage accent on hover.


Portfolio Item Card

↑ Hover to see lift + inset left sage accent

<a href="case-studies/project.html" class="portfolio-item fade-in">
    <div class="portfolio-image">
        <img src="assets/images/case-study/project/cover.png" alt="Project Name">
    </div>
    <div class="portfolio-info">
        <div class="portfolio-meta">
            <span>Category</span>
            <span>Year</span>
        </div>
        <div class="portfolio-item-title-row">
            <h3 class="portfolio-title">Project Title</h3>
            <i data-lucide="arrow-right" class="portfolio-arrow"></i>
        </div>
    </div>
</a>

Toolbox Item Card

Figma Expert
HTML / CSS Expert
JavaScript Proficient
Framer Familiar
<div class="toolbox-grid">
    <div class="tool-item">
        <div class="tool-icon">
            <!-- 40×40 SVG or Lucide icon -->
        </div>
        <div class="tool-info">
            <span class="tool-name">Figma</span>
            <span class="tool-level tool-level--expert">Expert</span>
        </div>
    </div>
</div>
/* Level modifiers: tool-level--expert | tool-level--proficient | tool-level--familiar */

Testimonial Card

"Sazzad is one of the most versatile UX designers I have ever worked with. His knowledge spans front-end engineering, growth, marketing, and more."

Read full story →
Diego Ballona Senior Engineering Manager, Spotify

"His passionate commitment to understanding the needs of the end-user is simply UNRIVALED, and it shows in the consistency of organic, scalable UIUX practices."

Read full story →
Jas Gil Engineering Project Manager, Apple

"His designs are comprehensive and well thought out. Sazzad effectively bridges the gap between user requirements and code."

Read full story →
Rob Mitola Engineering Lead, Top Hat

↑ Sage background (#E4F0EA) is the section background, not the card

<div class="t-card fade-in">
    <p class="t-quote">"Visible excerpt shown on card..."</p>
    <span class="t-read-hint">Read full story →</span>
    <p class="t-full-quote" hidden>"Full text opened in modal..."</p>
    <div class="t-author">
        <img src="..." alt="Name" class="t-avatar">
        <div class="t-author-info">
            <strong>Full Name</strong>
            <span>Title, Company</span>
        </div>
    </div>
</div>

Contact / Info Card

Location

City

New York City, NY

Remote

Open to fully remote

<div class="contact-card">
    <h3>Card Heading</h3>
    <div class="contact-item">
        <strong>Label</strong>
        <p>Value or content</p>
    </div>
</div>

Skill Category Card

Product Design

  • UX/UI Design
  • User Research
  • Prototyping
  • Design Systems

Development

  • HTML & CSS
  • JavaScript
  • Responsive Design
  • Accessibility
<div class="skill-category fade-in">
    <div class="skill-category-icon">
        <i data-lucide="layout-template"></i>
    </div>
    <h3>Category Name</h3>
    <ul>
        <li>Skill One</li>
        <li>Skill Two</li>
    </ul>
</div>

Accordion

Collapsible panels driven by the is-open class. Toggle with SageFlow JS or your own handler.


SageFlow is a sage-green design system built with pure CSS and vanilla JS — no dependencies required.
<div class="sf-accordion">
    <div class="sf-accordion-item is-open">
        <button class="sf-accordion-trigger">
            What is SageFlow?
            <i data-lucide="chevron-down" class="sf-accordion-icon"></i>
        </button>
        <div class="sf-accordion-body">
            <div class="sf-accordion-content">
                SageFlow is a sage-green design system...
            </div>
        </div>
    </div>
    <div class="sf-accordion-item">...</div>
</div>

Tabs

Underline tabs and pill-style tabs. Panel visibility toggled with is-active class via SageFlow JS.


Underline tabs

Tab panel content appears here when a tab is active.

Pill tabs

<!-- Underline tabs -->
<div class="sf-tabs" data-sf-tabs>
    <div class="sf-tabs-list">
        <button class="sf-tab-btn is-active" data-sf-tab="overview">Overview</button>
        <button class="sf-tab-btn" data-sf-tab="process">Process</button>
    </div>
    <div class="sf-tab-panel is-active" data-sf-panel="overview">...</div>
    <div class="sf-tab-panel" data-sf-panel="process">...</div>
</div>

<!-- Pill tabs -->
<div class="sf-tabs sf-tabs--pills" data-sf-tabs>
    <div class="sf-tabs-list">
        <button class="sf-tab-btn is-active" data-sf-tab="all">All</button>
        <button class="sf-tab-btn" data-sf-tab="ux">UX</button>
    </div>
    ...
</div>

Form Elements

Standard input, select, textarea, checkbox, radio, toggle, and range. All support dark mode and validation states.


Input

We'll never share your email.

This field is required.

Select, Textarea, Toggle, Range

<!-- Text input -->
<div class="sf-form-group">
    <label class="sf-label">Full Name</label>
    <input type="text" class="sf-input" placeholder="Sazzad Hossain" />
    <p class="sf-field-helper">Helper text here.</p>
</div>

<!-- Error state -->
<input type="text" class="sf-input sf-input--error" />
<p class="sf-field-error">This field is required.</p>

<!-- Select -->
<select class="sf-select"><option>Option A</option></select>

<!-- Textarea -->
<textarea class="sf-textarea-field" rows="4"></textarea>

<!-- Checkbox -->
<label class="sf-check-label">
    <input type="checkbox" class="sf-check" /> Agree to terms
</label>

<!-- Radio -->
<label class="sf-radio-label">
    <input type="radio" class="sf-radio" name="group" /> Option A
</label>

<!-- Toggle -->
<label class="sf-toggle-label">
    <input type="checkbox" class="sf-toggle" /> Enable notifications
</label>

<!-- Range -->
<input type="range" class="sf-range" min="0" max="100" value="65" />

Form Elements

The contact form uses a conversational fill-in-the-blank pattern. Inline inputs are underline-only; the message field is a standard bordered textarea.


Inline Input (sentence-style)

Hi, I'm
and I'd love to talk about
<div class="form-sentence">
    <div class="form-line">
        <span class="form-text">Hi, I'm</span>
        <div class="inline-field-wrap">
            <input type="text" name="name" placeholder="your name"
                   class="inline-input" required>
        </div>
    </div>
</div>
/* .inline-input: no border except bottom underline in --color-primary
   focus: --color-secondary underline */

Textarea

<textarea class="form-message" rows="4" name="message" required
          placeholder="Here's a bit more context..."></textarea>
/* bg: --color-bg-primary · border: --color-border · border-radius: 12px
   focus: border → primary · box-shadow: 0 0 0 3px rgba(primary, 0.12) */

Social Link Row

<div class="social-links-list">
    <a href="#" class="social-link">
        <i data-lucide="linkedin"></i>
        <span>LinkedIn</span>
        <i class="link-arrow" data-lucide="arrow-right"></i>
    </a>
</div>
/* hover: bg sage tint · border → primary · padding-left animates
   .link-arrow slides in from left on hover */

Pagination

Page navigation with active, hover, and disabled states. Works as links or buttons.


<nav>
    <ul class="sf-pagination">
        <li class="is-disabled"><a href="#"><i data-lucide="chevron-left"></i></a></li>
        <li><a href="#">1</a></li>
        <li class="is-active"><a href="#">2</a></li>
        <li><a href="#">3</a></li>
        <li><a href="#">…</a></li>
        <li><a href="#">8</a></li>
        <li><a href="#"><i data-lucide="chevron-right"></i></a></li>
    </ul>
</nav>

Alerts & Callouts

Five semantic variants: info, success, warning, error, and sage. Add an icon and optional dismiss button.


InfoYour session expires in 30 minutes.
SuccessYour changes have been saved.
WarningThis action cannot be undone.
ErrorSomething went wrong. Please try again.
SageA neutral callout using the brand color.
<div class="sf-alert sf-alert-info">
    <span class="sf-alert-icon"><i data-lucide="info"></i></span>
    <div>
        <span class="sf-alert-title">Info</span>
        <span class="sf-alert-body">Your session expires in 30 minutes.</span>
    </div>
    <button class="sf-alert-close"><i data-lucide="x"></i></button>
</div>

<!-- Variants: sf-alert-info / success / warning / error / sage -->

Progress Bar

Linear progress bars in three sizes and five color variants. Optional striped animation.


Proficiency 85%
<!-- With label -->
<div class="sf-progress-header">
    <span class="sf-progress-label">Proficiency</span>
    <span class="sf-progress-value">85%</span>
</div>
<div class="sf-progress">
    <div class="sf-progress-bar" style="width: 85%"></div>
</div>

<!-- Color variants -->
<div class="sf-progress-bar sf-progress-bar--success" style="width:60%"></div>
<div class="sf-progress-bar sf-progress-bar--warning" style="width:40%"></div>
<div class="sf-progress-bar sf-progress-bar--error"   style="width:25%"></div>

<!-- Sizes: sf-progress-sm / (default) / sf-progress-lg -->

<!-- Striped animated -->
<div class="sf-progress">
    <div class="sf-progress-bar sf-progress-bar--striped" style="width:65%"></div>
</div>

Spinner & Skeleton

Loading spinner in three sizes and a shimmer skeleton for content placeholders.


Spinners

Skeleton Loaders

<!-- Spinner -->
<div class="sf-spinner"></div>
<div class="sf-spinner sf-spinner-sm"></div>
<div class="sf-spinner sf-spinner-lg"></div>

<!-- Skeleton lines -->
<div class="sf-skeleton sf-skeleton-line"></div>
<div class="sf-skeleton sf-skeleton-line sf-skeleton-line--short"></div>

<!-- Skeleton circle -->
<div class="sf-skeleton sf-skeleton-circle"></div>

<!-- Skeleton image block -->
<div class="sf-skeleton sf-skeleton-block"></div>

Stats Strip

Full-width strip with animated counter numbers. Counters increment from 0 to target on scroll using Intersection Observer.


15+
Years Experience
3M+
Users Reached
2
US Patents
8K+
Institutions Served
<section class="stats-section">
    <div class="container">
        <div class="stats-strip">
            <div class="stat-item fade-in">
                <div class="stat-number" data-target="15" data-suffix="+">15+</div>
                <div class="stat-label">Years Experience</div>
            </div>
            <div class="stat-divider" aria-hidden="true"></div>
            <!-- repeat for each stat -->
        </div>
    </div>
</section>
/* Counter animation driven by data-target + data-suffix in main.js */

Section Structure

Two section treatments: standard (plain background) and pill (sage green, 94% width, rounded).


Standard Section

<section id="work" class="portfolio-section">
    <div class="container">
        <div class="portfolio-header">
            <div class="fade-in">
                <p class="section-label">Portfolio</p>
                <h2 class="heading-1">Selected<br />Work</h2>
            </div>
            <a href="portfolio.html" class="btn btn-secondary fade-in">
                <span>View All</span>
                <i data-lucide="arrow-right" class="btn-icon"></i>
            </a>
        </div>
        <!-- content -->
    </div>
</section>

Pill Section (sage green background)

Tools & Expertise

<section id="skills" class="skills-section">
    <div class="container">
        <div class="skills-header fade-in">
            <p class="section-label">What I Do</p>
            <h2 class="heading-1">Tools &<br />Expertise</h2>
        </div>
        <!-- content -->
    </div>
</section>
/* .skills-section / .testimonials-section:
   background: #E4F0EA · width: 94% · margin: 0 auto 80px · border-radius: 28px */

Footer

<footer class="site-footer">
    <div class="container">
        <!-- Large branding CTA -->
        <div class="footer-branding-section fade-in">
            <h2 class="footer-brand-heading">Let's Work<br />Together</h2>
            <p class="footer-brand-subtext">Short availability line.</p>
            <a href="contact.html" class="btn btn-primary footer-cta-btn">
                <span>Get in Touch</span>
                <i data-lucide="arrow-right" class="btn-icon"></i>
            </a>
        </div>

        <!-- 3-column grid -->
        <div class="footer-grid">
            <div class="footer-col footer-nav">
                <ul><li><a href="index.html">Home</a></li></ul>
            </div>
            <div class="footer-col footer-contact-col">
                <h4 class="footer-heading">Status</h4>
                <div class="footer-availability-status">
                    <span class="avail-dot"></span>
                    <span>Available for new roles</span>
                </div>
                <p class="footer-status-note">Based in NYC · Open to remote</p>
            </div>
            <div class="footer-col footer-ecosystem">
                <h4 class="footer-heading">Ecosystem</h4>
                <ul class="ecosystem-links">
                    <li><a href="#" target="_blank"><i data-lucide="linkedin"></i>LinkedIn</a></li>
                </ul>
            </div>
        </div>

        <!-- Bottom bar -->
        <div class="footer-bottom-bar">
            <div class="footer-legal"><a href="#">Privacy Policy</a></div>
            <p class="footer-credit">Sazzad Hossain © 2026</p>
            <button class="back-to-top" onclick="window.scrollTo({top:0,behavior:'smooth'})">
                <i data-lucide="arrow-up"></i>
            </button>
        </div>
    </div>
</footer>

Animations & States

All scroll reveals use .fade-in toggled by Intersection Observer. Hover patterns are consistent across all interactive surfaces.


Scroll Reveal

/* Add .fade-in to any element — JS adds .visible when it enters viewport */
.fade-in {
    opacity: 0;
    transform: translateY(15px);
    transition: opacity 1s ease-out, transform 1s ease-out;
}
.fade-in.visible {
    opacity: 1;
    transform: translateY(0);
}

/* JS in main.js */
const observer = new IntersectionObserver((entries) => {
    entries.forEach(e => {
        if (e.isIntersecting) e.target.classList.add('visible');
    });
}, { threshold: 0.1 });
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));

Hover — Card Lift + Left Accent

/* Applied consistently to: portfolio items, testimonial cards, tool items */
.card:hover {
    transform: translateY(-5px);
    box-shadow: inset 4px 0 0 var(--color-primary),
                0 20px 52px rgba(0, 0, 0, 0.08);
}

/* Arrow slide-in on portfolio items */
.portfolio-arrow {
    opacity: 0;
    transform: translateX(-6px);
    transition: opacity 0.25s ease, transform 0.25s ease;
}
.portfolio-item:hover .portfolio-arrow {
    opacity: 1;
    transform: translateX(0);
}

Availability Dot Pulse

Available for new roles
.avail-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #22c55e;
    box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.2);
    animation: pulse-dot 2.5s ease-in-out infinite;
}
@keyframes pulse-dot {
    0%, 100% { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.2); }
    50%       { box-shadow: 0 0 0 7px rgba(34, 197, 94, 0.08); }
}

Marquee Strip

Product Design UX Research Design Systems Frontend Dev Prototyping Brand Identity Product Design UX Research Design Systems Frontend Dev
<div class="hero-marquee-wrap">
    <div class="hero-marquee-inner">
        <span>Product Design</span>
        <span class="mq-sep">✦</span>
        <span>UX Research</span>
        <!-- duplicate content once for seamless loop -->
    </div>
</div>
/* animation: heroMarquee 22s linear infinite → translateX(-50%)
   Works by duplicating content so the loop is seamless */