/* ============ Self-hosted fonts ============
   Served from this origin, so no visitor IP reaches Google and the site
   needs no font-related consent. Subsets: latin, latin-ext (Polish),
   cyrillic (IBM Plex Mono only - Archivo has no Cyrillic on Google Fonts,
   so Ukrainian text falls back to the system stack, as it always did).
   ============================================ */
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-400-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-400-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;
}

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-500-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-500-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;
}

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-600-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;
}

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-700-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-700-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;
}

/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-800-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(fonts/archivo-800-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;
}

/* cyrillic */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-400-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-400-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-400-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;
}

/* cyrillic */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-500-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-500-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-500-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;
}

/* ============ Tokens (Signal design system) ============ */
:root {
  --ink: #17171A;
  --ink-2: #33312D;
  --text: #5F5C55;
  --text-2: #4E4B45;
  --muted: #86827A;
  --cream: #F3F0E9;
  --white: #FFFFFF;
  --line: #E4DFD4;
  --chip: #ECE8DE;
  --shot: #E9E5DA;

  --dark: #121214;
  --dark-2: #1C1C20;
  --dark-line: #232328;
  --dark-line-2: #2A2A2F;
  --dark-border: #33333A;
  --on-dark: #F2F0EA;
  --on-dark-2: #A9A399;
  --on-dark-3: #8C877D;
  --on-dark-4: #6E6A63;

  --blue: #1668D8;
  --blue-hover: #1257B8;
  --blue-light: #4FA3F5;
  --blue-tint: #DCEAFB;
  --blue-tint-line: #C9DEF7;
  --peach: #FBDDC6;
  --peach-line: #F2CFB4;
  --peach-ink: #A9622B;
  --green: #D2E7D6;
  --green-line: #BFD9C4;
  --green-ink: #3D6B48;

  --font: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, Menlo, monospace;
  --pad-x: clamp(18px, 6.9vw, 100px);
  --section-y: clamp(56px, 6.4vw, 92px);
  --max: 1440px;
}

/* ============ Base ============ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--cream); color: var(--ink);
  font-family: var(--font); font-size: 16px; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
a:hover { color: var(--blue); }
h1, h2, h3, p { margin: 0; }
:focus-visible { outline: 2px solid var(--blue-light); outline-offset: 3px; border-radius: 6px; }

.skip { position: absolute; left: -9999px; top: 8px; z-index: 100; background: var(--blue); color: #fff; padding: 10px 16px; border-radius: 999px; }
.skip:focus { left: 8px; }

.wrap { max-width: var(--max); margin: 0 auto; padding-left: var(--pad-x); padding-right: var(--pad-x); }
.section { padding-top: var(--section-y); padding-bottom: var(--section-y); }
.dark { background: var(--dark); color: var(--on-dark); }

/* ============ Type ============ */
.d { font-weight: 800; letter-spacing: -0.035em; }
.mono { font-family: var(--mono); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.accent { color: var(--blue); }
.dark .accent { color: var(--blue-light); }
.h1 { font-size: clamp(44px, 6.1vw, 88px); line-height: 0.94; color: #fff; }
.h2 { font-size: clamp(34px, 3.6vw, 52px); line-height: 1.0; }
.h2-xl { font-size: clamp(40px, 4.7vw, 68px); line-height: 0.98; }
.eyebrow { margin-bottom: 16px; }
.lead { font-size: clamp(16px, 1.3vw, 19px); line-height: 1.55; color: var(--on-dark-2); text-wrap: pretty; }

/* ============ Logo - direction 02 "Split weight" ============ */
.logo { font-weight: 800; letter-spacing: -0.05em; font-size: 22px; line-height: 1; white-space: nowrap; color: var(--ink); }
.logo span { color: var(--blue); }
.dark .logo, .logo--on-dark { color: #fff; }
.dark .logo span, .logo--on-dark span { color: var(--blue-light); }
.logo:hover { color: inherit; }

/* ============ Components ============ */
.tag { display: inline-block; font-family: var(--mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; background: var(--blue-tint); color: var(--blue-hover); border-radius: 999px; padding: 6px 12px; }
.tag--dark { background: #16294A; color: #7CBAF8; }
.chip { display: inline-block; font-size: 12px; color: var(--text-2); background: var(--chip); border-radius: 999px; padding: 6px 12px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.card { background: var(--white); border: 1px solid var(--line); border-radius: 18px; }
.shot { background: var(--shot); border: 1px solid var(--line); border-radius: 14px; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.shot img { width: 100%; height: 100%; object-fit: cover; }

.btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; background: var(--blue); color: #fff; border: 1px solid var(--blue); border-radius: 999px; padding: 16px 28px; font-size: 16px; font-weight: 600; line-height: 1.2; transition: background .15s ease, border-color .15s ease; }
.btn:hover { background: var(--blue-hover); border-color: var(--blue-hover); color: #fff; }
.btn svg { transition: transform .15s ease; }
.btn:hover svg { transform: translateX(3px); }
.btn-ghost { display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--dark-border); color: var(--on-dark); border-radius: 999px; padding: 16px 28px; font-size: 16px; font-weight: 500; line-height: 1.2; transition: border-color .15s ease; }
.btn-ghost:hover { border-color: var(--blue-light); color: #fff; }

/* ============ Header ============ */
.site-header { position: sticky; top: 0; z-index: 50; background: var(--dark); border-bottom: 1px solid var(--dark-line); }
.nav { display: flex; align-items: center; justify-content: space-between; padding-top: 18px; padding-bottom: 18px; gap: 24px; }
.nav-links { display: flex; align-items: center; gap: 28px; font-size: 15px; font-weight: 500; }
.nav-links > a { color: #C9C4BA; }
.nav-links > a:hover { color: #fff; }
.lang { display: flex; gap: 4px; align-items: center; border-left: 1px solid var(--dark-line-2); padding-left: 24px; }
.lang .mono { font-size: 11px; color: #8C877D; }
.lang .mono[aria-current] { color: #fff; }
.lang .sep { color: #55524C; }
.nav-phone { font-weight: 600; color: var(--on-dark) !important; }
.nav-cta { background: var(--blue); color: #fff !important; border-radius: 999px; padding: 12px 22px; font-size: 14px; font-weight: 600; }
.nav-cta:hover { background: var(--blue-hover); }
.nav-mobile { display: none; align-items: center; gap: 6px; }
.icon-btn { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 999px; background: none; border: 0; cursor: pointer; }
.icon-btn--round { border: 1px solid var(--dark-line-2); background: var(--dark-2); }

.mobile-menu { display: none; border-top: 1px solid var(--dark-line); padding: 12px var(--pad-x) 28px; }
.mobile-menu a { display: block; padding: 14px 0; font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--on-dark); border-bottom: 1px solid var(--dark-line); }
.mobile-menu .lang { border: 0; padding: 18px 0 20px; }
.mobile-menu .lang a { display: inline; border: 0; padding: 0; font-size: 13px; }
.mobile-menu .btn { width: 100%; font-size: 16px; color: #fff; border-bottom: 0; padding: 16px; }
.site-header.is-open .mobile-menu { display: block; }

/* ============ Hero ============ */
.hero { display: grid; grid-template-columns: 1.05fr 1fr; gap: 72px; align-items: center; padding-top: 88px; padding-bottom: 96px; }
.hero .h1 { margin-top: 24px; }
.hero .lead { margin-top: 26px; max-width: 560px; }
.hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; }
.langs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 28px; align-items: center; }
.langs .mono { font-size: 10px; margin-right: 4px; color: var(--on-dark-4); }
.langs .chip { background: var(--dark-2); color: var(--on-dark-2); }
.hero-shots { display: flex; flex-direction: column; gap: 14px; }
.hero-shots .row { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 14px; }

.clients { border-top: 1px solid var(--dark-line); display: flex; align-items: center; justify-content: space-between; gap: 40px; padding-top: 26px; padding-bottom: 30px; }
.clients ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 24px 48px; }
.clients li { display: flex; flex-direction: column; gap: 2px; }
.clients .d { font-size: 17px; color: var(--on-dark); }
.clients .url { font-family: var(--mono); font-size: 10px; letter-spacing: 0.04em; color: var(--on-dark-4); }

/* ============ Section head ============ */
.sec-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 60px; margin-bottom: 42px; }
.sec-head p { max-width: 360px; font-size: 15px; line-height: 1.6; color: var(--text); margin-bottom: 6px; }

/* ============ Services ============ */
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 18px; }
.svc { padding: 30px 28px; display: flex; flex-direction: column; gap: 13px; min-height: 278px; }
.svc h3 { font-size: 23px; line-height: 1.12; }
.svc p { font-size: 15px; line-height: 1.6; color: var(--text); flex-grow: 1; }
.svc .mono { color: var(--blue); }
.svc--blue { background: var(--blue-tint); border-color: var(--blue-tint-line); }
.svc--blue .mono { color: var(--blue-hover); }
.svc--blue p { color: var(--text-2); }
.svc--blue .chip { background: #EBF3FD; }
.svc--peach { background: var(--peach); border-color: var(--peach-line); }
.svc--peach .mono { color: var(--peach-ink); }
.svc--peach p { color: var(--text-2); }
.svc--peach .chip { background: #FDECE0; }
.svc--green { background: var(--green); border-color: var(--green-line); }
.svc--green .mono { color: var(--green-ink); }
.svc--green p { color: var(--text-2); }
.svc--green .chip { background: #E3F0E6; }

/* ============ Growth system ============ */
.growth .h2-xl { margin-bottom: 14px; max-width: 900px; }
.growth .lead { font-size: 18px; line-height: 1.6; max-width: 640px; margin-bottom: 48px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 14px; }
.layer { background: var(--dark-2); border: 1px solid var(--dark-line-2); border-radius: 16px; padding: 22px 24px; }
.layer .mono { color: var(--blue-light); margin-bottom: 12px; }
.layer .d { font-size: 19px; margin-bottom: 5px; }
.layer p { font-size: 14px; color: var(--on-dark-3); }
.layer--goal { background: var(--blue); border-color: var(--blue); }
.layer--goal .mono { color: #BFDCFA; }
.layer--goal .d { font-size: 22px; color: #fff; }
.layer--goal p { color: #CFE3FB; }

/* ============ Work ============ */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 28px; }
.project { display: block; padding: 20px 20px 26px; border-radius: 22px; transition: transform .2s ease, box-shadow .2s ease; }
.project:hover { color: inherit; transform: translateY(-3px); box-shadow: 0 18px 40px rgba(23,23,26,.08); }
.project .shot { height: 320px; }
.project-meta { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; margin-top: 20px; padding: 0 8px; }
.project-meta .d { font-size: 26px; }
.project-meta .sub { font-size: 15px; color: var(--muted); margin-top: 4px; }
.project .chips { margin-top: 14px; padding: 0 8px; }
.link-mono { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--blue); white-space: nowrap; }

/* ============ Case study band ============ */
/* One column since the screenshot box was removed: the copy is held to the
   width the gradient scrim actually covers, so it never runs onto petals. */
.case-grid { margin-top: 26px; max-width: 620px; }
.case h2 { font-size: clamp(30px, 3.05vw, 44px); line-height: 1.04; margin-bottom: 20px; }
.case p { font-size: 17px; line-height: 1.6; color: var(--text-2); }
.case p + p { margin-top: 16px; }
.case .btn { margin-top: 28px; }


.case-stats { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 16px; margin-top: 36px; }
.stat { background: #fff; border-radius: 18px; padding: 26px 28px; }
.stat .d { font-size: 22px; margin-bottom: 14px; }
.stat ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; font-size: 14px; color: var(--text); }
.stat .big { font-size: 52px; color: var(--blue); line-height: 1; margin: 0; }
.stat .big small { font-size: 26px; color: var(--muted); }
.stat .note { font-size: 14px; color: var(--text); margin-top: 10px; }
.placeholder { font-family: var(--mono); font-size: 13px; color: var(--blue-hover); line-height: 2; }
.quote { background: #fff; border-radius: 18px; padding: 36px 40px; margin: 16px 0 0; text-align: center; }
.quote blockquote { margin: 0; font-size: 26px; line-height: 1.3; color: var(--muted); }
.quote figcaption { margin-top: 14px; }

/* ============ AI / human ============ */
.split-card { padding: 34px 32px; border-radius: 22px; }
.split-card ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; font-size: 16px; color: var(--ink-2); }
.split-card li { display: flex; gap: 12px; }
.split-card li::before { content: "-"; color: #C4BFB5; }
.split-card--blue { background: var(--blue-tint); border-color: var(--blue-tint-line); }
.split-card--blue li::before { color: #8FB6E4; }
.split-card .mono { margin-bottom: 20px; }
.fineprint { margin-top: 24px; font-size: 16px; color: var(--text); max-width: 760px; line-height: 1.6; }

/* ============ Process ============ */
.step { padding: 26px 24px 30px; border-radius: 16px; }
.step .mono { color: var(--blue); margin-bottom: 14px; }
.step .d { font-size: 20px; margin-bottom: 8px; }
.step p { font-size: 14px; line-height: 1.55; color: var(--text); }

/* ============ Analytics ============ */
.analytics { background: var(--green); border-radius: 22px; padding: clamp(28px, 3.2vw, 46px); display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; }
.analytics .mono { color: var(--green-ink); margin-bottom: 14px; }
.analytics h3 { font-size: clamp(30px, 2.8vw, 40px); line-height: 1.04; margin-bottom: 14px; }
.analytics p { font-size: 16px; line-height: 1.6; color: var(--ink-2); }
.analytics .chips { gap: 8px; }
.analytics .chip { background: #E8F3EA; font-size: 13px; padding: 8px 14px; }

/* ============ About ============ */
.about { display: grid; grid-template-columns: 1fr 1fr; gap: 72px; align-items: start; }
.about h2 { margin-bottom: 22px; }
.about p { font-size: 17px; line-height: 1.62; color: var(--text); text-wrap: pretty; }
.about p + p { margin-top: 16px; }
.facts { display: flex; flex-wrap: wrap; gap: 24px 40px; margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--line); }
.facts .mono { margin-bottom: 8px; }
.facts .d { font-size: 16px; }
.perks { display: flex; flex-direction: column; gap: 12px; }
.perk { padding: 22px 26px; border-radius: 16px; }
.perk .d { font-size: 18px; margin-bottom: 5px; }
.perk p { font-size: 15px; color: var(--text); line-height: 1.55; }

/* ============ CTA + footer ============ */
.cta { text-align: center; padding-top: clamp(72px, 7.8vw, 112px); padding-bottom: clamp(72px, 7.8vw, 112px); }
.cta .mono { color: var(--on-dark-3); margin-bottom: 26px; }
.cta h2 { margin: 0 auto 24px; font-size: clamp(42px, 5.4vw, 78px); line-height: 0.98; max-width: 900px; }
.cta p { margin: 0 auto 38px; max-width: 620px; font-size: 18px; line-height: 1.6; color: var(--on-dark-2); }
.cta-btns { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }

.footer { padding-top: 20px; padding-bottom: 56px; }
.footer-grid { border-top: 1px solid var(--dark-line-2); padding-top: 48px; display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 44px; }
.footer .logo { margin-bottom: 12px; display: inline-block; }
.footer-about { font-size: 14px; color: var(--on-dark-3); line-height: 1.6; max-width: 300px; }
.footer .chips { margin-top: 18px; gap: 8px; }
.footer .chips a { background: var(--dark-2); color: var(--on-dark-2); }
.footer-col { display: flex; flex-direction: column; gap: 9px; font-size: 14px; }
.footer-col .mono { margin-bottom: 6px; }
.footer-col a { color: var(--on-dark-2); }
.footer-col a:hover { color: #fff; }
.footer-bottom { border-top: 1px solid var(--dark-line-2); margin-top: 44px; padding-top: 20px; display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; }
.footer-bottom .mono { font-size: 10px; }

/* ============ Responsive ============ */
@media (max-width: 1180px) {
  .nav-links { gap: 20px; }
  .nav-phone { display: none; }
  .hero { gap: 48px; }
  .clients { flex-direction: column; align-items: flex-start; gap: 20px; }
}
@media (max-width: 980px) {
  .nav-links { display: none; }
  .nav-mobile { display: flex; }
  .nav { padding-top: 14px; padding-bottom: 14px; }
  .logo { font-size: 19px; }
  .hero { grid-template-columns: 1fr; padding-top: 28px; padding-bottom: 30px; gap: 28px; }
  .hero-shots .shot:first-child { height: 190px !important; }
  .hero-shots .row .shot { height: 110px !important; }
  .sec-head { flex-direction: column; align-items: flex-start; gap: 18px; }
  .grid-3 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .grid-4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .analytics, .about { grid-template-columns: 1fr; gap: 36px; }
  .case-stats { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-grid > :first-child { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .hero-ctas { flex-direction: column; }
  .hero-ctas a { width: 100%; height: 54px; padding: 0 20px; }
  .hero-ctas .btn-ghost { background: var(--dark-2); }
  .grid-3, .grid-2, .grid-4 { grid-template-columns: 1fr; }
  .grid-2 { gap: 18px; }
  .svc { min-height: 0; }
  .project { padding: 14px 14px 20px; }
  .project .shot { height: 220px; }
  .project-meta .d { font-size: 22px; }
  .quote { padding: 28px 22px; }
  .quote blockquote { font-size: 20px; }
  .cta-btns a { width: 100%; }
  .footer-grid { grid-template-columns: 1fr; gap: 32px; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
}

/* =======================================================================
   WORK INDEX + CASE STUDY PAGES
   ======================================================================= */

/* ---- Page hero (shared by /work/ and every case study) ---- */
.page-hero { padding-top: clamp(40px, 5vw, 76px); padding-bottom: clamp(40px, 5vw, 72px); }
.page-hero .h2-xl { max-width: 900px; margin-top: 16px; }
.page-hero .lead { margin-top: 22px; max-width: 620px; }

/* ---- Breadcrumbs ---- */
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--on-dark-4); }
.crumbs a { color: var(--on-dark-3); }
.crumbs a:hover { color: var(--blue-light); }
.crumbs [aria-current] { color: var(--on-dark); }

/* ---- Work index grid ---- */
.work-intro { display: grid; grid-template-columns: 1.15fr 1fr; gap: 64px; align-items: end; }
.work-intro .lead { color: var(--on-dark-2); }
.work-count { display: flex; gap: 40px; }
.work-count .d { font-size: 44px; line-height: 1; color: #fff; }
.work-count .mono { margin-top: 8px; display: block; }
.project--wide { grid-column: 1 / -1; }
.project--wide .shot { height: 380px; }
.project-note { font-size: 15px; line-height: 1.6; color: var(--text); margin-top: 14px; padding: 0 8px; }
.project .visit { font-family: var(--mono); font-size: 10px; letter-spacing: .08em; color: var(--muted); text-transform: none; margin-top: 6px; }
.tag--soon { background: var(--chip); color: var(--text-2); }

/* ---- Sector filter row (static, not JS) ---- */
.sectors { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 34px; }
.sectors .chip { background: var(--white); border: 1px solid var(--line); }

/* ---- Case study layout ---- */
.case-hero { display: grid; grid-template-columns: 1.1fr .9fr; gap: 64px; align-items: center; padding-top: clamp(32px, 4vw, 60px); padding-bottom: clamp(48px, 5vw, 80px); }
.case-hero .h2-xl { margin-top: 18px; }
.case-hero .lead { margin-top: 20px; }
.case-hero .shot { height: 360px; background: var(--dark-2); border-color: var(--dark-line-2); }
.case-hero .shot .mono { color: var(--on-dark-4); }

.factbar { border-top: 1px solid var(--dark-line); display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 28px; padding-top: 28px; padding-bottom: 36px; }
.factbar .mono { margin-bottom: 8px; display: block; }
.factbar .d { font-size: 17px; color: var(--on-dark); }
.factbar p { font-size: 14px; color: var(--on-dark-3); margin-top: 3px; }
.factbar a.d:hover { color: var(--blue-light); }

/* ---- Case body: sticky side rail + prose ---- */
.case-body { display: grid; grid-template-columns: 260px 1fr; gap: 64px; align-items: start; }
.rail { position: sticky; top: 104px; display: flex; flex-direction: column; gap: 10px; }
.rail .mono { margin-bottom: 4px; }
.rail a { font-size: 15px; color: var(--text); }
.rail a:hover { color: var(--blue); }
.prose > * + * { margin-top: 20px; }
.prose h2 { font-size: clamp(28px, 2.7vw, 38px); line-height: 1.06; letter-spacing: -0.03em; font-weight: 800; margin-top: 52px; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: 20px; line-height: 1.25; letter-spacing: -0.02em; font-weight: 700; margin-top: 32px; }
.prose p { font-size: 17px; line-height: 1.65; color: var(--text); text-wrap: pretty; }
.prose ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.prose li { display: flex; gap: 12px; font-size: 16px; line-height: 1.55; color: var(--text); }
.prose li::before { content: "-"; color: #C4BFB5; flex: none; }
.prose strong { color: var(--ink-2); font-weight: 600; }

/* ---- Callouts inside a case ---- */
.pull { border-left: 3px solid var(--blue); padding: 6px 0 6px 24px; }
.pull p { font-size: 20px; line-height: 1.45; color: var(--ink-2); font-weight: 500; }
.panel { border-radius: 18px; padding: 28px 30px; }
.panel .mono { margin-bottom: 12px; display: block; }
.panel .d { font-size: 20px; margin-bottom: 8px; }
.panel p { font-size: 15px; line-height: 1.6; color: var(--text-2); }
.panel--blue { background: var(--blue-tint); border: 1px solid var(--blue-tint-line); }
.panel--blue .mono { color: var(--blue-hover); }
.panel--green { background: var(--green); border: 1px solid var(--green-line); }
.panel--green .mono { color: var(--green-ink); }
.panel--peach { background: var(--peach); border: 1px solid var(--peach-line); }
.panel--peach .mono { color: var(--peach-ink); }

/* ---- Layer checklist (which of the 8 layers are live) ---- */
.layers-list { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }
.layer-row { display: flex; align-items: center; gap: 12px; background: var(--white); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; font-size: 15px; color: var(--text-2); }
.layer-row svg { flex: none; }
.layer-row--off { background: transparent; color: var(--muted); border-style: dashed; }

/* ---- Screenshot strip ---- */
.strip { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 14px; }
.strip .shot { height: 260px; }

/* ---- Next project ---- */
.next { border-top: 1px solid var(--dark-line-2); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 24px; padding-top: 34px; padding-bottom: 8px; }
.next .mono { color: var(--on-dark-4); display: block; margin-bottom: 8px; }
.next .d { font-size: clamp(26px, 3vw, 40px); color: #fff; }
.next .d:hover { color: var(--blue-light); }

/* ---- Responsive ---- */
@media (max-width: 980px) {
  .work-intro { grid-template-columns: 1fr; gap: 32px; align-items: start; }
  .case-hero { grid-template-columns: 1fr; gap: 32px; }
  .case-hero .shot { height: 240px; }
  .factbar { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 22px; }
  .case-body { grid-template-columns: 1fr; gap: 32px; }
  .rail { position: static; flex-direction: row; flex-wrap: wrap; gap: 8px 18px; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
  .rail .mono { width: 100%; }
  .layers-list { grid-template-columns: 1fr; }
  .strip { grid-template-columns: 1fr; }
  .project--wide .shot { height: 260px; }
}
@media (max-width: 640px) {
  .factbar { grid-template-columns: 1fr; gap: 18px; }
  .work-count { gap: 28px; }
  .prose p, .prose li { font-size: 16px; }
  .panel { padding: 22px 20px; }
  .pull { padding-left: 18px; }
  .project--wide .shot { height: 220px; }
}

/* ---- Clients strip: name → case study, domain → live site ---- */
.clients li { gap: 3px; }
.clients a.d { transition: color .15s ease; }
.clients a.d:hover, .clients a.d:focus-visible { color: var(--blue-light); }
.clients a.url { display: inline-flex; align-items: center; gap: 5px; transition: color .15s ease; }
.clients a.url:hover, .clients a.url:focus-visible { color: var(--on-dark-2); }
.clients a.url .ext { font-size: 9px; opacity: .55; transform: translateY(-1px); }
.clients a.url:hover .ext { opacity: 1; }

/* Visually hidden - read by screen readers, never painted */
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* =======================================================================
   ESTIMATOR
   ======================================================================= */

.prog { display: flex; align-items: center; gap: 16px; margin-bottom: 40px; }
.prog-track { flex: 1; height: 3px; background: var(--line); border-radius: 99px; overflow: hidden; }
.prog-bar { height: 100%; background: var(--blue); border-radius: 99px; transform-origin: left center; transform: scaleX(0); transition: transform .35s cubic-bezier(0.23, 1, 0.32, 1); }
.prog .mono { white-space: nowrap; }

.step-panel h2 { margin-bottom: 12px; }
.step-panel h2:focus { outline: none; }
.step-lead { font-size: 17px; line-height: 1.6; color: var(--text); max-width: 640px; margin-bottom: 32px; text-wrap: pretty; }

/* ---- Option buttons ---- */
.opts { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 14px; }
.opt { display: flex; flex-direction: column; gap: 7px; text-align: left; background: var(--white); border: 1px solid var(--line); border-radius: 16px; padding: 22px 24px; font-family: inherit; cursor: pointer; transition: border-color .15s ease, background-color .15s ease, transform .15s cubic-bezier(0.23, 1, 0.32, 1); }
.opt-t { font-size: 18px; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); display: flex; justify-content: space-between; align-items: baseline; gap: 14px; }
.opt-p { font-family: var(--mono); font-size: 13px; font-weight: 500; color: var(--blue); white-space: nowrap; }
.opt-d { font-size: 14px; line-height: 1.55; color: var(--text); }
.opt.is-on { border-color: var(--blue); background: var(--blue-tint); }
.opt.is-on .opt-p { color: var(--blue-hover); }
@media (hover: hover) and (pointer: fine) {
  .opt:hover { border-color: var(--blue); transform: translateY(-2px); }
}

/* ---- Slider ---- */
.slider-card { padding: 30px 32px; display: flex; flex-direction: column; gap: 14px; max-width: 560px; }
.slider-card input[type="range"] { width: 100%; accent-color: var(--blue); height: 24px; }
.slider-card output { font-size: 30px; letter-spacing: -0.03em; }
.slider-note { font-size: 14px; line-height: 1.55; color: var(--text); }

/* ---- Switch ---- */
.switch { display: flex; align-items: flex-start; gap: 14px; padding: 24px 26px; max-width: 560px; cursor: pointer; }
.switch input { margin-top: 3px; width: 18px; height: 18px; accent-color: var(--blue); flex: none; }
.switch .d { font-size: 18px; display: block; margin-bottom: 4px; }
.switch-note { font-size: 14px; color: var(--text); }

/* ---- Step nav ---- */
.step-nav { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-top: 36px; padding-top: 26px; border-top: 1px solid var(--line); }
.btn-back { background: none; border: 0; font-family: inherit; font-size: 15px; font-weight: 500; color: var(--text); cursor: pointer; padding: 10px 0; }
.btn-back:hover { color: var(--blue); }
.btn[disabled] { opacity: .4; cursor: not-allowed; }

/* ---- Result ---- */
.res-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 40px; padding: 34px 36px; margin-bottom: 44px; }
.res-big { font-size: clamp(38px, 5vw, 62px); line-height: 1; color: var(--blue); margin: 10px 0 12px; }
.res-sub { font-size: 14px; line-height: 1.55; color: var(--muted); max-width: 400px; }
.res-meta { display: flex; gap: 36px; }
.res-meta .d { font-size: 20px; display: block; margin-top: 6px; }
.res-h3 { font-size: 22px; margin: 0 0 16px; }

.breakdown { border-top: 1px solid var(--line); margin-bottom: 44px; }
.bd-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; padding: 16px 0; border-bottom: 1px solid var(--line); }
.bd-label { font-size: 15px; color: var(--ink-2); display: block; }
.bd-note { font-size: 13px; color: var(--muted); display: block; margin-top: 4px; }
.bd-price { font-family: var(--mono); font-size: 14px; color: var(--ink); white-space: nowrap; }
.bd-row--inc .bd-price { color: var(--green-ink); }

.res-includes { list-style: none; margin: 0 0 44px; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 9px; }
.res-includes li { display: flex; gap: 10px; font-size: 15px; color: var(--text); }
.res-includes li::before { content: "✓"; color: var(--blue); }

.tiers { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 14px; margin-bottom: 44px; }
.tier { padding: 26px 28px; }
.tier-p { font-size: 32px; line-height: 1; margin: 10px 0 6px; }
.tier-w { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.tier-n { font-size: 14px; line-height: 1.5; color: var(--text); margin-top: 10px; }
.tier--on { border-color: var(--blue); background: var(--blue-tint); }
.tier--on .tier-p { color: var(--blue-hover); }

/* ---- Email card ---- */
.email-card { background: var(--dark); color: var(--on-dark); border-radius: 22px; padding: clamp(28px, 3.4vw, 46px); display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: start; }
.email-card .mono { color: var(--blue-light); }
.email-card h3 { font-size: clamp(26px, 2.6vw, 34px); line-height: 1.08; margin: 12px 0 14px; color: #fff; }
.email-card > div > p { font-size: 16px; line-height: 1.6; color: var(--on-dark-2); }
.fld { display: block; margin-bottom: 16px; }
.fld > span { display: block; font-size: 13px; color: var(--on-dark-2); margin-bottom: 7px; }
.fld em { font-style: normal; color: var(--on-dark-4); }
.fld input, .fld textarea { width: 100%; background: var(--dark-2); border: 1px solid var(--dark-border); border-radius: 12px; padding: 14px 16px; font-family: inherit; font-size: 15px; color: var(--on-dark); }
.fld input::placeholder, .fld textarea::placeholder { color: var(--on-dark-4); }
.fld input:focus, .fld textarea:focus { outline: none; border-color: var(--blue-light); }
.fld textarea { resize: vertical; }
.consent { display: flex; gap: 11px; align-items: flex-start; font-size: 13px; line-height: 1.5; color: var(--on-dark-2); margin-bottom: 20px; }
.consent input { margin-top: 2px; accent-color: var(--blue); flex: none; }
.consent a { color: var(--blue-light); text-decoration: underline; }
.email-card .btn { width: 100%; }
.form-status { font-size: 14px; margin-top: 14px; min-height: 1em; color: var(--on-dark-2); }
.form-status.is-ok { color: #8FC49B; }
.form-status.is-err { color: #F0A882; }

@media (max-width: 980px) {
  .opts { grid-template-columns: 1fr; }
  .res-head { flex-direction: column; gap: 26px; }
  .tiers { grid-template-columns: 1fr; }
  .email-card { grid-template-columns: 1fr; gap: 30px; }
  .res-includes { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .res-meta { gap: 24px; }
  .step-nav { flex-direction: column-reverse; align-items: stretch; gap: 12px; }
  .step-nav .btn { width: 100%; }
  .step-nav .link-mono { text-align: center; }
}

/* =======================================================================
   SCROLL-SCRUB - hero into section 02
   -----------------------------------------------------------------------
   Purpose: bridge a hard contrast edge (dark #121214 -> cream #F3F0E9) and
            open up depth between the hero layers as they leave.

   Tuning:  the three distances below are the whole effect. Raise them for a
            more pronounced parallax, lower them for a subtler one. The JS
            fallback reads the same numbers, so changing them here changes
            both paths.

   Easing:  linear, deliberately. A scrub must follow the finger 1:1; any
            curve makes it feel laggy and disconnected from the gesture.

   Longhands, not the `animation` shorthand: the shorthand resets
   animation-timeline to auto AND sets animation-duration to 0s, where a
   progress timeline needs auto. Both bugs are silent.
   ======================================================================= */

:root {
  --scrub-copy:  -64px;   /* hero headline + CTA block */
  --scrub-shots: -132px;  /* screenshots travel furthest = reads as depth */
  --scrub-strip: -30px;   /* clients strip trails behind */
}

@keyframes heroLift  { to   { transform: translate3d(0, var(--scrub-copy), 0);  opacity: .25; } }
@keyframes heroSink  { to   { transform: translate3d(0, var(--scrub-shots), 0); opacity: .35; } }
@keyframes heroFloor { to   { transform: translate3d(0, var(--scrub-strip), 0); opacity: .30; } }
@keyframes riseIn    { from { transform: translate3d(0, 26px, 0); opacity: 0; }
                       to   { transform: none; opacity: 1; } }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    .hero--matrix,
    .clients {
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-duration: auto;
      animation-timeline: view();
      animation-range: exit 0% exit 100%;
      will-change: transform, opacity;
    }
    .hero--matrix { animation-name: heroLift; }
    .clients      { animation-name: heroFloor; }

    /* Section 02 rises to meet it, so the handover reads as one movement */
    #services > .sec-head {
      animation-name: riseIn;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-duration: auto;
      animation-timeline: view();
      animation-range: entry 15% entry 75%;
    }
  }
}

/* ---- JS fallback, for browsers without scroll-driven animations --------
   scrub.js adds .scrub-js to <html> only when view() is unsupported and the
   visitor has not asked for reduced motion. It then writes the same
   transforms inline, so the effect looks identical everywhere.          */
.scrub-js .hero--matrix,
.scrub-js .clients { will-change: transform, opacity; }

/* =======================================================================
   CONSENT BANNER
   Entrance: rare/first-visit tier, purpose = state indication.
   transform + opacity, strong ease-out, 260ms. Reduced motion keeps the
   opacity fade and drops the movement.
   ======================================================================= */

.consent {
  position: fixed; left: 16px; right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 200;
  background: var(--dark); color: var(--on-dark);
  border: 1px solid var(--dark-border); border-radius: 18px;
  box-shadow: 0 22px 60px rgba(0,0,0,.34);
  max-width: 880px; margin: 0 auto;
  opacity: 0; transform: translate3d(0, 14px, 0);
  transition: opacity .26s cubic-bezier(0.23, 1, 0.32, 1), transform .26s cubic-bezier(0.23, 1, 0.32, 1);
}
.consent.is-in { opacity: 1; transform: none; }

.consent-inner { display: flex; align-items: center; gap: 28px; padding: 22px 26px; }
.consent-copy .d { font-size: 17px; color: #fff; margin-bottom: 5px; }
.consent-copy p { font-size: 14px; line-height: 1.55; color: var(--on-dark-2); margin: 0; }
.consent-copy a { color: var(--blue-light); text-decoration: underline; }

.consent-btns { display: flex; gap: 10px; flex: none; }
.consent-btn {
  font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1;
  padding: 13px 20px; border-radius: 999px; cursor: pointer; white-space: nowrap;
  background: transparent; color: var(--on-dark); border: 1px solid var(--dark-border);
  transition: border-color .15s ease, background-color .15s ease;
}
/* GDPR: refusing must be no harder than accepting, so both buttons carry
   the same weight, size and prominence - only the fill differs. */
.consent-btn--yes { background: var(--blue); border-color: var(--blue); color: #fff; }
@media (hover: hover) and (pointer: fine) {
  .consent-btn:hover { border-color: var(--blue-light); }
  .consent-btn--yes:hover { background: var(--blue-hover); border-color: var(--blue-hover); }
}

@media (max-width: 720px) {
  .consent-inner { flex-direction: column; align-items: stretch; gap: 16px; padding: 20px; }
  .consent-btns { flex-direction: column-reverse; }
  .consent-btn { width: 100%; padding: 15px 20px; }
}
@media (prefers-reduced-motion: reduce) {
  .consent { transform: none; transition: opacity .2s ease; }
}

/* ---- Insights empty state ---- */
.empty-state { padding: clamp(30px, 3.4vw, 48px); max-width: 780px; }
.empty-state .mono { color: var(--blue); display: block; margin-bottom: 12px; }
.empty-state h3 { font-size: clamp(24px, 2.4vw, 32px); line-height: 1.08; letter-spacing: -.03em; margin: 0 0 14px; }
.empty-state p { font-size: 16px; line-height: 1.6; color: var(--text); }
.queue { margin: 20px 0 22px; padding: 0; list-style: none; counter-reset: q; display: flex; flex-direction: column; gap: 14px; }
.queue li { counter-increment: q; position: relative; padding-left: 40px; font-size: 15px; line-height: 1.55; color: var(--text); }
.queue li::before { content: counter(q, decimal-leading-zero); position: absolute; left: 0; top: 1px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .08em; color: var(--blue); }
.queue strong { color: var(--ink-2); font-weight: 600; }
.empty-note { font-size: 15px; color: var(--muted); padding-top: 18px; border-top: 1px solid var(--line); }
.empty-note a { color: var(--blue); text-decoration: underline; }

/* The space hero puts the crumbs on a dark backdrop */
.space-copy .crumbs a { color: var(--on-dark-3); }
.space-copy .crumbs a:hover { color: var(--blue-light); }

/* =======================================================================
   MATRIX RAIN HERO
   -----------------------------------------------------------------------
   The rain sits behind the copy, not beside it, so the hero is one column
   instead of a text/screenshot split. Swap the two colours below for
   film-green if you want it: --matrix-head #7CFFB2, --matrix-body 120,255,170.
   ======================================================================= */

:root {
  --matrix-head: #7CBAF8;      /* leading glyph - brand blue */
  --matrix-body: 255,255,255;  /* the trail - white, as an r,g,b triplet */
}

.matrix-hero { position: relative; overflow: hidden; isolation: isolate; }
#matrix-canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 0; opacity: .42; pointer-events: none;
}
/* Keeps the rain off the headline: dense at the edges, clear behind the text */
.matrix-hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(ellipse 58% 62% at 30% 48%, #121214 28%, rgba(18,18,20,.72) 55%, transparent 78%),
    linear-gradient(to bottom, rgba(18,18,20,.55), transparent 22%, transparent 74%, #121214 100%);
}
.matrix-hero > .wrap { position: relative; z-index: 2; }

.hero--matrix {
  display: block;
  padding-top: clamp(64px, 9vw, 132px);
  padding-bottom: clamp(56px, 7vw, 104px);
  max-width: 940px;
}
.hero--matrix .h1 { margin-top: 24px; }
.hero--matrix .lead { margin-top: 26px; max-width: 620px; }

@media (max-width: 980px) {
  .hero--matrix { padding-top: 44px; padding-bottom: 40px; }
  #matrix-canvas { opacity: .32; }
}
@media (prefers-reduced-motion: reduce) {
  #matrix-canvas { opacity: .22; }
}


/* =======================================================================
   SHUFFLE - the eight process steps deal into place
   -----------------------------------------------------------------------
   shuffle.js does the work with inline transforms. All the grid needs from
   CSS is a 3D context so the tilt has some depth, and a guarantee that the
   stacked pile cannot widen the page for a frame.
   ======================================================================= */

.shuffle { perspective: 1200px; overflow: clip; }
@supports not (overflow: clip) { .shuffle { overflow: hidden; } }
.shuffle > * { transform-origin: 50% 55%; backface-visibility: hidden; }

/* =======================================================================
   SECTION 02 - INFINITE GALLERY
   -----------------------------------------------------------------------
   Two rows of service cards scrolling in opposite directions, looping
   seamlessly. Pure CSS: the track holds three copies of its cards and
   translates by exactly one third, so the moment it snaps back the frame
   is identical and the seam is invisible.

   Only the first copy is real. The other two carry aria-hidden and
   tabindex="-1", so assistive tech and the keyboard meet each service
   once, not three times.

   WCAG 2.2.2 - moving content must be pausable. It pauses on hover and on
   keyboard focus, and reduced motion stops it entirely and hands the row
   back to normal horizontal scrolling.
   ======================================================================= */

.gal {
  position: relative;
  /* Full-bleed out of .wrap so cards run to both edges */
  margin-left: calc(var(--pad-x) * -1);
  margin-right: calc(var(--pad-x) * -1);
  padding-block: 4px;
  /* Fade the cards out at the edges instead of cutting them off */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}

.gal-row { overflow: hidden; }
.gal-row + .gal-row { margin-top: 16px; }

.gal-track {
  display: flex;
  gap: 16px;
  width: max-content;
  will-change: transform;
  animation: galScroll 64s linear infinite;
}
.gal-row--rev .gal-track { animation-name: galScrollRev; animation-duration: 74s; }

/* One third, because the track holds exactly three copies of its cards. */
@keyframes galScroll    { to { transform: translate3d(-33.3333%, 0, 0); } }
@keyframes galScrollRev { from { transform: translate3d(-33.3333%, 0, 0); } to { transform: none; } }

.gal-track > .svc {
  flex: 0 0 clamp(266px, 25vw, 348px);
  min-height: 0;
  margin: 0;
}

/* Pausable, as moving content must be */
.gal-row:hover .gal-track,
.gal-row:focus-within .gal-track { animation-play-state: paused; }

.gal-hint {
  text-align: center;
  margin: 18px 0 0;
  color: var(--muted);
}

@media (max-width: 640px) {
  .gal-track { gap: 12px; }
  .gal-row + .gal-row { margin-top: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  /* Stop the movement, but keep every card reachable by scrolling the row. */
  .gal-track { animation: none; }
  .gal-row { overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
  .gal-track > .svc { scroll-snap-align: start; }
  .gal-hint { visibility: hidden; }
}

/* =======================================================================
   LIGHT WAVE - heading to the Enquiries card
   -----------------------------------------------------------------------
   A gleam leaves the first letter of "Every layer makes the next one
   cheaper", runs out and down through the gutter beside the grid, and
   lands on the blue Enquiries card - touching none of the other seven.

   lightwave.js measures the route from the real elements, so it stays
   correct at any width. Everything here is presentation only; with no JS
   nothing is added to the page at all.
   ======================================================================= */

.growth { position: relative; }

.lw {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: 1; pointer-events: none; overflow: visible;
  transition: opacity .7s ease;
}
.lw.is-done { opacity: 0; }

.lw-trail {
  fill: none;
  stroke: rgba(124,186,248,.20);
  stroke-width: 1.25;
  stroke-linecap: round;
}
.lw-gleam {
  fill: none;
  stroke: #BFDCFA;
  stroke-width: 2.25;
  stroke-linecap: round;
}

/* Split heading: words hold the line breaks, letters carry the shimmer */
.lw-w { display: inline-block; }
.lw-l { display: inline-block; will-change: color, text-shadow; }

/* inherit at both ends, so cream letters return to cream and the blue
   accent word returns to blue - one keyframe serves both */
@keyframes lwShimmer {
  0%   { color: inherit; text-shadow: none; }
  38%  { color: #fff; text-shadow: 0 0 16px rgba(124,186,248,.9), 0 0 40px rgba(22,104,216,.6); }
  100% { color: inherit; text-shadow: none; }
}

/* The card it arrives at: a single sweep across, then a settled glow */
.layer--goal { position: relative; overflow: hidden; }
.layer--goal.is-lit {
  box-shadow: 0 0 0 1px rgba(191,220,250,.55), 0 16px 48px rgba(22,104,216,.45);
  transition: box-shadow .6s cubic-bezier(0.23, 1, 0.32, 1);
}
.layer--goal.is-lit::before {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.42) 50%, transparent 62%);
  transform: translateX(-120%);
  animation: lwSweep 900ms cubic-bezier(0.23, 1, 0.32, 1) forwards;
  pointer-events: none;
}
@keyframes lwSweep { to { transform: translateX(120%); } }

@media (prefers-reduced-motion: reduce) {
  /* No travel and no sweep - the card simply arrives lit. */
  .layer--goal.is-lit::before { animation: none; opacity: 0; }
  .lw-l { animation: none !important; }
  .lw { display: none; }
}

/* =======================================================================
   SCREENSHOTS
   -----------------------------------------------------------------------
   A .shot that still holds a placeholder keeps its fixed height, because
   an empty box needs one. A .shot holding a real screenshot does not: it
   takes the image's own proportions, so the whole page top is visible
   instead of a slice cropped out of the middle.

   The !important is deliberate. Six context rules above set a fixed height
   on .shot (.project, .project--wide, .case, .case-hero, .strip, plus the
   responsive overrides), all of them more specific than :has(img). One
   override beats adding :not(:has(img)) to every one of them.
   ======================================================================= */

.shot:has(img) {
  height: auto !important;
  display: block;
  background: var(--white);
  border: 1px solid var(--line);
  box-shadow: 0 14px 40px rgba(23,23,26,.13);
}
.shot:has(img) img {
  width: 100%;
  height: auto;          /* the image sets the height, nothing is cropped */
  object-fit: initial;   /* overrides the cover used for placeholder boxes */
  display: block;
  border-radius: 13px;   /* sits just inside the 14px frame */
}

/* On dark sections the frame should read as light, not as a hole */
.dark .shot:has(img),
.case-hero .shot:has(img) {
  background: var(--dark-2);
  border-color: var(--dark-border);
  box-shadow: 0 18px 50px rgba(0,0,0,.42);
}

/* =======================================================================
   CASE BAND - dark, with the lilies
   -----------------------------------------------------------------------
   Replaces the peach block. The photograph already carries a wide stretch
   of flat dark space on its left, so the section's base colour is sampled
   straight from it (#021B26) and a gradient carries that colour across the
   copy. The join is invisible and the text never sits on petals.

   Everything inside the band flips to a dark treatment: white cards would
   read as holes punched in the photograph.
   ======================================================================= */

.case {
  position: relative;
  overflow: hidden;
  background-color: #021B26;
  color: var(--on-dark);
}
.case > .wrap { position: relative; z-index: 2; }
.case::before,
.case::after { content: ""; position: absolute; inset: 0; pointer-events: none; }
.case::before {
  z-index: 0;
  background: url(../images/case-lilies.webp) right center / cover no-repeat;
}
.case::after {
  z-index: 1;
  background: linear-gradient(100deg,
    #021B26 0%, #021B26 32%,
    rgba(2,27,38,.86) 46%,
    rgba(2,27,38,.42) 62%,
    rgba(2,27,38,.06) 78%,
    transparent 90%);
}

.case .tag { background: rgba(255,255,255,.12); color: #CFE3EC; }
.case h2 { color: #fff; }
.case p { color: #BCCBD3; }



/* Cards become glass, so the photograph still reads behind them */
.case .stat,
.case .quote {
  background: rgba(8,38,50,.62);
  border: 1px solid rgba(255,255,255,.12);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.case .stat .d,
.case .quote figcaption { color: #fff; }
.case .stat ul,
.case .stat .note { color: #BCCBD3; }
.case .stat .big { color: #7CBAF8; }
.case .stat .big small { color: #7E97A3; }
.case .placeholder { color: #9FD0F5; }
.case .quote blockquote { color: #93A8B2; }

@supports not (backdrop-filter: blur(10px)) {
  .case .stat, .case .quote { background: rgba(8,38,50,.9); }
}

/* Narrow screens see a slice of the photo rather than the composition, so
   it drops back to a texture and the copy keeps a flat ground. */
@media (max-width: 900px) {
  .case::before { opacity: .42; background-position: 72% center; }
  .case::after {
    background: linear-gradient(to bottom, rgba(2,27,38,.84), rgba(2,27,38,.94));
  }
}

/* =======================================================================
   A REAL TESTIMONIAL
   -----------------------------------------------------------------------
   The placeholder was one short line, so .quote centres it at 26px in a
   muted grey. A genuine quote is a paragraph and deserves to read as
   confident rather than provisional: smaller, darker, left-aligned with a
   controlled measure. Centring three sentences leaves both edges ragged
   and is noticeably harder to read.

   Placeholders on the other four case studies keep the old treatment, so
   the difference between real and pending stays visible at a glance.
   ======================================================================= */

.quote.is-real { text-align: left; }
.quote.is-real blockquote {
  font-size: clamp(18px, 1.5vw, 21px);
  line-height: 1.5;
  font-weight: 500;
  letter-spacing: -0.012em;
  color: var(--ink-2);
  max-width: 60ch;
  margin: 0 auto;
}
.quote.is-real figcaption {
  max-width: 60ch;
  margin: 16px auto 0;
  color: var(--muted);
}

/* On the dark lily band the same quote needs the opposite end of the scale */
.case .quote.is-real blockquote { color: #E4EEF3; }
.case .quote.is-real figcaption { color: #93A8B2; }

/* =======================================================================
   ORBIT - the work page hero
   -----------------------------------------------------------------------
   The scene sits on ::before as an image layer, the particles on the canvas
   above it, the legibility scrim on ::after, and the copy above all of it.

   Before the script runs the image is at full strength, so the hero is
   correct with no JS, with reduced motion, or on a slow connection.
   orbit.js adds .is-live once particles are drawing, which drops the image
   to a faint underlay - the particles are the subject, but the sun and
   Earth stay readable while everything is in motion.
   ======================================================================= */

.orbit-track { position: relative; height: 320vh; background: #04070E; }
.orbit-stage {
  position: sticky; top: 0;
  height: 100vh;
  overflow: hidden;
  background: #04070E;
}
.orbit-stage::before,
.orbit-stage::after { content: ""; position: absolute; inset: 0; pointer-events: none; }

.orbit-stage::before {
  z-index: 0;
  /* Follows --orbit-img so a page can use a different scene; the canvas
     data-src must be set to the same file. */
  background: var(--orbit-img, url(../images/orbit-scene.webp)) center / cover no-repeat;
  transition: opacity .8s ease;
}
.orbit-track.is-live .orbit-stage::before { opacity: .2; }

.orbit-canvas {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%;
  display: block;
  opacity: 0;
  transition: opacity .8s ease;
}
.orbit-track.is-live .orbit-canvas { opacity: 1; }

/* Keeps the copy legible over the sun, which is the brightest thing here */
.orbit-stage::after {
  z-index: 2;
  background:
    linear-gradient(to right, rgba(4,7,14,.86) 0%, rgba(4,7,14,.66) 38%, rgba(4,7,14,.18) 66%, transparent 86%),
    linear-gradient(to bottom, rgba(4,7,14,.55), transparent 26%, transparent 72%, #04070E 100%);
}

.orbit-copy {
  position: relative; z-index: 3;
  height: 100%;
  display: flex; flex-direction: column; justify-content: center;
  padding-top: 40px; padding-bottom: 40px;
}
.orbit-copy .work-intro { margin-top: 22px; }

.orbit-hint { position: absolute; z-index: 3; left: var(--pad-x); bottom: 30px; color: var(--on-dark-3); }

@media (max-width: 900px) {
  .orbit-track { height: 240vh; }
  .orbit-copy { justify-content: flex-start; padding-top: 12vh; }
  .orbit-stage::after {
    background: linear-gradient(to bottom, rgba(4,7,14,.82), rgba(4,7,14,.72) 55%, #04070E 100%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .orbit-track { height: auto; }
  .orbit-stage { position: relative; height: auto; min-height: 640px; }
  .orbit-canvas { display: none; }
  .orbit-track.is-live .orbit-stage::before { opacity: 1; }
}

/* Push mode enters from below, so the clip that keeps the pile tidy would
   cut the cards off on the way in. Nothing moves sideways here, so letting
   it overflow cannot produce a horizontal scrollbar. */
.shuffle[data-shuffle-mode="push"] { overflow: visible; perspective: none; }

/* ---- Orbit as a panel, not a journey --------------------------------------
   The estimate page wants the scene as a hero, not a four-screen scroll: its
   job is to get people into the calculator. The stage is a fixed height and
   does not stick, and orbit.js holds the camera at data-orbit-focus rather
   than panning, so the particles flow and respond to the pointer without
   costing anyone a single extra scroll.
   -------------------------------------------------------------------------- */
.orbit-track--panel { height: auto; }
.orbit-track--panel .orbit-stage {
  position: relative;
  height: clamp(420px, 62vh, 620px);
}
.orbit-track--panel .orbit-copy { justify-content: center; padding-top: 28px; padding-bottom: 28px; }
.orbit-track--panel .orbit-stage::after {
  background:
    linear-gradient(to right, rgba(4,7,14,.88) 0%, rgba(4,7,14,.7) 42%, rgba(4,7,14,.22) 70%, transparent 90%),
    linear-gradient(to bottom, rgba(4,7,14,.5), transparent 24%, transparent 70%, #04070E 100%);
}
@media (max-width: 900px) {
  .orbit-track--panel .orbit-stage { height: clamp(380px, 56vh, 520px); }
}
@media (prefers-reduced-motion: reduce) {
  .orbit-track--panel .orbit-stage { min-height: 0; }
}
