Bevel Kit — changelog

1.0.0
- Custom Code, per-element Custom CSS and the Site Settings custom CSS / JS boxes are removed: WordPress.org does not allow a plugin to store and run code a user pastes in, and WordPress has its own Additional CSS.
- Elementor's own settings are never written: the V4 experiments are only given a different DEFAULT (a site that chose keeps its choice), nothing is written on activation, and an import asks for unfiltered uploads through Elementor's own filter for the length of the import instead of switching its setting.
- Page cache: advanced-cache.php is copied from the file that ships in src/modules/page-cache/, rather than being generated as PHP code.
- Shortcodes are [bevel-kit-year] and [bevel-kit-site-title]; the old [year] / [site-title] names convert on import, on an Elementor save, and once for pages already stored.
- Starter Sites and Import / Export: kits exported with bevel-core import. Their manifest has no `generator`, so it is recognised by its title, version, site and includes. Starter Sites brings the kit's posts across (it passed no content types before). Custom fonts, which bevel-core kits name in site-settings.json but leave on the source site, are downloaded and installed; images the pages use but the archive left out are fetched from the source site's uploads; the kit's logo becomes the site's custom_logo; `bevel_kit_settings_*` controls become `bevel_settings_*`; Remix and Iconic icons become the nearest bundled glyph (Names::LEGACY_ICONS); `[bevel-post-reading-time]` still works; a form's From address follows this site's domain. Loop widgets and any widget holding a `template_id` point at the imported template after an import rather than at the source site's id.
- Carousel (bvl-nested-carousel): a nested carousel whose slides are containers, on Elementor's nested elements and its own carousel handler, with Elementor Pro's control ids, class names and custom properties so Pro-made carousels import and keep their look. Adds a continuous-scroll mode (bevel-core's `bevel_carousel_marquee`). `nested-carousel` converts to it while Pro is absent.
- WebP Converter: WebP Convert runs its GD and Imagick converters only. Its default stack also tried system binaries (cwebp, ImageMagick, GraphicsMagick, ffmpeg) through exec() and two cloud services first.
- Default starter set: the documents pass through the same name conversion as every import, so its Remix icons render.
- Settings: the "Bevel Console Signature" (a "Built with Bevel" line in the browser console on the front end) is off by default. WordPress.org does not allow a plugin to add a credit to the public site without the owner turning it on.
- Starter set and starter-site imports: Elementor's own default colours and fonts are switched off (the two "Disable Default …" settings under Elementor → Settings) whenever the site settings are imported. With them on, Elementor painted every widget with its own palette and Roboto before the kit's Global Colours and Fonts applied, so a fresh install did not look like its site settings.
- Nav Menu: the widget's script ships as readable source (assets/js/nav-menu.js, commented) instead of the mangled nav-menu.min.js, which had no source anywhere; WordPress.org asks for human-readable code, and the file is 12 KB heavier and behaves the same.
- Editor: every widget the kit adds to the panel carries a small Bevel mark in the card's top-right corner, where Elementor puts its own lock and plug badges, in the panel's muted text colour. No box behind it, just the B, so the kit's widgets are told apart from Elementor's at a glance.
- Widgets: the Blockquote's skin, alignment and tweet-button skin and view, the Flip Box's effect and direction, the Media Carousel's skin (coverflow, slideshow), and the Table of Contents' word-wrap option did nothing on the page. Each option adds a class to the widget's wrapper, and those classes were still spelled the way Elementor Pro spells them (`elementor-blockquote--skin-…`) while the stylesheets had been renamed to the kit's spelling (`bvl-blockquote--skin-…`). The prefixes now match the stylesheets; the Gallery's filter alignment and the Search Form's skin and button-type prefixes were renamed the same way for consistency. The Media Carousel's "Arrows → Position: Outside" option had no stylesheet behind it at all; it now makes room for the arrows on either side of the slides.
- Form: the editor panel's Style tab sat last, after Advanced. Elementor orders the tabs by the first control that names each one, and the "Additional Options" section was registered on the Advanced tab ahead of every style section; it is on the Content tab now, where Pro keeps it. The widget's stylesheet no longer repeats the base form rules Elementor core already ships (field group, textual fields and sizes, labels, select wrapper, options, messages, button sizes): loaded after Site Settings' stylesheet at the same specificity, that copy took over from it, and the Theme Style → Form Fields values never reached a textarea. The select wrapper now carries Pro's `remove-before` class, so the SVG caret is the only caret.
- Theme Builder: editing a footer, single, archive, search, 404 or section template showed it inside the theme's single-post layout — under a heading with the template's name, in the theme's boxed content column, and for a footer twice, since the footer location printed its own copy below. The template is a library post, and the theme laid it out like any post. The editor preview (and "Preview changes", and the template's own address) now goes through Elementor's header-footer page template: the header and footer locations around the template in its own location, edge to edge; while a header or footer is edited a "Content area" stand-in marks where the page goes. A template's own Page Layout setting (Canvas, say) still wins.
- Stylesheets in the head, not the footer. On a page not built with Elementor — an archive, a search, a page written in the block editor — Elementor only discovered its header and footer templates while printing the footer and enqueued its frontend and kit styles there, after the page had painted; the kit's own stylesheets (elements, the popup modal, the nav menu, button animations, animated backgrounds and borders, the loop grid) waited there too, and the page shifted as each arrived. The Theme Builder now asks Elementor for its styles at the head, the way Elementor Pro's does, enqueues every template's stylesheet after them, and enables the asset record Elementor keeps for each template so the widgets inside it load their stylesheets in the head as well. The elements runtime's stylesheet and the popup modal's are enqueued with the styles, not the scripts; the site-wide button animation's in the head; and anything a template only meets while the body renders — a Loop Item's cards, a mega menu, an off-canvas panel, a button's own animation, an animated border — is printed where it is met instead of waiting for the footer.
- Editor: a "WP_Styles::add was called incorrectly … enqueued with dependencies that are not registered: elementor-frontend" notice (WordPress 6.9.1 and up) while editing an archive template. The editor renders every widget once as it loads, so an Archive Posts or Loop Grid widget rendered its Loop Item's cards, and Elementor's builder enqueued the Loop Item's stylesheet on the editor page, where `elementor-frontend` is never registered. A stylesheet Elementor's builder is about to enqueue on an admin page without that handle is now swapped for one that prints but never enqueues; the editor prints a document's CSS inline anyway.
- Nav Menu: the "primary_menu" and "mobile_menu" locations are registered on every theme, not only when the theme registers none. A theme with its own location name (Bevel's is "primary") left the widget asking WordPress about a location that did not exist — has_nav_menu() answers false for an unregistered slug — and the widget then rendered the first menu that had items instead of the one assigned. The widget also falls back to the theme's first registered location that holds a menu, and the slide-out panel inherits the desktop selection unless a mobile location has a menu of its own. Module::resolve_location() is the shared resolver; Bevel MCP assigns to the same locations.
- Custom Fonts: a font file is checked by structure as well as by signature — the table directory of an sfnt, the WOFF directory, the WOFF2 length field — so a file that merely begins with "wOF2" is refused. Library::sniff_font_ext() and Library::font_structure_ok() are public for the importers that share the check. Every change to the library runs under a lock on a fresh read of the option, so two uploads landing at once no longer lose each other's faces.
- SVG sanitizer: url() is read in every presentation attribute — fill, stroke, filter, mask, clip-path, marker-* — not only in style, and CSS is read the way a browser reads it: comments are dropped and escapes resolved before the scan, so `@\69 mport`, `@im/**/port` and `\75 rl(` no longer slip past. url(), src() and image-set() may point at a fragment or an embedded raster and nothing else; a url( the parser cannot close is refused too. tests/svg-sanitizer-test.php holds it to twenty-five cases.
- Simple Accordion: panel and trigger ids carry the widget id, so two accordions on one page (or two items with the same title) no longer share ids and aria-controls points at the right panel.
- Forms: a forwarded address (X-Forwarded-For, CF-Connecting-IP) is believed only when the connection itself comes from a trusted proxy — Cloudflare's published ranges by default, `bevel/forms/trusted_proxies` for a load balancer of your own — so a sender can no longer choose the address the blocklist and the rate limit see. One address may send ten submissions a minute (`bevel/forms/rate_limit`); the eleventh is told to wait.
- Page cache: the capture checks what the request became after the bypass rules ran — anything but a plain 200, a Set-Cookie, a Cache-Control private / no-store / no-cache, or a late DONOTCACHEPAGE is served live and never written down.
- Theme Builder: header, footer, single, single post, single page, archive, search results, 404 and section templates with display conditions, theme locations, editor preview and a dedicated admin app.
- Site widgets: Site Logo, Site Title, Page Title, Post Title, Post Excerpt, Post Content, Featured Image, Archive Title, Archive Posts.
- Dynamic Tags: site, post, archive, author, comments, media and action groups; ACF tags when ACF is active.
- Popups: popup templates with conditions, triggers and advanced rules, a Popup dynamic tag for links, editor preview inside the modal.
- Mega Menu: Nav Menu widget and Mega Menu templates (from bevel-core), Appearance → Menus integration.
- Site widgets: Search Form, Author Box, Post Comments, Post Navigation, Post Info, Sitemap, Breadcrumbs.
- Editor: Display Conditions in the Publish menu.
- Element options (Advanced tab of every element): Sticky with Pro's controls plus hide on scroll down and a scrolled state (padding, background, shadow, transition); Motion Effects (scrolling: vertical, horizontal, transparency, blur, rotate, scale; mouse: track, 3D tilt; element and background variants); Custom CSS per device on elements, pages and Site Settings; Custom Attributes; Wrapper Link (from bevel-core); element Display Conditions with the site tree and visitor rules (logged in/out and roles, schedule, device, arriving from, URL parameter), evaluated on the server per request.
- Custom Fonts: upload families and faces (WOFF2/WOFF/TTF/OTF, weight and style read from file names), served as @font-face from uploads/bevel/fonts; "Custom Fonts" group in every typography control; live preview in the editor.
- Custom Icons: IcoMoon and Fontello zips imported into uploads/bevel/icons, offered as icon-picker tabs, drawn as inline SVG on the front end.
- Page Transitions (Site Settings → Page Transitions, replacing the free editor's teaser): background, entrance and exit animations (fade / zoom / slide in every direction), duration, preloader (13 built-in animations, icon or image, with colour, size, rotation, width, opacity, delay), the Preview button and live rendering in the editor canvas; <e-page-transition> / <e-preloader> elements, classes and CSS variables as Elementor Pro's; prefetch of hovered links; respects prefers-reduced-motion.
- Admin: one shell (admin-core.js) for every Bevel Kit screen, each rail linking Site Settings, Theme Builder, Custom Fonts and Custom Icons.
- Site Settings (Bevel → Site Settings, ported from bevel-core): every control of the active kit rendered natively (colours with global refs, typography popovers, sliders and dimensions per device, backgrounds, borders, shadows, filters, icons, media, the global colour / font repeaters), live previews for typography, buttons, images, form fields, colours and fonts, search, undo / redo, saved straight into the kit; a Settings tab with the plugin's site options (disable comments, disable XML-RPC, site icon on the login screen, console signature, Google Fonts load and local cache clearing, block styles, optimized image loading, inline font icons, optimized markup, jQuery Migrate, post revisions cap). The plugin's own settings are bevel_* options and go on uninstall; the handful of Elementor settings this screen exposes (Google Fonts loading and local cache, block styles, optimized image loading, SVG uploads, the active kit) are Elementor's own elementor_* options and are deliberately left alone — removing them would reset Elementor's configuration on a site that still runs it.
- Admin menu: a top-level "Bevel" menu with Site Settings, Theme Builder, Custom Fonts and Custom Icons; the Theme Builder lives at admin.php?page=bevel-theme-builder.
- Bevel top bar (brand, version, Site Settings, Theme Builder, Custom Elements dropdown, a sliding pill, a drop panel on narrow screens) on every Bevel screen and on Elementor's templates list, where Elementor's own admin chrome is detached; admin notices are dropped on these screens; the rails head with the screen's name instead of the brand and pin below the bar.
- Kit Settings (ported from bevel-core, control prefix bevel_settings_ kept so kits move over): a "General" tab in Site Settings right after Site Identity with Smooth Scrolling (Lenis), Auto Animation (staggered per document order, initial delay, step, entrance animation, noscript reveal), Animation Style (Creative, Snappy, Soft, Laser, Elastic, Linear, Magic, SCI-FI keyframe sets), Back to Top (position, mobile, icon, normal/hover colours, radius, padding, size) and Icon Libraries switches; extra sections in Elementor's tabs: Boxed Layout (Layout; wraps the theme locations in body > .site-container), Button Animation (Buttons; flip text, bubble background, switch icon, background grow, float 2/3/5/10px, applied to every Button widget through the render filter with the hover colour as a CSS variable), Blog Typography (Typography; H1–H6 and P of post content), Custom JS / Custom Content in Header / Footer (Custom CSS; printed on the site only, never in the editor; saving raw code needs unfiltered_html or a single-site administrator).
- Elementor's V4 experiments are switched off. Elementor 4 ships atomic widgets, global classes, variables, components and the V4 editor turned on by default and marked hidden, so they do not appear under Elementor > Experiments and a site owner cannot turn them off; most are still alpha or dev by Elementor's own release status. Every Bevel widget, every control this plugin adds to Elementor's own widgets, and every starter template is built against the V3 element model. The defaults go back to inactive on each load, which leaves a deliberate elementor_experiment-* option alone; activating the plugin and running the Starter Templates tool write them off outright, and an admin page load writes off anything still active despite the default - the case a default cannot reach, because something else holds an option for it. Any of those says so once in an admin notice. Nothing is converted and nothing is deleted, though anything already built with V4's own features renders differently while they are off, because those features are what render it. The bevel/elementor/pin_to_v3 filter leaves Elementor entirely alone, and deletes any experiment option this plugin had written, so turning the pin off really does give V4 back. Deleting the plugin does the same.
- Bevel Kit now runs alongside Elementor Pro instead of standing down. Every widget carries a `bvl-` key and, where Elementor Pro styles the same class name, a `bvl-` class name, so the two plugins never claim the same thing. The parts that genuinely belong to Pro — the Theme Builder, dynamic tags, popups and the element options — stay asleep while Pro is active, and Pro provides them under the names it always used. A page built with Elementor Pro still opens on a site without Pro: each of the nine widgets also answers to Pro's old name while Pro is absent, hidden from the panel, so the page renders with its settings intact.
- Pro-parity widgets, keeping Pro's section ids and control ids so a page built with Elementor Pro keeps its settings; they sit in the "Bevel" panel category:
  - Form: the fields repeater (text, email, textarea, URL, tel, radio, select, checkbox, acceptance, number, date, time, file upload, password, HTML, hidden, step), per-field width and CSS classes, labels above or inline, required marks, multi-step with number / icon / progress-bar indicators, and the whole style set. Submitting goes through admin-ajax with a nonce and a honeypot; the form's settings are read from the page it lives on, never from the request, and a field the form does not declare is dropped. Actions after submit: Email, Email 2, Redirect, Webhook and Collect Submissions. Uploads are checked by extension and by content, and a file sent only as an attachment is removed from the server afterwards.
  - Submissions: two tables of the plugin's own, a screen at Bevel → Submissions (inbox / unread / trash, a filter per form, a search across the answers, per-row read, unread and trash, and a CSV export of the current view), and a clean uninstall that drops both tables.
  - Search: three skins (input, input with button, full-screen overlay) with live results over admin-ajax — the request carries a signed payload, so a caller cannot widen the query — plus full keyboard support and a combobox's ARIA wiring.
  - Gallery: single or multiple galleries, grid / justified / masonry layouts with their own layout engine, a filter bar with six pointer styles, overlay content and Elementor's own lightbox.
  - Media Carousel: slideshow / carousel / coverflow skins on Elementor's bundled Swiper, with a thumbnail row, captions, arrows and dots.
  - Flip Box, Blockquote, Hotspot, Table of Contents (built on the client from the page's own headings) and Off-Canvas (the panel moves to the end of the body so no ancestor can clip it, with focus trapping and Escape to close).
- Bevel widgets: Counter (count-up on scroll, plain and motion styles), Testimonial Grid and Post Grid (its own query, featured-first and list layouts, numbered pagination or load-more over a signed admin-ajax request).
- Bevel widgets (ported from bevel-core, names unchanged so templates carry over: bevel-advanced-tabs, bevel-accordion, bevel-image-accordion, bevel-infobox, bevel-highlight-heading, bevel-animated-word-roller, bevel-marquee, bevel-image-marquee, bevel-image-compare, bevel-stacked-slider, bevel-timeline, bevel-circle-progress-bar) under a "Bevel" panel category, no licence gate; their stylesheets and scripts registered under the handles the widgets declare (Swiper comes from Elementor); the Nav Menu stays in the Mega Menu module.
- Custom controls (ported from bevel-core's Custom_Controls; Nested Accordion, Form and Nested Carousel extensions left out): Button icon styling + nine extra hover animations in every Hover Animation control; Icon List link hover underline (sequential per-line script) and icon styling; Heading span styles (gradient text) and Scroll Reveal Fill; Icon Box custom image (control + render filter; Icon Box and Button render on the server in the editor so the filters apply there too); Image Box and Text Editor link extras; Video "YouTube Optimized Embed" (thumbnail + play button, popup player, local thumbnail cache via WP-Cron); Container Sticky Header (smart hide, disable on mobile, sticky-state background/border/shadow, blur), Animated Background (25 animations with per-animation colours/intensity/speed and OGL-based shaders, scripts loaded only where used), Blur Background, Animated Border; editor panel tweak: a responsive control's title opens its device variants in place.
- Icon libraries (ported from bevel-core): Bevel Icons, Themify, Remix, Lucide, Iconic, Feather and Hero ship under assets/icons; each enabled library is a tab of the icon picker (glyph fonts only load in the editor and on the Bevel screens) and its icons render as inline SVG from the library's path map with a per-icon file cache under uploads/bevel/icon-cache; the Custom Icons screen gained an "Icon libraries" view with a picker switch and a browser per library.
- Forms, round B. Captcha as three field types — reCAPTCHA, reCAPTCHA v3 and hCaptcha — drawn by the provider's own script and checked against the provider before a submission counts; a provider with no keys renders nothing and stops nobody, so the site's own configuration never turns a visitor away. reCAPTCHA v3 is scored against a threshold you set. New Site Settings tab "Forms" holding the keys every form shares, and spam rules that run before any action: a blocklist of words, addresses and IP ranges, a minimum time to fill the form (signed, so the stamp cannot be back-dated), and a switch that keeps what was turned away under Submissions -> Spam. New actions after submit: Mailchimp (on a List_Service_Base, so the next list service is a subclass with one subscribe() method; a wrong audience id is answered with the audiences that do exist), Slack and Discord (on a Notification_Base — a webhook with a payload in that service's own shape, host-checked before anything is sent, and a Discord payload that never mentions anyone). Submissions gained a Spam view, a date range on the filter bar, "Mark as spam" / "Not spam", and "Resend notification", which rebuilds the stored submission and runs the form's email actions on it again.
- Site Settings option fields are filterable (bevel/site_settings/option_fields), and text, password, number and textarea fields render and save alongside the switches and selects that were already there, so a module that adds a panel tab saves through the same topbar button as everything else.
- Tools tab in Site Settings, ported from bevel-core, with no licence gate:
  - Optimization: the One-Click run, the delay-JavaScript engine (with its exclusion stack for GDPR banners and anything you name) and LCP image preloading; stands down when another delay engine is on the site.
  - WebP Converter: convert-on-upload and a batched run over the media library, quality per format, exclusions, and front-end serving that swaps images, srcset and Elementor's generated backgrounds; the rosell-dk/webp-convert library is vendored under vendor/webp and loaded only when a conversion runs.
  - Database Optimizer: what every table holds and its overhead, then post revisions, auto-drafts, trashed posts, spam and trashed comments, orphaned post and term metadata and expired transients removed in chunks, with a confirmation that names what will go and a report of what did, followed by OPTIMIZE TABLE.
  - Import / Export: package site settings, templates, pages, menus, custom fonts, custom icons and content as a ZIP and import it into another site running the kit. Installing plugins from a kit is deliberately not part of it.
- The autoloader maps an underscored namespace segment to a dashed directory (Import_Export_Parts -> import-export-parts), the same rule it already used for class names.
- Uninstall now removes the plugin's options, transients and post meta by prefix rather than by name, so a tool that adds a setting cleans up on its own.
- Every speed setting now sits on one screen. The performance options (Google Fonts load and local cache, block styles, optimized image loading, inline font icons, optimized markup, jQuery Migrate) moved off the Settings tab and onto Tools -> Optimization, between the One-Click run and the JavaScript Delay panel, the way Bevel Core arranges them. The Settings tab keeps General, Security and Post Revisions.
- Database Optimizer: the table breakdown is no longer squeezed into a 340px scroller with a sticky totals row over it, which left one table permanently half-hidden. It lists every table in full and scrolls sideways only when a narrow screen needs it, and the "Cap new revisions" link is underlined so it reads as a link rather than a stray bold phrase.
- The captcha and spam settings moved from a tab of their own to a Forms sub-tab of Settings, beside General, since they are settings for the site rather than a tool that does something to it. Site Settings sub-tabs are filterable for that (bevel/site_settings/settings_sections).
- An API secret is now a text field whose characters are covered rather than a password field, and it uncovers itself while it is being edited. A password field made the browser offer a saved login on the Site Settings screen, filling the sidebar search with a username and the secret with a stored password. A textarea on that screen is also as tall as its rows say instead of the 35px every other control is.
- Database Optimizer: the four figures above the table sit in a card of their own, so they read as a summary of the list below rather than as loose text.
- Six more modules taken from Bevel Core, each with no licence gate:
  - SVG uploads (Settings -> Security, off by default): the mime type is offered only to users who may upload unfiltered files, and every path an SVG can take into the library -- a browser upload, a sideload, a kit import, a REST insert -- goes through the plugin's one sanitizer first, which strips scripts, event handlers, javascript: URLs and remote references. Attachment metadata makes an SVG report real dimensions, so the media modal and Elementor's widgets stop complaining. The gzipped .svgz form is deliberately not offered, since its bytes cannot be read and so could never be made safe.
  - Meta Description: one post-meta key, a box in the WordPress editor with a character counter and a field in Elementor's Page Settings under Excerpt, on every public post type with an editor. It prints into <head> only when nothing else already did, and the whole module stands down when a known SEO plugin is active.
  - Light Logo: a second logo in Site Identity for dark backgrounds, and a Logo selector on the Site Logo widget that picks it. Hooked by widget name, so it keeps working when Elementor Pro is the one registering that widget.
  - Tooltip: a Tooltip section on the Advanced tab of every widget, container, section and column -- content, placement, follow cursor, animation, trigger, show and hide delays, offsets, arrow, and a full style set -- on Tippy.js, loaded only on a page that has one. The description is sanitised through a DOM parse rather than Bevel Core's regex, which turned every closing tag into an opening one.
  - Post Duplicator (Settings -> General): a Duplicate row action copying content, meta, terms and Elementor data into a draft. Tightened well past the source: the post type must be registered and UI-visible, the exclusion list is enforced on the ajax path and not only on the row, and the user must pass edit_posts, edit_post and create_posts for the destination type. An unreachable GET endpoint that duplicated a post was removed rather than ported.
  - Polylang (Settings -> General, only offered when Polylang is active): a theme-builder location serves the current language's translation of its template. An unpublished translation is left alone rather than emptying the location.
- Form input masks on any text or tel field, from the field's Advanced tab: International Telephone (flag dropdown, dial codes, live formatting, preferred/only/excluded countries), phone formats, date and time, money, credit card and IP address. The mask is checked on the server as well as in the browser -- Bevel Core trusted a hidden field carrying the browser's verdict, which is forgeable and useless with JavaScript off -- against dial codes and national-number lengths taken from the bundled library itself. Auto Detect Country answers only from what the network in front of the site already put on the request; Bevel Core's outbound geo lookup was deliberately not ported.
- Form notifications sent as HTML now go out in a layout carrying the site's logo, the form's name, the answers as a table and the page they came from. It is a per-email switch, and the message you wrote survives: [all-fields] expands inside your text rather than replacing it. The visitor's address and browser are deliberately left out of the email; they belong to the stored submission.
- The Form gained the style controls it was missing: field padding, button top spacing, and messages as boxes (background, border, radius and padding, with the border colour set per message kind). Nothing has a default, so a form built before this looks exactly as it did.
- The SVG sanitizer moved from the importer to src/core, because it is now the whole plugin's one SVG policy rather than the importer's.
- Page Cache (Site Settings → Tools → Optimization): a disk-based full-page cache that serves stored HTML from wp-content/cache/bevel-page/ through an advanced-cache.php drop-in, before WordPress loads. Logged-in visitors, WooCommerce cart and checkout, POST requests, searches, feeds and meaningful query strings always bypass it; content, menu, theme, plugin, option and Elementor saves purge what they invalidate and re-cache it in the background. A GZIP switch beside it writes mod_deflate rules to .htaccess and stores pre-compressed .gz twins. An admin-bar menu shows the live page count and size, and preloads, purges or turns the cache off. It never overwrites another plugin's drop-in or WP_CACHE line, and refuses to switch on while another cache plugin is active.
- Font preloading (Site Settings -> Tools -> Optimization): a Preload Fonts list offering the site's own Custom Fonts and the Google families Elementor has downloaded, and a <link rel="preload"> in the head for each one picked. One file per face, best format first, because preloading a face's fallbacks beside it downloads bytes nothing will use. A family still served from Google's CDN is not offered: a preload there only duplicates the request the stylesheet makes.
- WooCommerce: Product and Product Archive templates in a new Shop group of the Theme Builder, and fifteen widgets to build them from -- product title, images, price, add to cart, rating, stock, meta, short description, description, tabs, breadcrumb, notices, related, upsells, and a Products grid for the shop. Display conditions came for free: the existing Singular and Archive conditions already generate every product, category and tag rule. Where a template of yours claims a product or shop page the Theme Builder takes the page over, so WooCommerce's own single-product template no longer decides the layout; everything else on the shop -- the cart, the checkout, the account pages -- is still WooCommerce's. The whole module is invisible without WooCommerce, and stands down under Elementor Pro's own WooCommerce Builder.
- Starter Sites: the free templates import with no account at all. Only the Pro library asks for a plan.
- Theme Builder: Edit opens the editor in a new tab, so the template list stays where it was, and the New template dialog carries the Bevel mark instead of a plus.
- The admin rail matches Site Settings: one type scale throughout, and the sliding pill that follows the pointer.
- Fixed: the Starter Templates tool's "replace what is there?" dialog never became visible, so its Install button appeared to do nothing while an invisible overlay swallowed the click.
- Fixed: the Starter Sites dialogs fell back to the WordPress admin typeface, because they are rendered outside the screen's own wrapper.
- WooCommerce, part two: the shop looks like the rest of the site even where you have not built a template for it. The stylesheet that dresses WooCommerce's own pages, the markup wrappers it is written against, the star rating above the product name in the shop loop, the breadcrumb inside the product summary, and your button style carried through to WooCommerce's buttons on the cart and checkout, which are not Elementor buttons and would otherwise keep WooCommerce's look. None of it applies to a page one of your templates draws -- there the template is the layout. A shop that has chosen its own catalogue size keeps it; a new one gets 12 products, 4 across.
- WooCommerce, part three: the shop's other pages. A product category grid, a header cart with its count and total, and Cart, Checkout, My Account and Order Summary widgets. The four page widgets wrap WooCommerce's own shortcodes and style what they print rather than rebuilding them -- payment, tax and legal behaviour belongs in WooCommerce's templates, and a hand-written checkout is where a page builder's WooCommerce support goes wrong. In the editor, where there is no customer and no cart, each one draws a description of what the page will show instead of a checkout that looks live and is not.
- The theme's content column follows Site Settings. The kit publishes the container width as --bevel-content as well as its own --bvl-container-width, so a theme that sizes its templates from that property matches the width every Elementor container on the site already uses, instead of a reading width it picked without knowing.
- Post Info gained a Reading time row: an estimate from the post's own words, with the words-per-minute rate and the wording under your control, and the same icon, prefix and styling every other row has. Shortcodes are expanded before counting, so a post that is mostly a gallery does not read as a ten-second one.
- Fixed: Scroll Reveal Fill drew nothing. The heading control and the scroll scrubber were both there, but the rules that paint the fill were not, so switching it on changed the markup and nothing else. Headings that ask for it now fill as you scroll, and hold at full colour where a visitor has asked for reduced motion.
- Geist and Geist Mono are offered in every typography control again, beside the rest of the Google library.
- Fixed: a form's Field Text Color leaked into the operating system's own dropdown list, which could leave a select's options unreadable -- white on white on some systems. The list keeps system colours; the closed select still takes your colour.
- The editor's template catalog address is filterable (bevel/templates/api_url), for a site pointing the library at a staging feed.
- Starter Templates (Site Settings -> Tools) installs what you tick and nothing else. Site settings, a home page, header, footer, single post, single page, archive, 404 and the main menu are nine separate choices, with a select-all and a running count; the confirmation names the templates already on the site that the ticked set would draft, and the result says what went in item by item. Untick the site settings and the templates keep the palette the site already has, which the panel says out loud, because the templates are drawn against the starter colours. Your last choice is offered again next time, so coming back for one more piece is a two-click job. On a WordPress nobody has built anything on yet -- no theme templates, nothing made in Elementor, no more pages or posts than a new install ships with -- the whole set goes in by itself the first time you open the admin, so the site looks like something from the first minute. Anything else is left alone, as is a site running Elementor Pro, which has a Theme Builder of its own; the `bevel/starter/auto_run` filter turns it off entirely.
- Security: publishing a Theme Builder template now takes the right to publish, not just the right to edit. A published template decides the header, footer or archive every visitor sees, and WordPress does not check publishing for you on a custom post type, so a contributor who could edit their own draft could put it live across the whole site. Their request is now held for review instead, the way Elementor answers the same attempt on a page, and restoring a template from the trash cannot hand back a status they could not have set.
- Security: the page cache no longer stores a page rendered for someone who has commented before. It already refused to serve a cached page to that visitor, but not to store theirs, and because a returning commenter always misses the cache it was their copy that filled it, carrying the name and email WordPress puts back into the comment form. The two halves now read from one list, so they cannot drift apart again.
- Every service the plugin can contact is now named in the readme, with what it receives and when. Five were missing: the build service that checks a page an AI assistant composed, which receives that page; the openly-licensed photo library it searches, and the sites those photos are hosted on; the font previews on the Site Settings screen; and YouTube's player itself when a visitor presses play. The account server's entry now also covers counting what an assistant builds.
- Fixed: a Theme Builder template an assistant created did not take effect until something else was edited. The display conditions were written before the template's own type was recorded, so the cache that decides which template claims a page could not see it, and the only other rebuild happened when a competing header or footer had to be deactivated. On a site with nothing to deactivate the template was published, reported as applied, and rendered nowhere. Each later template quietly fixed the previous one.
- The two test probes that borrow the site's account while they run now put it back even if they fail part way, instead of only at the end.
- Form labels sit 10px above their field again, the gap Bevel Core gave them. The kit styled a label's colour and type but never its spacing, and there is no control for it, so labels sat flush against the input.
- The first and last paragraph of any builder content no longer add an outer margin. Without it a text editor's opening paragraph pushed itself down inside a card and the closing one pushed the card open, so cards sat on uneven padding that no control accounted for.
- Fixed: the Nav Menu's Toggle Style control showed five identical boxes. It offers five hamburger shapes, but nothing drew them, so every option fell back to the same generic image icon and there was no way to tell them apart.
- Fixed: a header or footer an assistant created sometimes rendered nowhere. The list of templates is looked up by type, and a template saved moments earlier in the same request was missing from a cached copy of that list, so the location cache was rebuilt without it. The rebuild now reads a fresh list.
