== Typography Stylist — Full Changelog ==

The complete version history of Typography Stylist. Recent releases are also
summarized in readme.txt; release notes with downloads live on GitHub:
https://github.com/mattcowan/typography-stylist-for-wordpress/releases


== Changelog ==

= 2.3.0 =
* **NEW: the style browser shows your own words.** When you open the Paragraph Styles browser with text selected, each row now renders the selected words in that style instead of the style name. The name stays in the row's detail line. Long selections are cut at 40 characters.
* **NEW: group the style browser by font family, size mode, or recently used.** A "Group by" control sorts the styles under headings. "Recently used" lists the styles you applied last, most recent first, and remembers them in this browser. Groups keep working with the search box and with "Show more".
* **Improved: the style browser is one keyboard stop.** The list is a listbox: Tab reaches it once, the arrow keys and Home/End move between styles, the first letter of a name jumps to it, and Enter or Space applies. Screen readers announce each style with its font, weight and size, and the group name when you enter a group. Mouse use is unchanged.
* **Fixed: switching one OpenType feature on made a bold heading light.** In the inline editor, toggling any feature wrote a normal (400) weight onto the selected text, so a heading your theme renders bold lost its weight on the styled word. A weight is now written only when the text already has one or you pick one in the panel. The Font Weight control opens on the weight the text actually renders at.
* **Fixed: "Convert to Typography Stylist Block" restyled the whole block.** With part of the text selected, the conversion copied the selection's font size, letter spacing and line height onto the new block, so the words outside the selection changed too. The selection keeps its styling on its own span and the block takes the defaults. Converting with the whole block selected works as before.
* **Fixed: a Font Library font that is installed but not activated rendered in a fallback font.** Picking such a font in the editor saved correctly but printed no @font-face, so the text showed the browser's serif font on the page and in the editor. The plugin now prints the family's own @font-face rules whenever WordPress does not, on the page, in the editor and in the settings preview.
* **Fixed: a font installed in the Font Library did not appear in the editor font pickers for up to an hour.** The pickers read a cached list. Installing or deleting a family now refreshes that list on the next editor load, and a face added to a family reaches the printed CSS on the next page load.
* **Improved: the inline editor warns when responsive sizes are out of order.** The Typography Stylist block already showed the note; the inline editor's Minimum, Preferred and Maximum sliders now show the same note, and screen readers hear it when it appears. The sizes are still written as you set them.
* **Improved: the Typography Stylist block tells you when styling cannot nest any deeper.** Inline styling nests at most three levels. A fourth level used to do nothing and leave the control showing a value it did not apply. The panel now shows and announces "Maximum nesting depth (3) reached", and the control returns to its real value.
* **Fixed: "Font Size (for selected text) → Responsive (fluid)" did nothing until you moved a slider.** In the Quick Feature Toggles, choosing Responsive now applies at once with the current slider values, and choosing "Inherit from block" removes the inline size. Also fixed: the collapsed-caret path wrote a malformed font-size declaration.
* **Improved: the word-boundary notice explains when conversion is not available.** On a list item or a button, the notice recommended converting to a Typography Stylist block but showed no button and no reason. It now says that conversion is available for heading and paragraph blocks.
* **Fixed: settings page buttons dropped keyboard focus while a request ran.** Every save, upload, register and delete button was disabled during its request, and browsers move focus off a disabled control. Screen readers re-read the page title after each save and keyboard users started over from the top. The buttons now stay focusable and announce "unavailable, busy" until the request completes, and a second press while busy is ignored.
* **Improved: settings page accessibility.** The Delete Font dialog is a real dialog for assistive technology. The font list is a named region with a visible focus ring after a refresh. The link-style buttons ("Manage", "Enable All", "Disable All", "Clear Font Cache", "Show Editor Tips Again") meet WCAG AA contrast on the default color scheme. The "Font deleted successfully!" notice can be dismissed. Only one settings confirmation is on screen at a time, and it stays until the next save replaces it. The Replacement Fonts tab's messages are translatable.
* **Fixed: the "Load on all pages" checkbox showed the wrong state after a failed save.** The rollback never ran; it does now.
* **Changed: the `typost_allow_variable_weights` option is no longer written by a settings save.** The option had no control on the form, and a save without JavaScript reset it. Nothing in the plugin writes it now; the font sanitizer still reads it.
* Developer: the toolbar-button click context's `accessibility.convertBlockedMessage` now also carries the reason for a block type that has no conversion. The Font Library `save_post_wp_font_family` and `save_post_wp_font_face` hooks invalidate the plugin's caches. See HOOKS.md and CLAUDE.md.
* **Fixed: screen readers heard the accessibility notice before the dialog's name.** Opening the Glyphs Panel or the inline editor with a partial-word selection read the whole notice first. The dialog name is read first; the notice follows, and the Convert button carries the reason.
* **Fixed: keyboard focus left an open panel after Enter or Space.** In Firefox, inserting a glyph or toggling a feature moved focus into the editor canvas without any event, and Escape no longer closed the panel. A focus guard keeps focus inside the open panel.
* **Fixed: the Quick Feature Toggle controls and the Paragraph Style dropdown had no accessible name.** Screen readers now announce Font Weight, Font Style, Font Size, Line Height, Letter Spacing and Paragraph Style by name.
* **Improved: the editor panels have fewer Tab stops.** The scroll areas, the drag handle, the tips bar and the eight resize handles are no longer Tab stops. Keyboard repositioning is a named "Move panel, use arrow keys" button, and the tips bar has its own "Dismiss tip" button. The Paragraph Styles browser opens with focus on the style list.
* **Fixed: contrast in the panels.** The accessibility notice link and the admin feature-code chips meet WCAG AA.
* **Fixed: the Glyphs Panel swapped or duplicated the wrong glyph.** Browsing to a different character right after an insert overwrote the inserted one; picking an alternate right after a caret insertion duplicated it. The panel now swaps only while you browse the same character.
* **Improved: the Glyphs Panel's character field accepts `U+XXXX` and sequences up to eight characters.** A sequence the font has no ligature for shows a message instead of a plain-character cell.
* **Fixed: paragraph styles.** A styled Typography Stylist block now renders from its style's CSS class in the editor, so an in-progress edit previews correctly and an update to the style elsewhere shows at once. The "(modified)" badge is correct right after you pick a style. Style selectors beat theme heading CSS on the frontend. Content styled only through a paragraph-style class loads its font. A block whose style was deleted falls back to its own attributes. A full block reset clears the style and font-axis attributes. Line-height rounding matches on both sides, and fixed-size styles no longer store the responsive size trio. The Paragraph Styles admin tab names each style's real font. Legacy style IDs with hyphens are matched in full.
* **Improved: the Paragraph Styles browser shows which scope it will apply to** and marks the selection's own style as active in selection scope. Applying a style over text that already has its own styling asks first, in both editors.
* **Improved: the Paragraph Styles admin tab moves focus and announces results** after Edit, Save, Cancel and Delete.
* Developer: `typost_content_font_ids` filter (fonts referenced only through an extension's CSS class), the `typost-paragraph-style-apply-cancelled` event, `state.selectionParagraphStyleId` in the toolbar click context, and the generic `typost_extension_panel_closed` action. `Typost::clear_font_detection_cache()` is public. See HOOKS.md.
* Developer: an NVDA screen-reader test harness (`npm run test:sr`, Guidepup + Playwright, Firefox) drives five journeys through the real editor and settings page and logs every phrase NVDA speaks. It runs on demand, not in CI.
* **Fixed: applying a paragraph style to selected text skipped any part of it that had styling of its own.** Select a whole headline whose first letter you had already given a font and a swash, apply a style, and every letter changed except that one — the letter's own settings beat the style in the browser's cascade, so the style silently lost. The Typography Stylist block now checks the selection first and, when some of it carries its own font, weight, size, spacing, or features, asks whether to replace that styling. Confirm and the whole selection takes the style; cancel and nothing changes. This also covers a word selected inside a longer styled run: the run is split at the selection so only that word takes the style and gives up the run's own size, spacing, or features, while the text on either side keeps them. Glyph alternates chosen in the Glyphs Panel and fit-relative size adjustments are kept either way, since they are choices about a glyph rather than the paragraph's typography.
* **Improved: notices in the editor panels share one spacing rule.** The accessibility notice in the inline editor ran into the top edge of the panel, and the block's tips notice ran straight into the controls below it (its spacing was set in a way the notice component never rendered). Every notice inside the inline panel and the Quick Feature Toggles now gets the same 16px of room on all sides, from a single stylesheet rule that any notice added later inherits, and the tips bar in both editors uses the same pinned, full-width layout. The "Manage accessibility settings" link in the accessibility notice (inline editor and Glyphs Panel) now sits left-aligned under the Convert button instead of floating to the right.
* **NEW: "Show Editor Tips Again" button on the Options tab.** Dismissing the tips notice in an editor panel is remembered per browser, and there was no way to see the tips again short of clearing site data. The button clears that memory for the browser you click it in.
* **Fixed: the Glyphs Panel's base glyph did not undo an alternate set at block level.** In the panel's alternates view, the first cell shows the plain form of the character, and clicking it is meant to put that plain form back. That worked when the alternate had been applied to the selected text itself, but not when it came from the block — a Typography Stylist block with Swashes turned on in its sidebar, say — because the plain form was inserted with the block's own features written onto it, so the swash stayed. The base cell now switches off the features that produce alternates for that character on the text it inserts, keeps the block's other features, and the change carries through to the published page. Applies in the Typography Stylist block and in the inline editor on regular headings and paragraphs. The feature toggles in both editors can also undo it: the Typography Stylist block's toggle now shows as off for that text instead of repeating the block-level state, and switching the feature back on takes effect, where before the "off" setting written by the panel silently won (the same precedence also made it impossible to switch off a feature the panel had written into a glyph's raw settings, such as an indexed alternate; that works now too).
* **Fixed: the Glyphs Panel ignored a weight set on the text around your selection.** In a Typography Stylist block, selecting a letter inside a run you had made bold (or any other weight) opened the panel at the block's weight instead: every glyph was drawn in the wrong weight, and inserting one dropped a glyph into your bold headline that came out lighter than the text beside it. The panel now uses the weight the selected text actually renders at — a weight inherited from an enclosing run, and text made bold with the editor's own Bold button, which leaves no Typography Stylist weight behind at all — so the glyphs you browse match what you will get. The same state feeds other extensions, so anything else reading the current weight was affected too. (The inline editor on regular headings and paragraphs already resolved this correctly.)
* **Improved: the font menus are searchable.** Every font name in the menus is preceded by a small icon showing where the font came from — an uploaded kit, Adobe Fonts, a custom definition, or the WordPress Font Library. A dropdown jumps to what you type, but it only matches from the very beginning of an entry, so that leading icon meant typing a font name matched nothing at all: on a site with a hundred families the only way to reach one was to scroll the whole list. The font menus in the sidebar, the Quick Feature Toggles, and the inline editor are now search fields — type any part of a name, including the middle of it, and the list narrows as you go. Clicking still opens the full list to browse, the entry that clears a font back to your default is still at the top of that list, and the menus name themselves properly to screen readers now, which they did not before.
* **NEW: optional Glyphs and Paragraph Styles buttons in the block toolbar.** Both features were previously only reachable *through* another panel — the glyph browser sat behind the Typography Stylist popover's features section, and paragraph styles were a dropdown inside that same popover and the sidebar. Two new Options settings put them one click away instead. "Glyphs Toolbar Button" adds a Glyphs button beside the Typography Stylist button, in the Typography Stylist block and on regular headings and paragraphs; the panel opens on the font of whatever you have selected, replaces the selection with the glyph you pick, and keeps inserting after it as you click more. "Paragraph Styles Toolbar Button" adds a button to the Typography Stylist block that opens a browser showing every saved style **rendered in its own typeface** — real font, weight, letter spacing, and OpenType features, with sizes scaled into a readable range so a 64px display style still reads as larger than a 16px body style. Click a style to apply it. Both settings are **off by default**, so nothing changes in your editor unless you turn them on, and the buttons inside the existing panels stay exactly where they are.
* Fixed: the Paragraph Styles dropdown labelled every style's font "Default". It looked styles up by the wrong identifier and only searched uploaded font kits, so Adobe Fonts, custom font definitions, and adopted Font Library faces could never match. Style labels now name the actual font.
* **Fixed: the Glyphs Panel opened on the wrong font for text styled only by your theme.** A heading your theme sets in one of your fonts carries no plugin font of its own, so the panel had nothing to go on and silently loaded whichever font happened to be first in your list — you went looking for a swash and were browsing a different typeface entirely. The panel now resolves the font the text is actually rendering in, for both the toolbar button and the button inside the Typography Stylist panel, in the inline editor and the Typography Stylist block.
* **Fixed: text styled by your theme no longer loses its weight.** Themes make headings bold with CSS rather than a stored setting, and the plugin treated "no stored weight" as normal — so a bold heading quietly turned normal when converted to a Typography Stylist block, and a glyph inserted from the Glyphs Panel came out lighter than the headline around it. Both now use the weight the text is actually rendering at. This covers both conversion routes (the "Convert to Typography Stylist Block" button and the block menu's Transform to); a weight you set yourself still wins, and paragraphs keep whatever weight their theme gives them too.
* **Improved: the accessibility notice now appears at the top of the inline editor panel**, instead of below every feature control where you had to scroll past everything to discover that your selection had a problem. Its "Convert to Typography Stylist Block" action — the fix the notice is recommending — is now a button rather than a line of link text, in the notice and in the panel's standalone convert section.
* **NEW: the Glyphs Panel raises the same accessibility notice.** Opening the panel straight from the block toolbar skips the Typography Stylist panel, and with it the word-boundary check — so you could split a word by swapping in a glyph and never be told. The panel now shows the same warning at the top when your selection breaks a word, with the same one-click conversion to a Typography Stylist block (which closes the panel, since the conversion replaces the block it was pointed at).
* **Fixed: three settings did nothing when switched off.** "Disable Word Boundary Warning", "Inline Format: Add aria-label Attributes", and "Clear Button Confirmation" were passed to the editor as the text "0" rather than as false, and every non-empty string counts as true in JavaScript — so turning any of them off had no effect. All three now behave as their labels say. (The word-boundary warning had never been switchable at all: nothing in the editor read that setting.)
* **Fixed: applying a paragraph style to selected text no longer restyles the words around it.** Paragraph styles describe a whole paragraph, so the style browser applied them block-level — which meant styling one highlighted word also restyled every neighbouring word that carried no styling of its own. With text selected, the style now wraps just that text; with only a cursor it still applies to the whole block, and the browser says which it will do. Detaching follows the same scope.
* Fixed: the size labels in the paragraph style browser ("Fluid 20–48", "Fit ≤ 120px") were hardcoded English and could not be translated. They now go through the module's text domain, which also required giving its shared utility script its own script translations — those are registered per handle, not inherited from the editor script that depends on it.
* Developer: the toolbar-button click context now carries an `accessibility` object (word-boundary warning, whether conversion is available, and why not when it isn't), a `typost-convert-to-block` event lets an extension trigger the conversion its own UI offers, and `typost-apply-block-properties` accepts `applyTo: 'selection'` to scope a paragraph style to the selected text. See HOOKS.md.
* Developer: new `typost_editor_toolbar_buttons` JavaScript filter for adding block toolbar buttons (core renders them as real toolbar buttons so keyboard navigation is unaffected), plus `typost_admin_options_rows` / `typost_admin_options_checkboxes` PHP hooks for adding a single setting to the Options tab. See HOOKS.md.
* Changed: bumped the Glyphs Panel (1.3.0) and Paragraph Styles (1.2.0) module version constants so browsers pick up the updated module scripts.
* **NEW: choose what the Enter key does in a Typography Stylist block.** Pressing Enter in a Typography Stylist block has always added a line break and kept you in the same block — deliberate, because a multi-line headline should share one set of typography settings, but surprising if you expect the rest of the editor's behaviour. A new Options setting, "Enter Key in Typography Stylist Blocks", makes it a choice. It defaults to the existing line-break behaviour, so nothing changes unless you change it; turn it off and Enter splits the block like a core heading does, carrying the block's font, features, and spacing into the first half and starting a paragraph after it. Shift+Enter adds a line break either way, and existing content is untouched whichever setting you use. The Help tab now explains the difference between a Typography Stylist block and a regular heading, including how to add a line break inside a core heading (Shift+Enter) and how to merge a heading that has already split.
* **Fixed: "Convert to Typography Stylist Block" no longer disappears without explanation.** The inline editor hides the conversion when it genuinely cannot be performed — the block is locked, or its parent block restricts which blocks are allowed inside it — but since v2.0 it hid the action silently, which read as a missing feature rather than a constraint. The modal now says which of the two applies and names the parent block, so the fix (move the block out, or have the container allow `typost/block`) is obvious. The conversion is also offered for any eligible heading or paragraph now, not only when the accessibility notice about word boundaries appears.
* Developer: new `typost_can_convert_to_block` JavaScript filter for overriding that capability decision, and the Typography Stylist block's `splitting` support is registered server-side from the new option (see HOOKS.md).
* **Improved: the settings page no longer reloads.** Every action on Settings → Typography Stylist that used to end in a full page reload — uploading a font kit, adding an Adobe Fonts project or custom font definition, saving font edits, deleting a font, registering/removing fonts in the WP Font Library (single and bulk), bulk weight detection, and the Options/Accessibility/Clear Cache forms — now updates the page in place over the REST API. After a font change the font list, the Font Features preview-font selector (your selection is preserved), the deletion modal's replacement list, the Replacement Fonts tab, and the @font-face/--font-N CSS all refresh together, so nothing on any tab goes stale; newly uploaded fonts are previewable immediately. Changing the admin color scheme restyles the page live. Extension hooks are unaffected: the refreshed fragments are server-rendered through the same template functions (badges, per-font axis rows), and the typost:font-saved / typost:fonts-added waitUntil contract is preserved — extensions' saves still complete before the refresh. Every update is announced to screen readers through polite aria-live regions, keyboard focus is kept anchored when the list under it is replaced, and the forms keep working without JavaScript via their original POST handlers. Also fixed: the Options and Accessibility checkboxes read stale option names, so their displayed state never reflected previous saves.
* **NEW: Fit-to-width blocks can be saved as Paragraph Styles.** Saving a style from a block in Fit to width mode now captures the full fit look as a first-class style property: the fit mode itself, the maximum-size cap, and the fallback sizes. Applying the style to another Typography Stylist block switches it into fit mode and re-measures its own lines (per-line sizes are content-specific and never copied). The style's CSS now also emits the fluid fallback size for fit styles, so browsers without container-query support get fluid sizing instead of the inherited theme size — this also restores the fallback for styled fit blocks, which previously lost it. The Paragraph Styles admin tab shows these styles as "Fit to width (fallback X–Ypx)" instead of the garbled "fitpx". In the inline editor (headings/paragraphs), where fitting to a block width has no meaning, applying a fit style renders the style's fluid fallback size; the Font Size dropdown states this plainly with a "Fit to Width (blocks only)" entry instead of showing a wrong value.
* **Fixed: the editor now renders a Typography Stylist block's font when only the numeric font ID is stored.** The block records its font twice — a numeric ID and a family-name string — and the editor preview required the string while the frontend required the ID. Blocks created through the editor UI always carry both, but content authored programmatically (builders, migrations, scripted imports) typically stores just the ID: the frontend rendered it correctly while the editor silently fell back to the theme's own heading font, and — worse — a Fit-to-width block edited in that state would have measured its line ratios against the wrong font. All three editor paths (the visual preview, the fit measurement, and the OpenType feature preview buttons in the Quick Feature Toggles) now resolve the font exactly like the frontend does: numeric ID first, family-name string as the fallback.
* Fixed: changing the font of styled text in a Typography Stylist block's Quick Feature Toggles no longer leaves a stale legacy family-name attribute (data-font) on the span. Spans created before v1.1.6 (and Glyphs Panel cross-font insertions) carry the family name alongside the numeric font ID; only the ID was updated on font changes, so previews could render the old font and frontend font detection could load it unnecessarily. The stale name is now removed on any actual font change, while same-font re-applies and non-font edits (weight, spacing, line height) leave it untouched.
* **Fixed: paragraph styles now save the Font Style (italic) setting.** Saving a style from text you had made italic with the Font Style control quietly dropped the italic: the style captured the font, size, weight, and spacing, but not the style itself, so the text applied everywhere that style was used came out upright. Font style is now a full member of a paragraph style — captured on save, shown on the style's card in Settings, rendered by the style's CSS on the frontend, and compared for the "(modified)" badge. Applying a style that has no font style of its own now also clears an italic previously set with that control. Emphasis added with the editor's own Italic button is a separate, semantic thing: it stays italic through style changes, and saving a style with the cursor in emphasized text does not quietly bake italic into the style. Styles saved before this fix don't know about italic yet — apply the style, set the Font Style again, and use "Update Style" to bake it in.
* **Fixed: text no longer loses its formatting in the editor right after you save or update a paragraph style.** Saving a style hands the styled text's rendering over to the style's CSS class — but that CSS was only generated when the page loaded, so a style created or updated mid-session had no rules in the editor yet and the text snapped back to the theme's plain defaults until you reloaded. (Your content was never affected — the frontend always rendered correctly on the next load, which made the editor's wrong preview extra confusing.) The editor now generates the style's CSS the moment a style is saved or updated, so what you see after saving is the style you just saved.

= 2.2.3 =
* **NEW: Per-selection relative size and vertical shift inside Fit-to-width blocks.** Two new sliders in the Quick Feature Toggles, shown only while the block uses Fit to width sizing: Relative size scales the selected text against its fitted line (10–100%), and Vertical shift nudges it up or down in em — so the wedding-invitation ampersand can sit small and optically centered between the names. Unlike absolute inline font sizes (which fit mode ignores because they would break the measured width ratio), these em-relative adjustments scale linearly with the line: the fitted line still fills the block width exactly at every viewport size, the scaled selection is included in measurement, and every change re-measures automatically. Vertical shift moves the glyph without changing its width, so it needs no re-measurement at all. Stored as data-fitscale / data-fitshift attributes with plain inline CSS on the styled span — zero frontend JavaScript, and the screen-reader heading is untouched. A scaled or shifted glyph swapped for an alternate in the Glyphs panel keeps its adjustments.

= 2.2.2 =
* **NEW: Fit-to-width sizing.** The Typography Stylist block gains a third font-sizing mode alongside Inherit and Responsive: each line of the block (split on line breaks) is sized so its text spans the full block width — the classic wedding-invitation/poster look where a short line renders huge and a long line renders smaller, all flush to the same width. The editor measures each line with its real fonts, weights, letter spacing, and OpenType features (swashes and ligatures change widths) and stores per-line ratios; the frontend renders with CSS container-query units and stays zero-JavaScript. Lines never wrap in this mode, inline font sizes on selections are ignored (the block controls sizing), an optional maximum-size cap stops short lines growing enormous on wide screens, and browsers without container-query support fall back to the responsive clamp() sizes. Automatic optical sizing is disabled on fit lines — fonts with an opsz axis (like Fraunces) change glyph widths with the rendered size, which would break the measured fit; setting the optical-size axis to a fixed value with the variable-font sliders still works. Editing is fully WYSIWYG in a single view: each line renders at its own fitted size while you type — the poster layout stays live as you edit — and Quick Feature Toggle changes (line height, fonts, features) preview and land on selections at their true rendered sizes. Under the hood the editor feeds RichText a per-line-wrapped copy of the content while the stored markup stays flat, so selections, the native formatting toolbar, undo, and paste all keep working unchanged. Existing blocks are untouched: non-fit save output is byte-identical, with a save deprecation as a safety net.
* Fixed: variable-font axis sliders in the Quick Feature Toggles now change only the selected text instead of restyling the whole block. The axis panels read their starting values from the selection but wrote changes to the block-level attribute — selecting one line and moving a slider restyled every line. QFT axis changes now land on the selection as a styled span (like the other QFT controls: with the caret in styled text they update that span in place; with no styled text they still fall back to the block attribute), while the sidebar Inspector sliders intentionally remain block-level. "Reset to defaults" removes the axis settings from the selection the same way.
* Fixed: an axis change (or any extension-applied block property) no longer applies to every Typography Stylist block on the page. The property-application event had no targeting, so every mounted block handled it; it is now handled only by the block whose Quick Feature Toggles modal is open (or, for sidebar events, the selected block).
* Fixed: the variable-font axis panels now initialize from the selection inside the iframed editor canvas (WordPress 6.3+). They walked the top document's selection, which cannot see block content in the iframe; the host editor now hands them the selection's axis values directly.
* Fixed: fonts registered in the WP Font Library (WordPress 6.5+) no longer lose their webfont on the frontend. The plugin skipped its own @font-face for every registered font on the assumption that WordPress prints those faces — but WordPress only prints faces for fonts activated in global styles, so registered-but-unactivated fonts (including every auto-registered upload) silently rendered with a local or system fallback while the editor looked correct. The plugin now checks what WordPress will actually print (merged theme.json families) and keeps emitting its own @font-face whenever the family isn't there; activating the font in the Site Editor still hands printing over to WordPress with no double output.
* Improved: the "Detect Axes from Font File" server fallback now reports the actual failure reason instead of a generic error.
* Developer: font-variation-settings values arriving through the typost-apply-block-properties extension event are validated on every apply path (invalid values are treated as empty, never partially applied into a style string).
* Changed: bumped the Variable Fonts module version constant (1.3.1) so browsers pick up the updated module scripts.
* Improved: the Glyphs panel can now be repositioned by dragging its title bar, matching the Quick Feature Toggles modal — useful when the panel covers the text you're inserting into.
* Fixed: choosing an alternate glyph is now reversible — clicking the base glyph in the Glyphs panel's alternates view restores the plain character. Previously the base glyph was inserted as plain text that inherited the very alternate being removed (an ampersand swapped for its "and" alternate could never be swapped back), and because the caret collapsed after each insertion, every retry appended another copy instead of replacing. Alternates-view clicks now keep the inserted glyph selected so consecutive picks swap in place, and base-glyph clicks explicitly clear the alternate while keeping the surrounding font, weight, and spacing. Extensions get the same powers via a new `swap` flag on the `typost-insert-content` event (see HOOKS.md).
* Changed: bumped the Glyphs Panel module version constant (1.2.2) so browsers pick up the updated module scripts.
* Fixed: fonts uploaded together in one ZIP no longer share each other's variable-font axes. Every font family extracted from a kit points at the same kit directory, and axis detection scanned that whole directory — so each family was assigned the axes of whichever font file happened to parse first. A ZIP containing EB Garamond (weight axis only) and Fraunces (optical size, SOFT, WONK, weight) gave Fraunces a lone weight slider and hid its custom axes, and gave non-variable fonts in the same ZIP a phantom weight slider in place of their real weight dropdown. Detection is now scoped to the font files each family's own @font-face rules reference, with the file path confined to the kit directory (kit CSS arrives inside an uploaded ZIP, so it is untrusted input). Fonts uploaded on their own were never affected.
* Improved: "Detect Axes from Font File" is now the way to repair fonts whose axes were mis-detected before this fix. It gained a server-side fallback that re-reads uploaded fonts with the corrected detection, so it still works when the in-browser font parser is unavailable. The browser is tried first because it can read real axis names out of the font ("Softness" rather than "SOFT") and can decompress WOFF2, which PHP cannot. Re-detection returns the axes for review; nothing is stored until Save Changes.
* Added: the detect button now says up front that it replaces every axis row and discards hand-set axis names, ranges, and defaults, and asks for confirmation before overwriting axes that are already defined. Detecting axes for the first time is still a single click.
* Changed: variable-font axis sliders now sit directly beneath the weight control in the inline editor and the Quick Feature Toggles, matching the block sidebar. Font Style previously came between them, separating the axis sliders from the weight they extend.

= 2.2.0 =
* Fixed: converting a styled heading or paragraph to a Typography Stylist block no longer destroys inline styling. The inline editor's convert button rebuilt the block from plain text whenever the selection crossed styled-span boundaries — exactly the selections that surface the convert option — wiping per-letter glyph alternates, swashes, fonts, and weights; it now applies the popover's settings over the existing markup with every surrounding span preserved (and on any failure converts with the content untouched rather than ever rebuilding from text). The block-menu transform's feature-extraction path is now guarded the same way: features are only lifted to block level when the spans carry nothing else that stripping them would silently delete. Converted spans also use the modern font-ID format so frontend font loading works.
* **NEW: Font Style (visual italic) controls.** All three editing surfaces gain a Font Style setting — block-level in the Typography Stylist block sidebar, per-selection in its Quick Feature Toggles, and per-selection in the inline editor for regular heading and paragraph blocks — selecting the font's italic (or upright) face. This is deliberately style-only: it never adds emphasis semantics, and the control says so — for semantic emphasis that screen readers announce, use the editor's own Italic button, which continues to work as before. Ideal for display typography where italic is a design choice, not emphasis.
* Fixed: feature previews now render with the italic face when the selection is italic — whether via the editor's Italic button (em), the new Font Style setting, or an italic styled span. Previously previews always showed the roman face, hiding italic-only glyphs like EB Garamond's swash italic capitals.
* Improved: the Glyphs Panel now browses the face variant actually rendering at your selection. Select italic text (via the Italic button or the Font Style setting) and open the panel: it loads the font’s italic file — with its own glyph set and features, like swash italic capitals — and renders every cell in that face. No toggle needed; the selection decides.
* Fixed: moving one variable-font axis slider no longer changes other axes. The axis panels emitted every axis on any change — including untouched axes pinned to the font file's built-in defaults, which differ from normal rendering (Fraunces' built-in weight default is 900, so nudging its WONK slider turned text bold). Only axes the author has actually adjusted (or that were already applied to the text) are written into font-variation-settings; "Reset to defaults" now returns axes to natural rendering instead of pinning them.
* Fixed: the variable-font Weight slider in the Quick Feature Toggles now works — it identified its context with a selector that matched nothing, dispatched to the wrong editor, and was silently dropped. The weight slider and the custom-axes panel also now share one axis session, so weight and custom-axis adjustments combine instead of overwriting each other.
* Changed: bumped the Variable Fonts module version constant (1.3.0) so browsers pick up the updated module scripts.
* Fixed: Quick Feature Toggle changes always land on the selected text. The per-setting apply paths read the live editor selection, which the popover itself can collapse by taking focus — toggles then silently applied block-wide (or not at all) despite an active selection. All appliers, clear/reset actions, and the settings-detection now share one selection resolver that falls back to the selection captured when the popover opened.
* Fixed: applying a font or feature over a whole span no longer wipes glyph alternates chosen from the Glyphs Panel — the rebuilt font-feature-settings honors raw indexed alternate values (e.g. a 2nd stylistic alternate) instead of flattening them, in both the apply and the feature-removal paths.
* Fixed: changing the font of styled text now clears variable-font axis values carried over from the previous font (axis settings are font-specific) — in whole-span merges and partial-selection splits alike.
* Fixed: splitting a styled span (partial-selection changes) corrupted spans whose attributes or styles contain double quotes — variable-font axis values and glyph alternates — because attribute values were not escaped when rebuilding the markup.
* Changed: the 3-level limit on nested styled spans is now enforced on every application path — previously one fallback path could exceed it. Applying to a fully-selected span merges in place regardless of depth, so existing deeply-nested content remains editable.
* Developer: span styling internals consolidated — one canonical style-string parser/builder (parseStyleString/buildStyleString), one shared whole-span merge (mergeTypostSpanStyling), and one QFT selection resolver, replacing seven copy-paste variants (see todo/refactor-style-string-helpers.md).
* Fixed: font (and other single-value) changes over multi-span selections in the Typography Stylist block's quick toggles now actually take effect. Applying a font to a selection containing styled spans wrapped them in a new span whose font-family every inner span overrode — the change looked like it did nothing, and repeated attempts deepened the nesting. The wrapped property is now removed from descendant spans so the new value renders throughout (their other settings are untouched), applied feature tags merge into descendants that declare their own feature settings, and descendant spans left with nothing are unwrapped.
* Fixed: changing one setting over a mixed selection in the inline editor no longer wipes the others. Selecting text that contained differently-styled spans (different features, sizes, or fonts on parts of the selection) and then changing any single setting — font family, weight, size, spacing, line height, or a feature toggle — replaced the entire selection with one uniform span built from the popover's controls, destroying every per-part setting. The editor now detects mixed selections and applies only the changed property to each styled run: a font change re-fonts everything while each part keeps its own features and sizes, and a feature toggle adds to (or removes from) each part's own feature set. Uniform selections and presets behave as before.
* Fixed: feature previews in the inline editor now render in the selection's actual font. Spans written since v1.1.6 carry only a numeric font ID (no legacy data-font family name), which the preview resolution didn't consult — previews silently fell back to the block's theme font. Affected any span created by the Typography Stylist block's quick toggles or built programmatically, including the wp.org Live Preview demo headline.
* Fixed: inserting a glyph from the Glyphs Panel no longer loses the surrounding span's styling. Swapping a selected letter for a feature glyph replaced its typost span outright, dropping font size (fixed and responsive), letter spacing, and line height — the inserted letter landed at the default size. Insertion now merges the replaced span's styling into the new glyph's span (the glyph's own feature, font, and weight still win), and glyphs swapped at the very start of a span no longer inherit formatting from the text before the span.
* Improved: the Glyphs Panel now opens straight to the selected text's alternates. A selected letter pre-fills the "Alternates for character" box; a short combination (up to 4 characters, e.g. "Th") shows its exact ligature alternates, falling back to the first letter's alternates when the font has no such ligature. Longer selections still open the full glyph grid, and the "All glyphs" button returns to it at any time.
* Changed: bumped the Glyphs Panel module version constant (1.2.1) so browsers pick up the updated module scripts.

= 2.1.2 =
* **NEW: automatic font-weight detection.** Newly uploaded font kits and newly added Adobe Fonts get their "Available Font Weights" checkboxes pre-set to only the weights the font actually ships, instead of all nine weights being enabled by default. Uploaded kits read the weights from their parsed (or generated) @font-face rules; Adobe Fonts read them from the kit stylesheet, fetched server-side when the project is added. WordPress Font Library fonts adopted from the editor picker carry their real weights too. Variable fonts covering the full 100–900 range keep all weights enabled (the weight slider replaces the dropdown anyway). Detection only ever narrows when it is confident — if the stylesheet can't be fetched or a kit can't be read, all weights stay enabled — and the checkboxes remain fully editable.
* New: one-click "Auto-detect weights for existing fonts" button on the Custom Fonts tab. Shown only for fonts added before weight detection existed that were never manually configured; it processes uploaded and Adobe fonts in one pass and disappears once every font is covered. Manual font definitions are skipped — there is no font file to read.
* Fixed: the Glyphs Panel reported "No readable font file is available" for variable fonts uploaded as font-only ZIPs — the generated @font-face CSS declares `format('truetype-variations')`, which the panel's file picker didn't recognize. Variable-font format hints now normalize to their base format, so variable fonts glyph-browse like any other uploaded font.

= 2.1.1 =
* Packaging: re-release of the 2.1.0 feature set under a fresh version number. The 2.1.0 tag's downloadable ZIP was cached against stale contents and never delivered the new files (Variable Fonts core integration, font metadata/sources modules, WordPress Font Library integration); 2.1.1 ships them correctly. See the 2.1.0 entry below for the full list of changes included in this release.

= 2.1.0 =
* Fixed: deleting an uploaded font now also removes its WordPress Font Library registration — previously the wp_font_family post survived the delete, kept printing @font-face rules for font files that no longer existed, and made the font appear to still be installed. Removal is ownership-guarded: only families the plugin itself registered are ever touched.
* Fixed: fonts registered in the WordPress Font Library no longer appear twice on the Custom Fonts tab (once as an uploaded font card and again in the read-only WP Library rows). The uploaded card with its "In WP Library" badge is now the single listing; genuine Library fonts — including orphaned registrations from older versions — remain visible.
* Removed: the required "Font Kit Name" field from the Upload Font Kit form. The name was stored but never displayed anywhere — font cards show the family names read from the kit. The REST endpoint still accepts an optional `name` and defaults to the ZIP filename, so API callers keep working.
* **NEW: font-only ZIPs (no CSS) are now accepted by Upload Font Kit.** Uploading a ZIP that contains just font files — e.g. a Google Fonts download — no longer fails with "No CSS file found in the font kit". The plugin reads each font's built-in metadata (name, OS/2, and fvar tables for TTF, OTF, and WOFF files) and generates the @font-face stylesheet automatically: correct family names, weights, italics, and for variable fonts a font-weight range with the matching format('…-variations'). Generated kits flow through the existing pipeline unchanged, including variable-font axis detection, the Variable card badge, and the editor weight slider. WOFF2 metadata cannot be read server-side, so WOFF2-only ZIPs fall back to filename-based detection and the upload shows a "review the generated font styles" warning. Kits whose CSS files contain no @font-face rules get the same fallback.
* **NEW: WordPress Font Library integration (WP 6.5+).** Uploaded webfont kits can now be registered in the WordPress Font Library (Appearance → Editor): newly uploaded fonts register automatically (toggle in Options), and existing fonts can be registered per font or in bulk from the Custom Fonts tab — registration is opt-in and fully reversible. Registered fonts keep their numeric IDs: the plugin's `--font-N` CSS variables alias to WordPress's `--wp--preset--font-family--{slug}` presets with a literal fallback, so all existing content, inline spans, and extension integrations keep rendering forever, even if a font is later removed from the Library. WordPress serves the font files for registered fonts (no double-loading). Adobe Fonts and custom font definitions remain plugin-managed by design (Adobe fonts load from Adobe's servers and may not be self-hosted).
* **NEW: WordPress Font Library fonts in the editor font pickers.** Both the inline editor and the Typography Stylist block now offer Library fonts (theme fonts and fonts installed via Appearance → Editor) in a dedicated picker group. Picking one adopts it seamlessly — it gets a numeric font ID like every other source, so the save format and all extensions work unchanged.
* **NEW: Variable font support.** Automatic axis detection on upload, per-axis admin configuration, and axis sliders in the editor — weight, width, slant, optical size, and any custom axes a font defines.
* **NEW: `typost_force_enqueue_font_ids` filter** — themes and extensions can force specific fonts to load on every page (for fonts referenced only from theme CSS, invisible to the content scan).
* Improved: extension data saves on the font edit form no longer race the page reload (`typost:font-saved` now provides a `waitUntil()` collector).
* Fixed: the per-page font CSS cache key now includes the used font IDs, so pages using different fonts can no longer share stale cached CSS.
* Fixed: font CSS variables now load inside the iframed block editor canvas (WP 6.3+) even when no uploaded webfont kits exist — Adobe Fonts, custom font definitions, and Font Library fonts previously fell back to the system font in the editor while rendering correctly on the frontend.
* Improved: the Glyphs Panel now distinguishes missing or failed parsing-library loads from genuinely unreadable fonts, shows honest error messages with technical detail, and offers a "Try again" button that retries without reloading the page.
* **NEW: "Detect Axes from Font File" button** — each font's Variable Font settings can now read the axis definitions (tag, name, min/max/default) straight from the font binary in your browser, instead of typing them by hand. Works for uploaded kits, Adobe Fonts, and custom font definitions, including WOFF2 files that upload-time detection can't parse. Detected axes fill the form for review; nothing is stored until you save.
* Improved: variable fonts without a weight (`wght`) axis no longer show the standard Font Weight dropdown in the editors — the variable axis sliders take its place (matching the per-font "Hide weight selection" admin setting, which previously only affected the admin form).
* Fixed: the "Variable Font Axes" section in the inline editor pop-up now has the same left/right padding as the other sections.
* Developer: the `typost_weight_control` JS filter recognizes a new `'hidden'` return value (suppress the weight control entirely), and the `typost_qft_after_font_controls` hook state now includes `inlineFontFamilyAtSelection` — see HOOKS.md.
* Fixed: extension panels rendered into font-dependent hook points (e.g. the Variable Font axis sliders) no longer go stale when the font is changed — the hook containers now remount with fresh state on font switch instead of keeping the previous font's controls.
* Improved: Variable Font quick-select buttons for custom axes now snap to round values (200, 400, 600 instead of 201, 401, 601) and are capped at 7 buttons so they fit on a single row; near-duplicate values next to the axis default are no longer generated.
* Added: variable font axes are now detected automatically when fonts are added — both webfont kit ZIP uploads and Adobe Fonts kits. Each family in a kit is checked individually, so kits mixing variable and static fonts work correctly; static families are simply left untouched.
* Fixed: axis detection (and glyph loading) for Adobe Fonts kits containing multiple families could resolve the wrong family's font file — per-family entries store a single family name, which the font loader now honors.
* Developer: new `typost:fonts-added` jQuery admin event fires after a kit upload or Adobe Fonts add, with the new entries and a `waitUntil()` collector so extensions can post-process fonts before the page reloads — see HOOKS.md.
* Fixed: a variable font with a weight (wght) axis but "Hide weight selection" unchecked showed the weight slider until the first edit, then inconsistently swapped to the weight dropdown. The unchecked setting now consistently keeps the standard weight dropdown (the wght slider is skipped); other variable axes still show in their own panel.
* Changed: "Hide weight selection" now defaults to checked for every variable font — when a weight (wght) axis exists the slider replaces the weight dropdown, and without one the weight is fixed by the font file, so the discrete weight UI is hidden either way. An explicit admin toggle still wins. Previously the auto rule only hid weights for variable fonts without a wght axis, leaving the redundant weight controls visible for exactly the fonts that least need them.
* Changed: bumped the Variable Fonts (1.2.1) and Glyphs Panel (1.1.2) module version constants so browsers pick up the updated module scripts (these files ship unminified and are cache-busted only by those constants).
* Accessibility: the Variable Fonts axis Tag and Name inputs on the settings page now have accessible labels (fixes 10 "missing form label" WAVE errors).
* Accessibility: color-contrast audit of all admin color schemes. Alice Blue's primary and muted-text colors were darkened to meet WCAG AA 4.5:1 on every panel background (feature code badges, size values, descriptions, visibility labels); the Dark scheme's badge text and danger color were corrected; High Contrast's danger red was darkened; and the Admin Colors scheme now automatically darkens colors derived from the WordPress admin palette until they meet 4.5:1.
* Accessibility: fixed heading hierarchy on the settings page — font card names are now h3 (previously h4 directly under the tab's h2).
* Changed: the read-only Variable Fonts admin tab was removed. Variable fonts are now marked with a "Variable" pill on their font cards (hover it to see the configured axis tags), alongside the existing source badges — the same information, in context. Axes are still managed in each font's edit form.
* Developer: new `typost_font_card_badges` PHP filter lets extensions append badges to font card headers on the Custom Fonts tab — see HOOKS.md.
* Improved: WP Font Library cards now render the font name in its own typeface (when font files are registered; @font-face CSS is printed via wp_print_font_faces on WP 6.4+), and the font-family code chip no longer touches the "Manage in Editor" button. The chip also follows the admin color scheme instead of hardcoded grays.
* Changed: the Quick Feature Toggles popover now shows the same two-line usage tips notice as the inline popover (drag-to-reposition + instant-apply/undo) and shares its dismissal — closing the notice in either popover hides it in both, remembered per browser.
* Changed: the "i" icon tooltips in the block sidebar and inline popover were replaced with plain help text (matching the line-height controls) or removed. The Font Family tip claiming "fonts only load on pages where they are used" was removed as inaccurate for WordPress Font Library fonts, which WordPress loads site-wide; the Font Size clamp() explanation now appears as help text when Responsive mode is selected; the OpenType overview is now a regular note at the top of the features panel.
* Removed: the required "Project Name" field from the Add Adobe Fonts Project form — since kits create one entry per family (named by the family), the project name was stored but never displayed anywhere.
* Fixed: the Glyphs button in the inline Typography Stylist popover now aligns with the section headings instead of sitting flush against the popover edge.
* Changed: the collapsible Tips list at the bottom of the inline popover was removed; its one non-obvious tip ("Changes apply instantly, press Ctrl+Z to undo") joined the drag-to-reposition tip in the notice at the top of the panel. The notice is now dismissible, and the dismissal is remembered per browser. The other tips duplicated information available elsewhere.
* Fixed: when a kit contains several variable fonts, the automatic axis detection could silently lose the first font's result — the per-font saves ran concurrently against a REST endpoint that does a read-modify-write on a shared option, so the earliest write was overwritten by the others. Axis saves are now serialized, so every detected font's axes persist.
* Developer: new block attribute `animationConfigId` + inline `data-animation-id` attribute as integration points for the upcoming Animations extension; font subsystem partially extracted into `includes/` modules (public extension API unchanged).

= 2.0.1 =
* Fixed: Mixed-content blocking of locally-hosted fonts in the Glyphs Panel — same-host `http://` font file URLs are now upgraded to `https://` before fetching, so fonts whose stored kit CSS contains absolute insecure URLs load correctly on HTTPS sites (cross-origin URLs are left untouched)

= 2.0.0 =
* **NEW: Glyphs Panel (built into core) — the flagship feature of 2.0.** An Illustrator-style full-font glyph browser. Explore every character and OpenType feature in a font; search by character, U+ codepoint, or glyph name; filter by Unicode block, stylistic set, or OpenType feature; and view all alternates for a single character. Click or press Enter to insert any glyph (including indexed feature alternates) directly into your content via a "Glyphs…" button in the inline rich-text toolbar (any heading or paragraph), in the Typography Stylist block's Quick Feature Toggles, or from a dedicated "Glyphs" admin tab (browse + copy to clipboard); closing the panel returns you to the editor popover you launched it from. Accessible by design: the glyph grid is a fully keyboard-navigable ARIA grid (arrow keys, Home/End, Page Up/Down, Enter to insert) with row/column semantics, and insertions and result counts are announced to screen readers — inserted glyphs use the real Unicode character plus CSS font-feature-settings, so assistive technology always reads the underlying text. Works with uploaded webfont kits, Adobe Fonts, custom font definitions, and WordPress Font Library fonts; font files are read in your browser, on demand, for metadata only — no glyph outlines are ever extracted or stored, and nothing font-derived is written to your server, making sure you respect font EULAs.
* **MAJOR CHANGE:** Inline text editor (richtext toolbar button) now uses live preview instead of Apply button paradigm - changes are auto-applied immediately with debouncing (matching the Typography Stylist block UX)
* **NEW: Extensibility hook system** - Comprehensive PHP and JavaScript hooks enabling third-party extensions via standalone WordPress plugins
* **NEW: Admin tab extensibility** - Data-driven admin settings tabs with filter-based registration for extensions to add their own configuration tabs
* **NEW: JavaScript hook system** (`window.typostHooks`) - Lightweight action/filter system for both the inline editor and Typography Stylist block, with container-based hook points for rendering extension UI
* **NEW: Per-font OpenType feature visibility** - Configure which of the 51 OpenType features appear in the editor on a per-font basis; defaults to all features visible for full backward compatibility
* **NEW: Unified font list** - All font sources (uploaded kits, Adobe Fonts, custom definitions, WP Font Library) now appear in a single organized list with color-coded type badges instead of three separate sections
* **NEW: Drag-to-reorder fonts** - Drag fonts up and down the list to control the order they appear in editor dropdowns; order is persisted via the REST API
* **NEW: WordPress Font Library integration** - Fonts registered through the WordPress Font Library (WP 6.5+) now appear in the Custom Fonts admin list as read-only entries with a link to manage them in the Appearance Editor; gracefully absent on older WordPress versions
* **NEW: Font name preview** - Font names in the Custom Fonts admin list now render in their actual typeface using CSS variables, making it easy to identify fonts at a glance
* **NEW: Card width slider** - Adjustable preview card width (280–800px) in the Font Features tab, persisted per-browser via localStorage
* **NEW: Contextual help panels** - Collapsible help panels added to each admin tab (Custom Fonts, Font Features, Options, Accessibility, Replacement Fonts) explaining what each section does and how to use it
* **NEW: Block editor Help & Tips panel** - A collapsible "Help & Tips" inspector panel in the Typography Stylist block explains when to use block vs. inline styling, accessibility features, and font selection guidance
* **NEW: Contextual tooltips** - Info tooltips on key block editor controls (font family, font weight, font size, letter spacing, line height, OpenType features) using WCAG-compliant `<Tooltip>` + `<Button>` pattern; keyboard focusable with screen reader support
* Added: `typost_editor_data` filter for extensions to add data to the block editor
* Added: `typost_editor_assets` action for extensions to enqueue editor scripts
* Added: `typost_admin_tabs` filter for registering custom admin settings tabs
* Added: `typost_admin_localize_data` filter for extensions to add admin page data
* Added: `typost_admin_assets` action for extensions to enqueue admin scripts/styles
* Added: `typost_register_rest_routes` action for extensions to register REST API endpoints
* Added: `typost_available_features` filter for modifying the available OpenType features list
* Added: `typost_presets` filter (replacing legacy `typost_default_presets`) for modifying the combined presets list
* Added: `typost_cache_clear` action for extensions to clear their caches when core clears
* Added: `typost_font_uploaded` and `typost_font_deleted` actions for font lifecycle events
* Added: `typost_admin_tab_content_{id}` and `typost_admin_tab_after_{id}` actions for admin tab content
* Added: 5 inline editor hook points, 4 Quick Feature Toggle hook points, 3 Inspector Controls hook points
* Added: State communication pattern via `typost_current_editor_state` filter and `typost-apply-block-properties` CustomEvent
* Added: HOOKS.md developer documentation with vanilla DOM and React extension examples
* Added: Blueprint specification for the Variable Font Axes extension
* Added: REST endpoints for font feature visibility (`GET/POST /typost/v1/font-feature-visibility/{font_id}`) and font order (`GET/POST /typost/v1/font-order`)
* Added: `filterFeaturesByVisibility()` utility function (exported from utils.js and exposed via `window.typostSharedUtils`) for filtering features based on per-font visibility settings
* Fixed: Editor nonce was incorrectly cached in transient (nonces are session-specific and must always be fresh)
* Fixed: Help tab section headers now use the primary text color instead of the accent color, fixing low contrast in the Alice Blue admin color scheme (WCAG-compliant across all schemes)
* Fixed: REST API namespace in bundled documentation corrected to the canonical `/wp-json/typost/v1/`
* Removed: Apply button from inline editor toolbar
* Removed: "Apply Anyway" and "Discard Changes" buttons from the word boundary accessibility warning workflow — these warning-specific actions are now obsolete because the warning is non-blocking and changes apply immediately via live preview
* Removed: Internal undo system (Undo button) - now relies on native WordPress undo (Ctrl+Z)
* Removed: Redundant preview panel with device toggles - live preview on actual selected text makes it unnecessary
* Removed: Separate Uploaded Fonts, Adobe Fonts, and Custom Font Definitions sections — replaced by unified font list
* Changed: Word boundary accessibility warning is now a persistent, non-blocking informational notice at top of modal instead of blocking application; it remains visible while editing but does not prevent changes and can effectively be dismissed by proceeding with edits or converting to a Typography Stylist block
* Changed: Users can still choose to convert to a Typography Stylist block for improved accessibility when needed, but this is now an optional follow-up action rather than a requirement to proceed
* Changed: Admin settings tabs are now data-driven with priority-based ordering (supports URL deep-linking via `?tab=` parameter)
* Changed: Add Font forms (upload kit, Adobe Fonts, custom definition) are now grouped in a collapsible accordion section beneath the font list
* Changed: Feature visibility is editor-UI-only — already-applied features in saved content continue to render correctly regardless of visibility settings
* Improved: Inline editor now matches Typography Stylist block UX with consistent debounce timings: Features (instant), Sliders (400ms), Dropdowns (300ms), Responsive Font-Size (600ms)
* Improved: User can still manage accessibility settings in Settings → Typography Stylist → Accessibility
* Improved: Font Features tab preview selector now includes WP Font Library fonts (when available) alongside uploaded, Adobe, and custom fonts
* Improved: Feature visibility changes auto-save on toggle with a brief "Saved" confirmation — no Save button needed
* Improved: Per-font feature visibility includes master "Enable All" / "Disable All" controls both on the Font Features tab and inside each font's edit form
* Improved: Glyphs Panel toolbar controls (Alternates, Search, OpenType feature, Unicode block) now show visible labels
* Improved: Glyphs Panel default "All glyphs" view also lists OpenType feature variants (e.g. stylistic alternates) previously reachable only by filtering or typing a character
* Note: Each debounced change creates its own undo step in WordPress undo history - use Ctrl+Z to undo individual changes (more granular than previous single Apply button undo)
* Note: WP Font Library fonts appear in the admin list as read-only; font order and feature visibility settings for WP Library fonts are not yet supported in this release

= 1.2.2 =
* Added: Re-introduced "Apply Anyway" button in the word boundary accessibility warning when applying features to partial words in core blocks, giving users the choice to proceed despite potential screen reader fragmentation
* Added: Smart conversion detection - the "Convert to Typography Stylist Block" button is automatically hidden when conversion is not possible (e.g., inside a locked pattern), with an adjusted warning message
* Added: Safety fallback - if block conversion fails despite the pre-check, features are applied directly with a snackbar notice informing the user
* Added: "Disable Word Boundary Warning" option in Settings → Typography Stylist → Accessibility to skip the partial word warning entirely
* Added: "Manage this setting" link in the warning message that deep-links to the admin accessibility settings page, auto-switching to the Accessibility tab and highlighting the relevant setting
* Fixed: Nonce mismatch in Accessibility and Options settings forms caused "The link you followed has expired" error when saving - the nonce names in wp_nonce_field() and check_admin_referer() did not match

= 1.2.1 =
* Added: Per-font weight restrictions - configure which font weights are available for each font in the admin panel (Settings → Typography Stylist → Custom Fonts). Fonts default to all weights for variable font compatibility
* Added: Single-weight auto-apply - when a font has only one available weight, the weight selector is hidden and the weight is automatically applied
* Added: Weight validation on font change - switching fonts automatically adjusts the weight to the closest available option
* Fixed: CSS variable trailing comma caused fonts without fallbacks to fail loading on both frontend and block editor (e.g. `--font-20: "EsmeraldaPro", ;` produced invalid CSS)
* Fixed: Line breaks (Shift+Enter) in Typography Stylist blocks caused words to run together in screen reader text (e.g. "MILANOCORTINA" instead of "MILANO CORTINA")
* Fixed: Inline editor modal lost font selection state on close/reopen - selecting a font, closing the modal without applying, then reopening and clicking Apply would silently fail because stale state caused the apply logic to enter the wrong code path
* Fixed: Missing data-lineheight attribute in format type registration - line-height values were silently dropped when reading back existing formatted content
* Improved: Apply notice in the inline editor now includes a "Convert to a Typography Stylist block" link, guiding users toward the block type that supports real-time preview
* Changed: "Cancel" button renamed to "Discard Changes" in accessibility warning for clearer intent
* Changed: "Edit Fallbacks" button renamed to "Edit Settings" in admin font management to reflect expanded functionality
* Improved: OpenType feature previews now show cumulative checked features - toggling a stylistic set updates ALL preview windows to include that feature, accurately showing how features combine (essential for fonts like Bookmania where stylistic sets interact to produce different glyphs)

= 1.2.0 =
* Fixed: Inline styles applied to wrong character when content contains line breaks (Shift+Enter) - styling the "M" on a second line would incorrectly style the "I" instead, off by one character per line break
* Fixed: TreeWalker document context bug - TreeWalkers are now created from the correct document object (DOMParser), preventing cross-context errors
* Fixed: Responsive font-size Reset button now removes all related attributes (data-fontsize-min, data-fontsize-preferred, data-fontsize-max) instead of leaving orphaned attributes
* Fixed: Memory leak in debounced auto-apply functions - cleanup handlers now properly cancel pending debounced calls on component unmount
* Fixed: Preview span removal now preserves nested elements instead of flattening to text, maintaining complex formatting structure
* Fixed: Stale closure bug in auto-apply functions - debounced wrappers now call latest version of apply functions via refs, resolving issue where controls wouldn't work when styles were already applied
* Improved: Quick Features Toggle auto-apply - letter spacing, line height, font family, font weight, and font size now apply automatically with debouncing (400ms for sliders, 300ms for dropdowns, 600ms for responsive font-size)
* Improved: Consistent UX across all Quick Features controls - all controls now auto-apply like OpenType features, no more confusion about which controls need Apply buttons
* Improved: Clear/Reset buttons now actually remove properties from content instead of just resetting state - clicking Reset removes the data attribute and CSS property from spans
* Improved: UI reorganization - Active Features section moved above feature panels for better visibility
* Added: Individual Reset buttons for font family, font weight, and font size with undo icons for clear visual feedback
* Added: `buildTextOffsetMap()` utility that accounts for `<br>` elements in character offset calculations, matching WordPress RichText's offset system
* Added: `getEffectiveTextLength()` utility for accurate text length measurement including line breaks
* Added: `debounce()` utility function with cancel method for performance optimization during rapid slider adjustments
* Added: `removePropertyFromSpan()` utility to remove specific properties and unwrap empty spans
* Added: `removePropertyFromSelection()` utility to find and remove properties from all spans in selection
* Added: Comprehensive test suite with 24 tests for property removal utilities, including edge cases for responsive font-size
* Improved: All 12 TreeWalker-based offset calculations across the inline editor, Typography Stylist block, and shared utilities now correctly handle multi-line content
* Technical: Extracted `classifyAtomicNode()` helper within `splitSpanAndApply` to reduce code duplication in segment classification logic
* Technical: Debounced functions use refs to avoid stale closures and maintain access to current state across renders

= 1.1.9 =
* Fixed: Archive page font loading - fonts now load correctly and more consistently on blog home, category pages, tag pages, and all archive types
* Fixed: WordPress hook timing issue - font detection now runs on `template_redirect` hook (after main query) instead of `wp_enqueue_scripts` (before query) for archive pages
* Added: Manual cache clear button in Settings → Typography Stylist → Options tab for troubleshooting font loading issues
* Added: Admin setting to control archive page full content checking (enabled by default)
* Improved: Singular pages (posts, pages) continue using optimized detection path without changes
* Improved: Cache clearing when options are changed to ensure settings take effect immediately
* Improved: Font detection caches now automatically clear when posts or pages are saved, so typography changes appear on the frontend immediately
* Updated: Filter `typost_check_full_content_on_archives` now defaults to true (was false)
* Technical: Font detection results cached in instance variables to avoid redundant queries
* Note: Existing sites will automatically benefit from improved archive page font loading

= 1.1.8 =
* Improved: Windows Narrator focus enhancement - screen reader accessible headings now display a visible focus outline that corresponds to the full styled headline area, making it easier to identify which heading is being read

= 1.1.7 =
* Improved: Screen reader elements maintain full-size dimensions while remaining invisible, using modern clip-path technique with backwards compatibility for legacy browsers
* Added: High contrast mode support for Windows users with enhanced outline visibility (4px outline with system Highlight color)
* Added: Dark mode support with adjusted outline colors for better visibility on dark backgrounds
* Added: pointer-events management to prevent invisible overlay from blocking interactions with styled text when not focused


= 1.1.6 =
* Improved: Standardized control order across all interfaces for better consistency. Reordered controls to: Font Family → Font Weight → Font Size → Line Height → Letter Spacing → OpenType Features.
* Fixed: Font size persistence bug where changes wouldn't persist after closing Quick Features Toggle popover
* Fixed: All inline controls (font weight, font family, font size, letter spacing, line height) now correctly apply only to selected text instead of entire block (sporadic errors before)
* Fixed: Sequential feature application bug where applying multiple inline features would incorrectly affect entire block
* Fixed: State management issue where inline control values wouldn't reset after successful apply
* Fixed: Inline fonts (applied via Quick Feature Toggles) now load correctly on frontend
* Fixed: Font detection now properly extracts inline fonts from Typography Stylist block content HTML
* Fixed: Quick Feature Toggle preview now displays in correct inline font instead of block-level font
* Fixed: OpenType features now apply only to selected text, not entire span when selecting partial text within existing styled spans
* Fixed: Font-feature-settings CSS now preserved when applying other inline styles (line-height, letter-spacing) to text with existing OpenType features
* Fixed: Nested span handling - applying features to partial selections within styled text now creates proper nested or split spans instead of merging incorrectly
* Fixed: Block-level fonts no longer incorrectly included in unrelated inline operations
* Fixed: Line-height and letter-spacing controls no longer pass incorrect empty data-features attributes that interfered with attribute preservation
* Improved: Inline fonts now use CSS variable system (var(--font-ID)) matching block-level architecture for consistent font loading and replacement
* Improved: Enhanced attribute preservation system to prevent style conflicts during sequential inline edits while properly handling font-family overrides
* Improved: Added comprehensive validation and fallback mechanisms for all inline text styling functions
* Improved: Inline state variables now reset after successful apply to prevent UI/content desync
* Improved: Font override logic - applying new inline font to text with existing font now properly replaces old font instead of preserving it
* Added: parseInlineFontFamilyAtCursor() utility for detecting inline fonts at cursor position
* Added: Memoized inline font detection for improved preview performance
* Developer: extract_fonts_from_blocks() enhanced to parse inline HTML content for data-font-id attributes

= 1.1.5 =
* Added: Line-height controls for block-level and inline text styling
* Added: Line-height control in Typography Stylist block inspector panel
* Added: Line-height control in Quick Features Toggle popover for inline selections
* Added: Line-height control in inline editor toolbar for standard heading/paragraph blocks
* Improved: Line-height can be adjusted from 0.5 to 3.0 with 0.1 step increments
* Improved: Responsive font size controls now operate independently without auto-adjusting other values
* Improved: Responsive font size labels now clearly indicate screen sizes (Mobile, Intermediate, Large)
* Improved: Visual warning displayed when responsive font sizes are out of logical order
* Improved: Default responsive font sizes for new blocks changed to 16/32/64 for more dramatic scaling
* Fixed: Confusing slider behavior where adjusting one size would move other sliders
* Developer: Breakpoint values (320px, 1920px) extracted to named constants (RESPONSIVE_FONT_MIN_VIEWPORT, RESPONSIVE_FONT_MAX_VIEWPORT) for future configurability across Typography Stylist block and inline editor

= 1.1.4 =
* Fixed: Mixed content warnings on HTTPS sites when loading custom fonts
* Improved: Font URLs now use relative paths for protocol-agnostic loading
* Improved: Legacy fonts with absolute URLs are automatically converted at render time

= 1.1.3 =
* Initial release approved for public distribution.
* Typography Stylist Block with ARIA markup and semantic HTML
* Smart selection validation warns when partial word selections could fragment text
* Conversion tool from inline formats to accessible block structure
* Configurable aria-label support for inline formatted text
* Screen reader class options (visually-hidden, sr-only, or custom classes)
* Accessibility documentation
* Upload custom font kits from MyFonts, Fontspring, and other webfont providers
* Adobe Fonts (Typekit) integration via embed code
* Define fonts loaded through themes, plugins, or CDN services
* Font fallback system
* Secure font file storage with .htaccess protection
* Font preview system with size controls
* OpenType feature support: ligatures (liga, dlig, calt)
* Stylistic sets (ss01-ss20)
* Swashes (swsh, cswh) and alternates (salt, titl, ornm)
* Quick-apply presets for common typography styles
* Custom preset creation and saving
* Inline text selection in the block editor
* Live preview before applying changes
* Popover interface with features organized by category
* Spanish (es_ES) and French (fr_FR) translations
* Native CSS font-feature-settings
* WordPress block editor (Gutenberg) API integration
* REST API for plugin features
* JSX/React architecture for the custom block
* WordPress @wordpress/scripts build toolchain
* Transient caching
* Rate-limited REST API endpoints (50 requests/minute per user)
