PageSourceSearch

https://www.thereclab.ai/

html thereclab.ai collected 2026-10-05 14:57:02 UTC 20,374 bytes, 327 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8" />
5<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6<title>TheRecLab · Helping recruiters turn AI into real impact</title>
7<meta name="description" content="TheRecLab helps recruiting teams turn AI into real impact: hands-on workshops, 1:1 coaching, and RecOps consulting from a recruiter with 8 years and 300+ hires behind him." />
8<meta name="theme-color" content="#161410" />
9<meta property="og:type" content="website" />
10<meta property="og:url" content="https://www.thereclab.ai/" />
11<link rel="canonical" href="https://www.thereclab.ai/" />
12<meta property="og:title" content="TheRecLab · Helping recruiters turn AI into real impact" />
13<meta property="og:description" content="We help recruiting teams build automations and stop leaving value on the table with Claude and ChatGPT." />
14<meta property="og:image" content="https://www.thereclab.ai/assets/og-image.jpg" />
15<meta property="og:image:width" content="1200" />
16<meta property="og:image:height" content="630" />
17<meta name="twitter:card" content="summary_large_image" />
18<meta name="twitter:title" content="TheRecLab · Helping recruiters turn AI into real impact" />
19<meta name="twitter:description" content="We help recruiting teams build automations and stop leaving value on the table with Claude and ChatGPT." />
20<meta name="twitter:image" content="https://www.thereclab.ai/assets/og-image.jpg" />
21<link rel="icon" type="image/png" sizes="32x32" href="favicon-32.png?v=4" />
22<link rel="icon" type="image/png" sizes="256x256" href="favicon.png?v=4" />
23<link rel="apple-touch-icon" href="apple-touch-icon.png?v=4" />
24<link rel="preconnect" href="https://fonts.googleapis.com" />
25<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
26<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Outfit:[email protected]&family=Schibsted+Grotesk:ital,wght@0,400..900;1,400..900&family=Newsreader:ital,opsz,wght@0,6..72,300..600;1,6..72,300..600&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet" />
27<link rel="preload" as="image" href="assets/workshop.jpg" fetchpriority="high" />
28<style>
29  :root {
30    --ink: #1c1a16;
31    --ink-soft: #4a463e;
32    --paper: #f4efe6;
33    --paper-2: #ece4d6;
34    --terra: #e0a589;
35    --terra-deep: #c98a64;
36    --terra-soft: #e0a589;
37    --concrete: #8c8782;
38    --sage: #6c7860;
39    --sans: "Outfit", system-ui, sans-serif;
40    --display: "Schibsted Grotesk", system-ui, sans-serif;
41    --serif: "Instrument Serif", Georgia, serif;
42    --news: "Newsreader", Georgia, serif;
43    /* Two-curve motion voice: --ease for micro-interactions (hover, toggles),
44       --ease-out (expo) for entrances - fast arrival, long luxurious settle */
45    --ease: cubic-bezier(.2,.7,.2,1);
46    --ease-out: cubic-bezier(.16,1,.3,1);
47  }
48  * { box-sizing: border-box; }
49  /* Body text uses Outfit (--sans); headings keep the Schibsted Grotesk display face */
50  h1, h2, h3, h4 { --sans: var(--display); }
51  html { scroll-behavior: smooth; scroll-padding-top: 70px; }
52  html, body { margin: 0; padding: 0; }
53  body { font-family: var(--sans); color: var(--ink); }
54  html { background: #14110d; }
55  /* copy of the photo top behind the nav, sized to the hero's scale (116% = the
56     hero's cover width x 1.16) and left-anchored so the screen/pole edges line up.
57     Hero scrim is bottom-up, so the top is near-clear — no band darkening needed */
58  body { background: url('assets/workshop.jpg') left top / 100% auto no-repeat, #14110d; }
59  ::selection { background: var(--terra); color: var(--ink); }
60  a:focus-visible, button:focus-visible { outline: 2px solid var(--terra); outline-offset: 3px; border-radius: 4px; }
61  .hero nav a { transition: color .25s var(--ease); }
62  .hero nav a:hover { color: #fff !important; }
63  footer a { transition: color .25s var(--ease); }
64  footer a:hover { color: #fff !important; }
65  .pill-btn { transition: transform .3s var(--ease), box-shadow .3s var(--ease); }
66  .pill-btn:hover { transform: translateY(-2px); box-shadow: 0 12px 26px -14px rgba(28,26,22,0.4); }
67
68  /* ---- Nav bar: transparent frosted glass, floats over the whole page ---- */
69  .sticky-bar { position: sticky; top: 0; left: 0; right: 0; z-index: 1000; height: 66px;
70    display: flex; align-items: center; justify-content: space-between; padding: 0 40px;
71    background: rgba(26,22,18,0.40);
72    -webkit-backdrop-filter: blur(16px) saturate(1.3); backdrop-filter: blur(16px) saturate(1.3);
73    border-bottom: 1px solid rgba(255,255,255,0.14);
74    text-shadow: 0 1px 14px rgba(0,0,0,0.32); }
75  .sticky-bar nav a:hover { color: #fff !important; }
76  .hero { width: 100%; height: 100%; overflow: hidden; position: relative; font-family: var(--sans); }
77  .hero-wrap { height: calc(100vh - 66px); }
78  .build-card { transition: transform .3s var(--ease), box-shadow .3s var(--ease); }
79  .build-card:hover { transform: translateY(-5px); box-shadow: 0 28px 56px -26px rgba(28,26,22,0.38); }
80  .b-view { transition: transform .3s var(--ease); }
81  .build-card:hover .b-view { transform: translateX(4px); }
82  /* Testimonials: two-row auto marquee */
83  @keyframes csScroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
84  .cs-marquee { display: flex; flex-direction: column; gap: 18px;
85    -webkit-mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent);
86    mask-image: linear-gradient(to right, transparent, #000 5%, #000 95%, transparent); }
87  .cs-track { display: flex; gap: 18px; width: max-content; animation: csScroll 70s linear infinite; will-change: transform; }
88  .cs-track-rev { animation-direction: reverse; animation-duration: 86s; }
89  .cs-marquee:hover .cs-track { animation-play-state: paused; }
90  @media (prefers-reduced-motion: reduce) { .cs-track { animation: none; } .cs-marquee { overflow-x: auto; } }
91  .cs-swipe { display: none; }
92  /* Testimonials slider (desktop): one full testimonial per slide */
93  .cs-slider { position: relative; max-width: 1160px; margin: 0 auto; }
94  .cs-slide-anim { animation: csFade .55s var(--ease-out) both; }
95  @keyframes csFade { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
96  .cs-arrow { position: absolute; top: 38%; transform: translateY(-50%); width: 46px; height: 46px; border-radius: 50%;
97    border: 1px solid rgba(255,255,255,0.25); background: rgba(20,16,12,0.5); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
98    color: #fff; cursor: pointer; display: flex; align-items: center; justify-content: center; z-index: 3; transition: background .2s, color .2s, border-color .2s; }
99  .cs-arrow:hover { background: var(--terra); color: var(--ink); border-color: var(--terra); }
100  .cs-prev { left: 0; } .cs-next { right: 0; }
101  .cs-dots { display: flex; gap: 9px; justify-content: center; margin-top: 28px; }
102  .cs-dot { width: 8px; height: 8px; padding: 0; border-radius: 50%; border: none; background: rgba(255,255,255,0.3); cursor: pointer; transition: background .2s, transform .2s; }
103  .cs-dot.on { background: var(--terra); transform: scale(1.35); }
104  /* Testimonial cards breathe on hover (pointer devices only) */
105  @media (hover: hover) {
106    .cs-cell { transition: transform .5s var(--ease-out), box-shadow .5s var(--ease-out); }
107    .cs-cell:hover { transform: translateY(-4px); box-shadow: 0 22px 44px -24px rgba(28,26,22,0.35); }
108  }
109  .build-card > div:first-child { transition: transform .55s var(--ease); }
110  .build-card:hover > div:first-child { transform: scale(1.045); }
111  .hero img.bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
112
113  /* ---- Hero: parallax media wrapper + slow Ken Burns push-in ----
114     Anchored to the top (parallax headroom lives at the bottom) and the zoom
115     origin pinned near the speaker so the push-in never crops his head. */
116  .hero-media { position: absolute; left: 0; right: 0; top: 0; height: 100%; overflow: hidden; will-change: transform; background: #15110d; }
117  .hero-media img.bg { transform: scale(1.0); transform-origin: 0% 0%; }
118  .hero-content { will-change: transform, opacity; }
119
120  /* ---- Hero entrance choreography ---- */
121  @keyframes hFade { from { opacity: 0; } to { opacity: 1; } }
122  @keyframes hRise { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: translateY(0); } }
123  @keyframes hlReveal { from { transform: translateY(115%); } to { transform: translateY(0); } }
124  .h-enter { opacity: 0; }
125  .h-nav { animation: hFade .9s var(--ease-out) .05s both; }
126  .h-sub { animation: hRise 1.1s var(--ease-out) .52s both; }
127  .hl-line { display: block; overflow: hidden; padding-bottom: .1em; margin-bottom: -.1em; }
128  .hl-inner { display: inline-block; transform: translateY(115%); animation: hlReveal 1.1s var(--ease-out) both; }
129
130  /* ---- Magnetic primary CTA ---- */
131  .magnetic { position: relative; display: inline-block; will-change: transform; transition: transform .3s var(--ease); }
132  .magnetic-label { display: inline-block; will-change: transform; transition: transform .3s var(--ease); }
133
134  @media (prefers-reduced-motion: reduce) {
135    .hero-media img.bg { animation: none; transform: scale(1.0); }
136    .h-enter, .h-nav, .h-sub, .hl-inner { animation: none !important; opacity: 1 !important; transform: none !important; }
137    .sticky-bar { transition: none; }
138    html { scroll-behavior: auto; }
139  }
140
141  /* Tablet: keep the "practical things" grid at 2 columns */
142  @media (min-width: 769px) and (max-width: 1280px) {
143    .practical-grid { grid-template-columns: repeat(2, 1fr) !important; }
144  }
145
146  /* Offering headings sit on one line on desktop; let them wrap below ~1024 */
147  @media (max-width: 1023px) {
148    .offer-h3 { white-space: normal !important; }
149  }
150  /* Builds heading is wider; let it wrap below ~1100 */
151  @media (max-width: 1100px) {
152    .builds-h2 { white-space: normal !important; }
153  }
154  /* Writing heading is wider still; let it wrap below ~1260 */
155  @media (max-width: 1260px) {
156    .writing-h2 { white-space: normal !important; }
157  }
158
159  /* ============ MOBILE ============ */
160  @media (max-width: 768px) {
161    html, body { overflow-x: hidden; }
162    /* Every multi-column grid collapses to a single column */
163    [style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
164    /* Bento / spanning cells reset so nothing creates implicit extra columns */
165    [style*="grid-template-columns"] > * { grid-column: auto !important; grid-row: auto !important; }
166    /* Offerings: full-bleed colour bands, content inset, sub-items 2x2 */
167    .offer-section { padding-left: 0 !important; padding-right: 0 !important; }
168    .offer-band { padding-left: 0 !important; padding-right: 0 !important; }
169    .offer-wrap { padding-left: 20px !important; padding-right: 20px !important; }
170    .bridge-lead { font-size: 24px !important; line-height: 1.32 !important; }
171    .bridge-sub { font-size: 17px !important; }
172    div.offer-items { grid-template-columns: 1fr 1fr !important; gap: 22px 16px !important; }
173    /* Reserve 2 lines for every step title so the body text lines up across all steps */
174    .offer-items h4 { min-height: 42px !important; }
175    /* Card overlays open at the top (centering hides the heading above the fold on tall modals) */
176    .ov-scrim { align-items: flex-start !important; padding: 14px !important; }
177    .faq-modal { padding: 30px 22px !important; }
178    .faq-modal h2 { font-size: 24px !important; }
179    .faq-steps { grid-template-columns: 1fr !important; }
180    .faq-step { border-left: none !important; padding: 22px 0 0 !important; }
181    .faq-step h3, .faq-step p { min-height: 0 !important; }
182    .faq-viz { height: auto !important; overflow: visible !important; }
183    /* Hiring Manager Enablement card + overlay */
184    /* Uniform preview height for mockup cards; top-aligned with a soft bottom fade so long mockups don't clip harshly */
185    .build-card .hm-front { aspect-ratio: auto !important; height: 200px !important; align-items: flex-start !important; padding: 16px 14px 0 !important; -webkit-mask-image: linear-gradient(180deg, #000 70%, transparent) !important; mask-image: linear-gradient(180deg, #000 70%, transparent) !important; }
186    .hm-cols { flex-direction: column !important; gap: 26px !important; }
187    .hm-cols > div { height: auto !important; overflow: visible !important; -webkit-mask-image: none !important; mask-image: none !important; }
188    .hm-modal { padding: 30px 20px !important; }
189    .hm-modal h2 { font-size: 22px !important; }
190    .mkt-modal h2 { font-size: 22px !important; }
191    .mkt-modal > div { padding-left: 20px !important; padding-right: 20px !important; }
192    .vibe-modal { padding: 26px 20px !important; }
193    .vibe-modal h2 { font-size: 24px !important; }
194    .vibe-cols { flex-direction: column !important; gap: 22px !important; align-items: stretch !important; }
195    .closing-row { flex-direction: column !important; align-items: stretch !important; gap: 28px !important; }
196    .closing-row > div:first-child { flex: none !important; max-width: 100% !important; }
197    /* Tame the fixed desktop padding on section wrappers */
198    section, footer { padding-left: 20px !important; padding-right: 20px !important; }
199    section > div, footer > div { padding-left: 4px !important; padding-right: 4px !important; }
200    /* Big fixed headings scale down */
201    [style*="font-size: 54px"] { font-size: 30px !important; line-height: 1.12 !important; }
202    [style*="font-size: 60px"] { font-size: 32px !important; line-height: 1.12 !important; }
203    /* Hero */
204    .hero-content { padding: 40px 22px 40px !important; }
205    .hero-content nav { display: none !important; }
206    .sticky-bar { height: 56px !important; padding: 0 20px !important; }
207    .sticky-bar nav { display: none !important; }
208    .hero-wrap { height: calc(100vh - 56px) !important; height: calc(100svh - 56px) !important; }
209    /* mobile hero uses a different crop; keep a simple flat band behind the nav */
210    body { background: linear-gradient(#bfbbb2,#bfbbb2) left top / 100% 56px no-repeat, #14110d !important; }
211    /* Hero text sits at the bottom on mobile */
212    .hero-textblock { margin-top: auto !important; margin-bottom: 0 !important; }
213    /* Proof band: darker scrim on mobile so the stat reads over the photo */
214    .proof-scrim { background: linear-gradient(to bottom, rgba(14,12,10,0.86) 0%, rgba(14,12,10,0.6) 45%, rgba(14,12,10,0.72) 100%) !important; }
215    /* Reframe the photo on mobile: shift the crop toward Jamie's side (moves him
216       right) and anchor the zoom at the top (drops his face lower, clear of logo) */
217    .hero-media img.bg { animation: none !important;
217 object-position: 38% top !important; transform: scale(1.0) !important; transform-origin: 50% 0% !important; }
218    /* Founder photo: give the frame a definite height so the image fills it
219       (div.founder-frame beats the [style*="height: 440px"] rule below) */
220    /* padding:0 undoes the [style*="px 80px"] rule that the frame's box-shadow
221       ("40px 80px") accidentally matches - it was leaving a gap above the photo */
222    div.founder-frame { height: 420px !important; min-height: 0 !important; padding: 0 !important; }
223    div.founder-frame img { height: 420px !important; }
224    .hero-headline { font-size: 32px !important; line-height: 1.1 !important; text-wrap: wrap !important; white-space: normal !important; }
225    .hero-headline .hl-line, .hero-headline .hl-inner { white-space: normal !important; overflow: visible !important; }
226    .h-sub { font-size: 16px !important; }
227    /* Tighten big section gaps that were tuned for desktop */
228    [style*="gap: 80px"], [style*="gap: 88px"], [style*="gap: 72px"] { gap: 36px !important; }
229    /* Tighter vertical rhythm on the big section containers (gaps were ~2x too big) */
230    [style*="px 80px"] { padding-top: 26px !important; padding-bottom: 28px !important; }
231    [style*="margin-bottom: 112px"] { margin-bottom: 40px !important; }
232    [style*="gap: 96px"] { gap: 40px !important; }
233    /* Repetitive card rows become horizontal swipe carousels (no more endless scroll) */
234    .cs-grid, .b-cards {
235      display: flex !important;
236      flex-wrap: nowrap !important;
237      overflow-x: auto;
238      scroll-snap-type: x mandatory;
239      -webkit-overflow-scrolling: touch;
240      gap: 14px !important;
241      padding-bottom: 14px !important;
242      scrollbar-width: none;
243    }
244    .cs-grid::-webkit-scrollbar, .b-cards::-webkit-scrollbar { display: none; }
245    .cs-grid > *, .b-cards > * { flex: 0 0 84% !important; scroll-snap-align: center; }
246    /* Scroll-progress slider under each carousel */
247    .carousel-indicator { width: 72px; height: 4px; margin: 18px auto 0; border-radius: 100px; background: rgba(28,26,22,0.12); overflow: hidden; }
248    .carousel-indicator-thumb { height: 100%; border-radius: 100px; background: var(--terra); transition: transform .14s ease-out; }
249    /* Shorter featured build-card media on mobile so cards aren't overly tall */
250    [style*="height: 440px"] { height: 200px !important; }
251    /* Build cards: clamp the body copy so cards aren't overly tall */
252    .b-desc { display: -webkit-box !important; -webkit-line-clamp: 4 !important; -webkit-box-orient: vertical !important; overflow: hidden !important; }
253    /* Testimonials: hide the desktop auto-marquee, show a single swipe carousel like Builds */
254    .cs-marquee, .cs-slider { display: none !important; }
255    .cs-swipe {
256      display: flex !important;
257      flex-wrap: nowrap !important;
258      overflow-x: auto;
259      scroll-snap-type: x mandatory;
260      -webkit-overflow-scrolling: touch;
261      gap: 14px !important;
262      padding-bottom: 14px !important;
263      scrollbar-width: none;
264    }
265    .cs-swipe::-webkit-scrollbar { display: none; }
266    /* taller cards so the section fills the space; one card ~84% wide */
267    .cs-swipe > .cs-mcard { flex: 0 0 84% !important; scroll-snap-align: center; min-height: 300px; }
268    .cs-swipe + .carousel-indicator { background: rgba(255,255,255,0.22); }
269  }
270  @media (max-width: 420px) {
271    .hero-headline { font-size: 27px !important; }
272    [style*="font-size: 54px"], [style*="font-size: 60px"] { font-size: 26px !important; }
273  }
274</style>
275</head>
276<body>
277<div id="root"></div>
278
279<script src="https://unpkg.com/[email protected]/umd/react.production.min.js" integrity="sha384-DGyLxAyjq0f9SPpVevD6IgztCFlnMF6oW/XQGmfe+IsZ8TqEiDrcHkMLKI6fiB/Z" crossorigin="anonymous"></script>
vendor: 1 bytes, line 279
279
280<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js" integrity="sha384-gTGxhz21lVGYNMcdJOyq01Edg0jhn/c22nsx0kyqP0TxaV5WVdsSH1fSDUf5YJj1" crossorigin="anonymous"></script>
vendor: 1 bytes, line 280
280
281<script src="https://unpkg.com/@babel/[email protected]/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
vendor: 1 bytes, line 281
281
282<script src="scroll-reveal.js"></script>
vendor: 1 bytes, line 282
282
283<script src="motion.js"></script>
vendor: 1 bytes, line 283
283
284<script src="carousel-indicator.js"></script>
vendor: 1 bytes, line 284
284
285<script type="text/babel" src="heroes.jsx"></script>
vendor: 1 bytes, line 285
285
286<script type="text/babel" src="offerings.jsx"></script>
vendor: 1 bytes, line 286
286
287<script type="text/babel" src="proof.jsx"></script>
vendor: 1 bytes, line 287
287
288<script type="text/babel" src="about.jsx"></script>
vendor: 1 bytes, line 288
288
289<script type="text/babel" src="casestudies.jsx"></script>
vendor: 1 bytes, line 289
289
290<script type="text/babel" src="builds.jsx"></script>
vendor: 1 bytes, line 290
290
291<script type="text/babel" src="blog.jsx"></script>
vendor: 1 bytes, line 291
291
292<script type="text/babel" src="contact.jsx"></script>
vendor: 1 bytes, line 292
292
293<script type="text/babel">
294  const H = window.RecLabHeroes;
295  const O = window.RecLabOfferings;
296  const PR = window.RecLabProof;
297  const A = window.RecLabAbout;
298  const CS = window.RecLabCases;
299  const B = window.RecLabBuilds;
300  const BL = window.RecLabBlog;
301  const C = window.RecLabContact;
302  const IMG = "assets/workshop.jpg";
303
304  function App() {
305    React.useEffect(() => {
306      window.initScrollReveal && window.initScrollReveal();
307      window.initMotion && window.initMotion();
308      window.initCarouselIndicators && window.initCarouselIndicators();
309    }, []);
310    return (
311      <div>
312        <H.StickyBar />
313        <div className="hero-wrap"><H.FullBleed img={IMG} imgMobile="assets/workshop-mobile.jpg" /></div>
314        <O.Offerings />
315        <CS.CaseStudies />
316        <B.Builds />
317        <A.About />
318        <BL.CardRow />
319        <C.Contact />
320        <C.Footer />
321      </div>
322    );
323  }
324  ReactDOM.createRoot(document.getElementById("root")).render(<App />);
325</script>
325
326</body>
327</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.