PageSourceSearch

https://talkify.nz/fish-and-chip-shop

html talkify.nz collected 2026-10-02 00:38:48 UTC 269,559 bytes, 7,055 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>AI Phone Answering for Fish &amp; Chip Shops NZ &amp; AU · Talkify</title>
29    <meta name="description"
30          content="Your chippie&#039;s phone rings flat out from five o&#039;clock and nobody can leave the fryer. Talkify answers every call, takes the order with the salt and sauces on it, and puts it on a screen by the till. From $10/month.">
31
32    
33                    <link rel="icon" type="image/x-icon" href="/favicon.ico">
34    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
35    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
36    <link rel="apple-touch-icon" sizes="180x180" href="/media/branding/brand/app-icon-180.png">
37    <link rel="manifest" href="/site.webmanifest">
38    
39    <meta name="theme-color" content="#318abe">
40
41    <meta property="og:type" content="website">
42    <meta property="og:url" content="https://talkify.nz/fish-and-chip-shop">
43    <meta property="og:site_name" content="Talkify">
44    <meta property="og:title" content="AI Phone Answering for Fish &amp; Chip Shops NZ &amp; AU · Talkify">
45    <meta property="og:description"
46          content="Your chippie&#039;s phone rings flat out from five o&#039;clock and nobody can leave the fryer. Talkify answers every call, takes the order with the salt and sauces on it, and puts it on a screen by the till. From $10/month.">
47        <meta property="og:image" content="https://talkify.nz/media/frontend/fish-and-chips.jpg">
48    
49    <meta property="og:image:width" content="1200">
50    <meta property="og:image:height" content="630">
51    <meta property="og:image:type" content="image/jpeg">
52    <meta property="og:image:alt"
53          content="A New Zealand fish and chip shop counter at teatime while Talkify takes a phone order.">
54    
55    <meta property="og:locale" content="en_NZ">
56
57    <meta name="twitter:card" content="summary_large_image">
58    <meta name="twitter:title" content="AI Phone Answering for Fish &amp; Chip Shops NZ &amp; AU · Talkify">
59    <meta name="twitter:description"
60          content="Your chippie&#039;s phone rings flat out from five o&#039;clock and nobody can leave the fryer. Talkify answers every call, takes the order with the salt and sauces on it, and puts it on a screen by the till. From $10/month.">
61    <meta name="twitter:image" content="https://talkify.nz/media/frontend/fish-and-chips.jpg">
62    <meta name="facebook-domain-verification" content="ic2puw1bkz233rscxrhcl0qol7suu1"/>
63    
64        
64<script
65        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>
65
66
67    
67<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Talkify","item":"https://talkify.nz"},{"@type":"ListItem","position":2,"name":"Industries","item":"https://talkify.nz/industries"},{"@type":"ListItem","position":3,"name":"Fish & Chip Shops","item":"https://talkify.nz/fish-and-chip-shop"}]},{"@type":"Service","name":"AI Phone Answering for Fish and Chip Shops","description":"AI phone answering for fish and chip shops in New Zealand and Australia. Answers every call through the teatime rush, takes the order with the salt, sauces and changes written on each line, quotes the current wait, and puts it on a screen by the till.","url":"https://talkify.nz/fish-and-chip-shop","provider":{"@id":"https://talkify.nz#organization"},"areaServed":[{"@type":"Country","name":"New Zealand"},{"@type":"Country","name":"Australia"}],"serviceType":"AI Phone Answering Service","audience":{"@type":"BusinessAudience","audienceType":"Fish & Chip Shops"},"offers":{"@type":"Offer","price":"129","priceCurrency":"NZD","description":"Business agents from $129/month at the founding rate for your first 3 months, then $199. No setup fee, no lock-in."}},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Our phone goes flat out from five. Can it really keep up?","acceptedA
67nswer":{"@type":"Answer","text":"It answers every call at once, which is the part a person cannot do. Four people ringing at ten past six all get answered on the second ring rather than three of them getting a busy tone and trying the shop up the road. Each one gets its own ticket on your screen, in the order they came in."}},{"@type":"Question","name":"Will it get the order right? Chips are not simple.","acceptedAnswer":{"@type":"Answer","text":"Anything the customer asks for on a particular item is written on that line in their own words. Chicken salt on the chips, no vinegar, extra tartare, scallops well done. It reads the order back before it sends it, and if they change their mind halfway through it updates the same ticket rather than starting another."}},{"@type":"Question","name":"We do not have a menu system. Do we need one?","acceptedAnswer":{"@type":"Answer","text":"No, and that is the point. Put your menu and your prices into your agent once, in whatever form you have them, and it can tell a caller what you do and what it costs as well as taking the order. The order lands on a screen you already own: a tablet, an old laptop, a spare monitor with a browser."}},{"@type":"Question","name":"Can it tell people how long the wait is?","acceptedA
67nswer":{"@type":"Answer","text":"Yes, and this is the one your customers will notice. Tap a time on the screen and the agent quotes it to everyone who rings after that. When the fryers are backed up you change it to forty minutes and nobody is promised fifteen. It clears itself after a few hours so a busy Friday figure is never still being quoted on a quiet Tuesday."}},{"@type":"Question","name":"What if we run out of something?","acceptedAnswer":{"@type":"Answer","text":"Type it on the screen once. \"No oysters tonight.\" The agent tells the callers it actually affects and offers them something else, and says nothing about it to the ones who never asked."}},{"@type":"Question","name":"Do we have to ring people back when it is ready?","acceptedAnswer":{"@type":"Answer","text":"Only if you want to. Tap the ticket when the order is going in the bag and the customer gets a message saying it is ready, already written with their name on it. It goes by WhatsApp when they have it, which is free, and as a text when they do not."}},{"@type":"Question","name":"Does it take card payments over the phone?","acceptedA
67nswer":{"@type":"Answer","text":"No. Talkify never handles card details. Customers pay at the counter the way they do now, which is also what stops a phone order becoming a chargeback argument."}},{"@type":"Question","name":"We are in Australia. Does this work over here?","acceptedAnswer":{"@type":"Answer","text":"Yes. Talkify runs on both sides of the Tasman, with Australian numbers answered in Australian data centres and New Zealand numbers in New Zealand ones. The agent speaks the way your customers do, and the screen works the same either way."}},{"@type":"Question","name":"What does it cost?","acceptedAnswer":{"@type":"Answer","text":"Two ways. Pay as you go is $10 a month for the number plus $1 a minute, which suits a shop whose phone goes in bursts. A reception agent is $129/month at the founding rate for your first 3 months, then $199 flat. The screen is $59 a month on top of either. No setup fee and no lock in."}}]}]}</script>
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    <link rel="canonical" href="https://talkify.nz/fish-and-chip-shop">
5169</head>
5170<body data-page="industry-fish-and-chips">
5171<!-- Google Tag Manager (noscript) -->
vendor: 73 bytes, lines 5171-5173
5171
5172<noscript>
5173    <iframe src="https://www.googletagmanager.com/ns.html?id=
5173GTM-TTGHDLQ4
vendor: 97 bytes, lines 5173-5176
5173"
5174            height="0" width="0" style="display:none;visibility:hidden"></iframe>
5175</noscript>
5176
5177<!-- End Google Tag Manager (noscript) -->
5178<div class="grain"></div>
5179<div class="scanlines"></div>
5180<div class="vignette"></div>
5181
5182<nav class="nav">
5183  
5184  <a href="https://talkify.nz" class="logo" aria-label="Talkify, home">
5185    <svg class="tk-logo" viewBox="-3 -3 317.81 106"
5186     width="113.93" height="38"
5187     xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Talkify" focusable="false">
5188            <defs>
5189            <linearGradient id="tkgw8PHrf" gradientUnits="userSpaceOnUse" x1="8" y1="92" x2="92" y2="8">
5190                <stop offset="0" stop-color="#318abe"/>
5191                <stop offset="1" stop-color="#a3d654"/>
5192            </linearGradient>
5193        </defs>
5194        <circle cx="50" cy="50" r="50" fill="url(#tkgw8PHrf)"/>
5195    
5196    <g fill="none" stroke="#ffffff" stroke-width="10" stroke-linecap="round">
5197        <path d="M34 26 V54 C34 74 62 80 76 62"/>
5198        <path d="M20 40 H46"/>
5199    </g>
5200    
5201    <g transform="translate(56 20) scale(0.30)">
5202        <g class="tk-eye">
5203            <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"/>
5204        </g>
5205    </g>
5206            <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"/>
5207        
5208        <g transform="translate(231.30 6.84) scale(0.216)">
5209            <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"
5210                  fill="#a3d654"/>
5211        </g>
5212    </svg>
5213  </a>
5214  <ul>
5215    <li class="nav-drop" data-nav-drop>
5216      <button type="button" class="nav-drop-btn "
5217              aria-expanded="false" aria-controls="nav-agents-menu" aria-haspopup="true">
5218        <span class="dot"></span>Agents
5219        <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>
5220      </button>
5221
5222      
5223      <div class="nav-drop-panel" id="nav-agents-menu">
5224        <div class="nav-drop-col">
5225          <span class="nav-drop-hd">Answering calls</span>
5226          <a href="https://talkify.nz/reception"><span>Reception</span><em>Answers every call, books the job</em></a>
5227          <a href="https://talkify.nz/personal-assistant"><span>Personal Assistant</span><em>Your own PA on the phone</em></a>
5228          <a href="https://talkify.nz/booking-service"><span>Booking Service</span><em>Fills the diary while you work</em></a>
5229          <a href="https://talkify.nz/front-counter"><span>Front Counter</span><em>Orders and bookings on a screen by the till</em></a>
5230          <a href="https://talkify.nz/ai-call-centre"><span>AI Call Centre</span><em>5, 10 or 15 lines at once</em></a>
5231          <span class="nav-drop-hd" style="margin-top:18px">Other channels</span>
5232          <a href="https://talkify.nz/website-chat"><span>Website Chat</span><em>The same agent, in a chat box on your site</em></a>
5233          <a href="https://talkify.nz/calendar"><span>Calendar</span><em>The diary the agent books into</em></a>
5234          <a href="https://talkify.nz/lead-management"><span>Leads</span><em>Every enquiry on one board, whatever door it came through</em></a>
5235                    <a href="https://talkify.nz/agent-coach"><span>Coach</span><em>Your agent listens back to its own calls</em></a>
5236                  </div>
5237        <div class="nav-drop-col">
5238          <span class="nav-drop-hd">Ringing out</span>
5239          <a href="https://talkify.nz/sales-agent"><span>Sales Agent</span><em>Qualifies and follows up leads</em></a>
5240          <a href="https://talkify.nz/outbound-calls"><span>Outbound Calls</span><em>Campaigns, reminders, win-backs</em></a>
5241          <a href="https://talkify.nz/ai-marketing-campaigns"><span>Marketing Campaigns</span><em>Offers, launches and reviews, by phone</em></a>
5242          <a href="https://talkify.nz/ai-phone-surveys"><span>Campaign Agent</span><em>Rings your list, asks your questions, reports back</em></a>
5243          <a href="https://talkify.nz/debt-collection"><span>Debt Collection</span><em>Chases overdue invoices from Xero</em></a>
5244          <a href="https://talkify.nz/ai-wellness-checks"><span>Wellness Checks</span><em>Rings to check somebody is alright</em></a>
5245          
5246          <a href="https://talkify.nz/dialler"><span>Dialler</span><em>Your own team ringing out, from the browser</em></a>
5247          <a href="https://talkify.nz/agents" class="nav-drop-all">See all agents <span class="arr">&rarr;</span></a>
5248        </div>
5249      </div>
5250    </li>
5251    
5252    <li class="nav-drop" data-nav-drop>
5253      <button type="button" class="nav-drop-btn is-active"
5254              aria-expanded="false" aria-controls="nav-industries-menu" aria-haspopup="true">
5255        <span class="dot"></span>Industries
5256        <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>
5257      </button>
5258
5259      
5260      <div class="nav-drop-panel nav-drop-panel--industries" id="nav-industries-menu">
5261        <div class="nav-drop-col">
5262          <span class="nav-drop-hd">Trades</span>
5263          <a href="https://talkify.nz/tradesman">All Trades</a>
5264          <a href="https://talkify.nz/builder">Builders</a>
5265          <a href="https://talkify.nz/electrician">Electricians</a>
5266          <a href="https://talkify.nz/hvac">Heat Pump &amp; HVAC</a>
5267          <a href="https://talkify.nz/landscaping">Landscaping</a>
5268          <a href="https://talkify.nz/automotive">Mechanics</a>
5269          <a href="https://talkify.nz/pest-control">Pest Control</a>
5270          <a href="https://talkify.nz/plumber">Plumbing</a>
5271        </div>
5272        <div class="nav-drop-col">
5273          <span class="nav-drop-hd">Health &amp; beauty</span>
5274          <a href="https://talkify.nz/barber">Barbers</a>
5275          <a href="https://talkify.nz/beauty">Beauty &amp; Wellness</a>
5276          <a href="https://talkify.nz/gym">Gyms &amp; Studios</a>
5277          <a href="https://talkify.nz/personal-trainer">Personal Trainers</a>
5278          <a href="https://talkify.nz/physio">Physio &amp; Clinics</a>
5279          <span class="nav-drop-hd" style="margin-top:18px">Office &amp; property</span>
5280          <a href="https://talkify.nz/accountant">Accountants</a>
5281          <a href="https://talkify.nz/professional-services">Professional Services</a>
5282          <a href="https://talkify.nz/real-estate">Real Estate</a>
5283          <a href="https://talkify.nz/retail">Retail</a>
5284        </div>
5285        <div class="nav-drop-col">
5286          <span class="nav-drop-hd">Food &amp; hospitality</span>
5287          <a href="https://talkify.nz/cafe">Cafes</a>
5288          <a href="https://talkify.nz/chinese-takeaway">Chinese Takeaways</a>
5289          <a href="https://talkify.nz/fish-and-chip-shop">Fish &amp; Chip Shops</a>
5290          <a href="https://talkify.nz/hotel">Hotels &amp; Motels</a>
5291          <a href="https://talkify.nz/pizza-shop">Pizza Shops</a>
5292          <a href="https://talkify.nz/restaurant-bookings">Restaurants</a>
5293          <a href="https://talkify.nz/industries" class="nav-drop-all">See all industries <span class="arr">&rarr;</span></a>
5294        </div>
5295      </div>
5296    </li>
5297    <li class="nav-drop" data-nav-drop>
5298      <button type="button" class="nav-drop-btn "
5299              aria-expanded="false" aria-controls="nav-integrations-menu" aria-haspopup="true">
5300        <span class="dot"></span>Integrations
5301        <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>
5302      </button>
5303
5304      <div class="nav-drop-panel nav-drop-panel--single" id="nav-integrations-menu">
5305        <div class="nav-drop-col">
5306          <span class="nav-drop-hd">Plugs into</span>
5307          <a href="https://talkify.nz/integrations"><span>All integrations</span><em>The software the agent already talks to</em></a>
5308          <a href="https://talkify.nz/business-phone-lines"><span>Phone Lines</span><em>Numbers, porting and how calls reach us</em></a>
5309        </div>
5310      </div>
5311    </li>
5312    <li><a href="https://talkify.nz/pricing" class=""><span class="dot"></span>Pricing</a></li>
5313    <li><a href="https://talkify.nz/blog" class=""><span class="dot"></span>Journal</a></li>
5314        <li><a href="https://talkify.nz/signup" class=""><span class="dot"></span>Get started</a></li>
5315      </ul>
5316  <div class="actions">
5317    <button type="button" class="theme-toggle" data-theme-toggle aria-label="Switch between light and dark theme" title="Switch theme">
5318      <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>
5319      <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>
5320    </button>
5321            
5322        <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>
5323        <a href="tel:+64800002967" class="num num-call" title="Call us on 0800 002 967" aria-label="Call us on 0800 002 967">
5324      <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>
5325    </a>
5326              <a href="https://talkify.nz/login" class="num" style="font-family:var(--sans);font-size:13px;color:var(--bone)">Sign in</a>
5327      <a href="https://talkify.nz/signup" class="btn btn-primary">Start free <span class="arr">→</span></a>
5328        <button class="menu-btn" aria-label="Open menu">
5329      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
5330    </button>
5331  </div>
5332</nav>
5333
5334
5335<section class="hero">
5336  <div class="hero-bg"><div class="glow1"></div><div class="glow2"></div><div class="grid-lines"></div></div>
5337
5338  <div class="hero-shell">
5339    <div>
5340      <div class="crumb"><a href="https://talkify.nz">Talkify</a> <span>/</span> <a href="https://talkify.nz/industries">Industries</a> <span>/</span> <span style="color:var(--paper)">Fish &amp; Chip Shops</span></div>
5341
5342      <span class="eyebrow" style="margin-top:18px"><span class="pin"></span>Takeaway · Orders on a screen · NZ &amp; AU</span>
5343
5344      <h1 class="display">
5345        <span class="ln"><span>The phone rings</span></span>
5346        <span class="ln"><span class="out">at ten past six.</span></span>
5347        <span class="ln"><span class="it">Nobody can leave the fryer.</span></span>
5348      </h1>
5349
5350      <p class="hero-sub">So it rings out, and that order goes to the shop up the road. Talkify answers every call, takes the order, and puts it on a screen by your till.</p>
5351
5352      <div class="hero-cta">
5353        <a href="#signup" class="btn btn-primary btn-lg">Set up your shop <span class="arr">→</span></a>
5354        <a href="#pricing" class="btn btn-ghost btn-lg">What it costs</a>
5355      </div>
5356
5357      <dl class="hero-meta">
5358        <div><dt>Answers</dt><dd>
5358Every call</dd></div>
5359        <div><dt>Order lands</dt><dd>Mid-call</dd></div>
5360        <div><dt>From</dt><dd>$10<small>/mo</small></dd></div>
5361        <div><dt>Setup fee</dt><dd>$0</dd></div>
5362      </dl>
5363    </div>
5364
5365    <figure class="hero-photo" style="--shot-dark:url('https://talkify.nz/media/frontend/fish-and-chips.jpg')" aria-label="A New Zealand fish and chip shop counter at teatime, wrapped parcels on the bench, while an order arrives on a tablet screen">
5366      <span class="corner">Order 0148 · 2 scoops</span>
5367      <figcaption class="caption">
5368        <div class="title">Four calls at once.<br><span class="it">Four orders on the screen.</span></div>
5369        <div class="stat">6:10pm<b>None missed</b></div>
5370      </figcaption>
5371    </figure>
5372  </div>
5373</section>
5374
5375<div class="strip">
5376  <div class="strip-track">
5377                                    <a href="https://talkify.nz/reception" class="strip-link" >
5378            Reception <span class="pip">●</span>          </a>
5379                                        <a href="https://talkify.nz/personal-assistant" class="strip-link it" >
5380            Personal Assistant          </a>
5381                                        <a href="https://talkify.nz/booking-service" class="strip-link" >
5382            Booking Service <span class="pip">●</span>          </a>
5383                                        <a href="https://talkify.nz/sales-agent" class="strip-link it" >
5384            Sales Qualification          </a>
5385                                        <a href="https://talkify.nz/tradesman" class="strip-link it" >
5386            Tradesman Dispatcher          </a>
5387                                        <a href="https://talkify.nz/real-estate" class="strip-link" >
5388            Real Estate Enquiry <span class="pip">●</span>          </a>
5389                                        <a href="https://talkify.nz/beauty" class="strip-link it" >
5390            Beauty &amp; Wellness          </a>
5391                                        <a href="https://talkify.nz/plumber" class="strip-link" >
5392            Plumbing Dispatch <span class="pip">●</span>          </a>
5393                                        <a href="https://talkify.nz/retail" class="strip-link it" >
5394            Retail          </a>
5395                                        <a href="https://talkify.nz/professional-services" class="strip-link" >
5396            Professional Services <span class="pip">●</span>          </a>
5397                                                  <a href="https://talkify.nz/reception" class="strip-link"  aria-hidden="true" tabindex="-1" >
5398            Reception <span class="pip">●</span>          </a>
5399                                        <a href="https://talkify.nz/personal-assistant" class="strip-link it"  aria-hidden="true" tabindex="-1" >
5400            Personal Assistant          </a>
5401                                        <a href="https://talkify.nz/booking-service" class="strip-link"  aria-hidden="true" tabindex="-1" >
5402            Booking Service <span class="pip">●</span>          </a>
5403                                        <a href="https://talkify.nz/sales-agent" class="strip-link it"  aria-hidden="true" tabindex="-1" >
5404            Sales Qualification          </a>
5405                                        <a href="https://talkify.nz/tradesman" class="strip-link it"  aria-hidden="true" tabindex="-1" >
5406            Tradesman Dispatcher          </a>
5407                                        <a href="https://talkify.nz/real-estate" class="strip-link"  aria-hidden="true" tabindex="-1" >
5408            Real Estate Enquiry <span class="pip">●</span>          </a>
5409                                        <a href="https://talkify.nz/beauty" class="strip-link it"  aria-hidden="true" tabindex="-1" >
5410            Beauty &amp; Wellness          </a>
5411                                        <a href="https://talkify.nz/plumber" class="strip-link"  aria-hidden="true" tabindex="-1" >
5412            Plumbing Dispatch <span class="pip">●</span>          </a>
5413                                        <a href="https://talkify.nz/retail" class="strip-link it"  aria-hidden="true" tabindex="-1" >
5414            Retail          </a>
5415                                        <a href="https://talkify.nz/professional-services" class="strip-link"  aria-hidden="true" tabindex="-1" >
5416            Professional Services <span class="pip">●</span>          </a>
5417                    </div>
5418</div>
5419
5420<section class="shell">
5421  <div class="section-hd">
5422    <h2 class="r">A missed call at teatime is <span class="it">
5422a missed dinner.</span></h2>
5423    <p class="lede r r-1">Nobody rings a chippie twice. Busy tone, and they ring the next one on the list.</p>
5424  </div>
5425
5426  <div class="fcx-cards">
5427    <article class="fcx-card">
5428      <span class="fcx-tag" style="--k:#c4451c">Before</span>
5429      <h3>Five o'clock to seven</h3>
5430      <p>Rings out. Or somebody answers with wet hands and writes half of it on a docket that goes missing.</p>
5431    </article>
5432
5433    <article class="fcx-card">
5434      <span class="fcx-tag" style="--k:#10695a">After</span>
5435      <h3>The same two hours</h3>
5436      <p>Every call answered. Every order legible, with the changes on the right line.</p>
5437    </article>
5438
5439    <article class="fcx-card">
5440      <span class="fcx-tag" style="--k:#318abe">Sunday night</span>
5441      <h3>When you are shut</h3>
5442      <p>It says when you open and refuses an order nobody is there to cook.</p>
5443    </article>
5444  </div>
5445</section>
5446
5447<section class="shell tight">
5448  <div class="section-hd">
5449    <h2 class="r">The phone rings. <span class="it">Nobody stops.</span></h2>
5450    <p class="lede r r-1">Any tablet, laptop or spare screen with a browser on it. Nothing to install.</p>
5451  </div>
5452
5453  <div class="cap-plate mixed r"><div class="cap third">
5454    
5455            <div class="cap-hd">
5456            <h3>Answers <span class="green">every call.</span></h3>
5457            <svg class="cap-mark" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" 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.13.96.36 1.9.7 2.81a2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0122 16.92z"/></svg>
5458        </div>
5459    
5460    <p>All of them at once, on the second ring, however busy you are.</p>
5461
5462    
5463    </div>
5464            <div class="cap third">
5465    
5466            <div class="cap-hd">
5467            <h3>Asks <span class="it">the right things.</span></h3>
5468            <svg class="cap-mark" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v12H5.2L4 17.5V4z"/><path d="M8 8h8M8 12h5"/></svg>
5469        </div>
5470    
5471    <p>And writes what they asked for on the line it belongs to, in their words.</p>
5472
5473    
5474    </div>
5475            <div class="cap third">
5476    
5477            <div class="cap-hd">
5478            <h3>Lands <span class="green">mid-call.</span></h3>
5479            <svg class="cap-mark" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="14" rx="2"/><path d="M8 20h8M12 18v2"/><path d="M7 9h10M7 13h6"/></svg>
5480        </div>
5481    
5482    <p>The ticket fills in while they talk, so you see a big order coming.</p>
5483
5484    
5485    </div>
5486            <div class="cap half">
5487    
5488            <div class="cap-hd">
5489            <h3>You set <span class="it">the wait.</span></h3>
5490            <svg class="cap-mark" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/></svg>
5491        </div>
5492    
5493    <p>Tap a time and every caller after that is told it. Change it as the night goes on; it goes quiet on its own so a lunchtime figure is never quoted at nine.</p>
5494
5495    
5496    </div>
5497            <div class="cap half">
5498    
5499            <div class="cap-hd">
5500            <h3>Run out? <span class="green">One tap.</span></h3>
5501            <svg class="cap-mark" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l9 5v8l-9 5-9-5V8z"/><path d="M9 12l2 2 4-4"/></svg>
5502        </div>
5503    
5504    <p>Tap the item on the screen and the agent stops selling it from the very next call, and takes it off any order a caller tries anyway. Everything comes back at midnight on its own.</p>
5505
5506    
5507    </div></div>
5508
5509</section>
5510
5511<style>
5512  /* ---------- scenario cards: three columns, no prose ---------- */
5513  .fcx-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(18px,2.4vw,34px);margin-top:34px}
5514  .fcx-card{border-top:2px solid var(--k,var(--line-2));padding:22px 0 0}
5515  .fcx-tag{display:inline-block;font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;
5516    text-transform:uppercase;color:var(--k,var(--mute))}
5517  .fcx-card h3{font-family:var(--serif);font-size:clamp(19px,1.9vw,23px);font-weight:400;
5518    margin:10px 0 6px;letter-spacing:-.02em;color:var(--paper);line-height:1.2}
5519  .fcx-card p{font-size:14px;color:var(--bone);line-height:1.6;margin:0}
5520
5521  /* ---------- the two ways to pay ----------
5522     Two plans side by side with the number doing the talking, then the add-on
5523     as one strip underneath. The old version said all of this in sentences and
5524     nobody was going to read it standing in a kitchen. */
5525  .fcx-plans{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(18px,2.4vw,30px);margin-top:36px}
5526  .fcx-plan{position:relative;display:flex;flex-direction:column;padding:30px 28px 28px;
5527    border:1px solid var(--line-2);border-radius:14px;
5528    background:linear-gradient(180deg,rgba(255,255,255,.035),transparent 190px)}
5529  .fcx-plan.is-pick{border-color:color-mix(in srgb,var(--signal) 55%,transparent);
5530    box-shadow:0 0 0 1px color-mix(in srgb,var(--signal) 22%,transparent)}
5531  .fcx-flag{position:absolute;top:-11px;left:28px;padding:3px 12px;border-radius:99px;
5532    font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
5533    background:var(--signal);color:#0b1219;font-weight:700}
5534  .fcx-plan-lbl{font-family:var(--mono);font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute)}
5535  .fcx-num{display:flex;align-items:baseline;gap:8px;margin:16px 0 4px;
5536    font-family:var(--serif);font-weight:300;letter-spacing:-.03em;color:var(--paper);
5537    font-size:clamp(40px,5.4vw,62px);line-height:1}
5538  .fcx-num small{font-family:var(--sans,inherit);font-size:14px;font-weight:400;color:var(--mute);letter-spacing:0}
5539  .fcx-then{margin:0 0 18px;font-size:14.5px;color:var(--bone);line-height:1.55}
5540  .fcx-then b{color:var(--paper);font-weight:600}
5541  .fcx-list{list-style:none;margin:0 0 22px;padding:0;display:grid;gap:9px}
5542  .fcx-list li{position:relative;padding-left:24px;color:var(--bone);font-size:14px;line-height:1.55}
5543  .fcx-list li::before{content:'✓';position:absolute;left:0;top:-1px;color:var(--signal);font-weight:700}
5544  .fcx-suits{margin:auto 0 0;padding-top:18px;border-top:1px solid var(--line-2);
5545    font-size:13px;color:var(--mute);line-height:1.55}
5546  .fcx-suits b{color:var(--bone);font-weight:600}
5547
5548  /* ---------- the add-on strip ---------- */
5549  .fcx-addon{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
5550    gap:clamp(16px,2.6vw,34px);margin-top:20px;padding:24px 28px;
5551    border:1px dashed var(--line-2);border-radius:14px}
5552  .fcx-addon-num{font-family:var(--serif);font-weight:300;font-size:clamp(30px,3.4vw,40px);
5553    line-height:1;letter-spacing:-.03em;color:var(--paper);white-space:nowrap}
5554  .fcx-addon-num small{font-family:var(--sans,inherit);font-size:13px;color:var(--mute);letter-spacing:0}
5555  .fcx-addon p{margin:0;font-size:14px;color:var(--bone);line-height:1.6}
5556  .fcx-addon p b{color:var(--paper);font-weight:600}
5557  .fcx-addon .btn{white-space:nowrap}
5558
5559  .fcx-fine{margin:18px 0 0;font-size:13px;color:var(--mute);line-height:1.6;max-width:74ch}
5560
5561  @media (max-width:900px){
5562    .fcx-cards{grid-template-columns:1fr}
5563    .fcx-plans{grid-template-columns:1fr}
5564    .fcx-addon{grid-template-columns:1fr;text-align:left}
5565  }
5566</style>
5567
5568<section class="shell tight" id="pricing">
5569  <div class="section-hd">
5570    <span class="eyebrow eb-green"><span class="pin"></span>Pricing</span>
5571    <h2 class="r">Two ways to pay. <span class="green">No setup fee either way.</span></h2>
5572  </div>
5573
5574  <div class="fcx-plans">
5575    <article class="fcx-plan is-pick">
5576      <span class="fcx-flag">Most shops start here</span>
5577      <span class="fcx-plan-lbl">Pay as you go</span>
5578      <span class="fcx-num">$10<small>/month</small></span>
5579      <p class="fcx-then">Then <b>$1 a minute</b>, only on calls you take.</p>
5580      <ul class="fcx-list">
5581        <li>$10 free credit to start</li>
5582        <li>A quiet Tuesday costs almost nothing</li>
5583        <li>Cancel any time</li>
5584      </ul>
5585      <p class="fcx-suits"><b>Suits</b> a phone that goes in bursts: weekend trade, seasonal, or still working out the numbers.</p>
5586    </article>
5587
5588    <article class="fcx-plan">
5589      <span class="fcx-plan-lbl">Reception agent</span>
5590      <span class="fcx-num">$129<small>/month</small></span>
5591      <p class="fcx-then">Flat, per number. Founding rate, then $199.</p>
5592      <ul class="fcx-list">
5593        <li>200 call minutes and 50 texts a month</li>
5594        <li>Up to 3 agents on the number</li>
5595        <li>Extra minutes 10c each</li>
5596      </ul>
5597      <p class="fcx-suits"><b>Suits</b> a phone that barely stops through service, where you would rather know the figure up front.</p>
5598    </article>
5599  </div>
5600
5601  <div class="fcx-addon">
5602    <span class="fcx-addon-num">+$59<small>/mo</small></span>
5603    <p><b>Front Counter, the screen itself.</b> As many tablets as you like, on either plan, with sold-out taps, docket printing, daily order numbers and an end-of-day close-out included. Texts from the screen are 10c each and WhatsApp is free.</p>
5604    <a href="https://talkify.nz/front-counter" class="btn btn-ghost">How the screen works <span class="arr">&rarr;</span></a>
5605  </div>
5606
5607  <p class="fcx-fine">
5608    The screen needs an agent answering the phone, so it is one of the two above plus Front Counter, whichever suits a chip shop.
5609    <a href="https://talkify.nz/pricing">Full price list</a>.
5610  </p>
5611</section>
5612
5613<section class="shell" id="faq">
5614  <div class="section-hd">
5615    <h2 class="r">Frequently <span class="it">asked.</span></h2>
5616    
5617        <p class="lede r r-1">Nine of the questions we hear most. If yours isn't here, ring our live demo agent on 03 242 1262, it'll either answer or queue a callback from a human.</p>
5618      </div>
5619
5620  <div class="r faq-list" id="faq-grid">
5621          <details class="faq-q">
5622        <summary>
5623          <span class="faq-n" aria-hidden="true">01</span>
5624          <span class="faq-t">Our phone goes flat out from five. Can it really keep up?</span>
5625          <span class="faq-icon" aria-hidden="true">+</span>
5626        </summary>
5627        <div class="faq-a">It answers every call at once, which is the part a person cannot do. Four people ringing at ten past six all get answered on the second ring rather than three of them getting a busy tone and trying the shop up the road. Each one gets its own ticket on your screen, in the order they came in.</div>
5628      </details>
5629          <details class="faq-q">
5630        <summary>
5631          <span class="faq-n" aria-hidden="true">02</span>
5632          <span class="faq-t">Will it get the order right? Chips are not simple.</span>
5633          <span class="faq-icon" aria-hidden="true">+</span>
5634        </summary>
5635        <div class="faq-a">Anything the customer asks for on a particular item is written on that line in their own words. Chicken salt on the chips, no vinegar, extra tartare, scallops well done. It reads the order back before it sends it, and if they change their mind halfway through it updates the same ticket rather than starting another.</div>
5636      </details>
5637          <details class="faq-q">
5638        <summary>
5639          <span class="faq-n" aria-hidden="true">03</span>
5640          <span class="faq-t">We do not have a menu system. Do we need one?</span>
5641          <span class="faq-icon" aria-hidden="true">+</span>
5642        </summary>
5643        <div class="faq-a">No, and that is the point. Put your menu and your prices into your agent once, in whatever form you have them, and it can tell a caller what you do and what it costs as well as taking the order. The order lands on a screen you already own: a tablet, an old laptop, a spare monitor with a browser.</div>
5644      </details>
5645          <details class="faq-q">
5646        <summary>
5647          <span class="faq-n" aria-hidden="true">04</span>
5648          <span class="faq-t">Can it tell people how long the wait is?</span>
5649          <span class="faq-icon" aria-hidden="true">+</span>
5650        </summary>
5651        <div class="faq-a">Yes, and this is the one your customers will notice. Tap a time on the screen and the agent quotes it to everyone who rings after that. When the fryers are backed up you change it to forty minutes and nobody is promised fifteen. It clears itself after a few hours so a busy Friday figure is never still being quoted on a quiet Tuesday.</div>
5652      </details>
5653          <details class="faq-q">
5654        <summary>
5655          <span class="faq-n" aria-hidden="true">05</span>
5656          <span class="faq-t">What if we run out of something?</span>
5657          <span class="faq-icon" aria-hidden="true">+</span>
5658        </summary>
5659        <div class="faq-a">Type it on the screen once. &quot;No oysters tonight.&quot; The agent tells the callers it actually affects and offers them something else, and says nothing about it to the ones who never asked.</div>
5660      </details>
5661          <details class="faq-q">
5662        <summary>
5663          <span class="faq-n" aria-hidden="true">06</span>
5664          <span class="faq-t">Do we have to ring people back when it is ready?</span>
5665          <span class="faq-icon" aria-hidden="true">+</span>
5666        </summary>
5667        <div class="faq-a">Only if you want to. Tap the ticket when the order is going in the bag and the customer gets a message saying it is ready, already written with their name on it. It goes by WhatsApp when they have it, which is free, and as a text when they do not.</div>
5668      </details>
5669          <details class="faq-q">
5670        <summary>
5671          <span class="faq-n" aria-hidden="true">07</span>
5672          <span class="faq-t">Does it take card payments over the phone?</span>
5673          <span class="faq-icon" aria-hidden="true">+</span>
5674        </summary>
5675        <div class="faq-a">No. Talkify never handles card details. Customers pay at the counter the way they do now, which is also what stops a phone order becoming a chargeback argument.</div>
5676      </details>
5677          <details class="faq-q">
5678        <summary>
5679          <span class="faq-n" aria-hidden="true">08</span>
5680          <span class="faq-t">We are in Australia. Does this work over here?</span>
5681          <span class="faq-icon" aria-hidden="true">+</span>
5682        </summary>
5683        <div class="faq-a">Yes. Talkify runs on both sides of the Tasman, with Australian numbers answered in Australian data centres and New Zealand numbers in New Zealand ones. The agent speaks the way your customers do, and the screen works the same either way.</div>
5684      </details>
5685          <details class="faq-q">
5686        <summary>
5687          <span class="faq-n" aria-hidden="true">09</span>
5688          <span class="faq-t">What does it cost?</span>
5689          <span class="faq-icon" aria-hidden="true">+</span>
5690        </summary>
5691        <div class="faq-a">Two ways. Pay as you go is $10 a month for the number plus $1 a minute, which suits a shop whose phone goes in bursts. A reception agent is $129/month at the founding rate for your first 3 months, then $199 flat. The screen is $59 a month on top of either. No setup fee and no lock in.</div>
5692      </details>
5693      </div>
5694
5695  <style>
5696    /* V2 design language: a ruled list, not a grid of boxed cards. Each row is
5697       a hairline, a mono index, the question in serif, and a bare + opposite.
5698       The old version was two columns of rounded, filled panels each with the
5699       + in a circular badge, which is the card furniture the V2 homepage does
5700       without. One column because a ruled list has to read down a single
5701       measure; two columns of rules would fight each other across the gutter. */
5702    .faq-list { margin-top: 44px; border-bottom: 1px solid var(--line-2) }
5703
5704    .faq-q { border-top: 1px solid var(--line-2) }
5705
5706    .faq-q summary {
5707      display: grid;
5708      grid-template-columns: 54px 1fr auto;
5709      align-items: center;
5710      gap: clamp(12px, 2vw, 24px);
5711      padding: 24px clamp(4px, 1vw, 12px);
5712      cursor: pointer;
5713      list-style: none;
5714      transition: background .3s var(--ease)
5715    }
5716
5717    .faq-q::-webkit-details-marker, .faq-q summary::-webkit-details-marker { display: none }
5718    .faq-q summary::marker { content: "" }
5719
5720    .faq-n {
5721      font-family: var(--mono);
5722      font-size: 11px;
5723      letter-spacing: .14em;
5724      color: var(--mute-2)
5725    }
5726
5727    .faq-t {
5728      font-family: var(--serif);
5729      font-weight: 400;
5730      font-size: clamp(17px, 1.7vw, 22px);
5731      line-height: 1.28;
5732      letter-spacing: -.01em;
5733      color: var(--paper);
5734      transition: color .3s var(--ease)
5735    }
5736
5737    .faq-icon {
5738      font-family: var(--mono);
5739      font-size: 17px;
5740      line-height: 1;
5741      color: var(--mute);
5742      transition: transform .3s var(--ease-out), color .3s var(--ease)
5743    }
5744
5745    .faq-q:hover summary { background: var(--surface-2) }
5746    .faq-q:hover .faq-t { color: var(--signal) }
5747    .faq-q:hover .faq-icon { color: var(--signal) }
5748
5749    .faq-q[open] .faq-icon { transform: rotate(45deg); color: var(--signal) }
5750    .faq-q[open] .faq-n { color: var(--signal) }
5751
5752    .faq-a {
5753      padding: 0 clamp(4px, 1vw, 12px) 28px calc(54px + clamp(12px, 2vw, 24px));
5754      max-width: 76ch;
5755      color: var(--bone);
5756      font-size: 14.5px;
5757      line-height: 1.68
5758    }
5759
5760    .faq-q summary:focus { outline: none }
5761    .faq-q summary:focus-visible { outline: 2px solid var(--signal); outline-offset: -2px }
5762
5763    @media (prefers-reduced-motion: reduce) {
5764      .faq-q summary, .faq-t, .faq-icon { transition: none }
5765    }
5766
5767    @media (max-width: 640px) {
5768      .faq-q summary { grid-template-columns: 34px 1fr auto }
5769      .faq-a { padding-left: calc(34px + 12px) }
5770    }
5771  </style>
5772</section>
5773
5774<section class="shell" id="related">
5775  <div class="section-hd">
5776    <h2 class="r">The rest of <span class="it">the counter.</span></h2>
5777    <p class="lede r r-1">An agent answering the phone is half of it. The same setup can pick the phone up and ring out when that is what the job needs.</p>
5778  </div>
5779
5780  <div class="trade-plate r">
5781          <a class="trade row" href="https://talkify.nz/front-counter">
5782        <svg class="mark" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
5783                        <path d="M4 5.5a2 2 0 0 1 2-2h2.2l1.6 3.9-1.9 1.4a12 12 0 0 0 5.3 5.3l1.4-1.9 3.9 1.6V16a2 2 0 0 1-2 2A13.5 13.5 0 0 1 4 5.5z"/>
5784                  </svg>
5785        <h3>Front Counter</h3>
5786        <p>How the tablet by the till works, what a ticket looks like, and what happens when a call drops halfway through.</p>
5787        <span class="go"><span>The screen</span> <em>&rarr;</em></span>
5788      </a>
5789          <a class="trade row" href="https://talkify.nz/chinese-takeaway">
5790        <svg class="mark" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
5791                        <path d="M4 5.5a2 2 0 0 1 2-2h2.2l1.6 3.9-1.9 1.4a12 12 0 0 0 5.3 5.3l1.4-1.9 3.9 1.6V16a2 2 0 0 1-2 2A13.5 13.5 0 0 1 4 5.5z"/>
5792                  </svg>
5793        <h3>Chinese takeaways</h3>
5794        <p>The same phone problem with longer orders and more questions about what is in a dish.</p>
5795        <span class="go"><span>Next door</span> <em>&rarr;</em></span>
5796      </a>
5797      </div>
5798</section>
5799
5800<section class="endcta endcta-has-form" id="endcta">
5801    <div class="endcta-photo" aria-hidden="true"></div>
5802
5803    
5804    <div class="endcta-wrap" id="signup">
5805        <div class="endcta-pitch">
5806            <div class="stamp">TWO WAYS TO HEAR THE AGENT</div>
5807            <h2>Ring it like a customer.<br><span class="it">Order two scoops.</span></h2>
5808
5809            <div class="endcta-numbers">
5810                                <a href="tel:+6432421262" class="num-big" data-talkify-agent="default"
5811                   title="Hear the agent yourself">
5812      <span class="ic ic-demo">
5813        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"
5814             stroke-linecap="round"><path
5815                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>
5816      </span>
5817                    <span>
5818        <small>Hear it yourself · our AI agent, 24/7 · ask it anything</small>
5819        03 242 1262
5820      </span>
5821                </a>
5822                
5823                                    <a href="tel:+64800002967" class="num-big num-blue" title="Sign up, sales and support">
5824      <span class="ic ic-signup">
5825        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"
5826             stroke-linecap="round"><path
5827                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>
5828      </span>
5829                        <span>
5830        <small>Sign up, sales &amp; support · we'll set you up</small>
5831        0800 002 967
5832      </span>
5833                    </a>
5834                            </div>
5835
5836            <div class="endcta-meta">
5837                                    <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>
5838
5839            
5840                        <div class="endcta-alt">
5841                <a href="sms:+64272048827" class="btn btn-ghost btn-lg"
5842       title="Text us instead of ringing">
5843        <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"
5844             stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex:none">
5845            <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"/>
5846        </svg>
5847        Text our agent · 027 204 8827    </a>
5848            </div>
5849            
5850            
5851                            <p class="endcta-app-line">Or run it from your pocket</p>
5852                <div class="app-stores" style="--app-badge-h: 46px">
5853    <a class="app-badge" href="https://apps.apple.com/nz/app/talkify-mobile/id6766709308"
5854       target="_blank" rel="noopener">
5855        <img src="https://talkify.nz/media/branding/apple-app-store.svg"
5856             alt="Download Talkify Mobile on the App Store"
5857             width="137.6" height="46" loading="lazy">
5858    </a>
5859    <a class="app-badge" href="https://play.google.com/store/apps/details?id=com.talkifynz.app"
5860       target="_blank" rel="noopener">
5861        <img src="https://talkify.nz/media/branding/google-app-store.svg"
5862             alt="Get Talkify Mobile on Google Play"
5863             width="155.3" height="46" loading="lazy">
5864    </a>
5865</div>
5866                    </div>
5867
5868                    <div class="endcta-form">
5869                
5870                <span class="eyebrow"><span class="pin"></span>Get your first agent ·  No card needed </span>
5871
5872                <form method="POST" action="https://talkify.nz/contact" class="form">
5873                    <input type="hidden" name="_token" value="5MGekG5aEnJLziD1RYXq2wNDu47KXOfVE2QXDqz4" autocomplete="off">                                        <div class="row">
5874                        <div class="field">
5875                            <label>Your name</label>
5876                            <input type="text" name="name" required placeholder="Your full name" autocomplete="name" value="">
5877                        </div>
5878                        <div class="field">
5879                            <label>Company</label>
5880                            <input type="text" name="company" required placeholder="Your company" autocomplete="organization" value="">
5881                        </div>
5882                    </div>
5883                    <div class="row">
5884                        <div class="field">
5885                            <label>Email</label>
5886                            <input type="email" name="email" required placeholder="Your email" autocomplete="email" value="">
5887                        </div>
5888                        <div class="field">
5889                            <label>Mobile (NZ)</label>
5890                            <input type="tel" name="phone" required placeholder="Your mobile" autocomplete="tel" value="">
5891                        </div>
5892                    </div>
5893                    <div class="field">
5894  <label for="country-signup">Country</label>
5895  <select name="country" id="country-signup" required data-country-select autocomplete="country">
5896    <option value="" disabled selected>Select your country</option>
5897    <option value="NZ" >New Zealand</option>
5898    <option value="AU" >Australia</option>
5899  </select>
5900  <p style="margin-top:8px;font-family:var(--mono);font-size:11px;letter-spacing:.04em;color:var(--mute)">
5901    Talkify is currently available to businesses in New Zealand &amp; Australia only.
5902  </p>
5903</div>
5904
5905
5906<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">
5907  <input type="text" name="company_reference" tabindex="-1" autocomplete="off" value="" aria-hidden="true">
5908</div>
5909
5910<script>
5911(function () {
5912  var script = document.currentScript;
5913  var form = script && script.closest('form');
5914  if (!form) return;
5915  var select = form.querySelector('select[name="country"]');
5916  if (!select || select.value) return; // respect old() / a choice already made
5917
5918  try {
5919    var tz = (Intl.DateTimeFormat().resolvedOptions().timeZone || '').toLowerCase();
5920    var lang = (navigator.language || '').toLowerCase();
5921    var code = null;
5922
5923    if (tz.indexOf('auckland') >= 0 || tz.indexOf('chatham') >= 0 || lang === 'en-nz' || lang === 'mi') {
5924      code = 'NZ';
5925    } else if (tz.indexOf('australia/') >= 0 || lang === 'en-au') {
5926      code = 'AU';
5927    }
5928
5929    if (code) select.value = code;
5930  } catch (e) { /* detection is best-effort */ }
5931})();
5932</script>
5932
5933                    <div class="field">
5934                        <label>Pick your agent</label>
5935                        <div class="radios">
5936                                                        <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>
5937                            <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>
5938                            <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>
5939                            <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>
5940                            <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>
5941                            <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>
5942                            <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>
5943                        </div>
5944                        <p class="plan-recommend" data-plan-recommend style="display:none">
5945                            We recommend running an incoming agent alongside an outgoing or campaign agent. People you ring will often ring you
5946                            back, and an incoming agent makes sure those return calls are answered rather than missed. If you would
5947                            rather not add one, we can clone your business caller ID so return calls come straight back to your
5948                            existing phone.
5949                        </p>
5950                    </div>
5951
5952                    <div class="field">
5953                        <label>How you want to pay</label>
5954                        <div class="radios">
5955                            <label class="radio">
5956                                <input type="radio" name="plan" value="broadcast" checked>
5957                                <span class="dot"></span>
5958                                <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>
5959                            </label>
5960                            <label class="radio">
5961                                <input type="radio" name="plan" value="payg" >
5962                                <span class="dot"></span>
5963                                <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>
5964                            </label>
5965                        </div>
5966                    </div>
5967
5968                    <div class="plan-display" data-plan-display>
5969                        <div class="plan-display-left">
5970                            <div class="plan-display-label" data-plan-label>Personal Assistant</div>
5971                            <div class="plan-display-sub" data-plan-sub>Single mobile or landline. Built for one person, not a business.</div>
5972                        </div>
5973                        <div class="plan-display-right">
5974                            <div class="plan-display-price" data-plan-price>$89<small>/mo</small></div>
5975                            <div class="plan-display-tier" data-plan-tier>Shortwave plan</div>
5976                                                        <div class="plan-display-note" data-plan-note  style="display:none" ></div>
5977                        </div>
5978                    </div>
5979                    <p class="founding-line">
5980                                                    <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.
5981                                                Plans include 50 to 200 minutes a month, then 10c a minute. The first 20 texts each month are free, then 9c each.
5982                    </p>
5983                    <p class="plan-asterisk" data-plan-asterisk style="display:none">
5984                        <span>*</span> Subject to your CRM or booking system. Additional implementation cost may apply for non-standard integrations.
5985                    </p>
5986
5987                    <div class="actions">
5988                        <span class="note">● Your data stays in NZ.</span>
5989                        <button type="submit" class="btn btn-primary btn-lg">Create your first agent <span class="arr">→</span></button>
5990                    </div>
5991                </form>
5992
5993                
5993<script>
5994                    (function () {
5995                        // A plan only carries a crossed-out "was" price and a founding note while
5996                        // its intro price is genuinely below its standard price; when the two
5997                        // match in the pricing table both come through blank and the picker
5998                        // shows a plain price. Per-call plans never have a founding step.
5999                        const PA_NOTE = "";
6000                        const BIZ_NOTE = "Founding rate for your first 3 months, then $199/mo";
6001                        const PA_WAS = "";
6002                        const BIZ_WAS = "$199";
6003
6004                        const PLANS = {
6005                            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 },
6006                            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 },
6007                            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 },
6008                            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 },
6009                            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 },
6010                            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 },
6011                            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 },
6012                        };
6013                        // The pay-as-you-go face of the same picker: whatever agent they chose,
6014                        // the money side is the per-minute wallet, so the price panel follows
6015                        // the payment choice rather than quoting a monthly plan.
6016                        const PAYG = {
6017                            price: '$1',
6018                            suffix: '/min',
6019                            tier: 'Pay as you go · $10/month covers your phone number',
6020                            note: '$10 free credit to start, on top of the number. Calls and texts come off your prepaid balance.',
6021                        };
6022                        const form = document.currentScript.closest('.endcta-form') || document;
6023                        const radios = form.querySelectorAll('input[name="agent_type"]');
6024                        const payRadios = form.querySelectorAll('input[name="plan"]');
6025                        const labelEl = form.querySelector('[data-plan-label]');
6026                        const subEl = form.querySelector('[data-plan-sub]');
6027                        const priceEl = form.querySelector('[data-plan-price]');
6028                        const tierEl = form.querySelector('[data-plan-tier]');
6029                        const noteEl = form.querySelector('[data-plan-note]');
6030                        const astEl = form.querySelector('[data-plan-asterisk]');
6031                        const recEl = form.querySelector('[data-plan-rec
6031ommend]');
6032
6033                        function update(){
6034                            const checked = form.querySelector('input[name="agent_type"]:checked');
6035                            if (!checked) return;
6036                            const plan = PLANS[checked.value];
6037                            if (!plan) return;
6038                            const pay = form.querySelector('input[name="plan"]:checked');
6039                            const payg = pay && pay.value === 'payg';
6040                            labelEl.textContent = plan.label;
6041                            subEl.textContent = plan.sub;
6042                            priceEl.innerHTML = payg
6043                                ? PAYG.price + '<small>' + PAYG.suffix + '</small>'
6044                                : (plan.was ? '<s class="was-price">'+plan.was+'</s> ' : '') + plan.price + (plan.suffix ? '<small>'+plan.suffix+'</small>' : '');
6045                            tierEl.textContent = payg ? PAYG.tier : plan.tier;
6046                            if (noteEl) {
6047                                const note = payg ? PAYG.note : (plan.note || '');
6048                                noteEl.textContent = note;
6049                                noteEl.style.display = note ? 'block' : 'none';
6050                            }
6051                            astEl.style.display = (!payg && plan.asterisk) ? 'block' : 'none';
6052                            if (recEl) recEl.style.display = plan.recommend ? 'block' : 'none';
6053                        }
6054                        radios.forEach(r => r.addEventListener('change', update));
6055                        payRadios.forEach(r => r.addEventListener('change', update));
6056                        update();
6057                    })();
6058                </script>
6058
6059            </div>
6060            </div>
6061
6062            <style>
6063            /* Two top-ruled columns rather than two pills side by side. The pair is
6064               held to a readable measure and centred under the headline, so the
6065               block still reads as the close of the page even though the section
6066               itself is centred and these two are ruled and left-aligned. */
6067            .endcta-numbers {
6068                display: grid;
6069                grid-template-columns: 1fr 1fr;
6070                gap: clamp(24px, 4vw, 56px);
6071                margin: 56px auto 0;
6072                max-width: 780px;
6073                text-align: left
6074            }
6075
6076            @media (max-width: 800px) {
6077                .endcta-numbers {
6078                    grid-template-columns: 1fr;
6079                    gap: 30px;
6080                    max-width: 460px
6081                }
6082            }
6083
6084            .endcta-alt {
6085                margin-top: 36px;
6086                display: flex;
6087                flex-wrap: wrap;
6088                gap: 12px;
6089                justify-content: center
6090            }
6091
6092            /* The app line sits under the two ways to reach us and quieter than
6093               either, because it is aimed at people who have already signed up. */
6094            .endcta-app-line {
6095                margin-top: 40px;
6096                font-family: var(--mono);
6097                font-size: 10px;
6098                letter-spacing: .18em;
6099                text-transform: uppercase;
6100                color: var(--mute)
6101            }
6102
6103            .endcta .app-stores {
6104                margin-top: 14px;
6105                justify-content: center
6106            }
6107
6108            /* ── With the form in it ───────────────────────────────────────────
6109               The pitch stops being a centred banner and becomes the left half
6110               of one closing block, with the get-started form on the right. No
6111               panel and no rounding: the two columns simply share the page. */
6112            .endcta-has-form .endcta-wrap {
6113                display: grid;
6114                grid-template-columns: 1fr 1.05fr;
6115                gap: clamp(40px, 5vw, 76px);
6116                align-items: start;
6117                max-width: 1240px;
6118                margin: 0 auto;
6119                text-align: left
6120            }
6121
6122            /* The skyline sits behind a short centred banner comfortably. Behind
6123               a block three times as tall it runs up under the form fields and
6124               the price panel, where a photograph is just noise, so it is held
6125               well back and the scrim is carried the whole way down instead of
6126               fading out in the middle. */
6127            .endcta.endcta-has-form .endcta-photo {
6128                opacity: .12;
6129                background-position: center bottom
6130            }
6131
6132            html[data-theme="light"] .endcta.endcta-has-form .endcta-photo {
6133                opacity: .16
6134            }
6135
6136            .endcta.endcta-has-form .endcta-photo::after {
6137                background: linear-gradient(180deg, var(--scrim-mid) 0%, var(--scrim-strong) 30%, var(--scrim-strong) 100%)
6138            }
6139
6140            .endcta-has-form .endcta-numbers {
6141                grid-template-columns: 1fr;
6142                gap: 26px;
6143                margin: 44px 0 0;
6144                max-width: none
6145            }
6146
6147            .endcta-has-form .endcta-meta {
6148                justify-content: flex-start;
6149                gap: 22px
6150            }
6151
6152            .endcta-has-form .endcta-alt,
6153            .endcta-has-form .app-stores {
6154                justify-content: flex-start
6155            }
6156
6157            .endcta-form .eyebrow {
6158                display: inline-flex;
6159                margin-bottom: 20px
6160            }
6161
6162            @media (max-width: 1000px) {
6163                .endcta-has-form .endcta-wrap {
6164                    grid-template-columns: 1fr;
6165                    gap: 48px
6166                }
6167
6168                .endcta-has-form .endcta-numbers {
6169                    max-width: 460px
6170                }
6171            }
6172
6173            /* Carried over from the signup section this block absorbed: that
6174               partial's styles only ship on the page that includes it, and it
6175               is now only included by /v2. */
6176            .signup-errors {
6177                margin-bottom: 18px;
6178                padding: 14px 0 14px 16px;
6179                border-left: 2px solid var(--coral);
6180                font-family: var(--mono);
6181                font-size: 12px;
6182                line-height: 1.6;
6183                color: var(--paper)
6184            }
6185
6186            .was-price {
6187                font-size: .55em;
6188                color: var(--mute-2);
6189                text-decoration: line-through;
6190                text-decoration-color: var(--coral);
6191                margin-right: 4px;
6192                font-weight: 300
6193            }
6194
6195            .founding-line {
6196                margin-top: 14px;
6197                font-family: var(--sans);
6198                font-size: 12px;
6199                line-height: 1.55;
6200                color: var(--mute)
6201            }
6202
6203            .founding-line .fl-tag {
6204                font-family: var(--mono);
6205                font-size: 10px;
6206                letter-spacing: .14em;
6207                text-transform: uppercase;
6208                color: var(--signal);
6209                margin-right: 8px
6210            }
6211        </style>
6212    </section>
6213
6214<style>
6215    .foot-social {
6216        display: inline-flex;
6217        align-items: center;
6218        gap: 8px;
6219        padding: 6px 0;
6220        font-family: var(--mono);
6221        font-size: 11px;
6222        color: var(--mute);
6223        letter-spacing: .06em;
6224        transition: color .25s var(--ease);
6225    }
6226
6227    .foot-social:hover { color: var(--paper); }
6228
6229    /* The badges sit tighter than the marketing rows and wrap rather than
6230       squeeze, because this column is the narrowest place they appear. */
6231    .foot-apps {
6232        margin-top: 22px;
6233        gap: 10px;
6234    }
6235</style>
6236<footer class="foot">
6237    <div class="foot-grid">
6238        <div class="foot-brand">
6239            
6240            <a class="logo" href="https://talkify.nz" aria-label="Talkify, home"
6241               style="display:flex;align-items:center;gap:14px;color:inherit;text-decoration:none">
6242                <svg class="tk-logo" viewBox="-3 -3 317.81 106"
6243     width="125.92" height="42"
6244     xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Talkify" focusable="false">
6245        <circle cx="50" cy="50" r="50" fill="var(--tk-word, #101820)"/>
6246    
6247    <g fill="none" stroke="var(--tk-ground, #ffffff)" stroke-width="10" stroke-linecap="round">
6248        <path d="M34 26 V54 C34 74 62 80 76 62"/>
6249        <path d="M20 40 H46"/>
6250    </g>
6251    
6252    <g transform="translate(56 20) scale(0.30)">
6253        <g class="tk-eye">
6254            <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)"/>
6255        </g>
6256    </g>
6257            <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"/>
6258        
6259        <g transform="translate(231.30 6.84) scale(0.216)">
6260            <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"
6261                  fill="var(--tk-word, #101820)"/>
6262        </g>
6263    </svg>
6264            </a>
6265                                        <p>The voice operating system for New Zealand business. Built in Aotearoa, hosted in Aotearoa, working while
6266                    you don't.</p>
6267                        <div
6268                style="margin-top:20px;font-family:var(--mono);font-size:12px;color:var(--mute);letter-spacing:.06em;line-height:1.7">
6269                                <span style="color:var(--mute);font-size:10px;text-transform:uppercase;letter-spacing:.18em">Sign up by phone</span><br>
6270                <a href="tel:+64800002967" style="color:var(--bone);transition:.25s">0800 002 967</a><br>
6271                                <span
6272                    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>
6273                <a href="tel:+6432421262" data-talkify-agent="default" style="color:var(--bone);transition:.25s">03 242 1262</a>
6274                                    <br>
6275                    <span
6276                        style="color:var(--mute);font-size:10px;text-transform:uppercase;letter-spacing:.18em;margin-top:8px;display:inline-block">Text our agent</span><br>
6277                    <a href="sms:+64272048827" style="color:var(--bone);transition:.25s">027 204 8827</a>
6278                            </div>
6279            <div style="margin-top:20px;
6279display:flex;flex-wrap:wrap;gap:8px 22px;align-items:center">
6280                <a href="https://www.facebook.com/profile.php?id=61572226258048" target="_blank"
6281                   rel="noopener noreferrer" aria-label="Facebook"
6282                   class="foot-social">
6283                    <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
6284                        <path
6285                            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"/>
6286                    </svg>
6287                    Facebook
6288                </a>
6289                <a href="https://www.instagram.com/talkifynz/" target="_blank"
6290                   rel="noopener noreferrer" aria-label="Instagram"
6291                   class="foot-social">
6292                    <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
6293                        <path
6294                            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"/>
6295                    </svg>
6296                    Instagram
6297                </a>
6298                <a href="https://www.linkedin.com/company/talkify-nz/" target="_blank"
6299                   rel="noopener noreferrer" aria-label="LinkedIn"
6300                   class="foot-social">
6301                    <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
6302                        <path
6303                            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"/>
6304                    </svg>
6305                    LinkedIn
6306                </a>
6307            </div>
6308
6309            
6310            <div class="app-stores foot-apps" style="--app-badge-h: 38px">
6311    <a class="app-badge" href="https://apps.apple.com/nz/app/talkify-mobile/id6766709308"
6312       target="_blank" rel="noopener">
6313        <img src="https://talkify.nz/media/branding/apple-app-store.svg"
6314             alt="Download Talkify Mobile on the App Store"
6315             width="113.7" height="38" loading="lazy">
6316    </a>
6317    <a class="app-badge" href="https://play.google.com/store/apps/details?id=com.talkifynz.app"
6318       target="_blank" rel="noopener">
6319        <img src="https://talkify.nz/media/branding/google-app-store.svg"
6320             alt="Get Talkify Mobile on Google Play"
6321             width="128.3" height="38" loading="lazy">
6322    </a>
6323</div>
6324        </div>
6325        <div>
6326            <h4>Agents</h4>
6327            <ul>
6328                <li><a href="https://talkify.nz/reception">Reception</a></li>
6329                <li><a href="https://talkify.nz/personal-assistant">Personal Assistant</a></li>
6330                <li><a href="https://talkify.nz/booking-service">Booking Service</a></li>
6331                <li><a href="https://talkify.nz/sales-agent">Sales Agent</a></li>
6332                <li><a href="https://talkify.nz/ai-phone-surveys">Campaign Agent</a></li>
6333                <li><a href="https://talkify.nz/debt-collection">Debt Collection</a></li>
6334                <li><a href="https://talkify.nz/ai-wellness-checks">Wellness Checks</a></li>
6335                <li>
6335<a href="https://talkify.nz/outbound-calls">Outbound Calls</a></li>
6336                <li><a href="https://talkify.nz/ai-marketing-campaigns">Marketing Campaigns</a></li>
6337                <li><a href="https://talkify.nz/website-chat">Website Chat</a></li>
6338                <li><a href="https://talkify.nz/calendar">Team Calendar</a></li>
6339                <li><a href="https://talkify.nz/dialler">Dialler</a></li>
6340                <li><a href="https://talkify.nz/agents">All agents &rarr;</a></li>
6341            </ul>
6342        </div>
6343        
6344        <div>
6345            <h4>Trades</h4>
6346            <ul>
6347                <li><a href="https://talkify.nz/plumber">Plumbing</a></li>
6348                <li><a href="https://talkify.nz/electrician">Electricians</a></li>
6349                <li><a href="https://talkify.nz/builder">Builders</a></li>
6350                <li><a href="https://talkify.nz/hvac">Heat Pump &amp; HVAC</a></li>
6351                <li><a href="https://talkify.nz/automotive">Mechanics &amp; Workshops</a></li>
6352                <li><a href="https://talkify.nz/landscaping">Landscaping</a></li>
6353                <li><a href="https://talkify.nz/pest-control">Pest Control</a></li>
6354                <li><a href="https://talkify.nz/tradesman">All Trades</a></li>
6355            </ul>
6356        </div>
6357        <div>
6358            <h4>Industries</h4>
6359            <ul>
6360                <li><a href="https://talkify.nz/beauty">Beauty &amp; Wellness</a></li>
6361                <li><a href="https://talkify.nz/real-estate">Real Estate</a></li>
6362                <li><a href="https://talkify.nz/retail">Retail</a></li>
6363                <li><a href="https://talkify.nz/professional-services">Professional Services</a></li>
6364                <li><a href="https://talkify.nz/barber">Barbers</a></li>
6365                <li><a href="https://talkify.nz/gym">Gyms &amp; Studios</a></li>
6366                <li><a href="https://talkify.nz/personal-trainer">Personal Trainers</a></li>
6367                <li><a href="https://talkify.nz/hotel">Hotels &amp; Motels</a></li>
6368                <li><a href="https://talkify.nz/accountant">Accountants</a></li>
6369                <li><a href="https://talkify.nz/industries">All industries &rarr;</a></li>
6370            </ul>
6371        </div>
6372        <div>
6373            
6374            <h4>Call answering</h4>
6375            <ul>
6376                <li><a href="https://talkify.nz">AI receptionist NZ</a></li>
6377                <li><a href="https://talkify.nz/ai-phone-agent">AI phone agent NZ</a></li>
6378                <li><a href="https://talkify.nz/virtual-receptionist">Virtual receptionist NZ</a></li>
6379                <li><a href="https://talkify.nz/ai-answering-service">AI answering service NZ</a></li>
6380                <li><a href="https://talkify.nz/after-hours-answering">After hours answering NZ</a></li>
6381                <li><a href="https://talkify.nz/on-call-roster">On-Call Roster</a></li>
6382                <li><a href="https://talkify.nz/ai-call-centre">AI Call Centre Agents</a></li>
6383                <li><a href="https://talkify.nz/business-phone-lines">Business Phone Lines</a></li>
6384                
6385                <li style="margin-top:6px;color:var(--mute);line-height:1.8">
6386                    By city:
6387                    <a
6388                            href="https://talkify.nz/ai-receptionist-auckland">Auckland</a><span
6389                            style="color:var(--line-2)"> · </span><a
6390                            href="https://talkify.nz/ai-receptionist-wellington">Wellington</a><span
6391                            style="color:var(--line-2)"> · </span><a
6392                            href="https://talkify.nz/ai-receptionist-christchurch">Christchurch</a><span
6393                            style="color:var(--line-2)"> · </span><a
6394                            href="https://talkify.nz/ai-receptionist-hamilton">Hamilton</a><span
6395                            style="color:var(--line-2)"> · </span><a
6396                            href="https://talkify.nz/ai-receptionist-tauranga">Tauranga</a><span
6397                            style="color:var(--line-2)"> · </span><a
6398                            href="https://talkify.nz/ai-receptionist-dunedin">Dunedin</a>                </li>
6399            </ul>
6400        </div>
6401        <div>
6402            
6403            <h4>Company</h4>
6404            <ul>
6405                <li><a href="https://talkify.nz/pricing">Pricing</a></li>
6406                <li><a href="https://talkify.nz/integrations">Integrations</a></li>
6407                
6408                <li><a href="https://talkify.nz/compare">Compare Providers</a><span
6409                        style="color:var(--line-2)"> · </span><a
6410                        href="https://talkify.nz/alternatives">Alternatives</a></li>
6411                <li><a href="https://talkify.nz/missed-call-calculator">Missed Call Calculator</a></li>
6412                <li><a href="https://talkify.nz/blog">Journal</a></li>
6413                
6414                <li><a href="https://talkify.nz/help">Help centre</a><span
6415                        style="color:var(--line-2)"> · </span><a
6416                        href="https://talkify.nz/contact-us">Contact us</a></li>
6417                <li><a href="https://talkify.nz/demo">Live demo</a></li>
6418                <li><a href="https://talkify.nz/signup">Get started</a></li>
6419            </ul>
6420        </div>
6421    </div>
6422    <div class="foot-bot">
6423                    <span>© <span id="year">2026</span> · Talkify Limited · NZ owned and hosted</span>
6424                <span>
6425            
6426                            <span aria-current="page">New Zealand</span> · <a href="https://talkify.nz/au" style="color:var(--bone)">Australia</a> ·
6427                        <a href="https://talkify.nz/privacy" style="color:var(--bone)">Privacy</a> ·
6428            <a href="https://talkify.nz/terms" style="color:var(--bone)">Terms</a> ·
6429            <a href="https://talkify.nz/support" style="color:var(--bone)">Support</a> ·
6430                            <a href="https://talkify.nz/login" style="color:var(--bone)">Sign in</a>
6431                        · <a href="https://d3v.nz" style="color:var(--bone)">Made by D3V</a>
6432        </span>
6433    </div>
6434</footer>
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445<script>
6446    function tick() {
6447        const d = new Date();
6448        const f = new Intl.DateTimeFormat('en-NZ', {
6449            timeZone: 'Pacific/Auckland',
6450            hour: '2-digit',
6451            minute: '2-digit',
6452            second: '2-digit',
6453            hour12: false
6454        });
6455        const el = document.getElementById('clock');
6456        if (el) el.textContent = f.format(d);
6457    }
6458
6459    tick();
6460    setInterval(tick, 1000);
6461    const yEl = document.getElementById('year');
6462    if (yEl) yEl.textContent = new Date().getFullYear();
6463
6464    /* Scroll reveal. Fires once per block. Anybody who has asked for less
6465       motion, and any browser without IntersectionObserver, gets the lot
6466       revealed immediately rather than a page of invisible sections. */
6467    (function () {
6468        const blocks = document.querySelectorAll('.r');
6469        if (!blocks.length) return;
6470        const reduce = window.matchMedia
6471            && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6472        if (reduce || !('IntersectionObserver' in window)) {
6473            blocks.forEach(el => el.classList.add('in'));
6474            return;
6475        }
6476        const io = new IntersectionObserver((entries) => {
6477            entries.forEach(e => {
6478                if (e.isIntersecting) {
6479                    e.target.classList.add('in');
6480                    io.unobserve(e.target);
6481                }
6482            });
6483        }, {rootMargin: '-8% 0px -5% 0px'});
6484        blocks.forEach(el => io.observe(el));
6485    })();
6486
6487    /* Agent phones. Each opens on a plain lock screen, then the clock drops to
6488       its compact size and the notifications land on top of it, which is the
6489       order an iPhone does it in. Plays once, when the panel is on screen.
6490
6491       The clock is the VISITOR'S OWN time and every stamp is counted back from
6492       it, so a screen can never show a notification that arrived after the time
6493       printed above it. Nothing is written into the markup, so a cached page
6494       cannot go stale either.
6495
6496       The tilt and the sheen are a couple of degrees and a highlight eased
6497       across the viewport. Both are off on coarse pointers, where there is no
6498       hover to reward them and the scroll handler is pure cost, and the whole
6499       thing collapses to "already arrived" under prefers-reduced-motion. */
6500    (function () {
6501        const phones = [...document.querySelectorAll('[data-agent-phone]')];
6502        if (!phones.length) return;
6503
6504        const clockOf = d => d.toLocaleTimeString('en-NZ', {hour: 'numeric', minute: '2-digit', hour12: false});
6505        const stampOf = d => d.toLocaleTimeString('en-NZ', {hour: 'numeric', minute: '2-digit', hour12: true})
6506            .replace(/\s/g, '').toLowerCase();
6507        const dateOf = d => d.toLocaleDateString('en-NZ', {weekday: 'long', day: 'numeric', month: 'long'});
6508
6509        const still = matchMedia('(prefers-reduced-motion: reduce)').matches;
6510        const coarse = matchMedia('(pointer: coarse)').matches;
6511
6512        phones.forEach(phone => {
6513            // A phone may pin its own clock with data-agent-at="HH:MM". The
6514            // after-hours story is an escalation at a quarter to midnight, and
6515            // stamped 2pm on a daytime visitor's own clock it reads as
6516            // nonsense. Everything else still shows the visitor's real time,
6517            // counted back from, so nothing arrives after the clock above it.
6518            const now = new Date();
6519            const pinned = (phone.dataset.agentAt || '').match(/^(\d{1,2}):(\d{2})$/);
6520            if (pinned) now.setHours(+pinned[1], +pinned[2], 0, 0);
6521
6522            const t = phone.querySelector('[data-agent-time]');
6523            const dt = phone.querySelector('[data-agent-date]');
6524            if (t) t.textContent = clockOf(now);
6525            if (dt) dt.textContent = dateOf(now);
6526
6527            phone.querySelectorAll('[data-agent-ago]').forEach(el => {
6528                const mins = parseInt(el.dataset.agentAgo, 10);
6529                if (!Number.isFinite(mins)) return;
6530                el.textContent = stampOf(new Date(now.getTime() - mins * 60000));
6531            });
6532
6533            const clock = phone.querySelector('[data-agent-clock]');
6534            const notes = [...phone.querySelectorAll('.hpn')];
6535            if (!clock || !notes.length) return;
6536
6537            if (still) {
6538                clock.classList.add('is-compact');
6539                notes.forEach(n => n.classList.add('is-in'));
6540                return;
6541            }
6542
6543            let played = false;
6544            const play = () => {
6545                if (played) return;
6546                played = true;
6547                setTimeout(() => clock.classList.add('is-compact'), 420);
6548                notes.forEach((n, i) => setTimeout(() => n.classList.add('is-in'), 780 + i * 380));
6549            };
6550
6551            const io = new IntersectionObserver(entries => {
6552                entries.forEach(e => {
6553                    if (!e.isIntersecting) return;
6554                    play();
6555                    io.unobserve(phone);
6556                });
6557            }, {threshold: .35});
6558            io.observe(phone);
6559
6560            if (coarse) return;
6561
6562            const lean = phone.classList.contains('agent-phone--left') ? -1 : 1;
6563            let queued = false;
6564            const tilt = () => {
6565                queued = false;
6566                const r = phone.getBoundingClientRect();
6567                if (r.bottom < 0 || r.top > innerHeight) return;
6568                // -0.5 above the fold, +0.5 below it
6569                const p = (r.top + r.height / 2 - innerHeight / 2) / innerHeight;
6570                phone.style.setProperty('--ag-tilt', (lean * (3 - p * 4.5)).toFixed(2) + 'deg');
6571                phone.style.setProperty('--ag-sheen', (p * -150).toFixed(1) + '%');
6572            };
6573            addEventListener('scroll', () => {
6574                if (queued) return;
6575                queued = true;
6576                requestAnimationFrame(tilt);
6577            }, {passive: true});
6578            tilt();
6579        });
6580    })();
6581
6582
6583    /* Hero phone. The chips are the data source, so the markup stays the one
6584       place the copy lives. Cycling pauses the moment the visitor takes over,
6585       and never starts at all under prefers-reduced-motion. */
6586    (function () {
6587        const root = document.querySelector('[data-hp-stack]');
6588        if (!root) return;
6589        const chips = [...document.querySelectorAll('[data-hp-chip]')];
6590        if (!chips.length) return;
6591
6592        const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6593        const icon = document.querySelector('.hpn header img');
6594        const iconSrc = icon ? icon.getAttribute('src') : '';
6595        let i = 0, timer = null, taken = false;
6596
6597        // the phone shows the viewer's own clock, so it reads as their phone
6598        // rather than a screenshot taken at some other time
6599        const clock = () => {
6600            const now = new Date();
6601            const t = document.querySelector('[data-hp-time]');
6602            const d = document.querySelector('[data-hp-date]');
6603            if (t) t.textContent = now.toLocaleTimeString('en-NZ', {hour: 'numeric', minute: '2-digit'})
6604                .replace(/\s?(am|pm)$/i, '');
6605            if (d) d.textContent = now.toLocaleDateString('en-NZ', {weekday: 'long', day: 'numeric', month: 'long'});
6606        };
6607
6608        const AGO = ['now', '2m ago', '8m ago'];
6609
6610        const build = (chip) => {
6611            const frag = document.createDocumentFragment();
6612            // two or three per screen: one card at a time made the phone look
6613            // idle, and a digest is the thing being sold
6614            [['title', 'body'], ['title2', 'body2'], ['title3', 'body3']].forEach((keys, i) => {
6615                const title = chip.dataset[keys[0]], body = chip.dataset[keys[1]];
6616                if (!title) return;
6617                const n = document.createElement('article');
6618                n.className = 'hpn';
6619                n.style.transitionDelay = (i * 620) + 'ms';
6620                n.innerHTML =
6621                    '<header><img src="' + iconSrc + '" alt="" width="18" height="18">' +
6622                    '<span class="hpn-app">Talkify</span><span class="hpn-ago"></span></header>' +
6623                    '<h4></h4><p></p>';
6624                n.querySelector('.hpn-ago').textContent = AGO[i] || 'earlier';
6625                n.querySelector('h4').textContent = title;
6626                n.querySelector('p').textContent = body;
6627                frag.appendChild(n);
6628            });
6629            return frag;
6630        };
6631
6632        const show = (idx) => {
6633            i = (idx + chips.length) % chips.length;
6634            chips.forEach((c, n) => c.classList.toggle('is-on', n === i));
6635            chips.forEach((c, n) => c.setAttribute('aria-selected', n === i ? 'true' : 'false'));
6636            root.replaceChildren(build(chips[i]));
6637            // let the browser paint the start state before transitioning in
6638            requestAnimationFrame(() => requestAnimationFrame(() =>
6639                root.querySelectorAll('.hpn').forEach(n => n.classList.add('is-in'))));
6640        };
6641
6642        const stop = () => { if (timer) { clearInterval(timer); timer = null; } };
6643        const start = () => { if (!reduce && !taken && !timer) timer = setInterval(() => show(i + 1), 7000); };
6644
6645        chips.forEach((chip, n) => {
6646            const take = () => { taken = true; stop(); show(n); };
6647            chip.addEventListener('click', take);
6648            chip.addEventListener('mouseenter', () => { stop(); show(n); });
6649            chip.addEventListener('mouseleave', () => { if (!taken) start(); });
6650        });
6651
6652        // do not animate a phone nobody is looking at
6653        const vis = new IntersectionObserver((es) => {
6654            es.forEach(e => e.isIntersecting ? start() : stop());
6655        }, {threshold: 0.2});
6656        vis.observe(root);
6657
6658        clock();
6659        setInterval(clock, 30000);
6660        show(0);
6661    })();
6662
6663    (function () {
6664        const hero = document.querySelector('.hero-bg');
6665        if (!hero) return;
6666        // Pointer parallax is a mouse affordance: a finger cannot hover, and
6667        // it is exactly the sort of movement prefers-reduced-motion is for.
6668        const mq = (q) => window.matchMedia && window.matchMedia(q).matches;
6669        if (mq('(prefers-reduced-motion: reduce)') || mq('(pointer: coarse)')) return;
6670
6671        let x = 0, y = 0, queued = false;
6672        const paint = () => {
6673            queued = false;
6674            hero.style.transform = `translate(${x}px,${y}px)`;
6675        };
6676        document.addEventListener('mousemove', (e) => {
6677            x = (e.clientX / window.innerWidth - .5) * 24;
6678            y = (e.clientY / window.innerHeight - .5) * 24;
6679            if (!queued) {
6680                queued = true;
6681                requestAnimationFrame(paint);
6682            }
6683        }, {passive: true});
6684    })();
6685
6686    // ─── Live call deck, messages animate in as if the call is happening now ───
6687    (function () {
6688        document.querySelectorAll('.deck').forEach(deck => {
6689            const rows = Array.from(deck.querySelectorAll('.deck-row'));
6690            if (!rows.length) return;
6691
6692            // Insert a typing indicator before each agent row
6693            rows.forEach(row => {
6694                if (row.classList.contains('agent')) {
6695                    const ts = row.querySelector('.ts')?.textContent || '';
6696                    const typing = document.createElement('div');
6697                    typing.className = 'deck-typing';
6698                    typing.innerHTML = `<span class="ts">${ts}</span><span class="who">Talkify</span><span class="dotset"><i></i><i></i><i></i></span>`;
6699                    row.parentNode.insertBefore(typing, row);
6700                }
6701            });
6702
6703            let started = false;
6704            const start = () => {
6705                if (started) return;
6706                started = true;
6707                let t = 400;
6708                rows.forEach(row => {
6709                    if (row.classList.contains('agent')) {
6710                        const typing = row.previousElementSibling;
6711                        if (typing && typing.classList.contains('deck-typing')) {
6712                            setTimeout(() => typing.classList.add('on'), t);
6713                            t += 900;
6714                            setTimeout(() => typing.classList.remove('on'), t);
6715                            t += 200;
6716                        }
6717                    }
6718                    setTimeout(() => row.classList.add('in'), t);
6719                    t += 1200;
6720                });
6721
6722                // After the prepared script plays, optionally append a follow-up exchange
6723                const followup = deck.dataset.followup;
6724                if (followup === 'on') {
6725                    setTimeout(() => {
6726                        appendDeckExchange(deck);
6727                    }, t + 1500);
6728                }
6729            };
6730
6731            const io = new IntersectionObserver(entries => {
6732                entries.forEach(e => {
6733                    if (e.isIntersecting) {
6734                        start();
6735                        io.unobserve(deck);
6736                    }
6737                });
6738            }, {threshold: 0.25});
6739            io.observe(deck);
6740        });
6741
6742        function appendDeckExchange(deck) {
6743            // Append one extra caller + agent exchange to the home hero deck
6744            const followups = [
6745                {
6746                    caller: "One more thing, can my partner come too?",
6747                    agent: "Of course. I'll add them to the appointment. Anything else?"
6748                },
6749                {
6750                    caller: "Is there parking?",
6751                    agent: "Yep, two-hour free parking on Vivian Street, or paid building parking off the lobby."
6752                },
6753            ];
6754            const ex = followups[Math.floor(Math.random() * followups.length)];
6755            const wave = deck.querySelector('.wave');
6756            const insertBefore = wave || deck.querySelector('.deck-foot');
6757
6758            const lastTs = deck.querySelectorAll('.deck-row .ts');
6759            const baseSec = parseInt((lastTs[lastTs.length - 1]?.textContent || '00:14').split(':')[1]) + 6;
6760            const fmtTs = s => `00:${String(s).padStart(2, '0')}`;
6761
6762            const callerRow = document.createElement('div');
6763            callerRow.className = 'deck-row caller';
6764            callerRow.innerHTML = `<span class="ts">${fmtTs(baseSec)}</span><span class="who">Caller</span><span class="msg">${ex.caller}</span>`;
6765            deck.insertBefore(callerRow, insertBefore);
6766
6767            const typingRow = document.createElement('div');
6768            typingRow.className = 'deck-typing';
6769            typingRow.innerHTML = `<span class="ts">${fmtTs(baseSec + 2)}</span><span class="who">Talkify</span><span class="dotset"><i></i><i></i><i></i></span>`;
6770            deck.insertBefore(typingRow, insertBefore);
6771
6772            const agentRow = document.createElement('div');
6773            agentRow.className = 'deck-row agent';
6774            agentRow.innerHTML = `<span class="ts">${fmtTs(baseSec + 3)}</span><span class="who">Talkify</span><span class="msg">${ex.agent}</span>`;
6775            deck.insertBefore(agentRow, insertBefore);
6776
6777            requestAnimationFrame(() => callerRow.classList.add('in'));
6778            setTimeout(() => typingRow.classList.add('on'), 1100);
6779            setTimeout(() => typingRow.classList.remove('on'), 2400);
6780            setTimeout(() => agentRow.classList.add('in'), 2500);
6781        }
6782    })();
6783
6784    // ─── Real conversations, bubbles type into existence as user scrolls in ───
6785    (function () {
6786        document.querySelectorAll('.convo').forEach(convo => {
6787            const bubs = Array.from(convo.querySelectorAll('.bub'));
6788            if (!bubs.length) return;
6789
6790            let started = false;
6791            const start = () => {
6792                if (started) return;
6793                started = true;
6794
6795                let t = 200;
6796                bubs.forEach((bub) => {
6797                    // Show typing indicator with the same alignment + colour, then swap to bubble
6798                    const typing = document.createElement('div');
6799                    typing.className = 'convo-typing' + (bub.classList.contains('caller') ? ' caller' : '');
6800                    const who = bub.classList.contains('caller') ? 'Caller' : 'Talkify';
6801                    typing.innerHTML = `<span class="lbl">${who}</span><span class="dotset"><i></i><i></i><i></i></span>`;
6802                    convo.insertBefore(typing, bub);
6803
6804                    const typingMs = bub.classList.contains('caller') ? 500 : 800;
6805                    setTimeout(() => typing.classList.add('on'), t);
6806                    t += typingMs;
6807                    setTimeout(() => {
6808                        typing.classList.remove('on');
6809                        typing.remove();
6810                    }, t);
6811                    setTimeout(() => bub.classList.add('in'), t + 50);
6812                    t += 450; // settle time before next message
6813                });
6814            };
6815
6816            /* Watch the transcript's wrapper where it has one. On the home page
6817               the transcript sits inside a phone, and a clipped flex child that
6818               deep gets no intersection entries at all, so a threshold against
6819               the transcript itself never fires and the conversation never
6820               starts. The wrapper is an ordinary block in normal flow. */
6821            const target = convo.closest('.convo-device') || convo;
6822            const io = new IntersectionObserver(entries => {
6823                entries.forEach(e => {
6824                    if (e.isIntersecting) {
6825                        start();
6826                        io.unobserve(target);
6827                    }
6828                });
6829            }, {threshold: 0.2});
6830            io.observe(target);
6831        });
6832    })();
6833
6834    // ─── Live PA digest, notifications drop in on scroll, more arrive as you watch ───
6835    (function () {
6836        document.querySelectorAll('.pa-floater').forEach(floater => {
6837            const initialRows = Array.from(floater.querySelectorAll('.row'));
6838            if (!initialRows.length) return;
6839
6840            const queue = [
6841                {
6842                    lbl: 'Returning client · routed',
6843                    name: 'Liam, message taken for Tom',
6844                    meta: '<span class="vip" style="color:var(--mute)">● Routine</span>'
6845                },
6846                {
6847                    lbl: 'New booking',
6848                    name: 'Te Aroha · Saturday haircut',
6849                    meta: '<span class="vip" style="color:var(--signal)">● Booked</span>'
6850                },
6851                {
6852                    lbl: 'Urgent · escalated to mobile',
6853                    name: 'Maria @ Hartwell, sent to your phone',
6854                    meta: '<span class="vip" style="color:var(--coral)">● VIP</span>'
6855                },
6856                {lbl: 'Quietly handled', name: '14 vendors politely declined', meta: ''},
6857            ];
6858            let qIdx = 0;
6859            let started = false;
6860
6861            const start = () => {
6862                if (started) return;
6863                started = true;
6864                initialRows.forEach((row, i) => {
6865                    setTimeout(() => {
6866                        row.classList.add('in', 'ping');
6867                        setTimeout(() => row.classList.remove('ping'), 1400);
6868                    }, i * 1200 + 400);
6869                });
6870
6871                // After initial settle, push a new notification every 9 seconds
6872                const settled = initialRows.length * 1200 + 2000;
6873                setTimeout(() => {
6874                    const interval = setInterval(() => {
6875                        if (!floater.isConnected) {
6876                            clearInterval(interval);
6877                            return;
6878                        }
6879                        const item = queue[qIdx % queue.length];
6880                        qIdx++;
6881                        const newRow = document.createElement('div');
6882                        newRow.className = 'row in fresh ping';
6883                        newRow.innerHTML = `
6884            <span class="lbl">${item.lbl}</span>
6885            <span class="name">${item.name}</span>
6886            ${item.meta ? '<span>' + item.meta + '</span>' : ''}
6887          `;
6888                        floater.insertBefore(newRow, floater.firstChild);
6889
6890                        // Drop the oldest if we have too many, keep card from growing
6891                        const all = floater.querySelectorAll('.row');
6892                        if (all.length > 4) {
6893                            const oldest = all[all.length - 1];
6894                            oldest.style.transition = 'opacity .5s ease, transform .5s ease, max-height .5s ease, margin .5s ease, padding .5s ease';
6895                            oldest.style.opacity = '0';
6896                            oldest.style.transform = 'translateY(8px)';
6897                            setTimeout(() => oldest.remove(), 600);
6898                        }
6899
6900                        setTimeout(() => newRow.classList.remove('ping'), 1400);
6901                    }, 9000);
6902                }, settled);
6903            };
6904
6905            const io = new IntersectionObserver(entries => {
6906                entries.forEach(e => {
6907                    if (e.isIntersecting) {
6908                        start();
6909                        io.unobserve(floater);
6910                    }
6911                });
6912            }, {threshold: 0.3});
6913            io.observe(floater);
6914        });
6915    })();
6916
6917    // ─── Conversion + engagement events → GA4 / GTM dataLayer ───
6918    // Every tel: tap, CTA click and lead form submit lands in the dataLayer so
6919    // GTM/GA4 can build conversions without touching the templates again.
6920    (function () {
6921        const page = "industry-fish-and-chips";
6922        const push = (event, params) => {
6923            window.dataLayer = window.dataLayer || [];
6924            window.dataLayer.push(Object.assign({event: event, page_key: page}, params || {}));
6925        };
6926
6927        // Phone taps: the demo line and the sign-up lines are separate conversions.
6928        // The demo lines come from App\Services\Market (they differ by country
6929        // and by how a visitor has to dial them), matched on their last eight
6930        // digits so the local and the international form are the same line.
6931                const demoTails = ["32421262","92420020"];
6932        document.querySelectorAll('a[href^="tel:"]').forEach(a => {
6933            a.addEventListener('click', () => {
6934                const num = (a.getAttribute('href') || '').replace('tel:', '');
6935                const digits = num.replace(/\D/g, '');
6936                const isDemo = demoTails.some(t => t && digits.endsWith(t));
6937                push(isDemo ? 'demo_call_click' : 'phone_signup_click', {
6938                    phone_number: num,
6939                    link_text: (a.textContent || '').trim().slice(0, 80),
6940                });
6941            });
6942        });
6943
6944        // CTA buttons (primary/blue/ghost), which CTA, on which page
6945        document.querySelectorAll('a.btn').forEach(a => {
6946            a.addEventListener('click', () => {
6947                push('cta_click', {
6948                    cta_text: (a.textContent || '').trim().slice(0, 80),
6949                    cta_style: a.classList.contains('btn-primary') ? 'primary'
6950                        : a.classList.contains('btn-blue') ? 'blue' : 'ghost',
6951                    cta_href: a.getAttribute('href') || '',
6952                });
6953            });
6954        });
6955
6956        // Lead forms: signup/contact, live demo call, support
6957        document.querySelectorAll('form').forEach(form => {
6958            const action = form.getAttribute('action') || '';
6959            let event = null;
6960            if (action.includes('/signup/verify')) event = 'sign_up';
6961            else if (action.includes('/signup/send-code')) event = 'sign_up_start';
6962            else if (action.includes('/contact')) event = 'generate_lead';
6963            else if (action.includes('/demo')) event = 'demo_call_request';
6964            else if (action.includes('/support')) event = 'support_request';
6965            if (!event) return;
6966            form.addEventListener('submit', () => {
6967                const agent = form.querySelector('input[name="agent_type"]:checked');
6968                push(event, {
6969                    form_action: action,
6970                    agent_type: agent ? agent.value : undefined,
6971                });
6972            });
6973        });
6974    })();
6975
6976    /* Agents mega-menu. Desktop opens it on hover/focus via CSS; this handles
6977       the click path, which is the only way in on touch, plus Escape and
6978       click-outside. */
6979    (function () {
6980        const drops = document.querySelectorAll('[data-nav-drop]');
6981        if (!drops.length) return;
6982
6983        const closeAll = (except) => drops.forEach((drop) => {
6984            if (drop === except) return;
6985            drop.classList.remove('is-open');
6986            drop.querySelector('.nav-drop-btn')?.setAttribute('aria-expanded', 'false');
6987        });
6988
6989        drops.forEach((drop) => {
6990            const trigger = drop.querySelector('.nav-drop-btn');
6991            if (!trigger) return;
6992
6993            trigger.addEventListener('click', (event) => {
6994                event.preventDefault();
6995                event.stopPropagation();
6996                const open = drop.classList.toggle('is-open');
6997                trigger.setAttribute('aria-expanded', open ? 'true' : 'false');
6998                closeAll(drop);
6999            });
7000        });
7001
7002        document.addEventListener('click', (event) => {
7003            if (!event.target.closest('[data-nav-drop]')) closeAll();
7004        });
7005
7006        document.addEventListener('keydown', (event) => {
7007            if (event.key === 'Escape') closeAll();
7008        });
7009
7010        window.talkifyCloseNavDrops = closeAll;
7011    })();
7012
7013    (function () {
7014        const btn = document.querySelector('.menu-btn');
7015        const nav = document.querySelector('.nav ul');
7016        if (!btn || !nav) return;
7017        btn.addEventListener('click', () => {
7018            const open = nav.style.display === 'flex';
7019            // Collapsing the menu should not leave the Agents accordion open
7020            // behind it, or it reappears expanded next time.
7021            if (open && window.talkifyCloseNavDrops) window.talkifyCloseNavDrops();
7022            nav.style.display = open ? 'none' : 'flex';
7023            nav.style.position = 'fixed';
7024            nav.style.top = '92px';
7025            nav.style.left = '20px';
7026            nav.style.right = '20px';
7027            nav.style.flexDirection = 'column';
7028            nav.style.background = 'var(--ink-2)';
7029            nav.style.border = '1px solid var(--line)';
7030            nav.style.borderRadius = '14px';
7031            nav.style.padding = '12px';
7032            nav.style.zIndex = '85';
7033        });
7034    })();
7035
7036    /* Theme toggle, persist choice, flip data-theme on <html> */
7037    (function () {
7038        var toggles = document.querySelectorAll('[data-theme-toggle]');
7039        if (!toggles.length) return;
7040        toggles.forEach(function (btn) {
7041            btn.addEventListener('click', function () {
7042                var current = document.documentElement.getAttribute('data-theme') === 'light' ? 'light' : 'dark';
7043                var next = current === 'light' ? 'dark' : 'light';
7044                document.documentElement.setAttribute('data-theme', next);
7045                try {
7046                    localStorage.setItem('talkify-theme', next);
7047                } catch (e) {
7048                }
7049            });
7050        });
7051    })();
7052</script>
7052
7053
7054</body>
7055</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.