Video — Services Gear
A cinematic dark services-and-gear page for a video production studio, pairing a letterboxed hero with a filterable services list (film, edit, color, aerial) and gear showcase cards for cameras, lenses, and lighting — each with real specs, monospaced timecode-style stats, hover tilt, and a slide-in quote drawer that tallies your selected services.
MCP
Code
:root {
--bg: #0a0a0b;
--surface: #141416;
--surface-2: #1c1c1f;
--amber: #ffb020;
--amber-d: #e6971a;
--red: #ff4d4d;
--ink: #f4f4f6;
--muted: #8a8a92;
--line: rgba(255, 255, 255, 0.10);
--line-2: rgba(255, 255, 255, 0.18);
--white: #fff;
--r-sm: 6px;
--r-md: 10px;
--r-lg: 16px;
--mono: "JetBrains Mono", ui-monospace, monospace;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
font-family: Inter, system-ui, -apple-system, sans-serif;
background: var(--bg);
color: var(--ink);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
h1, h2, h3 { margin: 0; letter-spacing: -0.02em; }
p { margin: 0; }
:focus-visible {
outline: 2px solid var(--amber);
outline-offset: 2px;
border-radius: var(--r-sm);
}
/* ===== HERO ===== */
.hero {
position: relative;
background:
radial-gradient(120% 80% at 80% -10%, rgba(255, 176, 32, 0.14), transparent 60%),
linear-gradient(180deg, #0d0d0f, #0a0a0b);
overflow: hidden;
}
.bar {
height: 42px;
background: #000;
}
.bar-top { border-bottom: 1px solid rgba(255, 176, 32, 0.25); }
.bar-bot { border-top: 1px solid rgba(255, 176, 32, 0.25); }
.hero-inner {
max-width: 1080px;
margin: 0 auto;
padding: 64px 24px;
display: grid;
grid-template-columns: 1fr auto;
gap: 40px;
align-items: center;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 8px;
font-family: var(--mono);
font-size: 12px;
letter-spacing: 0.14em;
color: var(--amber);
text-transform: uppercase;
}
.rec {
width: 9px;
height: 9px;
border-radius: 50%;
background: var(--red);
box-shadow: 0 0 0 0 rgba(255, 77, 77, 0.6);
animation: pulse 1.6s ease-out infinite;
}
@keyframes pulse {
70% { box-shadow: 0 0 0 8px rgba(255, 77, 77, 0); }
100% { box-shadow: 0 0 0 0 rgba(255, 77, 77, 0); }
}
.hero h1 {
font-size: clamp(40px, 8vw, 76px);
font-weight: 800;
margin: 16px 0 14px;
line-height: 1.02;
}
.hero h1 span { color: var(--amber); }
.lede {
max-width: 44ch;
color: var(--muted);
font-size: 17px;
}
.hero-actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin: 28px 0 26px;
}
.hero-meta {
display: flex;
flex-wrap: wrap;
gap: 26px;
font-size: 13px;
color: var(--muted);
}
.hero-meta b {
display: block;
font-family: var(--mono);
font-size: 22px;
color: var(--ink);
font-weight: 700;
}
.hero-tc {
display: flex;
flex-direction: column;
gap: 6px;
padding: 22px 24px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid var(--line);
border-radius: var(--r-lg);
text-align: center;
backdrop-filter: blur(4px);
}
.tc-label, .tc-sub {
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.16em;
color: var(--muted);
}
.tc {
font-family: var(--mono);
font-size: 30px;
font-weight: 700;
color: var(--amber);
font-variant-numeric: tabular-nums;
}
/* ===== BUTTONS ===== */
.btn {
font: inherit;
font-weight: 600;
font-size: 14px;
padding: 12px 20px;
border-radius: var(--r-md);
border: 1px solid transparent;
cursor: pointer;
transition: transform 0.12s ease, background 0.18s ease, border-color 0.18s ease;
}
.btn:active { transform: translateY(1px) scale(0.99); }
.btn-primary {
background: var(--amber);
color: #1a1200;
}
.btn-primary:hover { background: var(--amber-d); }
.btn-ghost {
background: transparent;
color: var(--ink);
border-color: var(--line-2);
}
.btn-ghost:hover { border-color: var(--amber); color: var(--amber); }
.btn.block { width: 100%; }
/* ===== SECTIONS ===== */
.section {
max-width: 1080px;
margin: 0 auto;
padding: 72px 24px;
}
.section-head {
display: flex;
flex-wrap: wrap;
gap: 18px;
justify-content: space-between;
align-items: flex-end;
margin-bottom: 30px;
}
.kicker {
font-family: var(--mono);
font-size: 12px;
letter-spacing: 0.16em;
color: var(--amber);
text-transform: uppercase;
}
.section-head h2 {
font-size: clamp(28px, 5vw, 40px);
font-weight: 800;
margin-top: 8px;
}
.filters, .rail {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.chip {
font: inherit;
font-size: 13px;
font-weight: 600;
color: var(--muted);
background: var(--surface);
border: 1px solid var(--line);
padding: 8px 15px;
border-radius: 999px;
cursor: pointer;
transition: color 0.18s, border-color 0.18s, background 0.18s;
}
.chip:hover { color: var(--ink); border-color: var(--line-2); }
.chip.is-active {
color: #1a1200;
background: var(--amber);
border-color: var(--amber);
}
/* ===== SERVICES ===== */
.svc-list {
list-style: none;
margin: 0;
padding: 0;
display: grid;
gap: 12px;
}
.svc {
display: grid;
grid-template-columns: auto 1fr auto auto;
align-items: center;
gap: 20px;
padding: 20px 22px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
transition: transform 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}
.svc:hover {
border-color: var(--line-2);
transform: translateX(4px);
background: var(--surface-2);
}
.svc.is-hidden { display: none; }
.svc-icon {
display: grid;
place-items: center;
width: 46px;
height: 46px;
border-radius: var(--r-md);
font-size: 20px;
background: var(--surface-2);
border: 1px solid var(--line);
}
.svc-body h3 { font-size: 17px; font-weight: 700; }
.svc-body p {
color: var(--muted);
font-size: 14px;
margin: 4px 0 8px;
max-width: 52ch;
}
.tag {
display: inline-block;
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.06em;
color: var(--amber);
background: rgba(255, 176, 32, 0.10);
border: 1px solid rgba(255, 176, 32, 0.24);
padding: 3px 9px;
border-radius: 999px;
}
.svc-rate { text-align: right; white-space: nowrap; }
.svc-rate .rate {
font-family: var(--mono);
font-size: 20px;
font-weight: 700;
color: var(--ink);
}
.svc-rate .unit { color: var(--muted); font-size: 12px; }
.add {
font: inherit;
font-weight: 600;
font-size: 13px;
color: var(--ink);
background: var(--surface-2);
border: 1px solid var(--line-2);
padding: 9px 16px;
border-radius: var(--r-md);
cursor: pointer;
transition: all 0.16s ease;
}
.add:hover { border-color: var(--amber); color: var(--amber); }
.add.is-added {
background: var(--amber);
border-color: var(--amber);
color: #1a1200;
}
/* ===== GEAR ===== */
.gear-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 18px;
}
.gcard {
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
overflow: hidden;
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
transform-style: preserve-3d;
will-change: transform;
}
.gcard:hover, .gcard:focus-visible {
border-color: var(--line-2);
box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.8);
}
.gcard.flash { border-color: var(--amber); }
.gcard-shot {
position: relative;
height: 150px;
display: flex;
align-items: flex-start;
padding: 12px;
}
.pill {
font-family: var(--mono);
font-size: 10px;
letter-spacing: 0.14em;
color: var(--ink);
background: rgba(0, 0, 0, 0.55);
border: 1px solid var(--line);
padding: 4px 8px;
border-radius: var(--r-sm);
}
.cam-1 { background: linear-gradient(135deg, #2a2a2e, #101012); }
.cam-2 { background: linear-gradient(135deg, #3a2a12, #14100a); }
.lens-1 { background: linear-gradient(135deg, #12232e, #0a1014); }
.lens-2 { background: linear-gradient(135deg, #101a3a, #0a0c18); }
.light-1 { background: linear-gradient(135deg, #3a3418, #14120a); }
.light-2 { background: linear-gradient(135deg, #2e1236, #140a18); }
.gcard-shot::after {
content: "";
position: absolute;
inset: 0;
background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.04) 0 1px, transparent 1px 3px);
opacity: 0.5;
}
.gcard-body { padding: 18px; }
.gcard-body h3 { font-size: 17px; font-weight: 700; }
.gsub { color: var(--muted); font-size: 13px; margin: 3px 0 14px; }
.specs {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px 16px;
margin: 0 0 14px;
}
.specs div {
display: flex;
flex-direction: column;
gap: 2px;
border-top: 1px solid var(--line);
padding-top: 8px;
}
.specs dt {
font-size: 10px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
}
.specs dd {
margin: 0;
font-family: var(--mono);
font-size: 13px;
font-weight: 500;
color: var(--ink);
}
.avail {
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.05em;
}
.avail.in { color: #6fe09a; }
.avail.out { color: var(--red); }
/* ===== DRAWER ===== */
.drawer {
position: fixed;
top: 0;
right: 0;
height: 100%;
width: min(360px, 90vw);
background: var(--surface);
border-left: 1px solid var(--line-2);
display: flex;
flex-direction: column;
transform: translateX(105%);
transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
z-index: 40;
box-shadow: -30px 0 60px -30px rgba(0, 0, 0, 0.9);
}
.drawer.open { transform: translateX(0); }
.drawer-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 22px 22px 16px;
border-bottom: 1px solid var(--line);
}
.drawer-head h2 { font-size: 20px; font-weight: 800; }
.drawer-close {
font: inherit;
font-size: 16px;
color: var(--muted);
background: var(--surface-2);
border: 1px solid var(--line);
width: 34px;
height: 34px;
border-radius: var(--r-sm);
cursor: pointer;
}
.drawer-close:hover { color: var(--ink); border-color: var(--line-2); }
.quote-list {
list-style: none;
margin: 0;
padding: 16px 22px;
flex: 1;
overflow-y: auto;
display: grid;
gap: 10px;
align-content: start;
}
.quote-empty {
color: var(--muted);
font-size: 14px;
padding: 16px 0;
}
.quote-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
padding: 12px 14px;
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-md);
animation: slideIn 0.24s ease;
}
@keyframes slideIn {
from { opacity: 0; transform: translateX(12px); }
to { opacity: 1; transform: translateX(0); }
}
.quote-item .qname { font-size: 14px; font-weight: 600; }
.quote-item .qprice { font-family: var(--mono); font-size: 13px; color: var(--amber); }
.quote-item .qrm {
font: inherit;
color: var(--muted);
background: none;
border: none;
cursor: pointer;
font-size: 16px;
line-height: 1;
}
.quote-item .qrm:hover { color: var(--red); }
.drawer-foot {
padding: 18px 22px 22px;
border-top: 1px solid var(--line);
display: grid;
gap: 14px;
}
.total-row {
display: flex;
justify-content: space-between;
align-items: baseline;
font-size: 14px;
color: var(--muted);
}
.total {
font-family: var(--mono);
font-size: 26px;
font-weight: 700;
color: var(--ink);
}
/* ===== FAB ===== */
.fab {
position: fixed;
bottom: 22px;
right: 22px;
z-index: 30;
display: inline-flex;
align-items: center;
gap: 9px;
font: inherit;
font-weight: 700;
font-size: 14px;
color: #1a1200;
background: var(--amber);
border: none;
padding: 13px 20px;
border-radius: 999px;
cursor: pointer;
box-shadow: 0 14px 30px -10px rgba(255, 176, 32, 0.5);
transition: transform 0.14s ease;
}
.fab:hover { transform: translateY(-2px); }
.fab:active { transform: translateY(0); }
.fab-count {
min-width: 22px;
height: 22px;
padding: 0 6px;
display: grid;
place-items: center;
font-family: var(--mono);
font-size: 12px;
border-radius: 999px;
background: #1a1200;
color: var(--amber);
}
/* ===== TOAST ===== */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translate(-50%, 26px);
background: var(--surface-2);
border: 1px solid var(--line-2);
color: var(--ink);
font-size: 14px;
font-weight: 500;
padding: 12px 20px;
border-radius: var(--r-md);
opacity: 0;
pointer-events: none;
transition: opacity 0.25s ease, transform 0.25s ease;
z-index: 50;
}
.toast.show {
opacity: 1;
transform: translate(-50%, 0);
}
/* ===== RESPONSIVE ===== */
@media (max-width: 760px) {
.hero-inner { grid-template-columns: 1fr; }
.hero-tc { justify-self: start; }
}
@media (max-width: 520px) {
.bar { height: 28px; }
.hero-inner { padding: 44px 18px; }
.section { padding: 52px 18px; }
.section-head { flex-direction: column; align-items: flex-start; }
.svc {
grid-template-columns: auto 1fr;
gap: 14px 16px;
}
.svc-icon { grid-row: span 2; }
.svc-rate { grid-column: 2; text-align: left; }
.add { grid-column: 2; justify-self: start; }
.specs { grid-template-columns: 1fr 1fr; }
.hero-meta { gap: 18px; }
}(function () {
"use strict";
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2400);
}
/* ---------- Smooth scroll from hero ---------- */
document.querySelectorAll("[data-scroll]").forEach(function (btn) {
btn.addEventListener("click", function () {
var target = document.getElementById(btn.dataset.scroll);
if (target) target.scrollIntoView({ behavior: "smooth", block: "start" });
});
});
/* ---------- Running timecode ---------- */
var tcEl = document.getElementById("timecode");
var frame = 0;
function pad(n) { return String(n).padStart(2, "0"); }
setInterval(function () {
frame = (frame + 1) % 24;
var totalSec = Math.floor(Date.now() / 1000) % 86400;
var h = Math.floor(totalSec / 3600);
var m = Math.floor((totalSec % 3600) / 60);
var s = totalSec % 60;
tcEl.textContent = pad(h) + ":" + pad(m) + ":" + pad(s) + ":" + pad(frame);
}, 1000 / 24);
/* ---------- Services filter ---------- */
var filterChips = document.querySelectorAll(".filters .chip");
var svcItems = document.querySelectorAll("#svcList .svc");
filterChips.forEach(function (chip) {
chip.addEventListener("click", function () {
filterChips.forEach(function (c) {
c.classList.remove("is-active");
c.setAttribute("aria-selected", "false");
});
chip.classList.add("is-active");
chip.setAttribute("aria-selected", "true");
var f = chip.dataset.filter;
svcItems.forEach(function (item) {
var show = f === "all" || item.dataset.cat === f;
item.classList.toggle("is-hidden", !show);
});
});
});
/* ---------- Gear rail (scroll to group) ---------- */
var railChips = document.querySelectorAll(".rail .chip");
railChips.forEach(function (chip) {
chip.addEventListener("click", function () {
railChips.forEach(function (c) { c.classList.remove("is-active"); });
chip.classList.add("is-active");
var group = chip.dataset.rail;
var card = document.querySelector('.gcard[data-group="' + group + '"]');
if (card) {
card.scrollIntoView({ behavior: "smooth", block: "center" });
card.classList.add("flash");
setTimeout(function () { card.classList.remove("flash"); }, 900);
}
});
});
/* ---------- Gear pointer tilt ---------- */
document.querySelectorAll(".gcard").forEach(function (card) {
card.addEventListener("pointermove", function (e) {
var r = card.getBoundingClientRect();
var px = (e.clientX - r.left) / r.width - 0.5;
var py = (e.clientY - r.top) / r.height - 0.5;
card.style.transform =
"perspective(700px) rotateX(" + (-py * 5).toFixed(2) + "deg) rotateY(" +
(px * 6).toFixed(2) + "deg) translateY(-3px)";
});
card.addEventListener("pointerleave", function () {
card.style.transform = "";
});
});
/* ---------- Quote state ---------- */
var quote = []; // { name, price, btn }
var quoteList = document.getElementById("quoteList");
var quoteTotal = document.getElementById("quoteTotal");
var fabCount = document.getElementById("fabCount");
var drawer = document.getElementById("drawer");
var fab = document.getElementById("fab");
function money(n) { return "$" + n.toLocaleString("en-US"); }
function render() {
fabCount.textContent = quote.length;
fab.setAttribute("aria-expanded", drawer.classList.contains("open"));
if (quote.length === 0) {
quoteList.innerHTML = '<li class="quote-empty">No services yet — add one to build your day rate.</li>';
quoteTotal.textContent = "$0";
return;
}
quoteList.innerHTML = "";
var total = 0;
quote.forEach(function (q, i) {
total += q.price;
var li = document.createElement("li");
li.className = "quote-item";
li.innerHTML =
'<span class="qname">' + q.name + '</span>' +
'<span class="qprice">' + money(q.price) + "</span>";
var rm = document.createElement("button");
rm.className = "qrm";
rm.type = "button";
rm.setAttribute("aria-label", "Remove " + q.name);
rm.textContent = "✕";
rm.addEventListener("click", function () { removeAt(i); });
li.appendChild(rm);
quoteList.appendChild(li);
});
quoteTotal.textContent = money(total);
}
function removeAt(i) {
var q = quote[i];
if (q && q.btn) {
q.btn.classList.remove("is-added");
q.btn.setAttribute("aria-pressed", "false");
q.btn.textContent = "Add";
}
quote.splice(i, 1);
render();
}
document.querySelectorAll(".add").forEach(function (btn) {
btn.addEventListener("click", function () {
var name = btn.dataset.name;
var price = parseInt(btn.dataset.price, 10);
var idx = quote.findIndex(function (q) { return q.btn === btn; });
if (idx >= 0) {
removeAt(idx);
toast(name + " removed from quote");
return;
}
quote.push({ name: name, price: price, btn: btn });
btn.classList.add("is-added");
btn.setAttribute("aria-pressed", "true");
btn.textContent = "Added ✓";
render();
toast(name + " added — " + money(price) + "/day");
});
});
/* ---------- Drawer open/close ---------- */
function openDrawer() {
drawer.classList.add("open");
drawer.setAttribute("aria-hidden", "false");
fab.setAttribute("aria-expanded", "true");
}
function closeDrawer() {
drawer.classList.remove("open");
drawer.setAttribute("aria-hidden", "true");
fab.setAttribute("aria-expanded", "false");
}
fab.addEventListener("click", function () {
drawer.classList.contains("open") ? closeDrawer() : openDrawer();
});
document.getElementById("drawerClose").addEventListener("click", closeDrawer);
document.addEventListener("keydown", function (e) {
if (e.key === "Escape" && drawer.classList.contains("open")) closeDrawer();
});
document.getElementById("requestBtn").addEventListener("click", function () {
if (quote.length === 0) {
toast("Add a service to request a booking");
return;
}
toast("Booking request sent for " + quote.length + " service" + (quote.length > 1 ? "s" : ""));
closeDrawer();
});
render();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Aperture & Motion — Services & Gear</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- ===== HERO (letterboxed) ===== -->
<header class="hero" role="banner">
<div class="bar bar-top" aria-hidden="true"></div>
<div class="hero-inner">
<div class="hero-copy">
<span class="eyebrow"><span class="rec" aria-hidden="true"></span> REC · Studio 12</span>
<h1>Aperture <span>&</span> Motion</h1>
<p class="lede">
A boutique film unit shooting narrative, brand, and aerial work.
Book crew and camera packages by the day — color and edit included.
</p>
<div class="hero-actions">
<button class="btn btn-primary" data-scroll="services">Explore services</button>
<button class="btn btn-ghost" data-scroll="gear">View gear list</button>
</div>
<div class="hero-meta" role="list">
<span role="listitem"><b>08</b> years rolling</span>
<span role="listitem"><b>140+</b> productions</span>
<span role="listitem"><b>4K/8K</b> deliverables</span>
</div>
</div>
<div class="hero-tc" aria-hidden="true">
<span class="tc-label">TIMECODE</span>
<span class="tc" id="timecode">00:00:00:00</span>
<span class="tc-sub">24 FPS · REC.709</span>
</div>
</div>
<div class="bar bar-bot" aria-hidden="true"></div>
</header>
<main>
<!-- ===== SERVICES ===== -->
<section id="services" class="section" aria-labelledby="services-h">
<div class="section-head">
<div>
<span class="kicker">01 — Disciplines</span>
<h2 id="services-h">Services</h2>
</div>
<div class="filters" role="tablist" aria-label="Filter services">
<button class="chip is-active" role="tab" aria-selected="true" data-filter="all">All</button>
<button class="chip" role="tab" aria-selected="false" data-filter="film">Film</button>
<button class="chip" role="tab" aria-selected="false" data-filter="edit">Edit</button>
<button class="chip" role="tab" aria-selected="false" data-filter="color">Color</button>
<button class="chip" role="tab" aria-selected="false" data-filter="aerial">Aerial</button>
</div>
</div>
<ul class="svc-list" id="svcList">
<li class="svc" data-cat="film">
<span class="svc-icon film" aria-hidden="true">🎬</span>
<div class="svc-body">
<h3>Principal Cinematography</h3>
<p>Director of photography, 2-person camera crew, lighting & grip package on set.</p>
<span class="tag">Turnaround · same-day rushes</span>
</div>
<div class="svc-rate"><span class="rate">$3,200</span><span class="unit">/ day</span></div>
<button class="add" data-name="Principal Cinematography" data-price="3200" aria-pressed="false">Add</button>
</li>
<li class="svc" data-cat="edit">
<span class="svc-icon edit" aria-hidden="true">✂️</span>
<div class="svc-body">
<h3>Offline & Online Edit</h3>
<p>Story assembly, sound design, motion titles, and versioned deliverables for socials.</p>
<span class="tag">Turnaround · 3–5 days</span>
</div>
<div class="svc-rate"><span class="rate">$1,450</span><span class="unit">/ day</span></div>
<button class="add" data-name="Offline & Online Edit" data-price="1450" aria-pressed="false">Add</button>
</li>
<li class="svc" data-cat="color">
<span class="svc-icon color" aria-hidden="true">🎨</span>
<div class="svc-body">
<h3>Color Grade & Finishing</h3>
<p>DaVinci grade, HDR pass, and delivery-ready masters in Rec.709, P3, and Rec.2020.</p>
<span class="tag">Turnaround · 2–4 days</span>
</div>
<div class="svc-rate"><span class="rate">$1,800</span><span class="unit">/ day</span></div>
<button class="add" data-name="Color Grade & Finishing" data-price="1800" aria-pressed="false">Add</button>
</li>
<li class="svc" data-cat="aerial">
<span class="svc-icon aerial" aria-hidden="true">🚁</span>
<div class="svc-body">
<h3>Aerial & Drone Unit</h3>
<p>Licensed pilot, cinema drone, and FPV rig for chase, reveal, and top-down shots.</p>
<span class="tag">Turnaround · same-day proxies</span>
</div>
<div class="svc-rate"><span class="rate">$2,600</span><span class="unit">/ day</span></div>
<button class="add" data-name="Aerial & Drone Unit" data-price="2600" aria-pressed="false">Add</button>
</li>
<li class="svc" data-cat="film">
<span class="svc-icon film" aria-hidden="true">🎬</span>
<div class="svc-body">
<h3>Documentary Coverage</h3>
<p>Run-and-gun single op, interview lighting, and lavalier + boom audio capture.</p>
<span class="tag">Turnaround · next-day selects</span>
</div>
<div class="svc-rate"><span class="rate">$1,900</span><span class="unit">/ day</span></div>
<button class="add" data-name="Documentary Coverage" data-price="1900" aria-pressed="false">Add</button>
</li>
<li class="svc" data-cat="edit">
<span class="svc-icon edit" aria-hidden="true">✂️</span>
<div class="svc-body">
<h3>Social Cutdowns</h3>
<p>Vertical and square reframes, captions, and platform-native exports for launch week.</p>
<span class="tag">Turnaround · 24–48 hrs</span>
</div>
<div class="svc-rate"><span class="rate">$680</span><span class="unit">/ day</span></div>
<button class="add" data-name="Social Cutdowns" data-price="680" aria-pressed="false">Add</button>
</li>
</ul>
</section>
<!-- ===== GEAR ===== -->
<section id="gear" class="section" aria-labelledby="gear-h">
<div class="section-head">
<div>
<span class="kicker">02 — Camera department</span>
<h2 id="gear-h">Gear showcase</h2>
</div>
<div class="rail" role="tablist" aria-label="Jump to gear group">
<button class="chip is-active" data-rail="camera">Cameras</button>
<button class="chip" data-rail="lens">Lenses</button>
<button class="chip" data-rail="light">Lighting</button>
</div>
</div>
<div class="gear-grid" id="gearGrid">
<!-- Cameras -->
<article class="gcard" data-group="camera" tabindex="0">
<div class="gcard-shot cam-1" aria-hidden="true"><span class="pill">CAMERA</span></div>
<div class="gcard-body">
<h3>Vela Cine 8K</h3>
<p class="gsub">Full-frame cinema body</p>
<dl class="specs">
<div><dt>Sensor</dt><dd>Full-frame 8K</dd></div>
<div><dt>Mount</dt><dd>PL / EF</dd></div>
<div><dt>ISO</dt><dd>800–12,800</dd></div>
<div><dt>Weight</dt><dd>2.4 kg</dd></div>
</dl>
<span class="avail in">● In kit</span>
</div>
</article>
<article class="gcard" data-group="camera" tabindex="0">
<div class="gcard-shot cam-2" aria-hidden="true"><span class="pill">CAMERA</span></div>
<div class="gcard-body">
<h3>Orbit Mirrorless R</h3>
<p class="gsub">Hybrid B-cam</p>
<dl class="specs">
<div><dt>Sensor</dt><dd>Super35 6K</dd></div>
<div><dt>Mount</dt><dd>RF</dd></div>
<div><dt>ISO</dt><dd>100–25,600</dd></div>
<div><dt>Weight</dt><dd>0.9 kg</dd></div>
</dl>
<span class="avail in">● In kit</span>
</div>
</article>
<!-- Lenses -->
<article class="gcard" data-group="lens" tabindex="0">
<div class="gcard-shot lens-1" aria-hidden="true"><span class="pill">LENS</span></div>
<div class="gcard-body">
<h3>Prime Set — Signature 5</h3>
<p class="gsub">25 · 35 · 50 · 85 · 135mm</p>
<dl class="specs">
<div><dt>Aperture</dt><dd>T1.5</dd></div>
<div><dt>Mount</dt><dd>PL</dd></div>
<div><dt>Coverage</dt><dd>Full-frame</dd></div>
<div><dt>Weight</dt><dd>1.1 kg ea</dd></div>
</dl>
<span class="avail in">● In kit</span>
</div>
</article>
<article class="gcard" data-group="lens" tabindex="0">
<div class="gcard-shot lens-2" aria-hidden="true"><span class="pill">LENS</span></div>
<div class="gcard-body">
<h3>Anamorphic 40mm</h3>
<p class="gsub">2x squeeze, blue flare</p>
<dl class="specs">
<div><dt>Aperture</dt><dd>T2.3</dd></div>
<div><dt>Mount</dt><dd>PL</dd></div>
<div><dt>Squeeze</dt><dd>2.0x</dd></div>
<div><dt>Weight</dt><dd>1.6 kg</dd></div>
</dl>
<span class="avail out">● On hold</span>
</div>
</article>
<!-- Lighting -->
<article class="gcard" data-group="light" tabindex="0">
<div class="gcard-shot light-1" aria-hidden="true"><span class="pill">LIGHT</span></div>
<div class="gcard-body">
<h3>Aperture 600d Pro</h3>
<p class="gsub">Daylight LED monolight</p>
<dl class="specs">
<div><dt>Output</dt><dd>600 W</dd></div>
<div><dt>CCT</dt><dd>5600 K</dd></div>
<div><dt>CRI</dt><dd>96+</dd></div>
<div><dt>Weight</dt><dd>3.1 kg</dd></div>
</dl>
<span class="avail in">● In kit</span>
</div>
</article>
<article class="gcard" data-group="light" tabindex="0">
<div class="gcard-shot light-2" aria-hidden="true"><span class="pill">LIGHT</span></div>
<div class="gcard-body">
<h3>Tube Kit — Pixel 4</h3>
<p class="gsub">RGBWW light tubes ×4</p>
<dl class="specs">
<div><dt>Output</dt><dd>4×20 W</dd></div>
<div><dt>CCT</dt><dd>2000–10000 K</dd></div>
<div><dt>Effects</dt><dd>Pixel FX</dd></div>
<div><dt>Weight</dt><dd>0.7 kg ea</dd></div>
</dl>
<span class="avail in">● In kit</span>
</div>
</article>
</div>
</section>
</main>
<!-- ===== QUOTE DRAWER ===== -->
<aside class="drawer" id="drawer" aria-label="Your quote" aria-hidden="true">
<div class="drawer-head">
<h2>Your quote</h2>
<button class="drawer-close" id="drawerClose" aria-label="Close quote">✕</button>
</div>
<ul class="quote-list" id="quoteList">
<li class="quote-empty">No services yet — add one to build your day rate.</li>
</ul>
<div class="drawer-foot">
<div class="total-row">
<span>Est. day rate</span>
<span class="total" id="quoteTotal">$0</span>
</div>
<button class="btn btn-primary block" id="requestBtn">Request booking</button>
</div>
</aside>
<!-- Floating quote toggle -->
<button class="fab" id="fab" aria-controls="drawer" aria-expanded="false">
<span class="fab-icon" aria-hidden="true">🎞️</span>
Quote
<span class="fab-count" id="fabCount">0</span>
</button>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>A film-forward services and gear page for a fictional production house, Aperture & Motion. The hero sits inside cinematic black letterbox bars with an amber accent line and a monospaced timecode counter that ticks upward like a running deck. Below it, a filterable services list lets you switch between Film, Edit, Color, and Aerial disciplines; each row carries a rate badge, a turnaround chip, and an “Add to quote” toggle.
The gear showcase presents camera bodies, lenses, and lighting as cards with JetBrains Mono spec readouts (sensor, mount, ISO range, weight) and a subtle pointer-tracking tilt on hover. A category rail scrolls the grid to the matching group, and every card exposes clear focus, hover, and active states for keyboard users.
Selecting services opens a slide-in quote drawer that lists your picks, sums an estimated day rate, and fires a toast on request. Everything is vanilla JS — no frameworks — and the layout collapses gracefully to a single column below 520px while keeping the letterbox, badges, and micro-interactions intact.