PageSourceSearch

https://laundrykingnyc.com/

html laundrykingnyc.com collected 2026-10-02 00:30:47 UTC 70,265 bytes, 1,346 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en" data-i18n-title-key="home.title">
3<head>
4<script>/* The project's default Firebase address cannot be removed, so it is sent
5   to the real domain here: an identical copy answering on two hostnames
6   invites the wrong one into search results and into customers' bookmarks. */
7if(location.hostname.endsWith(".web.app")||location.hostname.endsWith(".firebaseapp.com"))location.replace("https://laundrykingnyc.com"+location.pathname+location.search+location.hash);</script>
7
8
9<meta charset="UTF-8">
10<meta name="viewport" content="width=device-width, initial-scale=1.0">
11<title>Brooklyn Laundry Pickup & Delivery — Wash, Fold & Dry Cleaning | Laundry King</title>
12<meta name="description" data-i18n-content="home.metaDescription" content="Brooklyn's most trusted laundry pickup & delivery service. Wash & Fold from $1.55/lb, Wash & Press, Dry Cleaning. Free pickup, 1–2 day turnaround. Order online in 60 seconds.">
13<meta name="keywords" content="brooklyn laundry, laundry pickup brooklyn, laundry delivery brooklyn, wash and fold brooklyn, dry cleaning brooklyn, laundromat brooklyn, laundry service nyc, wash and press brooklyn">
14<link rel="icon" href="/logo.png">
15<link rel="manifest" href="/manifest.json">
16<meta name="theme-color" content="#061f75">
17<meta name="apple-mobile-web-app-capable" content="yes">
18<meta name="mobile-web-app-capable" content="yes">
19<meta name="apple-mobile-web-app-title" content="Laundry King">
20<link rel="apple-touch-icon" href="/logo.png">
21
22<!-- ─────────────────── SEO / Discovery ───────────────────
23     Canonical URL, robots directives, Open Graph (Facebook,
24     LinkedIn, WhatsApp, iMessage previews), Twitter Card,
25     and geo hints for local SEO. Update CANONICAL_HOST in one
26     place if the production domain changes.
27     ─────────────────────────────────────────────────────── -->
28<link rel="canonical" href="https://laundrykingnyc.com/">
29<meta name="author" content="Laundry King Brooklyn">
30<meta name="geo.region" content="US-NY">
31<meta name="geo.placename" content="Brooklyn, New York">
32<meta name="geo.position" content="40.5774;-73.9787">
33<meta name="ICBM" content="40.5774, -73.9787">
34
35<meta property="og:type" content="website">
36<meta property="og:locale" content="en_US">
37<meta property="og:locale:alternate" content="es_US">
38<meta property="og:locale:alternate" content="ru_RU">
39<meta property="og:site_name" content="Laundry King">
40<meta property="og:title" content="Brooklyn Laundry Pickup & Delivery — Laundry King">
41<meta property="og:description" content="Brooklyn's most trusted laundry pickup & delivery. Wash & Fold from $1.55/lb, Wash & Press, Dry Cleaning. Free pickup, 1–2 day turnaround.">
42<meta property="og:url" content="https://laundrykingnyc.com/">
43<meta property="og:image" content="https://laundrykingnyc.com/images/storefront-neptune-ave.jpg">
44<meta property="og:image:alt" content="Laundry King Brooklyn — laundry pickup and delivery">
45
46<meta name="twitter:card" content="summary_large_image">
47<meta name="twitter:title" content="Brooklyn Laundry Pickup & Delivery — Laundry King">
48<meta name="twitter:description" content="Brooklyn's most trusted laundry pickup & delivery. Wash & Fold from $1.55/lb. Order online in 60 seconds.">
49<meta name="twitter:image" content="https://laundrykingnyc.com/images/storefront-neptune-ave.jpg">
50<meta name="twitter:image:alt" content="Laundry King Brooklyn">
51
52<!-- LocalBusiness structured data — drives Google's "Local Pack" listing,
53     map results, knowledge panel, and rich snippet eligibility. -->
54<script type="application/ld+json">
55{
56  "@context": "https://schema.org",
57  "@type": "LaundryService",
58  "@id": "https://laundrykingnyc.com/#business",
59  "name": "Laundry King Brooklyn",
60  "alternateName": "Laundry King",
61  "description": "Brooklyn's most trusted laundry pickup & delivery service. Wash & Fold, Wash & Press, and Dry Cleaning with 1–2 day turnaround.",
62  "url": "https://laundrykingnyc.com/",
63  "logo": "https://laundrykingnyc.com/logo.png",
64  "image": "https://laundrykingnyc.com/logo.png",
65  "telephone": "+1-718-737-4242",
66  "email": "[email protected]",
67  "priceRange": "$$",
68  "currenciesAccepted": "USD",
69  "paymentAccepted": "Cash, Credit Card, Zelle",
70  "address": {
71    "@type": "PostalAddress",
72    "streetAddress": "39 Neptune Ave",
73    "addressLocality": "Brooklyn",
74    "addressRegion": "NY",
75    "postalCode": "11235",
76    "addressCountry": "US"
77  },
78  "geo": {
79    "@type": "GeoCoordinates",
80    "latitude": 40.5774,
81    "longitude": -73.9787
82  },
83  "openingHoursSpecification": [{
84    "_comment": "The laundromat at 39 Neptune Ave is open 24/7. The pickup & delivery SERVICE has its own, narrower window — see hoursAvailable on the Service node below. The two must never be conflated.",
85    "@type": "OpeningHoursSpecification",
86    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
87    "opens": "00:00",
88    "closes": "23:59"
89  }],
90  "makesOffer": {
91    "@type": "Offer",
92    "itemOffered": {
93      "@type": "Service",
94      "name": "Laundry Pickup & Delivery",
95      "serviceType": "Laundry Pickup and Delivery",
96      "provider": {"@id": "https://laundrykingnyc.com/#business"},
97      "hoursAvailable": {
98        "@type": "OpeningHoursSpecification",
99        "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
100        "opens": "07:00",
101        "closes": "23:00"
102      }
103    }
104  },
105  "areaServed": [
106    {"@type":"City","name":"Brooklyn","sameAs":"https://en.wikipedia.org/wiki/Brooklyn"},
107    {"@type":"Place","name":"Sheepshead Bay, Brooklyn"},
108    {"@type":"Place","name":"Brighton Beach, Brooklyn"},
109    {"@type":"Place","name":"Bay Ridge, Brooklyn"},
110    {"@type":"Place","name":"Bensonhurst, Brooklyn"},
111    {"@type":"Place","name":"Bath Beach, Brooklyn"},
112    {"@type":"Place","name":"Dyker Heights, Brooklyn"},
113    {"@type":"Place","name":"Midwood, Brooklyn"},
114    {"@type":"Place","name":"Gravesend, Brooklyn"},
115    {"@type":"Place","name":"Kings Highway, Brooklyn"},
116    {"@type":"Place","name":"Bay Parkway, Brooklyn"},
117    {"@type":"Place","name":"Borough Park, Brooklyn"},
118    {"@type":"Place","name":"Sunset Park, Brooklyn"},
119    {"@type":"Place","name":"Marine Park, Brooklyn"},
120    {"@type":"Place","name":"Mill Basin, Brooklyn"},
121    {"@type":"Place","name":"Flatbush, Brooklyn"},
122    {"@type":"Place","name":"East Flatbush, Brooklyn"},
123    {"@type":"Place","name":"Coney Island, Brooklyn"},
124    {"@type":"Place","name":"Kensington, Brooklyn"},
125    {"@type":"Place","name":"Windsor Terrace, Brooklyn"}
126  ],
127  "serviceType": ["Wash and Fold","Wash and Press","Dry Cleaning","Laundry Pickup","Laundry Delivery"],
128  "hasOfferCatalog": {
129    "@type": "OfferCatalog",
130    "name": "Laundry Services",
131    "itemListElement": [
132      {"@type":"Offer","itemOffered":{"@type":"Service","name":"Wash & Fold"},"priceSpecification":{"@type":"UnitPriceSpecification","price":"1.55","priceCurrency":"USD","unitText":"per pound"}},
133      {"@type":"Offer","itemOffered":{"@type":"Service","name":"Wash & Press — On Hanger"},"price":"4.50","priceCurrency":"USD"},
134      {"@type":"Offer","itemOffered":{"@type":"Service","name":"Wash & Press — Shirt in Box"},"price":"5.25","priceCurrency":"USD"},
135      {"@type":"Offer","itemOffered":{"@type":"Service","name":"Dry Cleaning"},"priceCurrency":"USD"}
136    ]
137  },
138  "sameAs": [
139    "https://apps.apple.com/us/app/laundry-king/id1489471695",
140    "https://play.google.com/store/apps/details?id=com.LaundryKing"
141  ]
142}
143</script>
143
144<!-- ───────────────────────────────────────────────────── -->
145<script>
146if ('serviceWorker' in navigator) {
147  navigator.serviceWorker.register('/sw.js').then(reg => {
148    const checkForUpdate = () => reg.update().catch(() => {});
149    checkForUpdate();
150    document.addEventListener('visibilitychange', () => {
151      if (document.visibilityState === 'visible') checkForUpdate();
152    });
153    setInterval(checkForUpdate, 60 * 1000);
154    reg.addEventListener('updatefound', () => {
155      const newSW = reg.installing;
156      newSW.addEventListener('statechange', () => {
157        if (newSW.state === 'installed' && navigator.serviceWorker.controller) {
158          document.getElementById('sw-update-bar').style.display = 'block';
159        }
160      });
161    });
162  });
163  let _swReloaded = false;
164  navigator.serviceWorker.addEventListener('controllerchange', () => {
165    if (_swReloaded) return;
166    _swReloaded = true;
167    window.location.reload();
168  });
169}
170window.applySwUpdate = function() {
171  navigator.serviceWorker.getRegistration().then(reg => {
172    if (reg?.waiting) reg.waiting.postMessage({ type: 'SKIP_WAITING' });
173    else window.location.reload();
174  });
175};
176</script>
176
177<link rel="stylesheet" href="/shared.css">
178<style>
179/* ── HERO ── */
180.hero {
181  background: linear-gradient(155deg, var(--navy) 50%, var(--navy2) 100%);
182  color: #fff; padding: 80px 32px 100px;
183  position: relative; overflow: hidden;
184}
185.hero::before {
186  content: '';
187  position: absolute; inset: 0;
188  background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ffffff' fill-opacity='0.04'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/svg%3E");
189}
190.hero-inner {
191  max-width: 1100px; margin: 0 auto;
192  display: grid; grid-template-columns: 1fr 1fr;
193  gap: 60px; align-items: center; position: relative;
194}
195.hero-badge {
196  display: inline-flex; align-items: center; gap: 6px;
197  background: rgba(255,111,0,.18); border: 1px solid rgba(255,111,0,.4);
198  color: var(--orange); border-radius: 100px;
199  padding: 5px 16px; font-size: 13px; font-weight: 600;
200  margin-bottom: 22px; letter-spacing: .5px;
201}
202.hero h1 {
203  font-family: 'Bebas Neue', sans-serif;
204  font-size: clamp(48px, 7vw, 80px);
205  line-height: .95; letter-spacing: 2px; margin-bottom: 20px;
206}
207.hero h1 span:last-of-type { color: var(--orange); }
208.hero p { font-size: 17px; opacity: .82; line-height: 1.65; margin-bottom: 36px; max-width: 440px; }
209.hero-btns { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
210/* The gradient, the sweep and the breathing glow now come from .btn-orange in
211   shared.css, so every CTA on the site moves the same way. What is left here
212   is what the hero alone needs: it is the single thing the page is asking for,
213   so it runs larger than the same button elsewhere, and its arrow lives in CSS
214   rather than in the label — so it can step forward on hover, and so
215   translators never have to carry a glyph. */
216.hero-btns .btn-orange {
217  font-size: 17px; padding: 18px 42px; letter-spacing: .4px;
218}
219.hero-btns .btn-orange::after {
220  content: '→'; display: inline-block; margin-left: 2px;
221  transition: transform .18s ease;
222}
223.hero-btns .btn-orange:hover { transform: translateY(-2px) scale(1.02); }
224.hero-btns .btn-orange:hover::after { transform: translateX(5px); }
225.hero-btns .btn-orange:active { transform: translateY(0) scale(.99); }
226@media (prefers-reduced-motion: reduce) {
227  .hero-btns .btn-orange::after { transition: none; }
228}
229.hero-visual {
230  display: flex; justify-content: center; align-items: center;
231}
232.hero-card {
233  background: rgba(255,255,255,.1);
234  border: 1px solid rgba(255,255,255,.15);
235  backdrop-filter: blur(12px);
236  border-radius: 24px; padding: 32px;
237  /* A fixed 320px could not shrink, so on a narrow screen the card ran past
238     the edge — which is why it was hidden outright below 900px instead. */
239  width: 100%; max-width: 320px;
240}
241.hero-card-title { font-weight: 700; font-size: 18px; margin-bottom: 20px; }
242.hero-stat {
243  /* Eight rows now, so each one gives back a little height. Values sit hard
244     right and are allowed to wrap: a label and a value that both refuse to
245     shrink would otherwise push each other out of a 320px card. */
246  display: flex; justify-content: space-between; align-items: center;
247  gap: 12px;
248  padding: 10px 0; border-bottom: 1px solid rgba(255,255,255,.1);
249}
250.hero-stat:last-child { border-bottom: none; }
251.hero-stat .label { opacity: .7; font-size: 14px; flex: 0 0 auto; }
252.hero-stat .val {
253  font-weight: 700; color: var(--orange); font-size: 16px;
254  text-align: right; min-width: 0;
255}
256/* Min-order row is clickable — taps it routes the customer straight to
257   the sign-in / order screen. Subtle hover + focus affordance so the
258   row looks tappable without breaking the visual rhythm of the card. */
259.hero-stat-link {
260  text-decoration: none; color: inherit;
261  margin: 0 -8px; padding: 12px 8px;
262  border-radius: 10px;
263  cursor: pointer;
264  transition: background .18s, transform .15s;
265}
266.hero-stat-link:hover { background: rgba(255,255,255,.06); transform: translateX(2px); }
267.hero-stat-link:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
268/* The app row is the only one that leads off the page, so it has to look
269   different while nobody is touching it. Hover was the whole cue before, and
270   a phone has no hover at all — on the device where the App Store link
271   actually matters, the row read as one more line of text. So it sits in the
272   card as its own chip: lifted off the panel, outlined in orange, with the
273   same band of light crossing it that the order buttons carry. */
274.hero-stat-app {
275  margin: 8px -10px; padding: 13px 12px;
276  border: 1px solid rgba(255,145,60,.45);
277  border-bottom: 1px solid rgba(255,145,60,.45);
278  border-radius: 14px;
279  background: rgba(255,255,255,.08);
280  position: relative; overflow: hidden; isolation: isolate;
281  animation: appRowGlow 3.2s ease-in-out infinite;
282}
283.hero-stat-app::before {
284  content: ''; position: absolute; z-index: 1;
285  top: -20%; bottom: -20%; left: -60%; width: 46%;
286  background: linear-gradient(100deg, transparent, rgba(255,255,255,.22), transparent);
287  transform: skewX(-22deg);
288  pointer-events: none;
289  animation: ctaShine 3.2s linear infinite;
290}
291@keyframes appRowGlow {
292  0%, 100% { box-shadow: 0 0 0 0 rgba(255,145,60,0);   border-color: rgba(255,145,60,.38); }
293  50%      { box-shadow: 0 0 18px 0 rgba(255,145,60,.28); border-color: rgba(255,145,60,.75); }
294}
295.hero-stat-app .val::after {
296  content: '›'; margin-left: 8px;
297  font-weight: 700;
298  display: inline-block; transition: transform .18s;
299}
300.hero-stat-app:hover { background: rgba(255,255,255,.14); }
301.hero-stat-app:hover .val::after { transform: translateX(3px); }
302@media (prefers-reduced-motion: reduce) {
303  .hero-stat-app, .hero-stat-app::before { animation: none; }
304  .hero-stat-app::before { opacity: 0; }
305  .hero-stat-app { border-color: rgba(255,145,60,.75); }
306  .hero-stat-app .val::after { transition: none; }
307}
308
309/* ── VISIT BAR ── */
310.visit-bar {
311  background: linear-gradient(135deg, #040f3a 0%, #061f75 60%, #0a2a99 100%);
312  padding: 0 32px;
313  border-top: 3px solid var(--orange);
314  border-bottom: 3px solid rgba(255,111,0,.25);
315}
316.visit-bar-inner {
317  max-width: 1100px; margin: 0 auto;
318  display: flex; align-items: center; gap: 40px;
319  padding: 28px 0;
320}
321.visit-24 {
322  font-family: 'Bebas Neue', sans-serif;
323  font-size: 90px; line-height: 1;
324  color: var(--orange);
325  text-shadow: 0 0 40px rgba(255,111,0,.45);
326  flex-shrink: 0;
327  letter-spacing: 2px;
328}
329.visit-divider {
330  width: 3px; height: 72px; flex-shrink: 0;
331  background: linear-gradient(to bottom, transparent, rgba(255,111,0,.6), transparent);
332}
333.visit-info { flex: 1; }
334.visit-title {
335  font-family: 'Bebas Neue', sans-serif;
336  font-size: 32px; letter-spacing: 2px;
337  color: #fff; line-height: 1;
338}
339.visit-sub {
340  font-size: 14px; color: rgba(255,255,255,.72);
341  margin-top: 6px; line-height: 1.5;
342}
343.visit-parking {
344  display: inline-flex; align-items: center; gap: 5px;
345  margin-top: 8px; background: rgba(255,111,0,.15);
346  border: 1px solid rgba(255,111,0,.35); border-radius: 100px;
347  padding: 3px 12px; font-size: 12px; font-weight: 600;
348  color: var(--orange);
349}
350.visit-addr {
351  flex-shrink: 0; text-align: right;
352  color: rgba(255,255,255,.8); font-size: 14px; line-height: 1.6;
353}
354.visit-addr strong { color: #fff; font-size: 15px; }
355.visit-addr a {
356  display: inline-flex; align-items: center; gap: 4px;
357  margin-top: 6px; color: #ffd166;
358  font-size: 13px; font-weight: 600; text-decoration: none;
359}
360.visit-addr a:hover { text-decoration: underline; }
361@media (max-width: 768px) {
362  .visit-bar-inner { flex-direction: column; align-items: flex-start; gap: 16px; padding: 24px 0; }
363  .visit-24 { font-size: 64px; }
364  .visit-divider { display: none; }
365  .visit-addr { text-align: left; }
366}
367
368/* ── HOW IT WORKS ── */
369.steps-grid {
370  display: grid; grid-template-columns: repeat(4, 1fr);
371  gap: 24px; margin-top: 48px;
372}
373.step-card {
374  background: var(--white); border-radius: var(--radius);
375  box-shadow: var(--shadow); padding: 28px 24px;
376  position: relative; border-top: 3px solid var(--orange);
377  transition: transform .2s;
378}
379.step-card:hover { transform: translateY(-4px); }
380
381/* ── QUICK ORDER SECTION ──
382   Frictionless entry: a pulsing orange banner + 4 service cards on the
383   landing page. Tapping a service card opens the guest-checkout flow
384   (?guest=1&svc=…) — customer fills the order and only enters their
385   name + phone at the very end. Stays brand-aligned (navy/orange). */
386.qo-bg {
387  background: linear-gradient(180deg, #fff 0%, #fff7ed 100%);
388}
389.qo-banner {
390  display: inline-flex; align-items: center; gap: 8px;
391  background: linear-gradient(135deg, var(--orange), var(--orange2));
392  color: #fff;
393  padding: 8px 18px;
394  border-radius: 100px;
395  font-family: 'Mulish', sans-serif;
396  font-weight: 800;
397  font-size: 14px;
398  letter-spacing: .4px;
399  box-shadow: 0 6px 22px rgba(255,111,0,.32);
400  margin-bottom: 18px;
401  animation: qo-pulse 2.2s ease-in-out infinite;
402}
403.qo-banner .qo-dot {
404  width: 9px; height: 9px; border-radius: 50%;
405  background: #fff;
406  animation: qo-dot 1.4s ease-in-out infinite;
407  box-shadow: 0 0 0 0 rgba(255,255,255,.7);
408}
409@keyframes qo-pulse {
410  0%, 100% { box-shadow: 0 6px 22px rgba(255,111,0,.32); transform: scale(1); }
411  50%      { box-shadow: 0 8px 32px rgba(255,111,0,.5);  transform: scale(1.025); }
412}
413@keyframes qo-dot {
414  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,255,.8); }
415  50%      { box-shadow: 0 0 0 7px rgba(255,255,255,0); }
416}
417.qo-title {
418  font-family: 'Bebas Neue', sans-serif;
419  font-size: clamp(34px, 5vw, 52px);
420  letter-spacing: 2px;
421  color: var(--navy);
422  line-height: 1.05;
423  margin-bottom: 8px;
424}
425.qo-title span { color: var(--orange); }
426.qo-sub {
427  font-size: 15px; color: var(--muted);
428  max-width: 540px; margin: 0 auto 30px;
429  line-height: 1.55;
430}
431.qo-grid {
432  display: grid; grid-template-columns: repeat(4, 1fr);
433  gap: 16px; max-width: 980px; margin: 0 auto;
434}
435.qo-card {
436  display: flex; flex-direction: column; align-items: center; justify-content: center;
437  background: #fff; border: 2px solid var(--border);
438  border-radius: var(--radius);
439  padding: 22px 14px;
440  cursor: pointer;
441  transition: transform .18s, box-shadow .2s, border-color .2s, background .2s;
442  text-decoration: none; color: var(--text);
443  position: relative; overflow: hidden;
444}
445.qo-card::before {
446  content: ''; position: absolute; inset: 0;
447  background: linear-gradient(135deg, rgba(255,111,0,.06), transparent 60%);
448  opacity: 0; transition: opacity .25s;
449}
450.qo-card:hover {
451  transform: translateY(-4px);
452  border-color: var(--orange);
453  box-shadow: 0 14px 36px rgba(6,31,117,.14);
454}
455.qo-card:hover::before { opacity: 1; }
456/* The badge carries the same three things as the order buttons — a drifting
457   gradient, a band of light crossing it, a soft glow — so a service tile reads
458   as the same kind of object as the button it leads to. Navy rather than
459   orange: the tiles sit on a warm cream field beside orange prices, and four
460   orange blocks in a row would flatten the one thing that should stand out. */
461.qo-card .qo-ico {
462  width: 66px; height: 66px; margin-bottom: 14px;
463  display: grid; place-items: center;
464  border-radius: 20px;
465  position: relative; overflow: hidden; isolation: isolate;
466  color: #fff;
467  background: linear-gradient(100deg, var(--navy) 0%, #0a2a99 28%, #2b56d8 50%, #0a2a99 72%, var(--navy) 100%);
468  background-size: 260% 100%;
469  box-shadow: 0 8px 22px rgba(6,31,117,.28), inset 0 1px 0 rgba(255,255,255,.22);
470  animation: ctaFlow 9s ease-in-out infinite;
471  transition: transform .2s, box-shadow .2s;
472}
473.qo-card .qo-ico::before {
474  content: ''; position: absolute; z-index: 1;
475  top: -20%; bottom: -20%; left: -60%; width: 46%;
476  background: linear-gradient(100deg, transparent, rgba(255,255,255,.42), transparent);
477  transform: skewX(-22deg);
478  pointer-events: none;
479  animation: ctaShine 2.6s linear infinite;
480}
481.qo-card .qo-ico svg { width: 34px; height: 34px; display: block; }
482.qo-card:hover .qo-ico {
483  transform: translateY(-2px) scale(1.05);
484  box-shadow: 0 14px 30px rgba(6,31,117,.36), inset 0 1px 0 rgba(255,255,255,.3);
485}
486@media (prefers-reduced-motion: reduce) {
487  .qo-card .qo-ico { animation: none; }
488  .qo-card .qo-ico::before { animation: none; opacity: 0; }
489  .qo-card:hover .qo-ico { transform: none; }
490}
491.qo-card .qo-name {
492  font-weight: 800; font-size: 15px; color: var(--navy);
493  letter-spacing: .2px; margin-bottom: 4px; text-align: center;
494}
495.qo-card .qo-price {
496  font-size: 12px; color: var(--orange); font-weight: 700;
497  text-align: center;
498}
499
500/* ── TRUST / TECH SECTION ── */
501.trust-bg { background: linear-gradient(180deg, #f4f5fa 0%, #fff 100%); }
502.trust-grid {
503  display: grid; grid-template-columns: repeat(3, 1fr);
504  gap: 24px; margin-top: 48px;
505}
506.trust-card {
507  background: var(--white); border-radius: var(--radius);
508  box-shadow: var(--shadow); padding: 32px 26px;
509  position: relative; border-top: 3px solid var(--navy);
510  transition: transform .2s; text-align: center;
511}
512.trust-card:hover { transform: translateY(-4px); }
513.trust-icon {
514  width: 64px; height: 64px; margin: 0 auto 18px;
515  border-radius: 50%; background: linear-gradient(135deg, var(--navy), var(--navy2));
516  display: flex; align-items: center; justify-content: center;
517  font-size: 30px; box-shadow: 0 6px 20px rgba(6,31,117,.18);
518}
519.trust-card h3 {
520  font-size: 17px; font-weight: 800; color: var(--navy);
521  margin-bottom: 10px; letter-spacing: -0.2px;
522}
523.trust-card p {
524  font-size: 14px; color: var(--muted); line-height: 1.6;
525}
526.trust-card .trust-pill {
527  display: inline-flex; align-items: center; gap: 6px;
528  background: #ecfdf5; color: #15803d;
529  padding: 4px 10px; border-radius: 100px;
530  font-size: 11px; font-weight: 700; letter-spacing: .5px;
531  text-transform: uppercase; margin-bottom: 12px;
532}
533.trust-pay-logos {
534  display: flex; align-items: center; justify-content: center;
535  gap: 14px; margin-top: 14px; flex-wrap: wrap;
536}
537.trust-pay-logo {
538  background: #000; color: #fff; padding: 7px 14px;
539  border-radius: 8px; font-size: 13px; font-weight: 700;
540  letter-spacing: -0.3px; display: inline-flex; align-items: center; gap: 4px;
541}
542.trust-status-line {
543  display: flex; align-items: center; gap: 8px;
544  margin-top: 14px; padding: 10px 12px;
545  background: #f0fdf4; border-radius: 12px;
546  font-size: 12px; color: #166534; font-weight: 600;
547  text-align: left;
548}
549.trust-status-dot {
550  width: 8px; height: 8px; border-radius: 50%;
551  background: #16a34a; box-shadow: 0 0 0 4px rgba(22,163,74,.18);
552  flex-shrink: 0;
553  animation: trust-pulse 1.6s ease-in-out infinite;
554}
555@keyframes trust-pulse {
556  0%, 100% { box-shadow: 0 0 0 0 rgba(22,163,74,.4); }
557  50%      { box-shadow: 0 0 0 6px rgba(22,163,74,.05); }
558}
559.step-num {
560  font-family: 'Bebas Neue', sans-serif;
561  font-size: 48px; color: rgba(6,31,117,.08);
562  position: absolute; top: 12px; right: 16px; line-height: 1;
563}
564.step-icon { font-size: 36px; margin-bottom: 14px; }
565.step-card h3 { font-size: 16px; font-weight: 700; color: var(--navy); margin-bottom: 8px; }
566.step-card p { font-size: 14px; color: var(--muted); line-height: 1.55; }
567
568/* ── SERVICES PREVIEW ── */
569.services-bg { background: var(--white); }
570.svc-grid {
571  display: grid; grid-template-columns: repeat(2, 1fr);
572  gap: 20px; margin-top: 40px;
573}
574.svc-card {
575  border-radius: var(--radius);
576  padding: 32px 28px;
577  border: 1.5px solid var(--border);
578  transition: all .25s; cursor: pointer;
579  position: relative; overflow: hidden;
580}
581.svc-card::before {
582  content: ''; position: absolute;
583  inset: 0; opacity: 0;
584  background: linear-gradient(135deg, rgba(6,31,117,.04), rgba(255,111,0,.04));
585  transition: opacity .25s;
586}
587.svc-card:hover { border-color: var(--orange); transform: translateY(-3px); box-shadow: var(--shadow); }
588.svc-card:hover::before { opacity: 1; }
589.svc-card-icon { font-size: 40px; margin-bottom: 16px; }
590.svc-card h3 { font-size: 20px; font-weight: 700; color: var(--navy); margin-bottom: 8px; }
591.svc-card p { color: var(--muted); font-size: 14px; line-height: 1.6; margin-bottom: 16px; }
592.svc-price { font-weight: 700; color: var(--orange); font-size: 15px; }
593
594/* ── SERVICE AREA CHECKER ── */
595.sa-section{background:linear-gradient(135deg,#061f75 0%,var(--navy2) 50%,#1a3fc4 100%);padding:64px 32px;color:#fff;}
596.sa-inner{max-width:900px;margin:0 auto;display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center;}
597/* Grid items default min-width:auto, so a child's intrinsic width can inflate
598   the 1fr track past the phone itself — measured: a 320px grid resolving its
599   only column to 397px, walking the whole page sideways on every iPhone. */
600.sa-inner>*{min-width:0;}
601.sa-left h2{font-family:'Bebas Neue',sans-serif;font-size:clamp(34px,4vw,50px);letter-spacing:2px;line-height:1.1;margin-bottom:14px;}
602.sa-left h2 span:last-of-type{color:#FF6F00;}
603.sa-left p{font-size:15px;opacity:.85;line-height:1.7;margin-bottom:10px;}
604.sa-nyc-badge{display:inline-flex;align-items:center;gap:7px;background:rgba(255,111,0,.18);border:1.5px solid rgba(255,111,0,.45);border-radius:30px;padding:7px 16px;font-size:13px;font-weight:600;color:#ffb347;margin-top:6px;}
605.sa-right{background:rgba(255,255,255,.07);border:1.5px solid rgba(255,255,255,.15);border-radius:24px;padding:32px 28px;backdrop-filter:blur(8px);}
606.sa-right h3{font-family:'Bebas Neue',sans-serif;font-size:22px;letter-spacing:1px;margin-bottom:6px;}
607.sa-right p{font-size:13px;opacity:.75;margin-bottom:20px;line-height:1.5;}
608.sa-input-row{display:flex;gap:10px;}
609.sa-zip-input{flex:1;min-width:0;padding:14px 16px;border:2px solid rgba(255,255,255,.25);border-radius:14px;background:rgba(255,255,255,.1);color:#fff;font-size:18px;font-family:inherit;font-weight:700;letter-spacing:2px;outline:none;transition:border-color .2s;text-align:center;}
610.sa-zip-input::placeholder{color:rgba(255,255,255,.4);font-weight:400;letter-spacing:0;font-size:14px;}
611.sa-zip-input:focus{border-color:rgba(255,111,0,.7);}
612.sa-check-btn{padding:14px 22px;background:linear-gradient(135deg,#FF6F00,#e65c00);border:none;border-radius:14px;color:#fff;font-weight:700;font-size:15px;cursor:pointer;font-family:inherit;transition:opacity .2s;white-space:nowrap;}
613.sa-check-btn:hover{opacity:.88;}
614.sa-result{margin-top:18px;border-radius:16px;padding:18px 20px;display:none;animation:saFadeIn .3s ease;}
615.sa-result.success{background:rgba(22,163,74,.2);border:1.5px solid rgba(34,197,94,.4);}
616.sa-result.outside{background:rgba(255,111,0,.15);border:1.5px solid rgba(255,111,0,.35);}
617.sa-result-head{font-weight:700;font-size:15px;margin-bottom:6px;display:flex;align-items:center;gap:8px;}
618.sa-result.success .sa-result-head{color:#86efac;}
619.sa-result.outside .sa-result-head{color:#fdba74;}
620.sa-result p{font-size:13px;opacity:.85;margin-bottom:14px;line-height:1.5;}
621.sa-result-btns{display:flex;gap:10px;flex-wrap:wrap;}
622/* Schedule Pickup borrows the CTA motion from shared.css but keeps its own
623   green — it answers a yes/no question in place, and turning it orange would
624   put two competing primary buttons on the same screen. */
625.sa-btn-primary{display:inline-flex;align-items:center;gap:6px;padding:10px 20px;border-radius:12px;color:#fff;font-weight:700;font-size:14px;text-decoration:none;
626  position:relative;overflow:hidden;isolation:isolate;
627  background:linear-gradient(100deg,#15803d 0%,#16a34a 25%,#22c55e 50%,#16a34a 75%,#15803d 100%);
628  background-size:260% 100%;
629  box-shadow:0 6px 20px rgba(22,163,74,.38), inset 0 1px 0 rgba(255,255,255,.3);
630  animation:ctaFlow 9s ease-in-out infinite;
631  transition:transform .2s, box-shadow .2s;}
632.sa-btn-primary::before{content:'';position:absolute;z-index:1;top:-20%;bottom:-20%;left:-60%;width:46%;
633  background:linear-gradient(100deg,transparent,rgba(255,255,255,.42),transparent);
634  transform:skewX(-22deg);pointer-events:none;animation:ctaShine 2.6s linear infinite;}
635.sa-btn-primary:hover{transform:translateY(-2px);box-shadow:0 12px 30px rgba(22,163,74,.52), inset 0 1px 0 rgba(255,255,255,.4);}
636.sa-btn-call{display:inline-flex;align-items:center;gap:6px;padding:10px 20px;background:linear-gradient(135deg,#FF6F00,#e65c00);border-radius:12px;color:#fff;font-weight:700;font-size:14px;text-decoration:none;transition:opacity .2s;}
637.sa-btn-call:hover{opacity:.88;}
638@keyframes saFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
639@media(max-width:768px){.sa-inner{grid-template-columns:1fr;gap:36px;}.sa-section{padding:48px 20px;}}
640
641/* ── APP DOWNLOAD BANNER ── */
642.app-dl-banner {
643  background: linear-gradient(135deg, #040f3a 0%, #061f75 55%, #0a2a99 100%);
644  padding: 64px 32px;
645  text-align: center;
646  position: relative; overflow: hidden;
647}
648.app-dl-banner::before {
649  content: '';
650  position: absolute; inset: 0;
651  background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ffffff' fill-opacity='0.03'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/svg%3E");
652}
653.app-dl-inner {
654  max-width: 700px; margin: 0 auto; position: relative;
655}
656.app-dl-pill {
657  display: inline-flex; align-items: center; gap: 6px;
658  background: rgba(255,111,0,.18); border: 1px solid rgba(255,111,0,.4);
659  color: var(--orange); border-radius: 100px;
660  padding: 5px 18px; font-size: 13px; font-weight: 600;
661  margin-bottom: 20px; letter-spacing: .5px;
662}
663.app-dl-banner h2 {
664  font-family: 'Bebas Neue', sans-serif;
665  font-size: clamp(36px, 5vw, 58px); letter-spacing: 2px; line-height: 1.05;
666  color: #fff; margin-bottom: 14px;
667}
668.app-dl-banner h2 span:last-of-type { color: var(--orange); }
669.app-dl-banner p {
670  font-size: 16px; color: rgba(255,255,255,.78); line-height: 1.7;
671  margin-bottom: 36px; max-width: 480px; margin-left: auto; margin-right: auto;
672}
673.app-dl-badges {
674  display: flex; gap: 18px; justify-content: center;
675  flex-wrap: wrap; align-items: center;
676}
677.app-dl-badge {
678  display: inline-block;
679  transition: transform .2s, opacity .2s;
680  border-radius: 14px;
681  overflow: hidden;
682  box-shadow: 0 8px 28px rgba(0,0,0,.35);
683}
684.app-dl-badge:hover { transform: translateY(-4px); opacity: .9; }
685.app-dl-badge img { height: 58px; display: block; }
686@media(max-width:600px){
687  .app-dl-banner { padding: 48px 20px; }
688  .app-dl-badge img { height: 48px; }
689}
690
691/* ── BONUS BANNER ── */
692.bonus-banner {
693  background: linear-gradient(135deg, var(--orange), var(--orange2));
694  color: #fff; padding: 48px 32px; text-align: center;
695}
696.bonus-banner h2 {
697  font-family: 'Bebas Neue', sans-serif;
698  font-size: 42px; letter-spacing: 2px; margin-bottom: 8px;
699}
700.bonus-banner p { font-size: 17px; opacity: .9; margin-bottom: 24px; }
701
702/* ── TESTIMONIALS ── */
703.reviews-grid {
704  display: grid; grid-template-columns: repeat(3, 1fr);
705  gap: 20px; margin-top: 40px;
706}
707.review-card {
708  background: var(--white); border-radius: var(--radius);
709  box-shadow: var(--shadow); padding: 24px;
710}
711.stars { color: #f59e0b; font-size: 16px; margin-bottom: 10px; }
712.review-card p { color: var(--text); font-size: 14px; line-height: 1.6; margin-bottom: 14px; font-style: italic; }
713.reviewer { font-weight: 600; font-size: 13px; color: var(--navy); }
714
715/* ── RESPONSIVE ── */
716@media (max-width: 900px) {
717  /* The card carries the five facts a first-time visitor asks for — where we
718     go, when, how fast, the app credit, the minimum. On a phone it used to be
719     hidden altogether, so the visitor who most needs them never saw them. It
720     now stacks under the headline, full width, at the left edge like
721     everything else in the hero. */
722  .hero-inner { grid-template-columns: 1fr; gap: 40px; }
723  .hero-visual { justify-content: flex-start; }
724  .hero-card { max-width: 460px; padding: 24px; }
725  .steps-grid { grid-template-columns: 1fr 1fr; }
726  .trust-grid { grid-template-columns: 1fr; }
727  .qo-grid { grid-template-columns: 1fr 1fr; gap: 12px; }
728  .qo-card { padding: 18px 10px; }
729  .qo-card .qo-ico { width: 56px; height: 56px;
729 border-radius: 17px; margin-bottom: 11px; }
730  .qo-card .qo-ico svg { width: 29px; height: 29px; }
731  .qo-card .qo-name { font-size: 13px; }
732  .reviews-grid { grid-template-columns: 1fr 1fr; }
733  .svc-grid { grid-template-columns: 1fr; }
734}
735@media (max-width: 600px) {
736  .steps-grid { grid-template-columns: 1fr; }
737  .reviews-grid { grid-template-columns: 1fr; }
738}
739
740/* ── AREAS WE SERVE — internal links to neighborhood landing pages ── */
741.areas-section { background: var(--white); padding: 56px 24px; border-top: 1px solid var(--border); }
742.areas-title { font-family: 'Bebas Neue', sans-serif; font-size: 34px; letter-spacing: 1px; color: var(--navy); text-align: center; margin-bottom: 6px; }
743.areas-sub { color: var(--muted); text-align: center; max-width: 580px; margin: 0 auto 26px; font-size: 15px; line-height: 1.5; }
744.areas-grid {
745  max-width: 980px; margin: 0 auto;
746  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
747  gap: 14px;
748}
749.area-link {
750  display: flex; align-items: center; gap: 12px;
751  padding: 16px 18px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
752  text-decoration: none; color: inherit;
753  transition: transform .15s, box-shadow .15s, border-color .15s, background .15s;
754}
755.area-link:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: var(--orange); background: #fff; }
756.area-link .pin { font-size: 22px; line-height: 1; flex-shrink: 0; }
757.area-link .area-meta { display: flex; flex-direction: column; }
758.area-link .area-name { font-weight: 800; color: var(--text); font-size: 15px; }
759.area-link .area-zip { font-size: 12px; color: var(--muted); margin-top: 2px; letter-spacing: .3px; }
760.areas-footer { text-align: center; margin-top: 22px; font-size: 14px; color: var(--muted); }
761.areas-footer a { color: var(--navy); font-weight: 700; text-decoration: none; }
762.areas-footer a:hover { text-decoration: underline; }
763</style>
764</head>
765<body>
766<!-- SW Update Banner -->
767<div id="sw-update-bar" class="sw-update-bar" data-i18n="home.swUpdate" onclick="applySwUpdate()">
768  🔄 New update available — tap to refresh
769</div>
770<div id="navbar"></div>
771
772<!-- HERO -->
773<section class="hero">
774  <div class="hero-inner">
775    <div>
776      <div class="hero-badge" data-i18n="home.heroBadge">🗽 Serving Brooklyn, NY</div>
777      <h1><span data-i18n="home.heroH1Line1">CLEAN CLOTHES,</span><br><span data-i18n="home.heroH1Line2">DELIVERED.</span></h1>
778      <p data-i18n="home.heroSubtitle">Brooklyn's most trusted laundry pickup & delivery service. We handle everything — you relax.</p>
779      <div class="hero-btns">
780        <a href="#quick-order" class="btn btn-orange" data-i18n="home.heroBtnOrder">Order Now</a>
781        <a href="/services/" class="btn btn-white" data-i18n="home.heroBtnPricing">View Pricing</a>
782      </div>
783    </div>
784    <div class="hero-visual">
785      <div class="hero-card">
786        <div class="hero-card-title" data-i18n="home.whyTitle">✨ Why Laundry King?</div>
787        <div class="hero-stat"><span class="label" data-i18n="home.statServiceArea">Service Area</span><span class="val" data-i18n="home.statServiceAreaVal">All Brooklyn</span></div>
788        <div class="hero-stat"><span class="label" data-i18n="home.statPickupTimes">Pickup Times</span><span class="val" data-i18n="home.statPickupTimesVal">7 AM – 10 PM</span></div>
789        <div class="hero-stat"><span class="label" data-i18n="home.statTurnaround">Turnaround</span><span class="val" data-i18n="home.statTurnaroundVal">Next Day</span></div>
790        <!-- Each environmental fact is tied to the service it belongs to. A bare
791             "eco-friendly" is a claim a visitor cannot check and a regulator
792             reads as greenwashing; "hypoallergenic" and "PERC-free" are things
793             the shop either does or does not do. -->
794        <div class="hero-stat"><span class="label" data-i18n="home.statDetergent">Detergents</span><span class="val" data-i18n="home.statDetergentVal">Hypoallergenic</span></div>
795        <div class="hero-stat"><span class="label" data-i18n="home.statDryClean">Dry Cleaning</span><span class="val" data-i18n="home.statDryCleanVal">PERC-Free</span></div>
796        <!-- THE APP IS OFF THE WEBSITE (owner, 2026-09-28). Customers were
797             ordering here, then installing the app and signing up a SECOND
798             time — and because the app still writes into the old database,
799             that second account is a duplicate nobody can reconcile. So
800             every route to the store is hidden until the two account worlds
801             are one, and the credit is advertised for what it actually is:
802             a first order with a card on it, wherever it is placed. -->
803        <a href="#quick-order" class="hero-stat hero-stat-link" id="idx-bonus-link" aria-label="First order with a credit card — welcome credit">
804          <span class="label" data-i18n="home.statBonus">First time order with credit card</span>
805          <span class="val" id="idx-bonus">$10 Credit</span>
806        </a>
807        <div class="hero-stat"><span class="label" data-i18n="home.statCheckout">Secure Checkout</span><span class="val" data-i18n="home.statCheckoutVal">Apple &amp; Google Pay</span></div>
808        <a href="#quick-order" class="hero-stat hero-stat-link" aria-label="Minimum order — scroll to quick order">
809          <span class="label" data-i18n="home.statMinOrder">Min. Order</span>
810          <span class="val" id="idx-min">$30.00</span>
811        </a>
812      </div>
813    </div>
814  </div>
815</section>
816
817<!-- 24/7 WALK-IN BAR -->
818<div class="visit-bar">
819  <div class="visit-bar-inner">
820    <div class="visit-24">24/7</div>
821    <div class="visit-divider"></div>
822    <div class="visit-info">
823      <div class="visit-title" data-i18n="home.visitTitle">OPEN FOR WALK-INS</div>
824      <div class="visit-sub" data-i18n="home.visitSub">Drop off or pick up your laundry anytime — day or night, no appointment needed.</div>
825      <div class="visit-parking" data-i18n="home.visitParking">🅿️ Free Parking Available On Site</div>
826    </div>
827    <div class="visit-addr">
828      <div><strong>📍 <span id="idx-visit-address">39 Neptune Ave, Brooklyn NY 11235</span></strong></div>
829      <div style="margin-top:6px;"><a href="https://maps.apple.com/?address=39+Neptune+Avenue,Brooklyn,NY+11235" target="_blank" rel="noopener" data-i18n="home.visitDirections">🗺 Get Directions →</a></div>
830      <div style="margin-top:6px;"><a id="idx-visit-email" href="mailto:[email protected]" style="color:#ffd166;">✉️ [email protected]</a></div>
831    </div>
832  </div>
833</div>
834
835<!-- ════════════════ QUICK ORDER (frictionless guest checkout) ════════════════
836     Pulsing orange "Ready for Quick Order!" badge + 4 service cards. Each
837     card jumps the customer straight into the guest-checkout flow on
838     order.html with the service preselected. Account creation happens at
839     the very end with just name + phone — address comes from the order. -->
840<section class="section qo-bg" id="quick-order" style="scroll-margin-top:calc(var(--nav-h) + 18px);">
841  <div class="container" style="text-align:center;">
842    <span class="qo-banner">
843      <span class="qo-dot"></span>
844      <span data-i18n="home.qoBanner">⚡ Ready for Quick Order!</span>
845    </span>
846    <h2 class="qo-title">
847      <span data-i18n="home.qoTitlePart1">Pick a Service</span>
848      <span data-i18n="home.qoTitlePart2">— Order in 60 Seconds</span>
849    </h2>
850    <div class="qo-grid">
851      <!-- Drawn icons rather than emoji: an emoji is rendered by the reader's
852           own device, so the four tiles arrived in four different art styles
853           and at four different weights, none of them ours. These are line
854           marks on a navy badge, one weight, one palette. -->
855      <a href="/order"  class="qo-card">
856        <span class="qo-ico" aria-hidden="true">
857          <!-- Folded towels -->
858          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
859            <rect x="3" y="14.6" width="18" height="5.2" rx="2"/>
860            <rect x="4.6" y="9.4" width="14.8" height="5.2" rx="2"/>
861            <rect x="6.2" y="4.2" width="11.6" height="5.2" rx="2"/>
862            <path d="M7.4 14.6v5.2M9 9.4v5.2M10.6 4.2v5.2"/>
863          </svg>
864        </span>
865        <span class="qo-name" data-i18n="home.qoCardWF">Wash &amp; Fold</span>
866        <span class="qo-price" id="idx-qo-wf-price"><span data-price="washFold.pricePerLb">$1.55</span>
866 / lb</span>
867      </a>
868      <a href="/order"  class="qo-card">
869        <span class="qo-ico" aria-hidden="true">
870          <!-- Pressed shirt -->
871          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
872            <path d="M9 3.4 12 6l3-2.6 3.6 1.8c.55.28.9.85.9 1.47v3.35c0 .55-.45 1-1 1h-1.6v7.9c0 .55-.45 1-1 1H8.1c-.55 0-1-.45-1-1v-7.9H5.5c-.55 0-1-.45-1-1V6.67c0-.62.35-1.19.9-1.47L9 3.4Z"/>
873            <path d="M9 3.4 12 8.2l3-4.8"/>
874          </svg>
875        </span>
876        <span class="qo-name" data-i18n="home.qoCardWP">Wash &amp; Press</span>
877        <span class="qo-price" id="qo-wp-price">From $4.50</span>
878      </a>
879      <a href="/order"  class="qo-card">
880        <span class="qo-ico" aria-hidden="true">
881          <!-- Garment bag on a hanger -->
882          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
883            <path d="M12 3.2a1.35 1.35 0 1 1 1.35 1.35c-.8 0-1.35.5-1.35 1.2v.5"/>
884            <path d="M12 6.4 6.7 10c-.75.5-1.2 1.35-1.2 2.25v6.3c0 .8.65 1.45 1.45 1.45h10.1c.8 0 1.45-.65 1.45-1.45v-6.3c0-.9-.45-1.75-1.2-2.25L12 6.4Z"/>
885            <path d="M12 6.4V20"/>
886          </svg>
887        </span>
888        <span class="qo-name" data-i18n="home.qoCardDC">Dry Cleaning</span>
889        <span class="qo-price" id="qo-dc-price">From $8.00</span>
890      </a>
891      <a href="/order" class="qo-card">
892        <span class="qo-ico" aria-hidden="true">
893          <!-- Everything else: three known services and one more -->
894          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
895            <rect x="3.4" y="3.4" width="7.2" height="7.2" rx="2.2"/>
896            <rect x="13.4" y="3.4" width="7.2" height="7.2" rx="2.2"/>
897            <rect x="3.4" y="13.4" width="7.2" height="7.2" rx="2.2"/>
898            <path d="M17 13.8v6.4M13.8 17h6.4"/>
899          </svg>
900        </span>
901        <span class="qo-name" data-i18n="home.qoCardOth">Other Services</span>
902        <span class="qo-price" data-i18n="home.qoCardOthPrice">Custom</span>
903      </a>
904    </div>
905  </div>
906</section>
907
908<!-- HOW IT WORKS -->
909
910<section class="section" style="padding-top:0;">
911  <div class="container">
912    <div class="lk-photo-row">
913      <figure class="lk-photo">
914        <img src="/images/driver-pickup-bag.jpg" alt="A Laundry King driver collecting a laundry bag from a customer's door in Brooklyn" width="1024" height="640" loading="lazy" decoding="async">
915        <figcaption>1. We collect at your door</figcaption>
916      </figure>
917      <figure class="lk-photo">
918        <img src="/images/staff-folding-towels.jpg" alt="A Laundry King team member folding clean towels by hand at the Brooklyn shop" width="1600" height="1000" loading="lazy" decoding="async">
919        <figcaption>2. Washed and folded by hand</figcaption>
920      </figure>
921      <figure class="lk-photo">
922        <img src="/images/delivery-doorstep.jpg" alt="Clean folded laundry delivered back to a customer's doorstep in Brooklyn" width="1024" height="640" loading="lazy" decoding="async">
923        <figcaption>3. Back at your door</figcaption>
924      </figure>
925    </div>
926  </div>
927</section>
928
929<section class="section">
930  <div class="container">
931    <div class="section-title" data-i18n="home.howTitle">How It Works</div>
932    <p class="section-sub" data-i18n="home.howSub">Four simple steps between you and fresh, clean laundry.</p>
933    <div class="steps-grid">
934      <div class="step-card">
935        <div class="step-num">1</div>
936        <div class="step-icon">📝</div>
937        <h3 data-i18n="home.step1Title">Place Your Order</h3>
938        <p data-i18n="home.step1Desc">Create an account and submit your order online. Choose your service, pickup method, and preferred times.</p>
939      </div>
940      <div class="step-card">
941        <div class="step-num">2</div>
942        <div class="step-icon">🚗</div>
943        <h3 data-i18n="home.step2Title">We Pick Up</h3>
944        <p data-i18n="home.step2Desc">Our driver arrives at your door. In person, lobby, curbside — you decide how it works for you.</p>
945      </div>
946      <div class="step-card">
947        <div class="step-num">3</div>
948        <div class="step-icon">🫧</div>
949        <h3 data-i18n="home.step3Title">Expert Cleaning</h3>
950        <p data-i18n="home.step3Desc">Your clothes are processed with professional care. Your detergent preferences are always respected.</p>
951      </div>
952      <div class="step-card">
953        <div class="step-num">4</div>
954        <div class="step-icon">✅</div>
955        <h3 data-i18n="home.step4Title">Fresh Delivery</h3>
956        <p data-i18n="home.step4Desc">Your laundry is delivered back to you, folded, pressed, or cleaned — right where you want it.</p>
957      </div>
958    </div>
959  </div>
960</section>
961
962<!-- WHY YOU'LL LOVE IT (Trust + Tech) -->
963<section class="section trust-bg">
964  <div class="container">
965    <div class="section-title" data-i18n="home.trustTitle">Why You'll Love It</div>
966    <p class="section-sub" data-i18n="home.trustSub">Modern payments, transparent flow, and live order tracking — built for peace of mind.</p>
967    <div class="trust-grid">
968
969      <!-- 1. Personal data security (payments are handled off-site by phone) -->
970      <div class="trust-card">
971        <div class="trust-icon" aria-hidden="true">🔒</div>
972        <span class="trust-pill" data-i18n="home.trustPillSecure">100% Secure</span>
973        <h3 data-i18n="home.trustSecureTitle">Your data, fully protected</h3>
974        <p data-i18n="home.trustSecureBody">We collect only what we need to schedule your pickup — name, phone, address. Payment is arranged by phone after pricing, so no card details are ever stored on this site.</p>
975      </div>
976
977      <!-- 2. Pay-when-ready (off-platform payment) -->
978      <div class="trust-card">
979        <div class="trust-icon" aria-hidden="true">💬</div>
980        <span class="trust-pill" data-i18n="home.trustPillFair">No Surprises</span>
981        <h3 data-i18n="home.trustFairTitle">You only pay once it's ready</h3>
982        <p data-i18n="home.trustFairBody">No upfront charges. We'll weigh your laundry, finalize the price, then call you to arrange payment — cash, Zelle, or card via our team. Nothing leaves your wallet before your laundry is finished.</p>
983      </div>
984
985      <!-- 3. Real-time tracking -->
986      <div class="trust-card">
987        <div class="trust-icon" aria-hidden="true">📍</div>
988        <span class="trust-pill" data-i18n="home.trustPillLive">Live</span>
989        <h3 data-i18n="home.trustLiveTitle">Always know what's happening</h3>
990        <p data-i18n="home.trustLiveBody">Watch your order's status update instantly — from pickup, through wash and fold, to your driver's live location on the map. No guesswork, no waiting in the dark.</p>
991        <div class="trust-status-line">
992          <span class="trust-status-dot" aria-hidden="true"></span>
993          <span data-i18n="home.trustLiveExample">Driver is 2 stops away · Out for delivery</span>
994        </div>
995      </div>
996
997    </div>
998  </div>
999</section>
1000
1001<!-- SERVICES PREVIEW -->
1002<section class="section services-bg">
1003  <div class="container">
1004    <div class="section-title" data-i18n="home.servicesTitle">Our Services</div>
1005    <p class="section-sub" data-i18n="home.servicesSub">From everyday laundry to delicate garments — we handle it all with care.</p>
1006    <div class="svc-grid">
1007      <div class="svc-card" onclick="location.href='services.html'">
1008        <div class="svc-card-icon">🫧</div>
1009        <h3 data-i18n="home.svcWFTitle">Wash &amp; Fold</h3>
1010        <p data-i18n="home.svcWFDesc">Everything washed, dried, and neatly folded. Choose your detergent, softener, and drying preferences.</p>
1011        <div class="svc-price" id="idx-wf-price">Starting at $1.55/lb · $30 minimum</div>
1012      </div>
1013      <div class="svc-card" onclick="location.href='services.html'">
1014        <div class="svc-card-icon">👔</div>
1015        <h3 data-i18n="home.svcWPTitle">Wash &amp; Press</h3>
1016        <p data-i18n="home.svcWPDesc">Shirts, pants, and dress clothes expertly washed and pressed. On hanger or boxed — your choice.</p>
1017        <div class="svc-price" id="idx-wp-price">From $4.50/shirt · Varies by item</div>
1018      </div>
1019      <div class="svc-card" onclick="location.href='services.html'">
1020        <div class="svc-card-icon">✨</div>
1021        <h3 data-i18n="home.svcDCTitle">Dry Cleaning</h3>
1022        <p data-i18n="home.svcDCDesc">Professional dry cleaning for suits, dresses, coats, and delicate garments that need extra care.</p>
1023        <div class="svc-price" id="idx-dc-price">From $8.00/item · Price list in app</div>
1024      </div>
1025      <div class="svc-card" onclick="location.href='services.html'">
1026        <div class="svc-card-icon">🛏️</div>
1027        <h3 data-i18n="home.svcOtherTitle">Other Services</h3>
1028        <p data-i18n="home.svcOtherDesc">Comforters, blankets, pillows, wedding dresses, and specialty items handled with the utmost care.</p>
1029        <div class="svc-price" data-i18n="home.svcOtherPrice">Custom pricing per item</div>
1030      </div>
1031    </div>
1032    <div style="text-align:center;margin-top:36px;">
1033      <a href="/services/" class="btn btn-outline" data-i18n="home.svcSeeAll">Full Pricing List →</a>
1034    </div>
1035  </div>
1036</section>
1037
1038<!-- SERVICE AREA CHECKER -->
1039<section class="sa-section">
1040  <div class="sa-inner">
1041    <div class="sa-left">
1042      <h2><span data-i18n="home.saTitlePart1">We Deliver Across</span> <span data-i18n="home.saTitlePart2">Brooklyn</span></h2>
1043      <p data-i18n="home.saSubP1">We currently serve 16 ZIP codes throughout Brooklyn — pickup and delivery every day of the week, 7 AM to 10 PM.</p>
1044      <p id="sa-sub-p2" data-i18n-html="home.saSubP2Html">Got a big haul? For orders over <strong>200 lbs</strong>, we'll come to <strong>any NYC borough</strong> — just give us a call.</p>
1045      <div class="sa-nyc-badge" data-i18n="home.saNycBadge">🗽 200+ lbs? We cover all of NYC</div>
1046    </div>
1047    <div class="sa-right">
1048      <h3 data-i18n="home.saAreYouTitle">📍 Are We in Your Area?</h3>
1049      <p data-i18n="home.saAreYouSub">Enter your ZIP code to find out if we can pick up from you.</p>
1050      <div class="sa-input-row">
1051        <input class="sa-zip-input" id="sa-zip" type="text" inputmode="numeric" maxlength="5" placeholder="e.g. 11235" data-i18n-placeholder="home.saZipPlaceholder" oninput="this.value=this.value.replace(/\D/g,'')" onkeydown="if(event.key==='Enter')checkServiceArea()">
1052        <button class="sa-check-btn" onclick="checkServiceArea()" data-i18n="home.saCheckBtn">Check →</button>
1053      </div>
1054      <div class="sa-result success" id="sa-result-yes">
1055        <div class="sa-result-head" data-i18n="home.saYesHead">✅ Great news — we serve your area!</div>
1056        <p data-i18n="home.saYesP">We pick up and deliver right to your door. Ready to get started?</p>
1057        <div class="sa-result-btns">
1058          <a href="#quick-order" class="sa-btn-primary" data-i18n="home.saYesBtn">🚀 Schedule Pickup →</a>
1059        </div>
1060      </div>
1061      <div class="sa-result outside" id="sa-result-no">
1062        <div class="sa-result-head" data-i18n="home.saNoHead">📦 Outside our regular Brooklyn zone</div>
1063        <p id="sa-no-p" data-i18n-html="home.saNoPHtml">For orders of <strong>200+ lbs</strong> we can reach you anywhere in NYC. Give us a call and we'll arrange it!</p>
1064        <div class="sa-result-btns">
1065          <a href="tel:7187374242" class="sa-btn-call" data-i18n="home.saNoBtn">📞 Call (718) 737-4242</a>
1066        </div>
1067      </div>
1068    </div>
1069  </div>
1070</section>
1071
1072<!-- ════════════════ AREAS WE SERVE ════════════════
1073     Visible internal links from the homepage to each neighborhood
1074     landing page. Crucial for SEO: gives Google a crawl path to every
1075     local page and tells it the homepage is the parent of these pages.
1076     `id="service-areas"` is the anchor target referenced from the
1077     neighborhood-page breadcrumbs. -->
1078<section class="areas-section" id="service-areas">
1079  <div class="container" style="max-width:1100px;">
1080    <h2 class="areas-title" data-i18n="home.areasTitle">South Brooklyn Neighborhoods We Serve</h2>
1081    <p class="areas-sub" data-i18n="home.areasSub">Free pickup &amp; delivery across South &amp; Central Brooklyn. Tap your neighborhood for local pickup details.</p>
1082    <div class="areas-grid">
1083      <a href="/laundry-pickup-sheepshead-bay/" class="area-link">
1084        <span class="pin">🏠</span>
1085        <div class="area-meta">
1086          <span class="area-name">Sheepshead Bay <span style="color:var(--orange);font-size:11px;">(HQ)</span></span>
1087          <span class="area-zip">11229 · 11235</span>
1088        </div>
1089      </a>
1090      <a href="/laundry-pick-up-brighton-beach/" class="area-link">
1091        <span class="pin">📍</span>
1092        <div class="area-meta">
1093          <span class="area-name">Brighton Beach</span>
1094          <span class="area-zip">11235</span>
1095        </div>
1096      </a>
1097      <a href="/laundry-pickup-bay-ridge/" class="area-link">
1098        <span class="pin">📍</span>
1099        <div class="area-meta">
1100          <span class="area-name">Bay Ridge</span>
1101          <span class="area-zip">11209 · 11220</span>
1102        </div>
1103      </a>
1104      <a href="/laundry-pickup-bensonhurst/" class="area-link">
1105        <span class="pin">📍</span>
1106        <div class="area-meta">
1107          <span class="area-name">Bensonhurst</span>
1108          <span class="area-zip">11204 · 11214</span>
1109        </div>
1110      </a>
1111      <a href="/laundry-pickup-bath-beach/" class="area-link">
1112        <span class="pin">📍</span>
1113        <div class="area-meta">
1114          <span class="area-name">Bath Beach</span>
1115          <span class="area-zip">11214</span>
1116        </div>
1117      </a>
1118      <a href="/laundry-pickup-dyker-heights/" class="area-link">
1119        <span class="pin">📍</span>
1120        <div class="area-meta">
1121          <span class="area-name">Dyker Heights</span>
1122          <span class="area-zip">11228</span>
1123        </div>
1124      </a>
1125      <a href="/laundry-pickup-midwood/" class="area-link">
1126        <span class="pin">📍</span>
1127        <div class="area-meta">
1128          <span class="area-name">Midwood</span>
1129          <span class="area-zip">11230 · 11210</span>
1130        </div>
1131      </a>
1132      <a href="/laundry-pickup-gravesend/" class="area-link">
1133        <span class="pin">📍</span>
1134        <div class="area-meta">
1135          <span class="area-name">Gravesend</span>
1136          <span class="area-zip">11223</span>
1137        </div>
1138      </a>
1139      <a href="/laundry-pickup-kings-highway/" class="area-link">
1140        <span class="pin">📍</span>
1141        <div class="area-meta">
1142          <span class="area-name">Kings Highway</span>
1143          <span class="area-zip">11223 · 11229 · 11230</span>
1144        </div>
1145      </a>
1146      <a href="/laundry-pickup-bay-parkway/" class="area-link">
1147        <span class="pin">📍</span>
1148        <div class="area-meta">
1149          <span class="area-name">Bay Parkway</span>
1150          <span class="area-zip">
115011204 · 11214 · 11223</span>
1151        </div>
1152      </a>
1153    </div>
1154    <p class="areas-footer" data-i18n-html="home.areasFooterHtml">We also serve <strong>Borough Park</strong> (11219), <strong>Sunset Park</strong> (11220, 11232), <strong>Marine Park / Mill Basin</strong> (11234), <strong>Flatbush</strong> (11226, 11203), <strong>Coney Island</strong> (11224), and <strong>Kensington / Windsor Terrace</strong> (11218). For larger orders we deliver throughout Brooklyn — <a href="#quick-order">schedule a pickup</a> and we'll confirm.</p>
1155  </div>
1156</section>
1157
1158<!-- APP DOWNLOAD BANNER — HIDDEN 2026-09-28.
1159     Not deleted, because this comes back the moment the app and the website
1160     share one account. Today they do not: a customer who orders here and
1161     then installs the app signs up again, that second sign-up lands in the
1162     OLD database, and the shop ends up with two records for one person. The
1163     owner's instruction was to take every route to the store off the site
1164     until that is fixed — so the markup stays, hidden, ready to unhide. -->
1165<section class="app-dl-banner lk-app-only" id="app-section" hidden aria-hidden="true">
1166  <div class="app-dl-inner">
1167    <div class="app-dl-pill" data-i18n="home.appPill">📱 Available on iOS &amp; Android</div>
1168    <h2><span data-i18n="home.appH2Line1">DOWNLOAD THE</span><br><span data-i18n="home.appH2Line2">LAUNDRY KING APP</span></h2>
1169    <p data-i18n="home.appSubtitle">The easiest way to schedule pickups, track your orders, and manage all your laundry preferences — right from your phone.</p>
1170    <div class="app-dl-badges">
1171      <a class="app-dl-badge" href="https://apps.apple.com/us/app/laundry-king/id1489471695" target="_blank" rel="noopener" aria-label="Download on the App Store" data-i18n-aria-label="home.appAriaApple">
1172        <img src="https://firebasestorage.googleapis.com/v0/b/laundry-king-web.firebasestorage.app/o/icons%2Fappstore.png?alt=media" alt="Download on the App Store" data-i18n-alt="home.appAriaApple">
1173      </a>
1174      <a class="app-dl-badge" href="https://play.google.com/store/apps/details?id=com.LaundryKing&pli=1" target="_blank" rel="noopener" aria-label="Get it on Google Play" data-i18n-aria-label="home.appAriaPlay">
1175        <img src="https://firebasestorage.googleapis.com/v0/b/laundry-king-web.firebasestorage.app/o/icons%2Fplaystore.png?alt=media" alt="Get it on Google Play" data-i18n-alt="home.appAriaPlay">
1176      </a>
1177    </div>
1178  </div>
1179</section>
1180
1181<!-- BONUS BANNER — FIRST ORDER WITH A CARD.
1182     It used to read "APP ONLY … not on the website", and that was true of
1183     the copy but never of the code: the grant in onOrderCreated asks for a
1184     first order and a real saved card, and has never cared which door the
1185     order came through. With the app hidden, the banner now says the same
1186     thing the rule says, and sends people to the order form instead of a
1187     store badge. -->
1188<div class="bonus-banner">
1189  <h2 id="idx-bonus-banner-h2">🎁 <span id="idx-bonus-banner"><span data-price="global.welcomeBonus" data-price-fmt="int">$10</span></span> BONUS — YOUR FIRST ORDER</h2>
1190  <p id="idx-bonus-banner-sub">Place your first order and add a credit card to receive a <span id="idx-bonus-banner-p"><span data-price="global.welcomeBonus" data-price-fmt="int">$10</span></span> credit on your account.</p>
1191  <a href="#quick-order" class="btn btn-white" data-i18n="home.bonusBtn">Order Now</a>
1192</div>
1193
1194<!-- REVIEWS -->
1195<section class="section">
1196  <div class="container">
1197    <div class="section-title" data-i18n="home.reviewsTitle">What Our Customers Say</div>
1198    <p class="section-sub" data-i18n="home.reviewsSub">Thousands of happy Brooklyn residents trust Laundry King every week.</p>
1199    <div class="reviews-grid">
1200      <div class="review-card">
1201        <p>&ldquo;I like this place a lot. It&rsquo;s by my house, and I go there several times a week to do laundry. They are open 24/7, often have excellent movies/tv programs playing, are clean and generally on-point.&rdquo;</p>
1202        <div class="reviewer">&mdash; Roman B.</div>
1203      </div>
1204      <div class="review-card">
1205        <p>&ldquo;I&rsquo;ve been taking my clothes here for 4 years for fluff and fold, dry cleaning, and pressed shirts on hanger. The employees are friendly and they have reliable service. My laundry always looks great.&rdquo;</p>
1206        <div class="reviewer">&mdash; Marc D.</div>
1207      </div>
1208      <div class="review-card">
1209        <p>&ldquo;Great place! I go there for their drop off service and I&rsquo;ve been very happy! They separate all of my clothes and plastic wrap my clean clothes before putt
1209ing back in my laundry bag! The staff is very friendly.&rdquo;</p>
1210        <div class="reviewer">&mdash; Crystal A.</div>
1211      </div>
1212    </div>
1213    <p style="text-align:center;margin-top:18px;">
1214      <a href="/reviews/" style="color:var(--navy);font-weight:600;text-decoration:none;">Read all customer reviews &rarr;</a>
1215    </p>
1216  </div>
1217</section>
1218
1219<div id="footer"></div>
1220
1221<script type="module">
1222  import { renderNav, renderFooter, loadPricing, loadBranding, applyLivePrices } from '/firebase.js';
1223  import { initI18n, t } from '/i18n.js';
1224  renderNav('/');
1225  renderFooter();
1226  initI18n();
1227applyLivePrices();
1228
1229  let _pricing = null;
1230
1231  function applyDynamicI18n() {
1232    const P = _pricing;
1233    if (!P) return;
1234    const fmt = v => `$${Number(v).toFixed(2)}`;
1235    const s = (id, v) => { const el = document.getElementById(id); if (el) el.textContent = v; };
1236    const sH = (id, v) => { const el = document.getElementById(id); if (el) el.innerHTML = v; };
1237    s('idx-bonus', t('home.bonusVal', { amount: fmt(P.global.welcomeBonus) }));
1238    s('idx-min',   fmt(P.global.minimumOrder));
1239    s('idx-wf-price', t('home.wfPriceVal', { amount: fmt(P.washFold.pricePerLb), min: fmt(P.global.minimumOrder) }));
1240    s('idx-wp-price', t('home.wpPriceVal', { onHanger: fmt(P.washPress.price), inBox: fmt(P.washPress.shirtInBox) }));
1241    /* Quick-order cards carry the same numbers as the service cards below and
1242     *  used to carry them as typed-in text, which is how they came to advertise
1243     *  a wash & press price we stopped charging. They read the price list now.
1244     *
1245     *  Dry cleaning has no single price — it is a list of 105 garments — so the
1246     *  "from" figure is the cheapest one we actually quote. Items priced at
1247     *  zero are the ones we quote on sight (tablecloths, drapes, lace curtains)
1248     *  and would otherwise drag the headline down to $0.00. */
1249    const dcFrom = (() => {
1250      const seen = [];
1251      (function walk(o) {
1252        if (!o || typeof o !== 'object') return;
1253        for (const k in o) {
1254          const v = o[k];
1255          if (typeof v === 'number') { if (v > 0) seen.push(v); }
1256          else walk(v);
1257        }
1258      })(P.dryCleaning);
1259      return seen.length ? Math.min.apply(null, seen) : null;
1260    })();
1261    s('qo-wp-price', t('home.qoCardWPPrice', { amount: fmt(P.washPress.price) }));
1262    if (dcFrom != null) {
1263      s('qo-dc-price',  t('home.qoCardDCPrice', { amount: fmt(dcFrom) }));
1264      s('idx-dc-price', t('home.svcDCPrice',    { amount: fmt(dcFrom) }));
1265    }
1266    sH('idx-bonus-banner-h2',  t('home.bonusTitleFull', { amount: fmt(P.global.welcomeBonus) }));
1267    sH('idx-bonus-banner-sub', t('home.bonusSubFull',   { amount: fmt(P.global.welcomeBonus) }));
1268  }
1269
1270  // ── Apply dynamic pricing ──
1271  loadPricing().then(P => {
1272    _pricing = P;
1273    applyDynamicI18n();
1274  });
1275
1276  // ── Apply dynamic branding (visit bar only) ──
1277  loadBranding().then(B => {
1278    const emailEl = document.getElementById('idx-visit-email');
1279    if (emailEl) { emailEl.href = `mailto:${B.supportEmail}`; emailEl.textContent = `✉️ ${B.supportEmail}`; }
1280    const addrEl = document.getElementById('idx-visit-address');
1281    if (addrEl) addrEl.textContent = B.address;
1282  });
1283
1284  // ── Re-apply dynamic strings when language changes ──
1285  window.addEventListener('lk-lang-change', applyDynamicI18n);
1286</script>
vendor: 1 bytes, line 1286
1286
1287<script>
1288const SERVICE_ZIPS=new Set(['11235','11230','11214','11228','11223','11209','11204','11219','11218','11229','11234','11226','11210','11203','11224','11220']);
1289function checkServiceArea(){
1290  const zip=(document.getElementById('sa-zip').value||'').trim();
1291  const yes=document.getElementById('sa-result-yes');
1292  const no=document.getElementById('sa-result-no');
1293  if(zip.length!==5){
1294    yes.style.display='none';no.style.display='none';
1295    document.getElementById('sa-zip').focus();
1296    return;
1297  }
1298  yes.style.display='none';no.style.display='none';
1299  // small delay for animation reset
1300  requestAnimationFrame(()=>{
1301    if(SERVICE_ZIPS.has(zip)){
1302      yes.style.display='block';
1303    } else {
1304      no.style.display='block';
1305    }
1306  });
1307}
1308
1309/* The bonus row used to retarget itself at whichever app store the visitor's
1310 * own phone could open. With the app hidden from the site (2026-09-28) that
1311 * is exactly the journey we are trying not to start — an install leads to a
1312 * second sign-up in the old database — so the row now stays pointed at the
1313 * order form and this rewrite is disabled rather than deleted. Restore it
1314 * together with #app-section when the two account worlds are merged. */
1315</script>
1315
1316<!-- Contact FAB (WhatsApp + Call) -->
1317<style>
1318/* Call FAB — orange so it reads against the navy sections it floats over
1319   (navy-on-navy was invisible), with a slow halo so the eye finds it. */
1320@keyframes lkFabPulse{
1321  0%  {box-shadow:0 6px 20px rgba(255,111,0,.45), 0 0 0 0    rgba(255,111,0,.55);}
1322  70% {box-shadow:0 6px 20px rgba(255,111,0,.45), 0 0 0 18px rgba(255,111,0,0);}
1323  100%{box-shadow:0 6px 20px rgba(255,111,0,.45), 0 0 0 0    rgba(255,111,0,0);}
1324}
1325.lk-fab-btn{animation:lkFabPulse 2.6s ease-out infinite;}
1326.lk-fab-btn:hover{transform:scale(1.08);}
1327@media (prefers-reduced-motion:reduce){.lk-fab-btn{animation:none;}}
1328</style>
1329<div id="lk-contact-fab" style="position:fixed;bottom:90px;right:20px;z-index:99999;font-family:inherit;">
1330  <div id="lk-contact-menu" style="display:none;position:absolute;bottom:66px;right:0;background:#fff;border-radius:14px;box-shadow:0 8px 28px rgba(0,0,0,.22);overflow:hidden;min-width:220px;">
1331    <a href="https://wa.me/17187374242" target="_blank" rel="noopener noreferrer" style="display:flex;align-items:center;gap:12px;padding:14px 16px;text-decoration:none;color:#0b1226;font-weight:600;font-size:14px;border-bottom:1px solid #f0f0f0;">
1332      <svg width="22" height="22" viewBox="0 0 24 24" fill="#25D366"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/></svg>
1333      <span data-i18n="home.fabWhatsapp">WhatsApp</span>
1334    </a>
1335    <a href="tel:7187374242" style="display:flex;align-items:center;gap:12px;padding:14px 16px;text-decoration:none;color:#0b1226;font-weight:600;font-size:14px;">
1336      <svg width="20" height="20" viewBox="0 0 24 24" fill="#061f75"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></svg>
1337      <span data-i18n="home.fabCall">Call (718) 737-4242</span>
1338    </a>
1339  </div>
1340  <button type="button" onclick="var m=document.getElementById('lk-contact-menu');m.style.display=(m.style.display==='none'||!m.style.display)?'block':'none';event.stopPropagation();" aria-label="Call us" data-i18n-aria-label="home.fabContact" data-track="contact_fab_open" class="lk-fab-btn" style="width:60px;height:60px;border-radius:50%;background:#FF6F00;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .2s;" onmouseover="this.style.transform='scale(1.1)'" onmouseout="this.style.transform='scale(1)'">
1341    <svg width="28" height="28" viewBox="0 0 24 24" fill="#fff"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></svg>
1342  </button>
1343</div>
1344<script>document.addEventListener('click',function(e){var f=document.getElementById('lk-contact-fab');var m=document.getElementById('lk-contact-menu');if(f&&m&&!f.contains(e.target))m.style.display='none';});</script>
1344
1345</body>
1346</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.