* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: #f4f4f0;
font-family: Inter, sans-serif;
font-size: 16px;
}
.tabs-demo {
width: 100%;
max-width: 1020px;
padding: 0 clamp(2rem, 8vw, 5rem);
}
.tabs {
display: flex;
justify-content: center;
gap: 12px;
margin-bottom: 32px;
flex-wrap: wrap;
}
.tab {
border: none;
padding: 10px 16px;
border-radius: 999px;
font-size: 16px;
font-weight: 500;
letter-spacing: 0.02em;
color: #000;
cursor: pointer;
background: rgba(0,0,0,0.08);
transition: all 0.25s cubic-bezier(0.256, 0.009, 0.125, 0.997);
}
.tab&:hover {
background: rgba(0,0,0,0.16);
}
.tab.active {
background: #111;
color: #fff;
}
.content-wrapper {
position: relative;
display: grid;
grid-template-columns: 1fr;
}
.role-content {
grid-column: 1;
grid-row: 1;
text-align: center;
font-size: clamp(2rem, 3vw, 3rem);
font-weight: 600;
line-height: 1.15;
letter-spacing: -0.03em;
color: #000;
}
/* SplitText mask */
.himaaax-split-line {
overflow: hidden;
display: block;
}
gsap.registerPlugin(SplitText);
const TAB_CONTENT = [
{
id: "teams",
label: "Teams",
text: "Work that moves at the speed of trust. Shared language, aligned direction, and a process that makes collaboration feel genuinely effortless."
},
{
id: "founders",
label: "Founders",
text: "Turn early conviction into something people actually want. From rough idea to refined product — without losing what made it compelling."
},
{
id: "designers",
label: "Designers",
text: "Craft interfaces that speak before a single word is read. Visual systems built to carry meaning across every touchpoint of a product."
},
{
id: "engineers",
label: "Engineers",
text: "Build with precision on a foundation that scales. Architecture decisions that outlast the brief and hold up under real-world pressure."
}
];
const DURATION = 0.4;
const STAGGER = 0.06;
const OVERLAP = "<0.24";
const Y_OFFSET = 150;
const tabsEl = document.getElementById("tabs");
const wrapper = document.getElementById("contentWrapper");
let activeIndex = 0;
let isAnimating = false;
let queuedIndex = null;
let tl = null;
TAB_CONTENT.forEach((item, i) => {
const btn = document.createElement("button");
btn.className = "tab" + (i === 0 ? " active" : "");
btn.textContent = item.label;
tabsEl.appendChild(btn);
const panel = document.createElement("div");
panel.className = "role-content";
panel.textContent = item.text;
wrapper.appendChild(panel);
});
const panels = [...document.querySelectorAll(".role-content")];
const splits = panels.map((el, i) => {
return SplitText.create(el, {
type: "lines",
mask: "lines",
linesClass: "himaaax-split-line",
autoSplit: true,
onSplit(self) {
gsap.set(el, { opacity: 1 });
.......................................
÷ºÎÆÄÀÏÈ®ÀÎ
.......................................
document.querySelectorAll(".tab").forEach((btn, i) => {
btn.addEventListener("click", () => switchTab(i));
});