=== Freeslot Calendar ===
Contributors: krasimirignatov
Tags: calendar, availability, schedule, freelancer, appointments
Requires at least: 6.0
Tested up to: 6.9
Requires PHP: 7.4
Stable tag: 1.7.19
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Read-only availability calendar with admin-managed events. Bilingual (BG/EN), shortcode-driven. Show visitors when you're free, no booking system.

== Description ==

Freeslot Calendar is a lightweight WordPress plugin that publishes a clean monthly availability view on any page or post. It's built for freelancers, designers, photographers, consultants, and small studios who want visitors to see *at a glance* which days are open and which are busy, without exposing a full booking system.

Events live in your WordPress admin like any other content. The public calendar reads from them and paints each day as **Free**, **Partially busy**, or **Fully busy** based on your working hours.

= Key features =

* **Drop-in shortcode** — `[igcal_availability]` renders the calendar anywhere.
* **Bilingual out of the box** — Bulgarian and English, per-event title and note translations, automatic locale switching.
* **Working-hours aware** — partial vs. full busy status is computed from your actual day, not a guess.
* **Recurring events** — daily, weekly, monthly, with an end date.
* **Per-event color, image, and category** for richer day-detail cards.
* **Customizable Contact CTA** — label, colors, size, and the URL it links to.
* **Customizable header** — change the calendar's title and subtitle per language, or pass a `title="..."` shortcode attribute.
* **Accessible** — full keyboard navigation (arrows, Home/End, PageUp/Down), ARIA roles, screen-reader announcements on month change.
* **Mobile responsive** — two-stage breakpoints, dense list view on phones.
* **AJAX month navigation** with skeleton loader and cross-fade transitions.
* **Cached** — each month grid is cached per language and invalidated automatically when events or settings change.
* **No tracking, no external calls** — your data stays on your site.

= Shortcode attributes =

* `months` — number of months to render (default `1`).
* `lang` — `auto` (follow site locale), `bg`, or `en`.
* `title` — override the header title for this instance.
* `show_legend` — `1` or `0`.
* `show_cta` — show the bottom Contact CTA bar (`1` or `0`).

Example:

`[igcal_availability lang="en" months="3" show_cta="0"]`

== Installation ==

1. Upload the `freeslot-calendar` folder to `/wp-content/plugins/` (or install via *Plugins → Add New → Upload*).
2. Activate the plugin through the *Plugins* screen.
3. Go to *Freeslot Calendar → Settings* to set working hours, language, colors, and the Contact CTA.
4. Go to *Freeslot Calendar → Events* to add busy events.
5. Drop `[igcal_availability]` on any page or post.

== Frequently Asked Questions ==

= Does this plugin accept bookings? =

No. It's intentionally read-only — visitors see your availability and contact you through whatever channel you configure (email, form, Calendly link, etc.). This keeps the plugin small, fast, and easy to reason about.

= Does it support languages other than Bulgarian and English? =

Out of the box the calendar ships with `bg_BG` and `en_US` translations. The plugin is fully internationalized (`Text Domain: freeslot-calendar`), so additional locales can be added via standard `.po`/`.mo` files.

= Can I have multiple calendars on different pages? =

Yes — the shortcode can be placed on any page or post. All instances share the same event pool and settings (there is currently one global calendar, not multiple separately-managed ones).

= Does it work with my caching plugin? =

Yes. Month grids are cached via WordPress transients with automatic invalidation on event save and settings change. Page-level cache plugins work fine because the AJAX month-nav endpoint is unauthenticated and idempotent.

= Will it slow down my site? =

Assets (CSS / JS / fonts) only load on pages that actually contain the shortcode. The initial month is server-rendered; subsequent months are fetched via a single small AJAX call.

= Is the public calendar keyboard-accessible? =

Yes. Tab into the grid, then use arrow keys to move between days, Home/End for first/last day of the visible month, and PageUp/PageDown to jump between months. Today's cell is marked with `aria-current="date"` and month changes are announced via an ARIA live region.

== Screenshots ==

1. The public availability calendar on the front-end — month grid with Free / Partial / Full status and the Contact CTA bar.
2. Day-detail panel showing public event cards, working-hours timeline, and the contact note.
3. Admin Events list with bilingual titles, per-event color, and category.
4. Event editor with date/time, recurring, image, color, and EN translation fields.
5. Settings page — working hours, language, colors, CTA customization, and header text overrides.

== Changelog ==

= 1.7.19 =
* Removed `Author URI` from the plugin header (the WordPress.org review team requires domain-ownership verification when an Author URI is set, and the simplest path was to drop the line). Author credit "Krasimir Ignatov" is unchanged.

= 1.7.18 =
* Renamed plugin to "Freeslot Calendar" (slug `freeslot-calendar`) at the request of the WordPress.org review team, who flagged the previous name as too generic. Text domain, language files, and folder name updated to match.

= 1.7.17 =
* Removed `Plugin URI` from the plugin header — WordPress.org rejects submissions where Plugin URI and Author URI point to the same site. Author URI (https://ignatovdesigns.com/) stays.

= 1.7.16 =
* Renamed the leftover `ignatov_calendar_force_assets` filter to `igcal_force_assets` so the hook name matches the plugin's prefix (caught by Plugin Check after the rename).
* Updated `Contributors:` field in readme.txt to `krasimirignatov` (matches the WordPress.org account that will own the plugin).

= 1.7.15 =
* Fix: post-activation welcome notice now displays in English when the admin locale is English. The main message string was missing from the .po files entirely, and the "Add your first event →" string had an arrow inside the gettext call that didn't match the .po msgid. Both are now in sync.

= 1.7.14 =
* Added `Author URI` header so the author name on the Plugins screen links to https://ignatovdesigns.com/.

= 1.7.13 =
* Renamed the plugin to "Freeslot Calendar"; author credit updated to Krasimir Ignatov.

= 1.7.12 =
* Mobile / tablet: added 20px right margin to the Today button so it no longer hugs the right edge of the month-nav pill.

= 1.7.11 =
* Fix: on tablet and phone the Today button is now actually pinned to the right edge of the month-nav. The 1.7.9 rule was being overridden by the base `margin-left: 8px` rule because of CSS source-order; bumped with `!important` so the mobile override wins.

= 1.7.10 =
* Day-detail close button: removed the grey hover background — only the icon color darkens on hover now.

= 1.7.9 =
* Empty-state banner icon switched from brand-orange to ink (matches the calendar's other dark icons). On tablet and phone the month-nav pill (prev / month / next / Today) now stretches to the full calendar width with the Today button pinned to the right edge, so the header and grid line up visually on narrow screens.

= 1.7.8 =
* Cleaned up the surrounding chrome: month nav, empty-state banner, and day-detail panel are now transparent (no cream / peach fill), all using the same grey border. Empty-state banner's drop-shadow was dropped since a shadow on a transparent element looks odd.

= 1.7.7 =
* Clicking a day now leaves a visible "selected" marker on the grid — a semi-transparent green inset ring — so the visitor can see which day they just opened in the detail panel. Distinct from today's solid-green ring; works for both grid clicks and list-view row clicks.

= 1.7.6 =
* Calendar grid is now wrapped in a single bordered card with rounded corners and a soft drop-shadow. Day cells sit edge-to-edge inside the card with shared 1px separators (no gaps), the weekday header row sits at the top of the same card with a subtle tinted background. Today's cell now uses an inset green ring (so it stays inside the shared-edge grid). Status pills use a soft tinted background with matching text color instead of solid white-on-color. Cleaned up legacy `!important` overrides that were forcing the older sharp-corner / solid-pill look.

= 1.7.5 =
* Apple-style calendar refresh: each day cell is now its own soft card (larger border-radius, resting drop-shadow, wider gap between cells), and the status text ("Свободно" / "Частично заето" / "Напълно заето") is rendered as a tinted pill instead of plain text. Empty-month banner picks up the same soft shadow. Off-month and empty cells stay flat as before.

= 1.7.4 =
* Calendar header restyled: title and subtitle now both use Roboto; the second word of the default title is no longer italicized or accent-colored. Added Roboto to the bundled Google Fonts request.

= 1.7.3 =
* Converted the remaining `meta_query` / `meta_key` `phpcs:ignore` markers into proper `phpcs:disable` / `phpcs:enable` blocks so Plugin Check fully recognizes them as intentional. Runtime behavior unchanged.

= 1.7.2 =
* Second Plugin Check compliance pass: normalized all ABSPATH guards to the PCP-recognized form (no leading backslash), switched calendar arithmetic from `date()` to `gmdate()` (timezone-safe), set an explicit `IGCAL_VERSION` on Google Fonts enqueues (PCP rejected `false`), added `translators:` comment for the slot-length string, escaped the language-radio flag emoji, marked the pre-rendered month-grid / month-list HTML echoes as intentional (built upstream by escaping templates), switched `image_id` sanitization to `absint( wp_unslash() )`, dropped deprecated `suppress_filters` from the uninstall query.
* Bumped "Tested up to" to WordPress 6.9.

= 1.7.1 =
* Plugin Check compliance pass: explicit input sanitization on all `$_POST` reads, justified `phpcs:ignore` markers for legitimate direct DB / `meta_query` / read-only `$_GET` patterns, explicit `false` version on external Google Fonts enqueues.
* Removed deprecated `load_plugin_textdomain()` call — WordPress 4.6+ auto-loads translations from the plugin's `/languages/` folder.
* Trimmed plugin short description to fit WordPress.org's 150-character limit.

= 1.7.0 =
* Renamed all internal prefixes from 2-letter `ic_` / `IC_` to 5-letter `igcal_` / `IGCAL_` for WordPress.org compliance (uniqueness rule).
* Renamed shortcode from `[availability_calendar]` to `[igcal_availability]`.
* Accessibility: added `aria-current="date"` on today, `aria-live="polite"` on the month label and empty-state banner, `role="region"` with label on the calendar root, and full keyboard navigation inside the grid (arrows, Home, End, PageUp, PageDown).

= 1.6.3 =
* Added Settings fields to customize the calendar's header title and subtitle per language (BG / EN). Empty falls back to the translated default; the shortcode `title` attribute still takes priority.
* Removed leftover `theme` attribute card from the Shortcode reference section.

= 1.6.2 =
* Fixed: a few admin-side strings (Publication section, status labels) were not translating to English.
* Tightened spacing in the month navigation header (chevron / Today button gap).

= 1.6.0 =
* Added per-event Contact CTA customization: label per locale, background and text colors, size variants (small / medium / large). Uses CSS custom properties so customizations always win over theme overrides.

= 1.5.0 =
* Added event thumbnails / images, category tags, improved typography hierarchy in day-detail cards.

= 1.4.0 =
* Mobile responsiveness pass: two-stage breakpoints (720 px tablet, 480 px phone), compact list view on phones.

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.7.0 =
Internal rename for WordPress.org compliance. **Important:** the shortcode tag changed from `[availability_calendar]` to `[igcal_availability]`. If you used the old shortcode on any pages, update them after upgrading. Existing events and settings are preserved.
