Νέο — ο τηλεφωνικός πράκτοράς σας AI είναι ζωντανός σε 3 λεπτά

Η επιχείρησή σας απαντά σε κάθε κλήση — με AI

Δημιουργήστε μια σελίδα AI με κλήση με ένα κλικ για την επιχείρησή σας σε 3 λεπτά. Οι πελάτες σας πατούν έναν σύνδεσμο και αρχίζουν να μιλούν. Εσείς λαμβάνετε την απομαγνητοφώνηση, την περίληψη και την επανάκληση.

Λεπτά AI περιλαμβάνονται κάθε μήνα · Δεν χρειάζεται αριθμός τηλεφώνου · Ακύρωση οποτεδήποτε

Η επιχείρησή σας
Ερωτήσεις; Απλώς πατήστε και μιλήστε.

Ο βοηθός μας απαντά αμέσως — τιμές, διαθεσιμότητα, κρατήσεις και άλλα.

Ζωντανή κλήση — 02:14
Καλών
“Έχετε κάποιο διαθέσιμο ραντεβού αυτή την Πέμπτη;”
Βοηθός
“Ναι! Έχω 10:30 π.μ. και 2:00 μ.μ. Ποια σας βολεύει;”
Πατήστε για να μιλήσετε
Όλα όσα μπορεί να κάνει η σελίδα σας — από την πρώτη οθόνη

Φωνητικές κλήσεις AI, 24/7

Οι πελάτες πατούν τον σύνδεσμό σας και μιλούν στο πρόγραμμα περιήγησής τους — χωρίς αριθμό τηλεφώνου, χωρίς εφαρμογή, χωρίς αναμονή στη γραμμή. Ο φωνητικός πράκτοράς σας AI απαντά αμέσως, μέρα ή νύχτα.

Κλείνει ραντεβού μέσα στην κλήση

Στη μέση της συνομιλίας, ο πράκτοράς σας προσφέρει πραγματικές διαθέσιμες ώρες και κλείνει το ραντεβού μέσα στην κλήση — και μετά οι υπενθυμίσεις και οι επιβεβαιώσεις ακολουθούν από μόνες τους.

Ένα κατάστημα που μένει ανοιχτό κατά την κλήση

Τα προϊόντα και οι συλλογές σας — κάθε συλλογή με τον δικό της σύνδεσμο — παραμένουν διαθέσιμα για περιήγηση στο κατάστημα κατά τη διάρκεια της κλήσης, ενώ ο πράκτορας συμβουλεύει για ό,τι βλέπει ο πελάτης, σε πραγματικό χρόνο.

Γνωρίζει τα προϊόντα σας απ’ έξω

Ο πράκτοράς σας αναφέρει τις ακριβείς τιμές και λεπτομέρειες από τον δικό σας κατάλογο και προτείνει το σωστό προϊόν — ποτέ δεν επινοεί τιμή.

Κάθε κλήση, καταγεγραμμένη & με αναζήτηση

Απομαγνητοφωνήσεις, περιλήψεις και αναλύσεις για κάθε συνομιλία, σε μία ροή Δραστηριότητας — βρείτε οποιαδήποτε κλήση με όνομα, αριθμό ή οτιδήποτε ειπώθηκε.

Πολύγλωσσο από το πρώτο γεια

Αυτός ο ιστότοπος μιλά 24 γλώσσες, και η σελίδα σας μπορεί επίσης: ένα μικρό πάτημα σημαίας αλλάζει τη γλώσσα, ώστε κάθε επισκέπτης να χαιρετίζεται στη δική του γλώσσα.

Ο δρόμος προς το μέλλον

Πού πηγαίνουν οι επαγγελματικές κλήσεις

Κάποτε κάθε επιχείρηση έχανε τις κλήσεις που δεν μπορούσε να απαντήσει. Ύστερα το τηλέφωνο έγινε σύνδεσμος. Τώρα ο σύνδεσμος απαντά — και πουλά.

Χθες — η χαμένη κλήση

Ένας πελάτης καλεί εκτός ωραρίου, ακούει να χτυπά χωρίς απάντηση και αγοράζει από όποιον απαντήσει πρώτος. Η επιχείρηση δεν μαθαίνει ποτέ καν ότι συνέβη.

The CallPages home page: a business answering a live AI call on a phone

Σήμερα — η σελίδα που απαντά

Η CallPage σας απαντά αμέσως, 24/7: μιλά, αναφέρει τις πραγματικές σας τιμές, κλείνει το ραντεβού μέσα στην κλήση και σας αφήνει την απομαγνητοφώνηση και την περίληψη.

A real business website on CallPages — Mi Junta — with its store and call button in reach

Αύριο — ο πράκτορας που μεγαλώνει την επιχείρηση

Ο ίδιος πράκτορας επικοινωνεί ξανά, επιβεβαιώνει, υπενθυμίζει και μαθαίνει τον κατάλογό σας απ’ έξω — μια ρεσεψιόν που δεν κοιμάται ποτέ, στις γλώσσες των πελατών σας.

Ζωντανή επίδειξη
● ΖΩΝΤΑΝΗ ΕΠΙΔΕΙΞΗ

Μη μας πιστεύετε στα λόγια — μιλήστε με μία

Αυτή είναι μια πραγματική CallPage, ζωντανή σε αυτήν ακριβώς τη σελίδα: η Mi Junta, μια υπηρεσία συμβουλών για ιδιοκτήτες διαμερισμάτων στο Πουέρτο Ρίκο. Συνομιλήστε με τον βοηθό της ή πατήστε το κουμπί κλήσης και μιλήστε — ο πράκτορας μιλά πρώτος και εσείς μπορείτε απλώς να ακούτε: δεν χρειάζεται ποτέ μικρόφωνο για να ξεκινήσετε.

Ανοίξτε τη σελίδα επίδειξης →

Οι κλήσεις επίδειξης είναι πραγματικές κλήσεις με μια πραγματική CallPage — παρακαλούμε να είστε ευγενικοί, μια απομαγνητοφώνηση πηγαίνει στον ιδιοκτήτη της σελίδας.

Πώς λειτουργεί

Ζωντανά σε τρία βήματα. Πραγματικά.

Χωρίς εξοπλισμό, χωρίς κλήσεις εγκατάστασης, χωρίς τίποτα τεχνικό. Αν μπορείτε να συμπληρώσετε μια φόρμα, μπορείτε να το κάνετε.

1

Σύνδεση με Google

Ένα κλικ με τον λογαριασμό σας Google. Χωρίς κωδικούς να θυμάστε, χωρίς λογαριασμούς να διαχειρίζεστε.

~30 δευτερόλεπτα
2

Περιγράψτε την επιχείρησή σας

Πείτε στο AI με απλά λόγια τι κάνετε, τι πουλάτε και πώς χαιρετάτε τους καλούντες. Διαλέξτε μια φωνή και ένα χρώμα ταυτότητας.

~2 λεπτά
3

Μοιραστείτε τον σύνδεσμό σας

Λάβετε τον σύνδεσμο της δικής σας σελίδας. Οι πελάτες τον πατούν σε οποιοδήποτε τηλέφωνο και αρχίζουν να μιλούν — αμέσως, σαν κλήση, στο πρόγραμμα περιήγησής τους.

Έτοιμο
What's new · Novedades

Release notes — Oct 22 · Blog · Learning Center

The in-call appointment slot picker on a CallPages page, showing open time slots computed from the page's own appointment book

Appointments belong to CallPages: booking works on every page, Google Calendar only syncs

CallPages' own appointment system is now the system of record on every page: booking is on by default everywhere, and a Google Calendar is only a sync target — never a gate.

See how it works →

The CallPages dashboard with a page's product editor open and the bookmarkable editor link row visible above the product list

Bookmark the editor: deep links into your page, and a light My Pages landing

Every editor tab in the CallPages dashboard now has its own bookmarkable link that survives sign-in, and the dashboard opens on the light My Pages list instead of the heavy Activity feed.

See how it works →

Illustration: a phone showing a website page as stacked blocks — heading, photo, text — with one text block tapped and outlined for editing, a pencil badge, and a glowing + divider between blocks above a button block

The friendly website editor: edit your site exactly as your visitors see it

The Website Studio's block editor is now fully visual: blocks render as the published page itself, you click any block to edit it in place, and a + divider between blocks opens a six-type picker — no Markdown, no guessing.

See how it works →

A collection page on CallPages: the Queen collection of a San Juan bed-frame shop at its own /c/queen address, with its products as cards

Collections get their own URLs — and their own place in search

Every collection on a CallPages page now lives at its own address — /p/<page>/c/<collection> — with its own title, description, canonical URL, structured data, and a spot in the page sitemap.

See how it works →

A CallPages page whose store stays browsable during a call: products the customer can tap while the voice agent advises on what they are viewing

The call that lets customers keep shopping

During a CallPages call, customers can tap any product and keep browsing the store — inside the call. The voice agent sees what they're looking at in real time and advises on the item in front of them.

See how it works →

Appointments that follow up by themselves

Booked appointments now manage themselves: a reminder two hours before, confirmation required one hour before, and a private manage page per appointment where the customer can confirm, cancel, or reschedule.

See how it works →

Illustration: a phone showing one unified Activity feed — call, appointment, callback and voicemail rows under filter chips — while two crossed-out separate tabs dissolve behind it

Callbacks and appointments moved in: Activity holds everything now

The dashboard shed two tabs. Callbacks and Appointments/Calendar now live inside Activity at full power — the callback queue, the calendar, Google Calendar — behind the chips you already use.

See how it works →

The page editor on a phone with the single Store tab selected: 'Tienda — products & collections in one place'

One Store tab: collections and products, edited together

The Store tab now holds everything: collections on top, products edited right inside them, reorder by drag or arrows — and every change autosaves. No second editor, no Save button.

See how it works →

The Website Studio page list on a phone: authored pages grouped by path with per-language published and draft chips

Website Studio: build your whole site from your phone

Every page now has a Website Studio: create your site's pages from templates, edit them block by block, add photos, preview drafts privately, publish when ready — right in the dashboard.

See how it works →

A dashboard header that holds only your account. The dashboard's top bar was de-cluttered: feature shortcuts moved into their own tabs where they belong, and the top-right now holds a single account menu. As a bonus, the plan pill finally tells the truth about your plan. Learn more

Guide agents now know every member of their guide. A city guide's voice agent now carries a complete digest of every member business — names, areas, categories, signature items with real prices, hours and phones — and never claims not to know a business its own guide lists. Learn more

Product pages now answer themselves in Google AI Mode. Every product page can end with a questions section — real questions about that product, each one a tap away from asking Google AI Mode, which answers from the product's own published facts. Learn more

Delete that actually deletes — and a Hide that keeps selling. Deleting a product in the dashboard now removes it for real, the moment you tap. And a new Hide turns the product's page into an honest 'Agotado' with similar products instead of a dead end. Learn more

Release notes — Oct 19 · Blog · Changelog · Learning Center · Learning Center

Illustration: an abstract admin console with owner and customer account cards side by side, a magnifier, and a settings gear

One console for every account

The CallPages admin console now shows page owners and consumer accounts side by side, lets an admin step into any account to help, and edit any page's settings.

See how it works →

Mi Junta's CallPages page in production: the call is the front door of the page, and appointments are arranged inside that conversation

Appointments live inside the call now

Booking an appointment now happens inside a live call, with the voice agent, in the middle of the conversation it belongs to. The public booking form — and the spam it invited — is gone.

See how it works →

The branded CallPages 404 page: Page not found or paused, with an explanation, a create-your-own button, and cards describing what CallPages offers

Even a wrong link looks like CallPages now

Every error on CallPages — a mistyped address, a paused page, a product that moved — now renders as one branded page that explains what happened and shows the way forward.

See how it works →

The Sleep Shop store on CallPages with its collection tab bar: King 11, Queen 18, Full 11, Twin 12 above the King collection's product grid

Every collection, one tap away

A CallPages shop now carries a collection tab bar: each collection sits in a sticky row with its product count, and tapping jumps straight to it — same page, all products, no reloads.

See how it works →

Illustration: a small business storefront connected by a glowing arc to a globe, its page living at its own web address

Your page, on your own domain

A CallPages page can now live on the business's own domain — the address on its signs, cards, and receipts — with the call, the store, and the agent answering there unchanged.

See how it works →

Illustration: a store product grid whose empty photo placeholders are being filled by bright product photos flowing in from a sparkling source

Product photos without a photo shoot

A catalog no longer waits for a camera: CallPages can fill in product photos from free image providers, chosen and controlled from Settings.

See how it works →

The new CallPages home page hero: Your business answers every call — with AI, beside a phone showing a live call with a caller asking about Thursday openings

A new front door for CallPages

The CallPages home page has been rebuilt: a hero that shows a live AI call on a phone, and the product's real features integrated into the first screen instead of listed somewhere below.

See how it works →

Illustration: a product page on a phone with a quiet chat bubble opening at the bottom and a glowing microphone button beside it

The Silent Magic Helper, on every page

The Silent Magic Helper is now on by default for every CallPages page — existing and new — and its chat sessions are logged as calls, right beside the voice ones.

See how it works →

Sleep Shop's website on CallPages in production — the web face of the page that now also carries its own sleep-shop@callpages.me address

Every page gets its own email address

Every CallPages page now has its own email address — <page>@callpages.me — and new pages greet their owners with a welcome email. A page is reachable by call, by web, and by mail.

See how it works →

Illustration: a completed payment card flowing into an envelope, a calendar appointment, and a reminder bell, connected by one glowing path

What happens after the payment, automatically

A payment on CallPages now sets its own follow-through in motion: confirmations and next steps happen on their own, and the owner watches it all land in Activity.

See how it works →

A consulting product page on CallPages whose top questions are about the service itself: what is included, how long it takes, how far ahead to book, and what affects the price

Questions that belong to the product

The questions on a product page are now written from that product itself — its name, its photo, its description — so a consulting session gets consulting questions and a bed frame gets frame questions.

See how it works →

The share row on a live CallPages product page: X, Facebook, WhatsApp, LinkedIn, Telegram, copy-link, and share buttons above the call button

Every page and product, ready to share

Pages and products now carry a proper share row — X, Facebook, WhatsApp, LinkedIn, Telegram, and copy-link — so anything worth finding is one tap from being passed on.

See how it works →

Mi Junta's website on CallPages in production, rendered in the current design generation: clean navigation, clear sections, and the call to action always in reach

WOW Design v2 — and styles that remember

Pages and websites get a new design generation, WOW Design v2, and page styles are now versioned: when a look changes, the old one is kept, not overwritten.

See how it works →

Πραγματικές σελίδες · Πραγματικά προϊόντα

Επιχειρήσεις που ήδη απαντούν με AI

Πραγματικές CallPages, ζωντανές αυτή τη στιγμή — με τα πραγματικά προϊόντα και τις πραγματικές τιμές τους. Πατήστε οποιαδήποτε και μιλήστε οι ίδιοι με την επιχείρηση.

Sleep Shop — a metal bed frame product photo from the live store

Sleep Shop

Σκελετοί κρεβατιών & στρώματα στο Σαν Χουάν, Πουέρτο Ρίκο — παράδοση σε όλο το νησί σε περίπου μία ώρα.

Frame Full 8 Pulgadas — product photoFrame Full 8 Pulgadas 🎁 NUEVO EN CAJA$99
Frame Full 3000 Libras Acero 18 Pulgadas — product photoFrame Full 3000 Libras Acero 18 Pulgadas 💪 📦✨$160
Frame Full Metal Con Cabecera Vintage — product photoFrame Full Metal Con Cabecera Vintage 🎁 NUEVO EN CAJA$180
Mi Junta — advice for condo owners about late HOA dues

Mi Junta

Βοήθεια για ιδιοκτήτες διαμερισμάτων στο Πουέρτο Ρίκο που αντιμετωπίζουν πρόστιμα HOA, χρεώσεις καθυστέρησης και ανεξήγητες χρεώσεις.

Cargos por pago tardío de la cuota de mantenimiento — topic imageCargos por pago tardío de la cuota de mantenimiento (Late Fees on Monthly Dues)$29
Multas por violaciones a las reglas — topic imageMultas por violaciones a las reglas (Rule-Violation Fines)$29
Intereses y recargos acumulados por mora — topic imageIntereses y recargos acumulados por mora (Accumulated Interest & Late Charges)$29
Vasily — executive advisory on future tech and mobility

Vasily — Consulting

Συμβουλές για τεχνολογία του μέλλοντος, κινητικότητα και στρατηγική προϊόντων — συνεδρίες συμβουλευτικής και εργαστήρια εμβάθυνσης.

Executive Advisory Session — session imageExecutive Advisory SessionConsultar
Diligence Sprint — session imageDiligence SprintConsultar
Priority Scheduling — session imagePriority Scheduling$2,000
Ferretería Ramón — construction materials at a San Juan hardware store

Ferretería Ramón

Ένα γειτονικό κατάστημα σιδηρικών στο Σαν Χουάν — ολόκληρος ο κατάλογός του σε μία σελίδα, ένα πάτημα μακριά από μια κλήση.

Arena de Río — product photoArena de Río
Arena Fina — product photoArena Fina
Cemento (Saco) — product photoCemento (Saco)
Όλα περιλαμβάνονται

Μία σελίδα. Μια ολόκληρη τηλεφωνική ομάδα.

Κάθε σελίδα CallPages περιλαμβάνει όλα όσα χρειάζεστε για να μη χάσετε ποτέ ξανά πελάτη.

Illustration: a business page living at its own web address

Ο δικός σας αποκλειστικός σύνδεσμος

Κάθε σελίδα αποκτά έναν μοναδικό σύνδεσμο όπως epicheirisisas.callpages.com — βάλτε τον στον ιστότοπό σας, στο προφίλ Google, στα τιμολόγια και στα κοινωνικά δίκτυα.

Illustration: two phones with voice waves — a test call to your own page

Δοκιμαστικές κλήσεις οποτεδήποτε

Δοκιμάστε τη δική σας σελίδα όπως θα έκανε ένας πελάτης — πατήστε, μιλήστε και ακούστε ακριβώς ό,τι θα ακούσουν οι καλούντες σας.

A call record in production: transcript and the products browsed during the call

Απομαγνητοφωνήσεις & περιλήψεις

Κάθε συνομιλία καταγράφεται για εσάς, με μια σύντομη περίληψη ώστε να ξέρετε σε δευτερόλεπτα τι συνέβη.

The Activity tab in production: every call, searchable

Ιστορικό κλήσεων με αναζήτηση

Βρείτε οποιαδήποτε κλήση αμέσως — αναζητήστε με το όνομα του καλούντος, τον αριθμό ή οτιδήποτε ειπώθηκε στη συνομιλία.

Mi Junta's website in production, wearing its own branding

Η δική σας ταυτότητα

Το όνομα της επιχείρησής σας, τα χρώματά σας, ο χαιρετισμός σας. Η σελίδα σας μοιάζει με εσάς — όχι με εμάς.

Illustration: a merchant with their business dashboard on a phone

Λειτουργεί σε κάθε τηλέφωνο

Οι καλούντες απλώς ανοίγουν τον σύνδεσμο στο πρόγραμμα περιήγησής τους — iPhone ή Android, χωρίς εγκατάσταση εφαρμογής, χωρίς λογαριασμό.

A product page in production asking questions drawn from the product itself

Γνωρίζει τα προϊόντα σας

Ανεβάστε τη λίστα προϊόντων σας και ο πράκτοράς σας αναφέρει ακριβείς τιμές, απαντά ερωτήσεις και προτείνει το σωστό προϊόν — ποτέ δεν επινοεί κανένα.

Μιλά τη γλώσσα των πελατών σας

Οι σελίδες και ο πράκτορας μιλούν τις γλώσσες που επιλέγετε — αυτός ο ιστότοπος και μόνο δημοσιεύεται σε 24 από αυτές.

🇪🇸 🇺🇸 🇫🇷 🇧🇷 🇩🇪 🇮🇹 🇳🇱 🇵🇱 🇷🇺 🇺🇦 🇨🇳 🇯🇵 🇰🇷 🇸🇦 🇮🇳 🇹🇷 🇮🇩 🇻🇳 🇹🇭 🇵🇭 🇧🇩 🇮🇷 🇸🇪 🇬🇷

Τιμές

Ένα πρόγραμμα. Απλό.

Όλα περιλαμβάνονται σε ένα μόνο πρόγραμμα. Προσθέστε περισσότερες σελίδες καθώς μεγαλώνει η επιχείρησή σας.

CallPages
$29/μήνα ανά σελίδα

Λεπτά AI για κάθε σελίδα, κάθε μήνα

  • Η δική σας σελίδα κλήσης με ένα κλικ, με τη δική σας ταυτότητα
  • Λεπτά AI περιλαμβάνονται σε κάθε σελίδα — δίκαιη χρήση
  • Απεριόριστοι καλούντες, απομαγνητοφωνήσεις & περιλήψεις
  • Αιτήματα επανάκλησης που σας αποστέλλονται με email
  • Ακύρωση οποτεδήποτε — χωρίς συμβόλαια, χωρίς χρεώσεις εγκατάστασης
Ξεκινήστε — Σύνδεση με Google
Ασφαλής πληρωμή · Ακύρωση οποτεδήποτε
FAQ

Ερωτήσεις, απαντημένες.

Απλές απαντήσεις, χωρίς τεχνική ορολογία.

Χρειάζομαι αριθμό τηλεφώνου για να λειτουργήσει;
Όχι. Το CallPages δεν χρησιμοποιεί καθόλου την τηλεφωνική σας γραμμή. Οι πελάτες σας ανοίγουν τον σύνδεσμο της σελίδας σας στο πρόγραμμα περιήγησής τους και μιλούν απευθείας — είναι σαν τηλεφωνική κλήση, αλλά γίνεται στον ιστό. Δεν χρειάζεται να αγοράσετε, να μεταφέρετε ή να διαχειριστείτε κανέναν αριθμό τηλεφώνου.
Ποιες γλώσσες μιλά το AI;
Αυτός ο ιστότοπος δημοσιεύεται σε 24 γλώσσες — πατήστε μια σημαία επάνω και όλα αλλάζουν. Η σελίδα σας μιλά τις γλώσσες που επιλέγετε γι’ αυτήν: το AI χαιρετά τους καλούντες και διεξάγει ολόκληρη τη συνομιλία σε αυτή τη γλώσσα, και μια σελίδα μπορεί να λειτουργεί σε πολλές γλώσσες ταυτόχρονα.
Πώς λειτουργούν στην πράξη οι κλήσεις;
Μοιράζεστε τον σύνδεσμο της σελίδας σας οπουδήποτε — στον ιστότοπό σας, στο προφίλ Google Business, στα τιμολόγια, στα κοινωνικά δίκτυα. Ο πελάτης πατά τον σύνδεσμο, πατά το κουμπί κλήσης και αρχίζει να μιλά στο πρόγραμμα περιήγησής του. Το AI απαντά αμέσως, 24/7. Μετά την κλήση, λαμβάνετε την πλήρη απομαγνητοφώνηση και μια σύντομη περίληψη στον πίνακά σας.
Τι μετρά ως λεπτό AI;
Ένα λεπτό AI είναι ένα λεπτό ζωντανής συνομιλίας με το AI σας. Κάθε σελίδα περιλαμβάνει λεπτά AI για ζωντανές συνομιλίες — οι περισσότερες μικρές επιχειρήσεις δεν πλησιάζουν καν το όριο δίκαιης χρήσης.
Μπορώ να ακυρώσω οποτεδήποτε;
Ναι. Δεν υπάρχουν συμβόλαια ούτε χρεώσεις ακύρωσης. Διαχειριστείτε τη συνδρομή σας από τον πίνακά σας με ένα κλικ, και οι σελίδες σας παραμένουν ενεργές μέχρι το τέλος της περιόδου χρέωσης.

Κοινοποιήστε το CallPages

Ξέρετε μια επιχείρηση που χάνει συνέχεια κλήσεις; Περάστε το παρακάτω.

Κοινοποίηση
/* public/theme-switcher.js — LANE 4 top-fixed theme switcher (Vasily, 2026-10-23). * * A floating pill, always visible at the very top of the page, with three * segments: Lame White / Current / Acid. Zero friction, unlimited changes. * - Instant: swaps + localStorage("cp-theme") immediately. * - Owner mode (dashboard, data-theme-mode="owner"): also persists to the * account in D1 via POST /api/owner/theme (fire-and-forget; the UI * never waits for the network). * - Visitor mode (public pages, data-theme-mode="visitor"): local only — * the visitor plays with themes without affecting anyone. * * Inlined into dashboard/dialer/landing/my-callpage by build.js at the * theme-switcher placeholder (plain script, no modules, no deps). * Unit-tested in node with stubbed DOM (src/theme-switcher.test.js). */ (function () { "use strict"; var THEMES = [ { id: "lame-white", label: "Lame White" }, { id: "current", label: "Current" }, { id: "acid-v1", label: "Acid" }, ]; var KEY = "cp-theme"; var MOUNT_ID = "cpThemeSwitcher"; function norm(v) { if (v === "lame-white" || v === "current" || v === "acid-v1") return v; if (v === "dark") return "current"; // legacy migration if (v === "light") return "lame-white"; // legacy migration return null; } function getMode(doc) { var m = doc.documentElement.getAttribute("data-theme-mode"); return m === "owner" ? "owner" : "visitor"; } function currentTheme(doc, ls) { var t = null; try { t = norm(ls.getItem(KEY)); } catch (e) {} if (!t) t = norm(doc.documentElement.getAttribute("data-theme")); return t || "current"; } function applyTheme(id, doc, ls) { id = norm(id) || "current"; doc.documentElement.setAttribute("data-theme", id); try { ls.setItem(KEY, id); } catch (e) {} return id; } function persistOwnerTheme(id, fetchFn) { // Fire-and-forget: the UI already applied instantly; a failed save // just means the next load falls back to the previous account theme. try { var p = fetchFn("/api/owner/theme", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ theme: id }), }); if (p && typeof p.catch === "function") p.catch(function () {}); } catch (e) {} } function setTheme(id, doc, ls, fetchFn) { id = applyTheme(id, doc, ls); if (getMode(doc) === "owner" && typeof fetchFn === "function") { persistOwnerTheme(id, fetchFn); } syncPill(doc, id); return id; } function syncPill(doc, activeId) { var pill = doc.getElementById(MOUNT_ID); if (!pill) return; var btns = pill.querySelectorAll ? pill.querySelectorAll("button[data-theme-id]") : []; for (var i = 0; i < btns.length; i++) { var b = btns[i]; var on = b.getAttribute("data-theme-id") === activeId; b.setAttribute("aria-pressed", on ? "true" : "false"); } } function render(doc, ls, fetchFn) { var mount = doc.getElementById(MOUNT_ID); if (!mount) { mount = doc.createElement("div"); mount.id = MOUNT_ID; (doc.body || doc.documentElement).appendChild(mount); } // Rebuild idempotently. while (mount.firstChild) mount.removeChild(mount.firstChild); var pill = doc.createElement("div"); pill.className = "cp-theme-switcher"; pill.setAttribute("role", "group"); pill.setAttribute("aria-label", "Theme"); var label = doc.createElement("span"); label.className = "cp-ts-label"; label.setAttribute("title", "Prueba los temas — cambia el look al instante"); label.textContent = "🎨 Temas"; pill.appendChild(label); THEMES.forEach(function (t) { var b = doc.createElement("button"); b.type = "button"; b.setAttribute("data-theme-id", t.id); b.setAttribute("aria-pressed", "false"); b.title = t.label; b.textContent = t.label; b.addEventListener("click", function () { setTheme(t.id, doc, ls, fetchFn); }); pill.appendChild(b); }); mount.appendChild(pill); syncPill(doc, currentTheme(doc, ls)); } function init(doc, ls, fetchFn) { render(doc, ls, fetchFn); } var api = { THEMES: THEMES, KEY: KEY, MOUNT_ID: MOUNT_ID, norm: norm, getMode: getMode, currentTheme: currentTheme, applyTheme: applyTheme, setTheme: setTheme, syncPill: syncPill, render: render, init: init, }; // Safe storage: localStorage throws on opaque origins (file://, about:blank // in tests) — fall back to an in-memory shim so the pill always renders. function safeStorage(win) { try { var ls = win.localStorage; ls.getItem("__cp_probe__"); return ls; } catch (e) { var mem = {}; return { getItem: function (k) { return Object.prototype.hasOwnProperty.call(mem, k) ? mem[k] : null; }, setItem: function (k, v) { mem[k] = String(v); }, removeItem: function (k) { delete mem[k]; }, }; } } // Browser: auto-mount (the early script already set data-theme). if (typeof document !== "undefined" && typeof window !== "undefined") { var boot = function () { try { init(document, safeStorage(window), window.fetch.bind(window)); } catch (e) {} }; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", boot); } else { boot(); } window.cpSetThemeId = function (id) { return setTheme(id, document, safeStorage(window), window.fetch.bind(window)); }; window.cpThemeSwitcher = api; } // node (unit tests). if (typeof module !== "undefined" && module.exports) { module.exports = api; } })();