=== Events Calendar, Tickets & Registration with QR Check-in ===
Contributors: bitforgenet
Donate link: https://ko-fi.com/bitforgenet
Tags: events, event calendar, tickets, registration, qr code
Requires at least: 5.8
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.15.7
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

An event calendar and a page for every event. Name every guest, send each a QR ticket, scan them in at the door. Seven languages. No fees.

== Description ==

**Events & Tickets** runs the evening from the first booking to the last guest
through the door. It was built for clubs, bars and party promoters — the people
for whom an event is a door, a list, and a queue outside — and it has since been
used for seated dinners, concerts, conferences and weddings, because they are
the same problem wearing different clothes.

Nothing is capped and nothing is metered. There is no per-ticket fee, no
external service to sign up for, no account to create, and no telemetry. Your
guest list lives in your own database, on your own server.

= It speaks seven languages, and it brought them with it =

English, French, Spanish, Portuguese, German, Italian and **Arabic** — not a
promise that somebody will translate it one day, but seven finished catalogues in
the download.
Install it and it is already in your language.

**It works the language out for itself.** Whatever WordPress is set to, the
plugin follows — and it follows by language rather than by locale, so `pt_BR`,
`pt_PT` and `pt` all land on Portuguese and `ar_DZ`, `ar_MA` and `ar_SA` all land
on Arabic. A site in a language it does not have falls back to French rather than
serving a screen that is half one language and half another. If you would rather
say it outright, there is one setting: *Settings → Language*.

**Everything is translated, not just the buttons.** The booking form the guest
fills in, the emails they receive, the words printed on the ticket itself, the
door station held at the entrance, and the admin screens you work in. Dates too —
the month and the weekday come out of the plugin's own catalogue rather than
WordPress's, so a French ticket does not print *September* under a French
heading on an English site.

**Arabic really is Arabic.** The screens, the emails and the booking form read
right to left. And the ticket — which is a drawn image, not a web page — is drawn
with an Arabic typeface that travels with the plugin, with the letters joined the
way Arabic joins them and the line put in reading order. A time, a price, a table
number or a ticket reference still runs the other way inside the sentence, as it
should. Most plugins that claim Arabic print a row of disconnected letters
backwards on the one thing the guest actually holds.

**The language travels with the booking.** A guest who booked in Spanish gets
their ticket in Spanish — including a ticket re-sent months later, from a screen
you are reading in French. And your own words stay yours: event titles, venue
names, payment instructions and the success message are your text, and the plugin
will not rewrite them.

= A calendar of your events, and a page for every one =

**An agenda your guests can use.** One shortcode, one block in the editor or
one Elementor widget, and your events are on a calendar: *Compact* (a dot a
night), *Month* (the time and the title in each day), *Large* (the picture of
each night) and *List*, in rows or as a grid of cards. It shows dates, not
events — every date of a series in its day, each with its own state: open, few
places left, sold out, closed, cancelled. Guests go to a date, keep only the
events they care about or one category, add a night to their calendar and
share it. The month they open comes with the page; the next one is asked for
when they turn to it. Without JavaScript, it is a list of links search engines
can follow.

**Shaped from one screen.** The view it opens on, the views on offer, the
number of nights a day, the pictures and their size, rows or a grid, the
corners, the colour of each state, your theme's style or its own — with a
sample beside the settings that changes as you choose, before you save.

**A page for every event, and for every date.** One page lists every event to
come, and under its address each event has its own: `/events/opening-night/`,
and `/events/opening-night/2026-10-09/` for one date of a series. The address
speaks your site's language — `/evenements/`, `/eventos/`, `/veranstaltungen/` —
and the page wears your theme or the *Classic* look: the picture, the date and
the place at the top, the details beside, the booking form below. An event can
also live on a page of its own, built with your editor or with Elementor; the
plugin finds it, and every link then leads there. Links already shared keep
working, with a permanent redirect.

**Categories, venues and organizers, each with a page.** Sort events into
families — Jazz under Concerts — each with a colour, a picture and a few words.
Guests filter the agenda by category, and every category, every venue and every
organizer has its own page with its own events to come. A venue's page shows
the address, the map and the website; an organizer's, the logo and the links —
never their email address or phone.

**Your own agenda, to run the season.** Under Events, a calendar for whoever
runs the events: every state, drafts included, what the site shows and what it
hides, how full each night is. Year, month, week or list; filters and a search.
Drag a night onto another day to move it; change the state of one event or of
several at once; start a new event from the day it falls on. A night somebody
has booked never moves from there.

**Found by search engines.** Every event page describes its date, its place, its
line-up and its prices in the structured data search engines read; a date of a
series says which series it belongs to, and the page of a series lists every
date on sale. Category, venue and organizer pages describe themselves too, and
every page carries the breadcrumb from the list of events.

= When it is full, when it sells, and what guests are told =

**A full date keeps the people it would have turned away.** Under "sold out",
the page offers to join the waiting list. When a place comes free — a
cancellation, a refund, a payment that ran out, a capacity you raised — it is
held for the first person in line, who gets a link to book it. Nobody else can
buy it in the meantime; if they do not book in time, it goes to the next
person. Not "first to click wins": first in line, for real. How long a place
is held is yours to set, and shortens on its own close to the date.

**Each category sells when you say.** An early bird that closes on the 1st, a
door price that opens on the day, a table sold by four: sale dates and a
minimum per booking on each category. A category outside its dates stays on
the page, greyed, with the reason, rather than vanishing; the server refuses
it whatever the browser sends.

**Reminders that bring people in.** The day before and two hours before by
default — a week before and the morning after if you want them — in the
language each guest booked in, with the doors, the address, the online link
and a fresh link to every ticket. Each one goes once and only once. The
morning after thanks them, offers the next date and, if you give one, the link
where they can review your event.

**Write to everybody who booked.** One date or all, one category or all,
confirmed, waiting for payment, came in or did not: preview it, send yourself a
test, then send. One email per address, in batches your host accepts, with a
record of every one. Nothing tracks who opens it.

= After the booking: a page of their own, the money, the paperwork =

**Every booking has a page of its own.** Each email about a booking ends with
a link to the guest's own page — no account, no password: where the booking
stands, every guest and their ticket to download, the venue, the way into the
online room, the invoice, and what happened when. A guest who has lost their
emails types the address they booked with and receives the links there; the
page never says whether an address has booked.

**Guests can cancel, if you let them.** Off unless you turn it on, for the site
or one event, until 48 hours before the date or the deadline you choose. The
guest cancels the whole booking from their page, after a question: its tickets
stop opening the door, its places go back on sale and the waiting list is
served. The money stays where it is: refunds are yours to make, in one click.

**A booking and its money are two facts.** A booking is pending, confirmed,
cancelled or expired; its money is due, paid or refunded. A paid booking you
cancel keeps its money until you decide — *Cancelled — paid* — and a payment
that arrives late never reopens a booking somebody cancelled.

**Refunds that give the money back.** From the booking's screen: by card,
through Stripe, back to the card that paid — or recorded, when you gave it back
by transfer or in cash. All of it or part: the guests you tick leave the
booking, their tickets stop working and their places go back on sale, and the
guest is told what was refunded, how, and who is no longer coming. A refund
here is money returned, not a word changed on the booking.

**Invoices and credit notes, when you turn them on.** Two series without a gap,
issued as the money moves: an invoice when a payment is confirmed, a credit
note when money goes back. Your name, your legal details, VAT none or included
in the price, in your site's language; an A4 PDF attached to the email and kept
on the guest's page; every document as a spreadsheet for your accountant. The
plugin follows your settings, not a tax law: what your invoices must say is
yours to check.

**Your words in the emails.** The subject, the title and the first paragraph of
each of the nineteen emails a guest can receive, in each language, with
`{first_name}`, `{event}` and the other words filled in for each guest. Below
your words the plugin still writes the evening, the tickets and the links, so
nothing a guest needs can go missing. Preview it as a guest will see it, send
yourself a test, and go back to the shipped text in one click.

**Questions for your guests.** A menu, a size, a company to invoice: each
question is asked of every guest or once per booking, in the ticket categories
it concerns — a child's age only of the Child category. The answers go to the
booking, the export and the team's email, and to the ticket or the invoice when
you choose. The server checks them against the category it records, and a
booking's answers are erased in one click.

= Who it is for =

* Clubs, bars and late-night venues
* Party and concert promoters
* Seated dinners, galas and weddings
* Conferences, seminars and school evenings
* Associations and community groups
* Anyone taking bookings by card, by transfer, by WhatsApp or in cash

= Set an event up by answering questions =

Creating an event asks three things first: how guests attend — at a venue,
online, or both — what it is called and when, and whether it repeats. Then an
assistant takes over, and it is the shortest way to describe a night that
exists. It starts with a drawing rather than a form:
fifteen kinds of event, from a standing club night to a banquet, a theatre, a
podium in I or in T, a stadium, a classroom. You point at the one that looks
like your room.

From there every answer decides the next question, and nothing is asked twice.
Are seats numbered? Then how is the room laid out — tables in rows, rows of
chairs, or no order at all? How many rows, how many tables to a row, how many
chairs to a table? Are there levels — a balcony, a terrace, a gallery? Which
parts are sold at which price? Do guests buy a ticket, or simply reply? How
are you paid, and what should somebody who
pays by transfer be told? Does the ticket leave immediately, or once you have
assigned the places yourself? Who chooses the place — the guest, or you?

The panel on the right draws the room while you answer, and shows the prices as
the booking page will show them and the line the ticket will print. When you
finish, the event is ready to sell: places, zones, prices, payment, delivery.

**The assistant owns nothing.** It adds no setting of its own and keeps no
column of its own — it fills in the panels that already held each answer, and
every one of them stays editable field by field afterwards. An assistant that
knows something the editor does not is a second source of truth, and this
plugin has already paid that bill. For the same reason it refuses to rebuild
the room of an event that already has bookings: it will not renumber a table
somebody has already been sold.

= The room is an inventory, and a zone is an interval of it =

Say the room once — six rows of eight tables, ten chairs a table, plus a
balcony — and the plugin numbers every place in it. A zone then claims a slice
of that inventory: *tables 1 to 5*, *rows A to C*, *the whole balcony*. It
invents nothing, so nothing can be sold twice and nothing is quietly lost:
whatever no zone claims is named on screen as unclaimed rather than forgotten.

A price category is not a zone. A category has a name and a price, and several
zones can share it — Premium is Premium on the left balcony and on the right.
**The booking page sells the categories; the ticket prints the zone**, because
the zone is what somebody reads at the door.

Each zone also says what it controls: access only — a standing area where
nobody has a seat — or exactly where each person sits. One event can hold all
three at once: a standing floor, a seated balcony, and a numbered block.

And if you want to draw the room instead of describing it, the builder is
there: drag tables and rows onto a plan, rectangle-select or shift-click,
align, space evenly, nudge with the arrow keys, place a stage, a bar, a door.
The plan you draw is the plan the guest picks from, and the plan you watch on
the night.

= One event, many dates =

A weekly club night, a play that runs for a month, a course every Tuesday: one
event with several dates, not one event per date. Set the rule once — every
day, week, month or year, on the weekdays you tick, until a date or for a
number of dates — and each date gets its own bookings, its own capacity, its
own door and its own online room. The guest picks a date on the booking page,
and everything they receive carries that date: the emails, the ticket, the
calendar file.

Changing dates works the way every calendar has taught everybody: this date,
this one and the following, or all of them. A date somebody has booked is never
moved with the others — it is named, so you change it knowing who holds a
ticket for it. A booked date is cancelled rather than deleted, and its tickets
are refused at the door with the reason. A date that needs another room or
other prices can be detached into an event of its own, taking a copy of the
room and the ticket categories with it.

At the door, a ticket for another date is refused as *not tonight*, with the
date it is for.

= Online, at the venue, or both =

How guests attend is the first question of every event. Online, nobody is
seated and nothing waits for a place: the capacity is the size of your online
room. Hybrid, the room people walk into and the online room share one capacity.

Guests never receive the meeting link itself. Each gets a personal link through
your site, checked the moment it is clicked — so the link can be added late or
changed at any time and still reach everyone, a cancelled booking stops opening
it, and you decide who gets in: anyone who booked, only paid guests, or only
once the room opens. Each date of a series can have a link of its own.

= Invitations as well as tickets =

Any ticket category can be a reply instead of a sale: free, confirmed the
moment the guest answers, with a ticket and its QR code or simply with their
name on the list. When every category of an event is a reply, the booking page
becomes an invitation — *count me in* or *I can't make it*, and no total. A
guest who cannot come says so, you are told, and the place stays free. One
evening can mix both: a free reply for the family beside a paid dinner.

= Speakers, performers and the programme =

Describe the people who appear once — a photo, a few lines, their links — and
put them on as many events as you like. Each event has a line-up, shown on the
booking page and printed on the ticket, and a programme of sessions: who, what,
when and where, day 2 at 00:30 included. On a series, a session can belong to
one date only.

= In your guests' calendars =

The thank-you page, the first email and every night of the agenda offer the
date to Apple Calendar and Outlook (a .ics file), Google Calendar and
Outlook.com — with the right time zone and, online, the way in.

= Your emails carry your name =

The top of every email is your event: the organizer's logo, the title of the
event and who is presenting it, in colours worked out to stay readable on your
brand colour. The plugin's name appears nowhere in what your guests receive. If
you would like to credit it, one box in *Settings → Email* adds a small line at
the bottom — off unless you switch it on.

= Every guest is a person, not a number =

A booking for five asks for five names, and each one gets their own ticket with
its own QR code. One code cannot let five people in, and the door knows who is
standing in front of it.

The booking form also knows what is left **while it is being filled in** —
counted against what the page was rendered with, what the lines above it have
already taken, and what somebody else is taking in another browser at the same
moment. An option with nothing left is greyed out rather than removed, so
nobody's choice is ever changed behind their back. The real guarantee is not in
the browser, where it could never be: the event is locked, the places are
recounted and the booking is refused at the moment of writing.

= Tickets that look like tickets =

Each one is drawn at 100 x 250 mm, 300 dpi, with the QR engraved into the
artwork, and delivered as a PDF by email. Mail servers strip attachments more
often than they admit, so every message also carries a download link for each
guest.

The ticket studio takes your own artwork if you have some — upload it, generate
colour variations, and move every printed field where you want it on a visual
field map — and generates a design for you in the colour of your choice if you
would rather not think about it.

= The door works =

Open the check-in station on any phone — no app to install. Point it at a
ticket and it answers in one screen: valid, already used, or not for tonight.
Counters update live, several phones can scan the same event at once, and when
the venue's wifi gives up — it will — there is a printable roll-call list with
every guest and every ticket number on it.

The plan says who is actually in the room. A place that has been sold and a
place whose guest has walked through the door are two different facts, and only
one of them moves all evening: a guest who has scanned turns green, carries a
tick and pulses, and a table whose whole party has arrived wears a green ring.

= Payment on your terms =

Two ways, and neither is the lesser one.

Take the money yourself: a booking arrives pending, you confirm it however you
actually get paid — bank transfer, WhatsApp, cash at the office — and the
tickets go out the moment you do. Nothing is ever issued for money you have not
received. What the guest is told about paying is your own text, written per
event, because offline that text *is* the payment.

Or let the card do it: add your own Stripe key and the guest pays on Stripe's
page, comes back confirmed, and gets their tickets without you touching
anything. Their places are held while they pay and released on their own if
they walk away, so the same seat is never sold twice. The money goes straight
from the guest to your own Stripe account — this plugin is never in between,
and takes nothing.

= What the free plugin does =

Everything below is in this plugin. There is nothing to unlock.

* **Unlimited events and unlimited tickets.** No cap, no per-ticket fee.
* **Seven languages in the box** — English, French, Spanish, Portuguese, German,
  Italian and Arabic, detected from your site or chosen in one setting, covering the
  admin, the booking form, the emails, the ticket artwork and the door station,
  with right-to-left layout and real Arabic shaping on the printed ticket.
* **Event assistant** — how guests attend first, then fifteen drawn
  archetypes, one question at a time, and a live preview of the room, the
  prices and the printed line — all the way to the day the event opens.
* **Event editor** — panels for each part of an event: information and
  details, recurring dates, programme, prices and places, rules and terms,
  payment, ticket and link.
* **Recurring events** — every day, week, month or year; each date with its own
  bookings, capacity, door and online room; change one date, the following ones
  or all; cancel, delete or detach a date.
* **Online and hybrid events** — a personal, checked join link for every guest,
  four access rules, a link per date, check-in on the first click.
* **RSVP** — free replies, confirmed at once, with a ticket or name on the list;
  a booking page that becomes an invitation.
* **People and the programme** — speakers and performers described once, a
  line-up per event, and sessions placed inside the night.
* **Event calendar (agenda)** — four views, rows or a grid of cards, go to a
  date, filter by event or category, add to calendar and share; settings with a
  live sample; a shortcode, a block for the editor and an Elementor widget.
* **A page for every event and every date** — an events page, addresses in your
  site's language, your theme's look or *Classic*, an event on a page of its
  own found wherever it is, and old links redirected.
* **Categories** — a tree of categories with colours and pictures, chosen on
  each event, each with its own page.
* **Venue and organizer pages** — each with its description, its links and its
  events to come.
* **Your own agenda** — every state, drag a night to move it, change states in
  bulk, start an event from its day.
* **Add to calendar and search engines** — .ics, Google Calendar and
  Outlook.com links; schema.org Event, EventSeries, Place and Organization data;
  breadcrumbs on every page.
* **Waiting list** — on a full date or a sold-out category; a freed place held
  for the first in line, for a time you set; emails in the guest's language; a
  screen per date, offer a place by hand, export.
* **Sale dates and minimum per booking** — per category, in the event's time
  zone; greyed with the reason when closed; refused by the server.
* **Reminders** — a week before, the day before, two hours before, the morning
  after; chosen for the site and per event; once each, in the booking's
  language.
* **Messages to participants** — filter by date, category and who came,
  preview, test, send in batches, history; no tracking.
* **Room builder** — describe the room in numbers or draw it: tables, rows,
  levels, a stage, multi-selection, alignment, even spacing, arrow-key nudging.
* **Zones and price categories** — a zone is an interval of the room, a category
  is a name and a price that several zones can share.
* **Organizers library** — name, logo, colours, contact. Reused across events.
* **Venues library** — address, capacity, notes, and a public page. Reused
  across events.
* **Public booking page** — one shortcode, `[bitforgenet_registration]`. Asks
  for the name of every person coming, shows what is still available as the
  form is filled in, respects capacity and the registration window, and
  confirms on screen. If no page carries the shortcode, the plugin shows the
  form itself rather than leaving a dead link.
* **Bookings screen** — search, filter by event and status, confirm payment,
  add an internal note, resend an email, cancel, or enter a booking by hand.
  A booking's state and its money are shown apart, and in one word in the list.
* **My tickets** — a page for every booking, opened by the signed link in each
  of its emails, and *Find my tickets* for a guest who has lost them.
* **Cancellation by the guest**, if you allow it, up to the deadline you choose,
  for the site or one event.
* **Refunds** — by card through Stripe or recorded when made elsewhere, in full
  or for some guests only, with an email to the guest every time.
* **Invoices and credit notes** — off until you turn them on; two series without
  a gap, A4 PDFs, attached to the emails and exported for your accountant.
* **Email texts** — the subject, title and first paragraph of each email, in
  your own words, per language, with a preview and a test.
* **Questions for your guests** — per guest or once per booking, per ticket
  category; on the booking, in the export, and on the ticket or the invoice.
* **Seating and the floor** — every zone on one screen while the evening fills,
  a booking seated by hand or placed for you, sold against arrived, and a
  ticket that will not print until every guest on it has a place.
* **Moving somebody who already holds a ticket** — the screen states the three
  consequences, the buttons stay dead until you type `edit place`, the old
  ticket stops working at the door and a second email goes out.
* **Personal QR tickets** — one per guest, rendered as a PDF, sent by email
  with a download link alongside.
* **Ticket studio** — your own artwork, colour variations, and a visual field
  map for every printed field.
* **Door check-in station** for any phone, opened with a per-event door code,
  with live counters and multi-station scanning.
* **Printable roll-call list** for the evenings the network fails.
* **Discount codes**, with their own limits.
* **Card payment with Stripe** — the guest pays on Stripe's own page and comes
  back with their booking confirmed. Their places are held while they pay and
  released on their own if they never finish. The money goes straight from the
  guest to your own Stripe account — this plugin is never in between and takes
  nothing.
* **Emails in your name** — the event and its organizer at the top, colours
  that stay readable on your brand colour, and the plugin's name nowhere unless
  you tick the optional credit line.
* **Team notifications** — a new booking can be copied to as many colleagues as
  you like, not just one address, with your site's name in the subject.
* **CSV export with a column picker** — bookings or guests, one event or all,
  every field the plugin holds, and it remembers what you ticked.
* **Tools and data** — a system check that tells you why a ticket or an email
  did not arrive, a test-ticket email, a database check, and an
  archive-and-clear that copies every booking into archive tables before
  emptying the live ones, behind a one-time code sent to an address you
  nominate.
* **Searchable archive** of everything that has been cleared.
* **Activity log** — who did what, and when.
* **A Help screen inside the plugin** — the whole guide, on the screen where
  you are stuck, linking to the screens it talks about. Open to anyone who can
  see the plugin at all, because the person who most needs it is the one on the
  door at midnight.
* **Delete-all-data on uninstall**, if you tick it. Off by default.

= Nothing is held back =

There is no paid edition of this plugin. The assistant, the room builder, the
ticket studio, the price categories, the discount codes and card payment are
all here, in the plugin you just installed. Nothing is capped, nothing is
metered, and no screen ends in an offer.

= Reporting a security issue =

If you find something, write to the address on
https://bitforgenet.dev/ and it will be looked at, fixed and credited here by
name unless you would rather not be. Please test against your own installation
rather than somebody else's.

Thank you to **Alik** for the two issues fixed in 1.2.1.

= Privacy =

The plugin stores what a booking needs — names, email address, phone number —
in your own database, on your own server. Email goes out through WordPress,
which means through whatever mail service your site already uses. There is no
account to create with us and no telemetry: nothing is ever sent to BitForge
Network.

The public agenda remembers the view a guest last chose, in their own browser
(local storage), and nowhere else. It sets no cookie.

Reminders and messages to participants go to the address given when booking,
through WordPress, like the tickets. They carry no tracking pixel and no
rewritten link: the plugin records that an email left, never whether it was
opened. Someone on a waiting list can take themselves off from the email they
received.

A guest's own page opens with the signed link in their emails, for whoever
holds it, until 30 days after the event; it asks search engines and caches
to keep nothing. *Find my tickets* answers the same way whether an address has
booked or not: only the mailbox learns it.

The questions you ask your guests are yours to choose: ask only what you need.
Their answers are kept with the booking and can be erased from it in one click;
deleting a booking deletes them. Invoices and credit notes are kept even when a
booking is deleted, as accounting documents are; only *delete all data* on
uninstall removes them.

= External services =

The plugin uses one external service, and only if you set it up yourself.

**Stripe** — used only when you enter a Stripe secret key under Settings →
Payments and turn card payment on for an event. Until then no connection to
Stripe is ever made.

When a guest chooses to pay by card, the plugin asks Stripe to open a payment
page and sends what that page has to show: the amount, the currency, the event
title, the booking reference, the number of tickets in each category, and the
guest's email address so Stripe can send them a receipt. The guest is then
taken to a page hosted by Stripe, where they enter their card details. No card
number ever reaches your site or this plugin. Stripe tells your site the result
in a signed message, and the plugin reads the payment status back from Stripe
before it confirms anything.

When you refund a booking by card, the plugin asks Stripe to refund that
booking's payment: it sends the payment to refund, the amount, and a key that
keeps the same refund from ever being made twice. Stripe's answer, and its
later messages about the refund, are read back the same way.

Stripe is a service of Stripe, Inc.
Terms: https://stripe.com/legal/ssa
Privacy: https://stripe.com/privacy

= Copyright and licence =

Copyright (C) 2026 BitForge Network — https://bitforgenet.dev/

Events & Tickets is free software, released under the GNU General Public
License, version 2 or (at your option) any later version. The full text is in
`LICENSE.txt`, in the plugin folder.

It bundles three typefaces, used to draw the tickets, all free for this use:

* **Poppins** — Copyright 2020 The Poppins Project Authors, SIL Open Font
  License 1.1.
* **Lora** — Copyright 2011 The Lora Project Authors, SIL Open Font License 1.1.
* **FreeSerif Arabic Subset** — a subset of GNU FreeFont's FreeSerif, Copyright
  2002-2012 GNU FreeFont contributors, GNU GPL version 3 or later with the GNU
  Font Exception.

Their licences and what was changed are in `assets/fonts/`. Everything else,
the QR code encoder included, was written for this plugin.

"BitForge Network", "BitForgeNet" and their logos are the names and marks of the
author. The licence covers the code, not the names: a modified copy is welcome
under the GPL, under a name of its own.

== Installation ==

= Requirements =

* WordPress 5.8 or later
* PHP 7.4 or later
* The GD extension, for rendering the tickets
* A working mail setup on the site — an SMTP plugin if your host's mail is
  unreliable

= Steps =

1. Plugins -> Add New, search for **Events and Tickets**, install and activate.
   Or upload the ZIP under Plugins -> Add New -> Upload Plugin.
2. Open **Events & Tickets -> Settings** and set your currency, your From
   address and your payment instructions.
3. Open **Events & Tickets -> Tools & data**, run the system check, then send
   yourself a test ticket. Do this before your first real booking, not after.
4. Create your first event with **Events & Tickets -> Events -> New event**.
   The assistant opens on its own and asks what kind of night it is.
5. Put the booking form on a page with the shortcode
   `[bitforgenet_registration]`.
6. On the night, open **Events & Tickets -> Door scanner**, note the door code,
   and give the link and the code to whoever is on the door.

== Screenshots ==

1. The event assistant. Fifteen kinds of night, drawn rather than listed — pick the one that looks like your room, and every answer from there decides the next question. The panel on the right builds the room as you go, and shows the prices the booking page will show and the line the ticket will print. It refuses to rebuild a room that already has bookings.
2. The room builder. Describe the room in numbers — rows, tables to a row, chairs to a table, levels — or draw it: drag a stage in, rectangle-select a whole row, shift-click, align, space evenly, nudge with the arrow keys. The plan you draw is the plan the guest picks from and the one you watch on the night.
3. Prices & places, on one panel. What a ticket will say, how places are given out, the levels, and each part of the room with the price category it is sold as and the first places it hands out. The capacity is counted from the room, not typed beside it.
4. The booking page. One shortcode on any page. It asks for the name of every person coming — five names for a booking of five — and it knows what is left while the form is being filled in, counting the lines above and the other people booking at the same moment.
5. The floor, on the night. Every part of the room on one screen, filling in real time, with three facts kept apart: sold, seated, and arrived. The pale bar is what has been sold; the solid one inside it is who has walked in.
6. The door check-in station. A web page on any phone, opened with a per-event door code — no app to install. Camera, photo or keypad, a live count of who is inside, and one screen per scan: let in, already inside, or not for tonight.
7. Every ticket issued. One per guest, with its own serial and its own QR code, the place it carries, and whether that guest has walked through the door — with the minute and the entrance they came in by.
8. The control room. Every event, what has sold, what is still waiting on a payment, who has arrived — and the shortcode for the event you are looking at, ready to paste.
9. Help, inside the plugin. The whole guide on the screen where you are stuck: a first event in ten minutes, then the assistant, the room, payment, tickets, the night, and what to do when something does not arrive. Every step links to the screen it talks about.
10. Dates that repeat. One event, every Friday: each date keeps its own bookings, capacity and door. Change one date, this one and the following, or all of them — a date somebody has booked is never moved with the others.
11. The guest chooses the date. A series shows its dates on the booking page, and the one chosen travels to the emails, the ticket and the calendar file.
12. The door works one date at a time. A ticket for another Friday is refused as "Not tonight", and the screen says which date it is for.
13. Online and hybrid events. Every guest gets a personal join link that goes through your site and is checked when clicked, so the meeting link can change at any time. You choose who gets it, and when the room opens.
14. The agenda, month view. Every date of every event in its day, each with its own state; switch to compact, large or list, go to a date, keep only some events or one category.
15. The agenda as a grid of cards. The picture on top, the price, the state, the category, a button to book — and add to my calendar, and share.
16. The page of an event. Your theme's look or the Classic one: the path from the list of events, the picture, the date and the place, the categories, the booking form below. Each date of a series has its own page.
17. A category's page. Its picture, its words and only its events — the agenda filtered for it, with the categories under it.
18. A venue's page. The address, the map, the website, a few words, and the events to come there.
19. Your own agenda. Every state, drafts included, what the site shows and what it hides, how full each night is. Drag a night to another day; change several at once.
20. Cards and colours. Rows or a grid, the size of the pictures, the corners and the colour of each state, with a sample that changes as you choose.
21. Categories. A tree of families, each with a colour, a picture and its own page; ticked on each event.
22. A full date keeps its guests. Under "sold out", the waiting list: a name, an email, how many places. A freed place is held for the first in line.
23. The waiting list of each date: who waits, in which order, whose place is held until when. Offer a place by hand, take somebody off, export.
24. Sale dates and a minimum. An early bird whose sale has ended stays on the page, greyed, with the reason; a group category says its minimum.
25. On each category: on sale from, until, and the minimum per booking — and the event's own waiting list, beside it.
26. Reminders, per event: the site's, its own, or none; and the link where guests can review the event the morning after.
27. A reminder the day before, in the guest's language: the night, the venue and the way there.
28. Messages to participants. Choose who, write once, see it as they will, send yourself a test, then send in batches. Nothing tracks who opens it.
29. The guest's own page, opened by the signed link in every email: where the booking stands, each guest and their ticket — one who left with a refund — the invoice and its credit note, and what happened when.
30. A guest cancels, if you allow it: a question first, with what it means. Their places go back on sale; a payment is not refunded on its own.
31. A booking and its money, in one word: paid, awaiting payment, cancelled but paid, refunded — and how much was given back.
32. Refunds, on a booking's screen: by card through Stripe or recorded when made elsewhere, for the guests who leave or an amount alone. Below, the invoice and its credit note.
33. An invoice, when you turn them on: your name and legal details, the categories sold, VAT included at your rate, and the answers marked for the invoice.
34. The words of an email, in each language: the subject, the title and the first paragraph, previewed as a guest will receive it. The plugin writes the rest.
35. Questions for your guests: a menu for everyone, a child's age only in the Child category, a company asked once per booking for the invoice.
36. The booking page asks them: the second guest, in the Child category, gets their own question; the questions asked once come before confirming.

== Frequently Asked Questions ==

= The name keeps changing. Is it the same plugin? =

Yes. Same plugin, same folder, same settings, same data, same updates — only
the name shown in the directory has changed. It was *BitForgeNet Guest Tickets
and Door Check-in*, then *Events and Tickets with QR Check-in*, and it is now
**Events Calendar, Tickets & Registration with QR Check-in**, because it now has
the calendar. On your own screens it is still **Events & Tickets**. Nothing to
reinstall and nothing to reconfigure. It is still published by BitForge
Network, which is what the Author line says, and this is the last renaming.

= How do I show a calendar of my events? =

Create the events page under *Settings → Event pages* — it shows the agenda —
or put `[bitforgenet_agenda]` on any page, the *Events agenda* block in the
editor, or the *Events agenda* widget in Elementor. *Events → Agenda settings*
decides how it looks, with a sample beside, and writes a shortcode for one
category, one venue, one organizer, this week, this month or this year.

= Does every event get a page of its own? =

Yes, under the events page: `/events/opening-night/`, and one more for each
date of a series. The address needs pretty permalinks; on a site with plain
ones, links go through the booking page and everything else works. Prefer to
build the page yourself? Paste the event's shortcode on any page or post — an
Elementor page included — and every link leads there instead.

= Will the links I already shared stop working? =

No. Old booking links, a base you changed, a renamed category: each answers
with a permanent redirect to where the page is now.

= Can my guests see only one kind of event? =

Yes. Give events categories under *Events → Categories*: guests filter the
agenda by them, and each category has its own page. A shortcode, a block or a
widget can also show one category, one venue or one organizer only.

= What happens when an event is full? =

Guests can join its waiting list from the page. When a place comes free, it is
held for the first person in line — 24 hours by default, less close to the
date — and they get a link to book it. Nobody else can buy it meanwhile. You
can turn the list off for the site or for one event.

= Can a ticket category go on sale later, or stop selling? =

Yes. Each category has its own sale dates and a minimum per booking, on the
event's *Prices & places* tab. Outside its dates it stays on the page, greyed,
with the reason. A booking you add by hand is not held to either.

= Does it send reminders? =

Yes: the day before and two hours before, by default, to every confirmed
booking, in the language it was made in, once each. A week before and a
thank-you the morning after can be added for the site or for one event. They
leave with WordPress's own scheduler, which runs when the site is visited.

= Can I write to everybody who booked? =

Yes, from *Messages*: choose the event, one date or all, one category or all,
and who — confirmed, waiting for payment, came in or did not. Preview it, send
a test to yourself, then send. It goes out in batches your host accepts, one
email per address, and records what left. It does not track who opens it.

= Can guests find their tickets again? =

Yes. Every email about a booking ends with a link to the guest's own page: the
booking, the tickets to download, the invoice, the history. A guest who has
lost their emails asks for the links on *Find my tickets* and receives them by
email — the page never says whether an address has booked.

= Can a guest cancel their booking? =

If you allow it: it is off until you turn it on, under *Settings → Booking
form*, for the site or for one event, with a deadline (48 hours before the date
by default). The whole booking is cancelled; its places go back on sale and the
waiting list is served. A payment is not refunded on its own: you refund it,
in one click.

= Can I refund a booking? =

Yes, from its screen: by card through Stripe, back to the card that paid, or
recorded when you refunded it some other way. In full or in part; the guests
you tick leave the booking and their places go back on sale. The guest always
receives an email saying what was refunded.

= Does it make invoices? Are they valid in my country? =

It can: turn them on under *Settings → Invoices*. Invoices and credit notes are
numbered in two series without a gap, issued as the money moves, and carry your
name, your legal details and VAT as you set them. What an invoice must say
depends on your country and your business: the plugin follows your settings,
not a tax law, so check them with your accountant.

= Can I change what the emails say? =

Yes, under *Settings → Email texts*: the subject, the title and the first
paragraph of each email a guest receives, in each language. The rest — the
evening, the tickets, the links — is still written by the plugin, and a
language you have not written in keeps the shipped text.

= Can I ask guests questions when they book? =

Yes, on the event's *Prices & places* tab: a menu, a size, a company to
invoice — of every guest or once per booking, in the categories you choose. The
answers are on the booking and in the export, and on the ticket or the invoice
if you tick it. They can be erased from a booking in one click.

= Is there a limit on events, guests or tickets? =

No. Nothing in this plugin is capped or metered, and there is no per-ticket
fee. What your server can hold is the limit.

= Is there a paid version? =

Not today. Everything this plugin can do is in the plugin you installed — the
assistant, the room builder, the ticket studio, the price categories, the
discount codes and card payment included. No screen ends in an offer.

= Do guests need an account? =

No. A guest fills in the form, receives their tickets by email, and shows the
QR code at the door.

= Can an event repeat? =

Yes. Under *Information & details*, set it to repeat every day, week, month or
year, on the weekdays you choose, until a date or for a number of dates. It
stays one event: each date has its own bookings, capacity and door, and the
guest chooses the date when booking. The *Recurring dates* tab lets you change
one date, the following ones or all of them.

= Can I run an online or hybrid event? =

Yes. Choose *Online* or *Both* as the first answer when you create the event,
and put your meeting link in *Information & details*. Every guest receives a
personal link through your site rather than the meeting link itself, so you can
change the link at any time, and a cancelled booking stops opening it.

= Can guests just reply, without paying? =

Yes. Set a ticket category to RSVP: the place is free and confirmed the moment
the guest replies, with a QR ticket or simply their name on the list. When every
category is an RSVP, the booking page becomes an invitation with *count me in*
and *I can't make it*.

= Does the plugin's name appear in my guests' emails? =

No. The top of every email shows your event and its organizer. There is an
optional credit line in *Settings → Email*, off by default.

= Does it need WooCommerce? =

No. It has its own booking form and its own bookings screen, and it works on a
site with no shop on it.

= Do I have to use the assistant? =

No. It opens when you create an event because that is the fastest way through,
and you can leave it at any point: every answer it writes is a field you can
open and change afterwards. It owns no setting of its own.

= How do I describe a room that is not a grid? =

Two ways, and they end in the same place. Describe it in numbers — rows, tables
to a row, chairs to a table, levels — or draw it in the builder: drop tables,
rows, a stage and a bar on a plan, select several at once, align them, space
them evenly, nudge them with the arrow keys. Either way the plugin numbers
every place and hands them out.

= Can one event have standing room and numbered seats? =

Yes. Each zone says for itself whether it controls access only or where each
person sits, so a standing floor, a seated balcony and a numbered block can all
belong to the same night.

= What is the difference between a zone and a price category? =

A zone is a piece of the room — *tables 1 to 5*, *the balcony*. A category is a
name and a price, and several zones can share one: Premium is Premium on the
left balcony and on the right. The booking page sells the categories; the
ticket prints the zone, because that is what somebody reads at the door.

= Can I change the room after people have booked? =

You can add to it and change prices. You cannot rebuild it: the assistant
refuses to renumber a room that already has bookings, because a table number
somebody has already been sold has to keep meaning the same table.

= Two people booked the last table at the same moment. What happens? =

One of them gets it and the other is told, before anything is charged. The form
shows what is left while it is being filled in — including what somebody else
is taking in another browser — but the guarantee is not in the browser: the
event is locked, the places are recounted and the booking is refused at the
moment it is written.

= Can I move somebody who already has their ticket? =

Yes, and the plugin treats it as what it is: a re-issue, not an edit. The
screen states the three consequences, the buttons stay dead until you type
`edit place`, and then the old ticket stops working at the door and a second
email goes out with the new one.

= Can I take payment online? =

Yes, with Stripe. Put your own Stripe secret key in Settings → Payments and
turn card payment on for the events you want it on. The guest pays on a page
hosted by Stripe, no card number touches your site, and the money goes straight
to your own Stripe account: this plugin is never in between and takes nothing
per ticket, ever.

Until you enter a key, nothing changes and no connection to Stripe is made. A
booking arrives pending and you confirm it once you have been paid — by
transfer, by WhatsApp, or in cash — exactly as before.

= Do I have to make guests pay by card? =

No. It is a choice per event, and you can also let a guest reserve now and pay
later: they get both buttons. If you would rather nothing be reserved until it
is paid for, there is a single setting for that. What a guest who pays offline
is told is your own text, written per event — offline, that text is the
payment.

= Does one booking give one QR code for everybody? =

No, and that is the point. A booking for five produces five tickets with five
different codes, each carrying the name of the person it belongs to.

= Can more than one of us be told when a booking arrives? =

Yes. The notification address takes a list, and every address on it is really
copied in.

= The tickets are not arriving. =

The plugin sends through WordPress, so anything that fixes email for the rest
of your site fixes it here. Run **Tools & data -> System check** first: it says
whether the failure is in the rendering or in the sending. If your host's mail
is unreliable, install an SMTP plugin and connect a real mailbox — it will be
picked up automatically.

= The email arrives but the PDF is missing. =

Your mail server is stripping the attachment. Lower the attachment ceiling in
Settings; every email already carries a download link per guest, so the guest
still gets their ticket.

= Does the door scanner need internet? =

It needs to reach your own website, the same as any other page. For the
evenings when the venue's wifi is not to be trusted, print the roll-call list
first: it carries every guest and every ticket number, and it works on paper.

= Do I need to install an app on the door phone? =

No. The station is a web page. Open the link in the phone's browser, enter the
door code, and allow the camera.

= Can two people scan at once? =

Yes. Every station checks the same database, so a ticket used at one door is
already used at the other.

= The camera stays black on the door phone. =

The page must be served over HTTPS — browsers refuse the camera otherwise. If
the site is already on HTTPS, a security plugin or your CDN is probably sending
a blanket camera policy; the scanner screen re-states its own, so clearing the
CDN cache usually settles it.

= Can I use my own ticket artwork? =

Yes. The plugin will generate a design for you in the colour you choose if you
would rather not think about it, and the ticket studio on the **Ticket designs**
screen takes your own artwork instead: upload it, generate colour variations of
it, and move every printed field where you want it on a visual field map.

= Can I clear the test bookings before going live? =

Yes. **Tools & data -> Archive and clear** copies every booking, guest, ticket
and scan into archive tables and then empties the live ones. Events, venues,
organizers and designs are untouched. It asks for a one-time code sent to an
address you set, so it cannot be run by accident.

= What languages does it come in? =

Seven, finished and in the download: English, French, Spanish, Portuguese,
German, Italian and Arabic. Nothing to install and nothing to wait for.

= How does it know which one to use? =

It reads the language WordPress is set to, and it reads it by language rather
than by locale — pt_BR, pt_PT and pt all get Portuguese; ar_DZ, ar_MA and ar_SA
all get Arabic. A site in an eighth language falls back to French rather than
showing you half a translation. You can also say it outright under **Settings →
Language**, which is the answer when your site is in one language and your guests
read another.

= Does it change the language of my site? =

No. It moves this plugin and nothing else. WordPress, your theme and every other
plugin keep the language they had.

= Is the ticket itself translated, or only the screens? =

The ticket itself. A ticket is a drawn image rather than a web page, so it is the
piece that usually gets left behind — here the words on it, the date written out
in full, and the line that says which table or seat all come out in the guest's
language.

= Does Arabic work properly, including on the ticket? =

Yes, and that is a real question rather than a polite one. Arabic letters change
shape depending on what is beside them, and the line reads right to left; the
image library that draws tickets does neither by itself, which is why Arabic on a
ticket usually comes out as a row of disconnected letters in the wrong order. The
plugin joins the letters and orders the line before anything is drawn, and carries
an Arabic typeface to draw them with. Numbers inside the sentence — a time, a
price, a table number, a ticket reference — still run the other way, as they
should. The screens, the booking form, the emails and the door station are laid
out right to left too.

= A guest booked in one language and I work in another. Which one do they get? =

Theirs. The language a guest booked in is kept with their booking, so their
ticket and their emails go out in it — including a ticket re-sent months later
from a screen you are reading in French.

= Are my own event titles translated? =

No, and they should not be. Your event titles, venue names, payment instructions
and success message are your words; the plugin translates its own and leaves
yours alone. A venue selling to guests in two languages writes those lines in
both.

= Can I correct or add a translation? =

Yes. The catalogues are ordinary .po files in the plugin's `languages` folder,
and the template is there beside them. Better still, put the correction on
https://translate.wordpress.org/projects/wp-plugins/bitforgenet-guest-tickets/ —
a language pack from there is loaded ahead of the plugin's own files, so your
wording wins and everybody gets it.

= Where do I get help? =

There is a **Help** screen in the plugin itself — the whole guide, one click from
wherever you are stuck. The same text is at
https://bitforgenet.dev/plugins/bitforgenet-guest-tickets/help/ — it walks
through a first event, the room, the door and the night itself. Beyond that,
the support forum on this page, or contact@bitforgenet.dev

== Upgrade Notice ==

= 1.15.7 =
A page of their own for every booking, guest cancellation, refunds, invoices
and credit notes, your own email texts, and questions for your guests. New
columns and two new tables: back up first. Guest cancellation and invoices
stay off until you turn them on.

== Changelog ==

= 1.15.7 =
After the booking: what a guest can do on their own, and what the money does.

* **My tickets.** Every email about a booking links to the guest's own page —
  signed, no account: the booking and its state, each guest and their ticket,
  the venue, the online room, the invoice, the history. *Find my tickets* sends
  the links to the mailbox and never says whether an address has booked.
* **A booking and its money, two facts.** Pending, confirmed, cancelled,
  expired or declined; due, paid, refunded or nothing due. *Cancelled — paid*
  keeps the money of a cancelled booking; a late payment reopens nothing. The
  old column keeps its old word, so an earlier version reinstalled still reads
  every booking right.
* **Guest cancellation**, off by default: from their page, after a question,
  until a deadline (48 hours by default), for the site or per event. The whole
  booking; places back on sale, waiting list served, the guest and the team
  told.
* **Refunds**: by card through Stripe, or recorded when made elsewhere; in
  full, or for some guests, who leave the booking for a closed one of their
  own. Never more than what is left; the same refund never made twice; an
  email to the guest every time.
* **Invoices and credit notes**, off by default: two series without a gap, an
  invoice when a payment is confirmed, a credit note when money goes back for
  good; A4 PDFs in the site's language, attached to the emails and on the
  guest's page; a spreadsheet export by year. Never deleted with a booking.
* **Email texts**: the subject, the title and the first paragraph of each of
  the nineteen guest emails, per language, with the words of *Messages*, a
  preview and a test. The shipped text wherever none is written.
* **Questions for your guests**: per guest or once per booking, in the ticket
  categories they name; checked by the server; on the booking, in the export,
  in the team's email, and on the ticket or the invoice when ticked; erased
  from a booking in one click.
* **The waiting list follows its date**: a detached date takes its list with
  it; a cancelled date or event tells everybody waiting.
* **Fixed**: saving *Prices & places* on an event without a room turned table
  numbers on, and its paid tickets then waited for a table; a booking that
  had expired, been refunded or declined could keep its table in the counts.
* **Seven languages**, every new screen and email included, and the *Help*
  screen with a section for each.

= 1.14.4 =
Full, on sale, reminded: what happens between the booking and the night.

* **Waiting list.** On a full date or a sold-out category, guests join the
  list. A freed place — cancellation, refund, payment run out, deleted
  booking, capacity raised — is held for the first in line, who is sent a link
  to book it; nobody else can buy it meanwhile. Hold time set for the site or
  per event, shorter close to the date. Emails in the guest's language; a
  leave link that asks first. A *Waiting list* screen per date, with "offer a
  place now", remove and CSV export.
* **Sale dates and minimum per booking**, per category, in the event's time
  zone. Closed categories stay on the page, greyed, with the reason; nothing on
  sale shows when sales open. Refused by the server too. A room's parts follow
  the ticket category of the same name.
* **Reminders**: a week before, the day before, two hours before, and a
  thank-you the morning after with the next date and the organizer's review
  link. Chosen for the site and per event (a *Reminders* tab). Once each, in
  the booking's language, with fresh ticket links.
* **Messages to participants**: by date, category and public (confirmed,
  waiting for payment, came in, did not), with preview, test, batches your
  host accepts, and a history address by address. No tracking pixel.
* **Seven languages**, every new screen and email included.

= 1.13.12 =
Being found: a calendar of your events, a page for every one, and what search
engines read about them.

* **An agenda for your guests.** Compact, month, large and list views, the list
  in rows or as a grid of cards; every date of a series in its day, with its
  own state; go to a date, keep some events or one category; add to my
  calendar and share on every night. A shortcode, a block for the editor and
  an Elementor widget, with the same choices.
* **Shaped from one screen.** Views, nights a day, pictures and their size,
  corners, the colour of each state, your theme's style or its own — with a
  live sample before you save.
* **A page for every event and every date**, under an events page that the
  plugin creates or that you choose; addresses in your site's language; your
  theme's look or *Classic*; a date picker on a calendar for a series; an event
  on a page of its own, found wherever it is, Elementor included; old links
  redirected.
* **Categories**, in a tree, with colours and pictures, chosen on each event;
  each with its own page.
* **A page for each venue and each organizer**, with its events to come —
  never an organizer's email or phone.
* **Your own agenda** under Events: every state, year, month, week or list,
  filters and a search; drag a night to move it, change states in bulk, start
  an event from its day.
* **Search engines**: a date of a series names its series, the page of a series
  lists its dates, venues and organizers describe themselves, and every page
  carries its breadcrumb.
* **A new name in the directory**: *Events Calendar, Tickets & Registration with
  QR Check-in*. Same plugin, same slug, same data.
* **Seven languages**, every new screen and page included.


= 1.12.18 =
The biggest release since the first: events that repeat, online events,
invitations, people and a programme, calendars — and a door that knows which
night it is.

* **Events that repeat.** Every day, week, month or year, on the weekdays you
  tick, until a date or for a number of dates. Each date keeps its own
  bookings, capacity, room and door. Change one date, this one and the
  following, or all of them; a date somebody has booked is never moved with
  the others. Cancel, delete or detach a date — a detached date takes a copy
  of its room and categories with it.
* **Guests choose their date** on the booking page, and everything they
  receive — the emails, the ticket, the calendar file — carries it.
* **The door works one date at a time.** A ticket for another date is refused
  as "Not tonight"; one for another event names its event. The Door screen
  opens on tonight's event. "Close all stations" closes every station,
  including phones signed in to WordPress, and gates are asked only where
  there are several.
* **Online and hybrid events.** Every guest gets a personal join link that
  goes through your site and is checked when clicked, so the meeting link can
  change at any time. You choose who gets in, and when.
* **Invitations (RSVP).** Any ticket category can be a free reply instead of
  a sale, confirmed at once — with a QR ticket, or just a name on the list.
  An event made only of replies becomes an invitation page.
* **People and the programme.** Speakers and performers described once and
  used on any event; a line-up on the page and on the ticket; sessions placed
  inside their date.
* **Add to my calendar, and found by search engines.** Apple, Outlook and
  Google Calendar from the thank-you page and the first email; every event
  page describes itself in the structured data search engines read.
* **One assistant.** How guests attend comes first, then the name, the date
  and whether it repeats; an online event skips the room.
* **Your emails, your name.** Every email carries your event and its
  organizer, in colours computed to stay readable on your brand colour. The
  plugin's name appears only in an optional credit line.
* **Seating that holds.** Rooms on several named levels keep every place, the
  plan writes "4/5" on every table, and "Place them for me" reports what was
  really saved.
* **Seven languages, completely.** Every screen, email and ticket in English,
  French, Spanish, Portuguese, German, Italian and Arabic — Arabic with its
  six plural forms.
* **Fixes**, among them: tickets on hosts without mbstring, online events
  sending their tickets, Arabic room and category names, screens saved
  without changes changing nothing, the places left on a booking for a later
  date of a series, and the door's "Next guest" button, now full width.
* **Copyright and licence stated**: a copyright notice in the plugin header,
  and the full text of the GNU GPL in `LICENSE.txt`.

= 1.11.0 =
* **Italian, the seventh language.** A complete catalogue in the download —
  admin screens, booking form, emails, door station, dates and the words printed
  on the ticket. it_IT, it_CH and it all land on Italian.
* **Settings → Language** lists Italian, and the other six catalogues name it in
  their own language.
* Directory banners updated to show the seven languages.

= 1.10.1 =
* Removed `admin/views/event/pricing.php`, a tombstone left from the retired
  Pricing tab that nothing has called since 1.9.0.
* Refreshed the two brand images shipped with the plugin.
* Added a donate link to the directory listing. Nothing appears inside
  WordPress: no screen in this plugin ends in an offer, and that has not
  changed.

= 1.10.0 =
* **Six languages, in the download.** English, French, Spanish, Portuguese,
  German and Arabic. Every screen, the booking form, the emails, the door
  station and the words printed on the ticket.
* **The language is worked out from your site**, by language rather than by
  locale: pt_BR, pt_PT and pt all land on Portuguese, ar_DZ, ar_MA and ar_SA all
  land on Arabic. A site in a language the plugin does not have falls back to
  French rather than serving half a translation.
* **New setting: Settings → Language.** Leave it on *Follow the site*, or name
  the language outright — for a site in one language selling to guests who read
  another. The screen says what your site is set to and what the plugin will
  speak, so there is nothing to guess at.
* **The language travels with the booking.** A guest who booked in Spanish is
  answered in Spanish, including a ticket re-sent months later from an admin
  screen in another language, or issued by cron in the middle of the night.
* **Dates are translated too**, out of the plugin's own catalogue rather than
  WordPress's — so a French ticket does not print "September" under a French
  heading on an English site, and a site that has never installed French still
  gets French months.
* **Arabic is drawn properly on the ticket.** The ticket is an image, and the
  library that draws it neither joins Arabic letters nor puts the line in
  reading order. The plugin now does both before drawing, and carries an Arabic
  typeface to draw with. A time, a price, a table number or a ticket reference
  still runs the other way inside the sentence.
* **Right-to-left layout** for the admin screens, the booking form, the emails
  and the door station — the plugin's own containers only, so the rest of your
  site is untouched. A seating plan is not mirrored: table 1 stays where table 1
  actually is.
* The plugin's catalogues are loaded after any language pack from
  translate.wordpress.org, so a translator's work always wins over ours.

= 1.9.1 =
* **Renamed, and this time for the search rather than for the branding.** The
  directory ranks the words of a title, so the title is now
  **Events and Tickets with QR Check-in** — the words somebody actually types.
  On your own screens and in the admin menu it is **Events & Tickets**, two
  words that fit a sidebar. The brand leaves the title: the Author line already
  says BitForge Network, and a name is not the place to sign your work twice.
* The slug, the text domain, the shortcodes, the option keys, the database
  tables and the update path are untouched, exactly as in 1.9.0. Nothing to
  reinstall, nothing to reconfigure.

= 1.9.0 =
* Renamed on screen. The slug, the text domain, the shortcodes, the option
  keys, the database tables and the update path were all untouched: a label,
  not a new plugin. (1.9.1, the same day, renamed it again — see above.)
* New icon and new directory banners: a ticket and a QR code, which is what the
  plugin actually is. The QR in the artwork is a real one.
* The directory page shows the screens again — eight of them, from the
  assistant to the door station — and the description finally covers what was
  added between 1.2.2 and 1.8.7: the assistant, the room builder, zones as
  intervals of an inventory, price categories, live availability in the booking
  form, arrivals on the plan, re-issuing a place, and team notifications.
* The FAQ was rewritten around the questions the last two months produced.
* **New: a Help screen inside the plugin.** The whole guide — setup, the
  assistant, the room and its zones, payment, tickets, seating, the door, and
  what to do when something does not arrive — on the screen where somebody is
  actually stuck, linking to the screens each sentence talks about. It reads
  nothing and writes nothing, and it needs no capability beyond being able to
  open the plugin: help only an administrator can read is help the person who
  needed it could not reach.
* Nothing else changes: no database change, no stored setting touched, and no
  existing screen behaves differently.

= 1.8.7 =
**The team notification field takes more than one address.** A team is more than
one person. Separate them however you like — a comma, a semicolon, a space, one
per line — and everybody on the list is copied on guest emails and alerted on
every new booking. Before, only the first address was ever used.

**An empty reply-to now follows WordPress.** Left blank it means "whatever this
site uses" rather than "nobody", so replies land in the site's own
administration inbox without anybody having to think about it. The from address
behaves the same way, and both boxes show you the address they would fall back
to.

**Fixed: typing an answer in the assistant left *Continue* greyed out.** Every
keystroke repainted the panel, but only a full redraw ever drew the buttons — so
after typing the payment instructions the only way to move on was to step back
and forward again. The answer and the button are drawn together now.

**The floor plan says who is actually in the room.** A seat that is sold and a
seat whose guest has walked through the door are two different facts, and only
one of them changes all evening. A guest who has scanned their ticket turns
**green**, carries a **tick**, and breathes gently; a table whose whole party
has arrived wears a green ring. There is an **Already in** filter, a key under
the plan explaining every colour, and the same story in the simple list for
anyone who never opens the drawing. The movement stops for anyone whose system
asks for less motion — the colour and the tick still say everything.

**Moving a guest who already has a ticket is no longer an ordinary save.** It
is a reissue, and it does three things at once: the tickets they are holding are
**voided** — the door refuses those QR codes from that moment — new tickets are
drawn with the new places, and a second email goes out. If they have already
shown somebody the first one, that is the copy that stops working. So the screen
now says all of that in plain words, and the buttons stay dead until you type
`edit place` into the box beside them. Not a checkbox, which the hand ticks
before the eye reads; not a browser dialog, which is dismissed by reflex. The
same sentence is checked again on the server, because a rule that only lives in
a browser is not a rule.

= 1.8.6 =
**The booking form now knows what is left while somebody is filling it in.**
Three things have to agree, and until now only the first was ever asked: the
number the page was drawn with, **the guest rows above this one**, and whoever
else is booking at the same moment somewhere else. Choose VIP for five guests in
a room that has five, and the sixth row greys VIP out as you reach it — instead
of letting you type eight names and refusing the lot at the end.

**It asks again at the moments a decision is being made**: a menu opening, a
choice changing, the quantity changing, the tab coming back to the front — and
on a slow tick in between, never while the tab is hidden. One function answers,
for the page and for the live refresh alike, so the two can never disagree. It
is cached for five seconds and thrown away the instant a booking is written, so
the next person to open a menu sees the seat go.

**The quantity stepper stops at what exists**, and a line above the guest rows
says how many places are still for sale, counting down as they go.

**A category that sells out under you is said out loud**, on the row it affects,
and the booking cannot be sent until you have picked another. Your choice is
never changed behind your back — first come, first served, and being told so.

**Fixed — and this was the hole underneath all of it: a booking held no place in
its category until somebody had been sat down.** The seat count could only see
guests who already had a place written against them, and where the organizer
seats people by hand nobody has one until they do it — hours or days after the
guest paid. A VIP zone of forty still reported forty places left after forty
people had bought it. Every booking now holds its places from the moment it is
written, whether or not anybody has decided where those people are sitting.

**None of this is the guarantee, and it does not pretend to be.** The booking
itself is still taken under a lock on the event, counted again, and refused with
a plain sentence if the last place went a second ago. The live form exists so
that you are told *before* you have typed eight names rather than after.

= 1.8.5 =
**Fixed: your event was not selling the price categories you gave the room.**
Every event is handed a "Standard admission" ticket category the moment it is
created, and the room only spoke up when nothing else had — so you could name
three price categories in the assistant, see all three on every screen in the
admin, and have the booking page sell one. **The room now decides what an event
sells whenever it describes it**, because it is the thing that actually holds
the people. A room category you left at zero borrows the price of the ticket
category of the same name, so nothing silently drops to the base price.

**The ticket-categories list stops competing.** With a room in place it folds
away on *Prices & places* under **Offers that are not places** — early bird,
member, child: a price about *when* or *who* rather than *where*. That is the
job it is actually for.

**Fixed: the WordPress footer printed across two tabs.** One stray closing tag
at the foot of two templates closed WordPress's own content wrapper early,
which dropped "Merci de faire de WordPress votre outil de création de contenu"
into the middle of the Ticket and Payment tabs. The test bench now counts
opening and closing tags in every template, because nobody reads a closing tag
at the foot of a 120-line file and a machine counts them in a millisecond.

**The floor plan builder can select more than one thing.** Drag a rectangle over
the floor and it picks up every part it touches; shift-click adds one;
<kbd>Ctrl</kbd>+<kbd>A</kbd> takes the lot. Then move them together, line them
up — left, centre, right, even gaps — duplicate them or remove them in one go.
Before this, the *only* rectangle gesture in the builder struck seats out: the
obvious way to grab a row of tables quietly crossed out every chair inside it.
A rectangle now means whatever the tool means, and striking seats out lives
with the strike-out tool where it belongs.

**The stage is picked up like anything else.** It needed its own tool before,
which is not something anybody guesses.

**More of the builder**: arrow keys nudge a selection by 10 cm, or a metre with
<kbd>Shift</kbd>. <kbd>Ctrl</kbd>+<kbd>D</kbd> duplicates,
<kbd>Delete</kbd> removes. The panel now opens on **what you have selected**
instead of on the template gallery, so clicking a table no longer scrolls its
own settings out of sight. A part has a **Level** field, and the room has a
name field in the builder.

**The name of the room is asked at the top of the assistant**, where you already
know it, instead of sitting in a box at the bottom of a tab.

**Fixed:** the Category column of a guest list showed a dash for every guest who
booked a part of the room, because it looked in one module's own table instead
of asking the question properly.

= 1.8.4 =
**The assistant describes a room the way you would describe it out loud.** You
say how many rows of tables and how many tables to a row — that lays the hall
out once and numbers every table — and then each zone claims a stretch of it:
*"the VIP zone runs from table 1 to table 5."* A zone no longer invents places
of its own, which is what makes the rest possible: the same table can never end
up in two zones, and a table you left out of every zone is named on screen
rather than quietly dropped off the sale.

**A price category is no longer the same thing as a zone.** A category has its
own name and its own price, and several zones can share one — Premium is
Premium whether it is the left balcony or the right. The booking page sells the
categories; the ticket prints the **zone**, because the zone is what somebody
actually reads at the door.

**The payment question is now the whole story.** As well as how people pay and
when the ticket goes out, the assistant asks what to tell a guest paying off the
site, how many places one booking may take, and whether you need a name for
every place or one name for the booking. All four are written into the event.

**Prices & places shows the room instead of asking for it again.** The four
buttons — no places, one gauge, zones, a plan — and the *"What one person is
given"* radio group are gone. Both asked what the assistant had just asked, and
the two screens could contradict each other: answer "tables" in the assistant,
tick "a chair" here, and the plugin starts selling chairs at a table nobody
booked. The tab now **draws the room that exists**, says in a sentence what a
ticket will print, and gives you the two ways back — run the assistant again, or
open the builder on what it built.

**The capacity is counted, not typed.** With a room in place, the capacity box
is replaced by the room's own total. Two boxes for one number always ends the
same way: one of them is believed at the door.

**Fixed: a balcony forgot it was a balcony.** A block's level and its control
were saved to the database and never read back, so both were lost the first time
the room was loaded again.

**Fixed: a hall of tables came back sold chair by chair.** The floor plan
builder never sent the room's grain back when you saved, so a room built around
whole tables was rewritten as a room of single seats.

= 1.8.3 =
**Fixed: finishing the assistant broke the site.** It wrote its entry to the
activity log with the wrong number of arguments, which PHP answers with a fatal
error — so the last click of the assistant produced a white screen. The test
bench now reads every logging call in the plugin and checks it passes what the
log actually asks for.

**The assistant walks you through it now.** It showed every question at once and
left you to work out where the end was. It asks **one question at a time**, with
**Back** and **Continue** at the bottom and a row of steps along the top showing
where you are, what is behind you, and what is still to come. Continue stays
greyed out, with a reason, until the question in front of you has an answer — a
button that disappears just leaves you looking for it.

= 1.8.2 =
**Fixed: finishing the assistant said "Security check failed".** Its form was
signed with the name of a different action, which is the same as not signing it
at all — so the one button that mattered died at the last step. Every form is now
checked against the action it posts, by the test bench, so this cannot come back
quietly.

= 1.8.1 =
**The creation wizard stops asking what the assistant asks.** It had a "Tickets"
step wanting a price and a capacity, and then the assistant wanted the same two
numbers again — with the zones and the room that give them meaning. One number
asked on two screens is how two screens end up disagreeing about it. Creating an
event is now three steps, and the last button says what happens next: *Set up
places and prices*.

= 1.8.0 =
**An assistant that sets up an event by asking about it.** Prices, zones,
capacity and the moment a ticket goes out are one decision described on four
screens, and nobody arriving for the first time can know that. So the assistant
has the conversation instead — starting from a picture of the kind of room you
are filling, not a word for it — and writes the answers into the tabs.

* It opens by itself after you create an event, and there is a button for it on
  **Prices & places** whenever you want to run it again.
* **Every answer decides the next question, and the panel beside it shows the
  consequence**: the room being drawn, the prices a guest will see, and what the
  ticket will actually print.
* It tells you what each answer settles and why — *"the ticket carries the table,
  so the chair number is not asked: at a round table it tells nobody anything."*
* **It owns nothing.** It adds no setting of its own; everything it decides is
  still there, field by field, on the tab that always owned it.
* It will not quietly rebuild a room for an event that already has bookings —
  a place is printed on a ticket the moment it is given out.

= 1.7.0 =
**One tab for money, capacity and places.** The price and the capacity lived on
one screen and the room on another, so you could set a capacity of 500 and then
describe a room holding 380 — and nothing said so until somebody was turned away
at the door. They are one decision, so they are now one tab: **Prices & places**.
A place there is whatever your event hands out: a seat, a table, a row, or a
whole area.

* **Pricing & capacity is gone.** The price, the currency and the capacity moved
  to Prices & places, along with the price categories and the zones.
* **When & where is now Information & details**, and holds what a guest is told
  before booking — including *this event serves food or drinks* and the sponsor
  strip.
* Old links to the removed tab land on Prices & places instead of dropping you
  back at the start.

**Fixed: the back button brought a finished booking form back to life.** After
booking, pressing Back showed the form still filled in, with the submit button
still greyed out and the countdown frozen — a page that looked broken. A booking
could never have been made twice (the server has refused that since 1.3.0), but
the page now reloads itself, with an empty form, a live clock and a working
button.

= 1.6.1 =
**Fixed: named zones were all sold at the price of the event.** Give three zones
three prices and the booking page offered three zones — at one price. Worse, the
booking was charged that price too, so a zone priced higher than the event was
sold short and one priced lower was overcharged. The room hands the booking form
a zone carrying its own price; the form then asked a separate question — *what
does this cost?* — that nothing was answering for a zone. It answers now.

**Fixed: deleting a zone moved the bookings of the one below it.** Zone
references were rebuilt from their position on every save, so removing the first
zone renamed the second into it, and a booking already sold pointed at a zone its
guest never bought. Each zone now carries its own reference.

**Fixed: a zone of 25 places sold 40.** A capacity that did not divide evenly
into rows was rounded up to fill the last row, silently. The surplus places are
now held back, and a zone holds the number you typed.

= 1.6.0 =
**Four capabilities that used to be withheld are now in the plugin.**

* **The ticket studio.** Bring in your own artwork, generate colour variations
  of it, and place every printed field yourself on a visual field map, on the
  Designs screen.
* **The floor plan editor.** Draw the room: the stage, curved rows, round
  tables, standing areas and aisles, with numbering that runs whichever way
  your venue counts — and a guest who picks their own seat on the plan.
* **Price categories.** VIP, table, early bird, member: several prices on one
  event instead of one.
* **Discount codes.** Fixed or percentage, limited by date or by number of
  uses.

Nothing was removed and nothing changed shape: existing events, designs, rooms
and settings are read exactly as before. If you never open these screens, the
plugin behaves as it did.

= 1.2.1 =
Two security fixes, both reported responsibly by **Alik**, who tested 1.0.9 in
an isolated environment and sent a clear, accurate write-up of each. Both were
real. Thank you.

**Bookings for one event now happen one at a time.** Counting the free seats
and taking one were two separate steps, and between two steps another request
fits: two people clicking at the same instant could both be told there was one
seat left, and both take it. The capacity check was never wrong -- it was just
on the wrong side of a gap. That gap is now closed with a lock held for the
length of a booking, per event, so a busy night with four events does not queue
into one line. Every capacity rule is now inside it: the event's own capacity,
each price category, and each area of the room. (CWE-362.)

**Forwarding headers are no longer believed by default.** The plugin recognises
a visitor by their address in order to count how often they book. It used to
read CF-Connecting-IP, X-Real-IP or X-Forwarded-For if they were present --
but those are written by whoever is making the request, so anybody could invent
one and get a fresh allowance. Only the address the connection actually came
from is used now. If your site really is behind Cloudflare or a reverse proxy,
say so under Settings → Anti-abuse, and the panel shows you what your server is
actually sending so the choice is not a guess. Naming your proxies in
wp-config.php as BFNET_TRUSTED_PROXIES narrows it further. Where a list of
forwarded addresses is read, the plugin now takes the entry the nearest proxy
wrote rather than the one at the front, which is the one a visitor can invent.
(CWE-799.)

**Also**: a second booking limit counted per email address, so getting around
the per-connection one is no longer enough on its own.

= 1.2.0 =
Everything below arrived since 1.0.9. It was built and tested over several
internal builds; this is the first of them anyone is offered, because a version
that was superseded the same week is not a version worth installing.

**Rooms and places.** An event can now describe where people sit. Three levels,
and nobody is made to climb them: a plain capacity, named zones with a capacity
and a price each, or -- with Pro -- a drawn floor plan. Seats are worked out
from a rule rather than stored, so a four thousand seat auditorium is twenty
rows in your database and not four thousand. The numbering runs whichever way
your venue counts: left to right, right to left, odd and even out from the
centre, alternating by row. It can skip row I and O, skip 13, start anywhere,
and carry a prefix.

**Card payment with Stripe.** Set your own secret key and a guest can pay on
Stripe's own page. No card number reaches your site. A payment is confirmed by
reading it back from Stripe and by a signed message Stripe sends your site --
never by the browser that came back. Your places are held for the length of the
payment session and released on their own if nobody finishes, so the same seat
cannot be sold twice. Card payment is optional, per event: an evening paid at
the door works exactly as it did before.

**When the ticket goes out, per event.** Acknowledge the booking now and send
the ticket once you have decided where somebody sits, or -- when the event has
a room -- send it straight away with the place printed on it.

**The booking page no longer depends on a page.** If a direct link to an event
has nowhere to open, the plugin renders the booking form itself inside your
theme. It also creates the booking page for you, once, rather than leaving a
link that opens nothing.

**Fixed**

* A booking link opened an empty page on sites that had never added the
  shortcode themselves.
* Guest rows two and after on the manual booking screen were greyed out instead
  of hidden, because the plugin's own stylesheet beat the browser's rule.
* The Reserve button was clipped by themes with their own line height.
* Sold-out categories were still offered for booking; a category is now closed
  by the room as well as by its own capacity, and the last place is re-counted
  at the moment the booking is written rather than only when the page was
  drawn.
* Reverting a booking to awaiting payment cleared the check-ins but kept them
  in the history, named.

**Also added**

* Add a guest by hand, for the bookings that arrive by phone.
* A live floor view of the evening -- what is taken, what has arrived, and what
  is full -- with the room drawn as the organizer drew it.
* The confirmation screen says which address the email went to, and to look in
  the spam folder.
* Keyboard in the plan editor: undo, redo, delete, escape, shift to select
  several, and a number beside every slider.

= 1.0.9 =
* The logo printed on the ticket, on the door's code screen and beside an
  organizer with no artwork of its own is the anvil alone. It had been the full
  lockup, wordmark included, which the renderer fits inside its box: a wide
  image with words in it shrank to a smudge nobody could read
* The plugin's page is rewritten. The feature list now says what this plugin
  actually does -- the organizer and venue libraries, the export column picker,
  the system check and the archive were all shipped and none of them were
  mentioned, while three of them were wrongly described as belonging to Pro.
  The Pro section says what Pro adds instead of hinting at it, and the FAQ
  answers fifteen questions rather than five. No code changed for this

= 1.0.8 =
* Every template under admin/views/ and public/views/ states once, at the top of
  the file, that the PrefixAllGlobals naming rule does not apply to it. A
  template is included from a method, never at file scope, so its variables
  belong to that method's scope rather than the global one, and PHPCS -- reading
  each file on its own -- has no way to see where the include happens. No
  variable was renamed and nothing behaves differently

= 1.0.7 =
* The plugin is renamed. It was submitted as "2KEvents", and "2K" is a
  registered trademark of Take-Two Interactive that we have no right to lead a
  name with. The display name, the slug, the text domain, the shortcodes and
  every PHP prefix now read BitForgeNet — the name of the site that publishes
  it, bitforgenet.dev
* Every stylesheet and script the plugin prints goes out through the enqueue
  API. The door station and the two screens around it are their own HTML
  documents, served on their own endpoint before the theme runs, so they had
  carried their CSS and JS inside the page. They now register handles and print
  them by name, the two runtime values arriving through wp_add_inline_style()
  and wp_add_inline_script()
* The admin menu icon is assembled from the mark at runtime and has no file
  behind it, so it registers a style handle with no source rather than printing
  a style tag into the head, and moves to admin_enqueue_scripts
* The code prefix is five characters. It was three, which is under the four the
  directory asks for

= 1.0.6 =
* Finished the tidy-up the last two releases started: every code-quality
  suppression in the plugin is now either stated once for a whole file or
  written on the single line it covers, and none of them can change the
  meaning of another one elsewhere in the same file. No behaviour changes

= 1.0.5 =
* Fixed suppression comments that did not cover what they appeared to cover.
  One kind switched every code-quality rule back on rather than the one it had
  switched off, quietly undoing notes written elsewhere in the same file; the
  other sat above a nine-line statement instead of around it. No behaviour
  changes for anyone using the plugin

= 1.0.4 =
* Request input is now read the way it should be read: eight admin screens
  applied the integer cast to the whole expression rather than to the value,
  and the export column list is sanitised where it arrives rather than three
  calls later
* The design proof screen now checks its parameter exists before reading it
* Every file that queries the plugin's own tables says so once, at the top,
  with the reason
* Dropped a call asking WordPress to load translations it already loads by
  itself, and closed a hatch that let the QR encoder run outside WordPress

= 1.0.3 =
* Fixed translatable strings that a translator could not have got right. The
  guest counter on an order wrote its two numbers as bare placeholders, which
  a language that reorders the words has no way to move, and several strings
  carrying a placeholder had no note saying what the placeholder holds.

= 1.0.2 =
* The plugin header pointed at a placeholder address. It now points at the
  plugin's own page, and the author is named.
* The address authorised to reset the plugin's data shipped with a developer's
  own address already filled in. It now starts empty, and the tool refuses to
  run until an administrator sets one.
* Added the full text of the SIL Open Font License beside the bundled Poppins
  and Lora fonts, as that licence requires.

= 1.0.1 =
* Fixed the door station refusing every scan with "Station closed". The page
  opened and showed the event, but each scan was posted to an address that no
  longer said which event the station was watching, so the server treated it as
  a station that had signed out. Nobody could be checked in

= 1.0.0 =
* First release.
