=== NEOVANTAGE ===
Contributors: pixelspress, mohsinrafique
Tags: one-column, two-columns, right-sidebar, left-sidebar, custom-background, custom-colors, custom-header, custom-logo, custom-menu, editor-style, featured-images, footer-widgets, post-formats, rtl-language-support, theme-options, threaded-comments, translation-ready, blog, e-commerce

Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 8.0
Stable tag: 2.4.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A clean, modern WordPress blog and WooCommerce theme with multiple layouts, live Customizer controls, post formats, and full Gutenberg support. Fast to set up, easy to make your own.

== Description ==

NEOVANTAGE is a clean, modern, and highly customizable WordPress theme built for bloggers and store owners who want a professional-looking site without touching a line of code. It works equally well as a content-first blog and as a fully styled WooCommerce storefront, so you can publish, sell, or do both from a single theme.

Whether you write about lifestyle, travel, technology, food, and fashion, or you sell physical products, digital downloads, and services -- NEOVANTAGE gives you the design flexibility to make your blog and online store uniquely yours. Every shopper-facing WooCommerce page (shop, single product, cart, checkout, and the My Account dashboard) is styled out of the box, and every setting is controlled from the live WordPress Customizer, so you see your changes in real time before publishing them.

= Why Bloggers and Store Owners Love NEOVANTAGE =

**Multiple Layout Options**
Choose from one-column full-width, right sidebar, or left sidebar layouts -- and switch between them per page or post.

**Live Customizer Controls**
Adjust your site colors, typography, header style, background, and layout directly from the WordPress Customizer with instant live preview. No page builder needed.

**Post Format Support**
Present your content in the format it deserves. NEOVANTAGE supports Standard, Gallery, Image, Video, Audio, Quote, and Link post formats -- each with a distinct, well-designed layout.

**Custom Logo & Custom Header**
Upload your logo and a custom header image from the WordPress Customizer. Your branding, your way.

**4-Column Footer Widget Area**
Fill your footer with widgets -- about text, recent posts, social links, custom HTML -- across four independent columns.

**Cookie Consent Notification Bar**
A built-in, GDPR-aware cookie consent bar with fully customizable text, link, and expiry settings. No extra plugin needed.

**Breadcrumb Navigation**
Automatically generated breadcrumbs help visitors understand where they are on your site and improve your SEO structure.

**Related Posts**
Keep readers on your site longer with an automatically generated related posts section at the bottom of every post.

**Open Graph Meta Tags**
Built-in Open Graph support ensures your posts look great when shared on Facebook, Twitter, LinkedIn, and other social platforms.

**Preloader Option**
A smooth, lightweight page preloader gives your site a polished, professional feel on first load.

**RTL Language Support**
Full right-to-left language support for Arabic, Hebrew, Persian, and other RTL languages.

**Translation Ready**
Every string in the theme is wrapped in proper translation functions. Translate NEOVANTAGE into any language using any .po/.mo editor.

**WooCommerce Ready**
Turn your blog into a fully-fledged online store. NEOVANTAGE is fully compatible with WooCommerce -- the world's most popular eCommerce platform, powering millions of shops across the US, UK, and beyond. Every shopper-facing page is beautifully styled straight out of the box: the shop and single-product pages, cart, checkout, order confirmation, and the complete My Account dashboard. A header cart icon with a live item count and a smooth slide-in mini-cart drawer let customers keep shopping without losing their place. Whether you sell physical products, digital downloads, or services, your store inherits the theme's colours, typography, and buttons automatically -- no page builder and no extra configuration required.

**Block Editor Ready**
NEOVANTAGE is a classic theme that fully supports the WordPress block editor (Gutenberg). All core blocks -- paragraphs, images, galleries, embeds, buttons -- render correctly with consistent styling. Wide and full-width block alignment is supported.

**Clean, Optimized Code**
Built on the solid Underscores (_s) starter theme foundation. PHP 8.4 compatible. WordPress 7.0 tested. Follows WordPress coding standards throughout.

= Quick Setup =

1. Install and activate the theme
2. Go to **Appearance -> Customize** and configure your logo, colors, and layout
3. Install the recommended NEOVANTAGE Core plugin for post view counts, widgets, and demo content
4. Start writing your first post

= Recommended Plugins =

* **NEOVANTAGE Core** -- Post view counts, enhanced recent posts widget, author contact fields, demo importer, and customizer export/import
* **WooCommerce** -- Build a fully styled online store; NEOVANTAGE styles every WooCommerce page out of the box
* **NEO Bootstrap Carousel** -- Add a beautiful image slider to your homepage
* **Contact Form 7** -- Simple, flexible contact forms
* **Smash Balloon Instagram Feed** -- Display your Instagram feed anywhere on your site
* **AMP WP** -- Serve fast, lightweight AMP versions of your pages for mobile readers

= Documentation & Support =

Full documentation is available at [pixelspress.com/article-categories/neovantage/](https://pixelspress.com/article-categories/neovantage/)

== License ==

NEOVANTAGE WordPress Theme, Copyright (C) 2016-2026 PixelsPress.
NEOVANTAGE is distributed under the terms of the GNU GPL v2 or later.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

NEOVANTAGE is based on Underscores https://underscores.me/, (C) 2012-2016 Automattic, Inc.
Underscores is distributed under the terms of the GNU GPL v2 or later.

== Credits ==

1. Underscores - https://underscores.me/
License: GNU General Public License v2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
Copyright: 2012-2016 Automattic, Inc., https://automattic.com/

2. normalize.css - https://necolas.github.io/normalize.css/
License: MIT License (https://opensource.org/licenses/MIT)
Copyright: 2012-2016 Nicolas Gallagher and Jonathan Neal

3. Bootstrap v3.3.7 - https://getbootstrap.com
License: MIT License (https://github.com/twbs/bootstrap/blob/master/LICENSE)
Copyright: 2011-2016 Twitter, Inc.

4. Lato Webfont - https://fonts.google.com/specimen/Lato
License: SIL Open Font License v1.1 (https://scripts.sil.org/OFL)
Copyright: Łukasz Dziedzic

5. Montserrat Webfont - https://fonts.google.com/specimen/Montserrat
License: SIL Open Font License v1.1 (https://scripts.sil.org/OFL)
Copyright: Julieta Ulanovsky

6. Open Sans Webfont - https://fonts.google.com/specimen/Open+Sans
License: SIL Open Font License v1.1 (https://scripts.sil.org/OFL)
Copyright: Steve Matteson

7. Noto Serif Webfont - https://fonts.google.com/specimen/Noto+Serif
License: SIL Open Font License v1.1 (https://scripts.sil.org/OFL)
Copyright: Google LLC

8. Lynny Icons - https://dribbble.com/shots/1925069-Lynny-Icon-Set-Free
License: Free for personal and commercial use with attribution (https://www.stockio.com/free-icons/lynny-icons-outline)
Copyright: 2015 Matthew Skiles

9. NEO Bootstrap Carousel - https://wordpress.org/plugins/neo-bootstrap-carousel/
License: GNU General Public License v3 or later (https://www.gnu.org/licenses/gpl-3.0.en.html)
Copyright: 2017 PixelsPress, https://pixelspress.com

10. Contact Form 7 - https://wordpress.org/plugins/contact-form-7/
License: GNU General Public License v2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
Copyright: Takayuki Miyoshi, https://ideasilo.wordpress.com/

11. Instagram Feed - https://wordpress.org/plugins/instagram-feed/
License: GNU General Public License v2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
Copyright: 2017 Smash Balloon, https://smashballoon.com/

12. TGM Plugin Activation - https://tgmpluginactivation.com/
License: GNU General Public License v2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
Copyright: 2011 Thomas Griffin, Gary Jones, Juliette Reinders Folmer

13. Demo images are sourced from Pexels (https://www.pexels.com) under the Pexels License (https://www.pexels.com/license/), which permits free personal and commercial use without attribution.

Image 1: https://www.pexels.com/photo/yellow-van-die-cast-386025/
Copyright: Nubia Navarro (https://www.pexels.com/@nubikini)

Image 2: https://www.pexels.com/photo/people-playing-cards-7330159/
Copyright: MART PRODUCTION (https://www.pexels.com/@mart-production)

Image 3: https://www.pexels.com/photo/person-playing-music-with-a-vinyl-record-6621701/
Copyright: KoolShooters (https://www.pexels.com/@kool-shooters)

Image 4: https://www.pexels.com/photo/white-book-on-brown-round-table-2387754/
Copyright: Adrienne Andersen (https://www.pexels.com/@adrienne-andersen-1174503)

Image 5: https://www.pexels.com/photo/scenic-view-of-snow-capped-mountains-during-night-3408744/
Copyright: stein egil liland (https://www.pexels.com/@therato)

Image 6: https://www.pexels.com/photo/monochrome-photo-of-bare-tree-3110355/
Copyright: Brett Sayles (https://www.pexels.com/@brett-sayles)

Image 7: https://www.pexels.com/photo/blue-lined-flat-surface-132204/
Copyright: FWStudio (https://www.pexels.com/@fwstudio-33348)

Image 8: https://www.pexels.com/photo/adult-art-awakening-black-and-white-220210/
Copyright: Pexels (photographer not listed)

Image 9: https://www.pexels.com/photo/person-in-blue-denim-jeans-lying-on-brown-wooden-table-4505458/
Copyright: cottonbro studio (https://www.pexels.com/@cottonbro)

Image 10: https://www.pexels.com/photo/set-of-multicolored-raw-eggs-on-wooden-table-4207654/
Copyright: Karolina Grabowska (https://www.pexels.com/@karolina-grabowska)

Image 11: https://www.pexels.com/photo/hispanic-woman-wrapping-parcel-at-home-6348048/
Copyright: Liza Summer (https://www.pexels.com/@liza-summer)

== Installation ==

1. In your admin panel, go to **Appearance -> Themes** and click **Add New**.
2. Search for "NEOVANTAGE" and click **Install**, then **Activate** -- or upload the zip file manually.
3. Go to **Appearance -> Customize** to set your logo, colors, layout, and typography.
4. Install the recommended **NEOVANTAGE Core** plugin when prompted for post views, demo content, and enhanced widgets.
5. Create your first post and start blogging.

Full setup guide: [pixelspress.com/article-categories/neovantage/](https://pixelspress.com/article-categories/neovantage/)

== Frequently Asked Questions ==

= Is NEOVANTAGE free? =

Yes, NEOVANTAGE is completely free and open source under the GNU General Public License v2 or later.

= Do I need to know how to code? =

No. Every layout, color, font, and content option is controlled from the WordPress Customizer with live preview. No coding required.

= Does NEOVANTAGE work with the Gutenberg block editor? =

Yes. NEOVANTAGE is a classic theme with full block editor support. All core blocks render correctly. Wide and full-width alignment is supported. It does not use Full Site Editing (FSE) or block templates.

= Is NEOVANTAGE compatible with WooCommerce? =

Yes. NEOVANTAGE is fully compatible with WooCommerce. Once you install and activate the free WooCommerce plugin, every storefront page -- shop, single product, cart, checkout, order confirmation, and the My Account dashboard -- is styled to match the theme automatically. It also adds a header cart icon with a live item count and a slide-in mini-cart drawer. The WooCommerce stylesheet loads only on store pages, so blog-only sites are not affected.

= Which plugins does NEOVANTAGE recommend? =

NEOVANTAGE recommends the NEOVANTAGE Core companion plugin for additional features (post views, demo content, customizer import/export). It also recommends NEO Bootstrap Carousel, Contact Form 7, Smash Balloon Instagram Feed, and AMP WP -- all available free on WordPress.org.

= Is NEOVANTAGE compatible with PHP 8.x? =

Yes. NEOVANTAGE has been tested and confirmed compatible with PHP 8.0, 8.1, 8.2, 8.3, and 8.4. No deprecated functions are used.

= Can I use NEOVANTAGE with a child theme? =

Yes. NEOVANTAGE fully supports child themes. Create a child theme to make customizations that survive future theme updates.

= Is NEOVANTAGE translation ready? =

Yes. All theme strings are wrapped in proper translation functions using the `neovantage` text domain. You can translate the theme using Loco Translate or any .po/.mo editor.

= Does NEOVANTAGE support RTL languages? =

Yes. NEOVANTAGE includes a dedicated rtl.css stylesheet for full right-to-left language support.

= Where can I get help? =

Post in the [WordPress.org support forum](https://wordpress.org/support/theme/neovantage/) or visit [pixelspress.com/article-categories/neovantage/](https://pixelspress.com/article-categories/neovantage/).

== Changelog ==

= 2.4.0 - 24 June, 2026 =
* Feature: Premium Gutenberg block styling suite. A pass over the core block library brings the front end and block editor up to the theme's premium design language -- a rounded "code window" Code block with a copy-to-clipboard button and horizontal scroll, a card-style Table with a shaded header, row hover and footer row, a rounded Calendar card with a brand "today" cell and post-day links, Group cards and a brand-tinted gradient Separator, an elegant Quote with a brand watermark, a light-panel Preformatted treatment and an italic prose Verse, brand-tinted List markers, a clean rounded Search field with a brand button, and a premium Latest Posts post-card grid (featured image, date glyph, Read More) that handles every image alignment and the author byline. Each is mirrored into the editor canvas so the preview matches the front end.
* Feature: WooCommerce blocks styled out of the box. The standalone WooCommerce blocks now match the classic shop card -- Product Collection (including the carousel layout with brand prev/next navigation), Product Categories (image-card grid and dropdown display styles), Featured Product / Featured Category banners, the legacy product grids (Best Selling, Newest, On Sale, Top Rated, Hand-picked, Products by Category), Product Search, and the Customer Account block. Mirrored into the editor canvas where applicable.
* Feature: In the Shop "Show categories & products" display mode, product categories now render in their own grid above the products (under a "Shop by Category" heading) instead of being mixed into the product grid, so a category no longer reads as an incomplete product. The category cards get a distinct treatment (brand-tinted card, a "collection" glyph, a count pill, and a browse chevron), built entirely with hooks calling WooCommerce's own category output -- no template overrides.
* Feature: The sidebar widget-title accent and the page-header title accent now inherit the Customizer Background Color.
* Fix: Editor / front-end parity sweep. Brought numerous blocks into visual agreement between the editor canvas and the front end -- Social Links (round chips instead of stretched capsules, with no square-on-hover artefact), Calendar cell alignment, the Latest Posts grid, the File block download button, block headings, Cover heading readability, Pullquote, the Quote watermark, Verse, Preformatted, and the restored blockGap between Group children.
* Fix: Theme stylesheets and scripts now cache-bust on edit -- the asset ?ver= derives from the file modification time, so CSS/JS changes are picked up without a hard refresh in the browser or the block editor.
* Fix: Gutenberg blocks now follow the Customizer theme colour and fonts -- block accents, link and hover states, headings, and button typography read the brand-colour and font tokens instead of hardcoded defaults.
* Fix: WooCommerce theming corrections. Store headings and content follow the Customizer font selections; hover and focus states follow the brand colour instead of reverting to the default cyan; the variable-product variation form stacks correctly; disabled buttons no longer flash WooCommerce purple; the store stylesheet also loads on pages that embed products via a shortcode or block; product-grid gutters and the Customer Account "Login" label were corrected; and the On Sale block buttons render as a full-bleed bar.
* Fix: Removed the horizontal page scroll caused by full-bleed .alignfull / .alignwide blocks (the 100vw scrollbar overshoot is now clipped with overflow-x: clip).
* Fix: Archive and search post layouts (Classic vs List view) now apply correctly, and the "Undefined variable $layout" notice on the search results page is gone -- the layout value is coerced with absint() before comparison.
* Fix: Corrected the Typekit (Adobe Fonts) script enqueue -- the version placeholder is replaced with the theme version, the dependencies argument is an array, and the kit loads in the document head before first paint.
* Fix: Accessibility -- screen-reader-only labels (such as the editor's "Editor canvas" iframe name) no longer paint as visible text in the block editor; the standard clip-based accessible-hide rule is now shipped in the editor stylesheet.
* Fix: neovantage-scripts.js now declares neovantage-library (Bootstrap, Magnific Popup) as an explicit dependency instead of relying on enqueue order.
* Compat: Raised the minimum required WordPress version from 5.3 to 6.0. The theme now relies on block patterns (auto-loaded from the patterns directory in WP 6.0+) and theme.json design tokens, so 6.0 is the genuine floor; the "Requires at least" header in style.css and readme.txt was updated to match.
* Compat: Mirrored the premium Product Categories block grid into the Gutenberg editor so the canvas matches the front end.
* Refactor: WordPress Coding Standards / PHP 8.4 hardening pass over functions.php -- doc-comments, return types, str_contains() for the product-detection checks, and a guarded DOM lookup for the Latest Posts read-more injection. No behaviour change.
* Performance: Removed the unused Google Code Prettify script (js/run_prettify.js, ~34 KB) and its enqueue -- it loaded on every page but nothing referenced it and it pulled assets from the long-dead rawgit.com CDN; the premium Code block now covers code styling. The Code-block copy-to-clipboard script was also folded into the main theme script, removing another file and request.
* i18n: Regenerated the translation template (languages/neovantage.pot) for 2.4.0, picking up newly translatable strings including the Code block copy button ("Copy" / "Copied!") and the Latest Posts "Read More" link, plus strings accumulated since the template was last built.
* Docs: The theme description now positions NEOVANTAGE as both a content-first blog and a fully styled WooCommerce storefront, rather than blog-only.

= 2.3.0 - 5 June, 2026 =
* Feature: NEO Knowledge Base integration. When the NEO Knowledge Base plugin is active, the theme's native breadcrumb roots a knowledge-base article at its product space's landing page (or the Knowledge Base archive when no space applies) and includes the article's first category -- Home > [Space | Knowledge Base] > Category > Article -- mirroring the plugin's own trail; category and space archives are handled the same way. The page header also surfaces the Knowledge Base search form in its right-hand column on single articles and the KB category/tag archives (excluded on product-space archives). Both integrations are guarded with function_exists(), so with the plugin inactive the breadcrumb falls back to its default output and the search column renders empty -- no change and no errors on any non-knowledge-base view.
* Security: Hardened the Customizer export/import nonce handling -- the export and import nonces are now unslashed before sanitization (sanitize_text_field( wp_unslash( ... ) )) and the nonce-verification annotations were corrected. The capability and wp_verify_nonce() checks were already in place; this aligns the input handling with WordPress security idioms.
* Fix: Customizer custom font choices apply on the front end again -- the inline heading/body font CSS was attached to a stylesheet handle the theme does not register, so WordPress silently dropped it. Reattached to the correct neovantage handle.
* Fix: Typekit / Adobe Fonts now emit their configured Sans-serif/Serif fallback family.
* Fix: Jetpack Content Options toggles (show/hide date, categories, tags, author, comments) now work -- the support declared the wrong stylesheet handle, so the hide CSS never loaded.
* Fix: Footer copyright default links now use full https:// URLs (the bare hostnames produced broken, scheme-less links).
* Fix: Breadcrumb category selection now sorts by term ID as intended, and add_post_parents() is hardened against a null post on PHP 8.
* Improvement: Jetpack Content Options can now also toggle featured-image display (archive, post, page) alongside the existing post-detail toggles.
* Compat: Updated the theme description and tags to reflect WooCommerce compatibility -- added the e-commerce subject tag and synced the tag list between style.css and readme.txt.
* Refactor: WordPress Coding Standards / PHP 8.4 hardening sweep across the Customizer subsystem (loader, settings registrar, all custom controls, custom-CSS, fonts, sanitization, export/import) and the breadcrumb and template helpers. Added missing file/class/member doc-comments and ABSPATH guards, documented and corrected property and return types for static analysis, tightened loose comparisons to type-safe strict ones, gave control scripts explicit versions, and removed dead and commented-out code. The bundled ~132 KB Google Fonts catalogue was moved out of fonts.php into a sibling google-fonts.json data file (byte-identical, 915 families). No behaviour change.
* i18n: Wrapped previously hardcoded Customizer typography labels (Google Fonts, Typekit, Custom, Sans-serif, Serif) for translation, and removed pointless HTML-wrapped translatable strings from the comment walker (the comment date is now escaped on output).

= 2.2.0 - 30 May, 2026 =
* Feature: WooCommerce compatibility. NEOVANTAGE is now a fully WooCommerce-ready theme. The shop, single product, cart, checkout, order confirmation, and the complete My Account area are styled to match the theme, with a header cart icon and a slide-in mini-cart drawer. WooCommerce output, blocks, forms, and notices inherit the theme's colours, typography, and buttons. The store stylesheet loads only on WooCommerce pages, so sites without WooCommerce carry zero extra weight.
* Security: Escaped all unescaped output in template-parts/author-box.php -- `the_author_meta()` in href attributes replaced with `esc_url( get_the_author_meta() )`, `get_avatar()` wrapped in `wp_kses_post()`, author description wrapped in `wp_kses_post()`, `rel="noopener noreferrer"` added to all `target="_blank"` links. Removed defunct Google+ social link (service shut down 2019). Replaced triple `count_user_posts()` call with single cached variable and proper `_n()` pluralization.
* Security: Escaped `the_title()` with `esc_attr( get_the_title() )` in template-parts/content-entry-media.php title attribute. Replaced `phpcs:ignore` on featured image output with proper `wp_kses_post()` escaping. Fixed indentation of nested elements inside conditional blocks.
* Fix: Sticky footer -- footer now stays at the bottom of the viewport on short-content pages. Uses flexbox on #page.site (min-height 100vh) with #content.site-content as the growing element.
* Fix: Parent theme stylesheet not loading when a child theme is active -- `get_stylesheet_uri()` resolves to the child's style.css, so the parent's CSS was skipped entirely. Replaced with `get_template_directory_uri() . '/style.css'` which always points to the parent regardless of active theme.
* Fix: Fixed equals sign alignment in `neovantage_related_posts()` (PHPCS Generic.Formatting.MultipleStatementAlignment). Removed three unused variable initializations (`$neovantage_tag_check`, `$neovantage_related_args`, `$neovantage_related_posts` pre-set to null then immediately reassigned). Fixed `@return` docblock on `neovantage_has_post_thumbnail()` from `string` to proper array shape type.
* Fix: Removed void return assignment from `wp_parse_str()` call in `neovantage_merge_args()` -- `wp_parse_str()` returns void and populates its second argument by reference, so the assignment stored null.
* Fix: Sidebar not rendering on any page -- `get_theme_mod()` returns the string default `'1'` but all six templates compared it with strict `===` against integers (`1 === '1'` is always false). Wrapped all sidebar layout reads in `absint()` to match the Customizer's `absint` sanitize callback. Affected templates: index.php, archive.php, search.php, page.php, sidebar.php, page-templates/template-slideshow.php.
* Fix: core/latest-comments .has-avatars variant -- avatar and comment icon no longer overlap. Restructured the row to a two-column flex layout: avatar (48x48, 50% radius) on the left, article column on the right. Moved the lynny comment icon from the <li>::before to the .wp-block-latest-comments__comment-meta::before so it always appears at the start of the content column regardless of avatar presence. Visual sequence now reads: [avatar] [icon + author "on" post-title] with the date wrapping onto its own line below. Editor canvas (style-editor.css) mirrors the layout.
* Fix: Reset core block-library's `.has-avatars .wp-block-latest-comments__comment-meta/excerpt { margin-left: 1em }` to 0 inside .widget_block (and the editor canvas mirror). The core rule was added for a floated-avatar layout; our flex layout already separates avatar from article column via gap:12px, so the 1em indent only stacked extra padding onto the content column.
* Improvement: The recommended-plugins screen now pulls the latest version of WordPress.org-hosted plugins (Contact Form 7, Smash Balloon Instagram Feed) live from the WordPress.org Plugins API, cached for 12 hours, so the listed versions stay current automatically without a theme update.
* Improvement: Styled core/details block (WordPress built-in accordion) in css/blocks.css, css/block-details.css, and css/style-editor.css to match the NEOVANTAGE design language -- 1px #eee bordered card, 600-weight summary with custom chevron marker, theme color on hover/open state, stacked sibling grouping with shared borders. Frontend loaded via wp_enqueue_block_style() (only when block is used). Editor canvas mirrors the frontend treatment.
* Improvement: Styled core/accordion block (WordPress 7.0+ built-in accordion) in css/blocks.css and css/style-editor.css to match the NEOVANTAGE design language -- card borders, custom CSS chevron replacing the default "+" icon, theme color on hover/open state, stacked sibling grouping with shared borders, zero-margin spacing fix for accordion sub-blocks in the editor.
* Improvement: Restyled NEOVANTAGE Latest Posts widget -- replaced float-based layout with flexbox for reliable thumbnail/text alignment, fixed thumbnail to 86x65 with border-radius and object-fit cover, added 2-line title truncation with text-overflow ellipsis, refined post-date typography, added theme color hover via theme-tokens.css, added dark-background footer overrides, updated RTL stylesheet for flexbox layout.
* Improvement: Restyled core/latest-posts block for sidebar and footer widget areas -- items now stack vertically with title (14px/600 weight), author (italic), and date on separate lines with compact spacing. Removed left padding and list bullets. Added 1px #f1f1f1 row separators. Footer dark-theme overrides for #ccc titles and #333 borders. Editor canvas (style-editor.css) mirrors the frontend treatment. Theme color hover via theme-tokens.css.
* Improvement: Designed core/latest-comments block for sidebar (widget_block) and footer widget areas -- each comment row now carries a left-aligned lynny "general-comment" icon, italic muted author name, and a 600-weight #333 post-title link separated by 1px #f1f1f1 row borders. Footer dark-context overrides lift colors to #aaa/#ddd against dark backgrounds. Theme-color hover for author and link via theme-tokens.css. RTL stylesheet mirrors the icon column to the right.
* Compat: Bumped Tested up to from 6.9 to 7.0. Verified child theme compatibility -- all enqueue handles, template inheritance, and editor-styles support work under WP 7.0's fully-iframed block editor.
* Compat: Mirrored the core/latest-comments widget design into the Gutenberg widgets-editor canvas (style-editor.css) -- authors now see the same lynny "general-comment" icon column, italic author, and bold post-title link layout in wp-admin/widgets.php and post editor that renders on the front-end. Replaces the previous bare 17px/1.4em-margin treatment.
* Compat: Mirrored core/archives + core/categories list-item flex layout into the Gutenberg widgets-editor canvas (style-editor.css). Item rows now use display:flex with align-items:baseline so the post-count <span> right-aligns next to the month/category link instead of fusing into "January 20237". Covers both markup variants: bare sibling <span> (modern core) and wrapped .post-count chip with parens (legacy). 1px #f1f1f1 row separator with last-child reset matches front-end.
* Compat: Editor canvas link color for core/archives, core/categories, core/latest-posts, core/rss list items now defaults to #555 with theme-color hover via var(--wp--preset--color--theme, #26c6da). Previously the editor canvas inherited the default global link color (cyan) on idle which read as "always active" -- now matches the front-end widget pattern where idle links are muted and the theme color is reserved for the active/hover state.
* Refactor: Removed dead `neovantage_get_nonce()` function from inc/template-tags.php -- the PixelsPress subscription download system it served was retired when the plugin moved to GitHub. Zero callers remain. The function also had a caching bug (stored `false` instead of the fetched response body).
* Refactor: Split inc/template-nav-menu.php into WPCS-compliant per-class files: inc/class-neovantage-walker-nav-menu-main.php and inc/class-neovantage-walker-nav-menu-mobile.php. Added class docblocks, renamed reserved keyword parameter `$object` to `$menu_item`, replaced `join()` with `implode()`, added strict `in_array()`, removed dead no-op `neovantage_menu_added_div()` filter and commented-out code.

= 2.1.0 - 6 May, 2026 =
* Feature: Added theme.json (schema 2) at the theme root, registering three palette slugs (`theme`, `contrast`, `header-bg`), two font-family slugs (`heading`, `body`), a four-step font-size scale, a four-step spacingSizes scale, and contentSize/wideSize layout tokens. Block-editor color picker, font-size picker, and spacing controls now show theme-branded entries instead of WordPress's generic palette. Initial values pulled from inc/customizer/defaults.php so a fresh install renders identically to 2.0.13.
* Feature: Added inc/theme-json-customizer.php -- a wp_theme_json_data_theme filter that merges the live Customizer theme color, contrast color, header background, and font-family choices into the theme.json data tree at runtime. Customizer choices now propagate as `--wp--preset--color--theme` / `--wp--preset--color--contrast` / `--wp--preset--color--header-bg` / `--wp--preset--font-family--heading` / `--wp--preset--font-family--body` on both the front-end and block-editor canvas in a single pass. sanitize_hex_color() guards every input; invalid Customizer values fall back to the theme.json static default.
* Feature: Added css/theme-tokens.css -- a new front-end stylesheet hosting all theme-color and contrast-color rules previously injected from PHP via neovantage_custom_styles(). Each rule reads `var(--wp--preset--color--theme, #26c6da)` / `var(--wp--preset--color--contrast, #ffffff)` so the Customizer choice flows through automatically. Hex literal in every var() fallback matches the theme.json default -- misconfigured Combine-CSS in optimisation plugins (WP-Optimize, Hummingbird, W3 Total Cache, WP Rocket) that can reorder global-styles-inline-css now degrade to the default cyan instead of unsetting the property.
* Feature: Added six block patterns under wp-content/themes/neovantage/patterns/ (auto-loaded by WP 6.0+). The set covers a centred hero with CTA, a full-width call-to-action strip, a three-column latest-posts grid, an image-and-text two-column, a solid-colour pull-quote, and a four-column footer-info layout. Each pattern uses core blocks only (no plugin coupling) and references theme.json design-token slugs (`has-theme-color`, `has-contrast-color`, `has-{size}-font-size`, `var(--wp--preset--spacing--{slug})`) so they pick up any Customizer colour or font choice automatically. All visible strings are wrapped in esc_html__() with the `neovantage` text domain for translation. No external image services -- patterns either use core/image without src (authors see the editor's Add Media placeholder) or rely on theme-coloured backgrounds.
* Feature: Registered a custom `neovantage` block-pattern category via inc/block-patterns.php so the inserter's Filter-by-category dropdown shows a NEOVANTAGE entry alongside core categories (Featured, Call to Action, Text, Query, Footer). Each pattern lists both its relevant core category AND `neovantage`, so theme-shipped patterns appear in their natural section AND under a theme-branded filter.
* New: Added "Accent Text Color" Customizer control (Colors section) -- sets the foreground color for all elements that use the Theme Color as a background (buttons, category badges, tag-cloud hover, pagination active state, drop-cap, news-ticker heading, input-group addons, etc.). Defaults to #ffffff; switch to #000000 for light theme colors.
* Feature: Styled in-post pagination (page-links / post-page-numbers) emitted by wp_link_pages() for posts split with a <!--nextpage--> page break. Static layout in css/blocks.css (chip-style 32px-min, 1px #eee border, 3px radius, smooth hover transition); active-page background, hover background, and contrast text colour come from neovantage_custom_styles() so it matches the archive pagination component live.
* Feature: Added support for the nine core/cover content-position variants (.has-custom-content-position .is-position-{top|center|bottom}-{left|center|right}). The Cover block is now a flex column container so the editor's 3x3 position picker actually moves content; the inner-container loses its forced auto-margin. Also added explicit .wp-block-cover__image-background and .wp-block-cover__video-background absolute-positioning rules so featured-image and video Cover variants render correctly with the dim-overlay span layered between.
* Fix: media-text pattern (`neovantage/media-text`) inserted with "Block contains unexpected or invalid content" error on first try. Root cause: the pattern markup specified `mediaPosition:"left"`, `mediaWidth:50`, and an inline `style="grid-template-columns:50% auto"` -- all of which are core/media-text defaults. WordPress's block validator omits default-value attributes from saved markup, so the pattern's explicit defaults didn't match the block's expected save output and Gutenberg flagged the markup as invalid. Stripped the explicit defaults from the wp:media-text comment and from the inner heading. Pattern now inserts cleanly with the figure left-positioned at 50/50 width via core defaults.
* Fix: Comment form submit button (id="submit", class="submit") -- rendered by both the classic comment_form() helper and the wp-block-post-comments-form block -- now inherits the Theme Color as background and Accent Text Color as foreground, matching all other primary buttons.
* Fix: Replaced hardcoded color: #fff on .wp-block-search__button with the Accent Text Color Customizer value for consistency with the rest of the theme.
* Fix: core/button Solid variant rendered with a hardcoded black background -- style.css:4761 set .wp-block-button__link:not(.has-background) { background-color: #000 } and style.css:4774 darkened text on hover, neither of which respected the Customizer Theme Color. Added a higher-specificity override in neovantage_custom_styles() (and a CSS-variable mirror in css/style-editor.css for editor preview parity) that paints the Solid button's background, border, hover background, and text colour from $theme_color / $contrast_color while leaving authors who explicitly pick a background (.has-background) or text colour (.has-text-color) untouched. Also patched the matching is-style-outline rule so it stays consistent.
* Fix: core/column .has-background had no inner padding, so background-fill columns rendered with content flush against the edge. Added .wp-block-column.has-background { padding: 1em 1.25em } in css/blocks.css mirroring the existing .wp-block-group.has-background pattern.
* Fix: Headings inside post body (.entry-content) rendered all in the theme accent (#26c6da) at flat sizes (H1=24, H4=H3=18) because of the global h1-h6 rule at style.css:2990 -- destroying document hierarchy on every post. Added an .entry-content scoped override in css/blocks.css (color #222, family Noto Sans, weight 700, line-height 1.3) with proper hierarchy: H1=36, H2=28, H3=22, H4=18, H5=15 caps, H6=13 caps. The global rule still wins for widget titles, sidebar section labels, and other chrome where accent-coloured headings are the design intent. First-child margin reset prevents double-margin against post meta. Mobile breakpoint (<=600px) scales H1-H3 down by ~6px.
* Fix: Block: Image alignwide / alignfull broke the page layout when a sidebar was present -- the existing rules at style.css:3320-3343 unconditionally extend to 100vw / calc(50% - 50vw), which on the standard col-lg-8 + sidebar layout overflows the column and crashes into / displaces the sidebar (visible on the WP test "Block: Image" post -- the giant black .alignfull image was eating the right column entirely). Added a sidebar-aware override in css/blocks.css that caps alignwide / alignfull at the column width by default, and only restores real viewport-edge breakout (incl. the >=1200px calc(100% + 570px) variant) when the body has .no-sidebar -- already set by neovantage_body_classes() when sidebar-1 is empty. Single posts which hardcode col-lg-8 in single.php now stay inside the column safely; one-column layouts (sidebar-layout=3 with empty sidebar-1, or pages where users disable the sidebar) keep the dramatic breakout. Did not modify single.php or style.css to keep the change CSS-only and reversible.
* Fix: Block: Button rendered blue in the Gutenberg editor canvas instead of the theme cyan -- css/style-editor.css :root declared --neovantage-primary-color: #0080ce (blue) and nine var() fallbacks throughout the file echoed the same wrong colour, while the actual theme default per inc/customizer/defaults.php:25 is #26c6da (cyan). The CSS variable was also never updated when the Customizer theme color changed, so authors saw a permanently-blue button regardless of front-end colour. Replaced the :root default and all nine fallbacks with #26c6da. Wired up a Customizer->editor live sync: new helper neovantage_get_editor_color_vars_css() builds a sanitize_hex_color()-validated :root rule with --neovantage-primary-color and --neovantage-contrast-color from the Customizer; neovantage_gutenberg_editor_styles() injects it into the editor chrome via wp_add_inline_style(), and a new neovantage_block_editor_canvas_inline_styles() filter on block_editor_settings_all pushes it into the canvas iframe via the documented `styles` settings array. Authors who change the Customizer Theme Color now see the editor button match without needing to refresh the editor frame. php -l clean on functions.php.
* Fix: Block: Button shape and sizing diverged between the editor (5px rounded rectangles, 18px label, 14x30 padding) and the front-end (pill / oval shape, 16px label, 6x12 padding) -- root cause was wp-includes/blocks/button/style.css:17-22 which sets border-radius:9999px via a :where() rule (specificity 0,0,0). The editor overrides it at css/style-editor.css:618-620 but the front-end had no equivalent. Mirrored the editor's button treatment into css/blocks.css, scoped to .entry-content (specificity 0,2,2) so the new rules beat both the bare style.css:4741 declaration and core's :where default without bleeding into widget / sidebar / nav buttons. Added border-radius:5px default, border-radius:0 for .is-style-squared, padding 14px 30px (12/11 for outline variant compensating for the 2px border), font-size 18px, weight 500, and white-space:normal so multi-line button labels can wrap (the previous nowrap was overriding the button-block test pattern). No editor change needed -- the editor already had this treatment.
* Fix: Block: Quote -- solid-color pullquote rendered with a box-within-a-box on the front-end (visible spacing offset on the WP test "Block: Quote" post). The generic blockquote rule at style.css:7610-7619 (background:#f9f9f9 + border-left:5px solid #26c6da + padding:24px) cascades into the inner <blockquote> of <figure class="wp-block-pullquote"> because the existing pullquote reset only handled max-width and margin. Added a full inner-blockquote reset in css/blocks.css covering background, border, padding, margin, font-family/size/style, text-align, and color so the figure's own treatment is the only one visible. Also moved the solid-color variant's citation/paragraph colour to `inherit` so the figure's chosen foreground colour applies through.
* Fix: Block: File -- both the filename label and the Download button rendered in the theme cyan, making the button text cyan-on-cyan and unreadable. Root cause was style.css:8048 painting `.single .entry-content a:not(.carousel-control)` with `#26c6da` at specificity 0,3,1, which overrode the contrast-color rule emitted by neovantage_custom_styles() (specificity 0,1,0) and the gray label rule in css/blocks.css (specificity 0,2,1). Bumped both selectors to 0,3,2 by combining `.entry-content a.wp-block-file__button` with the `.single .entry-content a.wp-block-file__button` form so the contrast color wins regardless of post type, and matched the filename label with `.entry-content .wp-block-file > a:not(.wp-block-file__button)` (and its `.single` sibling) at 0,3,1 -- ties on specificity but blocks.css source-orders after style.css.
* Fix: core/table cells showed visible per-cell borders on all four sides in both the Gutenberg editor canvas and on the front-end, drowning the row-separator-only rhythm the theme intends. Root cause: WP core's wp-includes/blocks/table/style.css sets `.wp-block-table td, .wp-block-table th { border: 1px solid }` (currentColor by default) -- my `border-top: 1px solid #f1f1f1` only overrode the top side, leaving right/bottom/left at core's default. Added explicit `border-right: 0; border-bottom: 0; border-left: 0` on cells, thead th, and tfoot cells in both css/blocks.css (.entry-content scope) and css/style-editor.css (.editor-styles-wrapper scope). Tables now render as clean horizontal row separators only, matching the rest of the theme's table aesthetic.
* Improvement: Introduced css/blocks.css -- a dedicated frontend stylesheet for Gutenberg block structural overrides (shape, padding, transitions). Loaded after style.css via its own enqueue handle neovantage-blocks. Dynamic colour rules remain in neovantage_custom_styles() so they stay responsive to Customizer changes.
* Improvement: Expanded core Gutenberg block coverage in css/blocks.css and neovantage_custom_styles(). Added structural rules for heading, list, quote citation, pullquote (default + is-style-solid-color), preformatted, verse, image (figcaption + alignleft/aligncenter/alignright + is-style-rounded), gallery, cover, media-text (with mobile stack at 600px), embed (responsive aspect-ratio container with named-ratio modifiers), audio, video, file (with .btn-shaped download button), buttons parent (flex layout + is-content-justification-* + is-vertical), button is-style-outline, separator (default + is-style-wide + is-style-dots), columns (mobile stack at 781px, respects is-not-stacked-on-mobile), group (has-background padding), archives, categories, latest-posts, page-list, rss, tag-cloud, calendar, social-links, latest-comments refinements, and the has-text-align-* alignment utilities scoped to .entry-content. Theme-color rules added to neovantage_custom_styles() for pullquote borders, file download button, button is-style-outline border/fill, archives/categories/latest-posts/page-list/rss link hover, tag-cloud hover, calendar #today highlight, and social-links hover -- they react live to Customizer changes via the existing convention. Editor preview parity mirrored into css/style-editor.css for the most visually impactful rules. Existing block coverage in style.css (table, button, search, code, latest-comments, drop cap) and the alignwide/alignfull breakout were left untouched.
* Improvement: core/group is-layout-flex (Row variation) and .is-vertical (Stack variation) now have theme-side defaults -- flex-wrap, gap, item alignment, .is-nowrap, and the four .is-content-justification-* utilities -- so groups read consistently before and after WordPress's per-block .wp-container-core-group-is-layout-* inline CSS lands. Children's vertical margins are reset inside flex groups to keep gap as the single source of truth.
* Improvement: core/search block now has a unified form-control treatment for both layout variants (button-outside + button-inside). Static rules in css/blocks.css give .wp-block-search__inside-wrapper a 38px input with 1px #eee border, themed placeholder colour, and a 0.15s focus transition matching the existing .form-control component (style.css:5158); the focus border colour is themed live via neovantage_custom_styles() and uses :focus-within on the wrapper for the button-inside variant.
* Improvement: core/media-text -- three issues fixed. (a) is-image-fill variant collapsed to zero height because the image is moved to background and the original <img> hidden; figure now gets min-height: 280px and the hidden <img> uses a screen-reader-only clip-path so it stays accessible. (b) Content column was flush against the image edge; added 8% horizontal padding inside .wp-block-media-text__content and reset first/last-child margins so vertically-centered text doesn't double-space. (c) Mobile stack now respects the .is-stacked-on-mobile flag (editor opt-in) instead of stacking unconditionally below 600px. Removed the 1.5em outer gap so image and content sit edge-to-edge; the content-side padding gives the breathing room.
* Improvement: core/file block redesigned as a card row -- light gray background (#fafafa), 1px #eee border, 4px radius, 14px/16px padding. The filename link reads as a label (color #333, weight 600, no underline until hover) and the .wp-block-file__button is pushed to the far right via margin-left:auto. Wraps cleanly on narrow viewports.
* Improvement: core/audio block now sits inside a matching card container (same #fafafa / 1px #eee / 4px radius pattern as the file block) so the bare browser audio control reads as a deliberate page element instead of a stranded widget. Native audio control gets a 999px radius for a softer pill shape where supported.
* Improvement: core/table block -- only border-color was set theme-side; cells had no padding, headers no background, captions unstyled, footer indistinguishable. Added an .entry-content scoped table system in css/blocks.css mirroring the .table component (style.css:984+) -- 10x12px cell padding, 1px #f1f1f1 row separators, fafafa header bg with uppercase 13px label, 2px header bottom border, fafafa footer with bold contrast, italic centred captions (caption-side: bottom). is-style-stripes variant zebras odd tbody rows with transparent borders. Below 600px the block becomes a horizontal-scroll container so wide tables don't crush.
* Improvement: Plain `<ul>` and `<ol>` inside .entry-content (Classic blocks, raw HTML, embedded markup) now match the rhythm of modern .wp-block-list -- same 1.5em left padding, 0.35em row gap. The global `ul, ol { margin-bottom: 12px }` at style.css:3226 left padding-left at the browser default which mismatched modern Gutenberg list blocks visibly. Also restored disc / circle / square nested marker progression and decimal numbering on the entry-content scope so Markup test posts read correctly.
* Improvement: Image hover overlay icon for the Standard post format (the magnific-popup zoom-on-click affordance shown on featured images and recent-posts widget thumbnails) changed from lynny-general-file (a generic document icon) to lynny-general-search (magnifier) at inc/template-tags.php:496. The post-format-specific icons (gallery -> photo-list, link -> link, quote -> quote, etc.) are unchanged -- only the STANDARD fallback was updated to communicate the click-to-enlarge intent.
* Improvement: Rounded image variant (.wp-block-image.is-style-rounded img) now respects the source image's natural footprint via max-width:100%; width:auto; height:auto and centers the figure. Fixes a case where the WP test 150x150 placeholder rendered as a column-wide circle on the Markup post because no width was set on the figure and the parent column stretched the img.
* Improvement: Block category: Widgets -- multiple widget blocks reworked for the in-content rendering. (a) core/archives and core/categories list items now flex-row with align-items:baseline so the post-count chip sits beside its link; the count itself is wrapped in CSS-generated parens via .post-count::before / ::after with a dim #999 colour (was rendering as "January 20227" with the count fused into the year). Added padding-left:0 on the lists so the bullet column doesn't push the items off centre. (b) Dropdown variants (.wp-block-archives-dropdown, .wp-block-categories-dropdown) get inline label + 6px/10px padded select with the theme's #eee border so the controls match form-control aesthetics. (c) core/latest-comments -- the .has-avatars variant now uses a flex row with the 40px round avatar pinned left and the article filling the rest; date moved onto its own dim 0.8em line under the meta; excerpt indented under the content column. The no-avatar variant falls back to a plain block layout. Without these the comments crammed against the avatar with no visible row separation.
* Compat: theme.json sets appearanceTools to false explicitly. Color link, typography lineHeight, and spacing padding/margin/blockGap are opted in individually since the theme has CSS coverage for those surfaces. Other appearanceTools surfaces (border-radius pickers, dimensions presets, filter effects) remain disabled until validated visually -- enabling them all at once would let authors produce blocks the theme renders incorrectly.
* Compat: Mirrored the entry-content heading hierarchy and table system into css/style-editor.css so the Gutenberg block-editor canvas matches what the front-end renders. .editor-styles-wrapper-scoped rules use .wp-block-heading specificity to beat the existing flat-size editor heading rules (style-editor.css:60-97) without breaking widget editing in the Customizer.
* Compat: Block: Quote -- pullquote rendered differently in the Gutenberg editor canvas vs the front-end. css/blocks.css is enqueued only for the front-end (functions.php:285); the editor only loads css/style-editor.css via add_editor_style(), so the .wp-block-pullquote rules never reached the canvas. Mirrored the pullquote treatment (top/bottom borders, italic 1.4em paragraph, citation typography, inner <blockquote> reset, solid-color variant with figure-as-card) into style-editor.css under .editor-styles-wrapper. Author preview now matches the rendered post for both regular and is-style-solid-color variants.
* Compat: Gutenberg list items rendered with ~60px vertical gap between siblings in the editor canvas (visible on the WP test "Markup" post). Modern Gutenberg renders each <li> as its own inner block with data-type="core/list-item" -- the editor's existing 30px-block-margin rule at css/style-editor.css:39 only excluded core/list (the parent), not the items, so each li picked up 30px top + 30px bottom. Added :not([data-type='core/list-item']) to the chain plus an explicit `[data-type='core/list'] [data-type='core/list-item'] { margin-top: 0; margin-bottom: 0 }` belt-and-braces rule. Also mirrored the entry-content list rhythm (1.5em padding-left, 0.35em row gap, disc/circle/square nested-marker progression) into style-editor.css under .editor-styles-wrapper so editor preview matches front-end. The legacy .block-library-list .editor-rich-text__tinymce rules at lines 648-660 are TinyMCE-era and untouched.
* Compat: Mirrored the .wp-block-archives-dropdown / .wp-block-categories-dropdown label + select styling into css/style-editor.css under .editor-styles-wrapper. blocks.css is front-end only via wp_enqueue_style(); the editor canvas only loads style-editor.css via add_editor_style(), so the dropdown widget rendered with browser-default controls in the editor while the front-end showed inline label + form-control select. Author preview now matches the rendered post.
* Compat: core/calendar header (M T W T F S S) rendered with no background, no bottom rule, and unstyled labels in the Gutenberg editor canvas while the front-end picked up the .entry-content table thead th treatment (fafafa background, 2px e5e5e5 bottom border, uppercase 13px #444 label). The .wp-block-table editor rules don't catch core/calendar because its markup is <figure class="wp-block-calendar"><table> -- plain <table> with no .wp-block-table class. Added explicit .editor-styles-wrapper .wp-block-calendar thead th / tfoot td / caption rules in css/style-editor.css mirroring the front-end thead treatment plus tfoot border-reset and caption typography. Author preview now matches.
* Refactor: Trimmed neovantage_custom_styles() in inc/template-functions.php from ~410 lines to ~70. Static-token rules (color, background-color, border-color paired with theme/contrast values) lifted out to css/theme-tokens.css. The PHP function now emits only the seven brightness-derived rule groups that need a value computed from the live Customizer color (`.btn.btn-primary:hover`, `.widget_tag_cloud .tagcloud a:hover`, `.nkb-category .nkb-category-article-list a:hover`, `#respond #submit:hover`, `.wp-block-file__button:hover`, `.wp-block-button:not(.is-style-outline) .wp-block-button__link:not(.has-background):hover`, `.wp-block-tag-cloud .tag-cloud-link:hover`) -- these continue to use neovantage_adjust_brightness( $theme_color, -20 ) since theme.json cannot express derived values.
* Refactor: Removed neovantage_get_editor_color_vars_css() and neovantage_block_editor_canvas_inline_styles() from functions.php -- both injected `--neovantage-primary-color` / `--neovantage-contrast-color` into the block-editor canvas. Their job is now done by theme.json + the wp_theme_json_data_theme filter via WordPress's auto-emitted `--wp--preset--color--theme` / `--wp--preset--color--contrast`. css/style-editor.css updated to consume the new variable names. neovantage_gutenberg_editor_styles() is kept for the chrome-stylesheet enqueue but no longer carries the wp_add_inline_style() call.
* Refactor: Removed the in-line `add_theme_support( 'editor-color-palette', ... )` registration from neovantage_setup() -- theme.json's settings.color.palette is now the canonical source. The legacy `primary` slug is replaced by the `theme` slug; downstream sites that hardcoded the `primary` slug in saved post markup (e.g. `class="has-primary-color"`) should rename to `has-theme-color` on next edit. The default value (Customizer theme color, fallback #26c6da) is unchanged.
* Refactor: Moved `header-bg` from theme.json's palette to settings.custom.color so it no longer appears as a swatch in the block-editor inserter. Visual verification of the new palette surfaced two cyan swatches side-by-side (`theme` and `header-bg`, both #26c6da by default) which would confuse authors picking colours for in-content blocks -- `header-bg` is a chrome-only colour consumed by the `.site-header` rule, not an in-content choice. The CSS variable rename is `--wp--preset--color--header-bg` -> `--wp--custom--color--header-bg`; theme-tokens.css and inc/theme-json-customizer.php updated together. Customizer override still flows through the same wp_theme_json_data_theme filter. Non-breaking -- the slug never reached a shipped release.
* Docs: Bumped theme version 2.0.13 -> 2.1.0. New design-token surface plus public-contract additions (palette/font slugs) qualify as a minor bump. No breaking change for existing sites -- Customizer choices, classic templates, and saved block content all continue to render identically.
* Docs: Added README.md at the theme root -- a GitHub-friendly project document with badges, requirements table, install steps, recommended plugins, FAQ, full versioned changelog (synced with this readme.txt including the Unreleased section), credits table, and license. Theme readme.txt remains the canonical WordPress.org-format source; README.md is generated/maintained from it.

= 2.0.12 - 23 April, 2026 =
* Security: Replaced esc_attr() with esc_html() for quote author output in template-parts/content-quote.php -- esc_attr() is for HTML attribute values; esc_html() is correct for text content inside an element.
* Security: Escaped $link_title post meta with esc_html() before injecting it into anchor HTML in template-parts/content-link.php -- the value was previously raw, allowing stored XSS via the _neovantage_link_title custom field.
* Security: Sanitized $_SERVER['REQUEST_URI'] with wp_unslash() and esc_url_raw() at all 14 read sites in class-neovantage-breadcrumb.php before passing to home_url() -- satisfies WordPress.Security.ValidatedSanitizedInput coding standard.
* Security: Escaped custom_class argument with esc_attr() in breadcrumb wrapper sprintf() in class-neovantage-breadcrumb.php -- the value was interpolated into a class attribute without escaping.
* Security: Replaced esc_attr( get_the_title() ) with esc_html( get_the_title() ) in header.php news-ticker loop -- esc_attr() double-encodes entities when used for element text content.
* Security: Replaced the_title() with echo esc_html( get_the_title() ) in archive.php grid layout -- the_title() outputs unescaped content directly.
* Fix: Resolved PHP warning "Undefined array key with_front" in class-neovantage-breadcrumb.php -- replaced direct array key access with empty() check at both call sites, preventing notices on custom post types that register rewrite rules without explicitly declaring with_front.
* Fix: Corrected double-hash colour output (##ffffff) in custom-header.php inline CSS -- root cause was default-text-color declared with a leading # in add_theme_support(), contrary to WordPress convention; corrected to plain hex (ffffff) so get_header_textcolor() returns a consistent unprefixed value and ltrim() is no longer needed.
* Fix: Refactored neovantage_header_style() in custom-header.php to build CSS as a PHP string instead of interleaving PHP tags inside a <style> block -- eliminates IDE CSS-linter false positives caused by mixed PHP/CSS mode and removes the empty mobile-navigation rule that was outputting a blank {} block on every page load.
* Fix: Fixed inverted fallback condition for quote author in template-parts/content-quote.php -- && was used where || was needed, so the post author display name was never substituted when no custom quote author meta was set.
* Fix: Replaced bitwise & with logical && operator in template-parts/content-quote.php author display check.
* Fix: Added phpcs:ignore WordPress.DB.SlowDBQuery comment on tax_query usage in archive.php -- query is intentional and required for category-scoped grid output; no alternative WP API avoids this.
* Fix: Changed post-increment $i++ to pre-increment ++$i in archive.php loop per WordPress coding standards.
* Fix: News ticker no longer renders on fresh installs or when no posts exist -- the entire wrapper and navigation arrows are now suppressed when the query returns zero results, eliminating the broken "Latest ..." display.
* Fix: Removed undefined $atts variable references from the news ticker block in header.php -- $atts was a shortcode remnant never set in the template context, causing a PHP 8 "Undefined variable" warning on every front page load.

= 2.0.11 - 20 April, 2026 =
* Improvement: Plugin cache now automatically clears on theme update -- ensures users always get fresh plugin version data from GitHub after upgrading, eliminating stale version mismatches.

= 2.0.10 - 20 April, 2026 =
* Fix: Bumped NEOVANTAGE Core fallback version in TGM plugin registration from 2.0.6 to 2.0.9 -- the stale fallback caused the Install Plugins screen to display 2.0.8 instead of 2.0.9 on sites where the remote plugins-data.json had not yet been fetched.

= 2.0.9 - 11 April, 2026 =
* Fix: Cookie consent close element changed from non-interactive <span> to <button type="button"> for full keyboard and screen-reader accessibility.
* Fix: Eliminated duplicate navigation markup in the page source -- the menu is now rendered once server-side; the mobile off-canvas drawer is populated client-side via a JavaScript DOM clone.
* Fix: Removed the separate "Mobile Menu" Customizer location -- a single "Primary" menu location now drives both desktop and mobile navigation, removing the two-assignment requirement from WordPress Admin -> Menus.
* Fix: Customizer sidebar section Dashicons now reliably vertically centred -- switched from inline-block + vertical-align (unreliable across font metrics) to flexbox align-items: center on the row element.
* Improvement: Preloader now dismisses on DOM-ready instead of window.load -- eliminates multi-second blocking on image-heavy pages. Fade duration reduced from 1200 ms to 300 ms.
* Improvement: Added CSS safety-valve animation that auto-hides the preloader overlay after 4 s if JavaScript is delayed or blocked.
* Improvement: Preloader Customizer default changed from enabled to disabled -- new installs are unaffected; existing users who enabled it via Customizer are unaffected.
* Improvement: Cookie consent banner redesigned -- two-column flex layout (message left, actions right), theme-accent top border (3 px, #26c6da), Montserrat typography, and a responsive mobile breakpoint.
* Improvement: "Menus" panel repositioned in the Customizer sidebar to appear immediately after "Header" (priority 5) for faster access.

= 2.0.8 - 07 April, 2026 =
* Fix: Removed erroneous code in TGM class that skipped all recommended plugins from the Install/Update Plugins table -- caused the list to appear empty while the tab count still showed plugins to install.
* Fix: Plugin metadata transient (neovantage_premium_plugins_info) is now automatically busted on theme update -- stale version data from a previous theme version is cleared on the first admin page load after updating, with no manual action required.

= 2.0.7 - 07 April, 2026 =
* Security: Wrapped breadcrumb link output with esc_url() in class-neovantage-breadcrumb.php.
* Security: Escaped alert() output in Customizer export/import with esc_js().
* Security: Replaced unescaped echo with wp_kses_post() for custom code injection output in header.php and footer.php.
* Security: Added wp_unslash() and sanitize_text_field() to $_REQUEST nonce values in Customizer export/import before wp_verify_nonce().
* Security: Replaced serialize()/unserialize() in Customizer export/import with wp_json_encode()/json_decode() to prevent object injection vulnerabilities.
* Security: Export file format changed from .dat (octet-stream) to .json (application/json).
* Fix: Replaced unlink() with wp_delete_file() in Customizer export/import and image sideload.
* Fix: Added strict true parameter to all in_array() calls in class-neovantage-customize-export-import.php.
* Fix: Added strict true parameter to all in_array() calls (19 instances) in class-neovantage-control-typography.php.
* Fix: Replaced (int) cast with absint() for $_GET['paged'] in template-slideshow.php.
* Fix: Loose == and != comparisons replaced with strict === and !== in Customizer export/import.
* Fix: Replaced WP_Filesystem usage with file_get_contents() for reading uploaded import file -- WP_Filesystem is for upgrade operations only.
* Fix: Removed unused init_filesystem() method from Neovantage_Customize_Export_Import class.
* Fix: Renamed private methods in Neovantage_Customize_Export_Import removing underscore prefix (_export, _import, _import_images, _sideload_image, _is_image_url) per PSR-2 coding standards.
* Fix: Renamed reserved keyword parameter $string to $url in is_image_url() method.
* Fix: no_items() in TGM class now correctly renders the "Return to Dashboard" link -- replaced esc_html__() with __() wrapped in wp_kses() to allow the anchor tag through.
* Fix: TGM plugin download URL updated from downloads.pixelspress.com to GitHub Releases (mohsin-rafique/neovantage-core).
* Fix: Plugin version metadata JSON endpoint updated from downloads.pixelspress.com to GitHub raw content (mohsin-rafique/neovantage-core/main/plugins-data.json).

= 2.0.6 - 05 April, 2026 =
* Security: Escaped header_image() output with esc_url() in header.php style attribute.
* Security: Replaced unescaped the_title(), the_excerpt(), the_permalink(), and bloginfo() in Open Graph meta tags with properly escaped get_* equivalents (esc_attr, esc_url).
* Fix: Updated License URI in style.css from http:// to https://.
* Fix: Removed dead unprefixed function get_gallery_attachments() from inc/template-tags.php.
* Fix: Removed duplicate TGM library (class-tgm-plugin-activation.php); now correctly loads the prefixed Neovantage_TGM_Plugin_Activation class with ABSPATH guard and conflict-safe naming.
* Fix: Replaced dirname(__FILE__) with __DIR__ constant throughout admin/ (PHP 5.3+ best practice).
* Fix: Replaced deprecated wp_resource_hints filter (removed WP 6.7) with version-aware wp_preconnect_urls shim.
* Fix: Updated all protocol-relative URLs to explicit https:// in fonts.php, template-tags.php, and typekit.php.
* Fix: Added strict type checking (true) to all in_array() and array_search() calls in template-tags.php.
* Fix: Replaced reserved keyword parameter names $object and $default in template-functions.php.
* Fix: Collapsed lone if-inside-else to elseif in neovantage_get_post_thumbnail().
* Fix: Corrected $post global override in neovantage_related_posts() loop.
* Fix: Restored accidentally disabled get_transient() call in neovantage_get_nonce().
* Improvement: Moved NEOVANTAGE Core update notices to the plugin itself (Neovantage_Core_Updater) -- plugins manage their own update lifecycle per WP standards.
* Improvement: TGM plugin list now fetches live version data from remote JSON endpoint with 24-hour transient cache, timeout, HTTP status check, and proper error handling.
* Compatibility: Tested up to WordPress 6.9.
* Compatibility: Minimum PHP requirement raised to 8.0; confirmed clean on PHP 8.4.

= 2.0.5 - 07 July, 2021 =
* Fix: Dynamic CSS value for header links.

= 2.0.4 - 05 April, 2021 =
* Feature: Option to show/hide related posts.
* Fix: Default layout for archive pages.

= 2.0.3 - 18 March, 2021 =
* Compatibility: Code improvements and compatibility check with WordPress 5.7.1.

= 2.0.2 - 15 March, 2021 =
* Fix: Removed Pinterest share link.

= 2.0.1 - 15 March, 2021 =
* Fix: Incomplete output on gallery post format.
* Fix: Undefined index: with_front.

= 2.0.0 - 14 March, 2021 =
* Major: Revamped from scratch with improved site header and breadcrumb.

= 1.2.6 - 24 August, 2018 =
* Feature: Cookie consent notification bar.
* Improvement: Theme options panel improvements.
* Update: Replaced Font Awesome with Lynny Icons.

= 1.2.5.2 - 23 May, 2018 =
* Fix: Mobile menu close icon.

= 1.2.5 - 14 May, 2018 =
* Update: Revised author page with author bio box.

= 1.2.4 - 07 May, 2018 =
* Feature: Post view count.
* Fix: Missing Fontawesome icons.

= 1.2.3 - 06 May, 2018 =
* Feature: Social media follow links in theme options.
* Update: Font Awesome updated to 5.0.12.

= 1.2.1 - 05 May, 2018 =
* Feature: Custom code injection in head, after body open, and before body close via theme options.

= 1.2 - 05 May, 2018 =
* Update: Theme options panel improvements.

= 1.1.4 - 15 November, 2017 =
* Update: TGM Plugin Activation class updated.

= 1.1.3 - 11 November, 2017 =
* Fix: Responsive video size.
* Note: CSS cleanup.

= 1.1.2 - 17 October, 2017 =
* Fix: Post format structure and Open Graph permalink URL.

= 1.1.1 - 09 August, 2017 =
* Feature: Open Graph meta tags.

= 1.1.0 - 17 April, 2017 =
* Feature: Page preloader.
* Improvement: Migrated all theme options to WordPress Customizer; removed Redux Framework dependency.
* Improvement: Replaced custom pagination with native the_posts_pagination() and the_post_navigation().
* Improvement: Replaced custom excerpt function with native excerpt length filter.

= 1.0.4 - 04 January, 2017 =
* Feature: Custom logo support.

= 1.0.3 - 23 November, 2016 =
* Compliance: All functions, options, globals, and post meta prefixed with neovantage_.
* Note: All resources included within the theme directory.

= 1.0.0 - 28 August, 2016 =
* Initial release.
