VICTORIA CALL BOOKING — CPANEL FILES
Version: 1.0 — integration build (no admin authentication)

AS REQUESTED
- No admin password.
- No login form.
- No Firebase authentication or Firebase dependency.
- Booking data is stored in your cPanel MySQL/MariaDB database.
- This is a booking scheduler, not a built-in video call service.
- Admin access is OPEN. Anyone who reaches /booking/ or its admin API can
  see and change bookings. Connect your existing login before live use.

REQUIREMENTS
- PHP 8.1 or newer, PDO and pdo_mysql extensions.
- MySQL 5.7+ or MariaDB 10.3+ with InnoDB.
- HTTPS/SSL on your domain.
- Apache or LiteSpeed honoring .htaccess (typical cPanel hosting).
- No Node.js, Composer, Firebase, or build command needed.

INSTALL IN CPANEL
1. Open File Manager > public_html (or your domain's document root).
2. Upload the ZIP and Extract. Move its booking/ folder into public_html/.
   The final structure should be public_html/booking/index.php.
   Do not overwrite your existing site's files.
3. In cPanel > MySQL Databases or Database Wizard:
   - Create a NEW dedicated database, e.g. youruser_booking.
   - Create a database user and assign it ALL PRIVILEGES on this database.
   - Record the FULL database and username, including the cPanel prefix.
4. In phpMyAdmin, select that new database and Import:
       booking/private/schema.sql
   Import once. Do not import into an existing application database.
5. Copy booking/private/config.example.php to booking/private/config.php.
   Edit:
   - db_host (usually localhost), db_port (usually 3306)
   - db_name, db_user, db_password (DATABASE credentials, NOT admin login)
   - base_url: https://yourdomain.com/booking (no trailing slash)
   - existing_login_url: your existing website URL (back link only)
   - timezone, if needed
6. Use HTTPS: https://yourdomain.com/booking/
   The admin dashboard opens directly. There is NO admin password.
7. Confirm that /booking/private/schema.sql returns Forbidden, not the SQL
   contents. The included private/.htaccess blocks access to that folder.
   If your server ignores .htaccess, ask your host to deny web access to it.
8. Remove the uploaded ZIP from public_html after extraction. Keep your
   local original ZIP and a database backup.

USE THE BOOKING SYSTEM
1. Availability > Add availability.
2. Select the display timezone, date, start/end times, and call duration.
3. Customer links > Create customer link.
4. Enter customer name and https://onlyfans.com/username.
5. Choose Once, Twice, or Unlimited.
6. Copy the generated link and send it privately to that customer.
7. Customer picks a time and submits a request: Pending.
8. Approve or Decline in Bookings.
9. After an approved call's scheduled end, mark it Done.

BOOKING RULES
- Pending does NOT block a slot for other customers.
- Approved locks the slot, removing it from availability for everyone else.
- Other pending requests for that approved slot are automatically declined.
- Pending + Approved + Done count toward the link allowance.
- Declined requests restore the allowance.
- Revoking a link disables it; existing approved calls remain confirmed.
- An invitation identifies the profile you entered; it does not prove that
  the visitor owns the OnlyFans account. Anyone with the link can use it.
- At most 10 requests per invitation per hour, including unlimited links.
- Overlapping availability is skipped. Slots cannot be approved twice.
- A database transaction and a shared row lock serialize booking changes.
- Time values are stored in UTC; the interface displays the chosen timezone.
- Past slots cannot be booked. Mark Done is available after the call ends.
- Calls spanning midnight: add availability separately for each date.

NOTIFICATIONS
- The open admin dashboard refreshes every 15 seconds.
- Enable browser alerts using the button on the admin dashboard.
- Browser alerts only work while the dashboard is open and the browser
  permits notifications. This is not background push notification delivery.
- Optional email: set email_alerts=true, admin_email, and mail_from in config.
  PHP mail() must be available and configured by your host; delivery is not
  guaranteed. Ask the host to configure the sender, SPF, and DKIM.
- Telegram notifications are not included.

CONNECT YOUR EXISTING LOGIN LATER
- Replace admin() in private/admin-access.php with your existing server-side
  authentication and authorization check.
- Admin READ and WRITE API operations call this function.
- Hiding the page or checking only a browser variable is not enough.
- If using Firebase later, the backend must verify the Firebase ID token
  and the allowed role/UID. Do not simply trust a UID sent by the browser.
- If adding bearer-token authentication, update the api() request helper
  in assets/app.js to attach the verified identity token.
- Keep customer GET/customer and POST/book usable without an admin login.
- The back-to-website link is navigation only, not an authentication check.

FILES
booking/index.php                 Admin dashboard shell
booking/book.php                  Customer booking page
booking/api.php                   Database operations and booking rules
booking/assets/app.js             Calendar and UI logic
booking/assets/style.css          Responsive blue/white Victoria theme
booking/assets/favicon.svg        Site icon
booking/private/config.example.php Configuration template
booking/private/bootstrap.php      Database, CSRF, response helpers
booking/private/admin-access.php   Open access hook for later integration
booking/private/layout.php         Shared page shell
booking/private/schema.sql         MySQL schema (import once)
booking/.htaccess                  Basic Apache rules
booking/private/.htaccess          Blocks private folder web access

VERIFICATION AND LIMITS
- JavaScript syntax was checked.
- Source was reviewed for booking transactions, prepared SQL statements,
  random invitation tokens, CSRF checks, and output escaping.
- This environment has no PHP/MySQL runtime, so the cPanel package has NOT
  been executed end-to-end here. Validate it on your host with test data.
- Live hosting configuration, SSL, database access, email delivery, and
  integration with your current website have not been verified.

QUICK HOST TEST (USE TEST DATA)
- Create 2 customer invitations and a future slot.
- Request that slot from both links: both should show Pending.
- Approve one: the other must become Declined; the slot must disappear.
- A once-only link must reject an extra active booking.
- Decline a pending request and confirm its allowance is restored.
- Revoke a link and confirm its customer page rejects new requests.
- Test a different display timezone; confirm both represent the same instant.
- Verify the private folder is blocked before entering real credentials.

TROUBLESHOOTING
- Setup needed: config.php is missing.
- Database/service error: check the database name/user/password and SQL import.
- Blank page/500: choose PHP 8.1+; enable pdo_mysql; inspect cPanel Errors.
- HTTPS required behind a reverse proxy: ask the host to configure HTTPS
  correctly for PHP. Do not disable the HTTPS requirement or trust arbitrary
  X-Forwarded-Proto headers.
- 403 in private folder: expected.
- Configuring db_password is for MySQL; it does NOT add an admin password.
