PageSourceSearch

https://talkify.nz/pricing

html talkify.nz collected 2026-10-02 00:38:52 UTC 296,582 bytes, 7,716 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,viewport-fit=cover">
6    
6<script>
7        /*
8         * No-flash theme: a visitor's own choice wins, otherwise light.
9         *
10         * We deliberately do NOT follow prefers-color-scheme here. Most people
11         * run their OS in dark mode, so honouring it would mean the light site
12         * is the one almost nobody sees. The toggle in the nav still works and
13         * still persists, so anyone who prefers dark is one click away.
14         */
15        (function () {
16            try {
17                var stored = localStorage.getItem('talkify-theme');
18                document.documentElement.setAttribute('data-theme', stored === 'dark' ? 'dark' : 'light');
19            } catch (e) {
20                document.documentElement.setAttribute('data-theme', 'light');
21            }
22            /* Scripting is on, so .r may hide its block until the observer
23               reveals it. Without this class nothing is ever hidden, which is
24               what a visitor with no JS (or a crawler) sees. */
25            document.documentElement.classList.add('js');
26        })();
27    </script>
27
28    <title>Talkify Pricing | Business AI Agents $129/mo · Personal Assistant $89/mo · No Lock-in</title>
29    <meta name="description"
30          content="Talkify AI phone agent pricing for NZ. Business agents (Broadcast) $129/month at the founding rate for your first 3 months, then $199. Personal Assistant for one person (Shortwave) $89/month. Website Chat $49/month. Custom setups with API integration from $499. No setup fee, no per-seat charges, no lock-in. Free demo, no card needed.">
31
32    
33        <link rel="canonical" href="https://talkify.nz/pricing">
34                    <link rel="icon" type="image/x-icon" href="/favicon.ico">
35    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
36    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
37    <link rel="apple-touch-icon" sizes="180x180" href="/media/branding/brand/app-icon-180.png">
38    <link rel="manifest" href="/site.webmanifest">
39    
40    <meta name="theme-color" content="#318abe">
41
42    <meta property="og:type" content="website">
43    <meta property="og:url" content="https://talkify.nz/pricing">
44    <meta property="og:site_name" content="Talkify">
45    <meta property="og:title" content="Talkify Pricing | Business AI Agents $129/mo · Personal Assistant $89/mo · No Lock-in">
46    <meta property="og:description"
47          content="Talkify AI phone agent pricing for NZ. Business agents (Broadcast) $129/month at the founding rate for your first 3 months, then $199. Personal Assistant for one person (Shortwave) $89/month. Website Chat $49/month. Custom setups with API integration from $499. No setup fee, no per-seat charges, no lock-in. Free demo, no card needed.">
48        <meta property="og:image" content="https://talkify.nz/media/share/pricing.jpg">
49    
50    <meta property="og:image:width" content="1200">
51    <meta property="og:image:height" content="630">
52    <meta property="og:image:type" content="image/jpeg">
53    <meta property="og:image:alt"
54          content="Talkify, AI Phone Agent for New Zealand businesses.">
55    
56    <meta property="og:locale" content="en_NZ">
57
58    <meta name="twitter:card" content="summary_large_image">
59    <meta name="twitter:title" content="Talkify Pricing | Business AI Agents $129/mo · Personal Assistant $89/mo · No Lock-in">
60    <meta name="twitter:description"
61          content="Talkify AI phone agent pricing for NZ. Business agents (Broadcast) $129/month at the founding rate for your first 3 months, then $199. Personal Assistant for one person (Shortwave) $89/month. Website Chat $49/month. Custom setups with API integration from $499. No setup fee, no per-seat charges, no lock-in. Free demo, no card needed.">
62    <meta name="twitter:image" content="https://talkify.nz/media/share/pricing.jpg">
63    <meta name="facebook-domain-verification" content="ic2puw1bkz233rscxrhcl0qol7suu1"/>
64    
65        
65<script
66        type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":["Organization","LocalBusiness"],"@id":"https://talkify.nz#organization","name":"Talkify","url":"https://talkify.nz","logo":"https://talkify.nz/media/branding/talkify-face-gradient-512.png","image":"https://talkify.nz/media/meta-image.jpg","description":"AI Phone Agent for New Zealand and Australian businesses. 24/7 AI receptionist, smart booking, lead qualification, and intelligent call handling. Business agents from $129 per month, Personal Assistant from $89.","telephone":"+64-800-002-967","email":"[email protected]","priceRange":"$$","areaServed":[{"@type":"Country","name":"New Zealand"},{"@type":"Country","name":"Australia"}],"address":{"@type":"PostalAddress","addressCountry":"NZ","addressRegion":"Canterbury","addressLocality":"Christchurch"},"contactPoint":[{"@type":"ContactPoint","telephone":"+64-800-002-967","contactType":"sales","areaServed":"NZ","availableLanguage":["English","te reo Māori"]},{"@type":"ContactPoint","telephone":"+64-3-242-1262","contactType":"demo","areaServed":["NZ","AU"]},{"@type":"ContactPoint","telephone":"+611300852142","contactType":"sales","areaServed":"AU","availableLanguage":["English"]}],"foundingDate":"2024","foundingLocation":{"@type":"Place","address":{"@type":"PostalAddress","addressCountry":"NZ","addressLocality":"Christchurch"}},"parentOrganization":{"@type":"Organization","name":"D3V Services Limited","address":{"@type":"PostalAddress","addressCountry":"NZ","addressRegion":"Canterbury","addressLocality":"Christchurch"}},"knowsAbout":["AI receptionist","Virtual receptionist","Phone answering service","After-hours call answering","AI phone agent","Appointment booking","Outbound calling campaigns","Business phone numbers"],"sameAs":["https://www.facebook.com/profile.php?id=61572226258048","https://www.instagram.com/talkifynz/","https://www.linkedin.com/company/talkify-nz/"]},{"@type":"WebSite","@id":"https://talkify.nz#website","name":"Talkify","url":"https://talkify.nz","publisher":{"@id":"https://talkify.nz#organization"},"inLanguage":"en-NZ"},{"@type":"Service","@id":"https://talkify.nz#service","name":"Talkify AI Phone Agent","description":"AI-powered phone agent providing 24/7 AI reception, smart booking, lead qualification and intelligent call handling for New Zealand and Australian businesses.","provider":{"@id":"https://talkify.nz#organization"},"areaServed":[{"@type":"Country","name":"New Zealand"},{"@type":"Country","name":"Australia"}],"serviceType":"AI Phone Agent","category":"Business Phone System","audience":{"@type":"BusinessAudience","audienceType":"Small and medium businesses"},"hasOfferCatalog":{"@type":"OfferCatalog","name":"Talkify Plans","itemListElement":[{"@type":"Offer","name":"Shortwave (Personal Assistant, for one person)","price":"89","priceCurrency":"NZD"},{"@type":"Offer","name":"Broadcast (Business agents)","price":"129","priceCurrency":"NZD"},{"@type":"Offer","name":"Website Chat","price":"49","priceCurrency":"NZD"},{"@type":"Offer","name":"Custom Setup","price":"499","priceCurrency":"NZD","description":"From price. Includes custom API integration; 12-month contract."},{"@type":"Offer","name":"Fleet","priceCurrency":"NZD","description":"Custom pricing for multi-location operators"}]}}]}</script>
66
67
68    
69    
70            <!-- Google Analytics -->
vendor: 68 bytes, lines 70-71
70
71    <script async src="https://www.googletagmanager.com/gtag/js?id=
71G-YS6V82V8W9
vendor: 16 bytes, lines 71-72
71"></script>
72    
72<script>
73        
vendor: 176 bytes, lines 73-80
73window.dataLayer = window.dataLayer || [];
74
75        function gtag() {
76            dataLayer.push(arguments);
77        }
78
79        gtag('js', new Date());
80        gtag('config', "
80G-YS6V82V8W9
vendor: 12 bytes, lines 80-81
80");
81        
81gtag('config', "AW-18227321636");
82    </script>
82
83    
84    
85    
85<script>
86    // Safe before gtag has loaded: dataLayer is already an array by here and
87    // gtag() only pushes onto it, so an event queued early still gets sent.
88    window.talkifyTrack = function (name, params) {
89        if (typeof gtag !== 'function') { return; }
90        gtag('event', name, params || {});
91    };
92    </script>
92
93
94        <!-- Google Tag Manager -->
95    
95<script>
vendor: 534 bytes, lines 95-107
95(function (w, d, s, l, i) {
96            w[l] = w[l] || [];
97            w[l].push({
98                'gtm.start':
99                    new Date().getTime(), event: 'gtm.js'
100            });
101            var f = d.getElementsByTagName(s)[0],
102                j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
103            j.async = true;
104            j.src =
105                'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
106            f.parentNode.insertBefore(j, f);
107        })(window, document, 'script', 'dataLayer', "
107GTM-TTGHDLQ4
vendor: 3 bytes, line 107
107");
107</script>
107
108    <!-- End Google Tag Manager -->
109    <link rel="preconnect" href="https://fonts.googleapis.com">
110    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
111    <!-- Meta Pixel Code -->
112    
112<script>
vendor: 679 bytes, lines 112-131
112
113        !function (f, b, e, v, n, t, s) {
114            if (f.fbq) return;
115            n = f.fbq = function () {
116                n.callMethod ?
117                    n.callMethod.apply(n, arguments) : n.queue.push(arguments)
118            };
119            if (!f._fbq) f._fbq = n;
120            n.push = n;
121            n.loaded = !0;
122            n.version = '2.0';
123            n.queue = [];
124            t = b.createElement(e);
125            t.async = !0;
126            t.src = v;
127            s = b.getElementsByTagName(e)[0];
128            s.parentNode.insertBefore(t, s)
129        }(window, document, 'script',
130            'https://connect.facebook.net/en_US/fbevents.js');
131        fbq('init', '
1311560743332225994
vendor: 42 bytes, lines 131-133
131');
132        fbq('track', 'PageView');
133    
133</script>
133
134    <noscript><img height="1" width="1" style="display:none"
135                   src="https://www.facebook.com/tr?id=1560743332225994&ev=PageView&noscript=1"
136        /></noscript>
137    <!-- End Meta Pixel Code -->
138        
139    <link
140        href="https://fonts.googleapis.com/css2?family=Outfit:[email protected]&family=JetBrains+Mono:wght@400;500&display=swap"
141        rel="stylesheet">
142
143    <style>
144        /* ====== TOKENS ======
145           The 2026 brand guide, in one place.
146
147           Roles, not decoration:
148             blue   #318ABE  PRIMARY. Links, primary buttons, focus rings, the
149                             mark, the start of the gradient.
150             green  #A3D654  ACCENT. Live dots, success, the end of the
151                             gradient, small highlights on dark ground.
152             ink    #101820  Body copy on light, the dark surface on dark.
153
154           Green is never small text on a light ground: #A3D654 on white is
155           1.6:1. Where a word genuinely has to be green and small, use
156           --green-ink.
157
158           Naming note: this sheet grew up with --ink as the page GROUND and
159           --paper as the text on it, and ~65 pages are written against that,
160           so the pair keeps its meaning. :root is the dark treatment;
161           html[data-theme="light"] is what almost every visitor sees, because
162           the no-flash script picks light unless somebody has chosen dark. */
163        :root {
164            /* -- brand constants, identical in both themes -- */
165            --blue: #318ABE;
166            --blue-dark: #256D97;
167            --green: #A3D654;
168            --green-ink: #4F6B18; /* the rare small-green-text case, on light */
169            --brand-blue: #318ABE; /* legacy aliases, still referenced by pages */
170            --brand-blue-bright: #5BC7E8;
171            --brand-green: #A3D654;
172            --brand-green-bright: #B9DD80;
173
174            /* -- dark treatment -- */
175            --ink: #101820;
176            --ink-2: #16202A;
177            --ink-3: #1D2831;
178            --line: rgba(255, 255, 255, .10);
179            --line-2: rgba(255, 255, 255, .18);
180            --paper: #FFFFFF;
181            --paper-warm: #F2F4F5;
182            --bone: #C6CCD1;
183            --mute: #9AA2A8;
184            --mute-2: #79828A;
185
186            /* Primary. Blue carries links and fills here. --plasma is the same
187               family: the .blue / .eb-blue / .plasma-text idiom stays blue, the
188               brand simply has one primary rather than the two accents this
189               sheet used to run. Green is --accent, and only --accent. */
190            --signal: #4FA6D8;
191            --signal-warm: #7BC4E9;
192            --plasma: #4FA6D8;
193            --plasma-bright: #7BC4E9;
194            --accent: #A3D654; /* live, success, gradient end */
195            --coral: #FF5E3A;
196            --violet: #7C5BFF;
197            /* 45deg blue to green, hero surfaces only, never twice on a page */
198            --grad: linear-gradient(45deg, var(--blue) 0%, var(--green) 100%);
199            --grad-soft: linear-gradient(45deg, color-mix(in srgb, var(--blue) 18%, transparent) 0%, color-mix(in srgb, var(--green) 18%, transparent) 100%);
200
201            /* -- type --
202               Outfit does the display, heading and body work; JetBrains Mono
203               does labels. --serif and --serif-italic are kept as names because
204               ~65 pages reference them, but both now resolve to Outfit: there
205               is no second face on the site. */
206            --sans: 'Outfit', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
207            --serif: 'Outfit', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
208            --serif-italic: 'Outfit', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
209            --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
210
211            /* One scale, so a page cannot invent a size. The old sheet ran
212               138px headlines over 13.5px body copy; nothing here is below
213               14px and nothing above 96px. */
214            --t-display: clamp(44px, 6.4vw, 96px);
215            --t-h2: clamp(34px, 4.4vw, 60px);
216            --t-h3: clamp(22px, 2.2vw, 30px);
217            --t-sub: clamp(20px, 2vw, 26px);
218            --t-lede: 17px;
219            --t-body: 16px;
220            --t-small: 14px;
221            --t-label: 11.5px;
222            --lh-display: 1.04;
223            --lh-head: 1.12;
224            --lh-body: 1.6;
225            --ls-head: -.02em; /* the guide's -2% on headings */
226            --ls-label: .13em; /* the guide's +13% on mono labels */
227
228            --ease: cubic-bezier(.2, .7, .2, 1);
229            --ease-out: cubic-bezier(.16, 1, .3, 1);
230
231            --shell-pad: clamp(20px, 3.5vw, 56px);
232            /* Section rhythm, so a new page stops reaching for
233               style="padding-top:0". See section.shell and .shell.flush. */
234            --space-section: clamp(72px, 8vw, 120px);
235            --space-section-tight: clamp(52px, 5.5vw, 80px);
236
237            /* -- semantic tokens (recurring patterns that must flip per theme) -- */
238            --on-accent: #0B1116; /* text sitting on a brand fill */
239            --panel: #16202A;
240            --panel-2: #1A242E;
241            --panel-grad: linear-gradient(140deg, #18232D, #101820);
242            --panel-grad-160: linear-gradient(160deg, #16202A, #101820);
243            --deck-grad: linear-gradient(180deg, #18232D, #101820);
244            --surface: rgba(255, 255, 255, .02);
245            --surface-2: rgba(255, 255, 255, .04);
246            --surface-3: rgba(255, 255, 255, .06);
247            --scrim-strong: rgba(16, 24, 32, .85);
248            --scrim-mid: rgba(16, 24, 32, .6);
249            --scrim-soft: rgba(16, 24, 32, .4);
250            --scrim-solid: #101820;
251            --shadow-deep: rgba(0, 0, 0, .8);
252            --shadow-soft: rgba(0, 0, 0, .5);
253            --logo-light: none; /* logo image swap: see .logo img rules */
254        }
255
256        /* ====== LIGHT THEME ====== */
257        html[data-theme="light"] {
258            --ink: #FFFFFF;
259            --ink-2: #F7F8F8; /* the guide's surface */
260            --ink-3: #EDEFEF;
261            --line: #E9EAEA; /* the guide's line */
262            --line-2: #D5D8D9;
263            --paper: #101820; /* the guide's ink, as body copy */
264            --paper-warm: #1B242C;
265            --bone: #3F4A52; /* long-form body copy, 9.6:1 on white */
266            --mute: #5A6268; /* the guide's grey, 6.2:1 on white */
267            --mute-2: #79828A;
268
269            /* On white, #318ABE is 3.8:1, which is short of AA for a 14px
270               label or a link in running text. The guide's own blue dark is
271               5.7:1, so that is what carries text and button fills here;
272               #318ABE stays the brand blue for the mark, the gradient and
273               anything large. */
274            --signal: #256D97;
275            --signal-warm: #1F5D80;
276            --plasma: #256D97;
277            --plasma-bright: #1F5D80;
278            --accent: #A3D654;
279
280            --on-accent: #FFFFFF; /* white on the blue fill: 5.7:1 */
281            --panel: #F7F8F8;
282            --panel-2: #EFF1F1;
283            --panel-grad: linear-gradient(140deg, #FFFFFF, #F2F4F4);
284            --panel-grad-160: linear-gradient(160deg, #FFFFFF, #F2F4F4);
285            --deck-grad: linear-gradient(180deg, #FFFFFF, #F7F8F8);
286            --surface: rgba(16, 24, 32, .03);
287            --surface-2: rgba(16, 24, 32, .05);
288            --surface-3: rgba(16, 24, 32, .07);
289            --scrim-strong: rgba(255, 255, 255, .88);
290            --scrim-mid: rgba(255, 255, 255, .58);
291            --scrim-soft: rgba(255, 255, 255, .36);
292            --scrim-solid: #FFFFFF;
293            --shadow-deep: rgba(16, 24, 32, .20);
294            --shadow-soft: rgba(16, 24, 32, .12);
295        }
296
297        html {
298            transition: background-color .35s var(--ease), color .35s var(--ease);
299        }
300
301        @media (prefers-reduced-motion: reduce) {
302            html {
303                transition: none
304            }
305        }
306
307        /* Light-theme atmosphere, the dark grain/scanline/vignette overlays don't suit a light ground */
308        html[data-theme="light"] .grain {
309            opacity: .12;
310            mix-blend-mode: multiply
311        }
312
313        html[data-theme="light"] .scanlines {
314            display: none
315        }
316
317        html[data-theme="light"] .vignette {
318            background: radial-gradient(120% 80% at 50% 0%, transparent 45%, rgba(20, 22, 15, .06) 100%)
319        }
320
321        /* Theme-swappable photos: elements pass --shot-dark / --shot-light as inline custom props */
322        html[data-theme="light"] .hero-bg .photo {
323            background-image: var(--shot-light, var(--shot-dark))
324        }
325
326        html[data-theme="light"] .hero-photo {
327            background-image: var(--shot-light, var(--shot-dark))
328        }
329
330        html[data-theme="light"] .endcta .endcta-photo {
331            background-image: url('/media/frontend/nz-skyline-day.jpg');
332            opacity: .5;
333            filter: saturate(1) contrast(1)
334        }
335
336        /* ── The 2026 mark (x-brand.logo) ──────────────────────────────────
337           The lockup is drawn inline so the spark eye can wink and so the
338           word can take the theme's colour rather than needing a file per
339           combination. Base here is the dark treatment, matching :root; the
340           light theme, which is what the no-flash script picks unless somebody
341           has chosen dark, inverts the pair. The gradient circle is the same
342           blue-to-green in both, per the brand guide. */
343        .tk-logo {
344            --tk-word: #ffffff;
345            --tk-ground: #101820;
346            display: block;
347        }
348
349        html[data-theme="light"] .tk-logo {
350            --tk-word: #101820;
351            --tk-ground: #ffffff;
352        }
353
354        /* The guide's one permitted movement: 300ms close on a 4 second
355           cycle, on an inner group so the star keeps its translate and scale. */
356        @keyframes tk-blink {
357            0%, 92%, 100% { transform: scaleY(1) }
358            95% { transform: scaleY(.08) }
359        }
360
361        .tk-logo .tk-eye {
362            animation: tk-blink 4s ease-in-out infinite;
363            transform-origin: 50px 50px
364        }
365
366        @media (prefers-reduced-motion: reduce) {
367            .tk-logo .tk-eye {
368                animation: none
369            }
370        }
371
372        /* Theme toggle button */
373        .theme-toggle {
374            width: 40px;
375            height: 40px;
376            border-radius: 10px;
377            border: 1px solid var(--line);
378            display: grid;
379            place-items: center;
380            color: var(--bone);
381            transition: .25s var(--ease);
382            flex: 0 0 auto
383        }
384
385        .theme-toggle:hover {
386            border-color: var(--signal);
387            color: var(--paper)
388        }
389
390        .theme-toggle .icon-moon {
391            display: none
392        }
393
394        html[data-theme="light"] .theme-toggle .icon-sun {
395            display: none
396        }
397
398        html[data-theme="light"] .theme-toggle .icon-moon {
399            display: block
400        }
401
402        * {
403            box-sizing: border-box;
404            margin: 0;
405            padding: 0
406        }
407
408        html, body {
409            background: var(--ink);
410            color: var(--paper);
411            font-family: var(--sans);
412            font-weight: 400;
413            -webkit-font-smoothing: antialiased;
414            text-rendering: optimizeLegibility;
415            overflow-x: hidden
416        }
417
418        body {
419            font-size: var(--t-body);
420            line-height: var(--lh-body);
421            letter-spacing: 0
422        }
423
424        a {
425            color: inherit;
426            text-decoration: none
427        }
428
429        img, svg {
430            display: block;
431            max-width: 100%
432        }
433
434        button {
435            font: inherit;
436            color: inherit;
437            background: none;
438            border: 0;
439            cursor: pointer
440        }
441
442        input, textarea, select {
443            font: inherit;
444            color: inherit
445        }
446
447        ::selection {
448            background: var(--signal);
449            color: var(--on-accent)
450        }
451
452        /* Labels: JetBrains Mono 500, uppercase, +13% tracking. */
453        .mono {
454            font-family: var(--mono);
455            font-weight: 500;
456            letter-spacing: var(--ls-label)
457        }
458
459        .serif {
460            font-family: var(--serif)
461        }
462
463        /* The accent idiom.
464           It was a Fraunces italic in green. Outfit ships no italic, and a
465           browser-synthesised slant on a geometric sans at 96px looks broken,
466           so the accent is now weight and colour: Outfit 600 in the primary
467           blue. The !important is deliberate and is the only one in this
468           sheet: several pages set font-style on their own .it descendants
469           and would otherwise reintroduce the fake slant. */
470        .italic, .it, .blue {
471            font-family: var(--serif);
472            font-style: normal !important;
473            font-weight: 600
474        }
475
476        .signal-text {
477            color: var(--signal)
478        }
479
480        .plasma-text {
481            color: var(--plasma-bright)
482        }
483
484        /* ====== ATMOSPHERE ====== */
485        .grain {
486            position: fixed;
487            inset: 0;
488            pointer-events: none;
489            z-index: 200;
490            mix-blend-mode: overlay;
491            opacity: .32;
492            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
493            background-size: 160px
494        }
495
496        .scanlines {
497            position: fixed;
498            inset: 0;
499            pointer-events: none;
500            z-index: 201;
501            opacity: .04;
502            background-image: linear-gradient(to bottom, transparent 0, transparent 2px, rgba(255, 255, 255, .6) 2px, rgba(255, 255, 255, .6) 3px);
503            background-size: 100% 3px
504        }
505
506        .vignette {
507            position: fixed;
508            inset: 0;
509            pointer-events: none;
510            z-index: 199;
511            background: radial-gradient(120% 80% at 50% 0%, transparent 40%, rgba(0, 0, 0, .5) 100%)
512        }
513
514        @keyframes pulse {
515            0%, 100% {
516                transform: scale(1);
517                opacity: 1
518            }
519            50% {
520                transform: scale(1.4);
521                opacity: .6
522            }
523        }
524
525        @keyframes slide {
526            from {
527                transform: translateX(0)
528            }
529            to {
530                transform: translateX(-50%)
531            }
532        }
533
534        /* ====== NAV ====== */
535        .nav {
536            position: fixed;
537            top: 0;
538            left: 0;
539            right: 0;
540            z-index: 80;
541            display: grid;
542            grid-template-columns:1fr auto 1fr;
543            align-items: center;
544            gap: 24px;
545            padding: 18px var(--shell-pad);
546            background: linear-gradient(180deg, var(--scrim-strong), var(--scrim-soft) 80%, transparent);
547            backdrop-filter: blur(10px) saturate(140%);
548            -webkit-backdrop-filter: blur(10px) saturate(140%)
549        }
550
551        .nav .logo {
552            display: flex;
553            align-items: center;
554            gap: 14px
555        }
556
557        .nav .logo .mark {
558            width: 34px;
559            height: 34px;
560            border-radius: 10px;
561            background: var(--grad);
562            display: grid;
563            place-items: center;
564            position: relative;
565            overflow: hidden;
566            box-shadow: 0 0 30px rgba(49, 138, 190, .4)
567        }
568
569        .nav .logo .mark::after {
570            content: "";
571            position: absolute;
572            inset: 0;
573            background: radial-gradient(circle at 30% 20%, rgba(255, 255, 255, .55), transparent 50%)
574        }
575
576        .nav .logo .mark svg {
577            width: 18px;
578            height: 18px;
579            color: var(--ink);
580            position: relative;
581            z-index: 1
582        }
583
584        .nav .logo b {
585            font-family: var(--serif);
586            font-weight: 500;
587            font-size: 22px;
588            letter-spacing: -.02em
589        }
590
591        .nav .logo .tag {
592            font-family: var(--mono);
593            font-size: var(--t-label);
594            color: var(--mute);
595            text-transform: uppercase;
596            letter-spacing: .18em;
597            margin-left: 6px;
598            padding: 3px 6px;
599            border: 1px solid var(--line);
600            border-radius: 4px
601        }
602
603        .nav ul {
604            display: flex;
605            gap: 6px;
606            list-style: none
607        }
608
609        .nav ul a {
610            display: inline-flex;
611            align-items: center;
612            gap: 6px;
613            padding: 8px 14px;
614            border-radius: 999px;
615            font-size: 13px;
616            color: var(--bone);
617            transition: .25s var(--ease)
618        }
619
620        .nav ul a:hover {
621            background: var(--ink-3);
622            color: var(--paper)
623        }
624
625        .nav ul a.is-active {
626            background: var(--ink-3);
627            color: var(--paper)
628        }
629
630        .nav ul a.is-active .dot {
631            background: var(--signal);
632            box-shadow: 0 0 8px var(--signal)
633        }
634
635        .nav ul a .dot {
636            width: 5px;
637            height: 5px;
638            border-radius: 50%;
639            background: var(--mute)
640        }
641
642        /* ── Agents mega-menu ─────────────────────────────────────────────
643           Desktop: opens on hover, on focus, or on click (the click state is
644           what mobile uses, where the whole nav is a stacked panel and the
645           menu becomes an inline accordion). */
646        .nav-drop {
647            position: relative
648        }
649
650        .nav-drop-btn {
651            display: inline-flex;
652            align-items: center;
653            gap: 6px;
654            padding: 8px 14px;
655            border-radius: 999px;
656            font-family: var(--sans);
657            font-size: 13px;
658            color: var(--bone);
659            background: none;
660            border: 0;
661            cursor: pointer;
662            transition: .25s var(--ease)
663        }
664
665        .nav-drop-btn:hover,
666        .nav-drop-btn.is-active {
667            background: var(--ink-3);
668            color: var(--paper)
669        }
670
671        .nav-drop-btn.is-active .dot {
672            background: var(--signal);
673            box-shadow: 0 0 8px var(--signal)
674        }
675
676        .nav-drop-btn .dot {
677            width: 5px;
678            height: 5px;
679            border-radius: 50%;
680            background: var(--mute)
681        }
682
683        .nav-drop-chev {
684            transition: transform .25s var(--ease);
685            opacity: .7
686        }
687
688        .nav-drop.is-open .nav-drop-chev {
689            transform: rotate(180deg)
690        }
691
692        .nav-drop-panel {
693            position: absolute;
694            top: calc(100% + 10px);
695            left: 0;
696            z-index: 90;
697            display: none;
698            grid-template-columns: minmax(240px, 1fr) minmax(300px, 1fr);
699            gap: 26px;
700            min-width: 620px;
701            padding: 22px;
702            background: var(--ink-2);
703            border: 1px solid var(--line);
704            border-radius: 16px;
705            box-shadow: 0 24px 60px rgba(0, 0, 0, .35)
706        }
707
708        /* Invisible bridge across the 10px gap between the button and the panel.
709           Without it the pointer leaves .nav-drop on the way down and the menu
710           shuts before you get there, unless you move quickly. It spans the full
711           width of the panel, so a diagonal approach is covered too. */
712        .nav-drop-panel::before {
713            content: "";
714            position: absolute;
715            left: 0;
716            right: 0;
717            top: -12px;
718            height: 12px
719        }
720
721        /* One-column variant, for a menu that holds a single short list. The
722           base two-column grid is what Agents uses. */
723        .nav-drop-panel--single {
724            grid-template-columns: 1fr;
725            min-width: 340px
726        }
727
728        /* Industries runs to twenty-three entries in four sectors, so it takes
729           a third column rather than a taller one. Sector headings do the
730           finding; the A-Z inside each does the rest. */
731        .nav-drop-panel--industries {
732            grid-template-columns: repeat(3, minmax(190px, 1fr));
733            min-width: 660px
734        }
735
736        .nav-drop:hover .nav-drop-panel,
737        .nav-drop:focus-within .nav-drop-panel,
738        .nav-drop.is-open .nav-drop-panel {
739            display: grid
740        }
741
742        .nav-drop-hd {
743            display: block;
744            font-family: var(--mono);
745            font-size: var(--t-label);
746            letter-spacing: .18em;
747            text-transform: uppercase;
748            color: var(--mute);
749            margin-bottom: 10px
750        }
751
752        /* These selectors carry `.nav ul` on purpose: the generic `.nav ul a`
753           rule above makes every nav link an inline-flex pill, which would put
754           each label and its description side by side instead of stacked. */
755        .nav ul .nav-drop-panel a {
756            display: block;
757            padding: 9px 10px;
758            border-radius: 10px;
759            font-size: var(--t-small);
760            line-height: 1.35;
761            color: var(--paper);
762            transition: .2s var(--ease)
763        }
764
765        .nav ul .nav-drop-panel a > span {
766            display: block;
767            font-weight: 500
768        }
769
770        .nav ul .nav-drop-panel a em {
771            display: block;
772            font-style: normal;
773            font-size: 11.5px;
774            line-height: 1.4;
775            color: var(--mute);
776            margin-top: 3px
777        }
778
779        .nav ul .nav-drop-panel a:hover {
780            background: var(--ink-3)
781        }
782
783        .nav-drop-col {
784            display: flex;
785            flex-direction: column;
786            align-items: stretch
787        }
788
789        /* A sector column's links sit tighter than the described Agents rows:
790           they are one word each and there is no <em> under them. */
791        .nav ul .nav-drop-panel--industries a:not(.nav-drop-all) {
792            padding-top: 6px;
793            padding-bottom: 6px
794        }
795
796        /* margin-top:auto pins it to the foot of its column, so both "See all"
797           links line up even though the two columns are different lengths. */
798        .nav ul .nav-drop-all {
799            margin-top: auto;
800            padding-top: 12px;
801            border-top: 1px solid var(--line);
802            border-radius: 0;
803            color: var(--signal);
804            font-weight: 500;
805            /* The arrow belongs on the same line as the words. In a sector
806               column ~190px wide it wrapped onto a line of its own. */
807            white-space: nowrap
808        }
809
810        .nav ul .nav-drop-all:hover {
811            background: none;
812            opacity: .8
813        }
814
815        /* `a` is in the selector to out-specify `.nav ul .nav-drop-panel a >
816           span`, which is display:block for the stacked label-and-description
817           rows. Without it the arrow was a block of its own and dropped onto a
818           second line under the words. */
819        .nav ul a.nav-drop-all > span {
820            display: inline;
821            font-weight: 500
822        }
823
824        .nav .actions {
825            justify-self: end;
826            display: flex;
827            align-items: center;
828            gap: 10px
829        }
830
831        .nav .num {
832            font-family: var(--mono);
833            font-size: 13px;
834            color: var(--bone);
835            padding: 8px 12px;
836            border: 1px solid var(--line);
837            border-radius: 8px;
838            transition: .25s;
839            white-space: nowrap
840        }
841
842        .nav .num:hover {
843            border-color: var(--signal);
844            color: var(--paper)
845        }
846
847        .nav .num b {
848            color: var(--signal);
849            font-weight: 500
850        }
851
852        /* The signup pill's two faces: the wide desktop one links to /signup
853           (a tel: link on a desktop rings nothing), the mobile one is a phone
854           glyph that actually dials. Only ever one on screen. */
855        .nav .num-call {
856            display: none;
857            align-items: center;
858            justify-content: center;
859            padding: 8px 10px;
860            line-height: 0
861        }
862
863        .menu-btn {
864            display: none
865        }
866
867        .btn {
868            display: inline-flex;
869            align-items: center;
870            gap: 10px;
871            padding: 12px 20px;
872            border-radius: 999px;
873            font-size: var(--t-small);
874            font-weight: 500;
875            letter-spacing: 0;
876            transition: .25s var(--ease);
877            border: 1px solid transparent;
878            white-space: nowrap
879        }
880
881        /* Primary is Talkify Blue, per the guide. Green is the accent and
882           never the button. */
883        .btn-primary {
884            background: var(--signal);
885            color: var(--on-accent)
886        }
887
888        .btn-primary:hover {
889            background: var(--signal-warm);
890            transform: translateY(-1px);
891            box-shadow: 0 8px 26px -8px color-mix(in srgb, var(--signal) 55%, transparent)
892        }
893
894        .btn-blue {
895            background: var(--plasma);
896            color: var(--on-accent)
897        }
898
899        .btn-blue:hover {
900            background: var(--plasma-bright);
901            transform: translateY(-1px)
902        }
903
904        .btn-ghost {
905            border-color: var(--paper);
906            color: var(--paper)
907        }
908
909        .btn-ghost:hover {
910            background: var(--paper);
911            color: var(--ink);
912            border-color: var(--paper)
913        }
914
915        /* One focus ring for every interactive thing on the site. */
916        .btn:focus-visible, a:focus-visible, button:focus-visible,
917        input:focus-visible, select:focus-visible, textarea:focus-visible,
918        summary:focus-visible, [tabindex]:focus-visible {
919            outline: 2px solid var(--blue);
920            outline-offset: 2px
921        }
922
923        .btn .arr {
924            transition: transform .25s var(--ease)
925        }
926
927        .btn:hover .arr {
928            transform: translateX(3px)
929        }
930
931        .btn-lg {
932            padding: 16px 28px;
933            font-size: 16px
934        }
935
936        /* ====== EYEBROW ====== */
937        .eyebrow {
938            display: inline-flex;
939            align-items: center;
940            gap: 10px;
941            font-family: var(--mono);
942            font-weight: 500;
943            font-size: var(--t-label);
944            text-transform: uppercase;
945            letter-spacing: var(--ls-label);
946            color: var(--mute);
947            padding: 6px 10px;
948            border: 1px solid var(--line);
949            border-radius: 999px;
950            background: var(--surface)
951        }
952
953        /* Green is the live state, which is exactly what this dot is. */
954        .eyebrow .pin {
955            width: 6px;
956            height: 6px;
957            border-radius: 50%;
958            background: var(--accent);
959            box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 70%, transparent)
960        }
961
962        .eyebrow.eb-blue .pin {
963            background: var(--plasma);
964            box-shadow: 0 0 10px var(--plasma)
965        }
966
967        .eyebrow.eb-coral .pin {
968            background: var(--coral);
969            box-shadow: 0 0 10px var(--coral)
970        }
971
972        /* ====== HERO ====== */
973        /* The nav is 84px and fixed, so 160px of padding was 76px of nothing
974           above the headline. On a laptop that pushed the whole hero, and the
975           dialler beside it, most of the way down the fold before a word was
976           read. 120 keeps a comfortable 36px under the bar. */
977        .hero {
978            position: relative;
979            padding: 120px var(--shell-pad) 80px;
980            overflow: hidden
981        }
982
983        .hero-bg {
984            position: absolute;
985            inset: 0;
986            pointer-events: none;
987            z-index: 0;
988            overflow: hidden
989        }
990
991        .hero-bg .photo {
992            position: absolute;
993            inset: 0;
994            background-image: var(--shot-dark);
995            background-position: center right;
996            background-size: cover;
997            background-repeat: no-repeat;
998            opacity: .78;
999            filter: saturate(.85) contrast(1.05)
1000        }
1001
1002        .hero-bg .photo::after {
1003            content: "";
1004            position: absolute;
1005            inset: 0;
1006            background: linear-gradient(90deg, var(--scrim-solid) 0%, var(--scrim-strong) 28%, var(--scrim-mid) 50%, var(--scrim-soft) 72%, var(--scrim-mid) 100%),
1007            linear-gradient(180deg, var(--scrim-soft) 0%, transparent 30%, transparent 70%, var(--scrim-mid) 100%)
1008        }
1009
1010        .hero-bg .glow1 {
1011            position: absolute;
1012            top: -20%;
1013            left: -10%;
1014            width: 80%;
1015            height: 120%;
1016            background: radial-gradient(closest-side, rgba(49, 138, 190, .20), transparent 70%);
1017            filter: blur(20px);
1018            mix-blend-mode: screen
1019        }
1020
1021        .hero-bg .glow2 {
1022            position: absolute;
1023            bottom: -30%;
1024            right: -10%;
1025            width: 70%;
1026            height: 120%;
1027            background: radial-gradient(closest-side, color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%);
1028            filter: blur(20px);
1029            mix-blend-mode: screen
1030        }
1031
1032        .hero-bg .grid-lines {
1033            position: absolute;
1034            inset: 0;
1035            background-image: linear-gradient(to right, var(--line) 1px, transparent 1px), linear-gradient(to bottom, var(--line) 1px, transparent 1px);
1036            background-size: 80px 80px;
1037            mask-image: radial-gradient(ellipse at center, #000, transparent 70%);
1038            opacity: .5
1039        }
1040
1041        /* The two hero columns are rarely the same height: the copy runs long
1042           on some pages, the photo is very tall on others, and the transcript
1043           deck is short everywhere. Bottom-aligning them dropped whichever was
1044           shorter to the floor and left a hole above it, which is what the
1045           debt-collection, outbound-calls, call-centre and pricing heroes were
1046           all showing. Centred, the difference is split top and bottom instead
1047           of piling up in one corner. */
1048        .hero-shell {
1049            position: relative;
1050            z-index: 1;
1051            display: grid;
1052            grid-template-columns:1.4fr 1fr;
1053            gap: 64px;
1054            align-items: center
1055        }
1056
1057        /* A hero photo is the exception: it is a full-bleed panel, so it fills
1058           the row rather than floating in the middle of it. */
1059        .hero-shell > .hero-photo {
1060            align-self: stretch
1061        }
1062
1063        .hero-shell.single {
1064            grid-template-columns:1fr;
1065            max-width: 1200px
1066        }
1067
1068        /* Heroes whose right column is a tall form. Bottom-aligning them drops a
1069           dead band above the headline and top-aligning just moves it below, so
1070           the left column instead stretches to the form's height and spreads its
1071           groups over it. Needs the left column's content in group wrappers. */
1072        .hero-shell.top {
1073            align-items: stretch
1074        }
1075
1076        .hero-shell.top > .hero-side {
1077            display: flex;
1078            flex-direction: column;
1079            justify-content: space-between
1080        }
1081
1082        h1.display {
1083            margin-top: 28px;
1084            font-family: var(--serif);
1085            font-weight: 600;
1086            font-size: var(--t-display);
1087            line-height: var(--lh-display);
1088            letter-spacing: var(--ls-head);
1089            padding-bottom: .06em
1090        }
1091
1092        /* The resting state IS the default. It used to be
1093           translateY(110%) inside overflow:hidden with a 1s animation, so the
1094           largest element on the page -- the LCP element -- was off screen
1095           until the animation ran, and never arrived at all if animations
1096           were suppressed. */
1097        h1.display .ln {
1098            display: block;
1099            padding-bottom: .06em;
1100            padding-right: .06em
1101        }
1102
1103        h1.display .ln span {
1104            display: inline-block;
1105            padding-bottom: .04em
1106        }
1107
1108        h1.display .it,
1109        h1.display .blue {
1110            font-family: var(--serif);
1111            font-style: normal;
1112            font-weight: 600;
1113            color: var(--signal)
1114        }
1115
1116        h1.display .out {
1117            color: var(--bone)
1118        }
1119
1120        @keyframes rise {
1121            from {
1122                opacity: 0;
1123                transform: translateY(16px)
1124            }
1125            to {
1126                opacity: 1;
1127                transform: none
1128            }
1129        }
1130
1131        @media (prefers-reduced-motion: no-preference) {
1132            h1.display .ln {
1133                overflow: hidden
1134            }
1135
1136            h1.display .ln span {
1137                animation: rise .4s var(--ease-out) both
1138            }
1139
1140            .hero h1.display .ln:nth-child(1) span { animation-delay: 0s }
1141
1142            .hero h1.display .ln:nth-child(2) span { animation-delay: .06s }
1143
1144            .hero h1.display .ln:nth-child(3) span { animation-delay: .12s }
1145
1146            .hero h1.display .ln:nth-child(4) span { animation-delay: .18s }
1147        }
1148
1149        .hero-sub {
1150            margin-top: 32px;
1151            max-width: 580px;
1152            color: var(--bone);
1153            font-size: var(--t-sub);
1154            line-height: 1.45
1155        }
1156
1157        /* rise2 is the site's general "arrive" animation. It is written from
1158           the resting state outwards, so an element that never animates is
1159           already where it belongs. */
1160        @keyframes rise2 {
1161            from {
1162                opacity: 0;
1163                transform: translateY(16px)
1164            }
1165            to {
1166                opacity: 1;
1167                transform: none
1168            }
1169        }
1170
1171        @media (prefers-reduced-motion: no-preference) {
1172            .hero-sub {
1173                animation: rise2 .4s .1s var(--ease-out) both
1174            }
1175        }
1176
1177        .hero-sub b {
1178            color: var(--paper);
1179            font-weight: 500
1180        }
1181
1182        .hero-cta {
1183            margin-top: 36px;
1184            display: flex;
1185            flex-wrap: wrap;
1186            align-items: center;
1187            gap: 14px
1188        }
1189
1190        .hero-meta {
1191            display: flex;
1192            flex-wrap: wrap;
1193            gap: 36px 56px;
1194            margin-top: 48px;
1195            padding-top: 28px;
1196            border-top: 1px dashed var(--line-2)
1197        }
1198
1199        @media (prefers-reduced-motion: no-preference) {
1200            .hero-cta {
1201                animation: rise2 .4s .16s var(--ease-out) both
1202            }
1203
1204            .hero-meta {
1205                animation: rise2 .4s .22s var(--ease-out) both
1206            }
1207        }
1208
1209        .hero-meta dt {
1210            font-family: var(--mono);
1211            font-size: var(--t-label);
1212            letter-spacing: .18em;
1213            text-transform: uppercase;
1214            color: var(--mute)
1215        }
1216
1217        .hero-meta dd {
1218            font-family: var(--serif);
1219            font-weight: 600;
1220            font-size: 30px;
1221            letter-spacing: var(--ls-head);
1222            margin-top: 4px
1223        }
1224
1225        .hero-meta dd b {
1226            color: var(--signal);
1227            font-weight: 600
1228        }
1229
1230        .hero-meta dd small {
1231            font-family: var(--mono);
1232            font-size: var(--t-small);
1233            color: var(--mute);
1234            margin-left: 4px
1235        }
1236
1237        /* Short reassurance list that sits under the hero meta, used to carry the
1238           left column down beside a tall form. */
1239        .hero-points {
1240            margin-top: 34px;
1241            padding-top: 26px;
1242            border-top: 1px dashed var(--line-2);
1243            display: grid;
1244            gap: 14px;
1245            max-width: 560px;
1246            opacity: 0;
1247            animation: rise2 .9s 1s var(--ease-out) forwards
1248        }
1249
1250        .hero-points .pt {
1251            display: flex;
1252    
1252        align-items: flex-start;
1253            gap: 12px;
1254            font-size: 14px;
1255            line-height: 1.5;
1256            color: var(--bone)
1257        }
1258
1259        .hero-points .pt svg {
1260            flex: 0 0 16px;
1261            margin-top: 3px;
1262            color: var(--signal)
1263        }
1264
1265        .hero-points .pt b {
1266            color: var(--paper);
1267            font-weight: 500
1268        }
1269
1270        /* HERO PHOTO PANEL, used on industry pages to showcase a story image as the hero visual */
1271        .hero-photo {
1272            position: relative;
1273            border-radius: 18px;
1274            overflow: hidden;
1275            box-shadow: 0 50px 80px -40px var(--shadow-deep), 0 0 0 1px var(--surface-2) inset;
1276            aspect-ratio: 4/5;
1277            background-image: var(--shot-dark);
1278            background-size: cover;
1279            background-position: center;
1280            opacity: 0;
1281            transform: translateY(30px);
1282            animation: rise2 1s 1s var(--ease-out) forwards
1283        }
1284
1285        .hero-photo::before {
1286            content: "";
1287            position: absolute;
1288            inset: 0;
1289            background: linear-gradient(180deg, transparent 50%, var(--scrim-mid) 100%);
1290            pointer-events: none
1291        }
1292
1293        .hero-photo::after {
1294            content: "";
1295            position: absolute;
1296            top: 0;
1297            left: 0;
1298            right: 0;
1299            height: 1px;
1300            background: linear-gradient(90deg, transparent, var(--signal), transparent);
1301            opacity: .6
1302        }
1303
1304        .hero-photo .corner {
1305            position: absolute;
1306            top: 18px;
1307            left: 18px;
1308            display: flex;
1309            align-items: center;
1310            gap: 8px;
1311            font-family: var(--mono);
1312            font-size: var(--t-label);
1313            letter-spacing: .18em;
1314            text-transform: uppercase;
1315            color: var(--paper);
1316            padding: 6px 12px;
1317            background: var(--scrim-strong);
1318            backdrop-filter: blur(6px);
1319            border: 1px solid var(--line-2);
1320            border-radius: 999px
1321        }
1322
1323        .hero-photo .corner::before {
1324            content: "";
1325            width: 6px;
1326            height: 6px;
1327            border-radius: 50%;
1328            background: var(--coral);
1329            box-shadow: 0 0 8px var(--coral);
1330            animation: pulse 1.6s var(--ease) infinite
1331        }
1332
1333        .hero-photo .caption {
1334            position: absolute;
1335            bottom: 24px;
1336            left: 24px;
1337            right: 24px;
1338            display: flex;
1339            justify-content: space-between;
1340            align-items: flex-end;
1341            gap: 16px;
1342            color: var(--paper);
1343            z-index: 1
1344        }
1345
1346        .hero-photo .caption .title {
1347            font-family: var(--serif);
1348            font-weight: 600;
1349            font-size: 22px;
1350            letter-spacing: -.01em;
1351            line-height: 1.1;
1352            max-width: 18ch
1353        }
1354
1355        .hero-photo .caption .title .it {
1356            font-family: var(--serif);
1357            font-weight: 600;
1358            color: var(--signal)
1359        }
1360
1361        .hero-photo .caption .stat {
1362            font-family: var(--mono);
1363            font-size: 11px;
1364            letter-spacing: .1em;
1365            text-align: right;
1366            flex: 0 0 auto
1367        }
1368
1369        .hero-photo .caption .stat b {
1370            display: block;
1371            font-family: var(--serif);
1372            font-size: 24px;
1373            font-weight: 300;
1374            color: var(--signal);
1375            letter-spacing: -.02em
1376        }
1377
1378        /* CALL DECK */
1379        /* The live call transcript. V2 renders the same thing as a left-ruled
1380           column rather than a floating rounded panel, so the conversation
1381           reads as part of the section instead of a card dropped onto it. */
1382        /* The live call transcript.
1383           This is a CARD, not a ruled column, and that is what /v2 does too:
1384           its hero carries .v2-livecard, which has a fill, a 10px radius and a
1385           drop shadow. Only the deck sitting inside a section (.v2-mini-deck)
1386           is left-ruled.
1387
1388           It was briefly converted to the ruled treatment everywhere, which
1389           left the transcript floating unanchored in the middle of five
1390           different heroes. The rule is: in a hero it is a card, in a section
1391           it is a ruled column (.deck.in-section below). */
1392        .deck {
1393            position: relative;
1394            background: var(--deck-grad);
1395            border-radius: 10px;
1396            padding: 18px 18px 14px;
1397            box-shadow: 0 30px 60px -20px var(--shadow-deep);
1398            backdrop-filter: blur(6px);
1399            font-family: var(--mono);
1400            font-size: 12.5px;
1401            line-height: 1.5;
1402            color: var(--bone);
1403            overflow: hidden;
1404            opacity: 0;
1405            transform: translateY(30px);
1406            animation: rise2 1s 1s var(--ease-out) forwards
1407        }
1408
1409        /* the in-section variant, matching .v2-mini-deck */
1410        .deck.in-section {
1411            background: none;
1412            border-radius: 0;
1413            box-shadow: none;
1414            backdrop-filter: none;
1415            border-left: 1px solid var(--line-2);
1416            padding: 6px 0 6px 28px
1417        }
1418
1419        /* This drew a green hairline across the top of the panel. The deck is
1420           ruled down its left edge now, so a top rule as well met it in a
1421           corner and read as half a box. The left rule is the deck's mark. */
1422        .deck::before {
1423            content: none
1424        }
1425
1426        .deck-hd {
1427            display: flex;
1428            justify-content: space-between;
1429            align-items: center;
1430            padding-bottom: 12px;
1431            border-bottom: 1px solid var(--line);
1432            margin-bottom: 14px;
1433            gap: 12px
1434        }
1435
1436        .deck-hd .dots {
1437            display: flex;
1438            gap: 6px
1439        }
1440
1441        .deck-hd .dots i {
1442            width: 9px;
1443            height: 9px;
1444            border-radius: 50%;
1445            background: var(--ink-3);
1446            display: block
1447        }
1448
1449        .deck-hd .dots i:first-child {
1450            background: var(--coral)
1451        }
1452
1453        .deck-hd .dots i:nth-child(2) {
1454            background: #f5b942
1455        }
1456
1457        .deck-hd .dots i:nth-child(3) {
1458            background: var(--signal)
1459        }
1460
1461        .deck-hd .ttl {
1462            font-size: 10px;
1463            letter-spacing: .16em;
1464            text-transform: uppercase;
1465            color: var(--mute);
1466            overflow: hidden;
1467            text-overflow: ellipsis;
1468            white-space: nowrap
1469        }
1470
1471        .deck-hd .rec {
1472            display: inline-flex;
1473            gap: 6px;
1474            align-items: center;
1475            color: var(--coral);
1476            font-size: 10px;
1477            text-transform: uppercase;
1478            letter-spacing: .16em;
1479            flex: 0 0 auto
1480        }
1481
1482        .deck-hd .rec::before {
1483            content: "";
1484            width: 6px;
1485            height: 6px;
1486            border-radius: 50%;
1487            background: var(--coral);
1488            animation: pulse 1.6s infinite
1489        }
1490
1491        .deck-row {
1492            display: flex;
1493            gap: 10px;
1494            padding: 6px 0;
1495            align-items: flex-start;
1496            opacity: 0;
1497            transform: translateY(6px);
1498            transition: opacity .55s var(--ease-out), transform .55s var(--ease-out)
1499        }
1500
1501        .deck-row.in {
1502            opacity: 1;
1503            transform: translateY(0)
1504        }
1505
1506        .deck-row .ts {
1507            color: var(--mute);
1508            min-width: 48px;
1509            flex: 0 0 48px;
1510            font-size: 11px
1511        }
1512
1513        /* Typing indicator, three dots that pulse */
1514        .deck-typing {
1515            display: flex;
1516            gap: 10px;
1517            padding: 6px 0;
1518            align-items: center;
1519            font-family: var(--mono);
1520            opacity: 0;
1521            transition: opacity .25s ease;
1522            height: 0;
1523            overflow: hidden
1524        }
1525
1526        .deck-typing.on {
1527            opacity: 1;
1528            height: auto;
1529            overflow: visible
1530        }
1531
1532        .deck-typing .ts {
1533            color: var(--mute);
1534            min-width: 48px;
1535            flex: 0 0 48px;
1536            font-size: 11px
1537        }
1538
1539        .deck-typing .who {
1540            min-width: 64px;
1541            flex: 0 0 64px;
1542            text-transform: uppercase;
1543            font-size: 10px;
1544            letter-spacing: .12em;
1545            color: var(--signal)
1546        }
1547
1548        .deck-typing .dotset {
1549            display: inline-flex;
1550            gap: 4px;
1551            align-items: center
1552        }
1553
1554        .deck-typing .dotset i {
1555            width: 6px;
1556            height: 6px;
1557            border-radius: 50%;
1558            background: var(--signal);
1559            opacity: .4;
1560            animation: typingDot 1.2s ease-in-out infinite
1561        }
1562
1563        .deck-typing .dotset i:nth-child(2) {
1564            animation-delay: .2s
1565        }
1566
1567        .deck-typing .dotset i:nth-child(3) {
1568            animation-delay: .4s
1569        }
1570
1571        @keyframes typingDot {
1572            0%, 60%, 100% {
1573                opacity: .3;
1574                transform: scale(.8)
1575            }
1576            30% {
1577                opacity: 1;
1578                transform: scale(1.1)
1579            }
1580        }
1581
1582        /* PA floater notifications, arrive with a green flash and slide */
1583        .pa-floater .row {
1584            opacity: 0;
1585            transform: translateY(-8px);
1586            transition: opacity .55s var(--ease-out), transform .55s var(--ease-out)
1587        }
1588
1589        .pa-floater .row.in {
1590            opacity: 1;
1591            transform: translateY(0)
1592        }
1593
1594        .pa-floater .row.ping {
1595            animation: ping 1.4s var(--ease-out)
1596        }
1597
1598        @keyframes ping {
1599            0% {
1600                box-shadow: 0 0 0 0 transparent
1601            }
1602            20% {
1603                box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 60%, transparent), 0 0 22px color-mix(in srgb, var(--accent) 45%, transparent);
1604                background: color-mix(in srgb, var(--accent) 8%, transparent)
1605            }
1606            100% {
1607                box-shadow: 0 0 0 0 transparent;
1608                background: transparent
1609            }
1610        }
1611
1612        .pa-floater .row.fresh::before {
1613            content: "NEW";
1614            position: absolute;
1615            right: 0;
1616            top: -4px;
1617            font-family: var(--mono);
1618            font-size: 8px;
1619            letter-spacing: .18em;
1620            color: var(--ink);
1621            background: var(--signal);
1622            padding: 2px 5px;
1623            border-radius: 3px;
1624            animation: freshFade 4s ease-out forwards
1625        }
1626
1627        .pa-floater .row {
1628            position: relative
1629        }
1630
1631        @keyframes freshFade {
1632            0%, 60% {
1633                opacity: 1
1634            }
1635            100% {
1636                opacity: 0
1637            }
1638        }
1639
1640        .deck-row .who {
1641            min-width: 64px;
1642            flex: 0 0 64px;
1643            text-transform: uppercase;
1644            font-size: 10px;
1645            letter-spacing: .12em
1646        }
1647
1648        .deck-row.caller .who {
1649            color: var(--plasma-bright)
1650        }
1651
1652        .deck-row.agent .who {
1653            color: var(--signal)
1654        }
1655
1656        .deck-row .msg {
1657            color: var(--paper);
1658            flex: 1;
1659            font-size: 12px
1660        }
1661
1662        .deck-foot {
1663            margin-top: 12px;
1664            padding-top: 12px;
1665            border-top: 1px solid var(--line);
1666            display: grid;
1667            grid-template-columns:repeat(3, 1fr);
1668            gap: 8px
1669        }
1670
1671        .deck-foot .stat {
1672            padding: 8px 10px;
1673            background: var(--surface);
1674            border: 1px solid var(--line);
1675            border-radius: 8px
1676        }
1677
1678        .deck-foot .stat span {
1679            display: block;
1680            color: var(--mute-2);
1681            font-size: 9px;
1682            text-transform: uppercase;
1683            letter-spacing: .16em;
1684            margin-bottom: 4px
1685        }
1686
1687        .deck-foot .stat b {
1688            color: var(--paper);
1689            font-weight: 500;
1690            font-size: 13px
1691        }
1692
1693        .wave {
1694            display: flex;
1695            align-items: center;
1696            gap: 2px;
1697            height: 28px;
1698            margin-top: 14px
1699        }
1700
1701        .wave i {
1702            flex: 1;
1703            background: var(--signal);
1704            border-radius: 1px;
1705            animation: wv 1.2s ease-in-out infinite;
1706            height: 30%;
1707            box-shadow: 0 0 6px var(--signal)
1708        }
1709
1710        .wave i:nth-child(2) {
1711            animation-delay: .1s
1712        }
1713
1714        .wave i:nth-child(3) {
1715            animation-delay: .2s
1716        }
1717
1718        .wave i:nth-child(4) {
1719            animation-delay: .3s
1720        }
1721
1722        .wave i:nth-child(5) {
1723            animation-delay: .4s
1724        }
1725
1726        .wave i:nth-child(6) {
1727            animation-delay: .5s
1728        }
1729
1730        .wave i:nth-child(7) {
1731            animation-delay: .6s
1732        }
1733
1734        .wave i:nth-child(8) {
1735            animation-delay: .7s
1736        }
1737
1738        .wave i:nth-child(9) {
1739            animation-delay: .8s
1740        }
1741
1742        .wave i:nth-child(10) {
1743            animation-delay: .9s
1744        }
1745
1746        .wave i:nth-child(11) {
1747            animation-delay: 1s
1748        }
1749
1750        .wave i:nth-child(12) {
1751            animation-delay: 1.1s
1752        }
1753
1754        .wave i:nth-child(13) {
1755            animation-delay: .05s
1756        }
1757
1758        .wave i:nth-child(14) {
1759            animation-delay: .15s
1760        }
1761
1762        .wave i:nth-child(15) {
1763            animation-delay: .25s
1764        }
1765
1766        .wave i:nth-child(16) {
1767            animation-delay: .35s
1768        }
1769
1770        .wave i:nth-child(17) {
1771            animation-delay: .45s
1772        }
1773
1774        .wave i:nth-child(18) {
1775            animation-delay: .55s
1776        }
1777
1778        .wave i:nth-child(19) {
1779            animation-delay: .65s
1780        }
1781
1782        .wave i:nth-child(20) {
1783            animation-delay: .75s
1784        }
1785
1786        @keyframes wv {
1787            0%, 100% {
1788                height: 20%;
1789                opacity: .4
1790            }
1791            50% {
1792                height: 95%;
1793                opacity: 1
1794            }
1795        }
1796
1797        /* ====== STRIP ====== */
1798        /* same treatment as the V2 ticker: a faint raised surface between two
1799           hairlines, rather than a solid slab of ink */
1800        .strip {
1801            border-top: 1px solid var(--line);
1802            border-bottom: 1px solid var(--line);
1803            background: var(--surface);
1804            overflow: hidden;
1805            padding: 18px 0;
1806            font-family: var(--serif);
1807            font-size: 36px;
1808            letter-spacing: -.02em
1809        }
1810
1811        .strip-track {
1812            display: flex;
1813            gap: 64px;
1814            white-space: nowrap;
1815            animation: slide 60s linear infinite;
1816            will-change: transform
1817        }
1818
1819        .strip-track:hover {
1820            animation-play-state: paused
1821        }
1822
1823        @media (prefers-reduced-motion: reduce) {
1824            .strip-track {
1825                animation: none
1826            }
1827        }
1828
1829        .strip-track .pip {
1830            color: var(--signal)
1831        }
1832
1833        .strip-track .it {
1834            font-family: var(--serif);
1835            font-weight: 600;
1836            color: var(--bone)
1837        }
1838
1839        .strip-track .blue {
1840            color: var(--plasma)
1841        }
1842
1843        .strip-link {
1844            color: var(--paper);
1845            text-decoration: none;
1846            display: inline-flex;
1847            align-items: center;
1848            gap: 14px;
1849            padding: 0 4px;
1850            border-radius: 6px;
1851            transition: color .25s, background .25s
1852        }
1853
1854        .strip-link.it {
1855            font-family: var(--serif);
1856            font-weight: 600;
1857            color: var(--bone)
1858        }
1859
1860        .strip-link:hover {
1861            color: var(--signal);
1862            background: color-mix(in srgb, var(--signal) 6%, transparent)
1863        }
1864
1865        /* An item with no page behind it states rather than links, so it takes
1866           no pointer and no hover. */
1867        .strip-link.is-static {
1868            color: var(--mute);
1869            cursor: default
1870        }
1871
1872        .strip-l
1872ink.is-static:hover {
1873            color: var(--mute);
1874            background: none
1875        }
1876
1877        .strip-link:hover .pip {
1878            color: var(--paper)
1879        }
1880
1881        /* ====== SECTION SHELL ====== */
1882        section.shell {
1883            padding: var(--space-section) var(--shell-pad);
1884            position: relative
1885        }
1886
1887        section.shell.tight {
1888            padding: var(--space-section-tight) var(--shell-pad)
1889        }
1890
1891        /* A section that butts straight onto the one above it. Pages were
1892           writing style="padding-top:0" for this, ~1,400 inline styles' worth
1893           of ad-hoc rhythm across the site; new work uses the modifier. */
1894        section.shell.flush {
1895            padding-top: 0
1896        }
1897
1898        section.shell.flush-bottom {
1899            padding-bottom: 0
1900        }
1901
1902        .section-hd {
1903            display: flex;
1904            justify-content: space-between;
1905            align-items: flex-end;
1906            gap: 32px;
1907            margin-bottom: 64px;
1908            flex-wrap: wrap
1909        }
1910
1911        .section-hd h2 {
1912            font-family: var(--serif);
1913            font-weight: 600;
1914            font-size: var(--t-h2);
1915            line-height: var(--lh-head);
1916            letter-spacing: var(--ls-head);
1917            max-width: 18ch
1918        }
1919
1920        .section-hd h2 .it,
1921        .section-hd h2 .blue {
1922            font-family: var(--serif);
1923            font-style: normal;
1924            font-weight: 600;
1925            color: var(--signal)
1926        }
1927
1928        .section-hd .lede {
1929            max-width: 46ch;
1930            color: var(--bone);
1931            line-height: var(--lh-body);
1932            font-size: var(--t-lede)
1933        }
1934
1935        /* ====== SLAB ====== */
1936        /* V2 design language: a ruled band rather than a filled, rounded slab */
1937        .slab {
1938            display: grid;
1939            grid-template-columns:1.1fr 1fr;
1940            gap: 0;
1941            border-top: 1px solid var(--line-2);
1942            overflow: hidden
1943        }
1944
1945        .slab-l {
1946            padding: clamp(40px, 5vw, 64px) clamp(28px, 4vw, 56px) clamp(40px, 5vw, 64px) 0;
1947            display: flex;
1948            flex-direction: column;
1949            justify-content: center;
1950            gap: 40px
1951        }
1952
1953        .slab-l h3 {
1954            font-family: var(--serif);
1955            font-weight: 600;
1956            font-size: clamp(36px, 4.4vw, 60px);
1957            line-height: .98;
1958            letter-spacing: -.02em
1959        }
1960
1961        .slab-l h3 .it {
1962            font-family: var(--serif);
1963            font-weight: 600;
1964            color: var(--signal)
1965        }
1966
1967        .slab-l h3 .blue {
1968            font-family: var(--serif);
1969            font-weight: 600;
1970            color: var(--plasma-bright)
1971        }
1972
1973        .slab-l p {
1974            color: var(--bone);
1975            font-size: 15px;
1976            line-height: 1.6;
1977            max-width: 42ch
1978        }
1979
1980        .slab-l ul {
1981            list-style: none;
1982            display: flex;
1983            flex-direction: column;
1984            gap: 14px;
1985            font-size: 14px;
1986            color: var(--bone)
1987        }
1988
1989        .slab-l ul li {
1990            display: flex;
1991            gap: 12px;
1992            align-items: flex-start;
1993            padding-bottom: 14px;
1994            border-bottom: 1px dashed var(--line)
1995        }
1996
1997        .slab-l ul li:last-child {
1998            border-bottom: 0;
1999            padding-bottom: 0
2000        }
2001
2002        .slab-l ul li::before {
2003            content: "";
2004            flex: 0 0 8px;
2005            width: 8px;
2006            height: 8px;
2007            border-radius: 50%;
2008            margin-top: 7px;
2009            background: var(--signal);
2010            box-shadow: 0 0 12px var(--signal)
2011        }
2012
2013        .slab-l ul li b {
2014            color: var(--paper);
2015            font-weight: 500
2016        }
2017
2018        .slab-r {
2019            position: relative;
2020            padding: 46px 0;
2021            background: radial-gradient(closest-side at 50% 30%, rgba(49, 138, 190, .18), transparent 70%);
2022            display: flex;
2023            align-items: center;
2024            justify-content: center;
2025            overflow: hidden;
2026            min-height: 520px
2027        }
2028
2029        .slab-r::before {
2030            content: "";
2031            position: absolute;
2032            inset: 0;
2033            background-image: linear-gradient(to right, var(--line) 1px, transparent 1px), linear-gradient(to bottom, var(--line) 1px, transparent 1px);
2034            background-size: 48px 48px;
2035            mask: radial-gradient(closest-side, #000, transparent 70%)
2036        }
2037
2038        .slab-r::after {
2039            content: "";
2040            position: absolute;
2041            inset: 0;
2042            pointer-events: none;
2043            background: linear-gradient(to bottom, var(--ink) 0, transparent 13%, transparent 87%, var(--ink) 100%)
2044        }
2045
2046        /* ====== PHONE FRAME ====== */
2047        .phone-frame {
2048            position: relative;
2049            width: 280px;
2050            aspect-ratio: 9/19;
2051            border-radius: 38px;
2052            background: linear-gradient(180deg, #1a1d22, #0a0d10);
2053            padding: 8px;
2054            box-shadow: 0 60px 120px -30px rgba(0, 0, 0, .9), 0 0 0 1px rgba(255, 255, 255, .06) inset
2055        }
2056
2057        .phone-frame::before {
2058            content: "";
2059            position: absolute;
2060            top: 14px;
2061            left: 50%;
2062            transform: translateX(-50%);
2063            width: 90px;
2064            height: 24px;
2065            background: #000;
2066            border-radius: 14px;
2067            z-index: 2
2068        }
2069
2070        .phone-screen {
2071            width: 100%;
2072            height: 100%;
2073            border-radius: 32px;
2074            background: linear-gradient(180deg, #0a0d12, #13171f);
2075            overflow: hidden;
2076            position: relative;
2077            display: flex;
2078            flex-direction: column;
2079            padding: 42px 14px 14px;
2080            font-family: var(--mono);
2081            font-size: var(--t-label)
2082        }
2083
2084        /* Light mode: silver handset + light app screen (text inside uses tokens, so it flips to dark) */
2085        html[data-theme="light"] .phone-frame {
2086            background: linear-gradient(180deg, #dde0e6, #b7bcc6);
2087            box-shadow: 0 50px 90px -30px var(--shadow-deep), 0 0 0 1px rgba(0, 0, 0, .12) inset
2088        }
2089
2090        html[data-theme="light"] .phone-screen {
2091            background: linear-gradient(180deg, #ffffff, #f4f1e8)
2092        }
2093
2094        .phone-screen .stat-row {
2095            display: flex;
2096            justify-content: space-between;
2097            color: var(--bone);
2098            font-size: 9px;
2099            letter-spacing: .06em;
2100            padding: 0 6px 14px
2101        }
2102
2103        .phone-screen .ph-h {
2104            font-family: var(--serif);
2105            font-weight: 600;
2106            font-size: 24px;
2107            color: var(--paper);
2108            padding: 0 6px;
2109            letter-spacing: -.02em;
2110            line-height: 1
2111        }
2112
2113        .phone-screen .ph-h .it {
2114            font-family: var(--serif);
2115            font-weight: 600;
2116            color: var(--signal)
2117        }
2118
2119        .phone-screen .ph-h .blue {
2120            font-family: var(--serif);
2121            font-weight: 600;
2122            color: var(--plasma-bright)
2123        }
2124
2125        .phone-screen .ph-card {
2126            margin-top: 14px;
2127            background: var(--surface-2);
2128            border: 1px solid var(--line);
2129            border-radius: 14px;
2130            padding: 12px;
2131            display: flex;
2132            flex-direction: column;
2133            gap: 8px
2134        }
2135
2136        .phone-screen .ph-card .lbl {
2137            color: var(--mute);
2138            font-size: 9px;
2139            text-transform: uppercase;
2140            letter-spacing: .16em
2141        }
2142
2143        .phone-screen .ph-card .name {
2144            color: var(--paper);
2145            font-size: 12px
2146        }
2147
2148        .phone-screen .ph-card .meta {
2149            color: var(--bone);
2150            font-size: 9px;
2151            display: flex;
2152            gap: 8px
2153        }
2154
2155        .phone-screen .ph-card .meta i {
2156            font-style: normal;
2157            color: var(--signal)
2158        }
2159
2160        .phone-screen .ph-bar {
2161            margin-top: 4px;
2162            display: flex;
2163            align-items: center;
2164            gap: 6px
2165        }
2166
2167        .phone-screen .ph-bar .b {
2168            flex: 1;
2169            height: 3px;
2170            border-radius: 2px;
2171            background: var(--line)
2172        }
2173
2174        .phone-screen .ph-bar .b.on {
2175            background: var(--signal);
2176            box-shadow: 0 0 8px var(--signal)
2177        }
2178
2179        .phone-screen .ph-cta {
2180            margin-top: auto;
2181            background: var(--signal);
2182            color: var(--ink);
2183            padding: 10px;
2184            border-radius: 999px;
2185            text-align: center;
2186            font-size: 11px;
2187            font-weight: 600;
2188            font-family: var(--sans);
2189            letter-spacing: .02em
2190        }
2191
2192        /* ====== METRICS ====== */
2193        .metrics {
2194            display: grid;
2195            grid-template-columns:repeat(12, 1fr);
2196            gap: 0 clamp(24px, 3vw, 40px)
2197        }
2198
2199        /* ruled stats, the way the V2 proof block does them */
2200        .metric {
2201            grid-column: span 3;
2202            border-top: 1px solid var(--line-2);
2203            padding: 24px 0 0;
2204            position: relative;
2205            overflow: hidden;
2206            min-height: 170px;
2207            display: flex;
2208            flex-direction: column;
2209            justify-content: space-between;
2210            transition: border-color .3s var(--ease)
2211        }
2212
2213        .metric:hover {
2214            border-top-color: var(--signal)
2215        }
2216
2217        .metric .lbl {
2218            font-family: var(--mono);
2219            font-size: var(--t-label);
2220            letter-spacing: .16em;
2221            text-transform: uppercase;
2222            color: var(--mute)
2223        }
2224
2225        .metric .val {
2226            font-family: var(--serif);
2227            font-weight: 600;
2228            font-size: 60px;
2229            line-height: 1;
2230            letter-spacing: -.04em;
2231        }
2232
2233        .metric .val small {
2234            font-size: 18px;
2235            color: var(--mute);
2236            font-family: var(--mono);
2237            margin-left: 4px
2238        }
2239
2240        .metric .delta {
2241            font-family: var(--mono);
2242            font-size: 11px;
2243            color: var(--signal)
2244        }
2245
2246        .metric .delta.dn {
2247            color: var(--coral)
2248        }
2249
2250        .metric.wide {
2251            grid-column: span 6
2252        }
2253
2254        /* ====== TIERS ====== */
2255        .tiers {
2256            display: grid;
2257            grid-template-columns:repeat(3, 1fr);
2258            gap: 18px
2259        }
2260
2261        /* Pricing tiers in the V2 language: a rule, a label, a number. They were
2262           rounded, filled cards, and the featured one was picked out with a
2263           masked gradient border. A plan is now marked out by the weight and
2264           colour of its rule instead, which is how the V2 price blocks do it. */
2265        .tier {
2266            position: relative;
2267            border-top: 2px solid var(--line-2);
2268            padding: clamp(26px, 3vw, 40px) 0 0;
2269            display: flex;
2270            flex-direction: column;
2271            gap: 24px;
2272            transition: border-color .3s var(--ease)
2273        }
2274
2275        .tier:hover {
2276            border-top-color: var(--mute-2)
2277        }
2278
2279        .tier.featured {
2280            border-top-color: var(--signal)
2281        }
2282
2283        .tier.featured:hover {
2284            border-top-color: var(--signal)
2285        }
2286
2287        .tier .row1 {
2288            display: flex;
2289            justify-content: space-between;
2290            align-items: center
2291        }
2292
2293        .tier .name {
2294            font-family: var(--mono);
2295            font-size: 11px;
2296            text-transform: uppercase;
2297            letter-spacing: .18em;
2298            color: var(--bone)
2299        }
2300
2301        /* was a filled badge; the rule above already says which plan this is */
2302        .tier .badge {
2303            font-family: var(--mono);
2304            font-size: var(--t-label);
2305            color: var(--signal);
2306            letter-spacing: .14em;
2307            text-transform: uppercase
2308        }
2309
2310        .tier .price {
2311            font-family: var(--serif);
2312            font-weight: 600;
2313            font-size: 64px;
2314            line-height: .95;
2315            letter-spacing: -.035em
2316        }
2317
2318        .tier .price small {
2319            font-family: var(--mono);
2320            font-size: 13px;
2321            color: var(--mute);
2322            margin-left: 6px
2323        }
2324
2325        .tier .desc {
2326            font-size: 14px;
2327            color: var(--bone);
2328            line-height: 1.5;
2329            border-top: 1px dashed var(--line);
2330            padding-top: 20px
2331        }
2332
2333        .tier ul {
2334            list-style: none;
2335            display: flex;
2336            flex-direction: column;
2337            gap: 10px;
2338            font-size: 14px;
2339            color: var(--bone)
2340        }
2341
2342        .tier ul li {
2343            display: flex;
2344            gap: 10px;
2345            align-items: flex-start
2346        }
2347
2348        .tier ul li svg {
2349            flex: 0 0 16px;
2350            color: var(--signal);
2351            margin-top: 3px
2352        }
2353
2354        .tier .cta {
2355            margin-top: auto
2356        }
2357
2358        /* ====== EDITORIAL QUOTE ====== */
2359        .editorial {
2360            display: grid;
2361            grid-template-columns:1fr 1.4fr;
2362            gap: 64px;
2363            align-items: center
2364        }
2365
2366        .ed-num {
2367            font-family: var(--mono);
2368            font-size: 11px;
2369            color: var(--mute);
2370            letter-spacing: .18em;
2371            text-transform: uppercase;
2372            margin-bottom: 24px
2373        }
2374
2375        .ed-quote {
2376            font-family: var(--serif);
2377            font-weight: 600;
2378            font-size: clamp(28px, 3.4vw, 46px);
2379            line-height: 1.1;
2380            letter-spacing: -.02em;
2381        }
2382
2383        .ed-quote .it {
2384            font-family: var(--serif);
2385            font-weight: 600
2386        }
2387
2388        .ed-quote .hl {
2389            background: linear-gradient(180deg, transparent 62%, color-mix(in srgb, var(--accent) 55%, transparent) 62%);
2390            color: inherit;
2391            padding: 0 2px;
2392            -webkit-box-decoration-break: clone;
2393            box-decoration-break: clone
2394        }
2395
2396        .ed-attr {
2397            margin-top: 32px;
2398            display: flex;
2399            align-items: center;
2400            gap: 16px;
2401            color: var(--mute);
2402            font-family: var(--mono);
2403            font-size: 12px;
2404            letter-spacing: .04em
2405        }
2406
2407        .ed-attr .av {
2408            width: 46px;
2409            height: 46px;
2410            border-radius: 50%;
2411            background: var(--grad);
2412            display: grid;
2413            place-items: center;
2414            color: var(--ink);
2415            font-family: var(--serif);
2416            font-weight: 500;
2417            font-size: 18px
2418        }
2419
2420        .ed-attr b {
2421            color: var(--paper);
2422            font-weight: 500;
2423            font-family: var(--sans);
2424            text-transform: none;
2425            letter-spacing: 0
2426        }
2427
2428        /* ====== APP STRIP ====== */
2429        /* V2 lays the app section out as a ruled band with the phone beside the
2430           copy, not as a filled panel with the whole thing inside it. */
2431        .app {
2432            display: grid;
2433            grid-template-columns:1.2fr 1fr;
2434            gap: clamp(32px, 5vw, 80px);
2435            align-items: center;
2436            padding: clamp(48px, 6vw, 80px) 0 0;
2437            border-top: 1px solid var(--line-2);
2438            position: relative
2439        }
2440
2441        /* the glow behind the phone belonged to the filled panel this section
2442           used to sit in; a ruled band carries no lighting of its own */
2443        .app::before {
2444            content: none
2445        }
2446
2447        .app-l {
2448            position: relative;
2449            z-index: 1
2450        }
2451
2452        /* Was a violet pill. The V2 language has no pills: a kicker is a rule,
2453           then mono caps. The leading dot in the markup is redundant against
2454           the rule, so it is not rendered. */
2455        .app-tag {
2456            display: flex;
2457            align-items: center;
2458            gap: 12px;
2459            font-family: var(--mono);
2460            font-size: 11px;
2461            color: var(--mute-2);
2462            text-transform: uppercase;
2463            letter-spacing: .22em
2464        }
2465
2466        .app-tag::before {
2467            content: "";
2468            flex: 0 0 28px;
2469            height: 1px;
2470            background: var(--signal)
2471        }
2472
2473        .app h2 {
2474            font-family: var(--serif);
2475            font-weight: 600;
2476            font-size: clamp(36px, 4.6vw, 68px);
2477            line-height: .98;
2478            letter-spacing: -.025em;
2479            margin-top: 24px;
2480        }
2481
2482        .app h2 .it {
2483            font-family: var(--serif);
2484            font-weight: 600;
2485            color: var(--signal)
2486        }
2487
2488        .app p {
2489            color: var(--bone);
2490            max-width: 48ch;
2491            margin-top: 20px;
2492            font-size: 15px;
2493            line-height: 1.6
2494        }
2495
2496        /* ── Store badges (x-app-badges) ───────────────────────────────────
2497           Apple's and Google's own artwork, which neither will let anybody
2498           redraw. What used to sit here was our own box with a hand-drawn
2499           glyph and the store name set in the site's serif, which is exactly
2500           what both sets of guidelines forbid.
2501
2502           Both files are the black badge with white type. On the light theme
2503           that is the standard treatment. On the dark theme the pill sinks
2504           into the page, so a hairline gives it its edge back; the white
2505           lettering carries either way. */
2506        .app-stores {
2507            margin-top: 32px;
2508            display: flex;
2509            align-items: center;
2510            gap: 14px;
2511            flex-wrap: wrap
2512        }
2513
2514        .app-badge {
2515            display: inline-block;
2516            border-radius: 8px;
2517            box-shadow: 0 0 0 1px var(--line);
2518            transition: opacity .25s var(--ease), box-shadow .25s var(--ease)
2519        }
2520
2521        html[data-theme="light"] .app-badge {
2522            box-shadow: none
2523        }
2524
2525        .app-badge:hover {
2526            opacity: .82;
2527            box-shadow: 0 0 0 1px var(--line-2)
2528        }
2529
2530        .app-badge img {
2531            display: block;
2532            height: var(--app-badge-h, 56px);
2533            width: auto
2534        }
2535
2536        /* Two badges side by side stop fitting a phone at about 340px, and a
2537           badge that has to shrink stops being the store's badge. Let them
2538           stack instead. */
2539        @media (max-width: 420px) {
2540            .app-badge img {
2541                height: calc(var(--app-badge-h, 56px) * .82)
2542            }
2543        }
2544
2545
2546        .app-r {
2547            position: relative;
2548            z-index: 1;
2549            display: flex;
2550            justify-content: center;
2551            align-items: center
2552        }
2553
2554        .app-phone {
2555            transform: rotate(-6deg)
2556        }
2557
2558        .app-phone .phone-screen {
2559            padding: 42px 12px 12px
2560        }
2561
2562        .app-phone .ph-h {
2563            font-size: 18px
2564        }
2565
2566        /* ====== FORMS ====== */
2567        /* The demo deck and other steppers hide panels with the hidden
2568           attribute; any display rule on the element would otherwise win. */
2569        [hidden] {
2570            display: none !important
2571        }
2572
2573        .form {
2574            display: grid;
2575            gap: 18px
2576        }
2577
2578        .form .row {
2579            display: grid;
2580            gap: 18px;
2581            grid-template-columns:1fr 1fr
2582        }
2583
2584        .form .field {
2585            display: flex;
2586            flex-direction: column;
2587            gap: 6px;
2588            position: relative
2589        }
2590
2591        .form .field label {
2592            font-family: var(--mono);
2593            font-size: var(--t-label);
2594            color: var(--mute);
2595            text-transform: uppercase;
2596            letter-spacing: .18em
2597        }
2598
2599        /* squared off; the ruled language has no rounded fields in it */
2600        .form .field input, .form .field select, .form .field textarea {
2601            background: var(--surface);
2602            border: 1px solid var(--line);
2603            border-radius: 2px;
2604            padding: 14px 16px;
2605            color: var(--paper);
2606            font-size: 15px;
2607            font-family: var(--sans);
2608            transition: .25s var(--ease);
2609        }
2610
2611        .form .field input:focus, .form .field select:focus, .form .field textarea:focus {
2612            outline: none;
2613            border-color: var(--signal);
2614            background: var(--ink-3);
2615            box-shadow: 0 0 0 3px color-mix(in srgb, var(--signal) 22%, transparent)
2616        }
2617
2618        .form .field input::placeholder, .form .field textarea::placeholder {
2619            color: var(--mute-2)
2620        }
2621
2622        .form .field textarea {
2623            min-height: 120px;
2624            resize: vertical;
2625            line-height: 1.5
2626        }
2627
2628        .form .radios {
2629            display: grid;
2630            grid-template-columns:repeat(2, 1fr);
2631            gap: 10px
2632        }
2633
2634        /* Options in the V2 language: a hairline and square corners rather than
2635           a filled, rounded card each. They keep a full border rather than only
2636           a top rule because they sit in a two-column grid and have to read as
2637           separately selectable, which a top rule alone does not convey. The
2638           control marks themselves stay round: a radio dot is an affordance
2639           people know by its shape, not decoration. */
2640        .form .radio,
2641        .form .check {
2642            position: relative;
2643            display: flex;
2644            align-items: flex-start;
2645            gap: 12px;
2646            padding: 16px;
2647            border: 1px solid var(--line);
2648            border-radius: 2px;
2649            cursor: pointer;
2650            transition: .25s var(--ease);
2651            background: none
2652        }
2653
2654        .form .radio:hover,
2655        .form .check:hover {
2656            border-color: var(--line-2);
2657            background: var(--surface-2)
2658        }
2659
2660        .form .radio input,
2661        .form .check input {
2662            position: absolute;
2663            opacity: 0;
2664            pointer-events: none
2665        }
2666
2667        .form .radio .dot {
2668            width: 18px;
2669            height: 18px;
2670            border-radius: 50%;
2671            border: 1px solid var(--line-2);
2672            flex: 0 0 18px;
2673            display: grid;
2674            place-items: center;
2675            margin-top: 2px;
2676            transition: .25s
2677        }
2678
2679        .form .radio .dot::after {
2680            content: "";
2681            width: 8px;
2682            height: 8px;
2683            border-radius: 50%;
2684            background: var(--signal);
2685            transform: scale(0);
2686            transition: .25s;
2687            box-shadow: 0 0 8px var(--signal)
2688        }
2689
2690        .form .radio input:checked ~ .dot {
2691            border-color: var(--signal)
2692        }
2693
2694        .form .radio input:checked ~ .dot::after {
2695            transform: scale(1)
2696        }
2697
2698        .form .radio:has(input:checked),
2699        .form .check:has(input:checked) {
2700            border-color: var(--signal);
2701            background: color-mix(in srgb, var(--signal) 6%, transparent)
2702        }
2703
2704        /* Same card as a radio, squared off with a tick so it reads as a
2705           multi-select rather than one of a set. */
2706        .form .check .box {
2707            width: 18px;
2708            height: 18px;
2709            border-radius: 5px;
2710            border: 1px solid var(--line-2);
2711            flex: 0 0 18px;
2712            display: grid;
2713            place-items: center;
2714            margin-top: 2px;
2715            transition: .25s
2716        }
2717
2718        .form .check .box::after {
2719            content: "";
2720            width: 10px;
2721            height: 5px;
2722            margin-top: -2px;
2723            border-left: 2px solid var(--signal);
2724            border-bottom: 2px solid var(--signal);
2725            transform: rotate(-45deg) scale(0);
2726            transition: .25s
2727        }
2728
2729        .form .check input:checked ~ .box {
2730            border-color: var(--signal)
2731        }
2732
2733        .form .check input:checked ~ .box::after {
2734            transform: rotate(-45deg) scale(1)
2735        }
2736
2737        .form .radio .ttl,
2738        .form .check .ttl {
2739            font-family: var(--serif);
2740            font-weight: 400;
2741            font-size: 18px;
2742            letter-spacing: -.01em;
2743            color: var(--paper);
2744            line-height: 1
2745        }
2746
2747        .form .radio .sub,
2748        .form .check .sub {
2749            font-size: 12px;
2750            color: var(--bone);
2751            margin-top: 4px;
2752            line-height: 1.4
2753        }
2754
2755        .form .actions {
2756            display: flex;
2757            justify-content: space-between;
2758            align-items: center;
2759            gap: 16px;
2760            flex-wrap: wrap;
2761            margin-top: 8px
2762        }
2763
2764        .form .actions .note {
2765            font-size: 12px;
2766            color: var(--mute);
2767            font-family: var(--mono);
2768            letter-spacing: .04em
2769        }
2770
2771        /* ====== PLAN DISPLAY (live price panel under agent_type radios) ====== */
2772        /* The running total of what has been picked. Was a rounded card filled
2773           with a blue-to-green wash; in the V2 language a price is a rule and a
2774           number, so it is ruled top and bottom and carries no fill. */
2775        .plan-display {
2776            display: grid;
2777            grid-template-columns:1fr auto;
2778            gap: 18px;
2779            align-items: center;
2780            padding: 22px 0;
2781            margin-top: 24px;
2782            border-top: 1px solid var(--line-2);
2783            border-bottom: 1px solid var(--line);
2784            position: relative;
2785        }
2786
2787        .plan-display::before {
2788            content: "";
2789            position: absolute;
2790            top: 0;
2791            left: 0;
2792            right: 0;
2793            height: 1px;
2794            background: linear-gradient(90deg, transparent, var(--signal), transparent);
2795            opacity: .6
2796        }
2797
2798        .plan-display-label {
2799            font-family: var(--serif);
2800            font-weight: 400;
2801            font-size: 18px;
2802            letter-spacing: -.01em;
2803            color: var(--paper);
2804            line-height: 1.1
2805        }
2806
2807        .plan-display-sub {
2808            font-family: var(--sans);
2809            font-size: 12px;
2810            color: var(--bone);
2811            line-height: 1.5;
2812            margin-top: 4px;
2813            max-width: 38ch
2814        }
2815
2816        .plan-display-right {
2817            text-align: right;
2818            flex: 0 0 auto
2819        }
2820
2821        .plan-display-price {
2822            font-family: var(--serif);
2823            font-weight: 600;
2824            font-size: 34px;
2825            line-height: 1;
2826            letter-spacing: -.025em;
2827            color: var(--signal);
2828            white-space: nowrap
2829        }
2830
2831        .plan-display-price small {
2832            font-family: var(--mono);
2833            font-size: 11px;
2834            color: var(--mute);
2835            margin-left: 4px;
2836            font-weight: 400
2837        }
2838
2839        .plan-display-tier {
2840            font-family: var(--mono);
2841            font-size: 9.5px;
2842            text-transform: uppercase;
2843            letter-spacing: .16em;
2844            color: var(--mute);
2845            margin-top: 6px
2846        }
2847
2848        /* Spells out how long the quoted founding rate lasts and what it becomes. */
2849        .plan-display-note {
2850            font-family: var(--sans);
2851            font-size: 11.5px;
2852            line-height: 1.5;
2853            color: var(--mute);
2854            margin-top: 6px;
2855            max-width: 34ch;
2856            margin-left: auto
2857        }
2858
2859        .plan-asterisk {
2860            font-family: var(--sans);
2861            font-size: 11.5px;
2862            line-height: 1.5;
2863            color: var(--mute);
2864            margin-top: 10px;
2865            padding: 0 4px
2866        }
2867
2868        .plan-asterisk span {
2869            color: var(--signal);
2870            font-weight: 600;
2871            margin-right: 2px
2872        }
2873
2874        /* Shown under "Pick your agent" only for plans that pair with another
2875           one (currently the Outgoing Agent, which wants an incoming agent to
2876           catch the return calls). Toggled by the plan-display script. */
2877        .plan-recommend {
2878            font-family: var(--sans);
2879            font-size: 12.5px;
2880            line-height: 1.55;
2881            color: var(--bone);
2882            margin-top: 12px;
2883            padding: 10px 12px;
2884            border-left: 2px solid var(--signal);
2885            background: rgba(49, 138, 190, .07)
2886        }
2887
2888        @media (max-width: 480px) {
2889            .plan-display {
2890                grid-template-columns:1fr;
2891                gap: 10px
2892            }
2893
2894            .plan-display-right {
2895                text-align: left
2896            }
2897
2898            .plan-display-price {
2899                font-size: 30px
2900            }
2901        }
2902
2903        /* ====== END CTA ====== */
2904        .endcta {
2905            padding: 140px var(--shell-pad);
2906            position: relative;
2907            overflow: hidden;
2908            text-align: center
2909        }
2910
2911        .endcta .endcta-photo {
2912            position: absolute;
2913            inset: 0;
2914            background-image: url('/media/frontend/nz-skyline-dusk.jpg');
2915            background-size: cover;
2916            background-position: center bottom;
2917            opacity: .32;
2918            filter: saturate(.9) contrast(1.1);
2919            z-index: 0
2920        }
2921
2922        .endcta .endcta-photo::after {
2923            content: "";
2924            position: absolute;
2925            inset: 0;
2926            background: linear-gradient(180deg, var(--scrim-strong) 0%, var(--scrim-mid) 30%, var(--scrim-soft) 70%, var(--scrim-strong) 100%),
2927            radial-gradient(ellipse at center, rgba(49, 138, 190, .22) 0%, transparent 60%)
2928        }
2929
2930        .endcta > * {
2931            position: relative;
2932            z-index: 1
2933        }
2934
2935        .endcta::before {
2936            content: "";
2937            position: absolute;
2938            inset: 0;
2939            z-index: 0
2940        }
2941
2942        .endcta .stamp {
2943            font-family: var(--mono);
2944            font-size: 11px;
2945            color: var(--mute);
2946            text-transform: uppercase;
2947            letter-spacing: .2em;
2948            margin-bottom: 24px;
2949            display: flex;
2950            justify-content: center;
2951            align-items: center;
2952            gap: 14px
2953        }
2954
2955        .endcta .stamp::before, .endcta .stamp::after {
2956            content: "";
2957            flex: 0 0 80px;
2958            height: 1px;
2959            background: var(--line)
2960        }
2961
2962        .endcta h2 {
2963            font-family: var(--serif);
2964            font-weight: 600;
2965            font-size: var(--t-display);
2966            line-height: var(--lh-display);
2967            letter-spacing: var(--ls-head)
2968        }
2969
2970        .endcta h2 .it {
2971            font-family: var(--serif);
2972            font-weight: 600;
2973            color: var(--signal)
2974        }
2975
2976        .endcta h2 .blue {
2977            font-family: var(--serif);
2978            font-weight: 600;
2979            color: var(--plasma-bright)
2980        }
2981
2982        /* The two numbers were pills with a circular icon badge each. In the V2
2983           language a number is a rule, a mono label and the figure itself: the
2984           same shape the price blocks use, so the closing line of every page
2985           rhymes with the pricing. The rule fills with the brand gradient on
2986           hover, which is the only affordance it needs. */
2987        .endcta .num-big {
2988            margin-top: 0;
2989            position: relative;
2990            display: block;
2991            text-align: left;
2992            padding: 26px 0 0;
2993            font-family: var(--serif);
2994            font-size: clamp(30px, 3.2vw, 44px);
2995            font-weight: 600;
2996            line-height: 1.1;
2997            letter-spacing: var(--ls-head);
2998            color: var(--paper);
2999            transition: color .3s var(--ease)
3000        }
3001
3002        .endcta .num-big::before, .endcta .num-big::after {
3003            content: "";
3004            position: absolute;
3005            top: 0;
3006            left: 0;
3007            right: 0;
3008            height: 1px
3009        }
3010
3011        .endcta .num-big::before {
3012            background: var(--line-2)
3013        }
3014
3015        .endcta .num-big::after {
3016            background: var(--grad);
3017            transform: scaleX(0);
3018            transform-origin: left;
3019            transition: transform .5s var(--ease-out)
3020        }
3021
3022        .endcta .num-big:hover::after {
3023            transform: scaleX(1)
3024        }
3025
3026        .endcta .num-big:hover {
3027            color: var(--signal)
3028        }
3029
3030        .endcta .num-big.num-blue:hover {
3031            color: var(--plasma-bright)
3032        }
3033
3034        /* the icon badges go with the pills */
3035        .endcta .num-big .ic {
3036            display: none
3037        }
3038
3039        .endcta .num-big small {
3040            display: block;
3041            margin-bottom: 14px;
3042            font-family: var(--mono);
3043            font-size: var(--t-label);
3044            color: var(--mute);
3045            letter-spacing: .18em;
3046            text-transform: uppercase;
3047            line-height: 1.5
3048        }
3049
3050        .endcta .endcta-meta {
3051            margin-top: 32px;
3052            display: flex;
3053            justify-content: center;
3054            gap: 32px;
3055            font-family: var(--mono);
3056            font-size: 11px;
3057            color: var(--mute);
3058            text-transform: uppercase;
3059            letter-spacing: .14em;
3060            flex-wrap: wrap
3061        }
3062
3063        /* ====== FOOTER ====== */
3064        .foot {
3065            padding: 80px var(--shell-pad) 32px;
3066            border-top: 1px solid var(--line);
3067            background: var(--ink-2)
3068        }
3069
3070        /* Brand block plus five link columns. Six tracks only pay off on a wide
3071           screen; between 1100 and 1400 the brand column gives ground and the
3072           gap tightens rather than the links wrapping to a second row. */
3073        .foot-grid {
3074            display: grid;
3075            grid-template-columns:2fr repeat(5, 1fr);
3076            gap: 48px;
3077            margin-bottom: 64px
3078        }
3079
3080        @media (max-width: 1400px) {
3081            .foot-grid {
3082                grid-template-columns:1.4fr repeat(5, 1fr);
3083                gap: 28px
3084            }
3085        }
3086
3087        .foot h4 {
3088            font-family: var(--mono);
3089            font-size: 11px;
3090            color: var(--mute);
3091            text-transform: uppercase;
3092            letter-spacing: .16em;
3093            margin-bottom: 16px
3094        }
3095
3096        .foot ul {
3097            list-style: none;
3098            display: flex;
3099            flex-direction: column;
3100            gap: 8px;
3101            font-size: 13px;
3102            color: var(--bone)
3103        }
3104
3105        .foot ul a {
3106            transition: .25s
3107        }
3108
3109        .foot ul a:hover {
3110            color: var(--signal)
3111        }
3112
3113        .foot-brand p {
3114            margin-top: 16px;
3115            color: var(--bone);
3116            font-size: 13px;
3117            line-height: 1.55;
3118            max-width: 36ch
3119        }
3120
3121        .foot-bot {
3122            display: flex;
3123            justify-content: space-between;
3124            align-items: center;
3125            padding-top: 32px;
3126            border-top: 1px solid var(--line);
3127            font-family: var(--mono);
3128            font-size: 11px;
3129            color: var(--mute);
3130            letter-spacing: .06em;
3131            flex-wrap: wrap;
3132            gap: 16px
3133        }
3134
3135        /* ====== V2 RULED VOCABULARY ======
3136           The shared shapes of the V2 design language, so a new section does
3137           not have to hand-roll the hairline pair again. The language is:
3138
3139             · no boxed cards. A block is a rule and the copy under it.
3140             · no icon marks, no tag pills, no lift-on-hover.
3141             · the rule fills with the brand gradient as the block scrolls in,
3142               which is the only motion a block gets.
3143             · a price, a phone number and a stat all take the same shape:
3144               a rule, a mono label, and a big serif figure.
3145
3146           Reach for these on anything new. The older components (.cap-plate,
3147           .step, .tier, .metric, .trade) carry their own copies of the same
3148           shapes because their markup predates this block; they are not worth
3149           rewriting just to share four declarations, but they must not drift.
3150
3151             <div class="ruled-set r">
3152               <div class="ruled-col">...</div>
3153             </div>
3154
3155           .r on the container is what starts the fill: the site-wide reveal
3156           observer adds .in, and .ruled-set.in is the trigger. */
3157        .ruled-set {
3158            display: grid;
3159            gap: clamp(20px, 2.6vw, 40px)
3160        }
3161
3162        .ruled-set.cols-2 { grid-template-columns:repeat(2, 1fr) }
3163        .ruled-set.cols-3 { grid-template-columns:repeat(3, 1fr) }
3164        .ruled-set.cols-4 { grid-template-columns:repeat(4, 1fr) }
3165
3166        .ruled-col {
3167            position: relative;
3168            padding: 30px 0 0
3169        }
3170
3171        .ruled-col::before, .ruled-col::after {
3172            content: "";
3173            position: absolute;
3174            top: 0;
3175            left: 0;
3176            right: 0;
3177            height: 1px
3178        }
3179
3180        .ruled-col::before { background: var(--line-2) }
3181
3182        .ruled-col::after {
3183            background: var(--grad);
3184            transform: scaleX(0);
3185            transform-origin: left;
3186            transition: transform .9s var(--ease-out)
3187        }
3188
3189        /* the reveal class lands on the container in most sections and on the
3190           column itself in a few, so both spellings start the fill */
3191        .ruled-set.in .ruled-col::after, .ruled-col.in::after {
3192            transform: scaleX(1)
3193        }
3194
3195        .ruled-set.in .ruled-col:nth-child(2)::after { transition-delay: .12s }
3196        .ruled-set.in .ruled-col:nth-child(3)::after { transition-delay: .24s }
3197        .ruled-set.in .ruled-col:nth-child(4)::after { transition-delay: .36s }
3198
3199        .ruled-col h3 {
3200            font-family: var(--serif);
3201            font-weight: 600;
3202            font-size: var(--t-h3);
3203            line-height: var(--lh-head);
3204            letter-spacing: var(--ls-head);
3205            color: var(--paper)
3206        }
3207
3208        .ruled-col h3 .it {
3209            font-family: var(--serif);
3210            font-style: normal;
3211            font-weight: 600;
3212            color: var(--signal)
3213        }
3214
3215        .ruled-col p {
3216            margin-top: 12px;
3217            color: var(--bone);
3218            font-size: var(--t-body);
3219            line-height: var(--lh-body)
3220        }
3221
3222        .ruled-col p b { color: var(--paper); font-weight: 500 }
3223
3224        .ruled-col .tag {
3225            margin-top: 18px;
3226            display: inline-block;
3227            font-family: var(--mono);
3228            font-weight: 500;
3229            font-size: var(--t-label);
3230            letter-spacing: var(--ls-label);
3231            text-transform: uppercase;
3232            color: var(--signal)
3233        }
3234
3235        /* A ruled index: numbered rows under one another, each a hairline, a
3236           name, a description and a tag. This is the /v2 service index and the
3237           shape the FAQ and the wellness escalation ladder both take. Rows may
3238           be links or plain divs; only the links get the sliding arrow.
3239
3240             <div class="rul
3240ed-index r">
3241               <a class="ruled-row" href="...">
3242                 <span class="num">01</span>
3243                 <span class="name">Fergus</span>
3244                 <span class="desc">...</span>
3245                 <span class="go"><span>Books visits</span><span class="arr">→</span></span>
3246               </a>
3247             </div> */
3248        .ruled-index {
3249            margin-top: 44px;
3250            border-bottom: 1px solid var(--line-2)
3251        }
3252
3253        .ruled-row {
3254            display: grid;
3255            grid-template-columns:64px minmax(160px, 240px) 1fr auto;
3256            gap: clamp(14px, 2vw, 28px);
3257            align-items: center;
3258            padding: 22px clamp(4px, 1vw, 12px);
3259            border-top: 1px solid var(--line-2);
3260            text-decoration: none;
3261            transition: background .3s var(--ease)
3262        }
3263
3264        .ruled-row .num {
3265            font-family: var(--mono);
3266            font-size: 11px;
3267            letter-spacing: .14em;
3268            color: var(--mute-2)
3269        }
3270
3271        .ruled-row .name {
3272            font-family: var(--serif);
3273            font-weight: 600;
3274            font-size: clamp(19px, 1.8vw, 24px);
3275            letter-spacing: -.01em;
3276            color: var(--paper);
3277            transition: color .3s var(--ease)
3278        }
3279
3280        .ruled-row .desc {
3281            color: var(--bone);
3282            font-size: var(--t-small);
3283            line-height: var(--lh-body)
3284        }
3285
3286        .ruled-row .go {
3287            display: inline-flex;
3288            align-items: center;
3289            gap: 14px;
3290            font-family: var(--mono);
3291            font-size: var(--t-label);
3292            letter-spacing: .14em;
3293            text-transform: uppercase;
3294            color: var(--mute);
3295            white-space: nowrap
3296        }
3297
3298        .ruled-row .go .arr {
3299            color: var(--signal);
3300            font-size: 15px;
3301            transition: transform .3s var(--ease-out)
3302        }
3303
3304        a.ruled-row:hover {
3305            background: var(--surface-2)
3306        }
3307
3308        a.ruled-row:hover .name {
3309            color: var(--signal)
3310        }
3311
3312        a.ruled-row:hover .go .arr {
3313            transform: translateX(6px)
3314        }
3315
3316        @media (max-width: 900px) {
3317            .ruled-row {
3318                grid-template-columns:40px 1fr auto
3319            }
3320
3321            .ruled-row .desc {
3322                grid-column:2 / 3;
3323                grid-row: 2;
3324                margin-top: 2px
3325            }
3326
3327            .ruled-row .go span:not(.arr) {
3328                display: none
3329            }
3330        }
3331
3332        /* ====== INTEGRATION WALL ======
3333           "Plugged into the software you already run", shared by the industry
3334           pages and the booking page. Replaces a bare grid of words whose cells
3335           were divided by a 1px gap, so "Microsoft" and "Outlook" ran together
3336           with nothing between one system and the next. Each system now gets
3337           its logo and room to breathe, which is the treatment /integrations
3338           already uses. Markup lives in frontend.partials.integration-wall. */
3339        .ig-wall {
3340            margin-top: 40px;
3341            display: grid;
3342            grid-template-columns:repeat(auto-fit, minmax(210px, 1fr));
3343            gap: clamp(20px, 2.4vw, 34px)
3344        }
3345
3346        .ig-item {
3347            display: flex;
3348            align-items: center;
3349            gap: 14px;
3350            padding: 20px 0 0;
3351            border-top: 1px solid var(--line-2);
3352            min-width: 0
3353        }
3354
3355        .ig-tile {
3356            flex: 0 0 44px;
3357            width: 44px;
3358            height: 44px;
3359            border-radius: 3px;
3360            border: 1px solid var(--line-2);
3361            display: grid;
3362            place-items: center;
3363            overflow: hidden
3364        }
3365
3366        .ig-tile.is-light {
3367            background: #fff
3368        }
3369
3370        .ig-tile img {
3371            width: 100%;
3372            height: 100%;
3373            object-fit: contain;
3374            padding: 7px
3375        }
3376
3377        .ig-tile b {
3378            font-family: var(--serif);
3379            font-size: 20px;
3380            font-weight: 400;
3381            line-height: 1
3382        }
3383
3384        .ig-name {
3385            font-family: var(--serif);
3386            font-weight: 400;
3387            font-size: 17px;
3388            line-height: 1.15;
3389            letter-spacing: -.01em;
3390            color: var(--paper);
3391            min-width: 0
3392        }
3393
3394        .ig-name small {
3395            display: block;
3396            margin-top: 4px;
3397            font-family: var(--mono);
3398            font-size: var(--t-label);
3399            letter-spacing: .14em;
3400            text-transform: uppercase;
3401            color: var(--mute)
3402        }
3403
3404        /* A price, a phone number, a headline figure: a heavier rule, a mono
3405           label and a big serif number. .is-pick marks the one being pushed. */
3406        .ruled-figure {
3407            border-top: 2px solid var(--line-2);
3408            padding: clamp(24px, 3vw, 40px) 0 0
3409        }
3410
3411        .ruled-figure.is-pick { border-top-color: var(--signal) }
3412
3413        .ruled-figure .lbl {
3414            display: block;
3415            font-family: var(--mono);
3416            font-size: 11px;
3417            letter-spacing: .18em;
3418            text-transform: uppercase;
3419            color: var(--mute)
3420        }
3421
3422        .ruled-figure .big {
3423            display: block;
3424            margin-top: 16px;
3425            font-family: var(--serif);
3426            font-weight: 600;
3427            font-size: clamp(46px, 5vw, 72px);
3428            line-height: 1;
3429            letter-spacing: -.03em;
3430            color: var(--paper)
3431        }
3432
3433        .ruled-figure .big small {
3434            font-family: var(--mono);
3435            font-size: 12px;
3436            letter-spacing: .08em;
3437            color: var(--mute)
3438        }
3439
3440        /* A list inside the ruled language leads with an arrow in the signal
3441           colour, over a dashed rule. No bullets, no ticks in circles. */
3442        .ruled-list {
3443            margin-top: 24px;
3444            list-style: none;
3445            display: flex;
3446            flex-direction: column;
3447            gap: 12px;
3448            border-top: 1px dashed var(--line);
3449            padding-top: 22px
3450        }
3451
3452        .ruled-list li {
3453            display: flex;
3454            gap: 12px;
3455            color: var(--bone);
3456            font-size: 14px;
3457            line-height: 1.5
3458        }
3459
3460        .ruled-list li::before {
3461            content: "\2192";
3462            color: var(--signal);
3463            font-family: var(--mono)
3464        }
3465
3466        /* The list started life as a list of statements. The trade and town
3467           indexes use it as navigation instead, so a link inside one has to
3468           read as a link: the arrow already leads the row, and this gives the
3469           words themselves the signal colour and something on hover. */
3470        .ruled-list li a {
3471            color: var(--signal);
3472            transition: color .2s var(--ease)
3473        }
3474
3475        .ruled-list li a:hover { color: var(--signal-warm) }
3476
3477        /* An aside is ruled down its edge rather than boxed in a tinted panel. */
3478        .ruled-aside {
3479            padding: 4px 0 4px 18px;
3480            border-left: 2px solid var(--plasma);
3481            color: var(--bone);
3482            font-size: 14px;
3483            line-height: 1.6
3484        }
3485
3486        .ruled-aside.is-ok { border-left-color: var(--signal) }
3487
3488        @media (prefers-reduced-motion: reduce) {
3489            .ruled-col::after { transition: none; transform: scaleX(1) }
3490        }
3491
3492        @media (max-width: 1000px) {
3493            .ruled-set.cols-3, .ruled-set.cols-4 { grid-template-columns:repeat(2, 1fr) }
3494        }
3495
3496        @media (max-width: 640px) {
3497            .ruled-set.cols-2, .ruled-set.cols-3, .ruled-set.cols-4 { grid-template-columns:1fr }
3498            .ruled-set.in .ruled-col::after { transition-delay: 0s }
3499        }
3500
3501        /* ====== SCROLL REVEAL ======
3502       .r hides a block until it scrolls into view. Two things it must never
3503       do: hold content back for a full second, and hide it for ever when the
3504       observer never runs. So the hidden state is applied only once the
3505       script has declared itself (html.js), and only where motion is wel
3505come.
3506       No JS, or reduced motion, means everything is simply visible. */
3507        html.js .r {
3508            opacity: 0;
3509            transform: translateY(16px);
3510            transition: opacity .4s var(--ease-out), transform .4s var(--ease-out)
3511        }
3512
3513        html.js .r.in {
3514            opacity: 1;
3515            transform: none
3516        }
3517
3518        .r-1 { transition-delay: .05s }
3519
3520        .r-2 { transition-delay: .1s }
3521
3522        @media (prefers-reduced-motion: reduce) {
3523            html.js .r, html.js .r.in, .r, .r.in {
3524                opacity: 1;
3525                transform: none;
3526                transition: none
3527            }
3528        }
3529
3530        /* ====== STEPS ====== */
3531        .steps {
3532            display: grid;
3533            grid-template-columns:repeat(3, 1fr);
3534            gap: clamp(20px, 3vw, 40px);
3535            margin-top: 56px;
3536            position: relative
3537        }
3538
3539        /* There was a connector line here, threaded through the middle of the
3540           circular step badges at a fixed 36px from the top. The badges are
3541           outlined numerals now and each step carries its own rule, so the
3542           connector had nothing left to connect and simply struck through the
3543           numbers. */
3544
3545        /* V2 numbered steps: a hairline over each that fills with the brand
3546           gradient as it scrolls in, rather than a filled card that lifts. */
3547        .step {
3548            position: relative;
3549            padding: 30px 0 0;
3550            display: flex;
3551            flex-direction: column;
3552            gap: 16px
3553        }
3554
3555        .step::before, .step::after {
3556            content: "";
3557            position: absolute;
3558            top: 0;
3559            left: 0;
3560            right: 0;
3561            height: 1px
3562        }
3563
3564        .step::before {
3565            background: var(--line-2)
3566        }
3567
3568        .step::after {
3569            background: var(--grad);
3570            transform: scaleX(0);
3571            transform-origin: left;
3572            transition: transform .9s var(--ease-out)
3573        }
3574
3575        .step.in::after, .steps.in .step::after {
3576            transform: scaleX(1)
3577        }
3578
3579        .steps.in .step:nth-child(2)::after {
3580            transition-delay: .12s
3581        }
3582
3583        .steps.in .step:nth-child(3)::after {
3584            transition-delay: .24s
3585        }
3586
3587        .step:hover::after {
3588            transform: scaleX(1)
3589        }
3590
3591        /* V2 numbers a step with a big outlined italic numeral rather than a
3592           digit inside a circular badge. */
3593        .step .num {
3594            font-family: var(--serif);
3595            font-weight: 600;
3596            font-size: 64px;
3597            line-height: 1;
3598            color: transparent;
3599            -webkit-text-stroke: 1px var(--line-2);
3600            position: relative;
3601            z-index: 1
3602        }
3603
3604        .step h4 {
3605            font-family: var(--serif);
3606            font-weight: 400;
3607            font-size: 24px;
3608            letter-spacing: -.01em;
3609            line-height: 1.1
3610        }
3611
3612        .step h4 .it {
3613            font-family: var(--serif);
3614            font-weight: 600;
3615            color: var(--mute)
3616        }
3617
3618        .step h4 {
3619            margin-top: 2px
3620        }
3621
3622        .step p {
3623            color: var(--bone);
3624            font-size: var(--t-body);
3625            line-height: 1.6
3626        }
3627
3628        .hero-steps-hd {
3629            margin-top: 34px;
3630            font-family: var(--serif);
3631            font-weight: 600;
3632            font-size: 34px;
3633            letter-spacing: -.02em;
3634            line-height: 1.1;
3635            color: var(--paper);
3636            opacity: 0;
3637            animation: rise2 .9s 1.1s var(--ease-out) forwards
3638        }
3639
3640        .hero-steps-hd .it {
3641            font-family: var(--serif);
3642            font-weight: 600;
3643            color: var(--signal)
3644        }
3645
3646        /* Vertical variant, so the steps can run down a narrow hero column
3647           beside a tall form instead of across the page. */
3648        .steps.stack {
3649            grid-template-columns:1fr;
3650            gap: 12px;
3651            margin-top: 30px;
3652            max-width: 560px
3653        }
3654
3655        .steps.stack::before {
3656            display: none
3657        }
3658
3659        .steps.stack .step {
3660            flex-direction: row;
3661            align-items: flex-start;
3662            gap: 20px;
3663            padding: 22px 0 0
3664        }
3665
3666        .steps.stack .step .num {
3667            flex: 0 0 auto;
3668            font-size: 40px;
3669            line-height: .9
3670        }
3671
3672        .steps.stack .step .body {
3673            display: grid;
3674            gap: 8px
3675        }
3676
3677        .steps.stack .step h4 {
3678            font-size: 20px
3679        }
3680
3681        .steps.stack .step p {
3682            font-size: 13px
3683        }
3684
3685        /* ====== CAPABILITY PLATE ======
3686           Capabilities in the V2 design language, the same vocabulary the /v2
3687           homepage and the wellness page use: top-ruled columns rather than
3688           boxed cards. Each cell is a hairline and the copy under it, and the
3689           hairline fills with the brand gradient as the plate scrolls in.
3690
3691           It was a filled, rounded plate whose cells were divided by letting a
3692           1px grid gap show the plate's own background through. That is 
3692what
3693           made a short last row read as a slab of grey, and what made the set
3694           look like cards floating on the page rather than part of it.
3695
3696           Each cell still leads with the moment in the call it fires, so the
3697           set reads as a timeline rather than a feature dump. */
3698        .cap-plate {
3699            display: grid;
3700            gap: clamp(22px, 3vw, 44px);
3701            grid-template-columns:repeat(3, 1fr)
3702        }
3703
3704        .cap {
3705            position: relative;
3706            padding: 30px 0 0;
3707            display: flex;
3708            flex-direction: column;
3709            gap: 10px
3710        }
3711
3712        /* the standing hairline, and the gradient that draws over it */
3713        .cap::before, .cap::after {
3714            content: "";
3715            position: absolute;
3716            top: 0;
3717            left: 0;
3718            right: 0;
3719            height: 1px
3720        }
3721
3722        .cap::before {
3723            background: var(--line-2)
3724        }
3725
3726        .cap::after {
3727            background: var(--grad);
3728            transform: scaleX(0);
3729            transform-origin: left;
3730            transition: transform .9s var(--ease-out)
3731        }
3732
3733        /* the plate carries .r, so the site-wide reveal observer is what starts
3734           the fill; the cells stagger across the row behind it */
3735        .cap-plate.in .cap::after {
3736            transform: scaleX(1)
3737        }
3738
3739        .cap-plate .cap:nth-child(3n + 2)::after {
3740            transition-delay: .12s
3741        }
3742
3743        .cap-plate .cap:nth-child(3n)::after {
3744            transition-delay: .24s
3745        }
3746
3747        /* No icon marks in this language: the rule and the type carry the cell,
3748           and a glyph per capability was the last of the card furniture. The
3749           mark is still rendered so the components keep their contract; it just
3750           has nothing to say here. */
3751        .cap-mark {
3752            display: none
3753        }
3754
3755        .cap .when {
3756            font-family: var(--mono);
3757            font-size: var(--t-label);
3758            letter-spacing: .16em;
3759            text-transform: uppercase;
3760            color: var(--signal);
3761            display: flex;
3762            align-items: center;
3763            justify-content: space-between;
3764            gap: 14px
3765        }
3766
3767        /* the mark is gone, so this is just the title's own line now */
3768        .cap-hd {
3769            display: block
3770        }
3771
3772        .cap h3 {
3773            font-family: var(--serif);
3774            font-weight: 400;
3775            font-size: 24px;
3776            line-height: 1.14;
3777            letter-spacing: -.012em;
3778            color: var(--paper);
3779            padding-bottom: 2px
3780        }
3781
3782        .cap h3 .it {
3783            font-family: var(--serif);
3784            font-weight: 600;
3785            color: var(--signal)
3786        }
3787
3788        .cap h3 .blue {
3789            font-family: var(--serif);
3790            font-weight: 600;
3791            color: var(--plasma-bright)
3792        }
3793
3794        /* .green was never styled inside the old bento h4s, so it rendered as
3795           flat body text there. Carried onto the plate it gets the same
3796           treatment as .it, matching the tuner headings. */
3797        .cap h3 .green {
3798            font-family: var(--serif);
3799            font-weight: 600;
3800            color: var(--signal)
3801        }
3802
3803        .cap p {
3804            color: var(--bone);
3805            font-size: var(--t-body);
3806            line-height: 1.62
3807        }
3808
3809        .cap p b {
3810            color: var(--paper);
3811            font-weight: 500
3812        }
3813
3814        /* The closing call to action sits under the plate rather than in it. As
3815           a cell it was three times the width of its neighbours and read as a
3816           row that had failed to fill, so it carries no fill of its own.
3817
3818           It does carry a rule across the full width, which is what closes the
3819           plate off now that the plate has no border: the cells are ruled at
3820           the top, this rules underneath them, and the set reads as one block
3821           rather than a run of columns that simply stops. */
3822        .cap-foot {
3823            display: flex;
3824            align-items: center;
3825            justify-content: space-between;
3826            flex-wrap: wrap;
3827            gap: 20px 36px;
3828            margin-top: clamp(38px, 4vw, 56px);
3829            padding: clamp(26px, 3vw, 38px) 0 0;
3830            border-top: 1px solid var(--line-2)
3831        }
3832
3833        .cap-foot > div {
3834            max-width: 62ch;
3835            display: flex;
3836            flex-direction: column;
3837            gap: 8px
3838        }
3839
3840        .cap-foot h3 {
3841            font-family: var(--serif);
3842            font-weight: 600;
3843            font-size: 26px;
3844            line-height: 1.2;
3845            letter-spacing: -.015em;
3846            color: var(--paper);
3847            margin: 0
3848        }
3849
3850        .cap-foot h3 .it {
3851            font-family: var(--serif);
3852            font-weight: 600;
3853        }
3854
3855        .cap-foot p {
3856            font-size: var(--t-body);
3857            line-height: 1.6;
3858            color: var(--mute);
3859            margin: 0
3860        }
3861
3862        @media (max-width: 640px) {
3863            .cap-foot {
3864                margin-top: 24px
3865            }
3866
3867            .cap-foot h3 {
3868                font-size: 22px
3869            }
3870        }
3871
3872        /* Industry pages keep their own emphasis: two lead cells across the
3873           top, three underneath. A six-column track divides cleanly both ways,
3874           so neither row is left with a hole. */
3875        .cap-plate.mixed {
3876            grid-template-columns:repeat(6, 1fr)
3877        }
3878
3879        .cap-plate.mixed .cap.half {
3880            grid-column:span 3
3881        }
3882
3883        .cap-plate.mixed .cap.third {
3884            grid-column:span 2
3885        }
3886
3887        /* There used to be a set of rules here that stretched whatever was left
3888           alone on the final row so it filled the width. That existed only
3889           because the old plate drew its rules by letting its own background
3890           through a 1px grid gap, so a row the cells did not fill showed up as
3891           a slab of grey.
3892
3893           Top-ruled columns have no fill to show through, so a short last row
3894           is simply empty space and needs no correction. Stretching a lone cell
3895           now would be actively wrong: its hairline would run three times the
3896           length of every other cell's and break the measure. The plates are
3897           still authored to fill their rows, and CapabilityPlateTest still
3898           guards that, but it is a composition rule now rather than a patch
3899           over an artefact.
3900
3901           (The old block also had a stray half-comment in it, which made the
3902           browser discard the first of the two rules outright.) */
3903
3904        @media (max-width: 1000px) {
3905            .cap-plate {
3906                grid-template-columns:repeat(2, 1fr)
3907            }
3908
3909            .cap-plate.mixed {
3910                grid-template-columns:repeat(2, 1fr)
3911            }
3912
3913            .cap-plate.mixed .cap.half,
3914            .cap-plate.mixed .cap.third {
3915                grid-column:auto
3916            }
3917
3918            /* two across, so the three-column stagger no longer describes a row */
3919            .cap-plate .cap:nth-child(3n + 2)::after,
3920            .cap-plate .cap:nth-child(3n)::after {
3921                transition-delay: 0s
3922            }
3923
3924            .cap-plate .cap:nth-child(even)::after {
3925                transition-delay: .12s
3926            }
3927        }
3928
3929        @media (max-width: 640px) {
3930            .cap-plate,
3931            .cap-plate.mixed {
3932                grid-template-columns:1fr
3933            }
3934
3935            /* one column, so nothing is beside anything: no stagger */
3936            .cap-plate .cap::after {
3937                transition-delay: 0s
3938            }
3939
3940            .cap.wide {
3941                flex-direction: column;
3942                align-items: flex-start
3943            }
3944        }
3945
3946        @media (prefers-reduced-motion: reduce) {
3947            .cap::after {
3948                transition: none;
3949                transform: scaleX(1)
3950            }
3951        }
3952
3953        /* ====== HERO PHONE ======
3954           The one device mock on the site. It earns its place by being
3955           interactive: the chips drive the notification and pause the cycle. */
3956        .hphone {
3957            display: flex;
3958            flex-direction: column;
3959            align-items: center;
3960            gap: 20px;
3961            width: 100%
3962        }
3963
3964        .hphone-frame {
3965            width: min(268px, 72vw);
3966            aspect-ratio: 9/18.6;
3967            border-radius: 38px;
3968            padding: 9px;
3969            background: linear-gradient(160deg, #23262b, #0e1013 60%, #191c20);
3970            box-shadow: 0 30px 70px var(--shadow-deep), 0 0 0 1px rgba(255, 255, 255, .07) inset;
3971            flex: 0 0 auto
3972        }
3973
3974        .hphone-screen {
3975            position: relative;
3976            height: 100%;
3977            border-radius: 30px;
3978            overflow: hidden;
3979            background: radial-gradient(120% 80% at 50% 0%, #1c2330, #0a0d12 70%);
3980            display: flex;
3981            flex-direction: column;
3982            padding: 26px 12px 14px
3983        }
3984
3985        .hphone-notch {
3986            position: absolute;
3987            top: 8px;
3988            left: 50%;
3989            transform: translateX(-50%);
3990            width: 78px;
3991            height: 20px;
3992            border-radius: 12px;
3993            background: #05070a
3994        }
3995
3996        .hphone-clock {
3997            text-align: center;
3998            margin: 14px 0 18px;
3999            color: #fff
4000        }
4001
4002        .hphone-clock .t {
4003            font-size: 46px;
4004            font-weight: 300;
4005            letter-spacing: -.02em;
4006            line-height: 1
4007        }
4008
4009        .hphone-clock .d {
4010            font-size: 11.5px;
4011            color: rgba(255, 255, 255, .68);
4012            margin-top: 4px
4013        }
4014
4015        .hphone-stack {
4016            display: flex;
4017            flex-direction: column;
4018            gap: 7px;
4019            flex: 1
4020        }
4021
4022        .hpn {
4023            background: rgba(238, 238, 240, .93);
4024            border-radius: 16px;
4025            padding: 9px 11px 11px;
4026            opacity: 0;
4027            /* drops in from above the notch with a little overshoot, the way a
4028               push actually arrives, rather than fading on the spot */
4029            transform: translateY(-22px) scale(.94);
4030            transition: opacity .42s var(--ease-out),
4031                        transform .62s cubic-bezier(.22, 1.4, .36, 1);
4032            pointer-events: none
4033        }
4034
4035        .hpn.is-in {
4036            opacity: 1;
4037            transform: none
4038        }
4039
4040        .hpn header {
4041            display: flex;
4042            align-items: center;
4043            gap: 6px;
4044            margin-bottom: 5px
4045        }
4046
4047        .hpn header img {
4048            border-radius: 5px;
4049            display: block
4050        }
4051
4052        /* hpn- prefixed: a bare .app collides with the app showcase panel,
4053           which is an 80px-padded gradient grid, and it ate the header */
4054        .hpn .hpn-app {
4055            font-size: 10.5px;
4056            color: #63666b;
4057            flex: 1
4058        }
4059
4060        .hpn .hpn-ago {
4061            font-size: 10.5px;
4062            color: #8b8e93
4063        }
4064
4065        .hpn h4 {
4066            font-size: 13.5px;
4067            font-weight: 600;
4068            color: #14171a;
4069            letter-spacing: -.005em
4070        }
4071
4072        .hpn p {
4073            font-size: 11.5px;
4074            color: #4e5155;
4075            margin-top: 1px;
4076            line-height: 1.35
4077        }
4078
4079        .hphone-bar {
4080            width: 96px;
4081            height: 4px;
4082            border-radius: 4px;
4083            background: rgba(255, 255, 255, .55);
4084            margin: 8px auto 0
4085        }
4086
4087        /* A LOCK SCREEN THAT PLAYS. Used by the PA and reception panels, which
4088           tell the same story with different notifications. See
4089           partials/agent-phone.blade.php.
4090
4091           --ag-tilt and --ag-sheen are written by the scroll handler; the
4092           values here are the resting state before it runs and whenever motion
4093           is refused. The two panels lean opposite ways so the pair reads as a
4094           spread rather than as the same picture twice. */
4095        .agent-phone {
4096            transform: rotate(var(--ag-tilt, 3deg));
4097            transition: transform .25s linear
4098        }
4099
4100        .agent-phone--left {
4101            --ag-tilt: -3deg
4102        }
4103
4104        .agent-phone .hphone-frame {
4105            position: relative;
4106            overflow: hidden
4107        }
4108
4109        /* The sheen is what sells the front as glass rather than as a
4110           rectangle. Decorative only: nothing sits under it. */
4111        .agent-phone .hphone-frame::after {
4112            content: "";
4113            position: absolute;
4114            inset: -30%;
4115            pointer-events: none;
4116            z-index: 3;
4117            background: linear-gradient(105deg,
4118                transparent 38%,
4119                rgba(255, 255, 255, .13) 47%,
4120                rgba(255, 255, 255, .22) 50%,
4121                rgba(255, 255, 255, .13) 53%,
4122                transparent 62%);
4123            transform: translateX(var(--ag-sheen, -20%));
4124            transition: transform .25s linear
4125        }
4126
4127        /* iOS shrinks the clock and lifts it the moment something lands on a
4128           locked screen. Doing the same is what makes the notifications read as
4129           arriving rather than as part of the wallpaper. */
4130        .agent-phone .hphone-clock {
4131            transition: margin .55s var(--ease-out)
4132        }
4133
4134        .agent-phone .hphone-clock .t {
4135            transition: font-size .55s var(--ease-out)
4136        }
4137
4138        .agent-phone .hphone-clock .d {
4139            transition: font-size .55s var(--ease-out), opacity .4s var(--ease)
4140        }
4141
4142        .agent-phone .hphone-clock.is-compact {
4143            margin: 2px 0 12px
4144        }
4145
4146        .agent-phone .hphone-clock.is-compact .t {
4147            font-size: 21px
4148        }
4149
4150        .agent-phone .hphone-clock.is-compact .d {
4151            font-size: 10px;
4152            opacity: .8
4153        }
4154
4155        @media (prefers-reduced-motion: reduce) {
4156            .agent-phone,
4157            .agent-phone .hphone-clock,
4158            .agent-phone .hphone-clock .t,
4159            .agent-phone .hphone-clock .d,
4160            .agent-phone .hphone-frame::after {
4161                transition: none
4162            }
4163
4164            .agent-phone {
4165                transform: none
4166            }
4167
4168            .agent-phone .hphone-frame::after {
4169                display: none
4170            }
4171        }
4172
4173        .hphone-chips {
4174            display: flex;
4175            flex-wrap: wrap;
4176            justify-content: center;
4177            gap: 7px;
4178            max-width: 340px
4179        }
4180
4181        .hpc {
4182            font-family: var(--mono);
4183            font-size: var(--t-label);
4184            letter-spacing: .1em;
4185            text-transform: uppercase;
4186            /* --bone not --mute: the label is 10px, so it needs AA, and mute
4187               only clears 3:1 against the chip fill in light theme */
4188            color: var(--bone);
4189            background: var(--surface-2);
4190            border: 1px solid var(--line);
4191            border-radius: 7px;
4192            padding: 6px 9px;
4193            cursor: pointer;
4194            transition: color .25s var(--ease), border-color .25s var(--ease), background .25s var(--ease)
4195        }
4196
4197        .hpc:hover {
4198            color: var(--paper);
4199            border-color: var(--line-2)
4200        }
4201
4202        .hpc.is-on {
4203            /* fixed dark ink rather than --on-accent: it has to clear AA on
4204               both the light-theme green and the brighter dark-theme one */
4205            color: #0b0d0a;
4206            background: var(--signal);
4207            border-color: transparent
4208        }
4209
4210        .hpc:focus-visible {
4211            outline: 2px solid var(--plasma-bright);
4212            outline-offset: 2px
4213        }
4214
4215        @media (max-width: 900px) {
4216            .hphone {
4217                margin-top: 34px
4218            }
4219
4220            .hphone-frame {
4221                width: min(232px, 62vw)
4222            }
4223        }
4224
4225        @media (prefers-reduced-motion: reduce) {
4226            .hpn {
4227                transition: none
4228            }
4229        }
4230
4231        /* ====== TRADE INDEX ======
4232           Photographic directory. The tiles were held inside one rounded,
4233           filled container and ruled off each other by letting its background
4234           through a 1px grid gap. In the V2 language the container goes and the
4235           tiles are ruled individually, so the set sits on the page rather than
4236           on a plate laid over it. The photography stays: V2 keeps photographs,
4237           it is the boxes around them it does without. */
4238        .trade-plate {
4239            display: grid;
4240            gap: clamp(20px, 2.6vw, 36px)
4241        }
4242
4243        .trade-plate.cols-3 {
4244            grid-template-columns:repeat(3, 1fr)
4245        }
4246
4247        .trade-plate.cols-4 {
4248            grid-template-columns:repeat(4, 1fr)
4249        }
4250
4251        /* four across is tighter, so the type steps down with it */
4252        .trade-plate.cols-4 .body {
4253            padding: 19px 20px 18px;
4254            gap: 8px
4255        }
4256
4257        .trade-plate.cols-4 h3 {
4258            font-size: 20px
4259        }
4260
4261        .trade-plate.cols-4 p {
4262            font-size: 13px;
4263            line-height: 1.55
4264        }
4265
4266        .trade-plate.cols-4 .go {
4267            padding-top: 13px;
4268            font-size: 10px
4269        }
4270
4271        .trade {
4272            position: relative;
4273            display: flex;
4274            flex-direction: column;
4275            text-decoration: none;
4276            color: inherit;
4277            transition: background .35s var(--ease)
4278        }
4279
4280        .trade:hover {
4281            background: var(--surface-2)
4282        }
4283
4284        .trade .shot {
4285            position: relative;
4286            aspect-ratio: 16/10;
4287            overflow: hidden;
4288            /* the notification card inside is sized in cqw against this */
4289            container-type: inline-size
4290        }
4291
4292        /* THE NOTIFICATION ON A PHOTOGRAPH. See components/frontend/shot-alert.
4293           It used to be composited into the JPEG, which pinned it to one spot
4294           in a portrait frame and froze an old mark inside it. Drawn here it
4295           takes the mark from the brand component and sits where each context
4296           needs it.
4297
4298           Everything is derived from one unit, --u, so the whole card scales
4299           together: type, padding, corner radius, mark and tail all stay in
4300           proportion at every tile size. The card is 56 units wide, and .75cqw
4301           makes that 42% of the photo, which is the proportion the composited
4302           card had and the one the crops were framed around.
4303
4304           The clamp holds both ends of that. Below about a 350px tile a strict
4305           42% would put the subtitle under 10px, so the card is allowed to take
4306           a larger share of a small photo rather than become unreadable on it.
4307           Above about a 730px tile it stops growing, because past that the card
4308           has stopped reading as a notification and started reading as a
4309           banner. Anything holding a .shot-alert needs container-type:
4310           inline-size for cqw to resolve.
4311
4312           Light in both themes on purpose: it sits on a daylight photograph,
4313           not on the page. */
4314        .shot-alert {
4315            --u: clamp(3.1px, .75cqw, 5.5px);
4316            --alert-ground: rgba(244, 244, 242, .93);
4317            position: absolute;
4318            z-index: 2;
4319            display: flex;
4320            flex-direction: column;
4321            gap: calc(1.1 * var(--u));
4322            width: calc(56 * var(--u));
4323            padding: calc(3.6 * var(--u)) calc(4 * var(--u)) calc(4 * var(--u));
4324            border-radius: calc(4.4 * var(--u));
4325            background: var(--alert-ground);
4326            backdrop-filter: blur(7px);
4327            -webkit-backdrop-filter: blur(7px);
4328            box-shadow: 0 calc(3 * var(--u)) calc(6 * var(--u)) calc(-2 * var(--u)) rgba(8, 12, 16, .32);
4329            color: #101820;
4330            font-family: var(--sans);
4331            line-height: 1.25;
4332            text-wrap: balance;
4333            pointer-events: none
4334        }
4335
4336        /* the tail, on the side the card is anchored to */
4337        .shot-alert::after {
4338            content: "";
4339            position: absolute;
4340            bottom: calc(-2.6 * var(--u));
4341            width: 0;
4342            height: 0;
4343            border-top: calc(3 * var(--u)) solid var(--alert-ground);
4344            border-right: calc(3.4 * var(--u)) solid transparent
4345        }
4346
4347        /* Insets stay a fraction of the photo rather than of the card, so the
4348           gap to the frame edge reads the same on a tile and on a hero. */
4349        .shot-alert.at-top-left, .shot-alert.at-bottom-left {
4350            left: min(4cqw, 24px)
4351        }
4352
4353        .shot-alert.at-top-right, .shot-alert.at-bottom-right {
4354            right: min(4cqw, 24px)
4355        }
4356
4357        .shot-alert.at-top-left, .shot-alert.at-top-right {
4358            top: min(4.5cqw, 26px)
4359        }
4360
4361        .shot-alert.at-bottom-left, .shot-alert.at-bottom-right {
4362            bottom: min(7cqw, 40px)
4363        }
4364
4365        .shot-alert.at-top-left::after, .shot-alert.at-bottom-left::after {
4366            left: calc(9 * var(--u))
4367        }
4368
4369        .shot-alert.at-top-right::after, .shot-alert.at-bottom-right::after {
4370            right: calc(9 * var(--u));
4371            border-right: 0;
4372            border-left: calc(3.4 * var(--u)) solid transparent
4373        }
4374
4375        /* a card anchored to the bottom points its tail upward instead */
4376        .shot-alert.at-bottom-left::after, .shot-alert.at-bottom-right::after {
4377            bottom: auto;
4378            top: calc(-2.6 * var(--u));
4379            border-top: 0;
4380            border-bottom: calc(3 * var(--u)) solid var(--alert-ground)
4381        }
4382
4383        .shot-alert-hd {
4384            display: flex;
4385            align-items: center;
4386            gap: calc(1.8 * var(--u))
4387        }
4388
4389        .shot-alert-mark {
4390            width: calc(5.2 * var(--u));
4391            height: calc(5.2 * var(--u));
4392            flex: none
4393        }
4394
4395        .shot-alert-app {
4396            font-size: calc(2.8 * var(--u));
4397            font-weight: 500;
4398            color: #5b6570
4399        }
4400
4401        .shot-alert-stamp {
4402            margin-left: auto;
4403            font-size: calc(2.66 * var(--u));
4404            color: #8c949d
4405        }
4406
4407        .shot-alert-title {
4408            font-size: calc(3.86 * var(--u));
4409            font-weight: 600;
4410            letter-spacing: -.01em
4411        }
4412
4413        .shot-alert-body {
4414            font-size: calc(3.06 * var(--u));
4415            color: #3d4650
4416        }
4417
4418        /* Four across on a small laptop makes a tile barely wider than the card
4419           itself. The floor has already stopped the type shrinking, so the only
4420           thing left to give is the detail line: below this the card keeps the
4421           headline and drops the rest, the way a notification does when the
4422           space it has is one line deep. */
4423        @container (max-width: 300px) {
4424            .shot-alert-body {
4425                display: none
4426            }
4427        }
4428
4429        /* inner layer carries the photo so the scale-on-hover never touches type */
4430        .trade .shot i {
4431            position: absolute;
4432            inset: 0;
4433            background-image: var(--shot-dark);
4434            background-size: cover;
4435            /* --pos is set per entry: the source photos are a mix of portrait
4436               and landscape, so each one gets its own crop anchor to keep the
4437               face and the phone in frame */
4438            background-position: var(--pos, center);
4439            filter: saturate(.8) contrast(1.03);
4440            transform: scale(1.01);
4441            transition: transform .9s var(--ease-out), filter .5s var(--ease)
4442        }
4443
4444        html[data-theme="light"] .trade .shot i {
4445            background-image: var(--shot-light, var(--shot-dark));
4446            /* two of the day shots are portrait where their night twin is
4447               landscape, so they need their own anchor */
4448            background-position: var(--pos-light, var(--pos, center))
4449        }
4450
4451        .trade:hover .shot i {
4452            transform: scale(1.06);
4453            filter: none
4454        }
4455
4456        /* brand rule wipes along the photo edge, standing in for a hover lift */
4457        .trade .shot::after {
4458            content: "";
4459            position: absolute;
4460            top: 0;
4461            left: 0;
4462            right: 0;
4463            height: 2px;
4464            background: var(--grad);
4465            transform: scaleX(0);
4466            transform-origin: left;
4467            transition: transform .55s var(--ease-out)
4468        }
4469
4470        .trade:hover .shot::after {
4471            transform: scaleX(1)
4472        }
4473
4474        .trade .body {
4475            flex: 1;
4476            display: flex;
4477            flex-direction: column;
4478            gap: 9px;
4479            padding: 22px 24px 20px
4480        }
4481
4482        .trade .hd {
4483            display: flex;
4484            align-items: flex-start;
4485            justify-content: space-between;
4486            gap: 18px
4487        }
4488
4489        .trade h3 {
4490            font-family: var(--serif);
4491            font-weight: 400;
4492            font-size: 23px;
4493            line-height: 1.14;
4494            letter-spacing: -.012em;
4495            padding-bottom: 2px
4496        }
4497
4498        .trade h3 .it {
4499            font-family: var(--serif);
4500            font-weight: 600;
4501            color: var(--signal)
4502        }
4503
4504        .trade h3 .blue {
4505            font-family: var(--serif);
4506            font-weight: 600;
4507            color: var(--plasma-bright)
4508        }
4509
4510        /* the mark: bare glyph, no tile, no fill, muted until you reach for it.
4511           --mute not --mute-2: mute-2 only clears 2.8:1 on the light paper
4512           ground, which fails both the AA text and the 3:1 graphics minimum */
4513        .trade .mark {
4514            flex: 0 0 auto;
4515            color: var(--mute);
4516            transition: color .35s var(--ease)
4517        }
4518
4519        .trade:hover .mark {
4520            color: var(--signal)
4521        }
4522
4523        .trade p {
4524            color: var(--bone);
4525            font-size: var(--t-small);
4526            line-height: 1.58
4527        }
4528
4529        .trade .go {
4530            margin-top: auto;
4531            padding-top: 16px;
4532            display: flex;
4533            align-items: center;
4534            gap: 9px;
4535            font-family: var(--mono);
4536            font-size: var(--t-label);
4537            letter-spacing: .16em;
4538            text-transform: uppercase;
4539            color: var(--mute);
4540            transition: color .35s var(--ease)
4541        }
4542
4543        .trade:hover .go {
4544            color: var(--paper)
4545        }
4546
4547        .trade .go em {
4548            font-style: normal;
4549            transition: transform .35s var(--ease-out)
4550        }
4551
4552        .trade:hover .go em {
4553            transform: translateX(5px)
4554        }
4555
4556        /* full-width entry: photo becomes a left band, rule wipes down its edge */
4557        .trade.wide {
4558            grid-column:1 / -1;
4559            flex-direction: row;
4560            align-items: stretch
4561        }
4562
4563        .trade.wide .shot {
4564            flex: 0 0 36%;
4565            aspect-ratio: auto;
4566            min-height: 216px
4567        }
4568
4569        .trade.wide .shot::after {
4570            top: 0;
4571            bottom: 0;
4572            left: 0;
4573            right: auto;
4574            width: 2px;
4575            height: auto;
4576            transform: scaleY(0);
4577            transform-origin: top
4578        }
4579
4580        .trade.wide:hover .shot::after {
4581            transform: scaleY(1)
4582        }
4583
4584        .trade.wide .body {
4585            justify-content: center;
4586            padding: 34px 38px;
4587            max-width: 62ch
4588        }
4589
4590        .trade.wide h3 {
4591            font-size: 30px
4592        }
4593
4594        .trade.wide p {
4595            font-size: var(--t-body)
4596        }
4597
4598        /* compact ruled entries for the non-trade set: no photo, mark leads the row */
4599        /* The row variant carries no photo, so it is the V2 service index: a
4600           hairline over each row, the name, the description, and the tag with
4601           an arrow that slides on hover. It used to be a filled bar with a
4602           gradient stripe running down its left edge and an icon opposite. */
4603        .trade-plate:has(.trade.row) {
4604            gap: 0;
4605            border-bottom: 1px solid var(--line-2)
4606        }
4607
4608        .trade.row {
4609            flex-direction: row;
4610            align-items: center;
4611            gap: clamp(14px, 2vw, 28px);
4612            padding: 22px clamp(4px, 1vw, 12px);
4613            border-top: 1px solid var(--line-2)
4614        }
4615
4616        /* the icon mark goes with the boxes */
4617        .trade.row .mark {
4618            display: none
4619        }
4620
4621        .trade.row h3 {
4622            flex: 0 0 clamp(190px, 21vw, 270px);
4623            font-family: var(--serif);
4624            font-weight: 400;
4625            font-size: clamp(19px, 1.8vw, 24px);
4626            letter-spacing: -.01em;
4627            color: var(--paper);
4628            transition: color .3s var(--ease)
4629        }
4630
4631        .trade.row:hover h3 {
4632            color: var(--signal)
4633        }
4634
4635        .trade.row .go em {
4636            display: inline-block;
4637            color: var(--signal);
4638            font-style: normal;
4639            transition: transform .3s var(--ease-out)
4640        }
4641
4642        .trade.row:hover .go em {
4643            transform: translateX(6px)
4644        }
4645
4646        .trade.row p {
4647            flex: 1
4648        }
4649
4650        .trade.row .go {
4651            margin: 0;
4652            padding: 0;
4653            flex: 0 0 auto
4654        }
4655
4656        @media (max-width: 1240px) {
4657            .trade-plate.cols-4 {
4658                grid-template-columns:repeat(3, 1fr)
4659            }
4660        }
4661
4662        @media (max-width: 940px) {
4663            .trade-plate.cols-4 {
4664                grid-template-columns:repeat(2, 1fr)
4665            }
4666        }
4667
4668        @media (max-width: 1100px) {
4669            .trade-plate.cols-3 {
4670                grid-template-columns:repeat(2, 1fr)
4671            }
4672
4673            .trade.row h3 {
4674                flex-basis: 210px
4675            }
4676
4677            .trade.row .go span {
4678                display: none
4679            }
4680        }
4681
4682        @media (max-width: 640px) {
4683            .trade-plate.cols-4 {
4684                grid-template-columns:1fr
4685            }
4686
4687            .trade-plate.cols-3 {
4688                grid-template-columns:1fr
4689            }
4690
4691            .trade.wide {
4692                flex-direction: column
4693            }
4694
4695            .trade.wide .shot {
4696                flex: none;
4697                aspect-ratio: 16/9;
4698                min-height: 0
4699            }
4700
4701            .trade.wide .shot::after {
4702                top: 0;
4703                bottom: auto;
4704                left: 0;
4705                right: 0;
4706                width: auto;
4707                height: 2px;
4708                transform: scaleX(0);
4709                transform-origin: left
4710            }
4711
4712            .trade.wide:hover .shot::after {
4713                transform: scaleX(1)
4714            }
4715
4716            .trade.wide .body {
4717                padding: 22px 24px 20px
4718            }
4719
4720            .trade.wide h3 {
4721                font-size: 24px
4722            }
4723
4724            .trade.row {
4725                flex-direction: column;
4726                align-items: flex-start;
4727                gap: 10px;
4728                padding: 22px 24px
4729            }
4730
4731            .trade.row h3 {
4732                flex: none
4733            }
4734
4735            .trade.row .go span {
4736                display: inline
4737            }
4738        }
4739
4740        @media (prefers-reduced-motion: reduce) {
4741            .trade, .trade .shot i, .trade .shot::after, .trade .mark, .trade .go, .trade .go em, .trade.row::before {
4742                transition: none
4743            }
4744
4745            .trade:hover .shot i {
4746                transform: scale(1.01)
4747            }
4748        }
4749
4750        /* ====== CONVO ====== */
4751        .convo {
4752            display: flex;
4753            flex-direction: column;
4754            gap: 14px;
4755            max-width: 760px;
4756            margin: 0 auto;
4757            font-family: var(--mono);
4758            font-size: 13px
4759        }
4760
4761        .convo .bub {
4762            padding: 14px 18px;
4763            border-radius: 14px;
4764            border: 1px solid var(--line);
4765            max-width: 78%;
4766            line-height: 1.55;
4767            position: relative;
4768            opacity: 0;
4769            transform: translateY(12px) scale(.97);
4770            transition: opacity .55s var(--ease-out), transform .55s var(--ease-out)
4771        }
4772
4773        .convo .bub.in {
4774            opacity: 1;
4775            transform: translateY(0) scale(1)
4776        }
4777
4778        .convo .bub.caller {
4779            align-self: flex-start;
4780            background: rgba(49, 138, 190, .06);
4781            border-color: rgba(49, 138, 190, .25);
4782            color: var(--paper);
4783            border-bottom-left-radius: 4px
4784        }
4785
4786        .convo .bub.agent {
4787            align-self: flex-end;
4788            background: color-mix(in srgb, var(--signal) 6%, transparent);
4789            border-color: color-mix(in srgb, var(--signal) 25%, transparent);
4790            color: var(--paper);
4791            border-bottom-right-radius: 4px
4792        }
4793
4794        .convo .bub .lbl {
4795            font-size: 9px;
4796            color: var(--mute);
4797            text-transform: uppercase;
4798            letter-spacing: .2em;
4799            display: block;
4800            margin-bottom: 6px
4801        }
4802
4803        .convo .bub.caller .lbl {
4804            color: var(--plasma-bright)
4805        }
4806
4807        .convo .bub.agent .lbl {
4808            color: var(--signal)
4809        }
4810
4811        /* Typing indicator inside .convo */
4812        .convo-typing {
4813            align-self: flex-end;
4814            background: color-mix(in srgb, var(--signal) 6%, transparent);
4815            border: 1px solid color-mix(in srgb, var(--signal) 25%, transparent);
4816            border-radius: 14px;
4817            border-bottom-right-radius: 4px;
4818            padding: 14px 18px;
4819            display: none;
4820            align-items: center;
4821            gap: 10px;
4822            opacity: 0;
4823            transition: opacity .25s ease
4824        }
4825
4826        .convo-typing.on {
4827            display: inline-flex;
4828            opacity: 1
4829        }
4830
4831        .convo-typing.caller {
4832            align-self: flex-start;
4833            background: rgba(49, 138, 190, .06);
4834            border-color: rgba(49, 138, 190, .25);
4835            border-bottom-left-radius: 4px;
4836            border-bottom-right-radius: 14px
4837        }
4838
4839        .convo-typing .lbl {
4840            font-size: 9px;
4841            color: var(--signal);
4842            text-transform: uppercase;
4843            letter-spacing: .2em
4844        }
4845
4846        .convo-typing.caller .lbl {
4847            color: var(--plasma-bright)
4848        }
4849
4850        .convo-typing .dotset {
4851            display: inline-flex;
4852            gap: 4px;
4853            align-items: center
4854        }
4855
4856        .convo-typing .dotset i {
4857            width: 6px;
4858            height: 6px;
4859            border-radius: 50%;
4860            background: var(--signal);
4861            opacity: .4;
4862            animation: typingDot 1.2s ease-in-out infinite
4863        }
4864
4865        .convo-typing.caller .dotset i {
4866            background: var(--plasma)
4867        }
4868
4869        .convo-typing .dotset i:nth-child(2) {
4870            animation-delay: .2s
4871        }
4872
4873        .convo-typing .dotset i:nth-child(3) {
4874            animation-delay: .4s
4875        }
4876
4877        /* ====== INTEGRATION LOGOS ROW ====== */
4878        .integrations {
4879            display: grid;
4880            grid-template-columns:repeat(6, 1fr);
4881            gap: 1px;
4882            background: var(--line);
4883            border-top: 1px solid var(--line);
4884            border-bottom: 1px solid var(--line);
4885            overflow: hidden
4886        }
4887
4888        .integrations .ig {
4889            padding: 24px;
4890            background: var(--ink);
4891            display: flex;
4892            align-items: center;
4893            justify-content: center;
4894            font-family: var(--serif);
4895            font-size: 18px;
4896            color: var(--bone);
4897            transition: .25s;
4898            text-align: center
4899        }
4900
4901        .integrations .ig:hover {
4902            background: var(--ink-3);
4903            color: var(--paper)
4904        }
4905
4906        .integrations .ig small {
4907            font-family: var(--mono);
4908            font-size: var(--t-label);
4909            color: var(--mute);
4910            letter-spacing: .14em;
4911            text-transform: uppercase;
4912            display: block;
4913            margin-top: 4px
4914        }
4915
4916        /* ====== PAGE INDICATORS ====== */
4917        .crumb {
4918            font-family: var(--mono);
4919            font-size: 11px;
4920            color: var(--mute);
4921            text-transform: uppercase;
4922            letter-spacing: .18em;
4923            display: flex;
4924            gap: 10px;
4925            align-items: center
4926        }
4927
4928        .crumb a {
4929            color: var(--mute);
4930            transition: .25s
4931        }
4932
4933        .crumb a:hover {
4934            color: var(--signal)
4935        }
4936
4937        /* ====== RESPONSIVE ====== */
4938        @media (max-width: 1100px) {
4939            .hero-shell, .slab, .editorial, .app {
4940                grid-template-columns:1fr;
4941                gap: 48px
4942            }
4943
4944            .metric {
4945                grid-column: span 6
4946            }
4947
4948            .metric.wide {
4949                grid-column: span 12
4950            }
4951
4952            .tiers {
4953                grid-template-columns:1fr
4954            }
4955
4956            .nav ul {
4957                display: none
4958            }
4959
4960            /* Collapsed nav: the Agents menu stops being a floating panel and
4961               becomes an inline accordion inside the stacked menu, opened by
4962               tapping (never by hover, which does not exist on touch). */
4963            .nav-drop {
4964                width: 100%
4965            }
4966
4967            .nav-drop-btn {
4968                width: 100%;
4969                justify-content: flex-start
4970            }
4971
4972            .nav-drop-chev {
4973                margin-left: auto
4974            }
4975
4976            .nav-drop:hover .nav-drop-panel,
4977            .nav-drop:focus-within .nav-drop-panel {
4978                display: none
4979            }
4980
4981            .nav-drop.is-open .nav-drop-panel {
4982                display: grid
4983            }
4984
4985            /* No hover on touch, and the panel is inline here, so the bridge
4986               has nothing to bridge. */
4987            .nav-drop-panel::before {
4988                display: none
4989            }
4990
4991            .nav-drop-panel {
4992                position: static;
4993                min-width: 0;
4994                width: 100%;
4995                grid-template-columns: 1fr;
4996                gap: 14px;
4997                margin: 6px 0 4px;
4998                padding: 12px;
4999                max-height: min(58vh, 460px);
5000                overflow-y: auto;
5001                -webkit-overflow-scrolling: touch;
5002                box-shadow: none;
5003                background: var(--ink-3)
5004            }
5005
5006            .nav ul .nav-drop-panel a {
5007                padding: 10px
5008            }
5009
5010            /* Stacked on mobile, so there is no second column to line up with. */
5011            .nav ul .nav-drop-all {
5012                margin-top: 6px
5013            }
5014
5015            /* Descriptions are noise on a small screen; the labels carry it. */
5016            .nav ul .nav-drop-panel a em {
5017                display: none
5018            }
5019
5020            /* Collapsed nav: the wide signup-plus-number pill gives way to a
5021               compact call button that actually dials (this is a phone), and
5022               the full number stays in the footer. Sign in + CTA keep their
5023               places. */
5024            .nav .actions .num-signup {
5025                display: none
5026            }
5027
5028            .nav .actions .num-call {
5029                display: inline-flex
5030            }
5031
5032            .menu-btn {
5033                display: inline-flex;
5034                align-items: center;
5035                justify-content: center;
5036                width: 38px;
5037                height: 38px;
5038                border: 1px solid var(--line-2);
5039                border-radius: 8px
5040            }
5041
5042            .foot-grid {
5043                grid-template-columns:1fr 1fr;
5044                gap: 32px
5045            }
5046
5047            .steps {
5048                grid-template-columns:1fr
5049            }
5050
5051            .steps::before {
5052                display: none
5053            }
5054
5055            .integrations {
5056                grid-template-columns:repeat(3, 1fr)
5057            }
5058
5059            .form .row {
5060                grid-template-columns:1fr
5061            }
5062
5063            .form .radios {
5064                grid-template-columns:1fr
5065            }
5066        }
5067
5068        @media (max-width: 640px) {
5069            .nav {
5070                grid-template-columns:1fr auto;
5071                gap: 12px;
5072                padding: 14px var(--shell-pad)
5073            }
5074
5075            /* Small phones: also drop Sign in (still in the footer), leaving
5076               toggle + call icon + Start free + menu. The call icon stays: a
5077               phone is the one place the number can actually be rung. */
5078            .nav .actions .num {
5079                display: none
5080            }
5081
5082            .nav .actions .num-call {
5083                display: inline-flex
5084            }
5085
5086            /* Tighter again on a short screen, where the fold is the whole
5087               argument and every pixel above the headline is spent. */
5088            .hero {
5089                padding-top: 96px
5090            }
5091
5092            .hero-meta {
5093                gap: 24px 32px
5094            }
5095
5096            .hero-meta dd {
5097                font-size: 24px
5098            }
5099
5100            .slab-l, .app {
5101                padding: 36px 28px
5102            }
5103
5104            .slab-r {
5105                padding: 48px 0;
5106                min-height: 480px
5107            }
5108
5109            .metric {
5110                grid-column: span 12
5111            }
5112
5113            .foot-grid {
5114                grid-template-columns:1fr
5115            }
5116
5117            .editorial {
5118                gap: 32px
5119            }
5120
5121            .endcta .num-big {
5122                font-size: 32px;
5123                padding: 16px 24px
5124            }
5125
5126            .strip {
5127                font-size: 24px
5128            }
5129
5130            /* Pricing tier cards on phones: tighter padding + smaller price so $
5131        129/mo fits */
5132            .tier {
5133                padding: 28px 22px;
5134                gap: 18px
5135            }
5136
5137            .tier .price {
5138                font-size: 48px
5139            }
5140
5141            .tier .price small {
5142                font-size: 12px
5143            }
5144
5145            .tier .name {
5146                font-size: 10px
5147            }
5148
5149            .tier .desc {
5150                padding-top: 16px
5151            }
5152
5153            .tier ul {
5154                font-size: 13px
5155            }
5156
5157            .tier ul li {
5158                gap: 8px
5159            }
5160
5161            /* Pricing FAQ */
5162            .pricing-faq-grid {
5163                grid-template-columns:1fr !important
5164            }
5165        }
5166    </style>
5167
5168    </head>
5169<body data-page="pricing">
5170<!-- Google Tag Manager (noscript) -->
vendor: 73 bytes, lines 5170-5172
5170
5171<noscript>
5172    <iframe src="https://www.googletagmanager.com/ns.html?id=
5172GTM-TTGHDLQ4
vendor: 97 bytes, lines 5172-5175
5172"
5173            height="0" width="0" style="display:none;visibility:hidden"></iframe>
5174</noscript>
5175
5176<!-- End Google Tag Manager (noscript) -->
5177<div class="grain"></div>
5178<div class="scanlines"></div>
5179<div class="vignette"></div>
5180
5181<nav class="nav">
5182  
5183  <a href="https://talkify.nz" class="logo" aria-label="Talkify, home">
5184    <svg class="tk-logo" viewBox="-3 -3 317.81 106"
5185     width="113.93" height="38"
5186     xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Talkify" focusable="false">
5187            <defs>
5188            <linearGradient id="tkghbFwYU" gradientUnits="userSpaceOnUse" x1="8" y1="92" x2="92" y2="8">
5189                <stop offset="0" stop-color="#318abe"/>
5190                <stop offset="1" stop-color="#a3d654"/>
5191            </linearGradient>
5192        </defs>
5193        <circle cx="50" cy="50" r="50" fill="url(#tkghbFwYU)"/>
5194    
5195    <g fill="none" stroke="#ffffff" stroke-width="10" stroke-linecap="round">
5196        <path d="M34 26 V54 C34 74 62 80 76 62"/>
5197        <path d="M20 40 H46"/>
5198    </g>
5199    
5200    <g transform="translate(56 20) scale(0.30)">
5201        <g class="tk-eye">
5202            <path d="M50 8 Q55.5 39 92 50 Q55.5 61 50 92 Q44.5 61 8 50 Q44.5 39 50 8 Z" fill="#ffffff"/>
5203        </g>
5204    </g>
5205            <path d="M271.37 19.44 L274.1 19.47 L276.98 20.13 L279.56 21.51 L281.93 23.58 L276.86 28.65 L275.24 27.45 L274.04 26.97 L273.32 26.85 L270.62 26.97 L269.6 27.27 L268.28 28.05 L267.23 29.28 L266.57 30.96 L266.39 32.28 L266.39 37.38 L284.84 37.41 L293.66 59.85 L302.99 37.5 L311.81 37.44 L289.55 86.04 L289.34 86.37 L288.98 86.37 L280.61 86.34 L289.25 68.4 L276.89 39.18 L276.8 44.61 L266.39 44.64 L266.36 71.97 L258.47 71.94 L258.47 44.64 L250.19 44.58 L250.19 37.44 L258.44 37.41 L258.47 32.28 L258.71 30 L259.49 27.36 L260.69 25.14 L262.52 23.01 L264.98 21.21 L267.8 20.01 L270.08 19.53ZM190.01 20.16 L197.93 20.16 L197.93 71.94 L190.01 71.94ZM204.53 20.16 L212.45 20.16 L212.48 53.61 L226.46 37.41 L235.85 37.44 L221.33 53.94 L230.24 64.47 L236.57 71.94 L226.52 71.97 L212.48 55.05 L212.45 71.94 L204.53 71.94ZM131.63 23.04 L139.55 23.04 L139.58 37.41 L147.83 37.44 L147.8 44.61 L139.55 44.64 L139.55 71.94 L131.63 71.94 L131.63 44.64 L123.35 44.58 L123.38 37.41 L131.63 37.38ZM164.09 36.72 L167.06 36.81 L170.24 37.59 L171.92 38.37 L173.42 39.33 L175.4 41.19 L175.52 37.41 L183.41 37.44 L183.41 71.94 L175.52 71.97 L175.46 68.25 L174.08 69.57 L172.85 70.44 L170.84 71.55 L169.34 72.09 L167.84 72.45 L165.8 72.69 L163.76 72.69 L161.84 72.45 L159.92 71.97 L158.48 71.43 L156.44 70.35 L154.76 69.15 L152.27 66.66 L150.47 63.96 L149.57 62.04 L148.91 60.06 L148.55 58.5 L148.25 55.86 L148.37 52.2 L148.79 49.86 L149.39 47.88 L149.93 46.56 L151.01 44.58 L152.33 42.72 L153.65 41.28 L156.5 39.03 L158.54 37.95 L159.98 37.41 L161.9 36.93ZM239.21 37.44 L247.13 37.44 L247.13 71.94 L239.21 71.94ZM165.2 44.19 L163.04 44.61 L161.48 45.27 L159.98 46.29 L158.51 47.82 L157.73 49.02 L156.83 51.18 L156.41 53.52 L156.41 55.86 L156.65 57.48 L157.31 59.52 L158.51 61.56 L160.04 63.15 L161.48 64.11 L163.46 64.89 L165.32 65.19 L167.12 65.13 L169.34 64.77 L171.14 63.99 L172.34 63.15 L173.99 61.38 L175.01 59.64 L175.67 57.66 L175.97 55.44 L175.91 53.1 L175.49 51 L174.53 48.78 L173.81 47.7 L172.52 46.35 L170.84 45.21 L169.16 44.55 L167.18 44.19Z" fill="var(--tk-word, #101820)" fill-rule="evenodd"/>
5206        
5207        <g transform="translate(231.30 6.84) scale(0.216)">
5208            <path d="M50 8 Q55.5 39 92 50 Q55.5 61 50 92 Q44.5 61 8 50 Q44.5 39 50 8 Z"
5209                  fill="#a3d654"/>
5210        </g>
5211    </svg>
5212  </a>
5213  <ul>
5214    <li class="nav-drop" data-nav-drop>
5215      <button type="button" class="nav-drop-btn "
5216              aria-expanded="false" aria-controls="nav-agents-menu" aria-haspopup="true">
5217        <span class="dot"></span>Agents
5218        <svg class="nav-drop-chev" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
5219      </button>
5220
5221      
5222      <div class="nav-drop-panel" id="nav-agents-menu">
5223        <div class="nav-drop-col">
5224          <span class="nav-drop-hd">Answering calls</span>
5225          <a href="https://talkify.nz/reception"><span>Reception</span><em>Answers every call, books the job</em></a>
5226          <a href="https://talkify.nz/personal-assistant"><span>Personal Assistant</span><em>Your own PA on the phone</em></a>
5227          <a href="https://talkify.nz/booking-service"><span>Booking Service</span><em>Fills the diary while you work</em></a>
5228          <a href="https://talkify.nz/front-counter"><span>Front Counter</span><em>Orders and bookings on a screen by the till</em></a>
5229          <a href="https://talkify.nz/ai-call-centre"><span>AI Call Centre</span><em>5, 10 or 15 lines at once</em></a>
5230          <span class="nav-drop-hd" style="margin-top:18px">Other channels</span>
5231          <a href="https://talkify.nz/website-chat"><span>Website Chat</span><em>The same agent, in a chat box on your site</em></a>
5232          <a href="https://talkify.nz/calendar"><span>Calendar</span><em>The diary the agent books into</em></a>
5233          <a href="https://talkify.nz/lead-management"><span>Leads</span><em>Every enquiry on one board, whatever door it came through</em></a>
5234                    <a href="https://talkify.nz/agent-coach"><span>Coach</span><em>Your agent listens back to its own calls</em></a>
5235                  </div>
5236        <div class="nav-drop-col">
5237          <span class="nav-drop-hd">Ringing out</span>
5238          <a href="https://talkify.nz/sales-agent"><span>Sales Agent</span><em>Qualifies and follows up leads</em></a>
5239          <a href="https://talkify.nz/outbound-calls"><span>Outbound Calls</span><em>Campaigns, reminders, win-backs</em></a>
5240          <a href="https://talkify.nz/ai-marketing-campaigns"><span>Marketing Campaigns</span><em>Offers, launches and reviews, by phone</em></a>
5241          <a href="https://talkify.nz/ai-phone-surveys"><span>Campaign Agent</span><em>Rings your list, asks your questions, reports back</em></a>
5242          <a href="https://talkify.nz/debt-collection"><span>Debt Collection</span><em>Chases overdue invoices from Xero</em></a>
5243          <a href="https://talkify.nz/ai-wellness-checks"><span>Wellness Checks</span><em>Rings to check somebody is alright</em></a>
5244          
5245          <a href="https://talkify.nz/dialler"><span>Dialler</span><em>Your own team ringing out, from the browser</em></a>
5246          <a href="https://talkify.nz/agents" class="nav-drop-all">See all agents <span class="arr">&rarr;</span></a>
5247        </div>
5248      </div>
5249    </li>
5250    
5251    <li class="nav-drop" data-nav-drop>
5252      <button type="button" class="nav-drop-btn "
5253              aria-expanded="false" aria-controls="nav-industries-menu" aria-haspopup="true">
5254        <span class="dot"></span>Industries
5255        <svg class="nav-drop-chev" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
5256      </button>
5257
5258      
5259      <div class="nav-drop-panel nav-drop-panel--industries" id="nav-industries-menu">
5260        <div class="nav-drop-col">
5261          <span class="nav-drop-hd">Trades</span>
5262          <a href="https://talkify.nz/tradesman">All Trades</a>
5263          <a href="https://talkify.nz/builder">Builders</a>
5264          <a href="https://talkify.nz/electrician">Electricians</a>
5265          <a href="https://talkify.nz/hvac">Heat Pump &amp; HVAC</a>
5266          <a href="https://talkify.nz/landscaping">Landscaping</a>
5267          <a href="https://talkify.nz/automotive">Mechanics</a>
5268          <a href="https://talkify.nz/pest-control">Pest Control</a>
5269          <a href="https://talkify.nz/plumber">Plumbing</a>
5270        </div>
5271        <div class="nav-drop-col">
5272          <span class="nav-drop-hd">Health &amp; beauty</span>
5273          <a href="https://talkify.nz/barber">Barbers</a>
5274          <a href="https://talkify.nz/beauty">Beauty &amp; Wellness</a>
5275          <a href="https://talkify.nz/gym">Gyms &amp; Studios</a>
5276          <a href="https://talkify.nz/personal-trainer">Personal Trainers</a>
5277          <a href="https://talkify.nz/physio">Physio &amp; Clinics</a>
5278          <span class="nav-drop-hd" style="margin-top:18px">Office &amp; property</span>
5279          <a href="https://talkify.nz/accountant">Accountants</a>
5280          <a href="https://talkify.nz/professional-services">Professional Services</a>
5281          <a href="https://talkify.nz/real-estate">Real Estate</a>
5282          <a href="https://talkify.nz/retail">Retail</a>
5283        </div>
5284        <div class="nav-drop-col">
5285          <span class="nav-drop-hd">Food &amp; hospitality</span>
5286          <a href="https://talkify.nz/cafe">Cafes</a>
5287          <a href="https://talkify.nz/chinese-takeaway">Chinese Takeaways</a>
5288          <a href="https://talkify.nz/fish-and-chip-shop">Fish &amp; Chip Shops</a>
5289          <a href="https://talkify.nz/hotel">Hotels &amp; Motels</a>
5290          <a href="https://talkify.nz/pizza-shop">Pizza Shops</a>
5291          <a href="https://talkify.nz/restaurant-bookings">Restaurants</a>
5292          <a href="https://talkify.nz/industries" class="nav-drop-all">See all industries <span class="arr">&rarr;</span></a>
5293        </div>
5294      </div>
5295    </li>
5296    <li class="nav-drop" data-nav-drop>
5297      <button type="button" class="nav-drop-btn "
5298              aria-expanded="false" aria-controls="nav-integrations-menu" aria-haspopup="true">
5299        <span class="dot"></span>Integrations
5300        <svg class="nav-drop-chev" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
5301      </button>
5302
5303      <div class="nav-drop-panel nav-drop-panel--single" id="nav-integrations-menu">
5304        <div class="nav-drop-col">
5305          <span class="nav-drop-hd">Plugs into</span>
5306          <a href="https://talkify.nz/integrations"><span>All integrations</span><em>The software the agent already talks to</em></a>
5307          <a href="https://talkify.nz/business-phone-lines"><span>Phone Lines</span><em>Numbers, porting and how calls reach us</em></a>
5308        </div>
5309      </div>
5310    </li>
5311    <li><a href="https://talkify.nz/pricing" class="is-active"><span class="dot"></span>Pricing</a></li>
5312    <li><a href="https://talkify.nz/blog" class=""><span class="dot"></span>Journal</a></li>
5313        <li><a href="https://talkify.nz/signup" class=""><span class="dot"></span>Get started</a></li>
5314      </ul>
5315  <div class="actions">
5316    <button type="button" class="theme-toggle" data-theme-toggle aria-label="Switch between light and dark theme" title="Switch theme">
5317      <svg class="icon-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
5318      <svg class="icon-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
5319    </button>
5320            
5321        <a href="https://talkify.nz/signup" class="num num-signup" title="Sign up online, or ring 0800 002 967">Sign up · <b>0800 002 967</b></a>
5322        <a href="tel:+64800002967" class="num num-call" title="Call us on 0800 002 967" aria-label="Call us on 0800 002 967">
5323      <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 16.92z"/></svg>
5324    </a>
5325              <a href="https://talkify.nz/login" class="num" style="font-family:var(--sans);font-size:13px;color:var(--bone)">Sign in</a>
5326      <a href="https://talkify.nz/signup" class="btn btn-primary">Start free <span class="arr">→</span></a>
5327        <button class="menu-btn" aria-label="Open menu">
5328      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
5329    </button>
5330  </div>
5331</nav>
5332
5333    <section class="hero" style="padding-bottom:48px">
5334        <div class="hero-bg">
5335            <div class="glow1"></div>
5336            <div class="glow2"></div>
5337            <div class="grid-lines"></div>
5338        </div>
5339        
5340        <div class="hero-shell">
5341            <div>
5342                <div class="crumb"><a href="https://talkify.nz">Talkify</a> <span>/</span> <span
5343                        style="color:var(--paper)">Pricing</span></div>
5344                <span class="eyebrow" style="margin-top:18px"><span class="pin"></span>Founding rates ·  No surprises · Cancel anytime</span>
5345                <h1 class="display" style="font-size:clamp(60px,9vw,128px);max-width:20ch">
5346                    <span class="ln"><span>One agent.</span></span>
5347                    <span class="ln"><span class="it">Four ways to pay.</span></span>
5348                </h1>
5349                <p class="hero-sub" style="max-width:680px">From as little as
5350                    $10 a month* plus
5351                    $1 a minute on pay as you go, or a flat monthly plan with
5352                    minutes included. No per-seat fees, no setup tax, no lock-in, and every plan keeps every
5353                    transcript forever.</p>
5354
5355                <div class="founding-note">
5356                                            <span class="fn-tag">Founding rate</span>
5357                        <span class="fn-txt">On the monthly plans, your <b>first 3 months</b> are locked in at
5358                            the founding price below; standard pricing applies after that. Pay as you go has no
5359                            founding step. No setup fee, cancel any
5360                            time. Wondering how this stacks up? <a href="https://talkify.nz/compare" style="color:var(--brand-blue-bright);text-decoration:underline">See every NZ provider compared</a>, or read <a href="https://talkify.nz/ai-answering-service#cost" style="color:var(--brand-blue-bright);text-decoration:underline">what a phone answering service costs in NZ</a>.</span>
5361                                    </div>
5362            </div>
5363
5364            <div class="pricing-hero-figures r r-1">
5365                <a class="ruled-figure" href="#tiers">
5366                    <span class="lbl">Pay as you go</span>
5367                    <span class="big">$10<small> /mo*</small></span>
5368                    <span class="fig-note">* Covers your phone number, plus $1 a minute as you use it. $10 free credit to start.</span>
5369                </a>
5370                <a class="ruled-figure" href="#tiers">
5371                    <span class="lbl">Personal Assistant</span>
5372                    <span class="big">$89<small> /mo</small></span>
5373                    <span class="fig-note">One person's own mobile or landline. 50 minutes.</span>
5374                </a>
5375                <a class="ruled-figure is-pick" href="#tiers">
5376                    <span class="lbl">Broadcast · most common</span>
5377                    <span class="big">$129<small> /mo</small></span>
5378                    <span class="fig-note">Your business number, answered. Up to 3 agents on it, 200 minutes, 3 calls at once.</span>
5379                </a>
5380                <a class="ruled-figure" href="https://talkify.nz/contact">
5381                    <span class="lbl">Fleet</span>
5382                    <span class="big">Custom</span>
5383                    <span class="fig-note">Multi-location and contact centres. Quoted per account.</span>
5384                </a>
5385            </div>
5386        </div>
5387    </section>
5388
5389    
5390    <section class="shell tight" style="padding-top:0" id="service-map">
5391        <div class="section-hd">
5392            <h2 class="r">Which agent on <span class="it">which plan.</span></h2>
5393            <p class="lede r r-1">Priced by the phone number, not by the seat and not by the agent. Every number
5394                comes with up to three agents on it (reception, bookings, sales) and three simultaneous calls.
5395                Most businesses start with one number.</p>
5396        </div>
5397
5398        <div class="svc-band r"><span>Answering your phone.</span></div>
5399
5400        <div class="svc-plate r">
5401            <div class="svc">
5402                <div class="svc-head">
5403                    <span class="svc-name">Reception &amp; Sales</span>
5404                    <span class="svc-price"><s class="svc-was">$199</s>$129<small>/mo</small></span>
5405                </div>
5406                <p class="svc-founding">Founding rate for your first 3 months, then $199/mo.</p>                <p class="svc-desc">24/7 reception for your business number plus inbound sales qualification with CRM
5407                    sync, bundled on the Broadcast plan. One price per number, with up to three agents on it.
5408                    The most common pick.</p>
5409                <p class="svc-aster">* Sales Agent is subject to your CRM. Non-standard CRMs may carry an
5410                    implementation cost.</p>
5411                <div class="svc-tier">Broadcast · per number · 200 min a month</div>
5412            </div>
5413
5414            <div class="svc">
5415                <div class="svc-head">
5416                    <span class="svc-name">Personal Assistant</span>
5417                    <span class="svc-price">$89<small>/mo</small></span>
5418                </div>
5419                                <p class="svc-desc">One person, one mobile or landline. Screens your calls, takes detailed messages and
5420                    books your meetings. Personal use, not a business switchboard.</p>
5421                <div class="svc-tier">Shortwave · 50 min a month</div>
5422            </div>
5423
5424            <div class="svc">
5425                <div class="svc-head">
5426                    <span class="svc-name">AI Call Centre</span>
5427                    <span class="svc-price"><small style="margin-right:4px">from</small>$399<small>/mo</small></span>
5428                </div>
5429                <p class="svc-desc">For phone volume: 5, 10 or 15 calls answered at the same instant, no queue and no
5430                    hold music. $399, $599 or
5431                    $799 a month.
5432                    <a href="https://talkify.nz/ai-call-centre" class="svc-link">How it works</a>.</p>
5433                <div class="svc-tier">Answers and dials · by simultaneous lines</div>
5434            </div>
5435
5436            <div class="svc">
5437                <div class="svc-head">
5438                    <span class="svc-name">Website Chat</span>
5439                    <span class="svc-price">$49<small>/mo</small></span>
5440                </div>
5441                <p class="svc-desc">Your agent on your website: a white-labelled text and voice widget trained on the
5442                    same knowledge as your phone agent. $39 alongside any
5443                    Talkify agent. <a href="https://talkify.nz/website-chat" class="svc-link">See it in action</a>.</p>
5444                <div class="svc-tier">Per website</div>
5445            </div>
5446        </div>
5447
5448        <div class="svc-band r"><span>Making calls for you.</span></div>
5449
5450        <div class="svc-plate r">
5451            <div class="svc">
5452                <div class="svc-head">
5453                    <span class="svc-name">Outgoing campaigns</span>
5454                    <span class="svc-price">$59<small>/mo</small></span>
5455                </div>
5456                <p class="svc-desc">Campaigns from a list you load: reminders, win-backs, follow-ups on quotes that went
5457                    quiet. 20 minutes included each month you run a campaign,
5458                    then 50c a minute. One-off calls your agent makes outside a campaign
5459                    (booking confirmations, notifications) are just 50c a minute with no
5460                    monthly fee. <a href="https://talkify.nz/outboun
5460d-calls" class="svc-link">How campaigns run</a>.</p>
5461                <div class="svc-tier">Per month, in months you campaign</div>
5462            </div>
5463
5464            
5465            <div class="svc">
5466                <div class="svc-head">
5467                    <span class="svc-name">AI Call Centre</span>
5468                    <span class="svc-price"><small style="margin-right:4px">from</small>$399<small>/mo</small></span>
5469                </div>
5470                <p class="svc-desc">The same bank of lines, dialling out: 5, 10 or 15 calls running at once through a
5471                    list instead of waiting on one. One subscription covers both directions, so lines sized for your
5472                    busiest hour on the phone are yours for campaigns the rest of the day.
5473                    50c a minute on top.
5474                    <a href="https://talkify.nz/ai-call-centre" class="svc-link">How it works</a>.</p>
5475                <div class="svc-tier">Answers and dials · by simultaneous lines</div>
5476            </div>
5477
5478            <div class="svc">
5479                <div class="svc-head">
5480                    <span class="svc-name">Invoice chase-up</span>
5481                    <span class="svc-price">$10<small>/mo</small></span>
5482                </div>
5483                <p class="svc-desc">Connects your Xero, rings the overdue accounts politely, writes what they promised
5484                    back onto the invoice and emails your accounts team anything that needs a person.
5485                    50c a minute on top. <a href="https://talkify.nz/debt-collection" class="svc-link">What it says</a>.</p>
5486                <div class="svc-tier">Xero add-on</div>
5487            </div>
5488
5489            <div class="svc">
5490                <div class="svc-head">
5491                    <span class="svc-name">Marketing Campaigns</span>
5492                    <span class="svc-price">$59<small>/mo</small></span>
5493                </div>
5494                <p class="svc-desc">Rings your own customer base with promotions, win-backs, launches, review requests
5495                    and phone surveys, and hands you the results as people, not statistics. Same plan as outgoing
5496                    campaigns: 20 minutes included, then
5497                    50c a minute.
5498                    <a href="https://talkify.nz/ai-marketing-campaigns" class="svc-link">See the campaigns</a>.</p>
5499                <div class="svc-tier">Part of Outgoing campaigns</div>
5500            </div>
5501
5502        </div>
5503
5504        
5505        <div class="svc-foot r">
5506            <div>
5507                <h3>Custom Setup <span class="svc-foot-price">from $499</span></h3>
5508                <p>Custom API integration into your booking system, CRM or in-house software, built and maintained by
5509                    us. Includes the integration work and a dedicated onboarding, on a 12-month contract. The quote
5510                    depends on the systems involved.</p>
5511            </div>
5512                        <a href="tel:+64800002967" class="btn btn-ghost">Talk to us on 0800 002 967 <span class="arr">&rarr;</span></a>
5513                    </div>
5514
5515        <style>
5516            /* Same ruled-plate language as the industry index and the agent
5517               pages: one bordered plate per direction, cells ruled off each
5518               other by the 1px grid gap rather than floating as separate cards. */
5519            .svc-band {
5520                display: flex;
5521                align-items: center;
5522                gap: 20px;
5523                margin: 0 0 20px
5524            }
5525
5526            .svc-plate + .svc-band {
5527                margin-top: 44px
5528            }
5529
5530            .svc-band span {
5531                font-weight:600;
5532                font-size: 19px;
5533                color: var(--mute);
5534                flex: 0 0 auto
5535            }
5536
5537            .svc-band::after {
5538                content: "";
5539                flex: 1;
5540                height: 1px;
5541                background: var(--line)
5542            }
5543
5544            .svc-foot {
5545                display: flex;
5546                align-items: center;
5547                justify-content: space-between;
5548                flex-wrap: wrap;
5549                gap: 18px 36px;
5550                margin-top: 28px;
5551                padding: 0 4px
5552            }
5553
5554            .svc-foot > div {
5555                max-width: 68ch;
5556                display: flex;
5557                flex-direction: column;
5558                gap: 8px
5559            }
5560
5561            .svc-foot h3 {
5562                font-family: var(--serif);
5563                font-weight: 300;
5564                font-size: 24px;
5565                letter-spacing: -.015em;
5566                color: var(--paper);
5567                margin: 0;
5568                display: flex;
5569                align-items: baseline;
5570                gap: 12px;
5571                flex-wrap: wrap
5572            }
5573
5574            .svc-foot-price {
5575                font-family: var(--mono);
5576                font-size: 12px;
5577                letter-spacing: .06em;
5578                color: var(--mute)
5579            }
5580
5581            .svc-foot p {
5582                font-size: 14.5px;
5583                line-height: 1.6;
5584                color: var(--mute);
5585                margin: 0
5586            }
5587
5588            /* V2 design language, same as the capability plate: top-ruled
5589               columns rather than cells inside a filled, rounded plate. */
5590            .svc-plate {
5591                display: grid;
5592                grid-template-columns:repeat(4, 1fr);
5593                gap: clamp(20px, 2.6vw, 36px)
5594            }
5595
5596            .svc {
5597                position: relative;
5598                border-top: 1px solid var(--line-2);
5599                padding: 28px 0 0;
5600                display: flex;
5601                flex-direction: column;
5602                gap: 12px;
5603                transition: background .35s var(--ease)
5604            }
5605
5606            .svc:hover {
5607                background: var(--ink-3)
5608            }
5609
5610            .svc::before {
5611                content: "";
5612                position: absolute;
5613                top: 0;
5614                left: 0;
5615                right: 0;
5616                height: 2px;
5617                background: var(--grad);
5618                transform: scaleX(0);
5619                transform-origin: left;
5620                transition: transform .55s var(--ease-out)
5621            }
5622
5623            .svc:hover::before {
5624                transform: scaleX(1)
5625            }
5626
5627            .svc-head {
5628                display: flex;
5629                justify-content: space-between;
5630                align-items: baseline;
5631                gap: 14px;
5632                flex-wrap: wrap
5633            }
5634
5635            .svc-name {
5636                font-family: var(--serif);
5637                font-weight: 400;
5638                font-size: 21px;
5639                letter-spacing: -.012em;
5640                line-height: 1.14
5641            }
5642
5643            .svc-price {
5644                font-family: var(--mono);
5645                font-size: 19px;
5646                color: var(--paper);
5647                white-space: nowrap
5648            }
5649
5650            .svc-price small {
5651                font-size: 11px;
5652                color: var(--mute)
5653            }
5654
5655            .svc-was {
5656                color: var(--mute-2);
5657                margin-right: 6px;
5658                font-size: 14px
5659            }
5660
5661            .svc-founding {
5662                font-family: var(--mono);
5663                font-size: 10.5px;
5664                letter-spacing: .12em;
5665                text-transform: uppercase;
5666                color: var(--signal)
5667            }
5668
5669            .svc-desc {
5670                color: var(--bone);
5671                font-size: 13.5px;
5672                line-height: 1.58;
5673                flex: 1
5674            }
5675
5676            .svc-link {
5677                color: var(--plasma-bright);
5678                text-decoration: underline
5679            }
5680
5681            .svc-tier {
5682                font-family: var(--mono);
5683                font-size: 10.5px;
5684                letter-spacing: .14em;
5685                text-transform: uppercase;
5686                color: var(--mute);
5687                padding-top: 12px;
5688                border-top: 1px solid var(--line)
5689            }
5690
5691            .svc-aster {
5692                font-size: 11.5px;
5693                line-height: 1.5;
5694                color: var(--mute-2)
5695            }
5696
5697            @media (max-width: 1180px) {
5698                .svc-plate {
5699                    grid-template-columns:repeat(2, 1fr)
5700                }
5701            }
5702
5703            @media (max-width: 620px) {
5704                .svc-plate {
5705                    grid-template-columns:1fr
5706                }
5707            }
5708
5709            @media (prefers-reduced-motion: reduce) {
5710                .svc, .svc::before {
5711                    transition: none
5712                }
5713            }
5714        </style>
5715    </section>
5716
5717    <section class="shell tight" style="padding-top:0" id="tiers">
5718        <div class="section-hd">
5719            <h2 class="r">Or pick by <span class="it">plan tier.</span></h2>
5720            <p class="lede r r-1">Same pricing, different lens. Useful if you already know what minutes and concurrency
5721                you need.</p>
5722        </div>
5723        
5724        <style>
5725            /* The id outranks the layout's own .tiers rules, so every width
5726               is restated here rather than half-inherited. */
5727            #tiers .tiers { grid-template-columns: repeat(4, 1fr); }
5728            @media (max-width: 1100px) {
5729                #tiers .tiers { grid-template-columns: repeat(2, 1fr); }
5730            }
5731            @media (max-width: 700px) {
5732                #tiers .tiers { grid-template-columns: 1fr; }
5733            }
5734        </style>
5735        <div class="tiers">
5736            <div class="tier r">
5737                <div class="row1"><span class="name">SHORTWAVE · PERSONAL</span></div>
5738                <div class="price">$89<small>/mo</small></div>
5739                                <p class="desc">A personal assistant for one person's own mobile or landline. Personal use, not a
5740                    business line, businesses start on Broadcast.</p>
5741                <ul>
5742                    <li>
5743                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5744                            <path d="M5 12l5 5L20 7"/>
5745                        </svg>
5746                        50 minutes / month
5747                    </li>
5748                    <li>
5749                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5750                            <path d="M5 12l5 5L20 7"/>
5751                        </svg>
5752                        1 agent · 1 number
5753                    </li>
5754                    <li>
5755                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5756                            <path d="M5 12l5 5L20 7"/>
5757                        </svg>
5758                        Email + SMS summaries
5759                    </li>
5760                    <li>
5761                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5762                            <path d="M5 12l5 5L20 7"/>
5763                        </svg>
5764                        Calendar bookings
5765                    </li>
5766                    <li>
5767                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5768                            <path d="M5 12l5 5L20 7"/>
5769                        </svg>
5770                        Mobile app · iOS &amp; Android
5771                    </li>
5772                    <li>
5773                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5774                            <path d="M5 12l5 5L20 7"/>
5775                        </svg>
5776                        Full transcripts &amp; recordings
5777                    </li>
5778                </ul>
5779                <a href="https://talkify.nz/contact?plan=shortwave" class="btn btn-ghost cta">Choose Shortwave <span
5780                        class="arr">→</span></a>
5781            </div>
5782            <div class="tier featured r r-1">
5783                <div class="row1"><span class="name">BROADCAST</span><span class="badge">Most popular</span></div>
5784                <div class="price"><s class="svc-was">$199</s>$129<small>/mo per number</small></div>
5785                <p class="tier-founding">Founding rate for your first 3 months, then $199/mo.</p>                <p class="desc">Growing teams. The complete phone agent suite plus the mobile app, CRM sync and
5786                    3 concurrent lines.</p>
5787                <ul>
5788                    <li>
5789                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5790                            <path d="M5 12l5 5L20 7"/>
5791                        </svg>
5792                        Up to 3 agents on your number · $39/mo each after
5793                    </li>
5794                    <li>
5795                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5796                            <path d="M5 12l5 5L20 7"/>
5797                        </svg>
5798                        200 minutes + 50 texts / month
5799                    </li>
5800                    <li>
5801                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5802                            <path d="M5 12l5 5L20 7"/>
5803                        </svg>
5804                        Or <a href="#annual">$1,990 a year</a> and two months are free
5805                    </li>
5806                    <li>
5807                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5808                            <path d="M5 12l5 5L20 7"/>
5809                        </svg>
5810                        3 concurrent calls
5811                    </li>
5812                    <li>
5813                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5814                            <path d="M5 12l5 5L20 7"/>
5815                        </svg>
5816                        Mobile app · view your transcriptions
5817                    </li>
5818                    <li>
5819                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5820                            <path d="M5 12l5 5L20 7"/>
5821                        </svg>
5822                        CRM &amp; calendar integrations
5823                    </li>
5824                    <li>
5825                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5826                            <path d="M5 12l5 5L20 7"/>
5827                        </svg>
5828                        Multi-lingual · 32 languages
5829                    </li>
5830                    <li>
5831                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5832                            <path d="M5 12l5 5L20 7"/>
5833                        </svg>
5834                        A dedicated NZ / Aus Phone Number
5835                    </li>
5836                </ul>
5837                <a href="https://talkify.nz/contact?plan=broadcast" class="btn btn-primary cta">Start broadcasting <span
5838                        class="arr">→</span></a>
5839            </div>
5840            <div class="tier r r-2">
5841                <div class="row1"><span class="name">
5841PAY AS YOU GO</span></div>
5842                <div class="price">$1<small>/minute</small></div>
5843                <p class="desc">No monthly plan. A prepaid balance that calls and texts draw down, topped up
5844                    automatically from your card. Start with $10 of free credit. Cancel anytime.</p>
5845                <ul>
5846                    <li>
5847                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5848                            <path d="M5 12l5 5L20 7"/>
5849                        </svg>
5850                        $1/min incoming &amp; outgoing
5851                    </li>
5852                    <li>
5853                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5854                            <path d="M5 12l5 5L20 7"/>
5855                        </svg>
5856                        $10 free credit to start
5857                    </li>
5858                    <li>
5859                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5860                            <path d="M5 12l5 5L20 7"/>
5861                        </svg>
5862                        $10/month covers your NZ or Aussie landline number
5863                    </li>
5864                    <li>
5865                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5866                            <path d="M5 12l5 5L20 7"/>
5867                        </svg>
5868                        Texts at 15c each, no allowances
5869                    </li>
5870                    <li>
5871                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5872                            <path d="M5 12l5 5L20 7"/>
5873                        </svg>
5874                        Tops up $20 at a time, automatically
5875                    </li>
5876                </ul>
5877                <a href="https://talkify.nz/contact?plan=payg" class="btn btn-ghost cta">Go pay as you go <span
5878                        class="arr">→</span></a>
5879            </div>
5880            <div class="tier r r-2">
5881                <div class="row1"><span class="name">FLEET</span></div>
5882                <div class="price">Custom</div>
5883                <p class="desc">Multi-location operators, franchises and contact centres. SLA-backed, dedicated infra,
5884                    custom voices and white-glove onboarding.</p>
5885                <ul>
5886                    <li>
5887                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5888                            <path d="M5 12l5 5L20 7"/>
5889                        </svg>
5890                        Unlimited minutes
5891                    </li>
5892                    <li>
5893                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5894                            <path d="M5 12l5 5L20 7"/>
5895                        </svg>
5896                        Multi-tenant dashboard
5897                    </li>
5898                    <li>
5899                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5900                            <path d="M5 12l5 5L20 7"/>
5901                        </svg>
5902                        Dedicated voice clone
5903                    </li>
5904                    <li>
5905                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5906                            <path d="M5 12l5 5L20 7"/>
5907                        </svg>
5908                        Custom integrations · MCP tools
5909                    </li>
5910                    <li>
5911                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5912                            <path d="M5 12l5 5L20 7"/>
5913                        </svg>
5914                        99.95% SLA · NZ data residency
5915                    </li>
5916                    <li>
5917                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
5918                            <path d="M5 12l5 5L20 7"/>
5919                        </svg>
5920                        Dedicated success manager
5921                    </li>
5922                </ul>
5923                <a href="https://talkify.nz/contact?plan=fleet" class="btn btn-ghost cta">Talk to the team <span
5924                        class="arr">→</span></a>
5925            </div>
5926        </div>
5927    </section>
5928
5929    
5930        <section class="shell tight" style="padding-top:0" id="annual">
5931        <div class="annual-band">
5932            <div class="annual-copy">
5933                <h2 class="annual-h">Pay for the year and 2 months are free</h2>
5934                <p class="annual-lead">An annual licence for a Broadcast number is
5935                    <b>$1,990 + GST</b>, paid once. The same
5936                    number month by month comes to <b>$2,388</b>,
5937                    so you keep <b>$398</b> and deal with
5938                    one payment a year instead of twelve.</p>
5939                <p class="annual-note">Everything else is exactly the same. Your number still includes up to
5940                    3 agents, 200 minutes and
5941                    50 texts a month, and anything over that is charged at the
5942                    usual rates in the month you use it. The allowance is monthly, not a pool you can spend
5943                    early. If you are still on your founding rate, stay on it until it ends: it is cheaper than
5944                    the licence and we will tell you so rather than sell you this.</p>
5945                <a href="https://talkify.nz/contact?plan=annual" class="btn btn-primary cta">Ask about an annual
5946                    licence <span class="arr">→</span></a>
5947            </div>
5948            <div class="annual-figure">
5949                <span class="annual-was">$2,388</span>
5950                <span class="annual-now">$1,990</span>
5951                <span class="annual-unit">+ GST, per number, per year</span>
5952            </div>
5953        </div>
5954        <style>
5955            .annual-band {
5956                display: grid;
5957                grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
5958                gap: 2rem;
5959                align-items: center;
5960                padding: 2rem;
5961                border: 1px solid var(--rule, rgba(0, 0, 0, .12));
5962            }
5963            .annual-h { margin: 0 0 .75rem; }
5964            .annual-lead { margin: 0 0 1rem; }
5965            .annual-note { margin: 0 0 1.5rem; font-size: .92rem; opacity: .78; }
5966            .annual-figure { text-align: right; }
5967            .annual-was {
5968                display: block;
5969                text-decoration: line-through;
5970                opacity: .55;
5971                font-size: 1.1rem;
5972            }
5973            .annual-now {
5974                display: block;
5975                font-size: clamp(2.4rem, 6vw, 3.4rem);
5976                font-weight: 800;
5977                line-height: 1.05;
5978            }
5979            .annual-unit { display: block; font-size: .85rem; opacity: .7; }
5980            @media (max-width: 760px) {
5981                .annual-band { grid-template-columns: 1fr; padding: 1.5rem; }
5982                .annual-figure { text-align: left; }
5983            }
5984        </style>
5985    </section>
5986
5987    <section class="shell tight" style="padding-top:0">
5988                <div class="usage-strip r">
5989            <div class="us-col">
5990                <span class="us-h">Your minutes</span>
5991                <p>Shortwave includes 50 minutes a month, Broadcast 200 per number. Go over and extra minutes are just
5992                    <b>10c</b> for your first 3 months, then 20c (Shortwave stays at 10c). Fleet is unlimited.</p>
5993            </div>
5994            <div class="us-col">
5995                <span class="us-h">Your texts</span>
5996                <p>Every Broadcast number includes <b>50 texts</b> a month, and Shortwave includes
5997                    <b>20</b>. After that it's a flat
5998                    <b>9c</b> a message. Summaries, confirmations, follow-ups, all counted the same.</p>
5999            </div>
6000            <div class="us-col">
6001                <span class="us-h">Outgoing calls</span>
6002                <p>Running campaigns (surveys, reminder rounds, win-backs) is <b>$59 a month</b> in the months
6003                    you run them, with 20 minutes included, then
6004                    <b>50c per minute</b> rounded up to the next minute. Ring more and it comes down:
6005                    40c a minute from 200 calls a month, and 35c a minute from 500 calls a month, counted across all your campaigns and backdated over the whole
6006                    month. One-off calls outside a campaign are just 50c a minute, no fee.</p>
6007            </div>
6008            <div class="us-col">
6009                <span class="us-h">No bill shock</span>
6010                <p>We let you know as you near your allowance, so nothing creeps up on you. You are never charged
6011                    for usage without warning, and there is no lock-in.</p>
6012            </div>
6013        </div>
6014
6015        <style>
6016            .usage-strip {
6017                display: grid;
6018                grid-template-columns:repeat(4, 1fr);
6019                gap: 18px
6020            }
6021
6022            @media (max-width: 1180px) {
6023                .usage-strip {
6024                    grid-template-columns:repeat(2, 1fr)
6025                }
6026            }
6027
6028            .us-col {
6029                border-top: 1px solid var(--line-2);
6030                padding: 28px 0 0
6031            }
6032
6033            .us-h {
6034                font-family: var(--mono);
6035                font-size: 10px;
6036                letter-spacing: .16em;
6037                text-transform: uppercase;
6038                color: var(--signal);
6039                display: block;
6040                margin-bottom: 12px
6041            }
6042
6043            .us-col p {
6044                color: var(--bone);
6045                font-size: 14px;
6046                line-height: 1.6;
6047                margin: 0
6048            }
6049
6050            .us-col p b {
6051                color: var(--paper);
6052                font-weight: 600
6053            }
6054
6055            @media (max-width: 860px) {
6056                .usage-strip {
6057                    grid-template-columns:1fr
6058                }
6059            }
6060        </style>
6061    </section>
6062
6063    <section class="shell tight" id="calculator">
6064  <div class="section-hd">
6065    <h2 class="r">Build it <span class="it">your way.</span></h2>
6066    <p class="lede r r-1">Slide for the number of agents you would run on your number (the plan includes up to 3), pick the integrations you'd connect, and see live what your monthly looks like. Most businesses start with one. No sign-up needed.</p>
6067  </div>
6068
6069  <div class="r calc-grid" data-calc-grid>
6070    <div class="calc-controls">
6071      <div class="calc-row-head">
6072        <span class="eyebrow"><span class="pin"></span>How many agents</span>
6073        <span class="mono calc-row-val"><span data-calc-team>1</span> agents</span>
6074      </div>
6075      <input type="range" data-calc-range min="1" max="20" value="1" class="calc-range">
6076
6077      <div class="calc-row-head" style="margin-top:32px">
6078        <span class="eyebrow eb-blue"><span class="pin"></span>Integrations</span>
6079        <span class="mono calc-row-val"><span data-calc-ints>0</span> selected</span>
6080      </div>
6081
6082      <div data-calc-pills class="calc-pills">
6083                  <button type="button" class="int-pill" data-int="Google Calendar">Google Calendar</button>
6084                  <button type="button" class="int-pill" data-int="Microsoft Outlook">Microsoft Outlook</button>
6085                  <button type="button" class="int-pill" data-int="Calendly">Calendly</button>
6086                  <button type="button" class="int-pill" data-int="Zenoti">Zenoti</button>
6087                  <button type="button" class="int-pill" data-int="GymMaster">GymMaster</button>
6088                  <button type="button" class="int-pill" data-int="Cliniko">Cliniko</button>
6089                  <button type="button" class="int-pill" data-int="MechanicDesk">MechanicDesk</button>
6090                  <button type="button" class="int-pill" data-int="Workshop Software">Workshop Software</button>
6091                  <button type="button" class="int-pill" data-int="HubSpot">HubSpot</button>
6092                  <button type="button" class="int-pill" data-int="GoHighLevel">GoHighLevel</button>
6093                  <button type="button" class="int-pill" data-int="Pipedrive">Pipedrive</button>
6094                  <button type="button" class="int-pill" data-int="Xero">Xero</button>
6095                  <button type="button" class="int-pill" data-int="MYOB">MYOB</button>
6096                  <button type="button" class="int-pill" data-int="Trello">Trello</button>
6097                  <button type="button" class="int-pill" data-int="iTrade">iTrade</button>
6098                  <button type="button" class="int-pill" data-int="Tradify">Tradify</button>
6099                  <button type="button" class="int-pill" data-int="Slack">Slack</button>
6100                  <button type="button" class="int-pill" data-int="Microsoft Teams">Microsoft Teams</button>
6101                  <button type="button" class="int-pill" data-int="Zapier">Zapier</button>
6102                  <button type="button" class="int-pill" data-int="REST API &amp; webhooks">REST API &amp; webhooks</button>
6103                  <button type="button" class="int-pill" data-int="Custom MCP">Custom MCP</button>
6104              </div>
6105    </div>
6106
6107    <div class="calc-output">
6108      <span class="eyebrow"><span class="pin"></span>Your plan</span>
6109      <div class="calc-founding" data-calc-founding >
6110        <s class="calc-was" data-calc-was>$199/mo</s>
6111        <span class="calc-ftag">Founding rate · 3 months</span>
6112      </div>
6113      <div class="calc-price-row">
6114        <div class="calc-price-num" data-calc-price>$129</div>
6115        <div class="calc-price-suffix">/mo</div>
6116      </div>
6117      <div class="calc-stats">
6118        <div><div class="mono calc-stat-label">Plan</div><div class="calc-stat-val" data-calc-plan>Broadcast</div></div>
6119        <div><div class="mono calc-stat-label">Minutes</div><div class="calc-stat-val" data-calc-mins>200/mo</div></div>
6120        <div><div class="mono calc-stat-label">At once</div><div class="calc-stat-val" data-calc-conc>3 calls</div></div>
6121        <div><div class="mono calc-stat-label">Numbers</div><div class="calc-stat-val" data-calc-num>1</div></div>
6122      </div>
6123
6124      <p data-calc-desc class="calc-desc">Broadcast fits most growing NZ businesses. One number carries up to 3 agents and three callers at once.</p>
6125
6126      <p data-calc-usage class="calc-usage">Includes 200 minutes a month, then 10c a minute (20c after your first 3 months). Each number includes 50 texts a month, then 9c each.</p>
6127
6128      
6129      <p data-calc-extra class="calc-extra">Want more than 3 agents on one number? Extra agents are $39 a month each.</p>
6130
6131      <a href="https://talkify.nz/contact" class="btn btn-primary calc-cta">Start with this plan <span class="arr">→</span></a>
6132    </div>
6133  </div>
6134
6135  <style>
6136    /* V2 design language: the two halves are top-ruled columns, not boxed
6137       panels. This is the same shape as the /v2 missed-call calculator, which
6138       is a rule across the top and two columns under it, the controls on the
6139       left and the number on the right. */
6140    .calc-grid{
6141      display:grid;grid-template-columns:1.1fr 1fr;
6142      gap:clamp(28px,5vw,72px);align-items:start;
6143      margin-top:clamp(32px,4vw,52px);
6144      border-top:1px solid var(--line-2);
6145      padding-top:clamp(32px,4vw,56px)
6146    }
6147    .calc-controls{min-width:0}
6148    .calc-output{position:relative;min-width:0}
6149
6150    .calc-row-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:14px;flex-wrap:wrap}
6151    .calc-row-val{font-size:13px;color:var(--bone)}
6152
6153    .calc-range{width:100%;-webkit-appearance:none;appearance:none;height:4px;background:linear-gradient(90deg,var(--brand-blue),var(--brand-green));border-radius:2px;outline:none;cursor:pointer;display:block}
6154
6155    /* The integration toggles were pills. They are still toggles, so they still
6156       need a hit area and an on state, but square corners and a hairline keep
6157       them in the ruled language instead of reading as tags. Selected is a
6158       filled block, which is the one place a fill earns its keep: it has to be
6159       unmistakable at a glance how many are on. */
6160    .calc-pills{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
6161    .int-pill{
6162      padding:8px 13px;font-family:var(--mono);font-size:11px;letter-spacing:.08em;
6163      border:1px solid var(--line);border-radius:2px;background:none;color:var(--mute);
6164      transition:.25s var(--ease);cursor:pointer;max-width:100%;white-space:nowrap
6165    }
6166    .int-pill:hover{border-color:var(--line-2);color:var(--paper)}
6167    .int-pill.on{background:var(--signal);color:var(--ink);border-color:var(--signal)}
6168
6169    /* Price row */
6170    .calc-price-row{margin-top:24px;display:flex;align-items:flex-end;
6170gap:8px;flex-wrap:wrap}
6171    .calc-price-num{
6172      font-family:var(--serif);font-weight:300;line-height:.9;letter-spacing:-.04em;
6173      font-size:clamp(56px,10vw,96px);
6174      min-width:0;
6175      word-break:break-word;
6176    }
6177    .calc-price-suffix{font-family:var(--mono);font-size:12px;color:var(--mute);padding-bottom:clamp(8px,1.4vw,16px)}
6178
6179    /* Founding rate */
6180    .calc-founding{margin-top:18px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
6181    .calc-was{font-family:var(--serif);font-weight:300;font-size:22px;color:var(--mute);text-decoration:line-through;text-decoration-color:var(--coral)}
6182    /* was a filled pill; a founding rate is a note, not a badge */
6183    .calc-ftag{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--signal)}
6184    .calc-usage{margin-top:14px;font-family:var(--sans);font-size:12.5px;line-height:1.55;color:var(--mute)}
6185    .calc-extra{margin-top:10px;padding-top:10px;border-top:1px solid var(--line);font-family:var(--sans);font-size:11.5px;line-height:1.5;color:var(--mute-2)}
6186
6187    /* Stat grid, ruled the way the V2 proof stats are: a hairline over each,
6188       the mono label under the figure rather than above it. */
6189    .calc-stats{margin-top:30px;display:grid;grid-template-columns:1fr 1fr;gap:0 32px}
6190    .calc-stats > div{border-top:1px solid var(--line-2);padding:18px 0 20px;display:flex;flex-direction:column-reverse}
6191    .calc-stat-label{margin-top:8px;font-size:10px;color:var(--mute);text-transform:uppercase;letter-spacing:.16em}
6192    .calc-stat-val{font-family:var(--serif);font-size:clamp(18px,2.6vw,24px);font-weight:300;letter-spacing:-.02em;color:var(--paper);line-height:1.15;word-break:break-word;hyphens:auto}
6193
6194    .calc-desc{color:var(--bone);margin-top:24px;font-size:14px;line-height:1.6}
6195    .calc-cta{margin-top:24px}
6196
6197    /* Slider thumb */
6198    [data-calc-range]::-webkit-slider-thumb{-webkit-appearance:none;width:22px;height:22px;border-radius:50%;background:var(--paper);border:3px solid var(--ink);cursor:pointer;box-shadow:0 0 12px color-mix(in srgb, var(--signal) 60%, transparent)}
6199    [data-calc-range]::-moz-range-thumb{width:22px;height:22px;border-radius:50%;background:var(--paper);border:3px solid var(--ink);cursor:pointer}
6200
6201    /* Tablet: stack the two cards */
6202    @media (max-width:960px){
6203      .calc-grid{grid-template-columns:1fr;gap:18px}
6204    }
6205
6206    /* Small phone: tighten the stat grid */
6207    @media (max-width:480px){
6208      .calc-stats{grid-template-columns:1fr 1fr;gap:12px}
6209      .calc-stat-val{font-size:17px}
6210      .calc-row-val{font-size:12px}
6211      .int-pill{padding:7px 11px;font-size:10.5px}
6212    }
6213  </style>
6214</section>
6215
6216
6217    <section class="shell tight">
6218        <div class="section-hd">
6219            <h2 class="r">Frequently <span class="it">asked.</span></h2>
6220        </div>
6221                <div class="r pricing-faq-grid">
6222                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6223                    <div
6224                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">Can I pay for a year instead of monthly?</div>
6225                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">Yes. An annual licence for a Broadcast number is $1,990 + GST paid once, against $2,388 month by month, so 2 months are free. Nothing else changes: the number still includes up to 3 agents, 200 minutes and 50 texts a month, and anything over that is charged at the usual rate in the month you use it. The allowance is monthly rather than a pool for the whole year. If you are still on your founding rate, that is cheaper than the licence until it ends, and we will say so rather than sell you the licence.</p>
6226                </div>
6227                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6228                    <div
6229                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">What happens if I run over my minute allowance?</div>
6230                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">Each plan includes monthly minutes, 50 on Shortwave and 200 per number on Broadcast. If you go over, extra minutes on Broadcast are just 10c a minute for your first 3 months, then 20c, and on Shortwave a flat 10c a minute. Texts work the same way: a Broadcast number includes 50 a month and Shortwave includes 20, then 9c a message. We let you know as you near your allowance, so there are never any surprises.</p>
6231                </div>
6232                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6233                    <div
6234                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">How many agents can I have on one number?</div>
6235                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">Up to 3 agents are included in the one Broadcast price: a reception agent, a bookings agent and a sales agent can all share your number and hand callers between themselves. Agents beyond that are $39 a month each. A second phone number is simply a second plan.</p>
6236                </div>
6237                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6238                    <div
6239                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">Why is the price crossed out?</div>
6240                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">Every new account locks in our founding rate for its first 3 months: $129/mo for business agents on Broadcast (then $199). After that the standard rate applies, and there is no setup fee and no lock-in either way.</p>
6241                </div>
6242                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6243                    <div
6244                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">What&#039;s the difference between the Personal Assistant and a business agent?</div>
6245                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">
6245The Personal Assistant (Shortwave, $89/mo) answers one person&#039;s own mobile or landline: it screens your calls, takes messages and books your meetings. Any AI agent answering for a business (reception, sales, bookings on a business number) runs on Broadcast at $129/mo.</p>
6246                </div>
6247                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6248                    <div
6249                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">Do I keep my existing phone number?</div>
6250                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">Yes, Talkify works via call forwarding. Forward when you can&#039;t answer, or 24/7. Reversible any time, no porting.</p>
6251                </div>
6252                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6253                    <div
6254                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">Can I clone my voice?</div>
6255                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">On the Broadcast and Fleet plans. We use ElevenLabs voice cloning, you record about three minutes of script and the agent talks like you.</p>
6256                </div>
6257                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6258                    <div
6259                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">Where is my data stored?</div>
6260                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">Audio, transcripts, and call metadata are stored in NZ. AES-256 at rest. Detailed compliance docs available on request.</p>
6261                </div>
6262                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6263                    <div
6264                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">Can I edit the agent&#039;s prompt?</div>
6265                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">Yes, the dashboard has a live prompt editor. Tweak wording, escalation rules, opening hours, anything. Changes go live in seconds.</p>
6266                </div>
6267                            <div style="border-top:1px solid var(--line-2);padding:26px 0 0">
6268                    <div
6269                        style="font-family:var(--serif);font-weight:400;font-size:20px;letter-spacing:-.01em;line-height:1.2">Is there a setup fee?</div>
6270                    <p style="margin-top:10px;color:var(--bone);font-size:14px;line-height:1.55">No. Onboarding is included, and there&#039;s no lock-in. You can switch the agent off any time and keep every transcript.</p>
6271                </div>
6272                    </div>
6273    </section>
6274
6275    <section class="shell" id="app">
6276    <div class="app r">
6277        <div class="app-l">
6278            <span class="app-tag">Now shipping · iOS &amp; Android</span>
6279            <h2>Carry your <span class="it">control deck</span> in your pocket.</h2>
6280            <p>The Talkify mobile app puts the dashboard, transcripts and live coaching in your hand. Listen back to any
6281                call, edit your agent's prompt mid-shift, get push-notified the moment a hot lead lands.</p>
6282
6283            <div class="app-stores" style="--app-badge-h: 56px">
6284    <a class="app-badge" href="https://apps.apple.com/nz/app/talkify-mobile/id6766709308"
6285       target="_blank" rel="noopener">
6286        <img src="https://talkify.nz/media/branding/apple-app-store.svg"
6287             alt="Download Talkify Mobile on the App Store"
6288             width="167.5" height="56" loading="lazy">
6289    </a>
6290    <a class="app-badge" href="https://play.google.com/store/apps/details?id=com.talkifynz.app"
6291       target="_blank" rel="noopener">
6292        <img src="https://talkify.nz/media/branding/google-app-store.svg"
6293             alt="Get Talkify Mobile on Google Play"
6294             width="189" height="56" loading="lazy">
6295    </a>
6296</div>
6297        </div>
6298
6299        <div class="app-r">
6300            <div class="phone-frame app-phone">
6301                <div class="phone-screen">
6302                    <div class="stat-row"><span>9:41</span><span>5G ● ●</span></div>
6303                    <div class="ph-h">Today<br><span class="it">128 calls.</span></div>
6304                    <div class="ph-card">
6305                        <span class="lbl">Latest · 11:20am</span>
6306                        <span class="name">Booked · Sarah H.</span>
6307                        <span class="meta"><i>● Reception</i> · 00:42</span>
6308                    </div>
6309                    <div class="ph-card" style="margin-top:8px">
6310                        <span class="lbl">Live now · 1 line</span>
6311                        <div class="wave" style="height:14px;margin-top:4px">
6312                            <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div>
6313                    </div>
6314                    <div class="ph-card" style="margin-top:8px">
6315                        <span class="lbl">Sentiment</span>
6316                        <div class="ph-bar"><span class="b on"></span><span class="b on"></span><span
6317                                class="b on"></span><span class="b on"></span><span class="b"></span></div>
6318                    </div>
6319                    <div class="ph-cta" style="background:var(--signal);color:var(--on-accent)">Open dashboard</div>
6320                </div>
6321            </div>
6322        </div>
6323    </div>
6324</section>
6325    <section class="endcta endcta-has-form" id="endcta">
6326    <div class="endcta-photo" aria-hidden="true"></div>
6327
6328    
6329    <div class="endcta-wrap" id="signup">
6330        <div class="endcta-pitch">
6331            <div class="stamp">TWO WAYS TO HEAR THE AGENT</div>
6332            <h2>Don&#039;t read about it.<br><span class="it">Talk to it.</span></h2>
6333
6334            <div class="endcta-numbers">
6335                                <a href="tel:+6432421262" class="num-big" data-talkify-agent="default"
6336                   title="Hear the agent yourself">
6337      <span class="ic ic-demo">
6338        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"
6339             stroke-linecap="round"><path
6340                d="M3 5a2 2 0 012-2h2.5a1 1 0 01.96.73l1.2 4.2a1 1 0 01-.5 1.16l-1.94.97a11 11 0 005.7 5.7l.97-1.94a1 1 0 011.16-.5l4.2 1.2a1 1 0 01.73.96V19a2 2 0 01-2 2A16 16 0 013 5z"/></svg>
6341      </span>
6342                    <span>
6343        <small>Hear it yourself · our AI agent, 24/7 · ask it anything</small>
6344        03 242 1262
6345      </span>
6346                </a>
6347                
6348                                    <a href="tel:+64800002967" class="num-big num-blue" title="Sign up, sales and support">
6349      <span class="ic ic-signup">
6350        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"
6351             stroke-linecap="round"><path
6352                d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4 4v2M9 11a4 4 0 100-8 4 4 0 000 8zM19 8v6M22 11h-6"/></svg>
6353      </span>
6354                        <span>
6355        <small>Sign up, sales &amp; support · we'll set you up</small>
6356        0800 002 967
6357      </span>
6358                    </a>
6359                            </div>
6360
6361            <div class="endcta-meta">
6362                                    <span>● No card</span><span>● No lock-in</span><span>● Free to call</span><span>● The demo line can sign you up too</span>                            </div>
6363
6364            
6365                        <div class="endcta-alt">
6366                <a href="sms:+64272048827" class="btn btn-ghost btn-lg"
6367       title="Text us instead of ringing">
6368        <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"
6369             stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex:none">
6370            <path d="M21 11.5a8.4 8.4 0 01-9 8.4 9.5 9.5 0 01-2.6-.4L3 21l1.6-4.2A8.2 8.2 0 013 11.5 8.4 8.4 0 0112 3a8.4 8.4 0 019 8.5z"/>
6371        </svg>
6372        Text our agent · 027 204 8827    </a>
6373            </div>
6374            
6375            
6376                    </div>
6377
6378                    <div class="endcta-form">
6379                
6380                <span class="eyebrow"><span class="pin"></span>Get your first agent ·  No card needed </span>
6381
6382                <form method="POST" action="https://talkify.nz/contact" class="form">
6383                    <input type="hidden" name="_token" value="wcvUGyANOcL4HP8hrR8UbmGCzMFo0lavIDvlw1XJ" autocomplete="off">                                        <div class="row">
6384                        <div class="field">
6385                            <label>Your name</label>
6386                            <input type="text" name="name" required placeholder="Your full name" autocomplete="name" value="">
6387                        </div>
6388                        <div class="field">
6389                            <label>Company</label>
6390                            <input type="text" name="company" required placeholder="Your company" autocomplete="organization" value="">
6391                        </div>
6392                    </div>
6393                    <div class="row">
6394                        <div class="field">
6395                            <label>Email</label>
6396                            <input type="email" name="email" required placeholder="Your email" autocomplete="email" value="">
6397                        </div>
6398                        <div class="field">
6399                            <label>Mobile (NZ)</label>
6400                            <input type="tel" name="phone" required placeholder="Your mobile" autocomplete="tel" value="">
6401                        </div>
6402                    </div>
6403                    <div class="field">
6404  <label for="country-signup">Country</label>
6405  <select name="country" id="country-signup" required data-country-select autocomplete="country">
6406    <option value="" disabled selected>Select your country</option>
6407    <option value="NZ" >New Zealand</option>
6408    <option value="AU" >Australia</option>
6409  </select>
6410  <p style="margin-top:8px;font-family:var(--mono);font-size:11px;letter-spacing:.04em;color:var(--mute)">
6411    Talkify is currently available to businesses in New Zealand &amp; Australia only.
6412  </p>
6413</div>
6414
6415
6416<div aria-hidden="true" style="position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0">
6417  <input type="text" name="company_reference" tabindex="-1" autocomplete="off" value="" aria-hidden="true">
6418</div>
6419
6420<script>
6421(function () {
6422  var script = document.currentScript;
6423  var form = script && script.closest('form');
6424  if (!form) return;
6425  var select = form.querySelector('select[name="country"]');
6426  if (!select || select.value) return; // respect old() / a choice already made
6427
6428  try {
6429    var tz = (Intl.DateTimeFormat().resolvedOptions().timeZone || '').toLowerCase();
6430    var lang = (navigator.language || '').toLowerCase();
6431    var code = null;
6432
6433    if (tz.indexOf('auckland') >= 0 || tz.indexOf('chatham') >= 0 || lang === 'en-nz' || lang === 'mi') {
6434      code = 'NZ';
6435    } else if (tz.indexOf('australia/') >= 0 || lang === 'en-au') {
6436      code = 'AU';
6437    }
6438
6439    if (code) select.value = code;
6440  } catch (e) { /* detection is best-effort */ }
6441})();
6442</script>
6442
6443                    <div class="field">
6444                        <label>Pick your agent</label>
6445                        <div class="radios">
6446                                                        <label class="radio"><input type="radio" name="agent_type" value="assistant"  data-plan-key="assistant"><span class="dot"></span><div><div class="ttl">Personal Assistant</div><div class="sub">One mobile or landline. Personal use.</div></div></label>
6447                            <label class="radio"><input type="radio" name="agent_type" value="reception" checked data-plan-key="reception"><span class="dot"></span><div><div class="ttl">Reception</div><div class="sub">24/7 call answering for a business</div></div></label>
6448                            <label class="radio"><input type="radio" name="agent_type" value="sales"  data-plan-key="sales"><span class="dot"></span><div><div class="ttl">Sales Agent</div><div class="sub">Inbound qualifier, CRM-synced</div></div></label>
6449                            <label class="radio"><input type="radio" name="agent_type" value="booking"  data-plan-key="booking"><span class="dot"></span><div><div class="ttl">Booking Service</div><div class="sub">Live calendar, conflict-aware</div></div></label>
6450                            <label class="radio"><input type="radio" name="agent_type" value="outgoing"  data-plan-key="outgoing"><span class="dot"></span><div><div class="ttl">Outgoing Agent</div><div class="sub">Your agent does the ringing, billed per call</div></div></label>
6451                            <label class="radio"><input type="radio" name="agent_type" value="survey"  data-plan-key="survey"><span class="dot"></span><div><div class="ttl">Campaign Agent</div><div class="sub">Rings your list, asks your questions, billed per call</div></div></label>
6452                            <label class="radio"><input type="radio" name="agent_type" value="wellness"  data-plan-key="wellness"><span class="dot"></span><div><div class="ttl">Wellness Checks</div><div class="sub">Rings someone daily to check they're alright</div></div></label>
6453                        </div>
6454                        <p class="plan-recommend" data-plan-recommend style="display:none">
6455                            We recommend running an incoming agent alongside an outgoing or campaign agent. People you ring will often ring you
6456                            back, and an incoming agent makes sure those return calls are answered rather than missed. If you would
6457                            rather not add one, we can clone your business caller ID so return calls come straight back to your
6458                            existing phone.
6459                        </p>
6460                    </div>
6461
6462                    <div class="field">
6463                        <label>How you want to pay</label>
6464                        <div class="radios">
6465                            <label class="radio">
6466                                <input type="radio" name="plan" value="broadcast" checked>
6467                                <span class="dot"></span>
6468                                <div><div class="ttl">Monthly plan</div><div class="sub">A set monthly price with included minutes. Most people choose this. Cancel anytime.</div></div>
6469                            </label>
6470                            <label class="radio">
6471                                <input type="radio" name="plan" value="payg" >
6472                                <span class="dot"></span>
6473                                <div><div class="ttl">Pay as you go</div><div class="sub">$1 a minute and 15c a text, prepaid from a balance. $10/month covers your phone number, and you start with $10 of free credit on top. Cancel anytime.</div></div>
6474                            </label>
6475                        </div>
6476                    </div>
6477
6478                    <div class="plan-display" data-plan-display>
6479                        <div class="plan-display-left">
6480                            <div class="plan-display-label" data-plan-label>Personal Assistant</div>
6481                            <div class="plan-display-sub" data-plan-sub>Single mobile or landline. Built for one person, not a business.</div>
6482                        </div>
6483                        <div class="plan-display-right">
6484                            <div class="plan-display-price" data-plan-price>$89<small>/mo</small></div>
6485                            <div class="plan-display-tier" data-plan-tier>Shortwave plan</div>
6486                                                        <div class="plan-display-note" data-plan-note  style="display:none" ></div>
6487                        </div>
6488                    </div>
6489                    <p class="founding-line">
6490                                                    <span class="fl-tag">Founding rate</span> On a monthly plan your price is locked in at the founding rate for your first 3 months, then the standard rate applies. Pay as you go has no founding step: the rate is just the rate.
6491                                                Plans include 50 to 200 minutes a month, then 10c a minute. The first 20 texts each month are free, then 9c each.
6492                    </p>
6493                    <p class="plan-asterisk" data-plan-asterisk style="display:none">
6494                        <span>*</span> Subject to your CRM or booking system. Additional implementation cost may apply for non-standard integrations.
6495                    </p>
6496
6497                    <div class="actions">
6498                        <span class="note">● Your data stays in NZ.</span>
6499                        <button type="submit" class="btn btn-primary btn-lg">Create your first agent <span class="arr">→</span></button>
6500                    </div>
6501                </form>
6502
6503                
6503<script>
6504                    (function () {
6505                        // A plan only carries a crossed-out "was" price and a founding note while
6506                        // its intro price is genuinely below its standard price; when the two
6507                        // match in the pricing table both come through blank and the picker
6508                        // shows a plain price. Per-call plans never have a founding step.
6509                        const PA_NOTE = "";
6510                        const BIZ_NOTE = "Founding rate for your first 3 months, then $199/mo";
6511                        const PA_WAS = "";
6512                        const BIZ_WAS = "$199";
6513
6514                        const PLANS = {
6515                            assistant: { label: 'Personal Assistant', sub: 'Single mobile or landline. Built for one person, not a business.', was: PA_WAS, price: '$89', suffix: '/mo', tier: 'Shortwave plan · personal use only', note: PA_NOTE, asterisk: false },
6516                            reception: { label: 'Reception',         sub: '24/7 AI call answering for your business. Bundled with Sales on the Broadcast plan.', was: BIZ_WAS, price: '$129', suffix: '/mo', tier: 'Broadcast plan · includes Sales Agent', note: BIZ_NOTE, asterisk: false },
6517                            sales:     { label: 'Sales Agent',       sub: 'Inbound lead qualification with CRM sync. Bundled with Reception on the Broadcast plan.', was: BIZ_WAS, price: '$129', suffix: '/mo', tier: 'Broadcast plan · includes Reception *', note: BIZ_NOTE, asterisk: true },
6518                            booking:   { label: 'Booking Service',   sub: 'Live calendar booking into your booking system, with custom API integration where needed.', was: '', price: 'from $499', suffix: '/mo', tier: 'Custom setup · 12-month contract *', note: 'Quoted per build, on a 12-month term.', asterisk: true },
6519                            outgoing:  { label: 'Outgoing Agent',    sub: 'Your agent makes the calls: follow-ups, appointment reminders, confirmations and callbacks. It rings out on a Talkify number, or we can show your own business caller ID instead.', was: '', price: '$59', suffix: '/mo', tier: 'Outgoing campaigns · 20 minutes included, then 50c/min', note: 'Charged only in months you run campaigns. One-off calls outside a campaign are just 50c a minute, no monthly fee.', asterisk: false, recommend: true },
6520                            survey:    { label: 'Campaign Agent',    sub: 'Import your list and the agent rings everyone, asks your questions and reads each conversation against your goal, so you get answers, sentiment and hot leads by name.', was: '', price: '$59', suffix: '/mo', tier: 'Outgoing campaigns · 20 minutes included, then 50c/min', note: 'Marketing runs and phone surveys are the same plan, charged only in months you run one.', asterisk: false, recommend: true },
6521                            wellness:  { label: 'Wellness Checks',   sub: 'Scheduled or randomly timed check-in calls to somebody living alone. The agent asks how they are, gives medication and appointment reminders, texts you after every call and escalates down your contact list when nobody answers.', was: '', price: 'from $59', suffix: '/mo', tier: 'Family Member (one person) · $599 for as many as you like', note: 'Includes 20 call minutes, or 200 pooled minutes on Providers. Priced by how many people are rung, not by features.', asterisk: false },
6522                        };
6523                        // The pay-as-you-go face of the same picker: whatever agent they chose,
6524                        // the money side is the per-minute wallet, so the price panel follows
6525                        // the payment choice rather than quoting a monthly plan.
6526                        const PAYG = {
6527                            price: '$1',
6528                            suffix: '/min',
6529                            tier: 'Pay as you go · $10/month covers your phone number',
6530                            note: '$10 free credit to start, on top of the number. Calls and texts come off your prepaid balance.',
6531                        };
6532                        const form = document.currentScript.closest('.endcta-form') || document;
6533                        const radios = form.querySelectorAll('input[name="agent_type"]');
6534                        const payRadios = form.querySelectorAll('input[name="plan"]');
6535                        const labelEl = form.querySelector('[data-plan-label]');
6536                        const subEl = form.querySelector('[data-plan-sub]');
6537                        const priceEl = form.querySelector('[data-plan-price]');
6538                        const tierEl = form.querySelector('[data-plan-tier]');
6539                        const noteEl = form.querySelector('[data-plan-note]');
6540                        const astEl = form.querySelector('[data-plan-asterisk]');
6541                        const recEl = form.querySelector('[data-plan-rec
6541ommend]');
6542
6543                        function update(){
6544                            const checked = form.querySelector('input[name="agent_type"]:checked');
6545                            if (!checked) return;
6546                            const plan = PLANS[checked.value];
6547                            if (!plan) return;
6548                            const pay = form.querySelector('input[name="plan"]:checked');
6549                            const payg = pay && pay.value === 'payg';
6550                            labelEl.textContent = plan.label;
6551                            subEl.textContent = plan.sub;
6552                            priceEl.innerHTML = payg
6553                                ? PAYG.price + '<small>' + PAYG.suffix + '</small>'
6554                                : (plan.was ? '<s class="was-price">'+plan.was+'</s> ' : '') + plan.price + (plan.suffix ? '<small>'+plan.suffix+'</small>' : '');
6555                            tierEl.textContent = payg ? PAYG.tier : plan.tier;
6556                            if (noteEl) {
6557                                const note = payg ? PAYG.note : (plan.note || '');
6558                                noteEl.textContent = note;
6559                                noteEl.style.display = note ? 'block' : 'none';
6560                            }
6561                            astEl.style.display = (!payg && plan.asterisk) ? 'block' : 'none';
6562                            if (recEl) recEl.style.display = plan.recommend ? 'block' : 'none';
6563                        }
6564                        radios.forEach(r => r.addEventListener('change', update));
6565                        payRadios.forEach(r => r.addEventListener('change', update));
6566                        update();
6567                    })();
6568                </script>
6568
6569            </div>
6570            </div>
6571
6572            <style>
6573            /* Two top-ruled columns rather than two pills side by side. The pair is
6574               held to a readable measure and centred under the headline, so the
6575               block still reads as the close of the page even though the section
6576               itself is centred and these two are ruled and left-aligned. */
6577            .endcta-numbers {
6578                display: grid;
6579                grid-template-columns: 1fr 1fr;
6580                gap: clamp(24px, 4vw, 56px);
6581                margin: 56px auto 0;
6582                max-width: 780px;
6583                text-align: left
6584            }
6585
6586            @media (max-width: 800px) {
6587                .endcta-numbers {
6588                    grid-template-columns: 1fr;
6589                    gap: 30px;
6590                    max-width: 460px
6591                }
6592            }
6593
6594            .endcta-alt {
6595                margin-top: 36px;
6596                display: flex;
6597                flex-wrap: wrap;
6598                gap: 12px;
6599                justify-content: center
6600            }
6601
6602            /* The app line sits under the two ways to reach us and quieter than
6603               either, because it is aimed at people who have already signed up. */
6604            .endcta-app-line {
6605                margin-top: 40px;
6606                font-family: var(--mono);
6607                font-size: 10px;
6608                letter-spacing: .18em;
6609                text-transform: uppercase;
6610                color: var(--mute)
6611            }
6612
6613            .endcta .app-stores {
6614                margin-top: 14px;
6615                justify-content: center
6616            }
6617
6618            /* ── With the form in it ───────────────────────────────────────────
6619               The pitch stops being a centred banner and becomes the left half
6620               of one closing block, with the get-started form on the right. No
6621               panel and no rounding: the two columns simply share the page. */
6622            .endcta-has-form .endcta-wrap {
6623                display: grid;
6624                grid-template-columns: 1fr 1.05fr;
6625                gap: clamp(40px, 5vw, 76px);
6626                align-items: start;
6627                max-width: 1240px;
6628                margin: 0 auto;
6629                text-align: left
6630            }
6631
6632            /* The skyline sits behind a short centred banner comfortably. Behind
6633               a block three times as tall it runs up under the form fields and
6634               the price panel, where a photograph is just noise, so it is held
6635               well back and the scrim is carried the whole way down instead of
6636               fading out in the middle. */
6637            .endcta.endcta-has-form .endcta-photo {
6638                opacity: .12;
6639                background-position: center bottom
6640            }
6641
6642            html[data-theme="light"] .endcta.endcta-has-form .endcta-photo {
6643                opacity: .16
6644            }
6645
6646            .endcta.endcta-has-form .endcta-photo::after {
6647                background: linear-gradient(180deg, var(--scrim-mid) 0%, var(--scrim-strong) 30%, var(--scrim-strong) 100%)
6648            }
6649
6650            .endcta-has-form .endcta-numbers {
6651                grid-template-columns: 1fr;
6652                gap: 26px;
6653                margin: 44px 0 0;
6654                max-width: none
6655            }
6656
6657            .endcta-has-form .endcta-meta {
6658                justify-content: flex-start;
6659                gap: 22px
6660            }
6661
6662            .endcta-has-form .endcta-alt,
6663            .endcta-has-form .app-stores {
6664                justify-content: flex-start
6665            }
6666
6667            .endcta-form .eyebrow {
6668                display: inline-flex;
6669                margin-bottom: 20px
6670            }
6671
6672            @media (max-width: 1000px) {
6673                .endcta-has-form .endcta-wrap {
6674                    grid-template-columns: 1fr;
6675                    gap: 48px
6676                }
6677
6678                .endcta-has-form .endcta-numbers {
6679                    max-width: 460px
6680                }
6681            }
6682
6683            /* Carried over from the signup section this block absorbed: that
6684               partial's styles only ship on the page that includes it, and it
6685               is now only included by /v2. */
6686            .signup-errors {
6687                margin-bottom: 18px;
6688                padding: 14px 0 14px 16px;
6689                border-left: 2px solid var(--coral);
6690                font-family: var(--mono);
6691                font-size: 12px;
6692                line-height: 1.6;
6693                color: var(--paper)
6694            }
6695
6696            .was-price {
6697                font-size: .55em;
6698                color: var(--mute-2);
6699                text-decoration: line-through;
6700                text-decoration-color: var(--coral);
6701                margin-right: 4px;
6702                font-weight: 300
6703            }
6704
6705            .founding-line {
6706                margin-top: 14px;
6707                font-family: var(--sans);
6708                font-size: 12px;
6709                line-height: 1.55;
6710                color: var(--mute)
6711            }
6712
6713            .founding-line .fl-tag {
6714                font-family: var(--mono);
6715                font-size: 10px;
6716                letter-spacing: .14em;
6717                text-transform: uppercase;
6718                color: var(--signal);
6719                margin-right: 8px
6720            }
6721        </style>
6722    </section>
6723
6724    <style>
6725        /* The prices in the hero's right column. Uses the shared
6726           .ruled-figure vocabulary, so they read the same as every other price
6727           block on the site. */
6728        .pricing-hero-figures {
6729            display: flex;
6730            flex-direction: column;
6731            gap: clamp(18px, 2.4vw, 30px)
6732        }
6733
6734        .pricing-hero-figures .ruled-figure {
6735            display: block;
6736            text-decoration: none;
6737            padding-top: clamp(18px, 2vw, 26px);
6738            transition: border-color .3s var(--ease)
6739        }
6740
6741        .pricing-hero-figures .ruled-figure:hover {
6742            border-top-color: var(--signal)
6743        }
6744
6745        .pricing-hero-figures .big {
6746            margin-top: 8px;
6747            font-size: clamp(38px, 3.6vw, 52px)
6748        }
6749
6750        .pricing-hero-figures .fig-note {
6751            display: block;
6752            margin-top: 8px;
6753            color: var(--bone);
6754            font-size: 13px;
6755            line-height: 1.5
6756        }
6757
6758        @media (max-width: 1000px) {
6759            .pricing-hero-figures {
6760                flex-direction: row;
6761                flex-wrap: wrap
6762            }
6763
6764            .pricing-hero-figures .ruled-figure {
6765                flex: 1 1 220px
6766            }
6767        }
6768
6769        .pricing-faq-grid {
6770            display: grid;
6771            grid-template-columns:repeat(2, 1fr);
6772            gap: clamp(24px, 3vw, 44px)
6773        }
6774
6775        @media (max-width: 760px) {
6776            .pricing-faq-grid {
6777                grid-template-columns:1fr
6778            }
6779        }
6780    </style>
6781
6782
6783<style>
6784    .foot-social {
6785        display: inline-flex;
6786        align-items: center;
6787        gap: 8px;
6788        padding: 6px 0;
6789        font-family: var(--mono);
6790        font-size: 11px;
6791        color: var(--mute);
6792        letter-spacing: .06em;
6793        transition: color .25s var(--ease);
6794    }
6795
6796    .foot-social:hover { color: var(--paper); }
6797
6798    /* The badges sit tighter than the marketing rows and wrap rather than
6799       squeeze, because this column is the narrowest place they appear. */
6800    .foot-apps {
6801        margin-top: 22px;
6802        gap: 10px;
6803    }
6804</style>
6805<footer class="foot">
6806    <div class="foot-grid">
6807        <div class="foot-brand">
6808            
6809            <a class="logo" href="https://talkify.nz" aria-label="Talkify, home"
6810               style="display:flex;align-items:center;gap:14px;color:inherit;text-decoration:none">
6811                <svg class="tk-logo" viewBox="-3 -3 317.81 106"
6812     width="125.92" height="42"
6813     xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Talkify" focusable="false">
6814        <circle cx="50" cy="50" r="50" fill="var(--tk-word, #101820)"/>
6815    
6816    <g fill="none" stroke="var(--tk-ground, #ffffff)" stroke-width="10" stroke-linecap="round">
6817        <path d="M34 26 V54 C34 74 62 80 76 62"/>
6818        <path d="M20 40 H46"/>
6819    </g>
6820    
6821    <g transform="translate(56 20) scale(0.30)">
6822        <g class="tk-eye">
6823            <path d="M50 8 Q55.5 39 92 50 Q55.5 61 50 92 Q44.5 61 8 50 Q44.5 39 50 8 Z" fill="var(--tk-ground, #ffffff)"/>
6824        </g>
6825    </g>
6826            <path d="M271.37 19.44 L274.1 19.47 L276.98 20.13 L279.56 21.51 L281.93 23.58 L276.86 28.65 L275.24 27.45 L274.04 26.97 L273.32 26.85 L270.62 26.97 L269.6 27.27 L268.28 28.05 L267.23 29.28 L266.57 30.96 L266.39 32.28 L266.39 37.38 L284.84 37.41 L293.66 59.85 L302.99 37.5 L311.81 37.44 L289.55 86.04 L289.34 86.37 L288.98 86.37 L280.61 86.34 L289.25 68.4 L276.89 39.18 L276.8 44.61 L266.39 44.64 L266.36 71.97 L258.47 71.94 L258.47 44.64 L250.19 44.58 L250.19 37.44 L258.44 37.41 L258.47 32.28 L258.71 30 L259.49 27.36 L260.69 25.14 L262.52 23.01 L264.98 21.21 L267.8 20.01 L270.08 19.53ZM190.01 20.16 L197.93 20.16 L197.93 71.94 L190.01 71.94ZM204.53 20.16 L212.45 20.16 L212.48 53.61 L226.46 37.41 L235.85 37.44 L221.33 53.94 L230.24 64.47 L236.57 71.94 L226.52 71.97 L212.48 55.05 L212.45 71.94 L204.53 71.94ZM131.63 23.04 L139.55 23.04 L139.58 37.41 L147.83 37.44 L147.8 44.61 L139.55 44.64 L139.55 71.94 L131.63 71.94 L131.63 44.64 L123.35 44.58 L123.38 37.41 L131.63 37.38ZM164.09 36.72 L167.06 36.81 L170.24 37.59 L171.92 38.37 L173.42 39.33 L175.4 41.19 L175.52 37.41 L183.41 37.44 L183.41 71.94 L175.52 71.97 L175.46 68.25 L174.08 69.57 L172.85 70.44 L170.84 71.55 L169.34 72.09 L167.84 72.45 L165.8 72.69 L163.76 72.69 L161.84 72.45 L159.92 71.97 L158.48 71.43 L156.44 70.35 L154.76 69.15 L152.27 66.66 L150.47 63.96 L149.57 62.04 L148.91 60.06 L148.55 58.5 L148.25 55.86 L148.37 52.2 L148.79 49.86 L149.39 47.88 L149.93 46.56 L151.01 44.58 L152.33 42.72 L153.65 41.28 L156.5 39.03 L158.54 37.95 L159.98 37.41 L161.9 36.93ZM239.21 37.44 L247.13 37.44 L247.13 71.94 L239.21 71.94ZM165.2 44.19 L163.04 44.61 L161.48 45.27 L159.98 46.29 L158.51 47.82 L157.73 49.02 L156.83 51.18 L156.41 53.52 L156.41 55.86 L156.65 57.48 L157.31 59.52 L158.51 61.56 L160.04 63.15 L161.48 64.11 L163.46 64.89 L165.32 65.19 L167.12 65.13 L169.34 64.77 L171.14 63.99 L172.34 63.15 L173.99 61.38 L175.01 59.64 L175.67 57.66 L175.97 55.44 L175.91 53.1 L175.49 51 L174.53 48.78 L173.81 47.7 L172.52 46.35 L170.84 45.21 L169.16 44.55 L167.18 44.19Z" fill="var(--tk-word, #101820)" fill-rule="evenodd"/>
6827        
6828        <g transform="translate(231.30 6.84) scale(0.216)">
6829            <path d="M50 8 Q55.5 39 92 50 Q55.5 61 50 92 Q44.5 61 8 50 Q44.5 39 50 8 Z"
6830                  fill="var(--tk-word, #101820)"/>
6831        </g>
6832    </svg>
6833            </a>
6834                                        <p>The voice operating system for New Zealand business. Built in Aotearoa, hosted in Aotearoa, working while
6835                    you don't.</p>
6836                        <div
6837                style="margin-top:20px;font-family:var(--mono);font-size:12px;color:var(--mute);letter-spacing:.06em;line-height:1.7">
6838                                <span style="color:var(--mute);font-size:10px;text-transform:uppercase;letter-spacing:.18em">Sign up by phone</span><br>
6839                <a href="tel:+64800002967" style="color:var(--bone);transition:.25s">0800 002 967</a><br>
6840                                <span
6841                    style="color:var(--mute);font-size:10px;text-transform:uppercase;letter-spacing:.18em;margin-top:8px;display:inline-block">Hear an agent demo</span><br>
6842                <a href="tel:+6432421262" data-talkify-agent="default" style="color:var(--bone);transition:.25s">03 242 1262</a>
6843                                    <br>
6844                    <span
6845                        style="color:var(--mute);font-size:10px;text-transform:uppercase;letter-spacing:.18em;margin-top:8px;display:inline-block">Text our agent</span><br>
6846                    <a href="sms:+64272048827" style="color:var(--bone);transition:.25s">027 204 8827</a>
6847                            </div>
6848            <div style="margin-top:20px;display:flex;flex-wrap:wrap;gap:8px 22px;align-items:center">
6849                <a href="https://www.facebook.com/profile.php?id=61572226258048" target="_blank"
6850                   rel="noopener noreferrer" aria-label="Facebook"
6851                   class="foot-social">
6852                    <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
6853                        <path
6854                            d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
6855                    </svg>
6856                    Facebook
6857                </a>
6858                <a href="https://www.instagram.com/talkifynz/" target="_blank"
6859                   rel="noopener noreferrer" aria-label="Instagram"
6860                   class="foot-social">
6861                    <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
6862                        <path
6863                            d="M12 2.16c3.2 0 3.58.012 4.85.07 1.17.054 1.805.25 2.227.415.56.217.96.477 1.38.896.42.42.68.82.897 1.38.164.423.36 1.058.413 2.228.058 1.27.07 1.65.07 4.85s-.012 3.58-.07 4.85c-.054 1.17-.25 1.805-.413 2.227a3.72 3.72 0 0 1-.897 1.382c-.42.42-.82.68-1.38.896-.423.165-1.058.36-2.228.414-1.27.058-1.65.07-4.85.07s-3.58-.012-4.85-.07c-1.17-.054-1.805-.25-2.227-.414a3.72 3.72 0 0 1-1.38-.896 3.72 3.72 0 0 1-.897-1.382c-.164-.422-.36-1.057-.414-2.227C2.173 15.58 2.16 15.2 2.16 12s.013-3.58.07-4.85c.055-1.17.25-1.805.415-2.228.217-.56.477-.96.896-1.38.42-.42.82-.68 1.38-.896.423-.165 1.058-.36 2.228-.414C8.42 2.173 8.8 2.16 12 2.16zM12 0C8.74 0 8.333.014 7.053.072 5.775.13 4.905.333 4.14.63a5.88 5.88 0 0 0-2.126 1.384A5.88 5.88 0 0 0 .63 4.14C.333 4.905.13 5.775.072 7.053.014 8.333 0 8.74 0 12s.014 3.667.072 4.947c.058 1.277.261 2.148.558 2.913a5.88 5.88 0 0 0 1.384 2.126 5.88 5.88 0 0 0 2.126 1.384c.765.296 1.635.499 2.913.558C8.333 23.986 8.74 24 12 24s3.667-.014 4.947-.072c1.277-.06 2.148-.262 2.913-.558a5.88 5.88 0 0 0 2.126-1.384 5.88 5.88 0 0 0 1.384-2.126c.296-.765.499-1.636.558-2.913C23.986 15.667 24 15.26 24 12s-.014-3.667-.072-4.947c-.06-1.278-.262-2.148-.558-2.913a5.88 5.88 0 0 0-1.384-2.126A5.88 5.88 0 0 0 19.86.63c-.765-.297-1.636-.5-2.913-.558C15.667.014 15.26 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm7.846-10.405a1.44 1.44 0 1 1-2.88 0 1.44 1.44 0 0 1 2.88 0z"/>
6864                    </svg>
6865                    Instagram
6866                </a>
6867                <a href="https://www.linkedin.com/company/talkify-nz/" target="_blank"
6868                   rel="noopener noreferrer" aria-label="LinkedIn"
6869                   class="foot-social">
6870                    <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
6871                        <path
6872                            d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
6873                    </svg>
6874                    LinkedIn
6875                </a>
6876            </div>
6877
6878            
6879            <div class="app-stores foot-apps" style="--app-badge-h: 38px">
6880    <a class="app-badge" href="https://apps.apple.com/nz/app/talkify-mobile/id6766709308"
6881       target="_blank" rel="noopener">
6882        <img src="https://talkify.nz/media/branding/apple-app-store.svg"
6883             alt="Download Talkify Mobile on the App Store"
6884             width="113.7" height="38" loading="lazy">
6885    </a>
6886    <a class="app-badge" href="https://play.google.com/store/apps/details?id=com.talkifynz.app"
6887       target="_blank" rel="noopener">
6888        <img src="https://talkify.nz/media/branding/google-app-store.svg"
6889             alt="Get Talkify Mobile on Google Play"
6890             width="128.3" height="38" loading="lazy">
6891    </a>
6892</div>
6893        </div>
6894        <div>
6895            <h4>Agents</h4>
6896            <ul>
6897                <li><a href="https://talkify.nz/reception">Reception</a></li>
6898                <li><a href="https://talkify.nz/personal-assistant">Personal Assistant</a></li>
6899                <li><a href="https://talkify.nz/booking-service">Booking Service</a></li>
6900                <li><a href="https://talkify.nz/sales-agent">Sales Agent</a></li>
6901                <li><a href="https://talkify.nz/ai-phone-surveys">Campaign Agent</a></li>
6902                <li><a href="https://talkify.nz/debt-collection">Debt Collection</a></li>
6903                <li><a href="https://talkify.nz/ai-wellness-checks">Wellness Checks</a></li>
6904                <li>
6904<a href="https://talkify.nz/outbound-calls">Outbound Calls</a></li>
6905                <li><a href="https://talkify.nz/ai-marketing-campaigns">Marketing Campaigns</a></li>
6906                <li><a href="https://talkify.nz/website-chat">Website Chat</a></li>
6907                <li><a href="https://talkify.nz/calendar">Team Calendar</a></li>
6908                <li><a href="https://talkify.nz/dialler">Dialler</a></li>
6909                <li><a href="https://talkify.nz/agents">All agents &rarr;</a></li>
6910            </ul>
6911        </div>
6912        
6913        <div>
6914            <h4>Trades</h4>
6915            <ul>
6916                <li><a href="https://talkify.nz/plumber">Plumbing</a></li>
6917                <li><a href="https://talkify.nz/electrician">Electricians</a></li>
6918                <li><a href="https://talkify.nz/builder">Builders</a></li>
6919                <li><a href="https://talkify.nz/hvac">Heat Pump &amp; HVAC</a></li>
6920                <li><a href="https://talkify.nz/automotive">Mechanics &amp; Workshops</a></li>
6921                <li><a href="https://talkify.nz/landscaping">Landscaping</a></li>
6922                <li><a href="https://talkify.nz/pest-control">Pest Control</a></li>
6923                <li><a href="https://talkify.nz/tradesman">All Trades</a></li>
6924            </ul>
6925        </div>
6926        <div>
6927            <h4>Industries</h4>
6928            <ul>
6929                <li><a href="https://talkify.nz/beauty">Beauty &amp; Wellness</a></li>
6930                <li><a href="https://talkify.nz/real-estate">Real Estate</a></li>
6931                <li><a href="https://talkify.nz/retail">Retail</a></li>
6932                <li><a href="https://talkify.nz/professional-services">Professional Services</a></li>
6933                <li><a href="https://talkify.nz/barber">Barbers</a></li>
6934                <li><a href="https://talkify.nz/gym">Gyms &amp; Studios</a></li>
6935                <li><a href="https://talkify.nz/personal-trainer">Personal Trainers</a></li>
6936                <li><a href="https://talkify.nz/hotel">Hotels &amp; Motels</a></li>
6937                <li><a href="https://talkify.nz/accountant">Accountants</a></li>
6938                <li><a href="https://talkify.nz/industries">All industries &rarr;</a></li>
6939            </ul>
6940        </div>
6941        <div>
6942            
6943            <h4>Call answering</h4>
6944            <ul>
6945                <li><a href="https://talkify.nz">AI receptionist NZ</a></li>
6946                <li><a href="https://talkify.nz/ai-phone-agent">AI phone agent NZ</a></li>
6947                <li><a href="https://talkify.nz/virtual-receptionist">Virtual receptionist NZ</a></li>
6948                <li><a href="https://talkify.nz/ai-answering-service">AI answering service NZ</a></li>
6949                <li><a href="https://talkify.nz/after-hours-answering">After hours answering NZ</a></li>
6950                <li><a href="https://talkify.nz/on-call-roster">On-Call Roster</a></li>
6951                <li><a href="https://talkify.nz/ai-call-centre">AI Call Centre Agents</a></li>
6952                <li><a href="https://talkify.nz/business-phone-lines">Business Phone Lines</a></li>
6953                
6954                <li style="margin-top:6px;color:var(--mute);line-height:1.8">
6955                    By city:
6956                    <a
6957                            href="https://talkify.nz/ai-receptionist-auckland">Auckland</a><span
6958                            style="color:var(--line-2)"> · </span><a
6959                            href="https://talkify.nz/ai-receptionist-wellington">Wellington</a><span
6960                            style="color:var(--line-2)"> · </span><a
6961                            href="https://talkify.nz/ai-receptionist-christchurch">Christchurch</a><span
6962                            style="color:var(--line-2)"> · </span><a
6963                            href="https://talkify.nz/ai-receptionist-hamilton">Hamilton</a><span
6964                            style="color:var(--line-2)"> · </span><a
6965                            href="https://talkify.nz/ai-receptionist-tauranga">Tauranga</a><span
6966                            style="color:var(--line-2)"> · </span><a
6967                            href="https://talkify.nz/ai-receptionist-dunedin">Dunedin</a>                </li>
6968            </ul>
6969        </div>
6970        <div>
6971            
6972            <h4>Company</h4>
6973            <ul>
6974                <li><a href="https://talkify.nz/pricing">Pricing</a></li>
6975                <li><a href="https://talkify.nz/integrations">Integrations</a></li>
6976                
6977                <li><a href="https://talkify.nz/compare">Compare Providers</a><span
6978                        style="color:var(--line-2)"> · </span><a
6979                        href="https://talkify.nz/alternatives">Alternatives</a></li>
6980                <li><a href="https://talkify.nz/missed-call-calculator">Missed Call Calculator</a></li>
6981                <li><a href="https://talkify.nz/blog">Journal</a></li>
6982                
6983                <li><a href="https://talkify.nz/help">Help centre</a><span
6984                        style="color:var(--line-2)"> · </span><a
6985                        href="https://talkify.nz/contact-us">Contact us</a></li>
6986                <li><a href="https://talkify.nz/demo">Live demo</a></li>
6987                <li><a href="https://talkify.nz/signup">Get started</a></li>
6988            </ul>
6989        </div>
6990    </div>
6991    <div class="foot-bot">
6992                    <span>© <span id="year">2026</span> · Talkify Limited · NZ owned and hosted</span>
6993                <span>
6994            
6995                            <span aria-current="page">New Zealand</span> · <a href="https://talkify.nz/au" style="color:var(--bone)">Australia</a> ·
6996                        <a href="https://talkify.nz/privacy" style="color:var(--bone)">Privacy</a> ·
6997            <a href="https://talkify.nz/terms" style="color:var(--bone)">Terms</a> ·
6998            <a href="https://talkify.nz/support" style="color:var(--bone)">Support</a> ·
6999                            <a href="https://talkify.nz/login" style="color:var(--bone)">Sign in</a>
7000                        · <a href="https://d3v.nz" style="color:var(--bone)">Made by D3V</a>
7001        </span>
7002    </div>
7003</footer>
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014<script>
7015    function tick() {
7016        const d = new Date();
7017        const f = new Intl.DateTimeFormat('en-NZ', {
7018            timeZone: 'Pacific/Auckland',
7019            hour: '2-digit',
7020            minute: '2-digit',
7021            second: '2-digit',
7022            hour12: false
7023        });
7024        const el = document.getElementById('clock');
7025        if (el) el.textContent = f.format(d);
7026    }
7027
7028    tick();
7029    setInterval(tick, 1000);
7030    const yEl = document.getElementById('year');
7031    if (yEl) yEl.textContent = new Date().getFullYear();
7032
7033    /* Scroll reveal. Fires once per block. Anybody who has asked for less
7034       motion, and any browser without IntersectionObserver, gets the lot
7035       revealed immediately rather than a page of invisible sections. */
7036    (function () {
7037        const blocks = document.querySelectorAll('.r');
7038        if (!blocks.length) return;
7039        const reduce = window.matchMedia
7040            && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
7041        if (reduce || !('IntersectionObserver' in window)) {
7042            blocks.forEach(el => el.classList.add('in'));
7043            return;
7044        }
7045        const io = new IntersectionObserver((entries) => {
7046            entries.forEach(e => {
7047                if (e.isIntersecting) {
7048                    e.target.classList.add('in');
7049                    io.unobserve(e.target);
7050                }
7051            });
7052        }, {rootMargin: '-8% 0px -5% 0px'});
7053        blocks.forEach(el => io.observe(el));
7054    })();
7055
7056    /* Agent phones. Each opens on a plain lock screen, then the clock drops to
7057       its compact size and the notifications land on top of it, which is the
7058       order an iPhone does it in. Plays once, when the panel is on screen.
7059
7060       The clock is the VISITOR'S OWN time and every stamp is counted back from
7061       it, so a screen can never show a notification that arrived after the time
7062       printed above it. Nothing is written into the markup, so a cached page
7063       cannot go stale either.
7064
7065       The tilt and the sheen are a couple of degrees and a highlight eased
7066       across the viewport. Both are off on coarse pointers, where there is no
7067       hover to reward them and the scroll handler is pure cost, and the whole
7068       thing collapses to "already arrived" under prefers-reduced-motion. */
7069    (function () {
7070        const phones = [...document.querySelectorAll('[data-agent-phone]')];
7071        if (!phones.length) return;
7072
7073        const clockOf = d => d.toLocaleTimeString('en-NZ', {hour: 'numeric', minute: '2-digit', hour12: false});
7074        const stampOf = d => d.toLocaleTimeString('en-NZ', {hour: 'numeric', minute: '2-digit', hour12: true})
7075            .replace(/\s/g, '').toLowerCase();
7076        const dateOf = d => d.toLocaleDateString('en-NZ', {weekday: 'long', day: 'numeric', month: 'long'});
7077
7078        const still = matchMedia('(prefers-reduced-motion: reduce)').matches;
7079        const coarse = matchMedia('(pointer: coarse)').matches;
7080
7081        phones.forEach(phone => {
7082            // A phone may pin its own clock with data-agent-at="HH:MM". The
7083            // after-hours story is an escalation at a quarter to midnight, and
7084            // stamped 2pm on a daytime visitor's own clock it reads as
7085            // nonsense. Everything else still shows the visitor's real time,
7086            // counted back from, so nothing arrives after the clock above it.
7087            const now = new Date();
7088            const pinned = (phone.dataset.agentAt || '').match(/^(\d{1,2}):(\d{2})$/);
7089            if (pinned) now.setHours(+pinned[1], +pinned[2], 0, 0);
7090
7091            const t = phone.querySelector('[data-agent-time]');
7092            const dt = phone.querySelector('[data-agent-date]');
7093            if (t) t.textContent = clockOf(now);
7094            if (dt) dt.textContent = dateOf(now);
7095
7096            phone.querySelectorAll('[data-agent-ago]').forEach(el => {
7097                const mins = parseInt(el.dataset.agentAgo, 10);
7098                if (!Number.isFinite(mins)) return;
7099                el.textContent = stampOf(new Date(now.getTime() - mins * 60000));
7100            });
7101
7102            const clock = phone.querySelector('[data-agent-clock]');
7103            const notes = [...phone.querySelectorAll('.hpn')];
7104            if (!clock || !notes.length) return;
7105
7106            if (still) {
7107                clock.classList.add('is-compact');
7108                notes.forEach(n => n.classList.add('is-in'));
7109                return;
7110            }
7111
7112            let played = false;
7113            const play = () => {
7114                if (played) return;
7115                played = true;
7116                setTimeout(() => clock.classList.add('is-compact'), 420);
7117                notes.forEach((n, i) => setTimeout(() => n.classList.add('is-in'), 780 + i * 380));
7118            };
7119
7120            const io = new IntersectionObserver(entries => {
7121                entries.forEach(e => {
7122                    if (!e.isIntersecting) return;
7123                    play();
7124                    io.unobserve(phone);
7125                });
7126            }, {threshold: .35});
7127            io.observe(phone);
7128
7129            if (coarse) return;
7130
7131            const lean = phone.classList.contains('agent-phone--left') ? -1 : 1;
7132            let queued = false;
7133            const tilt = () => {
7134                queued = false;
7135                const r = phone.getBoundingClientRect();
7136                if (r.bottom < 0 || r.top > innerHeight) return;
7137                // -0.5 above the fold, +0.5 below it
7138                const p = (r.top + r.height / 2 - innerHeight / 2) / innerHeight;
7139                phone.style.setProperty('--ag-tilt', (lean * (3 - p * 4.5)).toFixed(2) + 'deg');
7140                phone.style.setProperty('--ag-sheen', (p * -150).toFixed(1) + '%');
7141            };
7142            addEventListener('scroll', () => {
7143                if (queued) return;
7144                queued = true;
7145                requestAnimationFrame(tilt);
7146            }, {passive: true});
7147            tilt();
7148        });
7149    })();
7150
7151
7152    /* Hero phone. The chips are the data source, so the markup stays the one
7153       place the copy lives. Cycling pauses the moment the visitor takes over,
7154       and never starts at all under prefers-reduced-motion. */
7155    (function () {
7156        const root = document.querySelector('[data-hp-stack]');
7157        if (!root) return;
7158        const chips = [...document.querySelectorAll('[data-hp-chip]')];
7159        if (!chips.length) return;
7160
7161        const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
7162        const icon = document.querySelector('.hpn header img');
7163        const iconSrc = icon ? icon.getAttribute('src') : '';
7164        let i = 0, timer = null, taken = false;
7165
7166        // the phone shows the viewer's own clock, so it reads as their phone
7167        // rather than a screenshot taken at some other time
7168        const clock = () => {
7169            const now = new Date();
7170            const t = document.querySelector('[data-hp-time]');
7171            const d = document.querySelector('[data-hp-date]');
7172            if (t) t.textContent = now.toLocaleTimeString('en-NZ', {hour: 'numeric', minute: '2-digit'})
7173                .replace(/\s?(am|pm)$/i, '');
7174            if (d) d.textContent = now.toLocaleDateString('en-NZ', {weekday: 'long', day: 'numeric', month: 'long'});
7175        };
7176
7177        const AGO = ['now', '2m ago', '8m ago'];
7178
7179        const build = (chip) => {
7180            const frag = document.createDocumentFragment();
7181            // two or three per screen: one card at a time made the phone look
7182            // idle, and a digest is the thing being sold
7183            [['title', 'body'], ['title2', 'body2'], ['title3', 'body3']].forEach((keys, i) => {
7184                const title = chip.dataset[keys[0]], body = chip.dataset[keys[1]];
7185                if (!title) return;
7186                const n = document.createElement('article');
7187                n.className = 'hpn';
7188                n.style.transitionDelay = (i * 620) + 'ms';
7189                n.innerHTML =
7190                    '<header><img src="' + iconSrc + '" alt="" width="18" height="18">' +
7191                    '<span class="hpn-app">Talkify</span><span class="hpn-ago"></span></header>' +
7192                    '<h4></h4><p></p>';
7193                n.querySelector('.hpn-ago').textContent = AGO[i] || 'earlier';
7194                n.querySelector('h4').textContent = title;
7195                n.querySelector('p').textContent = body;
7196                frag.appendChild(n);
7197            });
7198            return frag;
7199        };
7200
7201        const show = (idx) => {
7202            i = (idx + chips.length) % chips.length;
7203            chips.forEach((c, n) => c.classList.toggle('is-on', n === i));
7204            chips.forEach((c, n) => c.setAttribute('aria-selected', n === i ? 'true' : 'false'));
7205            root.replaceChildren(build(chips[i]));
7206            // let the browser paint the start state before transitioning in
7207            requestAnimationFrame(() => requestAnimationFrame(() =>
7208                root.querySelectorAll('.hpn').forEach(n => n.classList.add('is-in'))));
7209        };
7210
7211        const stop = () => { if (timer) { clearInterval(timer); timer = null; } };
7212        const start = () => { if (!reduce && !taken && !timer) timer = setInterval(() => show(i + 1), 7000); };
7213
7214        chips.forEach((chip, n) => {
7215            const take = () => { taken = true; stop(); show(n); };
7216            chip.addEventListener('click', take);
7217            chip.addEventListener('mouseenter', () => { stop(); show(n); });
7218            chip.addEventListener('mouseleave', () => { if (!taken) start(); });
7219        });
7220
7221        // do not animate a phone nobody is looking at
7222        const vis = new IntersectionObserver((es) => {
7223            es.forEach(e => e.isIntersecting ? start() : stop());
7224        }, {threshold: 0.2});
7225        vis.observe(root);
7226
7227        clock();
7228        setInterval(clock, 30000);
7229        show(0);
7230    })();
7231
7232    (function () {
7233        const hero = document.querySelector('.hero-bg');
7234        if (!hero) return;
7235        // Pointer parallax is a mouse affordance: a finger cannot hover, and
7236        // it is exactly the sort of movement prefers-reduced-motion is for.
7237        const mq = (q) => window.matchMedia && window.matchMedia(q).matches;
7238        if (mq('(prefers-reduced-motion: reduce)') || mq('(pointer: coarse)')) return;
7239
7240        let x = 0, y = 0, queued = false;
7241        const paint = () => {
7242            queued = false;
7243            hero.style.transform = `translate(${x}px,${y}px)`;
7244        };
7245        document.addEventListener('mousemove', (e) => {
7246            x = (e.clientX / window.innerWidth - .5) * 24;
7247            y = (e.clientY / window.innerHeight - .5) * 24;
7248            if (!queued) {
7249                queued = true;
7250                requestAnimationFrame(paint);
7251            }
7252        }, {passive: true});
7253    })();
7254
7255    // ─── Live call deck, messages animate in as if the call is happening now ───
7256    (function () {
7257        document.querySelectorAll('.deck').forEach(deck => {
7258            const rows = Array.from(deck.querySelectorAll('.deck-row'));
7259            if (!rows.length) return;
7260
7261            // Insert a typing indicator before each agent row
7262            rows.forEach(row => {
7263                if (row.classList.contains('agent')) {
7264                    const ts = row.querySelector('.ts')?.textContent || '';
7265                    const typing = document.createElement('div');
7266                    typing.className = 'deck-typing';
7267                    typing.innerHTML = `<span class="ts">${ts}</span><span class="who">Talkify</span><span class="dotset"><i></i><i></i><i></i></span>`;
7268                    row.parentNode.insertBefore(typing, row);
7269                }
7270            });
7271
7272            let started = false;
7273            const start = () => {
7274                if (started) return;
7275                started = true;
7276                let t = 400;
7277                rows.forEach(row => {
7278                    if (row.classList.contains('agent')) {
7279                        const typing = row.previousElementSibling;
7280                        if (typing && typing.classList.contains('deck-typing')) {
7281                            setTimeout(() => typing.classList.add('on'), t);
7282                            t += 900;
7283                            setTimeout(() => typing.classList.remove('on'), t);
7284                            t += 200;
7285                        }
7286                    }
7287                    setTimeout(() => row.classList.add('in'), t);
7288                    t += 1200;
7289                });
7290
7291                // After the prepared script plays, optionally append a follow-up exchange
7292                const followup = deck.dataset.followup;
7293                if (followup === 'on') {
7294                    setTimeout(() => {
7295                        appendDeckExchange(deck);
7296                    }, t + 1500);
7297                }
7298            };
7299
7300            const io = new IntersectionObserver(entries => {
7301                entries.forEach(e => {
7302                    if (e.isIntersecting) {
7303                        start();
7304                        io.unobserve(deck);
7305                    }
7306                });
7307            }, {threshold: 0.25});
7308            io.observe(deck);
7309        });
7310
7311        function appendDeckExchange(deck) {
7312            // Append one extra caller + agent exchange to the home hero deck
7313            const followups = [
7314                {
7315                    caller: "One more thing, can my partner come too?",
7316                    agent: "Of course. I'll add them to the appointment. Anything else?"
7317                },
7318                {
7319                    caller: "Is there parking?",
7320                    agent: "Yep, two-hour free parking on Vivian Street, or paid building parking off the lobby."
7321                },
7322            ];
7323            const ex = followups[Math.floor(Math.random() * followups.length)];
7324            const wave = deck.querySelector('.wave');
7325            const insertBefore = wave || deck.querySelector('.deck-foot');
7326
7327            const lastTs = deck.querySelectorAll('.deck-row .ts');
7328            const baseSec = parseInt((lastTs[lastTs.length - 1]?.textContent || '00:14').split(':')[1]) + 6;
7329            const fmtTs = s => `00:${String(s).padStart(2, '0')}`;
7330
7331            const callerRow = document.createElement('div');
7332            callerRow.className = 'deck-row caller';
7333            callerRow.innerHTML = `<span class="ts">${fmtTs(baseSec)}</span><span class="who">Caller</span><span class="msg">${ex.caller}</span>`;
7334            deck.insertBefore(callerRow, insertBefore);
7335
7336            const typingRow = document.createElement('div');
7337            typingRow.className = 'deck-typing';
7338            typingRow.innerHTML = `<span class="ts">${fmtTs(baseSec + 2)}</span><span class="who">Talkify</span><span class="dotset"><i></i><i></i><i></i></span>`;
7339            deck.insertBefore(typingRow, insertBefore);
7340
7341            const agentRow = document.createElement('div');
7342            agentRow.className = 'deck-row agent';
7343            agentRow.innerHTML = `<span class="ts">${fmtTs(baseSec + 3)}</span><span class="who">Talkify</span><span class="msg">${ex.agent}</span>`;
7344            deck.insertBefore(agentRow, insertBefore);
7345
7346            requestAnimationFrame(() => callerRow.classList.add('in'));
7347            setTimeout(() => typingRow.classList.add('on'), 1100);
7348            setTimeout(() => typingRow.classList.remove('on'), 2400);
7349            setTimeout(() => agentRow.classList.add('in'), 2500);
7350        }
7351    })();
7352
7353    // ─── Real conversations, bubbles type into existence as user scrolls in ───
7354    (function () {
7355        document.querySelectorAll('.convo').forEach(convo => {
7356            const bubs = Array.from(convo.querySelectorAll('.bub'));
7357            if (!bubs.length) return;
7358
7359            let started = false;
7360            const start = () => {
7361                if (started) return;
7362                started = true;
7363
7364                let t = 200;
7365                bubs.forEach((bub) => {
7366                    // Show typing indicator with the same alignment + colour, then swap to bubble
7367                    const typing = document.createElement('div');
7368                    typing.className = 'convo-typing' + (bub.classList.contains('caller') ? ' caller' : '');
7369                    const who = bub.classList.contains('caller') ? 'Caller' : 'Talkify';
7370                    typing.innerHTML = `<span class="lbl">${who}</span><span class="dotset"><i></i><i></i><i></i></span>`;
7371                    convo.insertBefore(typing, bub);
7372
7373                    const typingMs = bub.classList.contains('caller') ? 500 : 800;
7374                    setTimeout(() => typing.classList.add('on'), t);
7375                    t += typingMs;
7376                    setTimeout(() => {
7377                        typing.classList.remove('on');
7378                        typing.remove();
7379                    }, t);
7380                    setTimeout(() => bub.classList.add('in'), t + 50);
7381                    t += 450; // settle time before next message
7382                });
7383            };
7384
7385            /* Watch the transcript's wrapper where it has one. On the home page
7386               the transcript sits inside a phone, and a clipped flex child that
7387               deep gets no intersection entries at all, so a threshold against
7388               the transcript itself never fires and the conversation never
7389               starts. The wrapper is an ordinary block in normal flow. */
7390            const target = convo.closest('.convo-device') || convo;
7391            const io = new IntersectionObserver(entries => {
7392                entries.forEach(e => {
7393                    if (e.isIntersecting) {
7394                        start();
7395                        io.unobserve(target);
7396                    }
7397                });
7398            }, {threshold: 0.2});
7399            io.observe(target);
7400        });
7401    })();
7402
7403    // ─── Live PA digest, notifications drop in on scroll, more arrive as you watch ───
7404    (function () {
7405        document.querySelectorAll('.pa-floater').forEach(floater => {
7406            const initialRows = Array.from(floater.querySelectorAll('.row'));
7407            if (!initialRows.length) return;
7408
7409            const queue = [
7410                {
7411                    lbl: 'Returning client · routed',
7412                    name: 'Liam, message taken for Tom',
7413                    meta: '<span class="vip" style="color:var(--mute)">● Routine</span>'
7414                },
7415                {
7416                    lbl: 'New booking',
7417                    name: 'Te Aroha · Saturday haircut',
7418                    meta: '<span class="vip" style="color:var(--signal)">● Booked</span>'
7419                },
7420                {
7421                    lbl: 'Urgent · escalated to mobile',
7422                    name: 'Maria @ Hartwell, sent to your phone',
7423                    meta: '<span class="vip" style="color:var(--coral)">● VIP</span>'
7424                },
7425                {lbl: 'Quietly handled', name: '14 vendors politely declined', meta: ''},
7426            ];
7427            let qIdx = 0;
7428            let started = false;
7429
7430            const start = () => {
7431                if (started) return;
7432                started = true;
7433                initialRows.forEach((row, i) => {
7434                    setTimeout(() => {
7435                        row.classList.add('in', 'ping');
7436                        setTimeout(() => row.classList.remove('ping'), 1400);
7437                    }, i * 1200 + 400);
7438                });
7439
7440                // After initial settle, push a new notification every 9 seconds
7441                const settled = initialRows.length * 1200 + 2000;
7442                setTimeout(() => {
7443                    const interval = setInterval(() => {
7444                        if (!floater.isConnected) {
7445                            clearInterval(interval);
7446                            return;
7447                        }
7448                        const item = queue[qIdx % queue.length];
7449                        qIdx++;
7450                        const newRow = document.createElement('div');
7451                        newRow.className = 'row in fresh ping';
7452                        newRow.innerHTML = `
7453            <span class="lbl">${item.lbl}</span>
7454            <span class="name">${item.name}</span>
7455            ${item.meta ? '<span>' + item.meta + '</span>' : ''}
7456          `;
7457                        floater.insertBefore(newRow, floater.firstChild);
7458
7459                        // Drop the oldest if we have too many, keep card from growing
7460                        const all = floater.querySelectorAll('.row');
7461                        if (all.length > 4) {
7462                            const oldest = all[all.length - 1];
7463                            oldest.style.transition = 'opacity .5s ease, transform .5s ease, max-height .5s ease, margin .5s ease, padding .5s ease';
7464                            oldest.style.opacity = '0';
7465                            oldest.style.transform = 'translateY(8px)';
7466                            setTimeout(() => oldest.remove(), 600);
7467                        }
7468
7469                        setTimeout(() => newRow.classList.remove('ping'), 1400);
7470                    }, 9000);
7471                }, settled);
7472            };
7473
7474            const io = new IntersectionObserver(entries => {
7475                entries.forEach(e => {
7476                    if (e.isIntersecting) {
7477                        start();
7478                        io.unobserve(floater);
7479                    }
7480                });
7481            }, {threshold: 0.3});
7482            io.observe(floater);
7483        });
7484    })();
7485
7486    // ─── Conversion + engagement events → GA4 / GTM dataLayer ───
7487    // Every tel: tap, CTA click and lead form submit lands in the dataLayer so
7488    // GTM/GA4 can build conversions without touching the templates again.
7489    (function () {
7490        const page = "pricing";
7491        const push = (event, params) => {
7492            window.dataLayer = window.dataLayer || [];
7493            window.dataLayer.push(Object.assign({event: event, page_key: page}, params || {}));
7494        };
7495
7496        // Phone taps: the demo line and the sign-up lines are separate conversions.
7497        // The demo lines come from App\Services\Market (they differ by country
7498        // and by how a visitor has to dial them), matched on their last eight
7499        // digits so the local and the international form are the same line.
7500                const demoTails = ["32421262","92420020"];
7501        document.querySelectorAll('a[href^="tel:"]').forEach(a => {
7502            a.addEventListener('click', () => {
7503                const num = (a.getAttribute('href') || '').replace('tel:', '');
7504                const digits = num.replace(/\D/g, '');
7505                const isDemo = demoTails.some(t => t && digits.endsWith(t));
7506                push(isDemo ? 'demo_call_click' : 'phone_signup_click', {
7507                    phone_number: num,
7508                    link_text: (a.textContent || '').trim().slice(0, 80),
7509                });
7510            });
7511        });
7512
7513        // CTA buttons (primary/blue/ghost), which CTA, on which page
7514        document.querySelectorAll('a.btn').forEach(a => {
7515            a.addEventListener('click', () => {
7516                push('cta_click', {
7517                    cta_text: (a.textContent || '').trim().slice(0, 80),
7518                    cta_style: a.classList.contains('btn-primary') ? 'primary'
7519                        : a.classList.contains('btn-blue') ? 'blue' : 'ghost',
7520                    cta_href: a.getAttribute('href') || '',
7521                });
7522            });
7523        });
7524
7525        // Lead forms: signup/contact, live demo call, support
7526        document.querySelectorAll('form').forEach(form => {
7527            const action = form.getAttribute('action') || '';
7528            let event = null;
7529            if (action.includes('/signup/verify')) event = 'sign_up';
7530            else if (action.includes('/signup/send-code')) event = 'sign_up_start';
7531            else if (action.includes('/contact')) event = 'generate_lead';
7532            else if (action.includes('/demo')) event = 'demo_call_request';
7533            else if (action.includes('/support')) event = 'support_request';
7534            if (!event) return;
7535            form.addEventListener('submit', () => {
7536                const agent = form.querySelector('input[name="agent_type"]:checked');
7537                push(event, {
7538                    form_action: action,
7539                    agent_type: agent ? agent.value : undefined,
7540                });
7541            });
7542        });
7543    })();
7544
7545    /* Agents mega-menu. Desktop opens it on hover/focus via CSS; this handles
7546       the click path, which is the only way in on touch, plus Escape and
7547       click-outside. */
7548    (function () {
7549        const drops = document.querySelectorAll('[data-nav-drop]');
7550        if (!drops.length) return;
7551
7552        const closeAll = (except) => drops.forEach((drop) => {
7553            if (drop === except) return;
7554            drop.classList.remove('is-open');
7555            drop.querySelector('.nav-drop-btn')?.setAttribute('aria-expanded', 'false');
7556        });
7557
7558        drops.forEach((drop) => {
7559            const trigger = drop.querySelector('.nav-drop-btn');
7560            if (!trigger) return;
7561
7562            trigger.addEventListener('click', (event) => {
7563                event.preventDefault();
7564                event.stopPropagation();
7565                const open = drop.classList.toggle('is-open');
7566                trigger.setAttribute('aria-expanded', open ? 'true' : 'false');
7567                closeAll(drop);
7568            });
7569        });
7570
7571        document.addEventListener('click', (event) => {
7572            if (!event.target.closest('[data-nav-drop]')) closeAll();
7573        });
7574
7575        document.addEventListener('keydown', (event) => {
7576            if (event.key === 'Escape') closeAll();
7577        });
7578
7579        window.talkifyCloseNavDrops = closeAll;
7580    })();
7581
7582    (function () {
7583        const btn = document.querySelector('.menu-btn');
7584        const nav = document.querySelector('.nav ul');
7585        if (!btn || !nav) return;
7586        btn.addEventListener('click', () => {
7587            const open = nav.style.display === 'flex';
7588            // Collapsing the menu should not leave the Agents accordion open
7589            // behind it, or it reappears expanded next time.
7590            if (open && window.talkifyCloseNavDrops) window.talkifyCloseNavDrops();
7591            nav.style.display = open ? 'none' : 'flex';
7592            nav.style.position = 'fixed';
7593            nav.style.top = '92px';
7594            nav.style.left = '20px';
7595            nav.style.right = '20px';
7596            nav.style.flexDirection = 'column';
7597            nav.style.background = 'var(--ink-2)';
7598            nav.style.border = '1px solid var(--line)';
7599            nav.style.borderRadius = '14px';
7600            nav.style.padding = '12px';
7601            nav.style.zIndex = '85';
7602        });
7603    })();
7604
7605    /* Theme toggle, persist choice, flip data-theme on <html> */
7606    (function () {
7607        var toggles = document.querySelectorAll('[data-theme-toggle]');
7608        if (!toggles.length) return;
7609        toggles.forEach(function (btn) {
7610            btn.addEventListener('click', function () {
7611                var current = document.documentElement.getAttribute('data-theme') === 'light' ? 'light' : 'dark';
7612                var next = current === 'light' ? 'dark' : 'light';
7613                document.documentElement.setAttribute('data-theme', next);
7614                try {
7615                    localStorage.setItem('talkify-theme', next);
7616                } catch (e) {
7617                }
7618            });
7619        });
7620    })();
7621</script>
vendor: 1 bytes, line 7621
7621
7622<script>
7623(function(){
7624  document.querySelectorAll('[data-calc-grid]').forEach(grid => {
7625    const range = grid.querySelector('[data-calc-range]');
7626    const teamEl = grid.querySelector('[data-calc-team]');
7627    const intsEl = grid.querySelector('[data-calc-ints]');
7628    const priceEl = grid.querySelector('[data-calc-price]');
7629    const planEl = grid.querySelector('[data-calc-plan]');
7630    const minsEl = grid.querySelector('[data-calc-mins]');
7631    const concEl = grid.querySelector('[data-calc-conc]');
7632    const numEl = grid.querySelector('[data-calc-num]');
7633    const descEl = grid.querySelector('[data-calc-desc]');
7634    const foundingEl = grid.querySelector('[data-calc-founding]');
7635    const wasEl = grid.querySelector('[data-calc-was]');
7636    const usageEl = grid.querySelector('[data-calc-usage]');
7637    const extraEl = grid.querySelector('[data-calc-extra]');
7638    const pills = grid.querySelectorAll('.int-pill');
7639    let intCount = 0;
7640
7641    const TEXTS = 'Each number includes 50 texts a month, then 9c each.';
7642    const PA_TEXTS = 'Includes 20 texts a month, then 9c each.';
7643    const OVERAGE = " a minute (20c after your first 3 months). ";
7644    // Blank when the plan is not actually discounted: the JS hides the
7645    // crossed-out price and its founding tag whenever `was` is empty.
7646    const PA_WAS = "";
7647    const BIZ_WAS = "$199/mo";
7648    const BUSINESS_ONLY = false;
7649
7650    // The slider counts agents on ONE number. The Broadcast price covers up
7651    // to three of them; each agent past three adds the flat extra-agent rate.
7652    const INCLUDED_AGENTS = 3;
7653    const EXTRA_RATE = 39;
7654    const BIZ_RATE = 129;
7655    const BIZ_MINS = 200;
7656    const money = n => '$' + (Math.round(n * 100) / 100).toLocaleString('en-NZ', {minimumFractionDigits: n % 1 ? 2 : 0, maximumFractionDigits: 2});
7657
7658    function recalc(){
7659      const agents = parseInt(range.value);
7660      teamEl.textContent = agents;
7661      intsEl.textContent = intCount;
7662      let plan, price, was, mins, conc, num, desc, usage;
7663      num = '1';
7664      conc = '3 calls';
7665      if(!BUSINESS_ONLY && agents === 1){
7666        plan='Shortwave · PA'; price='$89'; was=PA_WAS; mins='50/mo';
7667        // The apostrophe in "person's" MUST stay escaped. Unescaped it closes
7668        // this single-quoted string, which is a syntax error that takes the
7669        // whole IIFE down with it, so no listeners bind and the agent slider
7670        // silently does nothing on all 24 pages that include this partial.
7671        desc='Shortwave is the Personal Assistant plan: one person\'s own mobile or landline, screened and answered. For a business number with reception, pick Broadcast.';
7672        usage='Includes 50 minutes a month, then 10c'+OVERAGE+PA_TEXTS;
7673      } else if(agents <= 10){
7674        // Up to three agents ride inside the plan price; the rest are the
7675        // flat extra-agent rate each.
7676        const extras = Math.max(0, agents - INCLUDED_AGENTS);
7677        const total = BIZ_RATE + extras * EXTRA_RATE;
7678        plan='Broadcast'; price=money(total); was = agents <= INCLUDED_AGENTS ? BIZ_WAS : '';
7679        mins=BIZ_MINS+'/mo';
7680        desc = agents <= INCLUDED_AGENTS
7681          ? (agents === 1
7682              ? 'Broadcast fits most growing NZ businesses. One number, up to '+INCLUDED_AGENTS+' agents on it, three callers at once.'
7683              : agents + ' agents sharing one number, all inside the one plan price ('+INCLUDED_AGENTS+' are included).')
7684          : agents + ' agents on one number: '+INCLUDED_AGENTS+' included in the plan, '+extras+' extra at '+money(EXTRA_RATE)+' a month each.';
7685        usage='Includes '+BIZ_MINS+' minutes a month, then 10c'+OVERAGE+TEXTS;
7686      } else {
7687        plan='Fleet'; price='Custom'; was=''; mins='Unlimited'; conc='Unlimited'; num='Unlimited';
7688        desc='Fleet is right for multi-location operators and contact centres. SLA-backed, NZ data residency, dedicated voice clone.';
7689        usage='Minutes, calls and texts are set in your custom Fleet quote.';
7690      }
7691      priceEl.textContent = price;
7692      planEl.textContent = plan;
7693      minsEl.textContent = mins;
7694      concEl.textContent = conc;
7695      numEl.textContent = num;
7696      descEl.textContent = desc;
7697      if(usageEl) usageEl.textContent = usage;
7698      // Fleet is quoted per account, so the extra-agent rate does not apply
7699      if(extraEl) extraEl.style.display = (plan === 'Fleet') ? 'none' : '';
7700      if(foundingEl){
7701        foundingEl.style.display = was ? 'flex' : 'none';
7702        if(was && wasEl) wasEl.textContent = was;
7703      }
7704    }
7705    range.addEventListener('input', recalc);
7706    pills.forEach(p => p.addEventListener('click', ()=>{
7707      p.classList.toggle('on');
7708      intCount = grid.querySelectorAll('.int-pill.on').length;
7709      recalc();
7710    }));
7711  });
7712})();
7713</script>
7713
7714
7715</body>
7716</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.