02 · Components

Built pieces, live.

Every specimen below is a working static recreation of a shiftops.ai component, rendered from tokens.css. The code under each one is the code on this page — copy it and it works anywhere the tokens are linked.

02.1

Buttons

One filled button per view.

Primary is ink on the page — it needs no color to win because nothing competes. Secondary is bordered, ghost is bare. The arrow nudges 2px on hover; that's the whole animation.

<a class="btn btn-primary" href="#">Request a demo <span class="arrow">→</span></a>
<a class="btn btn-secondary" href="#">Explore the platform</a>
<a class="btn btn-ghost" href="#">See gap analysis <span class="arrow">→</span></a>

/* css */
.btn { display:inline-flex; align-items:center; gap:6px;
  border-radius:var(--radius-full); padding:10px 20px;
  font-size:14px; font-weight:500; transition:all var(--dur-fast) ease; }
.btn-primary { background:var(--accent); color:var(--accent-fg); }
.btn-primary:hover { background:var(--accent-hover); }
.btn-secondary { background:var(--bg-elev); color:var(--fg);
  border:1px solid var(--line-strong); }
.btn-ghost { background:transparent; color:var(--fg-secondary); }
.btn:hover .arrow { transform:translateX(2px); }
02.2

Pills & capability chips

Small facts wear small frames.

Pills carry sans-serif metadata; chips carry mono capabilities with a status dot. The AI chip is the one place violet enters the chrome — it marks a capability an agent performs.

Workforce orchestration 96% fill rate location-verified check-in one rate rail confirmation sweep · agent calls
<span class="pill">Workforce orchestration</span>

<span class="chip"><span class="chip-dot"></span>location-verified check-in</span>

<!-- violet only because an agent does the work -->
<span class="chip chip-ai"><span class="chip-dot"></span>confirmation sweep · agent calls</span>

/* css */
.chip { display:inline-flex; align-items:center; gap:7px;
  border-radius:var(--radius-full); border:1px solid var(--line);
  background:var(--bg-elev); padding:5px 13px;
  font-family:var(--font-mono); font-size:11px; color:var(--fg-secondary); }
.chip .chip-dot { height:6px; width:6px; border-radius:9999px; background:var(--fg-subtle); }
.chip-ai { border-color:var(--ai-line); background:var(--ai-soft); }
.chip-ai .chip-dot { background:var(--ai); }
02.3

Status pills

Three colors, three facts.

ok / warn / danger appear only for real operational states. A pulsing dot means the number is live, not cached.

Gate A · 24/24 Club Level · 18/20 Suites · 10/12 LIVE
<span class="status-pill status-ok"><span class="dot"></span>Gate A · 24/24</span>
<span class="status-pill status-warn"><span class="dot"></span>Club Level · 18/20</span>
<span class="status-pill status-danger"><span class="dot"></span>Suites · 10/12</span>

<!-- pulse = live data -->
<span class="status-pill status-ok"><span class="dot animate-pulse-dot"></span>LIVE</span>

/* css */
.status-pill { display:inline-flex; align-items:center; gap:6px;
  border-radius:var(--radius-full); padding:2px 9px;
  font-size:10px; font-weight:500; }
.status-ok { background:var(--ok-soft); color:var(--ok); }
.status-warn { background:var(--warn-soft); color:var(--warn); }
.status-danger { background:var(--danger-soft); color:var(--danger); }
.animate-pulse-dot { animation:pulse-dot var(--dur-pulse) ease-in-out infinite; }
02.4

Cards

A border, a radius, a fact.

Three card species: the bordered default, the sunken stat card for numbers, and the update card whose only color is an 8px editorial-gradient bar on top.

The cascade

True gaps go to every partner at once

Open shifts become structured orders across agencies and marketplaces — tracked from placed to filled.

96%
fill rate
shifts covered before day-of

Live Gap Analysis in the Deploy command center

ProductJul 8, 2026
<!-- default card -->
<div class="card">…</div>

<!-- sunken stat card -->
<div class="stat-card">
  <div class="stat-n">96%</div>
  <div class="stat-l">fill rate</div>
  <div class="stat-s">shifts covered before day-of</div>
</div>

<!-- update card: color arrives as an 8px gradient bar, nowhere else -->
<a class="update-card" href="#">
  <div class="bar" style="background:linear-gradient(135deg,#8a7bd8 0%,#c77f9e 45%,#e8944a 100%);"></div>
  <div class="body">
    <h4>Live Gap Analysis in the Deploy command center</h4>
    <div class="meta"><span class="cat">Product</span><span class="date">Jul 8, 2026</span></div>
  </div>
</a>
02.5

MockFrame

Every mockup wears the same window.

Three neutral dots, a mono label in section · view form, and an optional LIVE pill with a pulsing dot. The frame carries --shadow-cmd so product screens read as windows floating over the page.

deploy · live gap analysis LIVE
Gate A24/24
Club Level18/20
Suites10/12
Overall fill91% · forecast beaten $8,220
<div class="mock">
  <div class="mock-bar">
    <div class="mock-dots"><span></span><span></span><span></span></div>
    <span class="mock-label">deploy · live gap analysis</span>
    <span class="mock-live status-pill status-ok">
      <span class="dot animate-pulse-dot"></span>LIVE</span>
  </div>
  <div class="mock-body">
    <div class="mock-row"><span>Gate A</span>
      <span class="status-pill status-ok"><span class="dot"></span>24/24</span></div>
    <div class="mock-row"><span>Club Level</span>
      <span class="status-pill status-warn"><span class="dot"></span>18/20</span></div>
    <div class="mock-row"><span>Suites</span>
      <span class="status-pill status-danger"><span class="dot"></span>10/12</span></div>
  </div>
</div>

/* labels are always mono, lowercase, "section · view" */
02.6

Lifecycle scrubber

One event, scrubbed end to end.

Mono time-pills switch a caption below — the pattern the marketing site uses to walk one event from brief to closeout. Selected state is the ink accent; this demo is wired, click through it.

T-30 days
Build the event
Zones, service locations, shifts & budget — from a brief, or cloned from a past event.
<div class="scrub-pills" role="tablist">
  <button class="scrub-pill" aria-selected="true">T-30 days</button>
  <button class="scrub-pill" aria-selected="false">T-7 days</button>
  …
</div>
<div class="scrub-caption">
  <span class="time">T-30 days</span>
  <div class="t">Build the event</div>
  <div class="d">Zones, service locations, shifts &amp; budget…</div>
</div>

/* css */
.scrub-pill { border:1px solid var(--line); background:var(--bg-elev);
  border-radius:var(--radius-full); padding:6px 14px;
  font-family:var(--font-mono); font-size:11px; cursor:pointer; }
.scrub-pill[aria-selected="true"] { background:var(--accent);
  border-color:var(--accent); color:var(--accent-fg); }
02.7

FAQ accordion

Hairlines and a rotating plus.

Divided by 1px lines, opened one at a time, the plus rotating 45° into a close. The reveal is a grid-template-rows: 0fr → 1fr transition — no measured heights, no JS animation. This one works.

Ranked shift offers go to your own people first — by certification, prior performance at the venue, and cost against budget. Only what remains becomes the gap that goes external.

Agencies, marketplaces, and regional staffing partners — one order fanned to three, four, or more at once, each commitment tracked from placed to filled.

A timestamped, location-verified clock-in at the gate and clock-out at the end of shift. Hours stop being a my-word-against-yours argument.

<div class="faq">
  <div class="faq-item">
    <button class="faq-q" aria-expanded="false">
      <span>What counts as a verified hour?</span>
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
        <path d="M7 1v12M1 7h12" stroke="currentColor"
          stroke-width="1.4" stroke-linecap="round"/></svg>
    </button>
    <div class="faq-a"><div><p>A timestamped, location-verified clock-in…</p></div></div>
  </div>
</div>

/* open state: .faq-item.open — grid-rows 0fr→1fr, plus rotates 45° */
.faq-a { display:grid; grid-template-rows:0fr; opacity:0;
  transition:grid-template-rows var(--dur-med) var(--ease-out-expo),
             opacity var(--dur-med) ease; }
.faq-item.open .faq-a { grid-template-rows:1fr; opacity:1; }
.faq-a > div { overflow:hidden; }
02.8

Photo cutout

The world, framed at 28px.

Photography never runs full-bleed. It sits in a --radius-3xl cutout with a bottom-up black scrim carrying a white caption. The gradient below stands in for a photo — swap in real labor, shot dark and cinematic.

Live at championship golf, motorsport & enterprise venues

Gate A, 5:40 a.m. — load-in crew, verified in

<div class="cutout">
  <img class="cutout-media" src="…" alt="">   <!-- or a .grain gradient -->
  <div class="cutout-scrim">
    <p>Live at championship golf, motorsport &amp; enterprise venues</p>
    <p class="sub">Gate A, 5:40 a.m. — load-in crew, verified in</p>
  </div>
</div>

/* css */
.cutout { position:relative; overflow:hidden;
  border-radius:var(--radius-3xl); border:1px solid var(--line);
  min-height:260px; }
.cutout-media { position:absolute; inset:0; object-fit:cover; }
.cutout-scrim { position:absolute; left:0; right:0; bottom:0; padding:24px;
  background:linear-gradient(to top, rgba(0,0,0,0.72), transparent); }
.cutout-scrim p { color:#fff; font-size:14px; font-weight:500; }
02.9

Mega panel

Navigation that names the work.

Dropdown panels float on --shadow-pop, group items under eyebrows, and give each item a mono-glyph tile. The violet tile marks the one item where an agent does the work.

<div class="mega">
  <div>
    <h5 class="eyebrow">Platform</h5>
    <a class="mega-item" href="#">
      <span class="mi-icon">SC</span>
      <span><span class="mi-t">Schedule</span><br>
        <span class="mi-d">Internal-first fill, ranked by skill, cost &amp; history</span></span>
    </a>
  </div>
  <div>
    <h5 class="eyebrow">Automation</h5>
    <!-- .mi-ai: violet tile, only because an agent acts -->
    <a class="mega-item mi-ai" href="#">
      <span class="mi-icon">AI</span>
      <span><span class="mi-t">Outbound agents</span><br>
        <span class="mi-d">Calls, texts &amp; emails that confirm every worker</span></span>
    </a>
  </div>
</div>
02.10

Dark theme

Same tokens, lights off.

Dark is the same tokens flipped by [data-theme="dark"] — nothing is redesigned. The panel below is forced dark regardless of the page toggle; every specimen inside is byte-identical to the ones above. One rule of thumb: photography and gradients are shared across themes; hairlines get slightly stronger in dark so edges keep reading.

forced [data-theme="dark"] · ignores the page toggle

Request a demo Explore the platform
location-verified check-in confirmation sweep · agent calls Gate A · 24/24 Club Level · 18/20 Suites · 10/12
96%
fill rate
shifts covered before day-of
deploy · live gap analysis LIVE
Gate A24/24
Club Level18/20
<!-- whole page: set the attribute on <html> and every token flips -->
<html data-theme="dark">

<!-- one region: nest the attribute; tokens re-resolve inside the wrapper -->
<div class="theme-panel" data-theme="dark">
  …any component, unchanged…
</div>

/* css — the wrapper just paints its own tokens */
.theme-panel { background: var(--bg); color: var(--fg);
  border: 1px solid var(--line); border-radius: var(--radius-2xl);
  padding: 28px 24px; }