/* CVH Visuals — site styles
   One stylesheet, no framework. Dark, show-floor aesthetic. */

/* Fonts, self-hosted: Google Fonts' variable woff2 files (one file per subset covers every weight used), latin
   and latin-ext only. unicode-range means a page downloads latin-ext only if it uses one of those characters.
   base.html preloads Inter Tight latin, the hero heading face. */
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400 600; font-display: swap; src: url("../fonts/inter-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400 600; font-display: swap; src: url("../fonts/inter-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Inter Tight"; font-style: normal; font-weight: 500 600; font-display: swap; src: url("../fonts/inter-tight-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Inter Tight"; font-style: normal; font-weight: 500 600; font-display: swap; src: url("../fonts/inter-tight-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("../fonts/jetbrains-mono-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

:root {
  --bg: #07080a;
  --bg-2: #0d0f13;
  --surface: #12151a;
  --surface-2: #181c22;
  --line: rgba(255, 255, 255, 0.08);
  --line-2: rgba(255, 255, 255, 0.14);
  --text: #eef0f3;
  --muted: #9aa2ad;
  --dim: #6b737e;
  --accent: #46d6c8;          /* brand teal (from the hand mark) */
  --accent-ink: #001b18;
  --tally: #ff3b30;           /* live / program red */
  --ok: #34d399;

  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: "Inter Tight", "Inter", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --radius: 14px;
  --radius-lg: 22px;
  --wrap: 1200px;
  --gutter: clamp(16px, 4vw, 40px);
  --section: clamp(72px, 10vw, 140px);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 80px; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 17px/1.6 var(--font-sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
img, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
::selection { background: var(--accent); color: var(--accent-ink); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.skip { position: absolute; left: -9999px; top: 8px; z-index: 100; background: var(--accent); color: var(--accent-ink); padding: 8px 14px; border-radius: 8px; }
.skip:focus { left: 8px; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.section { padding: var(--section) 0; position: relative; }
.section--tight { padding: calc(var(--section) * .6) 0; }
.section--alt { background: var(--bg-2); border-block: 1px solid var(--line); }

/* ---------- Type ---------- */
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.02em; line-height: 1.08; margin: 0 0 .5em; text-wrap: balance; }
h1 { font-size: clamp(2.6rem, 7vw, 5.6rem); letter-spacing: -0.035em; }
h2 { font-size: clamp(2rem, 4.4vw, 3.4rem); }
h3 { font-size: clamp(1.25rem, 2vw, 1.5rem); letter-spacing: -0.01em; }
p { margin: 0 0 1em; text-wrap: pretty; }
.lede { font-size: clamp(1.1rem, 1.6vw, 1.3rem); color: var(--muted); max-width: 62ch; }
.muted { color: var(--muted); }
.mono { font-family: var(--font-mono); }

.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font: 500 12px/1 var(--font-mono); letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 20px;
}
.eyebrow::before { content: ""; width: 22px; height: 1px; background: currentColor; }

.section-head { display: grid; gap: 8px; margin-bottom: clamp(36px, 5vw, 64px); max-width: 780px; }
.section-head h2 { margin: 0; }
.section-head p { margin: 8px 0 0; }

/* SMPTE-style bar strip used as a recurring accent */
.bars { display: flex; height: 4px; width: 100%; }
.bars span { flex: 1; }
.bars span:nth-child(1) { background: #c0c0c0; }
.bars span:nth-child(2) { background: #c0c000; }
.bars span:nth-child(3) { background: #00c0c0; }
.bars span:nth-child(4) { background: #00c000; }
.bars span:nth-child(5) { background: #c000c0; }
.bars span:nth-child(6) { background: #c00000; }
.bars span:nth-child(7) { background: #0000c0; }

/* ---------- Buttons ---------- */
.btn {
  --b: var(--line-2);
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 22px; border-radius: 999px; border: 1px solid var(--b);
  font: 500 15px/1 var(--font-sans); text-decoration: none; color: var(--text);
  background: rgba(255,255,255,.03); cursor: pointer;
  transition: background .2s, border-color .2s, transform .2s, color .2s;
}
.btn:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.3); }
.btn--primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
.btn--primary:hover { background: #86e8de; border-color: #86e8de; }
.btn svg { width: 16px; height: 16px; flex: none; }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

.appstore { display: inline-block; line-height: 0; }
.appstore img { height: 48px; width: auto; }

/* ---------- Header ---------- */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  transition: background .3s, border-color .3s, backdrop-filter .3s;
  border-bottom: 1px solid transparent;
}
.site-header.is-solid, .site-header.is-open {
  background: rgba(7, 8, 10, .82);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  backdrop-filter: saturate(140%) blur(14px);
  border-bottom-color: var(--line);
}
.nav { display: flex; align-items: center; justify-content: space-between; height: 72px; gap: 24px; }
.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.brand img { height: 22px; width: auto; }
.nav-links { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
.nav-links a {
  display: block; padding: 8px 14px; border-radius: 999px; text-decoration: none;
  font-size: 14.5px; color: var(--muted); transition: color .2s, background .2s;
}
.nav-links a:hover, .nav-links a[aria-current="page"], .nav-links a[aria-current="true"] { color: var(--text); background: rgba(255,255,255,.06); }
.nav-links .nav-cta a { color: var(--accent-ink); background: var(--accent); font-weight: 600; margin-left: 8px; }
.nav-links .nav-cta a:hover { background: #86e8de; }
.nav-toggle { display: none; background: none; border: 0; color: var(--text); padding: 8px; margin-right: -8px; cursor: pointer; }
.nav-toggle svg { width: 26px; height: 26px; }

@media (max-width: 880px) {
  .nav-toggle { display: inline-flex; }
  .nav-links {
    position: fixed; inset: 72px 0 auto 0; flex-direction: column; align-items: stretch; gap: 0;
    padding: 8px var(--gutter) 24px; background: rgba(7,8,10,.97); border-bottom: 1px solid var(--line);
    transform: translateY(-8px); opacity: 0; visibility: hidden; transition: opacity .2s, transform .2s, visibility .2s;
    /* Landscape phones: the panel scrolls inside the viewport instead of running off it (vh line is the fallback) */
    max-height: calc(100vh - 72px); max-height: calc(100dvh - 72px); overflow-y: auto; overscroll-behavior: contain;
  }
  .is-open .nav-links { opacity: 1; transform: none; visibility: visible; }
  .nav-links a { padding: 14px 4px; border-radius: 0; font-size: 18px; border-bottom: 1px solid var(--line); }
  .nav-links a:hover, .nav-links a[aria-current="page"], .nav-links a[aria-current="true"] { background: none; }
  .nav-links .nav-cta a { margin: 16px 0 0; text-align: center; border-radius: 999px; border: 0; }
}

/* ---------- Hero ---------- */
.hero { position: relative; min-height: 100vh; min-height: 100svh; display: flex; align-items: flex-end; overflow: hidden; isolation: isolate; }
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media video, .hero__media img { width: 100%; height: 100%; object-fit: cover; }
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(7,8,10,.55) 0%, rgba(7,8,10,.15) 35%, rgba(7,8,10,.7) 75%, var(--bg) 100%),
    linear-gradient(90deg, rgba(7,8,10,.75) 0%, rgba(7,8,10,0) 65%);
}
.hero__inner { padding-top: 140px; padding-bottom: clamp(48px, 8vw, 96px); width: 100%; }
.hero h1 { max-width: 14ch; margin-bottom: 24px; }
.hero h1 em { font-style: normal; color: var(--accent); }
.hero .lede { color: #c9cfd6; margin-bottom: 36px; }
.hero__hud {
  display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: clamp(40px, 6vw, 72px); padding-top: 20px;
  border-top: 1px solid var(--line-2); font: 500 12px/1.4 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.hero__hud b { color: var(--text); font-weight: 500; }
.tally { display: inline-flex; align-items: center; gap: 8px; color: var(--text); }
.tally::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--tally); box-shadow: 0 0 10px var(--tally); animation: tally-on 1.2s .6s both; }
@keyframes tally-on { from { opacity: .2; box-shadow: none; } }   /* lights once on load, then holds steady */
/* Hero video pause/play: same mono type as the HUD, at the right end of its line, as a 44px-tall target whose
   negative margins keep the line 16.8px. site.js unhides it only when the video autoplays.
   Desktop and phones pin it to the right end of the HUD's first line (top = 20px padding + half line − 22px),
   so the items' wrapping can never push it onto a row of its own; desktop reserves its width on that line
   (56px button + 18px gap). Tablets keep it in the flow, at the right end of the last row. */
.hero__hud { position: relative; }
.hero__hud .hud-btn { min-height: 44px; margin: -14px 0 -14px auto; }
@media (min-width: 981px), (max-width: 560px) {
  .hero__hud .hud-btn { position: absolute; right: 0; top: calc(20px + .7em - 22px); margin: 0; }
}
@media (min-width: 981px) { .hero__hud:has(.hud-btn:not([hidden])) { padding-right: 74px; } }
/* Phones: the stacked tools list always starts row 2, so row 1 (Program, TC) leaves room for the button.
   Without this, at 511–560px the tools fit on row 1 and run under it. */
@media (max-width: 560px) { .hero__hud:has(.hud-btn:not([hidden])) .hud-tools { flex-basis: 100%; } }
.hud-btn {
  display: inline-flex; align-items: center; gap: 8px; min-height: 24px; margin: -4px 0 -4px auto; padding: 0;
  background: none; border: 0; font: inherit; letter-spacing: inherit; text-transform: inherit; color: var(--muted); cursor: pointer; transition: color .2s;
}
.hud-btn:hover { color: var(--text); }
.hud-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 2px; }
.hud-btn::before { content: ""; width: 7px; height: 8px; box-sizing: border-box; border-inline: 2px solid currentColor; }   /* pause bars */
.hud-btn[data-state="paused"]::before { border: 0; background: currentColor; clip-path: polygon(0 0, 100% 50%, 0 100%); }   /* play triangle */
.hud-btn[hidden] { display: none; }

.page-hero { padding: 160px 0 clamp(48px, 7vw, 88px); position: relative; overflow: hidden; }
.page-hero h1 { font-size: clamp(2.4rem, 6vw, 4.6rem); max-width: 18ch; }
.page-hero .lede { margin-bottom: 32px; }
.page-hero__glow { position: absolute; inset: -20% -10% auto auto; width: 60vw; height: 60vw; max-width: 800px; max-height: 800px; z-index: -1; background: radial-gradient(closest-side, rgba(70,214,200,.16), transparent); pointer-events: none; }
.app-hero { display: grid; grid-template-columns: 1.1fr .9fr; gap: clamp(32px, 5vw, 72px); align-items: center; }
.app-hero__icon { width: 88px; height: 88px; border-radius: 22px; margin-bottom: 24px; box-shadow: 0 10px 40px rgba(0,0,0,.5); }
.app-hero__shot img { margin-inline: auto; max-height: 640px; width: auto; filter: drop-shadow(0 30px 60px rgba(0,0,0,.6)); }
.meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 28px; padding: 0; list-style: none; }
.chip { font: 500 12px/1 var(--font-mono); letter-spacing: .04em; padding: 8px 12px; border-radius: 999px; border: 1px solid var(--line-2); color: var(--muted); }
.chip--accent { color: var(--accent); border-color: rgba(70,214,200,.4); }
@media (max-width: 880px) { .app-hero { grid-template-columns: 1fr; } .app-hero__shot img { max-height: 480px; } }

/* ---------- Grids & cards ---------- */
.grid { display: grid; gap: clamp(14px, 2vw, 22px); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 980px) { .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; } }

.card {
  position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(22px, 2.6vw, 30px); transition: border-color .25s, transform .25s, background .25s;
}
.card h3 { margin-bottom: 10px; }
.card p { color: var(--muted); margin: 0; font-size: 15.5px; }
.card__num { font: 500 12px/1 var(--font-mono); color: var(--dim); letter-spacing: .1em; margin-bottom: 28px; display: block; }
.card__icon { width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; background: rgba(70,214,200,.1); color: var(--accent); margin-bottom: 22px; }
.card__icon svg { width: 22px; height: 22px; }
a.card { text-decoration: none; display: block; }
a.card:hover { border-color: var(--line-2); background: var(--surface-2); }
.card ul { margin: 14px 0 0; padding: 0; list-style: none; color: var(--muted); font-size: 15px; }
.card li { padding: 7px 0; border-top: 1px solid var(--line); }
.card li:first-child { border-top: 0; }

.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 18px; }
.tag { font: 500 11.5px/1 var(--font-mono); padding: 6px 9px; border-radius: 6px; background: rgba(255,255,255,.05); color: var(--muted); }

/* Services list */
.services { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--line); border-left: 1px solid var(--line); }
.service { padding: clamp(24px, 3vw, 36px); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); transition: background .25s; }
.service:hover { background: rgba(255,255,255,.02); }
.service h3 { margin: 18px 0 10px; }
.service p { color: var(--muted); font-size: 15.5px; margin: 0; }
.service--lead { background: linear-gradient(160deg, rgba(70,214,200,.09), transparent 60%); }
@media (max-width: 980px) { .services { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .services { grid-template-columns: 1fr; grid-auto-rows: auto; } }

/* ---------- Work gallery ---------- */
.gallery { display: grid; grid-template-columns: repeat(12, 1fr); gap: clamp(10px, 1.4vw, 16px); }
.shot { position: relative; margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--surface); grid-column: span 4; aspect-ratio: 4 / 3; }
.shot--wide { grid-column: span 8; aspect-ratio: 8 / 3; }
.shot--full { grid-column: span 12; aspect-ratio: 21 / 8; }
.shot img, .shot video { width: 100%; height: 100%; object-fit: cover; transition: transform .8s cubic-bezier(.2,.7,.2,1); }
.shot figcaption {
  position: absolute; inset: auto 0 0 0; padding: 40px 18px 16px;
  background: linear-gradient(transparent, rgba(0,0,0,.8));
  font: 500 12px/1.4 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: #d7dce2;
}
@media (max-width: 880px) { .shot, .shot--wide { grid-column: span 6; aspect-ratio: 4 / 3; } .shot--full { grid-column: span 12; aspect-ratio: 16/9; } }
@media (max-width: 560px) { .shot, .shot--wide { grid-column: span 12; aspect-ratio: 16 / 10; } }

/* ---------- Feature (split) ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 88px); align-items: center; }
.split--wide-media { grid-template-columns: .85fr 1.15fr; }
.split--flip > :first-child { order: 2; }
.split h2 { margin-bottom: 20px; }
.split .lede { margin-bottom: 28px; }
@media (max-width: 880px) { .split, .split--wide-media { grid-template-columns: 1fr; } .split--flip > :first-child { order: 0; } }

.media-frame { position: relative; border-radius: var(--radius-lg); overflow: hidden; border: 1px solid var(--line-2); background: #000; box-shadow: 0 40px 100px -30px rgba(0,0,0,.8); }
.media-frame video, .media-frame img { width: 100%; }
.media-frame__bar { display: flex; justify-content: space-between; gap: 12px; padding: 10px 14px; font: 500 11px/1 var(--font-mono); letter-spacing: .06em; color: var(--dim); border-bottom: 1px solid var(--line); background: #0b0d10; text-transform: uppercase; white-space: nowrap; overflow: hidden; }

.checklist { list-style: none; padding: 0; margin: 0 0 32px; display: grid; gap: 12px; }
.checklist li { display: grid; grid-template-columns: 22px 1fr; gap: 12px; color: var(--muted); }
.checklist li::before { content: ""; width: 18px; height: 18px; margin-top: 4px; border-radius: 5px; background: rgba(70,214,200,.14) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2346d6c8' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/12px no-repeat; }
.checklist strong { color: var(--text); font-weight: 600; }

/* Stats */
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-block: 1px solid var(--line); }
.stat { padding: 28px clamp(12px, 2vw, 24px); border-left: 1px solid var(--line); }
.stat:first-child { border-left: 0; padding-left: 0; }
.stat b { display: block; font: 600 clamp(1.8rem, 3.4vw, 2.8rem)/1 var(--font-display); letter-spacing: -0.03em; margin-bottom: 10px; }
.stat span { font-size: 14px; color: var(--muted); }
@media (max-width: 760px) { .stats { grid-template-columns: repeat(2, 1fr); } .stat:nth-child(3) { border-left: 0; padding-left: 0; } .stat { border-top: 1px solid var(--line); } .stat:nth-child(-n+2) { border-top: 0; } }

/* ---------- App cards ---------- */
.app-card, a.app-card { display: flex; flex-direction: column; gap: 0; padding: 0; overflow: hidden; }
.app-card__top { padding: 28px 28px 0; display: flex; gap: 16px; align-items: center; }
.app-card__top img { width: 64px; height: 64px; border-radius: 16px; flex: none; }
.app-card__top h3 { margin: 0 0 4px; }
.app-card__top small { font: 500 12px/1 var(--font-mono); color: var(--dim); letter-spacing: .04em; }
.app-card__body { padding: 20px 28px 28px; flex: 1; display: flex; flex-direction: column; }
.app-card__body p { flex: 1; }
.app-card__link { margin-top: 22px; font: 500 14px/1 var(--font-sans); color: var(--accent); display: inline-flex; align-items: center; gap: 8px; }

/* Screenshot rail */
.rail { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(220px, 260px); gap: 18px; overflow-x: auto; padding: 4px var(--gutter) 24px; margin: 0 calc(var(--gutter) * -1); scroll-snap-type: x mandatory; scrollbar-width: thin; }
.rail img { border-radius: 18px; scroll-snap-align: start; }
@media (min-width: 1280px) { .rail { margin: 0; padding-inline: 0; } }

/* Lab */
.lab-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: clamp(14px, 2vw, 22px); }
.lab-feature { padding: 0; overflow: hidden; display: grid; grid-template-rows: auto 1fr; }
.lab-feature img { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
.lab-feature .lab-feature__body { padding: clamp(22px, 2.6vw, 30px); }
.lab-side { display: grid; gap: clamp(14px, 2vw, 22px); grid-auto-rows: 1fr; }
@media (max-width: 880px) { .lab-grid { grid-template-columns: 1fr; } }

/* ---------- Tables (spec sheets) ---------- */
.spec { width: 100%; border-collapse: collapse; font-size: 15px; }
.spec th, .spec td { text-align: left; padding: 14px 16px; border-bottom: 1px solid var(--line); vertical-align: top; }
.spec th { font: 500 12px/1.3 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--dim); white-space: nowrap; }
.spec td { color: var(--muted); }
.spec td:first-child { color: var(--text); font-weight: 500; }
.table-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }

/* ---------- Contact ---------- */
.contact-grid { display: grid; grid-template-columns: .9fr 1.1fr; gap: clamp(32px, 6vw, 88px); align-items: start; }
@media (max-width: 880px) { .contact-grid { grid-template-columns: 1fr; } }
.form { display: grid; gap: 16px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(22px, 3vw, 36px); }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 560px) { .form-row { grid-template-columns: 1fr; } }
.field { display: grid; gap: 8px; }
.field label { font: 500 12px/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.field input, .field select, .field textarea {
  width: 100%; font: 400 16px/1.4 var(--font-sans); color: var(--text);
  background: var(--bg); border: 1px solid rgba(255,255,255,.36); border-radius: 10px; padding: 13px 14px;   /* 3.2:1 on --bg */
  transition: border-color .2s, box-shadow .2s;
}
.field select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa2ad' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; background-size: 18px; padding-right: 40px; }
.field textarea { min-height: 160px; resize: vertical; }
.field input[type="date"] { color-scheme: dark; height: 50px; }   /* same 50 px as the other controls */
.field input[type="date"]::-webkit-calendar-picker-indicator { opacity: .7; cursor: pointer; }
.field .opt { text-transform: none; letter-spacing: 0; color: var(--dim); }
.form-regarding { margin: 0; font: 500 13px/1.4 var(--font-mono); color: var(--muted); }
.form-regarding b { color: var(--text); font-weight: 500; }
.h-captcha { min-height: 78px; }
.form-row[hidden], .form-regarding[hidden] { display: none; }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(70,214,200,.18); }
.hp { position: absolute !important; left: -10000px !important; width: 1px; height: 1px; overflow: hidden; }
.form-status { font-size: 15px; min-height: 1.4em; margin: 0; }
.form-status.is-ok { color: var(--ok); }
.form-status.is-err { color: #ff8a80; }
.form-flash:not(:target) { display: none; }   /* no-JS result notes, shown via contact.html#form-sent / #form-error */
/* Required marker: accent asterisk in the label, explained once at the top of the form */
.req { color: var(--accent); }
.form-legend { margin: 0; font: 500 12px/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); justify-self: end; }
.contact-list { list-style: none; padding: 0; margin: 28px 0 0; display: grid; gap: 2px; }
.contact-list li { display: flex; justify-content: space-between; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--line); font-size: 15.5px; }
.contact-list span { color: var(--dim); font: 500 12px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; }
.contact-list a { text-decoration: none; }
.contact-list a:hover { color: var(--accent); }

/* CTA band */
.cta-band { position: relative; overflow: hidden; border-radius: var(--radius-lg); border: 1px solid var(--line-2); padding: clamp(36px, 6vw, 72px); background: radial-gradient(120% 140% at 100% 0%, rgba(70,214,200,.16), transparent 55%), var(--surface); }
.cta-band h2 { max-width: 18ch; }
.cta-band .lede { margin-bottom: 28px; }

/* ---------- Prose (legal) ---------- */
.prose { max-width: 760px; }
.prose h2 { font-size: 1.4rem; margin: 2.2em 0 .6em; }
.prose p, .prose li { color: var(--muted); }
.prose a { color: var(--accent); }
.prose h3 { margin-top: 1.6em; }

/* ---------- Footer ---------- */
.site-footer { border-top: 1px solid var(--line); padding: 64px 0 40px; background: var(--bg); }
.footer-grid { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 32px; }
.footer-grid h4, .footer-grid .footer-h { font: 500 12px/1 var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--dim); margin: 0 0 18px; }
.footer-grid ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.footer-grid a { color: var(--muted); text-decoration: none; font-size: 15px; }
.footer-grid a:hover { color: var(--text); }
.footer-brand img { height: 22px; width: auto; margin-bottom: 16px; }
.footer-brand p { color: var(--muted); font-size: 15px; max-width: 34ch; }
.socials { display: flex; gap: 8px; margin-top: 20px; }
.socials a { width: 40px; height: 40px; display: grid; place-items: center; border-radius: 10px; border: 1px solid var(--line); color: var(--muted); }
.socials a:hover { color: var(--text); border-color: var(--line-2); }
.socials svg { width: 18px; height: 18px; }
.footer-bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; margin-top: 56px; padding-top: 24px; border-top: 1px solid var(--line); font: 500 12px/1.4 var(--font-mono); color: var(--dim); letter-spacing: .04em; }
.footer-bottom a { color: var(--dim); text-decoration: none; }
.footer-bottom a:hover { color: var(--text); }
@media (max-width: 880px) { .footer-grid { grid-template-columns: 1fr 1fr; } .footer-brand { grid-column: 1 / -1; } }

/* ---------- Reveal ---------- */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .8s cubic-bezier(.2,.7,.2,1), transform .8s cubic-bezier(.2,.7,.2,1); }
.reveal.is-in { opacity: 1; transform: none; }
.no-js .reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ---------- Fixes from screenshot review ---------- */
/* Grid/flex children may shrink below their content (stops nowrap bars widening the page on phones) */
.split > *, .grid > *, .app-hero > *, .contact-grid > *, .lab-grid > * { min-width: 0; }
.media-frame__bar span { overflow: hidden; text-overflow: ellipsis; }
.media-frame__bar span + span { flex: none; }
.media-frame__bar b { font-weight: 500; color: var(--muted); font-variant-numeric: tabular-nums; }
.media-frame__bar .tc { display: inline-flex; align-items: center; gap: 14px; }
@media (max-width: 560px) { .media-frame__bar span + span { display: none; } }

/* Brand mark a touch larger */
.brand img { height: 30px; }

/* The hero footage has a black pillar on its left edge — push it out of frame */
.hero__media video { transform: scale(1.12); transform-origin: 72% 50%; }
@media (max-width: 880px) {
  .hero::before { background: linear-gradient(180deg, rgba(7,8,10,.5) 0%, rgba(7,8,10,.45) 40%, rgba(7,8,10,.85) 75%, var(--bg) 100%); }
}

/* Gallery rows share one height on desktop so wide and square tiles line up exactly */
@media (min-width: 881px) {
  .gallery { grid-auto-rows: clamp(220px, 21vw, 290px); }
  .gallery .shot, .gallery .shot--wide { aspect-ratio: auto; }
}
@media (max-width: 880px) and (min-width: 561px) {
  .gallery .shot:last-child:nth-child(odd) { grid-column: span 12; aspect-ratio: 21 / 9; }
}

/* ---------- Effects (subtle, one-shot or hover only) ---------- */
/* Hero: staggered fade-up on load */
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.hero__inner > *, .page-hero .wrap > * , .page-hero .app-hero > div > * { animation: rise .9s cubic-bezier(.2,.7,.2,1) both; }
.hero__inner > :nth-child(2), .page-hero .wrap > :nth-child(2), .page-hero .app-hero > div > :nth-child(2) { animation-delay: .08s; }
.hero__inner > :nth-child(3), .page-hero .wrap > :nth-child(3), .page-hero .app-hero > div > :nth-child(3) { animation-delay: .16s; }
.hero__inner > :nth-child(4), .page-hero .wrap > :nth-child(4), .page-hero .app-hero > div > :nth-child(4) { animation-delay: .24s; }
.hero__inner > :nth-child(5), .page-hero .wrap > :nth-child(5), .page-hero .app-hero > div > :nth-child(5) { animation-delay: .32s; }
.hero__inner > :nth-child(n+6), .page-hero .app-hero > div > :nth-child(n+6) { animation-delay: .4s; }
.hero__media { animation: fadein 1.6s ease both; }
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }

/* Eyebrow rule draws in when its section reveals */
.reveal .eyebrow::before { transform-origin: left; transform: scaleX(0); transition: transform .9s .2s cubic-bezier(.2,.7,.2,1); }
.reveal.is-in .eyebrow::before, .no-js .reveal .eyebrow::before { transform: none; }

/* Hover motion (lifts, zooms, marks closing in) only where a real pointer hovers: on touch screens a tap
   would leave the card lifted / image zoomed until the next tap elsewhere. Colour and border changes stay global. */
@media (hover: hover) and (pointer: fine) {
  a.card:hover { transform: translateY(-3px); }
  .shot:hover img { transform: scale(1.04); }
  .shot:hover figcaption { transform: translateY(-4px); }
  .media-frame:hover::after { opacity: 1; inset: 10px; }
  .media-frame:has(.media-frame__bar):hover::after { top: 43px; }
  .shot:hover::after { opacity: .9; inset: 12px; }
  .services .service:hover { transform: translateY(-3px); box-shadow: 0 24px 60px -28px rgba(var(--c), .45); }
  .services .service:hover .service__media img { transform: scale(1.04); }
}

/* Cursor spotlight on cards (pointer devices only; vars set in site.js) */
@media (hover: hover) and (pointer: fine) {
  .card, .service { overflow: hidden; }
  .card::after, .service::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .35s;
    background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 50%), rgba(70,214,200,.09), transparent 45%);
  }
  .card:hover::after, .service:hover::after { opacity: 1; }
  .service { position: relative; }
}

/* Gallery: caption slides up a touch on hover */
.shot figcaption { transition: transform .5s cubic-bezier(.2,.7,.2,1), color .3s; }
.shot:hover figcaption { color: #fff; }

/* Media frames lift gently on hover */
.media-frame { transition: border-color .4s, box-shadow .4s; }
.media-frame:hover { border-color: rgba(70,214,200,.35); }

/* =====================================================================
   Identity layer
   Palette sampled from the hand mark (teal #48A8A8, ocean #0078A8),
   lifted for a dark stage, plus violet from the projection work.
   Motifs: alignment grid, registration marks, SMPTE strip.
   ===================================================================== */
:root {
  --accent: #4fd8c9;
  --accent-ink: #00201c;
  --blue: #2f8fff;
  --violet: #8b6cff;
  --grad: linear-gradient(100deg, #4fd8c9 0%, #2f8fff 55%, #8b6cff 100%);
  --grad-soft: linear-gradient(100deg, rgba(79,216,201,.16), rgba(47,143,255,.12) 55%, rgba(139,108,255,.14));
  --grid-line: rgba(255,255,255,.035);
}

/* Gradient type for the one emphasised phrase per hero */
.hero h1 em, .grad-text {
  background: var(--grad); -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}

/* Primary button: gradient fill, crisp 1px inner highlight */
.btn--primary {
  background: var(--grad); border: 0; color: #031312;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 8px 24px -10px rgba(47,143,255,.6);
  padding: 14px 23px;  /* matches 13px + 1px border of .btn so heights align */
}
.btn--primary:hover { background: var(--grad); filter: brightness(1.08) saturate(1.05); }
.nav-links .nav-cta a { background: var(--grad); color: #031312; }
.nav-links .nav-cta a:hover { background: var(--grad); filter: brightness(1.08); }

.eyebrow { color: var(--accent); }
.eyebrow::before { background: var(--grad); height: 1px; width: 24px; }

/* Alignment grid behind page headers — 24px cells, faded out with a mask */
.page-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -2; pointer-events: none;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 24px 24px; background-position: -1px -1px;
  -webkit-mask-image: radial-gradient(ellipse 70% 80% at 75% 20%, #000 20%, transparent 75%);
          mask-image: radial-gradient(ellipse 70% 80% at 75% 20%, #000 20%, transparent 75%);
}
.page-hero { isolation: isolate; }
.page-hero__glow { background: radial-gradient(closest-side, rgba(47,143,255,.18), rgba(139,108,255,.08) 50%, transparent); }

/* Hero video: a cool colour wash to unify mixed footage with the palette */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; mix-blend-mode: soft-light;
  background: linear-gradient(120deg, rgba(79,216,201,.35), rgba(47,143,255,.15) 50%, rgba(139,108,255,.35));
}

/* Asymmetric section glows — each section leans to a different side */
#services { background: radial-gradient(60% 50% at 100% 0%, rgba(47,143,255,.07), transparent 70%); }
#work { background: radial-gradient(55% 45% at 0% 100%, rgba(139,108,255,.08), transparent 70%), var(--bg-2); }
#previz { background: radial-gradient(50% 60% at 100% 50%, rgba(79,216,201,.06), transparent 70%); }
#apps { background: radial-gradient(50% 50% at 0% 0%, rgba(79,216,201,.06), transparent 70%), var(--bg-2); }
#lab { background: radial-gradient(45% 55% at 0% 60%, rgba(139,108,255,.07), transparent 70%); }

/* Registration marks: projection-alignment corners on framed media */
.media-frame { position: relative; }
/* Written out as longhands without custom properties: Safari (27) renders the old one-line
   background shorthand with var() sizes as a solid grey layer over video. */
.media-frame::after, .shot::after {
  content: ""; position: absolute; inset: 12px; pointer-events: none; z-index: 2;
  background-image: linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75)),
    linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75)),
    linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75)),
    linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75)),
    linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75)),
    linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75)),
    linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75)),
    linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.75));
  background-size: 14px 1px, 1px 14px, 14px 1px, 1px 14px, 14px 1px, 1px 14px, 14px 1px, 1px 14px;
  background-position: left top, left top, right top, right top, left bottom, left bottom, right bottom, right bottom;
  background-repeat: no-repeat;
  opacity: .55; transition: opacity .4s, inset .5s cubic-bezier(.2,.7,.2,1);
}
.media-frame:has(.media-frame__bar)::after { top: 45px; }
.shot::after { opacity: 0; inset: 18px; }

/* Card hover border picks up the gradient */
a.card:hover { border-color: transparent; background:
  linear-gradient(var(--surface-2), var(--surface-2)) padding-box,
  var(--grad) border-box; border: 1px solid transparent; }

/* Services lead cell and CTA band use the brand gradient softly */
.service--lead { background: linear-gradient(160deg, rgba(79,216,201,.10), rgba(47,143,255,.04) 45%, transparent 70%); }
.cta-band {
  background:
    radial-gradient(90% 120% at 100% 0%, rgba(47,143,255,.16), transparent 55%),
    radial-gradient(70% 90% at 0% 100%, rgba(139,108,255,.12), transparent 60%),
    var(--surface);
}
.cta-band::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(var(--grid-line) 1px, transparent 1px), linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: linear-gradient(90deg, transparent 30%, #000); mask-image: linear-gradient(90deg, transparent 30%, #000);
}
.cta-band > * { position: relative; }

/* Checklist ticks and stat numerals in the palette */
.stat b { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }
.tally::before { background: #ff3b30; }

/* Footer strip sits flush, 3px like a scope graticule line */
.site-footer > .bars { height: 3px; }

/* Selection + focus in palette */
::selection { background: var(--blue); color: #fff; }
:focus-visible { outline-color: var(--blue); }

/* One control height everywhere: buttons, CTA pill and App Store badge are all 44px */
.btn { height: 44px; padding: 0 22px; line-height: 1; }
.btn--primary { padding: 0 23px; }
.btn-row { align-items: center; }
.appstore img { height: 44px; }
.nav-links .nav-cta a { height: 36px; display: inline-flex; align-items: center; padding: 0 16px; }

/* ---------- Precision pass ---------- */
/* Hero wash fades out before the section edge (no hard line) */
.hero::after { -webkit-mask-image: linear-gradient(#000 55%, transparent 92%); mask-image: linear-gradient(#000 55%, transparent 92%); }

/* No registration marks over native video controls */
.media-frame:has(video[controls])::after { display: none; }

/* Stats: tighter captions, numerals and captions share one left edge per column */
.stat b { margin-bottom: 12px; }
.stat span { display: block; line-height: 1.5; max-width: 26ch; }

/* App heroes: compact header row so the text column matches the device shot */
.app-hero h1 { font-size: clamp(2.4rem, 4.6vw, 3.9rem); }
.app-hero__icon { width: 72px; height: 72px; border-radius: 18px; margin-bottom: 28px; }
.app-hero .meta-row { flex-wrap: wrap; }

/* Screenshot rails: on wide screens the row spans the full content column, edge to edge */
@media (min-width: 1100px) {
  .rail { grid-auto-flow: row; grid-template-columns: repeat(auto-fit, 260px); justify-content: space-between; overflow: visible; margin: 0; padding: 0 0 8px; }
}

/* Contact: list labels and values share a baseline */
.contact-list li { align-items: baseline; }

/* Eyebrows are block-level so their box top is the column top (no inherited line-box offset) */
.eyebrow { display: flex; width: fit-content; }

/* App hero: the device shot takes exactly the text column's height, so top and bottom edges align */
@media (min-width: 881px) {
  .app-hero { align-items: stretch; }
  .app-hero__shot { position: relative; min-height: 420px; }
  .app-hero__shot img { position: absolute; inset: 0; width: 100%; height: 100%; max-height: none; object-fit: contain; object-position: center; }
}

/* Rail screenshots share one exact box regardless of source size */
.rail img { width: 100%; aspect-ratio: 1 / 2.1; object-fit: contain; }

/* Splits whose columns should share a top edge instead of a centre line */
.split--top { align-items: start; }
@media (min-width: 881px) { .split--top > :first-child { position: sticky; top: 104px; } }
/* Long copy beside a short image: the image waits at the top while its text scrolls past */
.split--sticky-media { align-items: start; }
@media (min-width: 881px) { .split--sticky-media > :last-child { position: sticky; top: 104px; } }

/* Poster-format images (4:5) */
.shot--poster { aspect-ratio: 4 / 5; }
@media (max-width: 880px) { .shot--poster { grid-column: auto; aspect-ratio: 4 / 5; } }

/* Device mockups: no frame; black canvas melts into the page */
.mockup img { width: 100%; mix-blend-mode: lighten; filter: drop-shadow(0 30px 60px rgba(0,0,0,.55)); }

/* .shot spans only apply inside the 12-col gallery */
.grid > .shot { grid-column: auto; }

/* Small mono labels meet WCAG AA contrast (4.5:1) on every surface */
:root { --dim: #8a929d; }

/* Mobile menu: links share the logo's left edge; full-width CTA; opaque panel */
@media (max-width: 880px) {
  .nav-links { background: var(--bg); }
  .nav-links a { padding: 14px 0; }
  .nav-links .nav-cta a { display: flex; justify-content: center; height: 48px; margin-top: 20px; padding: 0; }
}

/* Placeholder frame for media awaiting client-safe renders */
.placeholder { aspect-ratio: 16 / 9; display: grid; place-items: center; text-align: center;
  background:
    linear-gradient(var(--grid-line) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px) 0 0 / 24px 24px,
    radial-gradient(70% 90% at 50% 50%, rgba(47,143,255,.10), transparent 70%),
    #0a0c10; }
.placeholder::before { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 4px;
  background: linear-gradient(90deg, #c0c0c0 0 14.28%, #c0c000 0 28.57%, #00c0c0 0 42.85%, #00c000 0 57.14%, #c000c0 0 71.42%, #c00000 0 85.71%, #0000c0 0); opacity: .7; }
.placeholder__inner { display: grid; gap: 10px; justify-items: center; padding: 24px; }
.placeholder__tag { font: 500 11px/1 var(--font-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--accent); padding: 7px 10px; border: 1px solid rgba(79,216,201,.35); border-radius: 999px; }
.placeholder__label { font: 600 clamp(1rem, 1.6vw, 1.2rem)/1.3 var(--font-display); color: var(--text); }
.placeholder__note { font-size: 14px; color: var(--dim); }

/* Mirrored splits keep the media column the same width as unmirrored ones */
@media (min-width: 881px) { .split--wide-media.split--flip { grid-template-columns: 1.15fr .85fr; } }

/* Placeholders measure 16:9 on the content box, exactly like an image inside a 1px frame */
.placeholder { box-sizing: content-box; }

.media-frame--plain::after { display: none; }

/* ---------- Carousels ----------
   [data-carousel] tracks swipe with scroll-snap. .rail--wide is a carousel at every size;
   galleries and poster grids become carousels on phones only. Dots + arrows are added by site.js
   and hidden whenever the track isn't actually scrollable. */
[data-carousel] { position: relative; scrollbar-width: none; }
[data-carousel]::-webkit-scrollbar { display: none; }

.rail--wide { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; padding: 0; margin: 0; }
.rail--wide > figure { flex: 0 0 min(420px, 82%); margin: 0; scroll-snap-align: start; }
.rail--wide img { width: 100%; height: auto; aspect-ratio: 4 / 3; border-radius: 12px; border: 1px solid var(--line-2); background: #000; }
.rail--wide figcaption { margin-top: 12px; font: 500 12px/1.4 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.rail--wide figcaption b { color: var(--accent); font-weight: 500; margin-right: 8px; }

@media (max-width: 560px) {
  .gallery[data-carousel], .grid[data-carousel] {
    display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
    margin: 0 calc(var(--gutter) * -1); padding: 0 var(--gutter); scroll-padding: 0 var(--gutter);
  }
  .gallery[data-carousel] > *, .grid[data-carousel] > * { flex: 0 0 86%; scroll-snap-align: start; }
  .gallery[data-carousel] > .shot { aspect-ratio: 4 / 3; }
  .rail img { scroll-snap-align: start; }
}
/* Screenshot rails scroll edge to edge up to 1099px: snap the first phone to the gutter, not the screen edge */
.rail { scroll-padding: 0 var(--gutter); }

.carousel-nav { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 20px; }
.carousel-nav[hidden] { display: none; }
.carousel-dots { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; max-width: 70%; }
.carousel-dots button { width: 6px; height: 6px; padding: 0; border: 0; border-radius: 999px; background: rgba(255,255,255,.38); cursor: pointer; transition: width .3s, background .3s; }
.carousel-dots button[aria-current="true"] { width: 20px; background: var(--grad); }
.carousel-btn { width: 36px; height: 36px; flex: none; display: grid; place-items: center; border-radius: 999px; border: 1px solid var(--line-2); background: rgba(255,255,255,.03); color: var(--text); cursor: pointer; }
.carousel-btn:hover { border-color: rgba(255,255,255,.35); }
.carousel-btn:disabled { opacity: .3; cursor: default; }
.carousel-btn svg { width: 16px; height: 16px; }
@media (hover: none) { .carousel-btn { display: none; } }

@media (max-width: 560px) { .rail--wide { margin: 0 calc(var(--gutter) * -1); padding: 0 var(--gutter); scroll-padding: 0 var(--gutter); } }

/* Carousels scroll sideways only — never up and down inside the track */
.rail, .rail--wide { overflow-y: hidden; touch-action: pan-x pan-y; }
@media (max-width: 560px) { [data-carousel] { overflow-y: hidden; touch-action: pan-x pan-y; } }
/* Items inside a carousel don't run their own reveal (off-screen items would sit 18px low and fade in late) */
@media (max-width: 560px) { [data-carousel] > .reveal { opacity: 1; transform: none; transition: none; } }
.rail--wide > .reveal, .rail > .reveal { opacity: 1; transform: none; }

/* App hero, stacked variant (landscape device): headline left, details right, device full width below */
.app-hero--stacked { grid-template-columns: 1fr; gap: clamp(40px, 5vw, 64px); }
.app-hero__head { display: grid; grid-template-columns: 1.15fr .85fr; gap: clamp(32px, 6vw, 88px); align-items: end; }
.app-hero__head h1 { margin-bottom: 0; }
.app-hero__head .lede { margin-bottom: 24px; }
.app-hero__head .meta-row { margin-bottom: 24px; }
@media (max-width: 880px) { .app-hero__head { grid-template-columns: 1fr; gap: 24px; } }
.page-hero .app-hero__head > div > * { animation: rise .9s cubic-bezier(.2,.7,.2,1) both; }
.page-hero .app-hero__head > div:last-child > * { animation-delay: .16s; }
/* Landscape device spans the content column; its black canvas melts into the page */
@media (min-width: 881px) { .app-hero--stacked { align-items: start; } .app-hero__shot--landscape { min-height: 0; } .app-hero__shot--landscape img { position: static; height: auto; } }
.app-hero__shot--landscape img { width: 100%; height: auto; max-height: none; filter: drop-shadow(0 40px 80px rgba(0,0,0,.6)); }
.app-hero__shot--landscape picture { display: block; }
.app-hero__head .appstore { display: block; width: fit-content; }

/* ---------- App wordmarks ----------
   Each logo image has different padding (signal icon above Switcher Pro, colour bar under GenR8).
   --k is the fraction of the image height the letters occupy, --dy how far the letter block's centre
   sits from the image centre (as a fraction of letter height). Result: identical letter height and the
   letters centred on the app icon, regardless of the artwork's padding. */
.app-brand { display: flex; align-items: center; gap: 20px; margin-bottom: 28px; }
.app-brand .app-hero__icon { margin: 0; }
.app-brand h2 { margin: 0; line-height: 0; }
.wordmark { --cap: 30px; display: block; width: auto; height: calc(var(--cap) / var(--k)); transform: translateY(calc(var(--cap) * var(--dy))); }
.wordmark--lg { --cap: 40px; }
.wordmark--switcherpro { --k: .717; --dy: -.128; }
.wordmark--genr8 { --k: .717; --dy: .151; }
.wordmark--reseditor { --k: .95; --dy: 0; }
/* Cairn has no logo artwork: the name set in Inter Tight, sized so its cap height matches --cap (Inter cap height = .727em) */
.wordmark--text { height: auto; transform: none; font: 600 calc(var(--cap) / .727)/1 "Inter Tight", Inter, system-ui, sans-serif; letter-spacing: -.02em; color: var(--text); }
.wordmark__plus { background: linear-gradient(135deg, #8b6cff, #46d6c8); -webkit-background-clip: text; background-clip: text; color: transparent; }
@media (max-width: 560px) { .wordmark { --cap: 24px; } .wordmark--lg { --cap: 30px; } .app-brand { gap: 16px; } }

/* ---------- Services: five colour-keyed cards ----------
   Each card sets --c (r,g,b) inline; the lead card also --c2 for a two-tone edge.
   Desktop: lead card spans two rows on the left, the other four form a 2×2. */
.services {
  display: grid; gap: 16px; border: 0;
  grid-template-columns: 1.2fr 1fr 1fr; grid-template-rows: 1fr 1fr;
}
.services .service {
  --c2: var(--c);
  position: relative; overflow: hidden; isolation: isolate;
  border: 1px solid rgba(var(--c), .16); border-radius: var(--radius);
  padding: clamp(24px, 2.6vw, 32px);
  background:
    radial-gradient(120% 70% at 100% 0%, rgba(var(--c), .10), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,.02), transparent 40%),
    var(--surface);
  transition: transform .35s cubic-bezier(.2,.7,.2,1), border-color .35s, box-shadow .35s;
}
.services .service::before {               /* 2px accent edge along the top */
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px; z-index: 1;
  background: linear-gradient(90deg, rgb(var(--c)), rgb(var(--c2)) 60%, transparent);
  opacity: .85;
}
.services .service:hover { border-color: rgba(var(--c), .38); }
@media (hover: hover) and (pointer: fine) {
  .services .service::after { background: radial-gradient(380px circle at var(--mx, 50%) var(--my, 50%), rgba(var(--c), .10), transparent 45%); }
}
.service__icon {
  width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center; margin-bottom: 22px;
  color: rgb(var(--c)); background: rgba(var(--c), .12); box-shadow: inset 0 0 0 1px rgba(var(--c), .25);
}
.service__icon svg { width: 22px; height: 22px; }
/* Full-strength label for 4.5:1 on the card; --ct lets a dark accent (violet) use a lighter tint */
.services .card__num { color: rgb(var(--ct, var(--c))); margin-bottom: 0; }
.services .service h3 { margin: 12px 0 10px; }
.services .service p a { color: rgb(var(--c)); text-decoration-color: rgba(var(--c), .4); }

/* Lead card */
.services .service--lead {
  grid-row: span 2; display: flex; flex-direction: column;
  background:
    radial-gradient(90% 60% at 0% 0%, rgba(var(--c), .16), transparent 60%),
    radial-gradient(80% 60% at 100% 100%, rgba(var(--c2), .14), transparent 60%),
    var(--surface);
}
.services .service--lead .service__icon { width: 56px; height: 56px; border-radius: 14px;
  background: linear-gradient(135deg, rgba(var(--c), .22), rgba(var(--c2), .22)); }
.services .service--lead .service__icon svg { width: 28px; height: 28px; }
.services .service--lead h3 { font-size: clamp(1.5rem, 2.4vw, 2rem); }
.services .service--lead p { font-size: 16.5px; }
.services .service--lead .tags { list-style: none; padding: 0; margin: 22px 0 0; }
.services .service--lead .tag { background: rgba(var(--c), .08); color: #cfe9e5; box-shadow: inset 0 0 0 1px rgba(var(--c), .2); }
.service__bars { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; opacity: .8; }
.services .service--lead { padding-bottom: calc(clamp(24px, 2.6vw, 32px) + 3px); }

@media (max-width: 980px) {
  .services { grid-template-columns: 1fr 1fr; grid-template-rows: auto; grid-auto-rows: 1fr; }
  .services .service--lead { grid-column: 1 / -1; grid-row: auto; }
}
@media (max-width: 640px) { .services { grid-template-columns: 1fr; grid-auto-rows: auto; } }
/* Lead service card: a framed work photo fills whatever height the 2×2 beside it leaves */
.service__media { position: relative; margin: 24px 0 0; flex: 1 1 auto; min-height: 180px; border-radius: 10px; overflow: hidden; border: 1px solid rgba(var(--c), .22); }
.service__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.service__media::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 55%, rgba(7,8,10,.55)); pointer-events: none; }
@media (max-width: 980px) { .service__media { flex: none; aspect-ratio: 21 / 9; min-height: 0; } }
@media (max-width: 640px) { .service__media { aspect-ratio: 16 / 9; } }

/* Footer meta: dot-separated on one line; stacked without dots on phones (no dangling separators) */
.footer-meta { display: inline-flex; flex-wrap: wrap; }
.footer-meta > span + span::before { content: "·"; margin: 0 10px; }
@media (max-width: 560px) {
  .footer-meta { display: grid; gap: 6px; }
  .footer-meta > span + span::before { content: none; }
}

/* Hero tool list: two fixed groups so a wrap never strands a separator */
.hud-tools { display: inline-flex; flex-wrap: wrap; }
.hud-tools > span { white-space: nowrap; }
.hud-tools > span + span::before { content: "·"; margin: 0 .55em; }
@media (max-width: 560px) { .hud-tools { display: grid; gap: 6px; } .hud-tools > span + span::before { content: none; } }

/* Service cards — every card leads with a full-bleed image strip; the icon tile overlaps its lower edge.
   (Overrides the earlier lead-only .service__media rules.) */
.services .service { --pad: clamp(24px, 2.6vw, 32px); padding: var(--pad); display: flex; flex-direction: column; }
.services .service--lead { padding-bottom: calc(var(--pad) + 3px); }
.services .service__media {
  position: relative; flex: none; margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 0;
  aspect-ratio: 16 / 7; min-height: 0; border: 0; border-radius: 0; overflow: hidden;
  border-bottom: 1px solid rgba(var(--c), .25);
}
.services .service__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .8s cubic-bezier(.2,.7,.2,1); }
.services .service__media::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(var(--c), .10) 0%, transparent 35%, rgba(18,21,26,.55) 100%); }
/* Lead card's image takes all spare height so the card stays exactly two rows tall */
.services .service--lead .service__media { flex: 1 1 auto; aspect-ratio: auto; min-height: 220px; }
/* Icon tile sits half over the image edge — opaque so the photo doesn't show through */
.services .service__media + .service__icon {
  position: relative; z-index: 2; margin-top: -22px;
  background: linear-gradient(rgba(var(--c), .18), rgba(var(--c), .18)), #12151a;
}
.services .service--lead .service__media + .service__icon { margin-top: -28px; background: linear-gradient(135deg, rgba(var(--c), .26), rgba(var(--c2), .26)), #12151a; }
.services .service .service__icon { margin-bottom: 18px; }
@media (max-width: 980px) { .services .service--lead .service__media { flex: none; aspect-ratio: 21 / 8; min-height: 0; } }
@media (max-width: 640px) { .services .service__media, .services .service--lead .service__media { aspect-ratio: 16 / 8; } }
/* Renders with a small subject on a big empty canvas: frame the subject tightly */
.services .service__media--zoom img { scale: 1.75; transform-origin: 50% 48%; object-position: 50% 48%; }
/* Earth 6K strip: keep the globe in frame */
.services .service__media--earth img { object-position: 64% 50%; }

/* Desktop services v3: Playback runs full width (image left, text right); four cards in a row below. */
@media (min-width: 981px) {
  .services { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: auto auto; }
  .services .service--lead {
    grid-column: 1 / -1; grid-row: auto;
    display: grid; grid-template-columns: 1.3fr 1fr; align-items: center; column-gap: calc(var(--pad) * 1.5);
    padding: 0 var(--pad) 0 0;
  }
  .services .service--lead .service__media { margin: 0; align-self: stretch; aspect-ratio: auto; min-height: 340px; border-bottom: 0; border-right: 1px solid rgba(var(--c), .25); }
  .services .service--lead .service__media + .service__body .service__icon { margin-top: 0; }
  .services .service--lead .service__body { padding: var(--pad) 0 calc(var(--pad) + 3px); }
  .services .service--lead .service__icon { margin-top: 0; }
}
/* Tablet/phone: lead stacks like the others; the icon overlaps the image edge */
@media (max-width: 980px) {
  .services .service--lead .service__body > .service__icon:first-child { position: relative; z-index: 2; margin-top: -28px;
    background: linear-gradient(135deg, rgba(var(--c), .26), rgba(var(--c2), .26)), #12151a; }
}

/* Four-across row: titles reserve two lines so every description starts on the same baseline */
@media (min-width: 981px) { .services .service:not(.service--lead) h3 { min-height: 2.16em; } }

/* Gown frame: keep the dress centred in the strip */
.services .service__media--gown img { object-position: 50% 22%; }


/* Screen-reader-only headings keep the outline in order without changing the design */
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Carousel dots: 24×24 tap areas 4px apart (WCAG 2.5.8), the visible dot stays small; one row, never wrapped */
.carousel-dots { gap: 4px; flex-wrap: nowrap; max-width: none; }
.carousel-dots button { width: 24px; height: 24px; flex: none; background: none; display: grid; place-items: center; transition: width .3s; }
.carousel-dots button::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: rgba(255,255,255,.38);   /* 3.5:1 on --bg-2 */ transition: width .3s, background .3s; }
.carousel-dots button[aria-current="true"] { width: 32px; background: none; }
.carousel-dots button[aria-current="true"]::before { width: 20px; background: var(--grad); }
/* Long tracks (more than 10 items) show a HUD counter, "03 / 19", instead of a row of dots */
.carousel-count { min-width: 9ch; text-align: center; font: 500 12px/24px var(--font-mono); letter-spacing: .08em; color: var(--muted); font-variant-numeric: tabular-nums; }
.carousel-count b { color: var(--text); font-weight: 500; }

/* Software development band: stats then three colour-keyed cards (same accent system as Services) */
#software .stats { margin-bottom: clamp(28px, 4vw, 40px); }
.dev-card { --c: 70,214,200; display: flex; flex-direction: column; overflow: hidden;
  border-color: rgba(var(--c), .16);
  background: radial-gradient(120% 80% at 100% 0%, rgba(var(--c), .10), transparent 60%), var(--surface); }
.dev-card::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 2px; background: linear-gradient(90deg, rgb(var(--c)), transparent); opacity: .85; }
.dev-card .card__num { color: rgb(var(--ct, var(--c))); margin-bottom: 18px; }
.dev-card p { flex: 1; }
.dev-card .tags { list-style: none; padding: 0; margin: 18px 0 0; }
.dev-card .tag { background: rgba(var(--c), .08); box-shadow: inset 0 0 0 1px rgba(var(--c), .2); color: var(--text); }
.dev-card .app-card__link { color: rgb(var(--c)); }

/* Accent tints, the services-card language as a reusable pair:
   .accent-* sets --c (r,g,b) and, for dark violet, a lighter --ct for 4.5:1 labels.
   .card--tint colours a card; .tint colours a section's eyebrow, checklist ticks and media frame. */
.accent-teal { --c: 70,214,200; --ct: 70,214,200; }   /* --ct too, or a teal card inside a blue/violet section takes the section's text colour */
.accent-blue { --c: 47,143,255; --ct: 92,168,255; }
.accent-violet { --c: 139,108,255; --ct: 160,136,255; }
.card--tint {
  border-color: rgba(var(--c), .16);
  background: radial-gradient(120% 80% at 100% 0%, rgba(var(--c), .10), transparent 60%), var(--surface);
}
.card--tint::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 2px; background: linear-gradient(90deg, rgb(var(--c)), transparent); opacity: .85; }
.card--tint .card__num { color: rgb(var(--ct, var(--c))); }
.card--tint:hover { border-color: rgba(var(--c), .34); }
@media (hover: hover) and (pointer: fine) {
  .card--tint::after { background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 50%), rgba(var(--c), .10), transparent 45%); }
}
.tint .eyebrow { color: rgb(var(--ct, var(--c))); }
.tint .eyebrow::before { background: linear-gradient(90deg, rgb(var(--c)), transparent); }
.tint .checklist li::before { background-color: rgba(var(--c), .14); }
.tint.accent-blue .checklist li::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235ca8ff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
.tint.accent-violet .checklist li::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a088ff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
.tint .media-frame { border-color: rgba(var(--c), .22); }
.tint .media-frame:hover { border-color: rgba(var(--c), .40); }
/* Tint variants: linked cards keep their accent on hover (a.card:hover otherwise swaps in the brand gradient),
   app-card links and accent chips follow --c, and the contact form takes the card treatment. */
a.card--tint:hover { border-color: rgba(var(--c), .4); background: radial-gradient(120% 80% at 100% 0%, rgba(var(--c), .14), transparent 60%), var(--surface-2); box-shadow: 0 24px 60px -28px rgba(var(--c), .45); }
.card--tint .app-card__link { color: rgb(var(--ct, var(--c))); }
.tint .chip--accent { color: rgb(var(--ct, var(--c))); border-color: rgba(var(--c), .4); }
.form.card--tint { position: relative; overflow: hidden; }

a.dev-card:hover { border-color: rgba(var(--c), .4); background: radial-gradient(120% 80% at 100% 0%, rgba(var(--c), .14), transparent 60%), var(--surface-2); box-shadow: 0 24px 60px -28px rgba(var(--c), .45); }
@media (hover: hover) and (pointer: fine) { .dev-card::after { background: radial-gradient(380px circle at var(--mx, 50%) var(--my, 50%), rgba(var(--c), .10), transparent 45%); } }
@media (min-width: 981px) { .dev-card h3 { min-height: 2.16em; } }
a.card.dev-card { display: flex; }
/* Software band tags: undo the generic .card list styling */
.dev-card .tags .tag { padding: 6px 9px; border-top: 0; }

/* Hero roles: dot-separated on one line; one role per line on phones (no mid-phrase wraps) */
.roles { display: inline-flex; flex-wrap: wrap; }
.roles > span { white-space: nowrap; }
.roles > span + span::before { content: "·"; margin: 0 .7em; }
@media (max-width: 560px) {
  .eyebrow--roles { align-items: flex-start; }
  .eyebrow--roles::before { margin-top: .5em; }
  .roles { display: grid; gap: 8px; }
  .roles > span + span::before { content: none; }
}

/* Media can't be dragged out, selected or long-press saved (iOS); right-click is handled in site.js */
img, video { -webkit-user-drag: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }

/* ---------- Audit fixes (2026-10-05) ---------- */
/* Safe areas: with viewport-fit=cover, content stays clear of the notch / Dynamic Island in landscape
   and the footer's last line clears the home indicator. Same as --gutter wherever the insets are 0. */
.wrap { padding-left: max(var(--gutter), env(safe-area-inset-left)); padding-right: max(var(--gutter), env(safe-area-inset-right)); }
.site-footer { padding-bottom: calc(40px + env(safe-area-inset-bottom)); }
@media (max-width: 880px) {
  .nav-links { padding-left: max(var(--gutter), env(safe-area-inset-left)); padding-right: max(var(--gutter), env(safe-area-inset-right)); padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
}
/* Landscape phones: a tighter menu so every link and the CTA fit, or nearly fit, before the panel scrolls */
@media (max-width: 880px) and (max-height: 500px) {
  .nav-links a { padding: 10px 0; font-size: 16px; }
  .nav-links { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
  .nav-links .nav-cta a { height: 44px; margin-top: 12px; }
}

/* Hero copy stays readable over the brightest footage: a darker scrim behind the text column only
   (the right side of the frame keeps its full brightness), plus a soft shadow under the small type */
.hero::before {
  background:
    linear-gradient(180deg, rgba(7,8,10,.55) 0%, rgba(7,8,10,.15) 35%, rgba(7,8,10,.7) 75%, var(--bg) 100%),
    radial-gradient(50% 32% at 24% 36%, rgba(7,8,10,.4), rgba(7,8,10,0)),
    linear-gradient(90deg, rgba(7,8,10,.85) 0%, rgba(7,8,10,.55) 45%, rgba(7,8,10,0) 70%);
}
@media (max-width: 880px) {
  .hero::before { background: linear-gradient(180deg, rgba(7,8,10,.5) 0%, rgba(7,8,10,.62) 25%, rgba(7,8,10,.7) 40%, rgba(7,8,10,.85) 75%, var(--bg) 100%); }
}
.hero .lede, .hero .eyebrow, .hero__hud { text-shadow: 0 1px 12px rgba(0,0,0,.6); }

/* 3-up grids at tablet width (2 columns): an odd last card spans the row instead of sitting beside a hole */
@media (min-width: 641px) and (max-width: 980px) {
  .grid--3 > :last-child:nth-child(odd) { grid-column: 1 / -1; }
  .grid--3 > :last-child:nth-child(odd) p { max-width: 62ch; }
}

/* Screenshot rails of exactly four: four equal columns from 1100px (auto-fit at 260px only fits three until ~1174px) */
@media (min-width: 1100px) {
  .rail:has(> :nth-child(4):last-child) { grid-template-columns: repeat(4, minmax(0, 260px)); }
}

/* Feature cards (content packs): buttons pinned to the card bottom so every button in a row shares one line */
.lab-feature .lab-feature__body { display: flex; flex-direction: column; flex: 1; }   /* flex: 1 fills a flex-column card (home #lab) */
.lab-feature .lab-feature__body > .btn-row { margin-top: auto; padding-top: 20px; }

/* Spec tables: the 12px mono label takes the value's 24px line so both first lines share a centre */
.spec tbody th { line-height: 24px; }
/* Lab board table on phones: each board becomes a two-line row, name and chip on line 1 and the interface
   under it, instead of a 3-column table that wraps board names over 4–5 lines */
@media (max-width: 560px) {
  .spec--boards, .spec--boards tbody { display: block; }
  .spec--boards thead { display: none; }
  .spec--boards tr { display: grid; grid-template-columns: 1fr auto; gap: 4px 16px; padding: 14px 16px; border-bottom: 1px solid var(--line); }
  .spec--boards tr:last-child { border-bottom: 0; }
  .spec--boards td { padding: 0; border: 0; }
  .spec--boards td:nth-child(2) { text-align: right; font: 500 12px/24px var(--font-mono); letter-spacing: .08em; color: var(--dim); }
  .spec--boards td:last-child { grid-column: 1 / -1; }
}

/* Contact form: grid children may shrink, so a wide widget can't push the fields past the card */
.form > * { min-width: 0; }
@media (max-width: 379px) { .h-captcha { min-height: 144px; } }   /* compact widget (set in contact.html under 380px) */
.h-captcha iframe { display: block; }   /* no inline baseline gap: the loaded widget is exactly the reserved height, no jump */
.field input[type="date"]::-webkit-date-and-time-value { text-align: left; }   /* iOS centres it by default */

/* Footer links: 34px tap targets (19px text box + 7.5px above and below; the 10px list gap keeps them apart) and
   25px for the bottom-line email, without moving a pixel of the layout. The list links stay inline, so vertical
   padding grows the target but not the line, and a link that wraps (320px) keeps its original line pitch. */
.footer-grid ul a { padding: 7.5px 0; }
.footer-bottom a { display: inline-block; padding: 4px 0; margin: -4px 0; align-self: flex-start; }   /* not stretched down the stacked meta on phones */

/* Eyebrows that wrap: lines sit 18px apart and the leading rule stays on the first line.
   line-height 1.5 with -3px/17px margins keeps a one-line eyebrow exactly where it was. */
.eyebrow { align-items: flex-start; line-height: 1.5; margin-top: -3px; margin-bottom: 17px; text-wrap: balance; }
.eyebrow::before { flex: none; margin-top: calc(.75em - .5px); }
.section-head .eyebrow { margin: 5px 0 -3px; }   /* same compensation on top of .section-head p's 8px / 0 */
@media (max-width: 560px) { .eyebrow--roles .roles { gap: 2px; } }   /* 18px lines + 2px = the 20px role pitch it had at line-height 1 */

/* Dot-separated eyebrows that can wrap: each phrase is a flex item, so it moves to the next line whole (it only
   breaks inside if it is wider than the line on its own), and carries its '·' in a 2.22em gutter in front (one " · "
   at this tracking). The row is pulled 2.22em left and that strip is clipped, so the dot ahead of whichever phrase
   starts a line is hidden: no line starts or ends on a '·', and a one-line eyebrow is unchanged. */
.seps { display: flex; flex-wrap: wrap; margin-left: -2.22em; clip-path: inset(0 0 0 2.22em); }
.seps > span { position: relative; padding-left: 2.22em; }
.seps > span::before { content: "·"; position: absolute; left: 0; width: 2.22em; text-align: center; }

/* Phones and small tablets (the 3-button app rows wrap 2 + 1 up to ~632px): CTA buttons stack at one full width;
   an App Store badge keeps its size, centred on its own line */
@media (max-width: 640px) {
  .cta-band .btn-row .btn { flex: 1 1 100%; justify-content: center; }
  .cta-band .btn-row .appstore { margin: 0 auto; }
}
@media (max-width: 359px) { .cta-band { padding-left: 22px; padding-right: 22px; } }   /* 320: "Support & feature requests" (239px) on one line */

/* Button rows that can wrap: every button starts from the same basis (just wider than the longest label, "Latest
   firmware release" at 214.5px) and grows equally, so each line holds equal buttons: 3 across, 2 + a full-width 1,
   or one per line on phones. min-width keeps a label whole if a fallback font sets it wider than the basis. */
.btn-row--stack .btn { flex: 1 1 14.5em; min-width: max-content; justify-content: center; }

/* Text-only dev cards with a capability list: the list takes the spare height, so tags share a baseline across a row */
.dev-card--list > p, .dev-card--list > .lab-feature__body > p { flex: none; }
.dev-card--list > ul:not(.tags), .dev-card--list > .lab-feature__body > ul:not(.tags) { flex: 1; }
.dev-card--list.lab-feature h3 { min-height: 0; }   /* image cards (lab #show-tools): one-line titles, no reserved second line */

/* Footer at 2 columns: the third link list ("More") would sit alone under the first, so it spans both columns
   and sets its links in two columns on the same lines (same 32px gap) as the lists above */
@media (max-width: 880px) {
  .footer-grid > :last-child { grid-column: 1 / -1; }
  .footer-grid > :last-child ul { grid-template-columns: 1fr 1fr; column-gap: 32px; }
}

/* Four-chip rows: one line where all four fit, otherwise 2 + 2 on two column lines, never 3 + 1. Upper bound: the
   row's measured one-line width (chips + gaps) plus a hair (GenR8's hero chips 512px, the lead service's tags
   407.4px). Lower bound: the two columns' own width (329px, 235px); narrower rows wrap 2 + 2 by themselves. */
.app-hero__copy, .service--lead .service__body { container-type: inline-size; }
@container (min-width: 329px) and (max-width: 512.5px) {
  .meta-row--pairs { display: grid; grid-template-columns: repeat(2, max-content); justify-items: start; }
}
@container (min-width: 235px) and (max-width: 407.9px) {
  .service--lead .tags { display: grid; grid-template-columns: repeat(2, max-content); justify-items: start; }
}

/* Home #lab side cards (TRT, Pixera Assistant): a framed iPhone on the right. The eyebrow runs the full card width;
   the phone's top sits on the title's top edge and its right edge on the card padding, and the text column keeps
   the card padding as its gap to the phone. At 127px (wide desktop) the phone also ends on the link's bottom edge. */
.lab-side .dev-card { --pad: clamp(22px, 2.6vw, 30px); --phone: clamp(92px, 8.82vw, 127px);
  padding-right: calc(var(--pad) * 2 + var(--phone)); }
.lab-side .dev-card .card__num { margin-right: calc(-1 * (var(--pad) + var(--phone))); }
.dev-card__phone { position: absolute; right: var(--pad); width: var(--phone); height: auto;
  top: calc(var(--pad) + var(--num-h, 12px) + 18px);
  filter: drop-shadow(0 18px 28px rgba(0,0,0,.55)); pointer-events: none; transition: transform .35s ease; }
a.dev-card:hover .dev-card__phone { transform: translateY(-4px); }
@media (prefers-reduced-motion: reduce) { .dev-card__phone { transition: none; } a.dev-card:hover .dev-card__phone { transform: none; } }

/* Home #software cards: a 40px strip under the eyebrow (same 18px rhythm). A square mark tile, then thumbnails
   (PreViz renders 72px 16:9, Cairn firmware screens 54px 4:3) or the five App Store icons. Decorative: alt="". */
.dev-strip { display: flex; gap: 8px; height: 40px; margin: 0 0 18px; }
.dev-strip img { height: 40px; width: auto; border-radius: 6px; outline: 1px solid rgba(255,255,255,.08); outline-offset: -1px; }
.dev-strip .dev-strip__mark { width: 40px; border-radius: 9px; }
.dev-strip .dev-strip__mark--plate { background: rgba(var(--c), .10); outline-color: rgba(var(--c), .22); }
.dev-strip img:not(.dev-strip__mark) { flex: 0 1 auto; min-width: 0; object-fit: cover; }   /* narrow cards: thumbs crop, the mark never does */
