/* eslint-disable */ const { useState, useEffect, useRef, useMemo } = React; /* ================================================ I18N ================================================ */ const COPY = { tr: { nav: ["Ana Sayfa", "Ürünler", "Tasarla", "Hikaye", "İletişim"], cart: "Sepet · 0", ticker: ["El İşçiliği", "Modern Tasarım", "İstanbul'dan", "Konfor & Stil", "Akıllı QR", "Özel Üretim"], heroMetaTop: ["Est. 2023 · Köpek Ekipmanları", "Edition Nº 04 · Kış"], heroLines: [ ["EL", "EMEĞİ", "."], ["MODERN", null, "TASARIM."], ["DOSTUN", "İÇİN", "."] ], heroAccentIdx: { 1: 0 }, // "MODERN" word styled as accent? we'll do separately sticker: ["Tasarımı sen seç ·", "kişiselleştir ·"].join(" "), heroPitch: "Konforu bütünsel bir deneyim olarak görüyoruz. Geniş temas yüzeyi, yumuşak doku, ergonomik tutuş.", heroMeta: [ { k: "Koleksiyon", v: "04 · Kış '26" }, { k: "Üretim", v: "İstanbul · El yapımı" } ], marquee1: ["Konfor", "Stil", "Dayanıklılık", "El İşçiliği", "Modern"], marqueeAccent: "için dostun", marquee2: ["Boyun Tasması", "Gezdirme Kayışı", "Akıllı QR", "Kişiselleştir"], manifestoNum: "Nº 01 — Manifesto", manifestoQuote: [ "Bir tasma yalnızca bir", "ekipman değil; siz ile", "dostunuz arasındaki", { em: "zarif bir dokunuş." } ], manifestoTail: "Boynu ip gibi kesen, nefes almasını zorlaştıran kalitesiz tasmaların devri kapanıyor.", productsEyebrow: "Nº 02 — Koleksiyon", productsTitle: ["İki ürün.", { em: "sonsuz" }, "kombinasyon."], products: [ { num: "01", cornerLabel: "In Stock", title: ["Boyun", { em: "Tasması" }], desc: "Geniş temas yüzeyi ve yumuşak dokusu boyundaki baskıyı dağıtır. El işçiliği detaylar, paslanmaz çelik halka.", specs: [ { k: "Malzeme", v: "Bizon deri + neopren" }, { k: "Donanım", v: "Paslanmaz çelik" }, { k: "Beden", v: "XS — XL" }, { k: "Kişiselleştirme", v: "İsim · renk · isim plakası" } ], price: "₺ 1.290", swatchLabel: "Renk seç", cta: "Tasarla", bg: "https://peticota.com/wp-content/uploads/2025/12/2.png" }, { num: "02", cornerLabel: "Yeni", title: ["Gezdirme", { em: "Kayışı" }], desc: "Uzun yürüyüşlerde eli yormayan ergonomik tutuş. Çift karabina, refleks dikiş, gece görünürlük şeritleri.", specs: [ { k: "Uzunluk", v: "120 — 200 cm" }, { k: "Tutuş", v: "Yastıklı, ergonomik" }, { k: "Karabina", v: "Çift, paslanmaz" }, { k: "Kişiselleştirme", v: "Renk · uzunluk · isim" } ], price: "₺ 1.490", swatchLabel: "Renk seç", cta: "Tasarla", bg: "https://peticota.com/wp-content/uploads/2025/12/unnamed-4-2-e1767014417477.jpg" } ], customizeEyebrow: "Nº 03 — Kişiselleştir", customizeTitle: ["En iyisini", { em: "sen tasarla" }, "."], customizeSteps: [ { t: "Modeli seç", d: "Boyun tasması mı, gezdirme kayışı mı? Bedeni belirle." }, { t: "Renk & doku", d: "Krem, kömür, kil, kızıl. Mat ya da yağlı deri." }, { t: "İsim & detay", d: "İsim plakası, gizli baskı, refleks şerit, ton üstü ton dikiş." }, { t: "Üretim", d: "İstanbul atölyesinde 7 — 10 iş günü içinde el yapımı." } ], customizeCta: "Tasarlamaya başla", customizeMeta: "Min. sipariş yok · Yalnız sana", qrTitle: ["Akıllı", { em: "QR" }, "etiket."], qrDesc: "Acil durumlarda köpeğini bulan kişi tek taramayla alerjiler, iletişim ve ilk yardım bilgilerine ulaşır. Her tasmaya gizlenmiş halde gelir.", qrFeatures: ["Alerji bilgileri", "Acil iletişim", "İlk yardım", "Aşı kartı", "Veteriner", "Profilini güncelle"], qrTagTop: ["if found, scan", "Peticota ID"], qrTagBottom: ["scan", { em: "& save" }, "me."], footerMega: ["peticota", "•"], footerCols: [ { h: "İletişim", items: [ { l: "hello@peticota.com", href: "mailto:hello@peticota.com" }, { l: "+90 555 000 00 00", href: "tel:+905550000000" }, { l: "Galata, İstanbul", href: "https://maps.google.com/?q=Galata+Istanbul" } ] }, { h: "Keşfet", items: [ { l: "Tasarla", href: "tasarla.html" }, { l: "Koleksiyon", href: "#products" }, { l: "Hikaye", href: "#manifesto" }, { l: "Bayilik", href: "mailto:hello@peticota.com?subject=Bayilik%20Ba%C5%9Fvurusu" } ] }, { h: "Sosyal", items: [ { l: "Instagram", href: "https://instagram.com/peticota" }, { l: "TikTok", href: "https://www.tiktok.com/@peticota" }, { l: "Pinterest", href: "https://pinterest.com/peticota" } ] } ], newsletterTitle: "Bültene katıl", newsletterDesc: "Yeni koleksiyon ve özel ürünlerden ilk sen haberdar ol.", newsletterCta: "Kaydol", legal: ["© 2026 Peticota — All rights reserved.", "Tasarım & üretim · İstanbul"], floatBadge: ["Tasarla", "Sana özel"] }, en: { nav: ["Home", "Products", "Customize", "Story", "Contact"], cart: "Cart · 0", ticker: ["Hand Made", "Modern Design", "From Istanbul", "Comfort & Style", "Smart QR", "Bespoke"], heroMetaTop: ["Est. 2023 · Dog Equipment", "Edition Nº 04 · Winter"], heroLines: [ ["HAND", "MADE", "."], ["MODERN", null, "DESIGN."], ["FOR", "YOUR", "FRIEND."] ], sticker: ["Design it your way ·", "your edition ·"].join(" "), heroPitch: "We see comfort as a whole experience. Wide contact surface, soft texture, ergonomic grip.", heroMeta: [ { k: "Collection", v: "04 · Winter '26" }, { k: "Made in", v: "Istanbul · By hand" } ], marquee1: ["Comfort", "Style", "Durability", "Hand Made", "Modern"], marqueeAccent: "for your friend", marquee2: ["Collar", "Leash", "Smart QR", "Customize"], manifestoNum: "Nº 01 — Manifesto", manifestoQuote: [ "A collar is not just", "equipment; it is a", "graceful link between", { em: "you and your friend." } ], manifestoTail: "The era of stiff straps that cut into the neck and crush the windpipe ends here.", productsEyebrow: "Nº 02 — Collection", productsTitle: ["Two products.", { em: "endless" }, "combinations."], products: [ { num: "01", cornerLabel: "In Stock", title: ["The", { em: "Collar" }], desc: "Wide contact surface and soft texture spread pressure across the neck. Hand-stitched detail, stainless ring.", specs: [ { k: "Material", v: "Bison leather + neoprene" }, { k: "Hardware", v: "Stainless steel" }, { k: "Size", v: "XS — XL" }, { k: "Customize", v: "Name · color · ID plate" } ], price: "₺ 1.290", swatchLabel: "Pick color", cta: "Customize", bg: "https://peticota.com/wp-content/uploads/2025/12/2.png" }, { num: "02", cornerLabel: "New", title: ["The", { em: "Leash" }], desc: "Ergonomic grip that doesn't tire your hand on long walks. Double carabiner, reflective stitching, night visibility.", specs: [ { k: "Length", v: "120 — 200 cm" }, { k: "Grip", v: "Padded, ergonomic" }, { k: "Hardware", v: "Double, stainless" }, { k: "Customize", v: "Color · length · name" } ], price: "₺ 1.490", swatchLabel: "Pick color", cta: "Customize", bg: "https://peticota.com/wp-content/uploads/2025/12/unnamed-4-2-e1767014417477.jpg" } ], customizeEyebrow: "Nº 03 — Customize", customizeTitle: ["Design the", { em: "best one" }, "."], customizeSteps: [ { t: "Pick model", d: "Collar or leash? Choose your size." }, { t: "Color & finish", d: "Cream, charcoal, clay, red. Matte or oiled leather." }, { t: "Name & detail", d: "ID plate, blind embossing, reflective trim, tone-on-tone stitching." }, { t: "Production", d: "Made by hand in our Istanbul atelier within 7 — 10 working days." } ], customizeCta: "Start designing", customizeMeta: "No min. order · Just for you", qrTitle: ["Smart", { em: "QR" }, "tag."], qrDesc: "If your dog gets lost, anyone can scan and reach allergies, contact and first-aid info instantly. Hidden inside every collar.", qrFeatures: ["Allergies", "Emergency contact", "First aid", "Vaccine card", "Vet info", "Edit anytime"], qrTagTop: ["if found, scan", "Peticota ID"], qrTagBottom: ["scan", { em: "& save" }, "me."], footerMega: ["peticota", "•"], footerCols: [ { h: "Contact", items: [ { l: "hello@peticota.com", href: "mailto:hello@peticota.com" }, { l: "+90 555 000 00 00", href: "tel:+905550000000" }, { l: "Galata, Istanbul", href: "https://maps.google.com/?q=Galata+Istanbul" } ] }, { h: "Explore", items: [ { l: "Customize", href: "tasarla.html" }, { l: "Collection", href: "#products" }, { l: "Story", href: "#manifesto" }, { l: "Wholesale", href: "mailto:hello@peticota.com?subject=Wholesale%20inquiry" } ] }, { h: "Social", items: [ { l: "Instagram", href: "https://instagram.com/peticota" }, { l: "TikTok", href: "https://www.tiktok.com/@peticota" }, { l: "Pinterest", href: "https://pinterest.com/peticota" } ] } ], newsletterTitle: "Join the list", newsletterDesc: "First to hear about new collections and exclusives.", newsletterCta: "Subscribe", legal: ["© 2026 Peticota — All rights reserved.", "Designed & made · Istanbul"], floatBadge: ["Design", "your own"] } }; /* ================================================ Helpers ================================================ */ const renderParts = (parts, key = 0) => { if (typeof parts === "string") return parts; if (Array.isArray(parts)) return parts.map((p, i) => ( {renderParts(p, `${key}-${i}`)}{" "} )); if (parts && parts.em) return {parts.em}; return null; }; const useInView = (ref, opts = { threshold: 0.18 }) => { const [seen, setSeen] = useState(false); useEffect(() => { if (!ref.current) return; const obs = new IntersectionObserver( (entries) => { entries.forEach((e) => { if (e.isIntersecting) setSeen(true); }); }, opts ); obs.observe(ref.current); return () => obs.disconnect(); }, []); return seen; }; /* ================================================ NAV ================================================ */ const Nav = ({ lang, setLang, t }) => { const [hidden, setHidden] = useState(false); const lastY = useRef(0); useEffect(() => { const onScroll = () => { const y = window.scrollY; setHidden(y > 120 && y > lastY.current); lastY.current = y; }; window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); return ( <>
{[0, 1].map((d) => ( {t.ticker.map((x, i) => ( {x} ))} ))}
); }; /* ================================================ HERO ================================================ */ const Hero = ({ t }) => { const imgRef = useRef(null); useEffect(() => { const onScroll = () => { if (!imgRef.current) return; const y = window.scrollY; imgRef.current.style.transform = `scale(1.08) translateY(${y * 0.18}px)`; }; window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); // Hero lines from copy.heroLines — each line is array of strings. // We render words with stagger and underline accents return (
{t.heroMetaTop[0]} {t.heroMetaTop[1]}
{t.sticker}
{t.heroLines.map((line, i) => ( {line.map((w, j) => w == null ? ( design ) : ( {w} ) )} ))}

"{t.heroPitch}"

{t.heroMeta.map((m, i) => (
{m.k} {m.v}
))}
); }; /* ================================================ KINETIC MARQUEE ================================================ */ const Marquee = ({ words, accent, dark, reverse }) => { return (
{[0, 1].map((d) => ( {words.map((w, i) => ( {w} {i === 2 && accent ? ( {accent} ) : null} ))} ))}
); }; /* ================================================ MANIFESTO ================================================ */ const Manifesto = ({ t }) => { const ref = useRef(null); const seen = useInView(ref); return (
{t.manifestoNum}
{t.manifestoQuote.map((p, i) => { if (typeof p === "string") { // strike-through "ekipman" word optionally return ( {p.split(" ").map((w, j) => { const isCross = /ekipman|equipment/i.test(w); return ( {w}{" "} ); })}
); } if (p.em) return {p.em}; return null; })}

{t.manifestoTail}

); }; /* ================================================ PRODUCTS ================================================ */ const SWATCHES = [ { c: "#0b0b08", name: "Kömür" }, { c: "#e1261c", name: "Kızıl" }, { c: "#c9a371", name: "Buğday" }, { c: "#f1ecdf", name: "Krem" } ]; const ProductsIntro = ({ t }) => (
{t.productsEyebrow}

{renderParts(t.productsTitle)}

); const ProductCard = ({ p, idx, t, lang }) => { const wrapRef = useRef(null); const imgRef = useRef(null); const [activeSwatch, setActiveSwatch] = useState(idx === 0 ? 0 : 1); useEffect(() => { const onScroll = () => { if (!wrapRef.current || !imgRef.current) return; const r = wrapRef.current.getBoundingClientRect(); const center = r.top + r.height / 2; const vh = window.innerHeight; const progress = (vh / 2 - center) / vh; // -1..1 ish const rot = progress * 28 * (idx % 2 === 0 ? 1 : -1); const y = progress * 30; imgRef.current.style.transform = `translateY(${y}px) rotate(${rot}deg)`; }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); return () => window.removeEventListener("scroll", onScroll); }, [idx]); const flip = idx % 2 === 1; return (
{p.cornerLabel}
{p.title.join("
{p.price}
/ {p.num} {lang === "tr" ? "Ürün" : "Product"}

{renderParts(p.title)}

{p.desc}

{p.specs.map((s, i) => (
{s.k} {s.v}
))}
{p.swatchLabel} · {SWATCHES[activeSwatch].name}
{SWATCHES.map((s, i) => ( setActiveSwatch(i)} /> ))}
{p.cta}
); }; const Products = ({ t, lang }) => ( <> {t.products.map((p, i) => ( ))} ); /* ================================================ CUSTOMIZE ================================================ */ const Customize = ({ t }) => (
{t.customizeEyebrow}

{renderParts(t.customizeTitle)}

{t.customizeSteps.map((s, i) => (
0{i + 1}

{s.t}

{s.d}

))}
{t.customizeMeta} {t.customizeCta}
); /* ================================================ QR ================================================ */ const QRSection = ({ t }) => { const tagRef = useRef(null); useEffect(() => { const onScroll = () => { if (!tagRef.current) return; const r = tagRef.current.getBoundingClientRect(); const center = r.top + r.height / 2; const vh = window.innerHeight; const progress = (vh / 2 - center) / vh; tagRef.current.style.transform = `rotate(${-4 + progress * 18}deg)`; }; window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); return (
Nº 04 — Smart Tag

{renderParts(t.qrTitle)}

{t.qrDesc}

    {t.qrFeatures.map((f, i) => (
  • {f}
  • ))}
{t.qrTagTop[0]} {t.qrTagTop[1]}
QR
{renderParts(t.qrTagBottom)}
); }; /* ================================================ NEWSLETTER → Google Sheets (WhiteList) ================================================ */ const Newsletter = ({ t, lang }) => { const [email, setEmail] = React.useState(""); const [hp, setHp] = React.useState(""); // honeypot const [cfToken, setCfToken] = React.useState(""); // Cloudflare Turnstile const [status, setStatus] = React.useState("idle"); // idle | sending | ok | err | captcha const submit = async (e) => { e.preventDefault(); const v = email.trim(); if (!v || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) { setStatus("err"); return; } if (!cfToken) { setStatus("captcha"); return; } setStatus("sending"); // 1) Yerel kayıt (Sheet erişilemezse veri kaybolmasın) try { const k = "peticota.newsletter.v1"; const arr = JSON.parse(localStorage.getItem(k) || "[]"); arr.push({ email: v, at: new Date().toISOString(), lang }); localStorage.setItem(k, JSON.stringify(arr)); } catch (e) {} // 2) Google Sheet → WhiteList sekmesi if (typeof pushToSheet === "function") { await pushToSheet({ type: "whitelist", email: v, lang, source: "peticota.com", hp, cfToken }); } setStatus("ok"); setEmail(""); }; if (status === "ok") { return (
{t.newsletterTitle}
{lang === "en" ? "✓ Subscribed" : "✓ Kaydoldun"}
{lang === "en" ? "Welcome. We'll write before the next collection drops." : "Hoş geldin. Yeni koleksiyondan önce yazacağız."}
); } return (
{t.newsletterTitle}

{t.newsletterDesc}

{/* Honeypot — görünmez, sadece bot doldurur */} setHp(e.target.value)} style={{ position: "absolute", left: "-9999px", width: 1, height: 1, opacity: 0, pointerEvents: "none" }} /> { setEmail(e.target.value); if (status === "err" || status === "captcha") setStatus("idle"); }} style={status === "err" ? { borderColor: "var(--red)", color: "var(--red)" } : {}} />
{status === "captcha" ? (
{lang === "en" ? "Please complete verification" : "Lütfen doğrulamayı tamamlayın"}
) : null}
); }; /* ================================================ FOOTER ================================================ */ const Footer = ({ t, lang }) => { const ref = useRef(null); useEffect(() => { const onScroll = () => { if (!ref.current) return; const r = ref.current.getBoundingClientRect(); const vh = window.innerHeight; const p = Math.max(0, Math.min(1, 1 - r.top / vh)); ref.current.style.transform = `translateX(${-220 * (1 - p)}px)`; }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); return () => window.removeEventListener("scroll", onScroll); }, []); return (
{t.footerMega[0]}
{t.footerCols.map((c, i) => (
{c.h}
{c.items.map((it, j) => { const isExternal = typeof it.href === "string" && /^https?:\/\//.test(it.href); return ( {it.l} ); })}
))}
{t.legal[0]} {t.legal[1]}
); }; /* ================================================ SCROLL PROGRESS ================================================ */ const ScrollProgress = () => { const ref = useRef(null); useEffect(() => { const onScroll = () => { if (!ref.current) return; const h = document.documentElement.scrollHeight - window.innerHeight; const p = Math.min(1, window.scrollY / h); ref.current.style.width = `${p * 100}%`; }; window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); return
; }; /* ================================================ FLOAT BADGE (bottom-left) ================================================ */ const FloatBadge = ({ t }) => ( {t.floatBadge[0]}
{t.floatBadge[1]}
); /* ================================================ APP ================================================ */ const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "lang": "tr", "red": "#e1261c", "darkMarquee": true, "showFloat": true }/*EDITMODE-END*/; const App = () => { const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS); const lang = tweaks.lang; const setLang = (l) => setTweak("lang", l); const t = COPY[lang]; // Apply red as CSS variable useEffect(() => { document.documentElement.style.setProperty("--red", tweaks.red); }, [tweaks.red]); return ( <>