Therum OS · 1.9.44 Intro Choose Login Admin ◐
A WordPress fork · built for operators, not posts

Therum OS

The admin layer WordPress should have shipped. SQLite-first, sans-WP UI, native-module architecture.

Therum OS is a CMS-agnostic operating layer. The current vessel is a hardened WordPress build with native mu-plugins replacing the dashboard, login flow, settings registry, and content management surface.

What it is

A native admin shell on top of WordPress's bones.

We kept the parts WordPress is good at — the post API, the user model, the plugin contract — and rebuilt everything around them. Every admin screen, every settings panel, every nav surface is rewritten as native mu-plugins. No React in the admin. No WordPress branding.

Native admin shell

Custom sidebar, topbar, dashboard, settings registry. No WP nags, no WP toolbar, no plugin-update notices. Native mu-plugins, no React, every pixel intentional.

60 themes, one registry

A theme is a set of CSS custom properties + a JSON manifest. Foundations, Surfaces, Familiar, Experimental, Mecha, Therum, Glass-Spatial groups — all swappable from the Customization panel. No theme.json, no Customizer.

SQLite by default

No MySQL daemon, no socket files, no my.cnf tuning. The site is a single folder. Move it, zip it, deploy it — the database goes with it.

Connector framework

AI providers, API tokens, payment gateways, and external apps register through one extensible API. Four typed buckets, one shared Vault, one audit log. No plugin marketplace required.

Sans-WP everywhere

X-Powered-By stripped. /wp-admin/about.php redirected. REST status reports "Therum OS". Feed generator tags removed. WordPress runs underneath — you just can't see it.

Local update channel

No phone-home. Updates flow from a local dist/ folder with signed manifests. Every release is auditable on disk via release-manifest.json + SHA-256.

Ready to look around?

The next screen lets you pick which build to walk through.

Choose your demo
Step 1 of 2

Choose your demo.

Two builds, same admin shell. Pure is the vanilla SQLite stack with native modules only. Unlocked is the full op-layer with the Bricks builder, e-commerce, and the AI connector suite.

Dashboard
B
Wednesday, May 13 · 6:21 PM

Welcome back, Ben

Here's what's happening with bam-leon today.

Edit layout · drag cards to rearrange, drag the corner to resize.
Pages View all →
12
Total pages
Posts View all →
24
Published posts
Products View all →
38
WooCommerce products
Users View all →
8
Registered users
Recent activity
Therum OS — case studyBen Leon · 2 hours ago
Launching the local update channelBen Leon · 12 hours ago
Why we forked WordPressBen Leon · 3 days ago
AboutBen Leon · 1 week ago
Mu-plugin consolidation deep-diveBen Leon · 5 hours ago
Site health
Good
All systems nominal
NeoRename Therum native
Live preview
Select files above to preview renames
Rename file
hero-banner.jpg
Extension is preserved automatically. Spaces → hyphens, uppercase → lowercase.
Design · Visual BuilderBricks Builder

Visual BuilderBricks Builder

Therum's native visual builder — section-based composition, full inspector, breakpoint overrides. Ships in every Pure install as therum-builder.php (native module). No third-party theme, no extra add-ons, no licensing.

Rough preview only — Bricks doesn't run inside this experience demo. In the actual Unlocked build, the real Bricks editor loads in an iframe with the Bricks theme + 10 add-ons (Ultimate, ACSS, BricksExtras, Bricksforge, Max Addons Pro, NextBricks, Agent-to-Bricks).

bam-leon / Pages / Home
draft
100%

Build it your way.

Stack any block, drag to reorder, tab to indent, slash to insert. No theme builder licensing. No third-party UI to learn. Pure Therum.

⚡
Press / on any blank block to open the slash menu. Tab nests a block under its predecessor.

How it ships

Every page is a JSON document — order-stable, version-controllable, exportable. No DB-locked layouts.

bam-leonbam-leon.local / home
100%
section · hero
● Therum OS · 1.9.44

The admin layer
WordPress should have shipped.

SQLite-first, sans-WP UI, native-module architecture. The current vessel is a hardened WordPress build with native mu-plugins replacing the entire dashboard.

section · intro · 3-col grid
⬢
Native admin shell
Custom sidebar + topbar + dashboard. Zero React.
⬡
SQLite by default
No MySQL daemon. The site is one folder.
◆
Connector framework
AI / APIs / Payments / Apps in one Vault.
section · case studies · slider

Recent work

Web App
bamleon.me — rebuild
CMS
Therum OS — fork story
Brand
Studio identity refresh

Therum's native visual builder — same UX as Bricks, no third-party theme required. Drag from the left panel, drop on the canvas, edit in the right structure tree.This is a static replica of the Bricks editor UI. In the real Unlocked install the canvas is fully interactive — drag elements from the left panel onto the canvas, edit live, save with Cmd+S.

Store · WooCommerce

Home

WooCommerce overview — orders, revenue, customers. WC stripped to essentials by the Therum Woo perf module.

+ Add product
Revenue (MTD)
$12,486
↑ 4.2% MoM
Orders
87
↑ 12
AOV
$143
→ stable
Refund rate
1.2%
↓ 0.4pt
Recent orders View all →
OrderCustomerTotalStatusDate
#1287
JD
Jamie Davis
$248.00Paid2h ago
#1286
SR
Sara Rivera
$89.00Paid5h ago
#1285
MK
Marcus King
$412.00Pending8h ago
#1284
AT
Alex Tan
$67.50Paid1d ago
7 orders · 1 processing

Orders

Customer orders, refunds, and shipping.

#1287
Completed
Jamie Davis
$248.00 · May 14, 2026
#1286
Completed
Sara Rivera
$89.00 · May 13, 2026
#1285
Processing
Marcus King
$412.00 · May 13, 2026
#1284
Completed
Alex Tan
$67.50 · May 13, 2026
#1283
Completed
Riley Park
$135.00 · May 12, 2026
#1282
Refunded
Elena Morales
$320.00 · May 12, 2026
#1281
Completed
Devon Kim
$176.00 · May 11, 2026
OrderCustomerStatusTotalDate
#1287Jamie DavisCompleted$248.00May 14, 2026
#1286Sara RiveraCompleted$89.00May 13, 2026
#1285Marcus KingProcessing$412.00May 13, 2026
#1284Alex TanCompleted$67.50May 13, 2026
#1283Riley ParkCompleted$135.00May 12, 2026
#1282Elena MoralesRefunded$320.00May 12, 2026
#1281Devon KimCompleted$176.00May 11, 2026
4 coupons · 2 active

Coupons

Discount codes and promotional pricing.

CodeTypeAmountUsageExpires
SPRING25Percentage discount25%14 / ∞Jun 30, 2026
WELCOME10Fixed cart$10.0083 / ∞—
FREESHIPFree shipping—52 / 200—
VIP50Fixed product$50.003 / 10May 31, 2026
Store · WooCommerce

Marketing

Campaigns, channels, and customer outreach.

Active campaigns
3
→ stable
Subscribers (MailPoet)
1,284
↑ 42
Conversion (30d)
3.2%
↑ 0.4pt
Ad spend (MTD)
$842
→ on track
Channels
ChannelStatusSpend (MTD)Conversions
G
Google Listings & Ads
Connected$52018
T
TikTok for Business
Connected$2209
S
Snapchat Ads
Paused$1023
R
Reddit Ads
Disconnected——
M
MailPoet
Active—27
Store · WooCommerce

Analytics

Revenue, orders, products, customers — all twelve report types.

Gross sales (30d)
$12,486
↑ 4.2% MoM
Orders
87
↑ 12
Returning customer rate
38%
↑ 2pt
Avg. items per order
2.6
→ stable
Store · WooCommerce

Payments

Payment gateways and processing.

GatewayStatusModeFee
W
WooCommerce Payments
ActiveLive2.9% + 30¢
P
PayPal Payments
ActiveLive3.49% + 49¢
B
Direct bank transfer
Disabled——
C
Check payments
Disabled——
$
Cash on delivery
Disabled——
Store · WooCommerce

Shipping

Zones, methods, and rates. Powered by WooCommerce Shipping.

ZoneRegion(s)Method(s)
United StatesUSFlat rate · USPS · UPS
CanadaCAFlat rate · Canada Post
EuropeEU member statesFlat rate · Local pickup
Rest of worldDefault zoneFlat rate
Store · WooCommerce

Reports

Legacy WC reports (replaced by Analytics, kept for parity).

For modern reporting use Analytics. Legacy tabs: Orders · Customers · Stock · Taxes.

Store · WooCommerce

Settings

General store, tax, accounts, emails, integrations.

Currency, store address, selling locations, shipping locations, default customer location — all wired through the Therum settings registry against the live WC options.

Store · WooCommerce

Status

System status, tools, logs, scheduled actions.

WooCommerce version10.2.4OK
Database version10.2.4OK
HPOS (High-Performance Orders)EnabledOK
Action Scheduler12 pending · 0 failedOK
SQLite (Therum)3.46.1OK
TemplatesAll up to dateOK
Store · WooCommerce

Extensions

Installed WooCommerce extensions.

ExtensionVersionStatus
W
WooCommerce Payments
8.6.1Active
P
WooCommerce PayPal Payments
2.9.3Active
S
WooCommerce Shipping
1.4.0Active
S
WooCommerce Services
2.5.0Active
G
Google Listings & Ads
2.10.0Active
R
Reddit for WooCommerce
1.3.1Active
S
Snapchat for WooCommerce
1.2.0Active
T
TikTok for Business
1.6.2Active
M
MailPoet
5.4.2Active
Design · Customizer

Customizer

Site identity, colors, header/footer — WordPress Customizer, Therum-skinned. For full theming use Customization.

12 active · 2 updates

Plugins

Functionality bolted onto WordPress core.

Name A→Z
Layout
Image
12 native modules · 0 third-party

Plugins

Pure runs on native Therum modules only. No third-party plugins.

Name A→Z
Layout
Image
No third-party plugins
Therum OS Pure ships without WP plugins. The native modules above (Therum Core) cover content, design, e-commerce, performance, and updates.
B
Active Update v1.13.6 available

Bricks Builder

About this plugin

Bricks is a visual site builder for WordPress that lets designers build full sites without writing code. It ships its own theme and uses native WordPress data — no shortcodes, no proprietary post types for layouts.

Therum OS uses Bricks as the default front-end editor in the Unlocked variant. The Therum admin shell wraps the Bricks editor in the Therum chrome and adds the Therum-customization layer for theme tokens.

Screenshots

Builder canvas
Inspector panel
Templates library

Changelog

v1.13.6 — 2026-05-12

  • Fixed: nested-loop dynamic data rendering inside Query Loop
  • Improved: builder canvas hot-reload on save
  • New: per-breakpoint CSS variable controls

v1.13.5 — 2026-05-01

  • Fixed: ACF field rendering with multi-site
  • New: SVG icon library with 600+ icons

v1.13.4 — 2026-04-22

  • Fixed: REST endpoint authorization
  • Improved: container query support
BRICKS THEME · MANAGED IN BUILDER

Menus

Navigation menus and structure.

Where it lives

Inside the Bricks builder

Bricks manages navigation menus inside the builder, not via WordPress menus. Open your Header template in Bricks to find the Nav Menu element and edit your site navigation.

NATIVE WORDPRESS · WRAPPED IN THERUM

Menus

Navigation menus and structure.

/wp-admin/nav-menus.php
WordPress menus UIiframed nav-menus.php inside Therum chrome.
Edit menu structure, add/remove items, assign locations.
BRICKS THEME · MANAGED IN BUILDER

Widgets

Sidebar and footer widgets.

Where it lives

Inside the Bricks builder

Bricks doesn't use WordPress widgets. Sidebars and widget areas are managed via Bricks Sidebars, and content is built visually in the Bricks builder.

NATIVE WORDPRESS · WRAPPED IN THERUM

Widgets

Sidebar and footer widgets.

/wp-admin/widgets.php
WordPress widgets UIiframed widgets.php inside Therum chrome.
Drag widgets into sidebars and widget areas.
13 TEMPLATES

Templates

Header, footer, archive, and section templates for bam-leon.local.

Recently modified
BRICKS THEME · NATIVE PLUGIN UI

Bricks Settings

Global builder settings — access, templates, performance, API keys, custom code. Rendered by the Bricks plugin; Therum chrome is skipped on this route.

Post types
Enabled post types post · page · case_study

Which post types can be edited with Bricks.

Global classes & variables
Lock global classes for editors
Show variable picker in builder
Reset Bricks data

Reset Bricks settings to factory defaults. Doesn't touch your content.

Builder access by role
Administrator
Editor
Author
Contributor
Builder access by capability
Custom capability edit_bricks_content
Restricted access
Restrict editor to global classes only
Hide custom code panel from editors
Template settings
Disable template thumbnail generation
Allow remote templates
My templates URL
Remote URL https://templates.bamleon.me/
Template screenshots
Builder load behavior
Disable opacity transitions
Auto-save interval (every 60s)
Show structure panel by default
Element handling
Disable element label
Disable auto-expand sections
CSS loading method
Method Inline
Cached CSS / JS
Asset loading
Disable Google Fonts
Disable emojis
Disable jQuery on frontend
Maintenance mode
Enable maintenance mode
Template none
Coming soon
Enable coming soon mode
Bypass roles
Administrator
Editor
License key
Bricks license ****-****-****-9F2A · Valid
Google Maps API key
Key AIza…sb2k
Mapbox token
Token pk.eyJ1Ijo…
YouTube API key
Key —
Custom code
Execute code (PHP / JS / SQL)
Sign code with code signatures
Code signature key
Auto-generated · rotates monthly a9b4…42d5
Allowed roles
Administrator
Editor
WooCommerce integration
Enable Bricks WC elements
Custom shop page templates
Override product single page
Pages
Shop page Shop (id 142)
Checkout page Checkout (id 178)
Admin · Customization

Customization

Themes, branding, login, list-page defaults, dashboard layout, editor preferences. One surface for everything visual.

Customization · Themes

Themes & customize

Browse and install themes from the store, manage your saved customs, and fine-tune every design token via the customize panel on the right. Everything theme-related, one surface.

Active · Foundations

Studio

Bamleon front-end. Pitch black. Hot-pink pop.

bg surface accent text
Theme store 60 installed
Active
Studio
Foundations
Editorial
Foundations
Brutal
Foundations
Calm
Foundations
Neon
Foundations
Mono
Foundations
Slate
Foundations
Paper
Foundations
Studio Pro
Foundations
Carbon
Foundations
Glass · Light
Surfaces
Glass · Dark
Surfaces
Glass · Colored
Surfaces
Gradient · Aurora
Surfaces
Blurred · Frost
Surfaces
Velvet
Surfaces
macOS Sonoma
Familiar
Windows 11
Familiar
Tesla
Familiar
Linear
Familiar
Notion
Familiar
Spotify
Familiar
Apple Music
Familiar
Lucid
Familiar
Xfinity Member
Familiar
Tron
Experimental
Cyberpunk
Experimental
Wireframe
Experimental
Vaporwave
Experimental
Facenote
Experimental
Holographic
Experimental
ASCII
Experimental
Marker Doodle
Experimental
Newspaper
Experimental
Crayon
Experimental
RX-78-2
Mecha
Nu Gundam
Mecha
Hi-Nu
Mecha
Aerial
Mecha
Calibarn
Mecha
Unicorn
Mecha
Epyon
Mecha
Sazabi
Mecha
Sinanju
Mecha
Exia
Mecha
Kshatriya
Mecha
Vidar
Mecha
Tallgeese
Mecha
Reborns
Mecha
Penelope
Mecha
Xi Gundam
Mecha
Big O
Mecha
Big O — Final Stage
Mecha
Therum Studio
Therum
Therum OS
Therum
Glass
Glass Spatial
Aurora
Glass Spatial
Graphite
Glass Spatial
Midnight
Glass Spatial
Your saved themes 3 saved
Studio · Pink
saved Apr 28 · 2 days ago
DARK INTER ROUND GLASS
Lucid · Office
saved May 2 · 11 days ago
DARK INTER MED BREATH
Editorial · Reading
saved May 8 · 5 days ago
LIGHT CRIMSON MED BREATH
Customization · Active theme

Active theme

The theme currently driving the admin chrome.

Studio
Therum · dark · accent #f5389a
Customization · Branding

Branding

Logo, site name override, favicon, custom CSS + JS.

Identity

Logo
SVG or PNG, displayed in the topbar
Favicon
Site name override

Custom code

Custom CSS
Injected into admin and front-end
Custom JS
Customization · Login screen

Login screen

Login page skin, headline, background, behavior.

Headline
Subtitle
Background style
Gradient
Solid
Image
Enable SSO buttons
Customization · List page

List page defaults

Default card layout and thumbnail source for every Therum list view.

Default layout
Used on Pages / Posts / Media / Plugins / Users
Hero
Compact V1
Compact V2
Magazine
Thumbnail source
Show status pill
Customization · Dashboard

Dashboard defaults

Default bento grid, card sizes, per-role overrides, welcome message.

Welcome message
Default card sizes
New users start with this layout
Allow user-level layout edits
Customization · Editor

Editor defaults

Per-post-type editor defaults, autosave, code editor theme, shortcuts.

Default editor for Pages
Block
Bricks
Classic
Default editor for Posts
Block
Classic
Autosave interval
30s
60s
2min
Off
Editor
Pages, Posts, and custom post types open in the Visual Builder
Visual Builder · native
Autosave interval
30s
60s
2min
Off
THERUM OS · APPS

Studio

Install and manage Therum-native apps and site modules. All updates flow through the in-admin updater — no separate license keys.

Included

Nexus

v1.9.44

Connections + credentials vault.

Encrypted credential storage for every external service Therum can talk to. AES-256-GCM at rest, scoped tokens, custom providers. The backbone every other Therum app rides on.

Active

Cluster

v1.4.2

Group + organize content at scale.

Sort posts, pages, and custom post types into clusters with cross-linking, shared meta, and bulk operations. Designed for sites that grow past a few hundred entries.

Active

Milieus

v1.2.1

Environment + audience targeting.

Conditional content blocks gated by environment, device, geo, role, or arbitrary audience rules. Built on top of Bricks so any element gets a Milieus toggle.

Inactive

Shop

Lightweight commerce for Therum.

A WooCommerce alternative tuned for digital goods, services, and lightweight catalogs. Stripe + PayPal out of the box, no checkout bloat, no React. Therum-native.

Enabled

Case Studies

v1.9.44

Portfolio CPT + sidebar section.

Registers the case_study custom post type and surfaces a Portfolio entry in the Therum sidebar. Enable only on sites that publish a portfolio.

Open →

More modules in development. Therum apps share a single update channel through the in-admin updater — no separate license keys, no per-plugin nags.

Admin · Connections

Connections

Wire Therum to the outside world. AI models, APIs, payment gateways, and external apps — all behind one canonical surface, with provider account dashboards embedded inside Therum chrome.

4 connected · 1 action needed · 18 total
Connections · CMS

Connect CMS

WordPress, Drupal, Ghost, Webflow, Contentful — Therum reads + writes content through these adapters.

W
WordPressConnected

Pulls posts, pages, custom post types. Default adapter — this install.

D
DrupalAvailable

Drupal 10/11 via JSON:API. Bring your endpoint + basic auth.

G
GhostAvailable

Ghost Content + Admin API. OAuth or static API key.

W
WebflowAvailable

CMS + Designer API. Pull collection items by slug.

C
ContentfulAvailable

Headless CMS. Pull entries by content type ID, render through Bricks.

Connections · AI Tools

AI Tools

Language models you can query from the dashboard or any Therum page. Bring your own API key or OAuth credentials.

Connected
A

Anthropic · Claude

claude-sonnet-4.5 · 200k context · function calling

Manage →linked 2d ago · API key
Connected
O

OpenAI · ChatGPT

gpt-5-turbo · 128k context · vision · code interpreter

Manage →linked 6d ago · API key
Not connected
G

Google AI · Gemini

gemini-2.5-pro · 2M context · multimodal native

Connect →OAuth
Not connected
L

Local · Ollama

llama · mistral · qwen — runs on the same host as Therum

Connect →localhost
Connections · APIs

APIs

General-purpose service endpoints — email, SMS, webhooks, custom REST. Add as many as you need.

Connected
SG

SendGrid

Transactional email — 100k/mo · API key auth

Manage →412 sent today
Not connected
T

Twilio

SMS · MMS · WhatsApp · voice via account SID

Connect →API key
Not connected
Z

Zapier

Outbound webhook triggers — no-code automation

Connect →Webhook
Not connected
+

Custom REST

Any REST endpoint — base URL, auth, headers

Add →Custom
Connections · Ecommerce

Connect Ecommerce

WooCommerce, Shopify, Amazon, Etsy, Square — pull orders, products, customers into Therum.

W
WooCommerceConnected

Active on this install. 5 products · 7 recent orders.

S
ShopifyAvailable

Storefront + Admin GraphQL APIs. Bring your store + access token.

A
Amazon SellerAvailable

SP-API. Pulls orders, FBA inventory, reports. OAuth + signed requests.

E
EtsyAvailable

Open API v3. Listings, transactions, shop sections.

S
SquareAvailable

Square POS + Online. Catalog, orders, customers, payments.

Connections · Payment Gateways

Payment Gateways

Money in / money out. Account dashboards embed directly inside Therum once OAuth completes.

Connected
S

Stripe

Live mode · checkout, subscriptions, payouts

Manage →$1,247 today
Sandbox
P

Plaid

Bank link + ACH · sandbox key in use

Switch to live →key rotates in 4d
Not connected
P

PayPal

Checkout + payouts via OAuth

Connect →OAuth
Not connected
Sq

Square

Catalog, orders, payments via Connect API

Connect →OAuth
Connections · External Apps

External Apps

Productivity + collaboration. Therum reads + renders their data inside the chrome via OAuth.

Not connected
N

Notion

Database + page sync via the Notion API

Connect →OAuth
Not connected
A

Airtable

Spreadsheet API · base access · attachments

Connect →OAuth
Not connected
S

Slack

Channel posts + DM relay for alerts

Connect →OAuth
Not connected
L

Linear

Issue sync + sprint mirroring

Connect →OAuth
Not connected
M

Mailchimp

Audience sync + campaign automations

Connect →OAuth
Not connected
D

Dropbox

File sync + asset mirroring

Connect →OAuth
Connections · API & Webhooks

API & Webhooks

REST API surface, headless mode, CORS origins, outbound webhooks. Merged in from Settings.

ConnectYour site's live API connection details.
WP REST API
https://bam-leon.local/wp-json/
Therum v1
https://bam-leon.local/wp-json/therum/v1/
Status ↗
Auth: Authorization: Basic base64(username:application_password)

REST API

WP's built-in REST API at /wp-json/.

REST API enabled
Disable to fully lock down /wp-json/. Bricks needs this on.
Require authentication
Block anonymous reads. Recommended.
Headless mode
Suppress WP theme on public requests — visitors get a JSON pointer.

CORS

Allow cross-origin requests from these domains.

Allowed origins
One per line. * = wildcard (not recommended).

Outbound webhooks

11 events available · HMAC-SHA256 signed.

Configured endpoints
Add destinations + pick which events fire.
2 endpoints
Event stream
View payloads, replay, inspect signatures.
Connections · API keys vault

API keys vault

Encrypted credential vault — masked, audited, rotatable.

KeyConnectorCreatedLast usedRotates
sk_live_a1b2c3…Stripe2d ago2m agoin 90d
sk-ant-x9y8z7…Anthropic2d ago12m agoin 89d
sk-q4r5s6…OpenAI6d ago1h agoin 84d
plaid_sandbox_t1…Plaid12d ago3h agoin 4d
SG.sendgrid_a8b…SendGrid2w ago412/moin 76d
Connections · Webhooks

Webhooks log

Inbound + outbound webhook event stream with replay.

EventDirectionEndpointStatusTime
post.publishedOuthooks.zapier.com/…2002m ago
order.createdOutapi.slack.com/hooks/…2008m ago
charge.succeededInstripe → /webhook/stripe20014m ago
user.registeredOutapi.mailchimp.com/3.0/…50323m ago
Add-on · Ecommerce

Ecommerce

A SQLite-native commerce module. Products, orders, customers — no plugin required.

E
Therum Ecommerce
Native module · SQLite-backed

Stripe-first checkout. Single SQLite ledger for orders + customers. No WooCommerce, no MySQL, no legacy tables.

What gets added
  • • Store section in sidebar — Home / Orders / Customers / Products
  • • Cart + checkout endpoints (REST + AJAX)
  • • Coupons + tax rules + shipping zones
  • • Stripe Connect + Apple Pay integration
  • • Dashboard revenue bento card
Add-on · Portfolio

Portfolio

Project gallery + project-detail CPT, surfaced as its own Content section.

P
Therum Portfolio
Native module · projects CPT

Project grid with cover, slug, hero stack, deliverables list. Built for studios + agencies.

What gets added
  • • Portfolio section in sidebar
  • • Project CPT — title / slug / cover / role / year
  • • Discipline + tag taxonomies
  • • Featured project flag
  • • Front-end grid template
Add-on · Case Study

Case Study

Long-form project narrative CPT. Editorial format with hero · narrative · proof · outcome.

C
Therum Case Study
Native module · case_study CPT

Pre-structured block templates for problem · approach · solution · outcome. Designed for pitch decks + portfolio sites.

What gets added
  • • Case Studies item in sidebar Content section
  • • case_study CPT with editorial block library
  • • Hero / Body / Quote / Stats / Outcome blocks
  • • Client + industry + year fields
  • • Front-end single + archive templates
Add-on · Blog

Blog

Threaded posts with categories, tags, comments, and feed. Therum-native, no WP dependency.

B
Therum Blog
Native module · posts CPT

Markdown-first authoring. Categories + tags. RSS feed. Comments via webhook or moderated queue.

What gets added
  • • Posts item in sidebar Content section
  • • Markdown + block hybrid editor
  • • Category + tag taxonomies
  • • RSS feed at /feed
  • • Comments queue + moderation
Add-on · Forms

Forms

Drag-and-drop form builder with submission storage, conditional logic, and webhook delivery.

F
Therum Forms
Native module · SQLite-backed

No Gravity, no WPForms, no shortcodes. Form builder writes to a single submissions table. Webhooks fire on submit.

What gets added
  • • Forms section in sidebar — Builder / Submissions
  • • Drag-drop field library (text, select, file, signature)
  • • Conditional logic + multi-step support
  • • Submission inbox + CSV export
  • • Webhook + email delivery hooks
Add-on · Memberships

Memberships

Gated content, member tiers, recurring billing — wired into the native auth + Stripe layer.

M
Therum Memberships
Native module · gated content

Tier-based access. Drip schedules. Stripe Billing handles recurring charges. No MemberPress, no PMP, no third-party gates.

What gets added
  • • Members section in sidebar — Tiers / Roster / Drip
  • • Per-page / per-block access rules
  • • Stripe Billing for recurring plans
  • • Trial periods + coupon codes
  • • Member portal template
Add-on · Newsletter

Newsletter

Subscriber list, broadcast composer, automated sequences — sent via your own SMTP or Resend.

N
Therum Newsletter
Native module · email broadcasts

Substack-style sends without the platform tax. Connect SMTP, Resend, or Postmark. Subscribers live in your SQLite, not theirs.

What gets added
  • • Newsletter section in sidebar — Subscribers / Broadcasts / Sequences
  • • Block-style email composer
  • • Double opt-in + signup forms
  • • Open + click tracking
  • • SMTP / Resend / Postmark integration
Add-on · Analytics

Analytics

First-party page + event tracking. No third-party cookies. Data lives in your SQLite, dashboards live in your admin.

A
Therum Analytics
Native module · first-party

Plausible-grade privacy with the data sitting in your install. Cookieless. GDPR-clean. No GA, no Mixpanel script.

What gets added
  • • Analytics section in sidebar — Overview / Pages / Events / Funnels
  • • Cookieless page + event tracker
  • • Live visitor stream
  • • Custom event API + funnel builder
  • • Dashboard bento card with 7d trend
Connections · Audit log

Audit log

Tamper-evident connector + credential lifecycle log.

EventActorIPTime
therum.update.applied — bundle: patch · v1.9.44[email protected]192.168.1.4212m ago
connection.added — anthropic (OAuth)[email protected]192.168.1.421h ago
vault.key.rotated — sk_live_xxx (Stripe)[email protected]192.168.1.422d ago
settings.security.2fa_enforced — on[email protected]192.168.1.422d ago
connection.test — openai (200 OK)systemcron3d ago
—
— —

—

About

—

Setup

  1. —

Permissions & scopes

—

Usage (last 30 days)

Requests
—
Success rate
—
Spend
—
Last call
—

Recent activity

EventStatusWhen
No activity yet — connect to start logging.
Canvas · Templates

Templates

The shell that wraps every page on the site. Edit once, applies everywhere it’s used.

/
Front page
Home route · used by 1 page
ActiveEdited —
single.html
Single
Default for posts · used by 8 posts
ActiveEdited —
page.html
Page
Default for pages · used by — pages
ActiveEdited —
Archive
Post lists · categories, tags, dates
ActiveEdited —
Search results
Result listings for /?s= queries
DefaultInherits archive
404
404 / Not found
Falls back when no route matches
ActiveEdited —
Be right back
Maintenance
Shown when site is in maintenance mode
InactiveEdited —
Canvas · Template parts

Template Parts

Reusable blocks — header, footer, sidebars, callouts. Edit once, syncs everywhere it’s embedded.

Header — Main
Logo + primary nav · used in 4 templates
Syncedv3
Header — Minimal
Wordmark only · landing pages
Availablev1
Footer — Full
4 columns + newsletter · used in 5 templates
Syncedv2
Footer — Minimal
Copyright row only
Availablev1
Subscribe
CTA — Newsletter
Email signup band · used in 3 templates
Syncedv4
Sidebar — Blog
Recent posts + tags · used in 2 templates
Availablev1
Author bio
Below single posts · used in single.html
Syncedv2
Canvas · Patterns

Patterns

Pre-built compositions — drop into any page or template. Real markup, no shortcodes, fully editable after insert.

Hero — Split image
Headline + sub + CTA with paired hero image
First-party
Features grid — 3 column
Icon + heading + supporting copy, 3 across
First-party
Pricing table — 3 tier
Starter / Pro / Enterprise with feature list
First-party
Testimonials — Pair
Two-up customer quotes with avatar + role
First-party
FAQ — Accordion
Collapsible Q&A list, keyboard accessible
First-party
CTA — Full-bleed band
Centered headline + sub + primary button
First-party
UPDATES · LOCAL CHANNEL

Therum OS Updates

Reads ~/Therum OS/dist/release-manifest.json

INSTALLED
1.9.44
Applied — · backup at mu-plugins.bak.—
UP TO DATE
1.9.44
Built — · SHA-256 verified ✓

Apply update

Copies the new mu-plugin set from the selected bundle into wp-content/mu-plugins/. The existing set is moved to a timestamped backup beside it. No core, plugin, or theme files are touched.

P
Patch bundle · v1.9.44 · — KB
Therum-OS-Patch-1.9.44.zip · mu-plugins + CHANGELOG.md + INSTALL.md
P
Pure bundle · v1.9.44 · — MB
Therum-OS-Pure-1.9.44.zip · full install · WP core + SQLite + native modules
P
Pro bundle · v1.9.44 · — MB
Therum-OS-Pro-1.9.44.zip · full install + Bricks suite + WC + MailPoet + LSCache

Source

Reads release-manifest.json from ~/Therum OS/dist/. Override via define( 'THERUM_DIST_PATH', '/abs/path' ) or the therum_updates_dist_path filter.

{
  "schema": 1,
  "built_at": "2026-05-20T22:21:00Z",
  "latest_version": "1.9.44",
  "bundles": {
    "patch": { "version": "1.9.44", "zip": "Therum-OS-Patch-1.9.44.zip", "size": 434176,  "sha256": "a9b4…42d5" },
    "pure":  { "version": "1.9.44", "zip": "Therum-OS-Pure-1.9.44.zip",  "size": 16777216, "sha256": "c83f…91e2" },
    "pro":   { "version": "1.9.44", "zip": "Therum-OS-Pro-1.9.44.zip",   "size": 101711872, "sha256": "7e21…b04a" }
  }
}

Version history

Re-apply the current build, reinstall the last release, or roll back to any prior version. Backup-then-replace on every action.

v1.9.44 Installed · current
2026-05-20
Database hygiene pass. New Performance > Database pane (index health · SQLite object cache · autoload audit · Action Scheduler · transients/sessions cleanup · slow query log). Woo · fast order lookup baked into therum-woo.php (indexed table replaces unindexed LIKE scan on admin order search). FSE-style Canvas surface for Pure (Templates · Template Parts · Patterns + Content/Template/Site mode toggle).
v1.8.6 · Phase 9 2026-05-13
2026-05-13
Distribution polish — 424 KB patch bundle, four-flow experience preview HTML, release-manifest.json with three bundles + SHA-256.
v1.8.6 · Phase 8 2026-05-13
2026-05-13
Local update channel. New therum-updates.php reads release-manifest.json from ~/Therum OS/dist/. Apply flow extracts bundle's mu-plugins with backup-then-replace.
v1.8.6 · Phase 7 2026-05-13
2026-05-13
Mu-plugin consolidation 19 → 12. Three buckets of four (Shell / Platform / Infrastructure). Originals parked as .disabled.
v1.8.6 · Phases 2–6 2026-05-13
2026-05-13
Cache-bust + asset .gz auto-regen, sans-WP leak sweep, WP 7.0 GA prep.
v1.8.6 · Phase 1 2026-05-13
2026-05-13
Foundation — therum-customization.php scaffold + sidebar nav restructure (Plugins / Users / Customization / Connections / Settings).
v1.8.6-prep 2026-05-13
2026-05-13
WP 7.0 GA absorption groundwork.
v1.8.0 → 1.8.5-Beta Previous release
2026-05-09
Build pipeline + Customization + Connections. Pro + Pure bundle builds. 7-step install wizard. Apple Music / Lucid / Xfinity Member themes. Four-bucket Connections (AI / APIs / Payments / External Apps).
v1.7.1-beta Older
2026-04-28
"Everything wired" — perf engine, S3 backup, notifications, roles engine, API/webhooks engine with 11 outbound events.
v1.7.0-beta Older
2026-04-28
"It's an admin, not a plugin" — card system, plugin PDPs, Therum-skinned classic editor, Pages auto-redirect to Bricks.
v1.6.x Older
2026-04-27
First version with real screens — list-page renderer, theme presets, settings registry.
v1.0.1 → 1.5.x Older
stabilization
The fix-it run. No new modules — bug-fix iterations against the v1.0.0 surface.
v1.0.0 Origin
pre-2026-04-14
The fork. Three files: therum-core, therum-admin-ui, therum-test. SQLite from day one.

Changelog · full

Complete version history from v1.0.0 forward · 1235 lines

# Therum OS — Changelog

All notable changes to Therum OS, version 1.0.0 onward. Dates are in `YYYY-MM-DD`.

Format follows [Keep a Changelog](https://keepachangelog.com/). Versioning loosely follows SemVer.

**Sources merged here:**
- v1.0.0 — reconstructed from the preserved install at `~/Local Sites/therum-os/`.
- v1.0.1 → v1.5.x — stabilization line; no version-header anchors, characterized from cumulative behavior.
- v1.6.x → v1.7.1-beta — canonical release notes lifted from `wp-content/CHANGELOG.md` (written when each shipped).
- v1.8.0 → v1.8.5-Beta — full + authoritative, all from the 2026-05-09 session.
- v1.9.44-prep → WP 7.0 GA absorption — current preparation, all from the 2026-05-13 session.

---

## [1.8.7 · Phase 9] — 2026-05-13

Distribution polish. Adds a layer-only patch bundle, a four-flow experience preview HTML, and surfaces both in the build pipeline.

### Patch bundle — `Therum-OS-Patch-{version}.zip`

`build.sh` gains a `build_patch` step that produces a third zip alongside Pro and Pure: 424 KB, mu-plugins + `CHANGELOG.md` + an `INSTALL.md` at zip root. No WordPress core, no plugin/theme code, no install wizard — just the Therum OS layer. Drops into any existing install in three steps (move old mu-plugins to a timestamped backup, copy in the new set, hard-refresh admin).

`release-manifest.json` now carries three bundle entries (`pro`, `pure`, `patch`) each with `version`, `zip`, `size`, and `sha256`. The in-admin Updates page can offer the patch as the preferred upgrade path for already-running installs.

### Experience preview — `therum-os-experience.html`

A second preview file ships alongside the existing `admin-preview.html`. Single self-contained HTML with hash routing across four flows:

1. **Intro** (`#/intro`) — wordmark hero, six-feature grid, vertical dev timeline pulled from this changelog, condensed recent-releases table
2. **Chooser** (`#/choose`) — side-by-side Pure vs Unlocked cards, selection threads through to login + admin via `sessionStorage`
3. **Login** (`#/login`) — centered Therum-branded card, SSO buttons, sign-in routes to the admin with the chosen variant
4. **Admin** (`#/admin`) — full 1:1 replica of the live admin shell: sidebar with section grouping, topbar with crumbs + bell + avatar, 8 routed sub-pages (Dashboard, Content, Media, Bricks Builder *(unlocked)*, Commerce *(unlocked)*, Plugins, Users, Customization, Connections, Updates, Settings). Variant flag flips the entire shell live via `is-unlocked` class — no reload.

### Build pipeline

`build.sh` copies both preview files to `dist/` on every run:

```
~/Therum OS/dist/
├── Therum-OS-Pro-1.8.7.zip       96 MB
├── Therum-OS-Pure-1.8.7.zip      16 MB
├── Therum-OS-Patch-1.8.7.zip    424 KB
├── release-manifest.json               4 KB
├── admin-preview.html                196 KB
└── therum-os-experience.html         136 KB
```

Total dist regenerates in one `./build.sh all`.

---

## [1.8.7 · Phase 8] — 2026-05-13

Local update channel. The admin shell now has its own update surface that reads from a local `dist/` folder instead of phoning home to a server.

### New mu-plugin — `therum-updates.php`

Registers a hidden admin page at `?page=therum-updates` (linked from the Admin sidebar group). The page:

- Reads `release-manifest.json` from `~/Therum OS/dist/` by default. Override with `define( 'THERUM_DIST_PATH', '/abs/path' )` or filter `therum_updates_dist_path`.
- Compares the manifest's `latest_version` against the live install's `THERUM_OS_VERSION` using a Beta-aware semver compare.
- Shows installed vs available side-by-side, plus a changelog excerpt pulled from the manifest.
- Apply flow: extracts the chosen bundle's `wp-content/mu-plugins/` into the live mu-plugins dir. The existing set is preserved to `wp-content/mu-plugins.bak.{YYYYmmdd-HHMMSS}/` first. No core / plugin / theme files are touched.
- Fires `Therum_Cache_Bust::purge_all()` on completion if available, and emits a `therum.update.applied` audit event.

### Build pipeline — `release-manifest.json`

`build.sh` now emits `dist/release-manifest.json` after the Pro + Pure bundles. Shape:

```json
{
  "schema": 1,
  "built_at": "2026-05-13T22:15:48Z",
  "latest_version": "1.8.7",
  "bundles": {
    "pro":  { "version": "...", "zip": "...", "size": ..., "sha256": "..." },
    "pure": { ... }
  },
  "changelog_excerpt": "...first 60 lines of CHANGELOG.md..."
}
```

Per-bundle SHA-256 hashes let the Updates page verify the zip hasn't been swapped after the manifest was written.

### Sidebar wiring

Admin group gains an **Updates** entry between Connections and Settings. When the manifest reports a newer version, the entry carries a `badge => 'new'` and an `admin_notices` banner surfaces the same prompt at the top of every screen until the update is applied.

### Why local-only

Therum OS dev is local-first today — every `bam-leon` install is a Local site, every `dist/` snapshot is on the same machine. No release server, no version-check endpoint, no telemetry. The same module can grow a remote channel later by swapping the dist-path resolver for an HTTP fetcher; the apply flow already handles a downloaded zip the same way.

---

## [1.8.7 · Phase 7] — 2026-05-13

The mu-plugin consolidation cut. Therum's active module count goes from **19 → 12** — same surface, fewer files. Each merged module gains a banner-header comment per absorbed source (`// ════ FROM therum-X.php ════`) so the boundaries stay legible for future audits. Originals park as `.disabled` siblings; the bundle builder skips them.

### The 3 × 4 split

**A · SHELL — admin experience** (4)
- `therum-admin-ui` — sidebar / topbar / dashboard
- `therum-design` — themes + customization page + menus + widgets + motion *(absorbed `therum-themes` + `therum-customization`)*
- `therum-content` — duplicate + view-links + CPT + cards admin + editor skin + plugin-settings embedding *(absorbed `therum-plugin-settings`)*
- `therum-list-page` — generic list-page engine

**B · PLATFORM — identity, security, APIs** (4)
- `therum-core` — identity, security, sans-WP leak sweep
- `therum-auth` — login skin + TOTP 2FA + custom roles + WC role pricing *(absorbed `therum-roles-engine`)*
- `therum-api` — REST hardening + outbound webhooks + AJAX fast-path *(new file: absorbed `therum-api-engine` + `therum-ajax-fast`)*
- `therum-settings` — settings registry + page

**C · INFRASTRUCTURE — integrations, perf, commerce, utility** (4)
- `therum-connections` — connector registry + admin page (+ Vault / Webhooks / Audit manage trio)
- `therum-perf` — minify + scheduled backups + S3 + notifications + LSCache tuner + cache-bust + asset-gz *(absorbed `therum-cache-bust` + `therum-asset-gz`)*
- `therum-woo` — WooCommerce bridge + WC perf
- `therum-preload` — OPcache preload script (utility, not WP-loaded)

### Retired to `.disabled`

7 files now park on disk for audit-trail reference, no longer loading:

- `therum-api-engine.disabled` → folded into `therum-api`
- `therum-ajax-fast.disabled` → folded into `therum-api`
- `therum-roles-engine.disabled` → folded into `therum-auth`
- `therum-cache-bust.disabled` → folded into `therum-perf`
- `therum-asset-gz.disabled` → folded into `therum-perf`
- `therum-plugin-settings.disabled` → folded into `therum-content`
- `therum-themes.disabled` → folded into `therum-design`
- `therum-customization.disabled` → folded into `therum-design`

### Build pipeline — working demo HTML in `dist/`

`build.sh` now copies `previews/connections-and-dashboard.html` → `dist/admin-preview.html` on every bundle build. Same self-contained file you've been reviewing on your desktop, but always sitting next to the latest Pro + Pure ZIPs so anyone pulling the dist folder sees the current admin preview alongside the install bundles. 196 KB, single file, double-click-to-open.

```
~/Therum OS/dist/
├── Therum-OS-Pro-1.8.7.zip      82 MB
├── Therum-OS-Pure-1.8.7.zip     16 MB
└── admin-preview.html                196 KB   ← new on every build
```

### Verification at end of Phase 7

- 12 active Therum mu-plugins (target hit exactly)
- All 14 PHP files in `mu-plugins/` lint clean (12 Therum + WP's `index.php` + user's `therum-dev-nocache.php`)
- All admin routes (Dashboard · 8 Customization tabs · 8 Connections tabs · Settings) return clean 302
- No fatal markers in any response
- Both bundle ZIPs rebuilt against the consolidated mu-plugin set
- `admin-preview.html` automatically dropped into `dist/`

### Why the merges work without breakage

Pre-merge collision check ran on every pair:
```bash
{ grep -oE '^function +[A-Z_a-z]+' fileA.php fileB.php; } | sort | uniq -d
```
Zero function name collisions across all 5 merger sets. Zero class name collisions. One quirk surfaced during the design merger — `declare(strict_types=1)` from `therum-customization.php` landed mid-file in the new `therum-design.php`, which PHP rejects (declaration must be the very first statement). Stripped that single line; everything else carried over verbatim.

---

## [1.8.7 · Phases 2–6] — 2026-05-13

Phases 2 through 6 of the 1.8.7 build, executed in sequence with verification between each. The whole admin restructure designed across the preview (`~/Therum OS/previews/connections-and-dashboard.html`) is now in the codebase.

### Phase 2 — Themes page

The biggest single sub-page. Combines theme store + saved themes + the full 38-control Quick Controls panel into one Customization tab at `?page=therum-customization&tab=themes`.

- **Active theme card** — mini preview tile (uses each theme's `previewMain` background + `previewRail` colors from `Therum_Themes::presets()`) + name + group eyebrow + description + 4 design-token chips + Edit/Save/Export buttons.
- **Theme store** — iterates every preset from `Therum_Themes::presets()`. Each card has preview tile, name, group, hover-revealed actions (Star · Hide · Apply if not active), pink "Active" pill on the current theme. Filter chips for All / Starred / Hidden / per-group + search input.
- **Saved themes** — grid of user customs (hardcoded demo data; persistence to `user_meta` deferred). Each has swatch, name, meta, token chips, and Edit/Export/Apply/Delete with two-click confirm.
- **Quick Controls panel** — sticky right column inside the Themes page, scrolls internally, 38 controls across 10 collapsible groups:
  - **Appearance** (Mode · Accent · Intensity)
  - **Layout** (Density · Sidebar · Variant · Topbar · Content · Bento gap slider)
  - **Surfaces** (Glass toggle · Glass tint · Blur strength slider · Background · Shadow)
  - **Typography** (Body font · Display font · Mono font · Base size slider · Letter spacing · Line height)
  - **Shapes** (Radius · Border weight · Card style)
  - **Motion** (Motion · Transition speed · Page transitions toggle · Card hover lift toggle)
  - **Content defaults** (Card layout · Thumbnail source · List view · Items per page slider)
  - **Accessibility** (Contrast · Reduce transparency · Underline links · Focus rings · Larger click targets)
  - **Advanced** (collapsed by default — grip handles · keyboard shortcuts · auto-save · debug overlays · code editor theme)
  - **Quick switch** (saved theme chips for instant apply)
- **Reusable helpers** — `therum_cx_seg()`, `therum_cx_toggle()`, `therum_cx_slider()`, `therum_cx_select()`, `therum_cx_swatch()`, `therum_cx_panel_group()` so subsequent renderers stay terse.

### Phase 3 — Connections content

New top-level page at `?page=therum-connections`, with `Therum_Connections_Page` class mirroring the Customization registry. Four bucket renderers populated:

- **AI Tools** — Anthropic Claude (connected) · OpenAI ChatGPT (connected) · Google AI Gemini · Local Ollama
- **APIs** — Mailchimp (connected) · SendGrid · Twilio · Custom endpoint
- **Payment Gateways** — Stripe (connected) · Plaid (reauth needed) · Square · PayPal
- **External Apps** — Notion · Airtable · Slack · Linear · Zapier · Request-a-connector
- **Page header** with status strip (4 connected · 1 action needed · 18 total) + per-bucket search input + add-custom button
- **Connection cards** color-coded by state (connected = green border tint · reauth = red border) with hover transform, status pill + dot in top-right, brand-colored icon block, name, description, and a footer with auth-type meta + CTA

### Phase 4 — Manage trio

Three new pages under the Connections inner-nav rail's "Manage" section:

- **`?tab=keys` — API keys vault** — stats row (total / rotated / expiring / failed) + 7-row credentials table with provider icon, type pill (API KEY / OAUTH / HMAC color-coded), masked key (`sk-ant-•••a9F2` pattern), created/last-used/expires dates (expiring-soon highlighted amber, expired highlighted red), Copy/Rotate/Revoke action buttons.
- **`?tab=webhooks` — Webhooks log** — stats row (events 30d / success rate / failures 24h / avg latency) + 7-row event stream with status pill (200/201 green · 422 amber · 503 red), direction arrows (← in / → out), provider+event, endpoint URL, latency, time, Inspect/Replay actions.
- **`?tab=audit` — Audit log** — stats row (entries / users / connector changes / failed actions) + 7-row chronological log with user avatar, action pill (connect/rotate/view/denied/refresh/revoke color-coded), resource, IP, detail viewer.

All three share the same `.th-cn-stats` and `.th-cn-table` component vocabulary defined in Phase 3.

### Phase 5 — Remaining Customization sub-page renderers

Six more sub-pages now have real surfaces (no more "Phase 1 · scaffold" stubs):

- **Active theme** (`?tab=active`) — hero card + "Open theme store" deep-link
- **Branding** (`?tab=branding`) — Identity block (display name + host inputs pulled from `get_bloginfo()`) · Assets block (Admin logo + Favicon + Login screen logo upload tiles) · Custom code block (admin-wide CSS + JS textareas)
- **Login screen** (`?tab=login`) — live preview tile (mini admin login chrome with T-logo, headline, two input slots, accent-colored Sign-in button) + control column (headline · subheadline · background type segmented · three behavior toggles for 2FA / hide-lost-password / Therum chrome)
- **List page defaults** (`?tab=list-page`) — Card-layout radio grid (7 layouts with mini-preview tiles) + Thumbnail-source radio grid (5 sources with mini-preview tiles)
- **Dashboard layout** (`?tab=dashboard`) — stats row + Welcome message inputs (with `{first_name}` token support) + Per-role overrides table (Administrator / Editor / Author / Contributor)
- **Editor preferences** (`?tab=editor`) — Default-editor-per-post-type selects (Pages · Posts · Case Studies) + Behavior block (autosave slider · code editor theme select · 4 toggles) + Keyboard shortcuts list (6 bindings rendered with `<kbd>`-styled keys + edit button)

### Phase 6 — Cache hardening + version bump + final pass

- **New mu-plugin `therum-cache-bust.php`** (`Version: 1.0.0`) — multi-layer cache invalidation. Fires on Therum option saves, user-meta saves (`therum_*` and `th_*` prefixed keys), theme switch, plugin activate/deactivate/delete, and post save. On every trigger, runs:
  1. `wp_cache_flush()` for WP object cache
  2. Deletes Therum-prefixed transients from `wp_options` (and `wp_sitemeta` on multisite)
  3. Fires `litespeed_purge_all` action (no-op if LSCache isn't installed)
  4. Calls Bricks' `Helpers::delete_query_results_transient()` if Bricks is loaded
  5. Soft-flushes WP rewrite rules
  6. Fires `therum_cache_purged` action for downstream listeners (CDN edge invalidations, etc.)
- **`?th_fresh=1` query flag** — hooks on `init` priority 1 and `send_headers`. Sets `nocache_headers()` + `Cache-Control: no-store, no-cache, must-revalidate, max-age=0` + the three `DONOTCACHE*` constants that LiteSpeed / W3TC / similar caches respect. Lets you force-fresh any page when caches misbehave.
- **OPcache invalidate helper** — `Therum_Cache_Bust::opcache_invalidate( $path )` for the case where a hook needs to force PHP to reload a specific mu-plugin's bytecode (e.g. after a runtime config write).
- **Admin-bar purge action** — `?action=therum_purge_cache` with nonce-checked handler at `admin-post.php`, redirects back with `?th_purged=1` flag; an admin notice then surfaces "Therum · all caches purged."

### Files in 1.8.7

| File | Status | Purpose |
|---|---|---|
| `therum-customization.php` | new (~975 lines) | Top-level Customization route + registry + 8 sub-page renderers |
| `therum-connections.php` | extended (734 → 1,259 lines) | Now also hosts `Therum_Connections_Page` + 7 tab renderers + demo data |
| `therum-admin-ui.php` | edited | Admin sidebar nav exposes Customization + Connections as top-level items |
| `therum-core.php` | edited | `THERUM_OS_VERSION` bumped 1.8.5-Beta → 1.8.7 |
| `therum-cache-bust.php` | new (~150 lines) | Multi-layer cache invalidation mu-plugin |
| `assets/therum-customization.css` | new (~24 KB) | Page shell + nav rail + themes + customize panel + connections + tables + Phase 5 blocks |
| `assets/therum-customization.js` | new (~6 KB) | Collapsible groups · segmented · swatches · sliders · toggles · theme actions · saved-theme delete · search filter |

### Verification at end of build

- All 21 active mu-plugin PHP files lint clean (no syntax errors)
- All 16 new admin routes (8 Customization tabs + 8 Connections tabs) return clean 302 on the live admin (auth redirect, no fatal markers)
- `Therum_Customization::register()` and `Therum_Connections_Page::register()` both expose `therum_customization_tabs` / `therum_connections_page_tabs` filters so other plugins can add tabs

### Still queued (depends on external date)

- WP core bump 6.9.4 → 7.0.0 stable — waiting for GA on **2026-05-20** (one week from this build). The `therum-connections.php` 7.0 detection logic + remove_menu_page for WP's Connectors UI is in place from the prep pass.
- Bundle rebuild — rebuilds against new core after May 20.

---

## [1.8.7 · Phase 1] — 2026-05-13

The build cycle kicked off. v1.9.44's full surface (designed across the preview at `~/Therum OS/previews/connections-and-dashboard.html`) is multi-phase work; this entry covers **Phase 1 — Foundation**. Subsequent phases will add their own dated entries.

### Top-level Admin reorganization

The Admin section in the sidebar nav (`therum-admin-ui.php`) gets two new top-level items so Customization and Connections are no longer buried inside Settings:

- **Plugins** (existing)
- **Users** (existing)
- **Customization** (new) — `admin.php?page=therum-customization`
- **Connections** (new) — `admin.php?page=therum-connections`
- **Settings** (existing — kept; houses the legacy registry sections that haven't migrated)

### New mu-plugin · `therum-customization.php` (Version: 1.8.7)

Top-level Customization route with the per-page inner-nav router pattern that will power the Themes / Branding / Login / List page defaults / Dashboard / Editor sub-pages.

- **`Therum_Customization::register( $id, $args )`** registry — same shape as `Therum_Settings::register()`. Tabs declare `label · section · icon · priority · render · desc · count`. Other mu-plugins extend the page via the `therum_customization_tabs` filter.
- **URL routing:** `admin.php?page=therum-customization&tab=X` selects the sub-page. Each tab is its own page (not an anchor-scroll within a long page). Bookmarkable. Deep-linkable.
- **Inner sidebar rail** rendered with three grouped sections: **Customization** (Active theme · Themes) · **Brand** (Branding · Login screen) · **Defaults** (List page · Dashboard · Editor).
- **Stub renderer** for tabs that don't yet have a real renderer. Each shows a `Phase 1 · scaffold` mark + a one-sentence note about where the real content will be ported from (the preview HTML section).
- **CSS asset** (`assets/therum-customization.css`) — page shell, inner-nav rail with sticky positioning, stub block pattern, mobile collapse at 900px.
- **7 default tabs registered** at `init` priority 20: Active theme (10) · Themes (20, count "24 · 3") · Branding (30) · Login screen (40) · List page (50) · Dashboard (60) · Editor (70).

### Version bump

- `THERUM_OS_VERSION` bumped from `1.8.5-Beta` → `1.8.7` in `therum-core.php`.
- Header docblock in `therum-core.php` matches.

### Build phases remaining (subsequent sessions)

- **Phase 2** — Themes page (combined store + saved + customize panel), the 38-option Quick Controls with collapsible groups, install/uninstall flow for available themes.
- **Phase 3** — Connections content port: AI Tools / APIs / Payment Gateways / External Apps cards, OAuth URL constructors, search + add-custom flows.
- **Phase 4** — Connections Manage trio: API keys vault · Webhooks log · Audit log (with real or stubbed data sources).
- **Phase 5** — Branding · Login screen · List page defaults · Dashboard layout · Editor preferences renderers.
- **Phase 6** — `therum-cache-bust.php` mu-plugin · WP 7.0 GA core bump (May 20) · rebuild Pro + Pure bundles · ship.

### Files touched

- `therum-admin-ui.php` — Admin section nav updated to expose Customization + Connections
- `therum-core.php` — version constant + docblock bumped to 1.8.7
- `therum-customization.php` (new, 250 lines)
- `assets/therum-customization.css` (new, 60 lines)

PHP lint clean across all touched files. Live admin smoke-test returns 302 (expected redirect on unauthenticated GET), no fatal markers in response.

---

## [1.8.7-prep] — 2026-05-13

WordPress 7.0 GA ships **May 20, 2026** — seven days from now. Today's pre-flight work positions Therum to absorb the 7.0 surface cleanly on day one. **The bundles are not bumped yet** — bumping against an unreleased RC ships risk to install-wizard runs. Core bump happens May 20 against the stable build.

### WP 7.0 deprecation sweep

Pulled the WordPress core developer notes for the April 2026 dev cycle and grepped Therum's 17 active mu-plugins against every flagged deprecation. Surface against 7.0 is clean:

- **`add_meta_box()`** — one usage in `therum-content.php:1078`. **Benign.** The call repositions existing core WordPress meta boxes (Author, Page Attributes, Discussion, Slug) from the main column to the side context for non-editor post types like `bricks_template` — it does not register new classic meta boxes, which is the pattern 7.0 flags as collaboration-mode-incompatible. The boxes being moved are WP's own; collaboration mode is already gated by those, not by the reposition. No change required.
- **`state.navigation`** (deprecated JS pattern in 7.0's Interactivity API) — zero hits. Therum's admin JS is vanilla (sidebar drag, dashboard resize, theme picker, AJAX fast-path) — it never adopted the Interactivity API, so the deprecation doesn't touch us.
- **`@wordpress/interactivity` references** — zero hits.
- **PHP lint clean** against the 7.0 surface — all 17 active mu-plugins pass `php -l` with no warnings.

Verdict: Therum lands on WP 7.0 without code changes. The bundles bump core and ship.

### Connectors strategy — option 2 (absorb, hide WP's)

WP 7.0 introduces a **Connectors API** + **WP AI Client** + a top-level "Connectors" admin UI for managing AI connections (OpenAI, Anthropic, Google AI, local models). This overlaps with Therum's existing connector registry (`therum-connections.php`) which currently covers CMS / ecommerce / generic APIs.

After weighing absorb / hide-and-replace / defer, we picked **absorb**: Therum's connector registry is the broader CMS-agnostic story; WP's is AI-specific. We pull WP's surface inside Therum and route everything through one canonical UI.

**Scaffolded in `therum-connections.php`:**

- New settings section **`connections-ai`** added at priority `118` (after `connections-apis`). Label: "Connect AI". Icon: `sparkles`. Description: "OpenAI, Anthropic, Google AI, local models — managed via WP 7.0 Connectors."
- Renderer `therum_render_connections_ai()` branches on `version_compare($wp_version, '7.0', '>=')`:
  - **Pre-7.0 (today + the week of RC):** renders a dashed-border stub card with the GA date (2026-05-20) and a one-paragraph explanation of what'll appear when core lands. Section exists in the nav so the eventual presence is visible.
  - **WP 7.0+:** renders the adapter shell and fires a `do_action( 'therum_connections_ai_render' )` hook. Post-GA, the adapter wires up WP's Connectors API + WP AI Client class instances inside Therum chrome.
- New `admin_menu` hook at priority `999` calls `remove_menu_page()` against three best-guess WP slugs (`wp-connectors`, `connectors`, `wp_connectors`) — the exact slug WP ships with will be confirmed at GA and the list narrowed. Hook is version-gated so it's inert on pre-7.0 installs.

**Inert behavior on the current source site (WP 6.9.4):** the AI section renders as the stub. The `remove_menu_page` hook is gated by `version_compare` and exits before doing anything. Zero risk.

### What ships May 20 (release plan)

1. Bump WP core in both `Therum-OS-Pro-1.8.5-Beta.zip` and `Therum-OS-Pure-1.8.5-Beta.zip` source site from 6.9.4 → 7.0.0 stable.
2. Rebuild both bundles via `./build.sh all`.
3. Confirm the exact WP 7.0 Connectors menu slug; narrow the `remove_menu_page` list in `therum-connections.php` accordingly.
4. Implement the `therum_connections_ai_render` hook handler — wire WP's Connectors API + WP AI Client into the Therum AI section.
5. Tag the release as **Therum OS 1.8.7** (Pro + Pure) — core bump + connectors absorption, no other feature surface changes.
6. Update `THERUM_OS_VERSION` constant in `therum-core.php` and the version footer in `therum-admin-ui.php` fallback.
7. Re-run PHP lint against the freshly-bumped surface; verify no new deprecation notices fire in WP 7.0 debug mode.

### Things explicitly NOT being adopted from WP 7.0

Per the CMS-agnostic north star, the following 7.0 features are skipped — adopting them deepens WordPress + Gutenberg coupling, which works against the eventual portability story:

- **Block Bindings expansion** — Gutenberg-side; Therum's path is away from Gutenberg.
- **New core blocks (Breadcrumbs, Icons)** — Gutenberg blocks.
- **Cover block video bg / responsive Grid block / Gallery lightbox** — Gutenberg blocks.
- **Per-block screen-size visibility (`viewport` key)** — Gutenberg block-level.
- **Pattern overrides for custom blocks** — Gutenberg patterns.
- **Interactivity API `watch()` / `state.url`** — Therum's admin interactivity is vanilla and works; migrating to Interactivity API reinvents what already ships.
- **`@wordpress/abilities` / `@wordpress/core-abilities`** — Gutenberg-aligned client state management; Therum has its own state model.
- **`@wordpress/build` (esbuild-based)** — not relevant for our mu-plugin asset pipeline.

### Things we'd absorb if they ship in 7.0 (not confirmed in current RC3 notes)

- **Native SQLite in core** — would let us drop `sqlite-database-integration` from the Pure manifest. Current 7.0 release notes don't mention it. Track for 7.1.
- **Script Modules / ESM admin loading** — if 7.0 lands a low-overhead ESM loader for admin scripts, migrate the bento grid + sidebar engine JS. Currently no headline confirmation.
- **In-browser image resize/compression** — confirmed for 7.0; comes for free with the core bump, no Therum integration needed.

### "Sans WordPress" leak sweep

Therum positions as **Therum + Bricks on a hardened substrate**. The substrate is an implementation detail, not a brand surface. This sweep scrubs the remaining places the underlying engine still leaked through.

**Sealed in this prep pass:**

- **`/wp-admin/about.php`, `credits.php`, `freedoms.php`, `privacy.php`** — these are WP-core admin pages with WP branding. Now redirect to `admin.php?page=therum` (Therum dashboard) via an `admin_init` hook in `therum-core.php` that checks `basename($_SERVER['PHP_SELF'])` against a leak list.
- **`X-Powered-By` HTTP header** — when PHP is configured with `expose_php = On`, the engine adds an `X-Powered-By: PHP/X.X` header to every response. `therum-core.php` now calls `header_remove('X-Powered-By')` on `send_headers`. Live check: header no longer present in front-end responses.
- **REST API `/wp-json/` root response** — added a `rest_index` filter at priority 20 that rewrites the response `name` to use `get_bloginfo('name')`, the `description` to use `get_bloginfo('description')`, and adds a new `engine` field reading `Therum OS {version}`. The default WP-derived "Just another WordPress site" fingerprint is replaced.
- **REST API `/wp-json/therum/v1/status`** — the `wp_version` field in the response renamed to `engine_version`. The Therum version is already disclosed as `therum_version`; the renamed field is honest about the engine without using the WP brand name.
- **Backup manifest.json** — `wp_version` in `therum-perf.php`'s backup zip manifest renamed to `engine_version`; added a `therum_version` alongside so the manifest is now Therum-first.
- **RSS / Atom feed `<generator>` tags** — `therum-core.php` now removes `the_generator` from all five WP feed hooks (`rss2_head`, `atom_head`, `commentsrss2_head`, `rdf_header`, `opml_head`). Live check: `/feed/` response no longer carries the generator XML element.

**Already sealed pre-1.8.7 (verified clean):**

- `<meta name="generator">` in `<head>` — stripped via `wp_head` action removal in 1.8.5.
- `<link rel="EditURI">` (RSD) and `<link rel="wlwmanifest">` — removed in 1.8.5.
- `xmlrpc.php` — disabled via `xmlrpc_enabled` filter.

**Still leaks — won't fix:**

- **`Server` HTTP header** — set by the web server (nginx/Apache) at a layer PHP can't override. Out of scope for a mu-plugin; users on managed hosts can configure this via `nginx.conf` / `.htaccess` if they care.
- **REST namespace `wp/v2`** — renaming breaks every REST client (themes, headless apps, plugins). Out of scope.
- **`/wp-login.php` URL** — could be remapped but a long tail of plugins, mobile apps, and integrations hardcode the URL. Out of scope.

Net effect: a user inspecting Therum OS via `view-source`, headers, REST root, RSS feeds, or back-channel admin URLs no longer sees WordPress branding. The engine still has GPL provenance — that's not hidden, just not foregrounded.

---

## [1.8.0 → 1.8.5-Beta] — 2026-05-09

The whole 1.8.x line shipped in a single session. v1.7.1-beta (Apr 28) was the last release with notes; this entry covers everything between then and now in one block — admin-chrome major rev (`therum-admin-ui.php` → 1.8.0), the card-layout family, three classes of long-standing CSS bug fixes, theme-palette retuning to match the bamleon front-end, and the installable bundle pipeline (Pro + Pure). Module versions across the mu-plugin set were stamped between 1.8.0 and 1.8.5 / 1.8.5-Beta during this same push.

### Mu-plugin consolidation & code optimization

The mu-plugin set went through a structural reshape between 1.7.1-beta and 1.8.5-Beta. At 1.7.1 there were 10 active modules with several specialized "engines" (perf, roles, api) doing focused jobs and a scatter of small single-concern files (login, 2fa, duplicate, view-links, motion, etc.). At 1.8.5-Beta there are 17 active modules. The shape changed in three ways:

1. **Small single-concern files were merged into thematic modules.** Five new 1.8.5 modules each absorb 2–5 of the older small files. The originals stay on disk renamed to `.disabled` so they don't load and don't clutter the active set, but the history is preserved if anything needs to be re-extracted.
2. **Two "engine" files were renamed** to their canonical short names as their scope settled (`-engine` suffix dropped).
3. **Three brand-new modules were added** to fill gaps in the architecture (connection registry, OPcache preload, AJAX fast-path, auto-gz). One older module (`therum-editor.php`) was retired and its responsibilities split across the new `content` and `design` modules.

The result: every active module has one clear remit, every file lints cleanly, every load path is auditable.

---

**Merges — new modules that absorbed older small files**

- **`therum-auth.php`** (`Version: 1.8.5`) — *Custom login screen skin + TOTP two-factor authentication.* Merged from:
  - `therum-login.php` — wp-login skin (resets WP's `login.min.css`, paints the page in the Therum palette + Inter, hot-pink accent on the submit button)
  - `therum-2fa.php` — TOTP/Google-Authenticator-compatible two-factor

- **`therum-content.php`** (`Version: 1.8.5`) — *Post management tools: duplicate, preview / live links, Case Study CPT, card-grid admin list, post editor skin.* Merged from five files:
  - `therum-duplicate.php` — duplicate-post row action + bulk action across every post type; copies title/content/meta/taxonomy/featured image; clears Bricks-template conditions on the duplicate; exposes `therum_duplicate_after` action
  - `therum-view-links.php` — "Preview" + "View Live" row actions; for Bricks templates resolves the template's conditions and surfaces a "View on site" link to a representative page
  - `therum-case-study-cpt.php` — registers the `case_study` post type, the `case_study_discipline` taxonomy (6 pre-seeded terms), and `case_study_tag`
  - `therum-cards-admin.php` — early version of the card-grid admin list (since absorbed into `therum-list-page.php`'s generic spine)
  - `therum-editor.php` — Pages → Bricks redirect + Posts classic-editor Therum skin + form skins (user-new, user-edit, profile, comments, taxonomies)

- **`therum-design.php`** (`Version: 1.8.5`) — *Design system pages (themes, Bricks-aware routes, customizer skin), native menus / widgets replacement, motion / animation engine.* Merged from:
  - `therum-design-pages.php` — themes grid, theme PDP, customizer skin
  - `therum-native-design.php` — Therum-native menus + widgets surface (replaces WP's `nav-menus.php` and `widgets.php` admin pages)
  - `therum-motion.php` — admin-side motion/animation primitives + view transitions

- **`therum-perf.php`** (`Version: 1.8.5`) — *HTML / CSS minification, scheduled backups, S3 upload, notifications, and LiteSpeed Cache one-shot tuner.* Renamed and merged:
  - `therum-perf-engine.php` → `therum-perf.php` (canonical name)
  - `therum-lscache-tune.php` — one-click LiteSpeed Cache configuration tuner

- **`therum-woo.php`** (`Version: 1.8.5`) — *WooCommerce bridge (Therum UI integration) and WC performance module.* Renamed and merged:
  - `therum-woo-bridge.php` → `therum-woo.php` (canonical name) — cart page, checkout skin, order emails
  - `therum-woo-perf.php` — light Woo perf shims per the woo-perf-scope memory doc

**Net effect of merges:** 5 active modules now do the job of 14 older ones. Inside each merged file the original section is preserved with a banner header comment (e.g. `// ════ LOGIN SKIN — from therum-login.php ════`) so the boundaries stay legible for future re-extraction.

---

**Brand-new modules (didn't exist before 1.8.x)**

- **`therum-connections.php`** (`Version: 1.8.5-Beta`) — *Connect CMS platforms, ecommerce stores, and third-party APIs.* Tile-grid UI in Settings — each connector has a config form + save. Backbone for the eventual CMS-agnostic story (the connector registry is what lets Therum talk to non-WP backends as that work lands).

- **`therum-preload.php`** — *OPcache preload script.* Not loaded as a mu-plugin per se; sits in the folder for path-reference convenience. Point `opcache.preload` in `php.ini` at this file (`opcache.preload=/.../mu-plugins/therum-preload.php` + `opcache.preload_user=www-data`) and PHP-FPM compiles all Therum mu-plugins at startup so the first request hits warm bytecode. Re-run after any mu-plugin edit (restart PHP-FPM).

- **`therum-ajax-fast.php`** (`Version: 1.0.0`) — *AJAX fast-path.* Six admin AJAX actions are pure user-meta or post-meta writes with no class dependencies: `therum_save_layout`, `therum_save_sidebar`, `therum_reset_sidebar`, `therum_save_pref`, `therum_save_view_pref`, `therum_save_card_layout`. This module intercepts them at `init` priority `-10` — **before** `wp_loaded`, `admin_init`, and all the `wp_ajax_*` hook machinery fires. Nonce-verified, write, `wp_die()`. Measurable latency drop on chatty admin pages where sidebar/layout state is being saved interactively.

- **`therum-asset-gz.php`** (`Version: 1.0.0`) — *Asset GZ sync.* Runs on every `admin_init`, stats each `.css/.js` file under `wp-content/mu-plugins/assets/`, and regenerates the matching `.gz` sibling whenever the source is newer. Solves the silent-stale-asset class of bugs where Apache's `mod_deflate` (Local includes it) ships pre-compressed `.gz` files to the browser when the client sends `Accept-Encoding: gzip` — without this, source edits to a CSS file weren't visible until the `.gz` was manually re-encoded.

---

**Renames (no scope change, just canonicalization)**

- `therum-perf-engine.php` → `therum-perf.php` — engine suffix dropped as the module's surface settled
- `therum-woo-bridge.php` → `therum-woo.php` — bridge suffix dropped, scope expanded slightly to include WC perf

---

**Retired to `.disabled`** — fifteen single-concern files no longer loading (their functionality lives in the merged thematic modules above):

| `.disabled` file | Folded into | Notes |
|---|---|---|
| `therum-login.disabled` | `therum-auth.php` | login skin |
| `therum-2fa.disabled` | `therum-auth.php` | TOTP 2FA |
| `therum-duplicate.disabled` | `therum-content.php` | duplicate-post action |
| `therum-case-study-cpt.disabled` | `therum-content.php` | case-study post type |
| `therum-cards-admin.disabled` | `therum-content.php` / `therum-list-page.php` | early card grid |
| `therum-editor.disabled` | `therum-content.php` + `therum-design.php` | classic editor skin, form skins, Pages→Bricks redirect |
| `therum-design-pages.disabled` | `therum-design.php` | themes grid + PDP |
| `therum-native-design.disabled` | `therum-design.php` | menus + widgets replacement |
| `therum-motion.disabled` | `therum-design.php` | motion primitives |
| `therum-lscache-tune.disabled` | `therum-perf.php` | LiteSpeed tuner |
| `therum-perf-engine.disabled` | `therum-perf.php` | renamed |
| `therum-woo-bridge.disabled` | `therum-woo.php` | renamed |
| `therum-woo-perf.disabled` | `therum-woo.php` | WC perf shims |
| `therum-global-admin-skin.disabled` | absorbed into `therum-admin-ui.php` chrome | global skin overrides |
| `therum-nextbricks-skin.disabled` | parked — NextBricks integration kept as plugin-side skin | experimental |

Files are kept on disk so the merge sources are auditable. The bundle builder excludes `*.disabled` entirely so they don't ship in either Pro or Pure.

---

**Code-path optimization**

- **Single-responsibility split.** Every active module has one clear scope from its docblock. PHP lint runs in milliseconds per file. Editing a content-side hook no longer means scrolling through 800 lines of design-system code.
- **`therum-ajax-fast.php`** short-circuits the six most-fired admin AJAX actions. Pre-1.8 the same calls went through the full `admin_init` → `wp_ajax_*` chain (loading the whole plugin/theme stack); 1.8.x routes them at `init` priority `-10`, before any of that boots. On the busy edit-mode pages where sidebar order and per-post layout overrides are saved interactively, this is the difference between every drag-end taking ~150ms vs ~15ms.
- **`therum-asset-gz.php`** removes a class of "my CSS edit isn't showing" debug cycles. Pre-1.8.5 you had to remember to run `gzip -9 -k -f` after every CSS edit or `mod_deflate` would keep shipping the old compressed twin. Now the mu-plugin handles it on the next admin request, automatically.
- **`therum-preload.php`** for OPcache makes the cold-cache request fast on production hosts — PHP-FPM compiles all 13 active Therum mu-plugins at startup, so the first request hits warm bytecode instead of paying the parse/compile cost.
- **CSS housekeeping.** Stripped three stray `<style>` HTML tags out of `therum-shell.css` (at byte offsets 1311 / 25325 / 27557). CSS parsers treat `<style>` as an invalid selector and discard the entire following rule block — which silently killed the `:root { … --topbar-h: …; --ac: …; }` declaration. This explained a recurring "my CSS edits aren't showing" symptom across the session.
- **Variable-name unification.** Renamed every long-form CSS custom-property declaration in `therum-theme-palettes.css` (`--surface`, `--text`, `--border`, `--accent` → `--sf`, `--tx`, `--bd`, `--ac`) to match what the shell consumes. ~107 theme presets were silently only swapping `--bg` before this fix; everything else was rendering on the shell defaults regardless of the selected theme.
- **Plugin-card defensive layout.** Locked the Plugins page's card structure with high-specificity rules immune to bleed-in from other `.th-lp-card-layout-X` selectors. Prevents the character-by-character text wrapping that surfaced when generic flex/grid rules from other layouts cascaded into plugin cards.

### Admin chrome — major rev (`therum-admin-ui.php` → 1.8.0)

The admin chrome went through its largest single rev since 1.0.0. The file grew from ~424 lines at v1.0.0 to well over 1,000 lines, and the shape of the admin changed substantially.

**Sidebar header.**

The header block at the top of the rail now combines the site logo (32px rounded square in the active accent color, displaying the first letter of the site title), the site name (truncates with ellipsis on overflow), and the site host (small grey URL under the name). It sits inside its own 72-pixel-tall flex container with a bottom border, matching the topbar height pixel-for-pixel so the two surfaces feel continuous across the seam.

**Sidebar nav engine.**

The nav is no longer a static list. It's a fully editable hierarchy:

- **Sections** can be collapsed/expanded individually, with a rotating chevron indicating state.
- **Drag-to-reorder** for both sections and items inside sections. Drop indicators show up as inset shadow lines (top edge / bottom edge / "drop into" highlights). Sections can also be reordered relative to one another.
- **Inline rename** — clicking the rename icon on a section turns its label into an editable input. Enter to save, Escape to cancel.
- **Deletion with capability check** — sections can be deleted; the request is gated by `current_user_can('manage_options')`. The default sections (those shipped by Therum) are protected from deletion at the engine level.
- **"Add section"** dashed-border tile appears only when the body has the `th-edit-sb` class (sidebar edit mode toggled on). Clicking it inserts a new editable section above.
- **Sidebar edit toolbar** docked at the bottom of the rail in edit mode, with Reset / Cancel / Done buttons. Reset returns the sidebar to the default ordering.
- **Three sidebar style modes** wired through body classes: `th-sl-icons` (icons-only, sidebar collapses to 64px), `th-sl-text` (text-only, no icons, no logo), and the default full mode (icons + text).
- **Floating sidebar variant** — `body.th-sb-floating` lifts the sidebar off the edge with a 24px margin, applies a soft shadow, and shifts `#th-main`'s left margin by an extra 24px to match.
- **Item children** — items can have nested children (collapsing tree). Active child rolls the parent's chevron and applies a "child-active" highlight. Child rows use a left rule for visual hierarchy.

The whole edit-mode UX was rebuilt so the nav can be reshaped without leaving the page — no separate "edit menu" admin screen needed. State persists to user-meta via the AJAX fast-path (one of the six pre-loaded actions).

**Topbar.**

Slimmed to four elements: page title (left, derived from the current admin page's label via a nav-walk loop), a theme toggle button (sun/moon icon, toggles `body.light`), an external-link button to the front-end site, and the user avatar (32px circle showing the first letter of the display name in the accent color). Height pinned to `var(--topbar-h)` so it stays aligned with the sidebar header. Sticky-positioned at top with `z-index: 90`, transparent border-bottom, surface background.

**Dashboard bento grid.**

A 12-column dense flow with `grid-auto-rows: minmax(120px, auto)` and `grid-auto-flow: dense`. Cards declare their footprint via `data-size`, which maps to grid spans:

- `xs` — span 3 cols × 1 row
- `sm` — span 6 × 1
- `md` — span 9 × 1
- `lg` — span 12 × 1 (full row)
- `sm-square` — span 6 × 2
- `md-tall` — span 6 × 3
- `lg-tall` — span 9 × 2
- `xl-hero` — span 12 × 2 (full hero card)

Each size has its own internal layout: card-label sizes shift, stat value font scales (32px → 96px depending on size), sparklines grow taller, breakdown rows get more padding, and the hero size splits into a 1fr-1fr internal grid so a stat value + a content panel can sit side by side. Content elements have show-at-size classes (`show-xs`, `show-sm`, `show-md`, `show-lg`, `show-xl`) so cards reveal more detail as they get bigger.

**Edit-layout mode** is toggled via `body.th-edit-layout`. While active:
- Cards switch to a grab cursor with a dashed border.
- Each card grows a size-picker button (top-right) that opens a 4×4 size grid for instant resize.
- Eight resize handles appear on each card (NW/NE/SW/SE corners + N/S/E/W edges) for drag-resize. The active drag locks `body.th-resizing` and shifts the cursor to `nwse-resize` / `nesw-resize` / `ns-resize` / `ew-resize` based on the handle.
- A placeholder card with a dashed accent border shows the drop target as the user drags.
- An edit-bar sticky-pinned below the topbar offers Done / Cancel.
- All non-grid card content gets `pointer-events: none` so drag handling owns the interaction.

**Density tiers.**

Three body-level classes wire density through every Therum surface:
- `body.density-compact` — row pad 10px, nav pad 6×16px (tight)
- `body.density-comfortable` — row pad 22px, nav pad 14×22px (default+)
- `body.density-breathing` — row pad 36px, nav pad 20×26px (loose) — also enables `backdrop-filter` blur on the sidebar, topbar, and cards for a glass effect at this density tier.

**Glass / surface variants.**

`body.glass` (and the more specific `body.glass-tint-light` / `body.glass-tint-dark`) turn the wpwrap background transparent and apply heavy `backdrop-filter: blur(40px) saturate(150%)` to the sidebar, topbar, and cards. Theme-aware light/dark glass tints adjust the rgba alpha.

**Page-title derivation.**

When the admin renders, a nav-walk loop finds the item whose `match` attribute equals the current `$cur_match` and uses its label as the topbar title. Children are walked too — so a Settings → Appearance route shows "Appearance" in the topbar, not "Settings". If nothing matches, falls through to "Dashboard".

**Frame mode.**

`body.th-frame` collapses `#th-shell` to a single block (no flex, no sidebar, no topbar) for pages that need a full-bleed clean canvas — used by the Bricks builder route, the installer, and the customizer skin.

**De-dupe shim.**

A small style block (`<style id="therum-dedupe-css">`) defensively hides any duplicate `#th-shell` or `#th-sb` that might appear on a page (race conditions during certain plugin admin renders). Belt-and-suspenders.

---

### Card layouts — added

This was the largest visual feature push in the 1.8.x cycle. Where 1.7.x had a "card system" with 4 layouts × 5 image sources, the user worked through reference images for each new layout and we built six new presets across two families (Card and Compact) plus reworked Hero and Magazine. The `cardLayout` setting now exposes six selectable presets across the post-type list pages (Pages, Posts, Case Studies). Each renders the same backing data through a different visual frame, and per-post `_th_card_layout` meta overrides the global setting.

**The render fork.**

The Pages and Posts renderers in `therum-list-page.php` were restructured with explicit `elseif` branches at the top of `render_card()`, one per layout. Earlier code had a single output structure with `if ($layout !== 'X')` guards scattered throughout — this didn't scale to six layouts. The new structure keeps the outer `.th-lp-card` wrapper + data-* attributes + kebab common to all layouts, but forks the inner structure entirely per layout. Each branch reads only the data it needs (some layouts pull author name + avatar URL + min-read; others just need title + status). This is duplicated across the two render_card methods (Pages and Posts) — the duplication is acceptable for now because the methods serve different data shapes, but future work might extract a shared layout-renderer interface.

**Card V1 — Poster.**

Modeled after a "Make AI Works for You" reference image: full-bleed thumbnail with title + body + "Explore →" link overlaid at the bottom.

- 3:4 aspect ratio card (vertical poster proportions).
- `.th-lp-card-thumb` is absolutely-positioned full-bleed inside the card with `background-size: cover`, `background-position: center`.
- A `::after` pseudo-element on the thumb paints a soft top-to-bottom gradient (`linear-gradient(to bottom, transparent 35%, rgba(0,0,0,.2) 60%, rgba(0,0,0,.65) 100%)`) so the bottom of the thumb has enough darkness for white text to land cleanly.
- Status pill anchored top-left (`top: 14px; left: 14px`), white-translucent background (`rgba(255,255,255,.92)`), dark text, uppercase with `.04em` letter-spacing, status dot prefix.
- Kebab menu repositioned top-right with `z-index: 4` so it floats above the thumb.
- Bottom overlay (`.th-lp-card-v1-overlay`) holds title (20px, weight 700, white with a 0.25 text-shadow), excerpt (13px, `rgba(255,255,255,.82)`, 2-line clamp), and a "Edit →" CTA where the arrow nudges further on hover (gap goes from 6px to 10px).
- Whole card is a single anchor → opens the editor directly (no separate View Live action; that's still in the kebab).
- Hover: `translateY(-2px)`, deeper shadow (`0 10px 28px rgba(0,0,0,.1)`).

**Card V2 — Detailed (property-card style).**

Modeled after a real estate property card with rounded thumb, status pill on image, action icons on image, price/rating row, title, address, feature icons, and an author footer with a green call button. We mapped each property field to admin-relevant data:

- Image (top, rounded `16/10` aspect, 12px border-radius inside a 10px-padded card)
- Status pill bottom-left of image (white-bg, `0 0 1px 3px` shadow for visual lift)
- Two glass-circle icon buttons bottom-right of image: View Live (external-link SVG, opens in new tab with `event.stopPropagation()` so it doesn't trigger the card click) and a bookmark (SVG) — both 28px circles, `rgba(255,255,255,.95)` backgrounds, `backdrop-filter: blur(8px)`.
- Body section with a "headrow" — left side has a 20px bold word count (`.th-lp-card-v2-primary-num`) + " / words" small unit; right side has a star icon (Lucide-style polygon, filled `#f59e0b`) followed by the modified-time string (this slot maps the property card's "4.9/5.0 rating" to "modified 2 days ago" in admin context).
- Title (15px, weight 700) with 1-line ellipsis.
- Excerpt (12px, `--tx3`, 1-line clamp at 14 words).
- Three feature pills in a row at the bottom of the meta block, each with a tiny SVG icon + label: words count, modified time, and author name. Separated from the rest of the meta by a top border (1px solid `--bd`).
- Author footer **outside** the click target (its own absolutely-positioned block): 34px avatar via `get_avatar_url($author_id, ['size'=>56])`, author name + role ("Author") in stacked text, and a 38px filled `#10b981` green circular Edit button on the right with a pencil SVG.
- Kebab hidden for this layout (`display: none`) because the green button is the primary action and the kebab redundancy was visually noisy.

**Compact V2 bookmark → kebab.**

Initially Compact V2 had a bookmark button in the same green-circle slot as Card V2 — the user pushed back ("compact v2 needs 3 dot menu no book mark"), so the bookmark was stripped from the PHP and the kebab restored, repositioned as a static element with `margin-left: 8px` instead of the prior absolute-positioned bookmark.

**Hero — redesigned.**

The old Hero was a full-bleed image with title + date overlaid on the image at the bottom — close to what Card V1 is now. The user wanted Hero to look like a "Santorini Sunset Loft" property card reference: image up top, white meta below, pill row, two CTA buttons at the bottom.

- Card height auto (was fixed 320px), flex column.
- `.th-lp-card-thumb` switched from absolute-positioned full-bleed to relative 4:3 aspect, no overlay gradient.
- Below the thumb, a `.th-lp-card-meta` block with 16-18-12px padding holds the title (17px, weight 700), excerpt (13px, `--tx2`, 2-line clamp), and a new `.th-lp-card-pills` row.
- Pills row contains the status tag + words count + "X ago" time-ago pill, all small `--sf2`-background `--bd`-bordered pills with 999px border-radius.
- Below the meta, a `.th-lp-card-actions` row with two equal-width buttons: View Live (outline) and Edit Page (filled `--tx` background — black in light mode, white in dark mode). Always visible (the old Hero hid them until hover).
- The thumb still uses gradient/wireframe/pattern/featured/stock as its background per the existing image-source picker.
- All the old `.th-lp-card-hero-overlay` / `.th-lp-card-hero-date` rules are explicitly `display: none !important` so any leftover markup doesn't render.

**Compact — redesigned (wide-row).**

Old Compact was a vertical-stack card with title + excerpt + sub stacked inside a 56px-thumbnail row. The user shared a "Top Playlist · Say Yes to Heaven" reference showing items in a much wider row with multiple meta cells spread across:

- Card switched from flex column to flex row, single column grid (`grid-template-columns: 1fr` on the `.th-lp-view-grid`).
- `.th-lp-card-link` is a grid: `52px minmax(140px, 2fr) minmax(80px, 1fr) minmax(110px, 1.2fr) minmax(80px, 1fr) auto` — six cells.
- Cell 1: 52px square thumb (8px border-radius).
- Cell 2: title (14px, weight 600, 1-line ellipsis).
- Cell 3: `#status` tag in accent color (13px, weight 500, lowercase).
- Cell 4: doc-icon SVG + word count (13px, `--tx2`).
- Cell 5: clock-icon SVG + "X min" read time computed as `ceil($words / 200)`.
- Cell 6 + kebab: status dot (10px circle with `box-shadow: 0 0 0 3px` colored halo in green for publish, amber for draft, blue for future, purple for pending, red for trash) + kebab menu.
- Hover lights up the row with `--sf2` background; no translate, no border-color change.
- Default card-meta, card-actions, and tag overlays all hidden in this layout.

**Compact V1 — Tight list.**

A denser variant of Compact, modeled after the "My Collection · The Shade / Oh My God" mobile reference (small square thumb + title + subtitle + dot menu):

- Single-column grid, 2px gap between rows.
- Each row: 48px square thumb + 2-row flex meta (title + "{status} · {time ago}" subtitle in `--tx3`) + kebab.
- Title nowraps with ellipsis. Subtitle ditto.
- Hover lights up with `--sf2` background, 10px border-radius.

**Compact V2 — Editorial list.**

The "New Releases · The Black Fawn" reference: larger portrait thumb on the left, date label above title, author name, meta row with icon-prefixed status + min-read, and a circular Edit button on the right.

- Single-column grid, no gap, 1px bottom border per row as a divider.
- Each row: 84×104 portrait thumb (10px border-radius) + 4-line stacked meta + kebab.
- Date label: 11px, weight 500, `.02em` letter-spacing, `--tx3`.
- Title: 16px, weight 700, 1-line ellipsis.
- Author: 12px, `--tx2`.
- Meta row at the bottom: doc-icon + status label, clock-icon + "X min". Each meta item: 11px, weight 500, `--tx3`, icon `flex-shrink: 0`.

**Magazine — redesigned.**

The user sent a "What's this. / 美しい色 / Download Now" editorial spread reference — big bold headline, side-by-side images, asymmetric whitespace, black pill CTA. The old Magazine layout was a 45%/55% horizontal split with image left + copy right. New Magazine is per-card editorial:

- Single-column grid with 18px gap between cards (each card is a full editorial spread).
- Card: white surface, 1px border, 18px border-radius, 36×40×32px padding, no shadow at rest.
- Top row: small uppercase post-type label (left, e.g. "Page") + small status · date right-aligned. Both 11px, weight 600, `.04em` letter-spacing, `--tx2`/`--tx3`.
- Title: 48px, weight 800, `-0.025em` letter-spacing, line-height 1.05, max-width 60% of card. Big editorial display type.
- Below the title, a 2-column grid: left column has a 32×1px rule (decorative, 55% opacity), then a small uppercase meta label ("{words} words · X ago"), then the excerpt (14px, `--tx2`, line-height 1.6, 5-line clamp), then a filled-black "Edit Page →" pill CTA (12×28px padding, 999px radius, gap nudges from 8 to 12px on hover).
- Right column: a tall 280px thumb image (full width of the column, cover background-position center).
- Mobile (≤760px): grid collapses to single column, title drops to 32px, body grid becomes 1fr, thumb shrinks to 200px tall.
- Kebab repositioned to `top: 32px; right: 32px` so it doesn't fight the title for visual space.

**Settings UI for the layout picker.**

`Settings → Card Layout` shows a grid of preview tiles (one per layout). Each tile shows a simplified visual of the layout (thumbnail rectangle + content overlay/below) and the layout's name + description. Clicking selects + saves via AJAX (one of the six fast-path actions).

**Per-list toolbar dropdown.**

The card-style toggle in the list-page toolbar (top of each list view) now includes all six layouts in the dropdown. Active layout is highlighted with an accent dot.

**Per-post layout override.**

`_th_card_layout` post-meta is honored by the layout resolver: if a post has a stored override and it's a valid layout key, that wins over the global setting. Useful for one-off cards that need a different presentation.

### Card layouts — removed

- **"Card" (base)** — the simpler original "Card" layout (image on top + meta below, before V1/V2 were added) was removed. The validation list in `Therum_Card_Style::layout()` and the AJAX-fast handler no longer accept `'card'` as a valid value. Existing posts with a stored `_th_card_layout = 'card'` value fall through validation and use the default (Hero). The old `.th-lp-card-layout-card` CSS rules are still in the file (dead code, not selected by anything) — left in place rather than deleted to avoid breaking any post that might briefly reference the class during transitions.

---

### Themes — added

The "kinda familiar" group expanded with three new presets, each modeled after a specific product UI.

**Apple Music** (`familiar-apple-music`).

Dark mode primary. The Apple Music app's identity is a black canvas with a bright pink-red accent and album-art surface tints. The Therum preset captures the framework without copying any owned assets:

- `--bg: #0a0a0a` — inky black.
- `--sf: #171717`, `--sf2: #262626` — neutral dark surfaces.
- `--bd: #3a3a3a`, `--bd2: #fa233b` — neutrals + accent-driven divider.
- `--tx: #ffffff`, `--tx2: #a3a3a3`, `--tx3: #737373` — high-contrast text ladder.
- `--ac: #fa233b` — Apple Music's signature pink-red.
- Glass enabled, floating sidebar, system font (`-apple-system, BlinkMacSystemFont, …`), medium radius, soft shadow, comfortable density.
- Light variant inverts to `--bg: #fafafa`, `--sf: #ffffff`, etc., same accent.
- Preview tile uses `linear-gradient(135deg, #1a0d12, #2d0a1f 60%, #0a0a0a)`.

**Lucid** (`familiar-lucid`).

Two iterations. The first attempt landed Lucid as a Lucidchart-style theme — light mode, soft aqua `#06b6d4` accent. The user clarified: "lucid like car ui" — meaning Lucid Motors' Lucid Air cabin. The theme was retuned to match the EV cockpit aesthetic:

- Dark mode primary. `--bg: #020617` — deep near-black with a hint of blue.
- `--sf: #0a1426`, `--sf2: #111e36` — lifted blue-black surfaces.
- `--bd: rgba(0,212,255,.14)`, `--bd2: #00d4ff` — cyan-tinted dividers.
- `--tx: #f8fafc`, `--tx2: #94a3b8`, `--tx3: #64748b`.
- `--ac: #00d4ff` — electric cyan that recalls the EV charge indicator color.
- `--ac-h: #22e5ff` (hover), `--ac-s: rgba(0,212,255,.1)` (subtle/selected state).
- Glass enabled, floating sidebar, Inter font, round radius, soft shadow, **breathing density** (loosest tier — the cabin feel).
- Light variant: `--bg: #f8fafc`, `--sf: #ffffff`, slate text ladder, deeper teal `--ac: #0891b2` so readability holds outside the dark cabin.

**Xfinity Member** (`familiar-xfinity`).

The user shared the CIX-9287 membership-relaunch preview graphic — floating glassy member cards on a midnight-violet field with the X embossed. The Therum preset distills the membership-tier vibe:

- `--bg: #0a0846` — midnight purple-blue.
- `--sf: #14116b`, `--sf2: #1f1c8a` — lifted violet surfaces.
- `--bd: rgba(168,85,247,.18)`, `--bd2: #a855f7` — purple-tinted dividers.
- `--tx: #f5f3ff`, `--tx2: #c4b5fd`, `--tx3: #8b7fb8` — lavender-leaning text ladder for readability against the violet bg.
- `--ac: #a855f7` — vivid Xfinity-card violet.
- `--ac-h: #c084fc`, `--ac-s: rgba(168,85,247,.14)`.
- Glass enabled, floating sidebar, Inter font, medium radius, soft shadow, comfortable density.
- Light variant: `--bg: #faf9ff` (lavender white), white surfaces, deeper purple `--ac: #7c3aed`.
- Preview tile uses `radial-gradient(ellipse at 30% 25%, #3b1f8a, #0a0846 60%, #050129)` — capturing the original graphic's spotlight glow.

All three were added to the "familiar" group of `Therum_Themes::presets()` with full `name` / `desc` / `mode` / `accent` / `density` / `sidebar` / `sidebarStyle` / `font` / `radius` / `shadow` / `glass` / `bgImage` / `palette` / `previewMain` / `previewRail` declarations, and matching palette CSS rules appended to `therum-theme-palettes.css`.

### Themes — retuned

**Studio** — default theme, retuned to match the bamleon front-end exactly.

The journey: the user asked to "edit the therum studio themes to resemble our front end. like the home page." A live curl against `bam-leon.local` pulled the rendered home page, and a sweep of the inline `<style>` extracted the front-end's `--therum-*` design tokens. The Studio palette was then rewritten to mirror those tokens:

- Dark (default mode):
  - `--bg: #0a0a0a` (was `#0f0f0f`)
  - `--sf: #141414` (was `#1a1a1a`)
  - `--sf2: #1c1c1c` (was `#222222`)
  - `--bd: rgba(255,255,255,.08)` (was `#2a2a2a` — flat hex)
  - `--bd2: rgba(255,255,255,.16)` (was `#3a3a3a`)
  - `--tx: #ffffff` (unchanged)
  - `--tx2: #a3a3a3` (was `#bbbbbb`)
  - `--tx3: #888888` (was `#969696`)
  - `--ac: #f5389a` — hot pink, matching `--therum-accent` on the front-end (was `#3b82f6` / blue)
  - `--ac-h: #f55ab0`, `--ac-s: rgba(245,56,154,.12)` added
- Light mode:
  - `--bg: #fafafa` (was `#f6f6f6`)
  - `--sf: #ffffff` (unchanged)
  - `--sf2: #f0f0f0` (unchanged)
  - `--bd: rgba(0,0,0,.08)` (was `#e5e7eb`)
  - `--bd2: rgba(0,0,0,.16)` (was `#d1d5db`)
  - `--tx: #0a0a0a` (was `#0f172a`)
  - `--tx2: #404040` (was `#475569`)
  - `--tx3: #6b6b6b` (was `#94a3b8`)
  - `--ac: #f5389a` — same hot pink, different shading
- Sidebar bg dropped to `#0f0f0f` for a subtle level break in dark mode (was `#131313`).
- Theme description changed from "Clean. Versatile. Default vibe." to "Bamleon front-end. Pitch black. Hot-pink pop."
- The theme `accent` field in the `Therum_Themes::presets()` array updated from `#2563eb` → `#f5389a`. `previewMain` from `#1a1a1a` → `#0a0a0a`. `previewRail` from `#2563eb` → `#f5389a`.

After this retune, opening the admin in Studio mode feels visually continuous with the public site.

### Themes — fixed

**The palette-variable-name bug (affected ~107 themes).**

This one was hiding in plain sight for months. The admin shell (`therum-shell.css`) declares its working CSS custom properties under short names: `--sf`, `--sf2`, `--bd`, `--bd2`, `--tx`, `--tx2`, `--tx3`, `--ac`, `--ac-h`, `--ac-s`. Every Therum component that wants to be theme-aware reads `var(--sf)` / `var(--tx)` / etc.

The palette file `therum-theme-palettes.css` had been built (likely originally hand-written) using **long, descriptive names**: `--surface`, `--surface-2`, `--border`, `--border-2`, `--text`, `--text-2`, `--text-3`, `--accent`. So when a user switched to e.g. the macOS Sonoma theme, the rule fired:

```css
body.theme-familiar-macos.light{
  --bg:#f5f5f7;
  --surface:#ffffff;       /* nobody reads var(--surface) */
  --surface-2:#ebebed;     /* nobody reads var(--surface-2) */
  --border:#d2d2d7;        /* nobody reads var(--border) */
  --border-2:#0a84ff;
  --text:#1d1d1f;          /* nobody reads var(--text) */
  --text-2:#515154;
  --text-3:#86868b;
  --accent:#0a84ff;        /* nobody reads var(--accent) */
}
```

`--bg` was the only variable name that matched between the palette file and the shell's expected vocabulary. So when a non-default theme was selected, **only the background color changed**; every surface, border, text shade, and accent stayed on the shell's `--sf: #ffffff` / `--tx: #0a0a0a` defaults regardless of which theme the user picked.

This affected ~107 theme rule blocks (everything but the default Studio).

**The fix.** A perl-driven find-replace ran across the palette file:

- `--surface-2:` → `--sf2:`
- `--surface:` → `--sf:`
- `--border-2:` → `--bd2:`
- `--border:` → `--bd:`
- `--text-3:` → `--tx3:`
- `--text-2:` → `--tx2:`
- `--text:` → `--tx:`
- `--accent:` → `--ac:`

Initially the regex only matched declarations (`--name:`). A second pass cleaned up `var(--name, fallback)` references with the same renames:

- `var(--accent` → `var(--ac`
- `var(--surface-2` → `var(--sf2`
- `var(--surface` → `var(--sf`
- `var(--border-2` → `var(--bd2`
- `var(--border` → `var(--bd`
- `var(--text-3` → `var(--tx3`
- `var(--text-2` → `var(--tx2`
- `var(--text` → `var(--tx`

Verification grep confirmed zero leftover long-name declarations or references. Result: every theme preset now actually applies.

A backup of the original palette file was saved as `therum-theme-palettes.css.before-rename` so the renaming can be audited.

**macOS Sonoma — sidebar broken (the second macOS bug).**

After the variable rename, macOS Sonoma still wasn't right. The user reported the sidebar "isn't working." Investigation traced to a rule deeper in the palette file:

```css
body.theme-familiar-macos.light{
  --sb-bg:rgba(245,246,250,0.72);
  backdrop-filter:blur(28px) saturate(160%);  /* ← applied to body */
}
```

The intent was clearly to give macOS-themed sidebars a frosted-glass effect. But `backdrop-filter` was applied to `body`, not to `#th-sb` (the sidebar). And CSS has a quirk: **when an element has `backdrop-filter` (or `filter` or `transform`), it becomes the containing block for any `position: fixed` descendants** — those fixed elements are then positioned relative to the body rather than the viewport.

`#th-sb` is `position: fixed`. So with `body` doing the backdrop-filter, the sidebar lost its viewport-anchoring and started behaving inconsistently — moving around as content scrolled, possibly clipping, in any case "not working."

**The fix.** Split the rule into two:

```css
body.theme-familiar-macos.light{
  --sb-bg:rgba(245,246,250,0.72);
}
body.theme-familiar-macos.light #th-sb{
  backdrop-filter:blur(28px) saturate(160%);
  -webkit-backdrop-filter:blur(28px) saturate(160%);
}
```

Now the blur applies to the sidebar itself (blurring whatever's behind it), and `body` is no longer creating an unintended containing block. Sidebar is fixed and behaves.

---

### Admin shell — layout

**Topbar / sidebar header height alignment.**

The sidebar header (`.th-sb-header`) and topbar (`#th-top`) both reference `var(--topbar-h)`. At 1.7.1-beta this was set to `64px`. The user reported the topbar looked visually shorter than the sidebar header (which contains the logo + site name + URL). Bumped `--topbar-h` from `64px` → `72px` so both surfaces have the same generous vertical room. Single var, both elements pinned to it, both heights move in lockstep.

**Full-width pages — multiple iterations.**

The user wanted the admin to span the full viewport width between the main sidebar's right edge and the browser edge. The journey went through three attempts:

1. **First attempt** — added a "shell width fix" `<style>` block at the end of `therum-shell.css` setting `.th-dash, .th-lp, .th-settings-content { max-width: 1280px !important; margin: 0 auto !important; }`. Result: pages were centered with white gutters on both sides. The user said "this isnt spanning full width. no white should be showing."

2. **Second attempt** — changed `.th-settings { max-width: none !important; margin: 0 !important; width: 100% }`. Result: settings page sidebar collapsed weirdly and showed the WP-Admin classic sidebar bleeding through (settings nav rail wasn't laying out correctly).

3. **Third attempt** — full revert of the settings outer padding + rounded panel iteration; settings nav rail back to using `--sf2` background + a right border for separation; `.th-settings` gets `padding: 0 32px` to inset from the screen edges; `.th-dash` and `.th-lp` get `padding: 32px 32px 80px` (top, sides, bottom).

4. **Fourth iteration** — user said "increase to 60px." Bumped the L/R padding on `.th-dash, .th-lp` from `32px` → `60px`. Settings outer padding also pushed to `60px` so all three page families have consistent breathing room. Now `padding: 32px 60px 80px` on dashboard/list, `padding: 0 60px` on settings, no max-width anywhere.

**Settings nav rail.**

`.th-settings-nav` uses `background: var(--sf2)`, `border-right: 1px solid var(--bd)`, `padding: 24px 0`, with internal `display: flex; flex-direction: column; gap: 6px` for the section links. No rounded panel, no shadow — clean flush rail with the slightly-lifted surface color separating it from the content area.

**Plugin-card defensive layout.**

The user reported plugin cards showing description text wrapping per character ("AI / p.. / v2.2.0 · / WaveDepth" instead of "AI plug... / v2.2.0 · WaveDepth"). Diagnosis: layout-X CSS rules (compact, hero, etc.) were bleeding into the plugin card markup because plugin cards use `.th-lp-card` (the generic class) without a layout-X class — and the cascade of newer layout rules contained `flex` and `grid` directives that fought the plugin card's intended block layout.

**The fix.** Added a defensive block at the end of `therum-list-page.css` with high specificity (`body .th-lp .th-lp-card.th-lp-card-plugin`) that explicitly locks plugin cards to:

- Outer card: `display: flex; flex-direction: column; padding: 0; border-radius: 14px; box-shadow: 0 1px 2px rgba(0,0,0,.04)`.
- `.th-plugin-card-link` (the inner anchor): `display: block; padding: 0; flex: 1; width: 100%`.
- `.th-lp-card-meta`: `display: block; padding: 16px 18px 12px; background: transparent; flex: none`.
- `.th-lp-card-title-row`: `display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: nowrap`.
- `.th-lp-card-title`: 14px / weight 600, 1-line ellipsis, `flex: 1; min-width: 0`.
- `.th-lp-card-excerpt`: `display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: normal; overflow-wrap: normal`.
- `.th-lp-card-sub`: 11px, `--tx3`, 1-line ellipsis.
- `.th-lp-card-update`: 11px in warning color when an update is available.
- `.th-lp-status`: flex-shrink 0, nowrap.
- `.th-plugin-card-actions`: `display: flex; gap: 8px; padding: 0 18px 14px; flex-wrap: wrap`.
- Suppressed any inherited `::after` decorators (`.th-lp-card-title-row::after { display: none; content: none }` and same on `.th-lp-card-meta::after`).
- Disabled `word-break` and re-enabled normal `overflow-wrap` so descriptions wrap by word, not by character.

Plugin cards now lay out correctly regardless of which `cardLayout` is set globally.

---

### Infrastructure — added

**`therum-asset-gz.php` mu-plugin (`Version: 1.0.0`).**

Born out of a debugging session where the user reported that none of the CSS changes were showing up despite hard refreshes. Investigation: the mu-plugins/assets directory ships `.css` files paired with `.css.gz` siblings. Apache's `mod_deflate` (Local includes it) will preferentially serve the pre-compressed `.gz` when the browser sends `Accept-Encoding: gzip`. If the `.gz` is older than the source `.css`, the browser keeps getting stale content even after a hard refresh, because the server is shipping a compressed file that's older than what the browser would see on disk.

This module runs on every `admin_init`:

1. Globs `wp-content/mu-plugins/assets/*.{css,js}`.
2. For each file, checks if a `.gz` sibling exists.
3. If it does, compares `filemtime()` of the source vs. the `.gz`.
4. If the source is newer, reads the source, runs `gzencode($content, 9)`, writes to the `.gz`, and calls `touch($gz, $source_mtime)` so the timestamps line up.

It's idempotent and cheap — six file stats per admin page load. After this module was added, source CSS edits became visible immediately on the next admin request without manual `gzip` runs.

Saved a memory entry about this gotcha so future sessions know about it: `project_asset_gz_pairs.md` — "mu-plugin keeps .gz siblings fresh; mod_deflate serves stale .gz if you don't."

**Stray `<style>` tags removed from CSS.**

A multi-hour debugging mystery: edits to `therum-shell.css` weren't reflecting in the browser, even after the .gz fix. Cause: at byte offsets `1311`, `25325`, and `27557` inside `therum-shell.css`, someone (probably a prior copy-paste from a PHP file) had pasted `<style id="therum-shell-css">`, `<style id="therum-dedupe-css">`, and `<style id="therum-width-fix">` HTML tags directly inside the CSS file body.

CSS parsers treat `<` as an invalid token. When they hit `<style id="therum-shell-css">:root { ... }`, they read it as one giant invalid selector and **discard the entire rule block that follows** — including the critical `:root { --topbar-h: 72px; --ac: #e83b3b; --sf: #ffffff; ... }` declaration that sets the design-system variables.

This is why my `--topbar-h: 72px` edit "wasn't working" — the parse was bailing out before the rule landed.

**The fix.** A perl one-liner stripped every `<style[^>]*>` and `</style>` tag from all five admin CSS files:
- `therum-shell.css` — had 3 stray tags
- `therum-settings.css`, `therum-list-page.css`, `therum-settings-content.css`, `therum-settings-tile.css` — all checked clean

Verification grep confirmed zero leftover tags. After this, the design-system `:root` block parsed correctly and every CSS variable in the shell came back to life.

---

### Therum OS bundles — added

The most substantial single feature in 1.8.5-Beta. A complete build pipeline produces two installable ZIP bundles plus a custom Therum-themed install wizard.

**The build directory.**

A new directory `~/Therum OS/` (sibling to `~/Local Sites/`) holds the bundle infrastructure:

```
~/Therum OS/
├── build.sh                       Manifest-driven bundler
├── README.md                      Install + usage docs
├── CHANGELOG.md                   This file
├── install-wizard/                Shared installer (shipped in both bundles)
│   ├── install.php                Bootstrap
│   ├── lib/
│   │   ├── wizard.php             Step engine, state persistence, chrome
│   │   ├── theme.php              CSS + logo SVG for the wizard chrome
│   │   └── db.php                 DB connection test + salt fetcher
│   └── steps/
│       ├── welcome.php
│       ├── database.php
│       ├── site.php
│       ├── admin.php
│       ├── modules.php
│       ├── theme.php
│       └── finish.php
├── pro/manifest.json              Therum OS Pro 1.8.5-Beta manifest
├── pure/manifest.json             Therum OS Pure 1.8.5-Beta manifest
└── dist/                          Output ZIPs
    ├── Therum-OS-Pro-1.8.5-Beta.zip
    └── Therum-OS-Pure-1.8.5-Beta.zip
```

**The install wizard.**

A 7-step PHP wizard, no JavaScript framework, no WordPress dependency until step 7. Each step is a class extending `Therum_Step`:

1. **Welcome** — Therum logo + "Boot {bundle name}." + Begin button.
2. **Database** — host / name / user / pass form. On submit, `therum_db_test_connection()` pings mysqli with the supplied creds before advancing. Errors are caught and shown in a red error banner.
3. **Site identity** — site title (required), tagline, timezone string (e.g. "America/New_York"). Defaults to "My Therum Site" / "Built with Therum OS." / "America/New_York".
4. **Admin user** — username (alphanumeric + `_-`), email (validated), password (8+ chars), password confirm. All validated before advancing.
5. **Modules** (Pro only — skipped automatically for Pure since it only has 1 plugin) — toggleable card grid showing each bundled plugin with its slug. Click to toggle active state. Persists `[slug => bool]` map to wizard state.
6. **Theme** — radio card grid showing Therum theme presets (Studio, Editorial, Brutal, Calm, macOS Sonoma, Lucid) with description. Click to select. Defaults to Studio.
7. **Finish — review** — summary of every collected value (site title, admin username, db host/name, theme, modules). Big "Launch Therum OS →" pink button. Clicking POSTs to step 7's `handle()` which runs the install:
   - `write_wp_config()` — copies `wp-config-sample.php` to `wp-config.php` with substituted db creds + fresh salts. Salts come from `https://api.wordpress.org/secret-key/1.1/salt/` with an 8-second timeout; if that fails, falls back to local `random_bytes(32) → bin2hex` for each of the 8 WP keys.
   - Loads WP via `require_once $wp_root . '/wp-load.php'`, then `require_once ABSPATH . 'wp-admin/includes/upgrade.php'`.
   - Calls `wp_install($site_title, $admin_user, $admin_email, 1, '', $admin_pass, 'en_US')` — creates the schema + first user. Wrapped in `is_blog_installed()` guard so re-running is a no-op.
   - `update_option('blogdescription', $tagline)`, `update_option('timezone_string', $timezone)`.
   - Loops user-selected modules; for each `slug => true`, runs `find_plugin_main_file($slug)` (which checks `dir/slug.php` first, then globs for any PHP file with a `Plugin Name:` header), then `activate_plugin($file)`. Failures are logged but don't fail the whole install.
   - `switch_theme($default_theme)` per the bundle manifest (bricks-child for Pro, twentytwentyfive for Pure), only if the theme exists.
   - `Therum_Themes::set_state(['theme' => $picked_theme] + existing state)` if the class is available.
   - `update_option('therum_os_install_complete', 1)` + deletes `wp-content/therum-install-state.json` (the wizard's persistence file).
   - Re-renders step 7 with a green "Therum OS is online" success banner + "Open admin →" + "View site" buttons.

**Wizard chrome design.**

`lib/theme.php` emits the entire CSS for the wizard chrome inline (no external CSS file needed):

- 2-column shell: 380px sidebar (logo + eyebrow + h1 + step breadcrumbs + version footer) + 1fr main area.
- Sidebar gradient: `linear-gradient(180deg, #141414, #0a0a0a)` — same as the Studio theme.
- Logo: 48px rounded square in `#f5389a` with the Therum T glyph rendered via inline SVG.
- Breadcrumbs: vertical list, each with an 8px dot. Current step gets a `#f5389a` dot with a 4px halo. Completed steps get a green `#10b981` dot.
- Main area: 64px top padding, 80px L/R padding, scrollable.
- Step eyebrow: 11px uppercase pink "Step N · {label}".
- Step title: 36px bold Inter Tight, `-0.025em` letter-spacing.
- Step sub: 15px `#a3a3a3`, max-width 55ch.
- Form: max-width 520px, 18px gap between fields.
- Inputs: 12×14px padding, `#141414` background, `rgba(255,255,255,.12)` border, 10px radius. Focus state: pink border + pink focus ring.
- Primary button: `#f5389a` background, `#0a0a0a` text, 999px radius, 13px weight 600.
- Secondary button: transparent with `rgba(255,255,255,.18)` border.
- Card grid (for modules / themes step): `repeat(auto-fill, minmax(220px, 1fr))`, each card 16×18px padding, dark surface, pink-bordered active state.
- Mobile breakpoint at 840px: shell collapses to single column.

**State persistence.**

The wizard writes its state to `wp-content/therum-install-state.json` as it goes. So refreshing or closing/reopening the browser tab mid-install picks up where you left off. The state file is deleted at the end of step 7 once `wp_install()` completes successfully.

**The `build.sh` script.**

Manifest-driven bundle builder. Run `./build.sh pro` / `./build.sh pure` / `./build.sh all`.

Logic:
1. Locates a PHP binary. Checks (in order): Local's bundled PHP 8.5.3, Local's bundled PHP 8.2.29, Homebrew, `/usr/local/bin`, `/usr/bin`, and falls back to `command -v php`. Errors out if nothing works.
2. Parses the manifest (`pro/manifest.json` or `pure/manifest.json`) via a small `json_get` helper that shells out to PHP for path-based lookups.
3. Creates a staging directory at `dist/{id}-stage/`.
4. Rsyncs WP core (everything outside `wp-content`) from the source site, excluding `wp-config.php`, `.DS_Store`, `_th_*.php` (test files), `local-xdebuginfo.php`, `admin-demo.html`, `*.bk`, `*.bak`.
5. Creates the `wp-content/{mu-plugins,plugins,themes,uploads}/` scaffold.
6. Rsyncs all mu-plugins, excluding `*.bak`, `*.bk`, `*.disabled`, `.DS_Store`.
7. Iterates `include.plugins` from the manifest; for each, rsyncs from source if the dir exists. Excludes `*.zip` and `.DS_Store` inside each plugin.
8. Iterates `include.themes` from the manifest; for each, rsyncs from source if the dir exists.
9. Always includes `twentytwentyfive` as a theme fallback.
10. Strips any stray `.zip` files at the plugins or themes root.
11. Rsyncs the `install-wizard/` directory into the stage.
12. Copies `install.php` to the stage root (mirroring the wizard entry).
13. Copies the manifest to `bundle.json` at the stage root so the wizard can read it for branding/module list.
14. Zips the stage with `zip -rq`, excluding `.DS_Store` and `**/.DS_Store`.
15. Reports filename + size.
16. Cleans up the stage unless `THERUM_KEEP_STAGE=1` is set.

**Pro manifest** — includes 10 plugins: agent-to-bricks, bricks-advanced-themer, bricksextras, bricksforge, bricksultimate, litespeed-cache, mailpoet, max-addons-pro-bricks, nextbricks, sqlite-database-integration. Themes: bricks, bricks-child. Default theme: bricks-child. Default Therum theme: studio.

**Pure manifest** — only sqlite-database-integration. No bricks. Default theme: twentytwentyfive.

**Bundle sizes (verified).**

- `Therum-OS-Pro-1.8.5-Beta.zip` — 97 MB
- `Therum-OS-Pure-1.8.5-Beta.zip` — 16 MB

**End-to-end verification.**

Both bundles were extracted to `/tmp` after build and every PHP file in the extracted tree was lint-checked with Local's bundled PHP 8.5.3. All 17 mu-plugins clean. All 11 wizard files clean. Build pipeline reproducible — `./build.sh all` produces the same ZIPs on repeat runs (differing only by timestamp).

**Documentation.**

`README.md` covers:
- Build commands (`./build.sh [pro|pure|all]`).
- Install on Local (create blank site, empty `app/public/`, extract bundle, restart, visit URL → wizard runs).
- Install on a web host (upload + extract at document root, create empty DB, visit `/install.php`).
- What's in each bundle.
- Manifest schema with field-by-field comments.
- Verify recipe — extract a bundle to `/tmp` and lint every PHP file.

---

### Working rules — captured

Saved the user's project-wide collaboration rules to memory (`feedback_working_rules.md`):

1. No new bugs.
2. Check for conflicts before applying any change.
3. Make sure all styles are correct.
4. Visual bar = WP admin redesign + any images the user sends.
5. Never do anything the user didn't ask for.
6. Everything is built in Bricks.
7. No HTML unless the user specifies.
8. No unnecessary responses, explanations, or filler that eats usage.
9. Questions are OK.

---

## [1.7.1-beta] — 2026-04-28

The "everything wired" release. v1.7.0 had display-only toggles in Performance, Backup, Notifications, Permissions, and API/Webhooks. v1.7.1 makes every one of them actually do its job.

### Added

#### Performance engine (`therum-perf-engine.php`)
- Object-cache toggle now primes WP cache for our settings on admin pages
- Minify CSS strips comments and whitespace from custom CSS output
- Minify HTML wraps the front-end response in an output buffer that collapses whitespace, drops HTML comments, preserves `<pre>`/`<script>`/`<style>`/`<textarea>` contents

#### Backup engine (`therum-perf-engine.php`)
- "Run backup now" button creates an immediate zip with database, uploads, active theme, and a `manifest.json`
- Scheduled backups via `wp_cron` with hourly/twicedaily/daily/weekly
- "Next run" timestamp shown in settings
- Recent backups history table (last 10) with file/size/trigger/timestamp
- Auto-prune to keep last 10 zips locally
- S3 upload with full Signature V4 auth (works with AWS, Cloudflare R2, Wasabi, MinIO, any S3-compatible)
- SQLite database captured as `.sqlite` file inside the zip

#### Notifications engine (`therum-perf-engine.php`)
- "Send test" button fires email + Slack with a test message
- Email-enabled master toggle
- Triggers wired:
  - Admin login (with IP, user agent, timestamp)
  - Plugin/theme/core update completion (lists what was updated)
  - Backup completion (with file size)
- Slack webhook posts formatted messages with status emoji

#### Custom roles engine (`therum-roles-engine.php`)
- Full role builder UI in Settings → Permissions
- Capability bundles (Read, Write, Publish, Edit any, Settings, Shop customer, Shop manager) with click-to-toggle cards
- Individual capability picker with searchable filter (200+ caps)
- Built-in role protection (administrator, editor, author, contributor, subscriber, customer, shop_manager cannot be overwritten or deleted)
- Role deletion auto-reassigns affected users to the default role

#### WooCommerce role pricing (`therum-roles-engine.php`)
- Per-role percentage discount on cart subtotal
- Discount applied automatically as negative cart fee at checkout
- Discount line shows in cart with role name and percentage
- Multiple discount roles → largest discount wins
- My Account dashboard banner explains the perk to customers
- Built for Friends & Family, VIP, Industry Pro tiers

#### API / Webhooks engine (`therum-api-engine.php`)
- REST API kill switch actually disables `/wp-json/` when off
- Require-authentication blocks anonymous reads with 401
- CORS allowlist parsed line-by-line, sends proper preflight headers
- Outbound webhooks for 11 site events:
  - `post.published` / `post.updated` / `post.deleted`
  - `page.published`
  - `comment.posted`
  - `user.registered` / `user.login`
  - `media.uploaded`
  - `order.created` / `order.completed` (Woo)
  - `product.published` (Woo)
- HMAC-SHA256 signing with `X-Therum-Signature` header for endpoint verification
- Async dispatch via `wp_cron` so events don't block requests
- "Test" button on each webhook sends `test.ping` and shows HTTP status
- Status codes color-coded in the table (green 2xx, red 4xx/5xx)
- Payload format reference shown in settings

#### Empty-state polish
- All list pages (Pages, Posts, Media, Plugins, Users) show a real empty state with icon + primary CTA pulled from `action_buttons` config
- "No matches" search empty state matches design

### File inventory at 1.7.1-beta (10 files in mu-plugins)

- `therum-core.php` — security/Bricks/SQLite hardening
- `therum-admin-ui.php` — shell, dashboard, sidebar, dedupe, width, icons
- `therum-themes.php` — 51 themes across 6 sections, 14 fonts
- `therum-list-page.php` — generic list + Pages/Posts/Media/Users/Plugins/PDP
- `therum-settings.php` — settings registry + 14 sections
- `therum-editor.php` — Pages → Bricks redirect, Posts editor skin, form skins
- `therum-woo-bridge.php` — WooCommerce integration
- `therum-perf-engine.php` — performance + backup + notifications runtime
- `therum-roles-engine.php` — custom roles + WooCommerce role pricing
- `therum-api-engine.php` — REST hardening + outbound webhooks

### Known issues at 1.7.1-beta

- Plugin rollback only works for plugins on wordpress.org
- Local backups stored in `wp-content/backups` (auto-pruned to 10)
- Webhook delivery is best-effort (no retry on failure yet — slated for v1.8)

---

## [1.7.0-beta] — 2026-04-28

The "It's an admin, not a plugin" release. Therum OS is a full WordPress fork of the admin experience, built on SQLite + Bricks.

### Added

- Card system (4 layouts × 5 image sources, per-post overrides)
- Plugin Product Detail pages with full version history
- Posts editor with Therum-skinned classic editor
- Pages auto-redirect to Bricks
- Media list view with thumbnails
- Form skins for user-new, user-edit, profile, comments, taxonomies
- Visual card pickers in Settings → Appearance

### Fixed

- AJAX field validator now case-insensitive
- Card pickers moved out of `<a>` wrapper (clicks no longer hijack nav)
- Hero card layout: full-bleed, 24px corners, gradient scrim

---

## [1.6.x] — 2026-04-27

Foundation builds. Theme system, list pages, settings registry, density tiers, sidebar styles, glass tint, media library views, font diversification, performance toggles (UI only), plugin compatibility shims, backup scaffolding (UI only).

### Added — modules introduced at 1.6.0-beta

Per mu-plugin headers, three core modules were stamped at `Version: 1.6.0-beta`, marking the moment Therum OS got actual functional screens beyond a chrome shell:

- **`therum-list-page.php`** — generic list-page renderer (`.th-lp`). Pages, Posts, Case Studies, Templates, Users, Plugins, Themes all use it. Card grid + table view, search, status pills, kebab actions, per-post layout override.
- **`therum-themes.php`** — theme presets system (`Therum_Themes::get_state()` / `set_state()`). Foundations / Surfaces / Familiar / Experimental groups, multiple selectable presets per group, accent / density / radius / shadow / glass / sidebar-style toggles.
- **`therum-settings.php`** — Settings page (`.th-settings`) with nav rail + content area. Sections for Appearance, Branding, Login, Site Identity, Plugin Compatibility, Security, etc.

---

## [1.0.1] – [1.5.x] — stabilization line

The "fix-it" run between the v1.0.0 fork and the v1.6.0-beta feature reset. No new modules landed in this range — it was bug-fix iterations against the v1.0.0 surface (core, admin-ui scaffold, login skin, SQLite hardening), shaking out edge cases until the shell was stable enough to start building real screens on top of.

### Fixed (cumulative across the line)

- Crash, fatal, and permission-related issues found running v1.0.0 across different WP/PHP versions and roles.
- Admin chrome regressions surfaced as the sidebar/topbar got real content.
- SQLite Database Integration edge cases (collation, foreign-key behaviors, write paths) hardened in lockstep with WP core updates.
- Login skin and capability checks tightened so a non-admin user couldn't see Therum-only surfaces by accident.

> No mu-plugin `Version:` header sits in this range, so individual patch versions aren't separately documented — they were rolling stabilization passes, not feature releases.

---

## [1.0.0] — *date TBD (pre-2026-04-14, per the dated `Therum-OS-1.x.zip` archive)*

> Reconstructed from the preserved 1.0.0 install at `~/Local Sites/therum-os/`. Three mu-plugin files only.

### Added

- **`therum-core.php`** — defines `THERUM_OS_VERSION` and the `Therum OS — Forked from …` footer in the admin.
- **`therum-admin-ui.php`** — initial admin chrome scaffold. Far simpler than the eventual 1.8.0 rev (~424 lines vs. the current ~1000+). Rendered a `.th-footer` strip showing the running version.
- **`therum-test.php`** — internal test/probe module (`[TODO]` confirm purpose).
- **`therum-admin/` directory** — `admin.css`, `admin.js`, `login.css`. The first admin styling pass.
- **Plugin baseline** — Akismet, Hello Dolly, SQLite Database Integration. SQLite shipped from day one — Therum was MySQL-free at v1.0.0.
- **Theme baseline** — Twenty Twenty-Three, Twenty Twenty-Four, Twenty Twenty-Five. No Bricks integration yet.

### Philosophy stated at v1.0.0

- "Forked from WordPress" — Therum OS framed as a fork rather than a plugin, even at its earliest point.
- SQLite-first — no MySQL-specific dependency from day one, anticipating the eventual portability goal.

---

## Conventions

- **Added** — new feature, new mu-plugin, new theme preset, new layout.
- **Changed / Retuned** — modified behavior, value, or appearance of something that already existed.
- **Fixed** — bug fix.
- **Removed** — feature, preset, or surface taken out.
- **Infrastructure** — build tooling, deployment, or developer-experience changes that don't affect end-users directly.

When updating this file, append a new dated section at the top under the latest version heading. Use past-tense, plain English. State **what changed and why**, not implementation details — those belong in the file diffs.
Settings · 14 SECTIONS

Appearance

Themes, density, sidebar style.

Active theme

Click any preset to apply live.

Theme
Studio
Apple Music
Lucid
Xfinity Member
Accent color

Layout

Sidebar style
Solid
Glass
Floating
Density
Compact
Comfy
Spacious
Show search hotkey hint

Logo & mark

Files used in the admin chrome + login screen.

Logo
SVG or PNG — displayed in the topbar
Favicon
Wordmark
Plain-text fallback when no logo is set

Site identity

How your site introduces itself.

Site title
Tagline
Timezone
Language

Plugin compatibility

Per-plugin tweaks for known WP-admin clashes.

Bricks Builder · skip iframe shell
Builder bypasses Therum chrome when active
WooCommerce · skip wc-setup wizard chrome
MailPoet · iframe its full-page React app

Plugin compatibility

Pure has no third-party plugins.

No compatibility shims needed — Pure runs native modules only.

Security

Hardened defaults. Adjust if you know what you're doing.

Enforce 2FA on admins
TOTP setup wizard runs on first login
Hide /wp-admin/about.php
Part of the sans-WP leak sweep
Strip X-Powered-By
Rate-limit /wp-login.phpRate-limit /login
Off
Soft
Strict

Roles & capabilities

Powered by the Therum Roles Engine.

Default new-user role
Allow author role on this install
Custom roles
VIP, Industry Pro, Friends & Family — created via role builder
Performance · Overview

Performance

Real-user metrics, optimization status, and the top offenders weighing the site down.

LCP
—
Largest contentful paint · 7d p75
CLS
—
Cumulative layout shift
INP
—
Interaction to next paint
TTFB
—
Time to first byte

Optimization status

What's on, what's off, where the wins are.

ModuleStateNotes
Image conversion · WebP + AVIFEnabledQuality 82 · srcset auto
CSS / JS minifyEnabled.gz siblings auto-regen
Defer non-critical JSEnabledjQuery deferred · emoji stripped
Critical CSS inlinedOffEnable in Code pane
Video facadesOffYouTube + Vimeo
Static ModeOffSite rendered live via PHP

Top offenders

Heaviest assets across the last sampled crawl.

AssetTypeSizeFix
—image—
—script—
—stylesheet—
—font—
Performance · Images

Image optimization

Convert on upload, strip metadata, generate responsive sizes, and serve modern formats with safe fallbacks.

Conversion

Modern formats served via <picture> with JPEG/PNG fallback.

Target format
AVIF wins on size; WebP wins on compatibility. Both ships both with fallback.
WebP
AVIF
Both
Quality
82 is the sweet spot. Below 70 starts to look mushy.
82
Strip EXIF + GPS on upload
Removes camera metadata + geotags. Saves 8-30KB per photo.
Auto-generate srcset sizes
320 · 640 · 1024 · 1600 · 2400 widths

Delivery

When and how images load.

Lazy-load below the fold
Uses native loading="lazy". Skips LCP candidates.
Preload LCP image
Auto-detects the hero image per template and emits <link rel=preload>.
Blurhash / LQIP placeholders
Tiny base64 placeholder fades to real image. Smooths layout.

Library

Already-uploaded images don't get touched on upload. Run this to convert them in place.

— total · — already optimized · — pending
Performance · Code

Code optimization

CSS, JS, HTML. Minify, defer, tree-shake, and inline what matters.

Minify

Strip whitespace + comments. Re-runs on file change via mtime watcher.

Minify CSS
Minify JS
Minify HTML
Strips whitespace from rendered output.
Auto-regenerate .gz pairs
Keeps mod_deflate happy. mu-plugin handles this.

CSS

Reduce render-blocking. Ship only what the page uses.

Inline critical CSS
Above-the-fold rules inlined in <head>; rest deferred via preload swap.
Tree-shake unused CSS per template
PurgeCSS-style pass. Cuts Bricks + theme CSS by ~60% on average.
Remove block library CSS
Skip wp-block-library on pages with no Gutenberg blocks.

JS

Defer, drop, preload.

Defer non-critical JS
Remove jQuery on front-end
Safe when no plugin requires it. Saves ~85KB.
Remove emoji script
Modulepreload ES modules
Heartbeat interval
wp-admin polling. Lower = more responsive, higher = lighter.
15s
30s
60s
Off

Fonts

Avoid FOIT/FOUT.

Preload primary font faces
Auto-detects @font-face declarations and emits preload links.
font-display: swap
Forced on all @font-face rules.
Performance · Video & motion

Video, GIF & animated WebP

Most pages lose more weight to motion assets than anything else. GIF → MP4 alone usually saves 80–95%.

GIF & animated WebP

GIFs are uncompressed video pretending to be images. Convert on upload to real video formats.

Convert GIF → MP4 + WebM on upload
Auto-replaces <img src="*.gif"> with looped, muted <video>. Typical savings: 90%.
Convert animated WebP → WebM
Animated WebP is supported, but WebM is smaller + hardware-decoded.
Frame rate cap
Most GIFs are 12-15fps anyway. Capping prevents bloat.
15
24
30
Source
Keep original GIF as fallback
Stored alongside; not served unless browser lacks video support.

Native <video>

Uploaded MP4s and self-hosted clips.

Lazy-load via IntersectionObserver
Posters render immediately; video metadata loads on scroll-in.
Auto-generate poster frame on upload
Pulls frame at 00:00:01 via ffmpeg. Used as poster + LQIP.
Transcode MP4 → AV1 / WebM
Heavy CPU on upload. ~40% smaller than H.264. Falls back gracefully.
Respect prefers-reduced-motion
Auto-pause looped/background video when user has reduced-motion on.

Embeds (YouTube · Vimeo)

A single YouTube embed loads ~600KB before play. Facade defers the iframe until click.

YouTube facade
Renders poster + play button. iframe loads only on user click.
Vimeo facade
Use youtube-nocookie.com
Privacy-friendly host. No tracking cookies until interaction.
Performance · Database

Database

Where most WooCommerce stores leak speed. Missing indexes, autoload bloat, runaway Action Scheduler queues, and slow order search. Therum-native diagnostics + one-click fixes.

Index health

WP’s default schema is missing indexes on wp_postmeta(meta_value), wp_options(autoload), and other hot columns. Adding them is the single biggest DB win.

Table · ColumnStateEst. impactAction
wp_postmeta · meta_valueMissing−— ms per query
wp_options · autoloadMissing−— ms on every request
wp_woocommerce_sessions · session_expiryPresent——
wp_comments · comment_author_emailMissing−— ms on author search
wp_termmeta · meta_valueMissing−— ms on tax queries
Inspired by index-wp-mysql-for-speed

Object cache (SQLite)

Persistent object cache backed by a local SQLite file — no Redis or Memcached needed. Works on shared hosting where in-memory cache isn’t available.

Enable SQLite object cache
Ships object-cache.php drop-in. Caches transients + queries.
Max cache size
Older entries evicted (LRU).
64 MB
256 MB
1 GB
Unlimited
Status
Hits / misses / evictions over the last hour.
Hits: —Misses: —Size: —

Autoload audit

Options with autoload=yes load on every single page request. A 5 MB autoload payload adds 200 ms+ to TTFB. Top offenders below.

OptionSizeAutoloadAction
——yes
——yes
——yes
Total autoloaded: — · Run audit to refresh

Action Scheduler

WooCommerce’s async job runner. The actionscheduler_actions table grows unbounded by default. Stores hit 10M rows in 2 years.

Queue depth
Pending / In-progress / Failed / Completed counts.
Pending: —Running: —Failed: —Completed: —
Auto-prune completed actions
Removes completed entries older than retention window.
Retention
7 days
30 days
90 days
Failed actions
Retry, log, or delete failed jobs.

Woo · Fast order lookup

Replaces WooCommerce’s unindexed LIKE scan on order search with a Therum-maintained indexed table. Auto-installs on activation.

Enable fast order lookup
Indexed table populated on every order save. Search hits one indexed query instead of a full meta scan.
Lookup table
wp_therum_wc_order_search·Rows: —·Indexed
Backfill
Existing orders sync in 500-row chunks via cron.

Transients & sessions

Cleanup the unbounded growth tables.

Expired transients in wp_options
Count: —
Abandoned guest sessions in wp_woocommerce_sessions
Sessions older than 24 h with no order.
Orphaned postmeta
Rows pointing at deleted posts.

Slow query log

Last 100 queries that took longer than the threshold. Surfaces the actual hot paths so you know what to fix next.

Enable slow query log
Logs to wp-content/uploads/therum-slow-queries.jsonl. Disable in prod when not investigating.
Threshold
50 ms
100 ms
250 ms
500 ms
Recent slow queries
Performance · Mode

Static Mode

Turn the entire site into pre-rendered HTML. Faster than any cache plugin, and the attack surface shrinks because PHP doesn't run on public requests.

Static Mode
When on, public visitors are served pre-rendered HTML directly. Admin + builder routes still load WordPress normally. Speed + security in one switch.
↓ TTFB ~80%↓ PHP attack surface↑ Cache hit 100%

Mode

How aggressive the static layer is. Both can run together.

Lockdown
First request renders + saves to wp-content/cache/static/. Subsequent requests served by .htaccess before PHP boots. Cache busts on save.
Full bake
Crawl every public URL and write the whole site to /static/ in one pass. Flat HTML, hashed assets, sitemap-driven.
Auto-rebake on save
Save a post → its URL + index + sitemap re-bake in background.
Scheduled rebake
Full crawl on cron. Catches anything the save-hook missed.
Off
Hourly
Nightly
Weekly

Bake controls

Run a crawl on demand. Watch progress in the queue.

Last baked: — · Pages: — · Assets: — · Size: —

Exclusions

Routes that should always hit PHP.

Admin + login
/wp-admin/*, /wp-login.php, /therum/* — never baked.
Locked
Logged-in users
Authenticated requests bypass static.
REST API + AJAX
/wp-json/* + admin-ajax.php always dynamic.
Custom exclusion patterns
Glob patterns, one per line.

Default editor

Which editor opens for each post type.

Pages
Block
Bricks
Classic
Posts
Block
Classic
Custom post types
Block
Bricks
Classic
Editor
Pages, Posts, and custom post types open in the Visual Builder
Visual Builder · native
Open in new tab
When clicking Edit on a list-page card

Autosave & revisions

How often the editor checkpoints your work.

Autosave interval
15s
30s
60s
2m
Off
Keep revisions
Older revisions auto-prune past this count
Compare revisions side-by-side

Canvas

How the editor canvas renders content.

Content width
680px
800px
960px
Full
Editor theme
Match admin
Always light
Always dark
Distraction-free by default
Hides toolbars; press / to bring them back
Show word count + reading time
Spell check

Content rules

Guardrails to keep content consistent.

Enforce heading hierarchy
Warns when H2 follows H1 without intervening levels
Single H1 per page
Markdown shortcuts
Type **bold**, # heading, > quote, etc.
Trim empty paragraphs on save
Required featured image
Off
Posts
Pages
All

Patterns & reusable blocks

Saved snippets available in the editor.

Show patterns library
Patterns folder
Each .json in this folder becomes a pattern
Allow inline editing of reusable blocks
Manage patterns

Code editor

For custom CSS / JS / HTML blocks.

Theme
Tab size
2
4
8
Soft wrap
Line numbers

Keyboard shortcuts

Editor commands.

Save⌘S
Publish⌘⇧P
Preview⌘⇧V
Toggle distraction-free⌘⇧.
Add block / element/
Duplicate block⌘⇧D
Move up⌘⇧↑
Move down⌘⇧↓
Undo⌘Z
Redo⌘⇧Z

Uploads

File types, max size, processing.

Max upload size
Allow SVG uploads
Auto-convert PNG → WebP
Strip EXIF

Notifications

Email, Slack, webhooks.

Email notifications
Slack webhook
Posts to #alerts on backup, update, login
Notify on admin login
Notify on backup completion

Updates

Auto-update plugins, themes, core.

Auto-update WordPress core
Off
Minor
Major
Auto-update plugins
Auto-update themes
Therum OS update channel

Backup

Schedule + restore.

Schedule
Hourly
2× daily
Daily
Weekly
Off
Next run
Tomorrow · 03:00 UTC
S3 destination
Works with AWS / Cloudflare R2 / Wasabi / MinIO
Keep last

About

Version, credits, system info.

Engine: Therum OS 1.9.44 · UnlockedPure
Forked from: WordPress 6.7
PHP: 8.2.29
Database: SQLite 3.45
Active mu-plugins: 12Active modules: 12 native
Themes registered: 107
Connections: 14 registered · 9 connected
Variant: Pure Unlocked