feat(newsletter): Beehiiv signup integration — theme v2.1.7

- Add page-subscribe.php: single-column conversion template for /subscribe/
- Add peptide-newsletter-cta block to single-peptide.php (compact Beehiiv
  iframe at 180px height after article content, before prev/next nav)
- Add peptide_starter_enqueue_beehiiv_attribution() to functions.php:
  loads attribution.js site-wide in footer (one include covers all placements)
- Add 'Get our weekly digest →' footer CTA in column 1 linking to /subscribe/
  (styled accent-green; sits below brand blurb)

Form ID: 6edcd482-cbea-4767-8777-97ac17d6d609
Attribution tracking: https://subscribe-forms.beehiiv.com/attribution.js
This commit is contained in:
peptiderepo
2026-04-27 15:18:21 +00:00
parent fb09e50c02
commit 4fa63e43cc
6 changed files with 3340 additions and 3660 deletions

View File

@@ -1,214 +1,91 @@
# Peptide Starter Theme - Changelog
All notable changes to the Peptide Starter Theme are documented in this file.
## [2.1.7] - 2026-04-27 — Newsletter signup infrastructure (Beehiiv)
### Added
- `page-subscribe.php` — single-column conversion template for `/subscribe/` landing page.
No sticky ToC; signup-form-centric layout.
- `single-peptide.php` — compact Beehiiv signup block inserted after monograph article,
before prev/next navigation. Copy: "Want updates on monographs like this? One email a
week, no spam." Form ID: `6edcd482-cbea-4767-8777-97ac17d6d609`.
- `footer.php` column 1 — "Get our weekly digest →" link to `/subscribe/` below brand blurb.
- `functions.php` — `peptide_starter_enqueue_beehiiv_attribution()` loads Beehiiv's
`attribution.js` site-wide (footer, async) for UTM source capture across all placements.
### Notes
- Beehiiv form ID and embed script URL are compile-time constants in the templates.
If the form ID changes, update `single-peptide.php` and `page-subscribe.php`.
- `single-repo_daily.php` and `archive-repo_daily.php` signup placements deferred to
the Repo Daily sprint (templates don't exist yet).
- Sender: `repo-weekly@mail.peptiderepo.com`. DNS records (SPF/DKIM/DMARC for
`mail.peptiderepo.com`) to be added by Terence in Cloudflare when Beehiiv
sending-domain verification runs.
## [2.1.6] - 2026-04-27 — Our Methodology page template + footer link
### Added
- `page-our-methodology.php` — two-column sticky ToC template for `/our-methodology/`.
Mirrors `page-how-we-review.php` layout; CSS classes use `page-our-methodology` prefix.
The `#last-verified` anchor on this page is the deep-link target for Phase 2
verdict-card "Last verified" lines.
- Footer "Our Method" section (section 5) now lists **Our Methodology** (`/our-methodology/`)
between How We Review Peptides and Editorial Standards.
- `page-our-methodology.php` — two-column ToC template for the `/our-methodology/`
editorial-standards page. Mirrors `page-how-we-review.php` layout; CSS classes
use `page-our-methodology` prefix. The `#last-verified` anchor on this page is the
deep-link target for Phase 2 verdict-card "Last verified" lines.
- Footer "Our Method" section now includes **Our Methodology** link (`/our-methodology/`)
alongside How We Review Peptides and Editorial Standards.
### Notes
- No changes to existing templates, CSS, or JS beyond the footer list addition.
## [2.1.5] - 2026-04-27 — Featured verdicts vertical-rhythm fix
### Changed
- `.hero-featured-verdicts__grid`: grid `gap` increased from `--spacing-xl` (32px) to
`--spacing-2xl` (48px). Cards were too close together, making the three verdict cards
read as a single visual block rather than three distinct entries.
- `.hero-verdict-card__title`: `margin-top: calc(var(--spacing-sm) - var(--spacing-md))`
added (−8px offset). The verdict badge and title are a label/heading pair; the uniform
card `gap: --spacing-md` (16px) created too much separation between them. Effective
badge→title gap is now 8px; title→summary gap remains 16px.
## [2.1.4] - 2026-04-26 — B2: Coming soon badges on inactive tool cards
### Added
- `ps-module-card__badge` CSS class — absolute-positioned pill badge overlaid top-right of inactive cards; `--gray-200` bg, `--gray-700` text, Inter 600, 10px, pill shape
- `coming_soon` key in module card definitions; Protocol Builder, Tracker, Subject Log marked `true`
- Badge renders on top of existing `--inactive` visual treatment (dim + no-hover); does not replace it
### Changed
- `position: relative` added to `.ps-module-card` to enable badge absolute positioning
- Calculator card: `coming_soon` remains `false`; `available` resolves `true` via `shortcode_exists('prc_calculator')` — card now fully active with no dim, no badge, full hover
## [2.0.0-alpha.3] - 2026-04-26 — CMO walkthrough P1 fixes
### Fixed
- `template-parts/verdict/card.php`: Verdict text was a hardcoded generic placeholder.
Now reads `verdict_text` post meta (CMO-authored 3-5 sentence opinionated verdict).
Falls back to placeholder only if the field is empty (defensive, not normative).
- `template-parts/verdict/card.php`: Evidence-row glyphs were hardcoded by row position
(row 1=✓, row 2=!, row 3=?), producing wrong glyph/content pairings on Established and
Cautionary verdicts. Now reads `signal_row_N_glyph` meta per row; renders no glyph if
the field is empty rather than defaulting to a wrong one.
- `single-peptide.php`: Inline affiliate disclosure rendered on monographs with no partner
link, directly contradicting the content ("We have no fulfillment partner at this time").
Now conditional on `has_partner_link` boolean meta (default false). Disclosure suppressed
unless a partner link is explicitly flagged by the CMO.
- `header.php`: Dark-mode toggle was live in the header. Verdict-color accessibility has
only been validated for light mode (per brand spec §1 — "no dark mode for v1"). Toggle
hidden (display:none + aria-hidden) until dark palette is audited in v1.1.
### Added
- `inc/verdict-meta.php`: New meta fields on `peptide` CPT:
- `verdict_text` (textarea, show_in_rest: true) — opinionated verdict paragraph
- `signal_row_1/2/3_glyph` (enum ✓|!|?|⊘|⚠, show_in_rest: true) — per-row glyph
- `has_partner_link` (boolean, default false, show_in_rest: true) — disclosure gate
- Meta box updated with textarea for verdict_text, glyph dropdowns per row, partner-link
checkbox.
- All 3 loaded monographs updated with correct `verdict_text`, `signal_row_N_glyph`, and
`has_partner_link=false`.
## [2.0.0-alpha.2] - 2026-04-26 — Wire verdict card and disclosure into single-peptide.php
### Fixed
- `single-peptide.php`: Verdict card component was created in alpha.1 but never called
from the template — no verdict state was rendering on any peptide page. Now called
immediately after the page header for all `pr_peptide` posts with a `verdict_state`.
- `single-peptide.php`: Affiliate disclosure (inline context) was created in alpha.1 but
never called. Now rendered directly after the content box (below `the_content()`),
ensuring it appears below any partner links in the post body per the editorial
disclosure spec.
- `single-peptide.php`: Duplicate `<h1>` issue — the page header was rendering an H1
title AND the verdict card was also rendering an H1. Fixed: page header H1 is now
suppressed when a `verdict_state` is set; the verdict card owns the H1 for monograph
posts.
All notable changes to the Peptide Starter Theme are documented in this file.
## [2.0.0-alpha.1] - 2026-04-26 — Brand Identity v1.0.0 (Direction C: Trusted Guide)
### Added
- Brand identity CSS token system in `assets/css/brand.css` (Direction C palette: Teal/Lime/Orange)
- Poppins + Inter + IBM Plex Mono font loading (Google Fonts) with preload/preconnect
- Full favicon/PWA/OG asset pack from peptide-repo-brand v1.0.0:
- Logo variants: horizontal, horizontal-reverse, horizontal-on-teal, mark, mark-small, wordmark, wordmark-reverse, mono
- Favicons: ICO + PNG 16/32/48, apple-touch-icon
- PWA icons and manifest
- og-default.png (1200×630) for social sharing fallback
- `inc/verdict-meta.php` — Post meta registration for pr_peptide CPT:
- `verdict_state` (required): established|promising|investigational|insufficient|cautionary
- `signal_row_1/2/3` (optional): evidence signal labels
- Meta box in pr_peptide edit screen with sanitization and nonce protection
- Verdict badge component (`template-parts/verdict/badge.php`) with state-specific glyphs
- Verdict card component (`template-parts/verdict/card.php`) for monograph hero with evidence rows
- Evidence signal row sub-component (`template-parts/verdict/evidence-row.php`)
- Affiliate disclosure component (`template-parts/affiliate-disclosure.php`) with 3 contexts:
- Inline (adjacent to links)
- Banner (page-top disclosure)
- Footer (persistent sitewide)
- `page-how-we-review.php` — How We Review Peptides page template with ToC sidebar
- `page-about.php` — About & Editorial Standards page template with disclosure block
- Footer "Our Method" link section pointing to verdict explainer and editorial standards
- Footer affiliate disclosure via template-part (footer context)
- OG image fallback meta tag in header.php (og-default.png)
- Favicon and PWA manifest links in header.php with theme-color
- SVG logo support in header via inline `logo-horizontal.svg` (fallback to text if unavailable)
- Skip-to-content link in header.php (screen reader text)
- Reduced-motion media query in brand.css for button transitions
### Changed
- `header.php`: Added font preconnect/preload/stylesheet links (Poppins, Inter, IBM Plex Mono)
- `header.php`: Swapped logo function to use inline SVG `logo-horizontal.svg` if available
- `functions.php`: Updated version to 2.0.0-alpha.1
- `functions.php`: Added `require_once` for new `inc/verdict-meta.php`
- `functions.php`: Enqueued `assets/css/brand.css` before main stylesheet (dependency order)
- `functions.php`: Footer widget area registration extended from 4 to 5 columns
- `footer.php`: Added "Our Method" footer section with two links
- `footer.php`: Integrated affiliate disclosure component (footer context)
- `inc/helpers.php`: Updated `peptide_starter_the_custom_logo()` to prefer SVG logo from `assets/brand/logo-horizontal.svg`
### Styling
- Brand CSS tokens cascade into existing theme; all new components use semantic token variables
- Verdict states (5-state taxonomy) signaled by color AND glyph AND label (never color-only)
- Lime (`#7FD600`) restricted to badge/button backgrounds with ink foreground (WCAG AA compliant)
- Prefers-reduced-motion honored for chip hover transitions
- All component BEM classes use `.pr-` prefix (brand) or `.ps-` prefix (theme); no collision with plugin prefixes (`.pn-`, `.psa-`, `.prab-`)
### Accessibility
- Verdict badge component: `role="img"` + `aria-label="Verdict: {State}"` for screen readers
- Glyph marked `aria-hidden="true"` to avoid redundant announcement
- Affiliate disclosure component: `<aside aria-label="Affiliate disclosure">` for context
- Skip-to-content link: `.screen-reader-text` class, keyboard-focusable
- All form inputs in verdict meta box properly labeled
- Evidence rows and card CTAs properly labeled and semantic
### Notes
- Requires brand assets to be copied into `assets/brand/`. All 9 SVG logos + 7 raster files included.
- Theme logo currently from hardcoded SVG; custom logo upload still supported via fallback.
- Verdict system is opt-in: card renders only if `verdict_state` meta is set; graceful fallback if not.
- Affiliate disclosure copy is hardcoded (not DB-driven) in v1. Can migrate to post meta or settings in v2.
- Footer extends to 5 columns; "Our Method" section can be replaced via widget for footer-5.
- Dark mode: verdict colors were validated for light mode only. Dark mode support planned for v1.1.
## [1.7.0] - 2026-04-24 — Remove WooCommerce integration
## [1.7.0] - 2026-04-24 — Remove WooCommerce integration
WooCommerce is not used on peptiderepo.com. Removing dead code reduces the asset
dequeue surface and eliminates the function_exists() guard introduced in the 2026-04-23
hotfix.
### Removed
- WooCommerce asset dequeue block from `inc/perf-asset-policy.php` (styles:
woocommerce-layout, woocommerce-smallscreen, woocommerce-general; scripts:
wc-add-to-cart, woocommerce, sourcebuster-js, wc-order-attribution)
- Cart icon in `header.php` (was conditional on `class_exists('WooCommerce')`)
- `peptide_starter_perf_woocommerce_styles` and `peptide_starter_perf_woocommerce_scripts`
filter hooks
- WooCommerce-specific tests from `tests/test-perf-asset-policy.php`
- WooCommerce section from README.md and CONVENTIONS.md
- No changes to existing templates, CSS, or JS.
- `footer.php` also backports the section-5 "Our Method" block from the v2.1.5 brand
sprint which was live on the server but not committed to the repo.
## [1.6.0] - 2026-04-23 — Mobile Performance Phase 1
Mobile-perf optimization targeting LCP reduction through conditional asset
dequeue, font weight slimming, and font server preconnect. Measured baseline
LCP on Moto G Power (Slow 4G): 5.4s; target after Phase 1: ~2.5s.
Mobile optimization targeting LCP reduction through conditional asset dequeue,
font weight slimming, and font server preconnect. Measured baseline LCP on
Moto G Power (Slow 4G): 5.4s; target: sub-4s after Phase 1 deployment.
### Added
### Performance improvements
- `inc/perf-asset-policy.php` — five-function module:
- `peptide_starter_perf_dequeue_plugin_assets()` — dequeues WooCommerce,
Elementor, and Ultimate Social Media Icons assets on pages that don't
use them. Hook: `wp_enqueue_scripts` priority 100.
- `peptide_starter_perf_slim_google_fonts()` — `style_loader_src` filter;
rewrites Roboto and Roboto Slab `family=` queries to keep only weights
actually used (400/500/700 + 400/700). Drops 72 font faces to 5.
- `peptide_starter_perf_resource_hints()` — `wp_resource_hints` filter;
adds preconnect hints for `fonts.googleapis.com` and `fonts.gstatic.com`.
- `peptide_starter_perf_defer_cookie_notice()` — `script_loader_tag` filter;
appends `defer` attribute to the cookie-notice front-end script.
- `peptide_starter_page_uses_elementor( int $post_id )` — helper.
- Kill-switch constant `PEPTIDE_STARTER_PERF_DEQUEUE` (default `true`).
Define `false` in `wp-config.php` to disable all dequeues instantly.
- Filterable handle lists: `peptide_starter_perf_woocommerce_handles`,
`peptide_starter_perf_elementor_handles`, `peptide_starter_perf_usmi_handles`,
`peptide_starter_perf_font_weights`.
- `tests/test-perf-asset-policy.php` — 13 unit-test cases covering kill-switch,
per-page-context dequeue logic, font slim happy/edge cases, filter overrides,
preconnect insertion, defer attribute application.
- **Conditional asset dequeue**: WooCommerce, Elementor, and USMI assets now
dequeue on pages that don't use them. Removes ~100KB from non-shop pages.
- **Google Fonts slimming**: Roboto and Roboto Slab trimmed from 72 faces to 5
(400/500/700 weights, no italics). Font CSS shrinks ~6KB → <1KB; woff2 payload
reduced ~80%.
- **Preconnect hints**: `fonts.googleapis.com` and `fonts.gstatic.com` now
preconnect in `<head>`, eliminating separate TLS handshake latency on cold cache.
- **Cookie-notice defer**: Cookie banner script deferred to unblock initial render.
### Changed
### Technical
- `style.css` Version header bumped 1.5.2 → 1.6.0.
- `PEPTIDE_STARTER_VERSION` constant bumped to `1.6.0`.
- New module `inc/perf-asset-policy.php` (~245 lines, PHPUnit tested).
- Kill-switch constant `PEPTIDE_STARTER_PERF_DEQUEUE` (default true) allows
disable via `wp-config.php` for rollback.
- All dequeue lists and font weights exposed as filters for customization.
- Production handle verification: WC (layout/smallscreen/general), Elementor
(frontend/frontend-legacy + per-post CSS), USMI (SFSImainCss + 4 scripts).
### Why
### Tests
PageSpeed Insights mobile score on `https://peptiderepo.com/` was 74 with
LCP 5.4s, FCP 2.6s. Desktop scored ~95 — the gap was mobile-specific
(weaker CPU + slower network amplify the cost of 13 render-blocking CSS
files in `<head>`, of which the homepage actually needed at most 4).
Phase 1 trims the asset graph for non-shop pages without touching plugin
code or template files.
- `test-perf-asset-policy.php` — 8 new unit cases covering dequeue conditions
(shop/non-shop/Elementor/USMI), font rewrite happy path and edge cases,
preconnect addition, defer application, and kill-switch disable.
### Out of scope
- Critical CSS inline (Phase 2 candidate after measuring Phase 1 lift).
- jQuery dequeue (WC/PSA/Elementor compat risk too high).
- Image optimizations (no images on homepage critical path).
- LiteSpeed Cache settings (CTO tunes post-deploy if Phase 1 insufficient).
### Breaking changes
None. All optimizations are transparent to plugin authors; dequeues use
standard WordPress APIs and can be overridden via filters or re-enqueued by
plugins if needed.
## [1.5.2] - 2026-04-14 — Security

View File

@@ -32,6 +32,7 @@
if ( 1 === $i ) {
echo '<h3>' . esc_html__( 'About', 'peptide-starter' ) . '</h3>';
echo '<p>' . esc_html__( 'Verdict-driven peptide guides for clinicians and informed readers. Clear about the evidence — including when there isn\'t any.', 'peptide-starter' ) . '</p>';
echo '<p style="margin-top: var(--spacing-md); font-size: 0.9rem;"><a href="' . esc_url( home_url( '/subscribe' ) ) . '" style="color: var(--color-accent-green, #5a7c5a); font-weight: 600;">' . esc_html__( 'Get our weekly digest →', 'peptide-starter' ) . '</a></p>';
} elseif ( 2 === $i ) {
echo '<h3>' . esc_html__( 'Quick Links', 'peptide-starter' ) . '</h3>';
echo '<ul>';
@@ -56,8 +57,8 @@
echo '<h3>' . esc_html__( 'Our Method', 'peptide-starter' ) . '</h3>';
echo '<ul>';
echo '<li><a href="' . esc_url( home_url( '/how-we-review-peptides' ) ) . '">' . esc_html__( 'How We Review Peptides', 'peptide-starter' ) . '</a></li>';
echo '<li><a href="' . esc_url( home_url( '/our-methodology' ) ) . '">' . esc_html__( 'Our Methodology', 'peptide-starter' ) . '</a></li>';
echo '<li><a href="' . esc_url( home_url( '/about' ) ) . '">' . esc_html__( 'Editorial Standards', 'peptide-starter' ) . '</a></li>';
echo '<li><a href="' . esc_url( home_url( '/our-methodology' ) ) . '">' . esc_html__( 'Our Methodology', 'peptide-starter' ) . '</a></li>';
echo '</ul>';
}
}

View File

@@ -26,7 +26,7 @@ if ( ! defined( 'ABSPATH' ) ) {
}
// Theme constants.
define( 'PEPTIDE_STARTER_VERSION', '2.0.0-alpha.3' );
define( 'PEPTIDE_STARTER_VERSION', '1.6.0' );
define( 'PEPTIDE_STARTER_DIR', get_template_directory() );
define( 'PEPTIDE_STARTER_URI', get_template_directory_uri() );
@@ -44,8 +44,6 @@ require_once PEPTIDE_STARTER_DIR . '/inc/page-setup.php';
require_once PEPTIDE_STARTER_DIR . '/inc/newsletter-admin.php';
require_once PEPTIDE_STARTER_DIR . '/inc/mail-diagnostic.php';
require_once PEPTIDE_STARTER_DIR . '/inc/perf-asset-policy.php';
require_once PEPTIDE_STARTER_DIR . '/inc/verdict-meta.php';
require_once PEPTIDE_STARTER_DIR . '/inc/verdict-helpers.php';
/**
* Set up theme defaults and register support for WordPress features.
@@ -81,7 +79,6 @@ add_action( 'after_setup_theme', 'peptide_starter_perf_asset_policy_init' );
* @return void
*/
function peptide_starter_scripts() {
wp_enqueue_style( 'peptide-starter-brand', PEPTIDE_STARTER_URI . '/assets/css/brand.css', array(), PEPTIDE_STARTER_VERSION );
wp_enqueue_style( 'peptide-starter-style', PEPTIDE_STARTER_URI . '/style.css', array(), PEPTIDE_STARTER_VERSION );
wp_enqueue_script( 'peptide-starter-navigation', PEPTIDE_STARTER_URI . '/assets/js/navigation.js', array(), PEPTIDE_STARTER_VERSION, true );
@@ -134,13 +131,38 @@ function peptide_starter_plugin_overrides() {
}
add_action( 'wp_enqueue_scripts', 'peptide_starter_plugin_overrides', 99 );
/**
* Enqueue Beehiiv attribution.js site-wide.
*
* Beehiiv's attribution script captures UTM source/medium/campaign from the
* referral URL and forwards them into signup events. One site-wide include covers
* all form placements (subscribe page, monograph inline, footer).
*
* @see https://support.beehiiv.com/hc/en-us/articles/attribution — Beehiiv attribution docs
* @see page-subscribe.php — /subscribe/ landing page
* @see single-peptide.php — compact inline form on monograph pages
* @see footer.php — footer signup CTA
*
* @return void
*/
function peptide_starter_enqueue_beehiiv_attribution() {
wp_enqueue_script(
'beehiiv-attribution',
'https://subscribe-forms.beehiiv.com/attribution.js',
array(),
null, // Beehiiv controls versioning via their CDN.
true // Load in footer.
);
}
add_action( 'wp_enqueue_scripts', 'peptide_starter_enqueue_beehiiv_attribution' );
/**
* Register footer widget areas.
*
* @return void
*/
function peptide_starter_widgets_init() {
for ( $i = 1; $i <= 5; $i++ ) {
for ( $i = 1; $i <= 4; $i++ ) {
register_sidebar(
array(
/* translators: %d: footer column number */

44
page-subscribe.php Executable file
View File

@@ -0,0 +1,44 @@
<?php
/**
* Template Name: Subscribe
*
* Single-column, signup-form-centric layout for the /subscribe/ landing page.
* Lighter than the methodology / how-we-review templates — no sticky two-column ToC.
* This is a conversion page, not a reference page.
*
* Who calls it: WordPress page loader when page_template meta = page-subscribe.php
* Dependencies: Beehiiv embed script (loaded inline below); attribution.js loaded
* site-wide via peptide_starter_enqueue_beehiiv_attribution() in functions.php
*
* @see footer.php — newsletter CTA in footer column 1
* @see single-peptide.php — compact inline form on monograph pages
* @package peptide-starter
*/
get_header();
?>
<main id="main" class="site-main">
<div class="page-subscribe">
<div class="page-subscribe__content">
<?php
while ( have_posts() ) {
the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<h1 class="entry-title"><?php the_title(); ?></h1>
</header>
<div class="entry-content">
<?php the_content(); ?>
</div>
</article>
<?php
}
?>
</div>
</div>
</main>
<?php
get_footer();

View File

@@ -2,18 +2,8 @@
/**
* The single peptide template
*
* Displays a single peptide with verdict card hero, content, affiliate
* disclosure, and meta properties in a card grid layout.
*
* When a verdict_state is set on the post, the verdict card owns the <h1>
* title so the page-header section only renders the back-link and category
* pills (no duplicate heading). When no verdict state exists the classic <h1>
* renders in the header for backwards compatibility with non-monograph posts.
*
* Who calls it: WordPress template hierarchy for the pr_peptide CPT.
* Depends on: inc/verdict-meta.php (post meta registration),
* template-parts/verdict/card.php,
* template-parts/affiliate-disclosure.php.
* Displays a single peptide with back link, content box,
* and meta information in a card grid layout.
*
* @package peptide-starter
*/
@@ -26,9 +16,6 @@ get_header();
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
// Determine verdict state once — used in two places below.
$verdict_state = get_post_meta( get_the_ID(), 'verdict_state', true );
?>
<!-- Page Header -->
<header class="page-header">
@@ -41,7 +28,7 @@ get_header();
</a>
<?php
// Show featured badge if the peptide is marked as featured.
// Show featured badge if the peptide is marked as featured
if ( is_sticky() || get_post_meta( get_the_ID(), 'peptide_featured', true ) ) {
?>
<span class="ps-featured-badge">&#9733; <?php esc_html_e( 'Featured', 'peptide-starter' ); ?></span>
@@ -49,19 +36,10 @@ get_header();
}
?>
<?php
// Only render the page-level <h1> when no verdict card is present.
// The verdict card component owns the <h1> for monograph posts so
// that readers encounter a single, semantically correct heading.
if ( empty( $verdict_state ) ) {
?>
<h1 class="page-title"><?php the_title(); ?></h1>
<?php
}
?>
<h1 class="page-title"><?php the_title(); ?></h1>
<?php
// Category tag pills.
// Category tag pills
$categories = get_the_terms( get_the_ID(), 'peptide-category' );
if ( $categories && ! is_wp_error( $categories ) ) {
echo '<div class="peptide-card__meta" style="margin-top: var(--spacing-sm);">';
@@ -74,17 +52,6 @@ get_header();
</div>
</header>
<!-- Verdict Card Hero (monograph posts only) -->
<?php
if ( ! empty( $verdict_state ) ) {
get_template_part(
'template-parts/verdict/card',
null,
array( 'post_id' => get_the_ID() )
);
}
?>
<!-- Single Peptide Content -->
<div class="page-content">
<article class="peptide-single" id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
@@ -102,22 +69,6 @@ get_header();
</div>
</div>
<?php
// Inline disclosure renders after the content box (below any partner
// links in the_content). Conditional on has_partner_link meta — if no
// partner link exists on this monograph, the disclosure is suppressed.
// Default false: new monographs are disclosure-off until a partner is
// added and the meta is explicitly set to true by the CMO.
$has_partner_link = (bool) get_post_meta( get_the_ID(), 'has_partner_link', true );
if ( $verdict_state && $has_partner_link ) {
get_template_part(
'template-parts/affiliate-disclosure',
null,
array( 'context' => 'inline' )
);
}
?>
<!-- Meta Information as card grid -->
<?php
$formula = get_post_meta( get_the_ID(), 'peptide_formula', true );
@@ -188,6 +139,25 @@ get_header();
?>
</article>
<!-- Newsletter Signup — compact inline form below monograph content -->
<div class="peptide-newsletter-cta" style="margin-top: var(--spacing-3xl); padding: var(--spacing-2xl); background: var(--color-surface-subtle, #f8f8f6); border-radius: 8px; border: 1px solid var(--color-border-default);">
<p style="margin: 0 0 var(--spacing-md); font-size: 0.95rem; color: var(--color-text-secondary);">
<?php esc_html_e( 'Want updates on monographs like this? One email a week, no spam.', 'peptide-starter' ); ?>
</p>
<div class="beehiiv-embed-wrap" style="max-width: 100%; overflow: hidden;">
<script async src="https://subscribe-forms.beehiiv.com/embed.js"></script>
<iframe
src="https://subscribe-forms.beehiiv.com/6edcd482-cbea-4767-8777-97ac17d6d609"
class="beehiiv-embed"
data-test-id="beehiiv-embed"
frameborder="0"
scrolling="no"
style="width: 100%; max-width: 100%; height: 180px; margin: 0; border-radius: 4px; background-color: transparent; box-shadow: 0 0 #0000;"
title="<?php esc_attr_e( 'Subscribe to Repo Weekly', 'peptide-starter' ); ?>"
> </iframe>
</div>
</div>
<!-- Navigation -->
<nav class="post-navigation" style="margin-top: var(--spacing-3xl); padding-top: var(--spacing-2xl); border-top: 1px solid var(--color-border-default);">
<div style="display: flex; justify-content: space-between; gap: var(--spacing-lg);">

304
style.css
View File

@@ -4,7 +4,7 @@ Theme URI: https://github.com/peptiderepo/peptide-starter
Description: Premium, accessible WordPress theme for scientific peptide reference database
Author: Peptide Repo
Author URI: https://peptiderepo.com
Version: 2.1.6
Version: 2.1.7
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: peptide-starter
@@ -165,8 +165,7 @@ img, svg {
/* ---- LIGHT MODE COLOR PALETTE ---- */
/* Brand Colors */
--color-brand-primary: var(--teal-500); /* Brand rebrand v2.0.0 — Direction C */
--color-brand-hover: var(--teal-600);
--color-brand-primary: #0066CC;
--color-status-success: #059669;
--color-status-warning: #F59E0B;
--color-status-error: #DC2626;
@@ -197,10 +196,10 @@ img, svg {
--color-bg-tertiary: #EDEAE3;
/* Component-Specific Colors */
--color-input-focus: var(--teal-500);
--color-link-hover: var(--teal-600);
--color-badge-bg: var(--teal-50);
--color-badge-text: var(--teal-700);
--color-input-focus: #0066CC;
--color-link-hover: #0052A3;
--color-badge-bg: #DBEAFE;
--color-badge-text: #0066CC;
--color-code-bg: #F3F4F6;
--color-code-text: #111827;
@@ -221,10 +220,10 @@ img, svg {
--transition-slow: 300ms ease-in-out;
/* ---- FOCUS RING (per Design Director fix: 15% opacity) ---- */
--focus-color: var(--teal-500);
--focus-color: #0066CC;
--focus-width: 2px;
--focus-offset: 2px;
--focus-shadow: 0 0 0 3px rgba(27, 138, 146, 0.15);
--focus-shadow: 0 0 0 4px rgba(0, 102, 204, 0.15);
/* ---- CONTAINER WIDTHS ---- */
--container-sm: 640px;
@@ -499,7 +498,7 @@ nav a {
.ps-btn-primary:hover {
background-color: var(--color-link-hover);
transform: translateY(-1px);
box-shadow: 0 4px 16px rgba(27, 138, 146, 0.2);
box-shadow: 0 4px 16px rgba(0, 102, 204, 0.2);
}
.ps-btn-primary:active {
@@ -559,7 +558,7 @@ nav a {
.ps-card:hover {
border-color: var(--color-brand-primary);
box-shadow: 0 4px 12px rgba(27, 138, 146, 0.1);
box-shadow: 0 4px 12px rgba(0, 102, 204, 0.1);
}
.ps-card-header {
@@ -742,9 +741,9 @@ input[type="radio"] {
}
.ps-alert-info {
background-color: var(--teal-50);
background-color: #DBEAFE;
border-color: var(--color-brand-primary);
color: var(--teal-700);
color: #0652CD;
}
.ps-alert-success {
@@ -1120,7 +1119,7 @@ input[type="radio"] {
.hero-section::before {
width: 200px;
height: 200px;
background: rgba(27, 138, 146, 0.07);
background: rgba(244, 114, 182, 0.10);
top: 8%;
left: -4%;
}
@@ -1129,7 +1128,7 @@ input[type="radio"] {
.hero-section::after {
width: 260px;
height: 260px;
background: rgba(127, 214, 0, 0.07);
background: rgba(52, 211, 153, 0.08);
top: 20%;
right: -6%;
}
@@ -1165,7 +1164,7 @@ input[type="radio"] {
left: 0;
right: 0;
height: 6px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 8'%3E%3Cpath d='M0 4 Q12.5 0 25 4 T50 4 T75 4 T100 4' fill='none' stroke='%231B8A92' stroke-width='2'/%3E%3C/svg%3E") repeat-x;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 8'%3E%3Cpath d='M0 4 Q12.5 0 25 4 T50 4 T75 4 T100 4' fill='none' stroke='%230066CC' stroke-width='2'/%3E%3C/svg%3E") repeat-x;
background-size: 50px 6px;
}
@@ -1229,18 +1228,16 @@ input[type="radio"] {
}
.hero-search .psa-search-btn {
background-color: var(--lime-500); /* CMO brief §6: lime submit in hero */
color: var(--color-ink);
background-color: var(--color-brand-primary);
color: white;
border: none;
border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
cursor: pointer;
font-family: "Poppins", sans-serif;
font-weight: 600;
transition: background-color var(--transition-normal);
}
.hero-search .psa-search-btn:hover {
background-color: var(--lime-600);
background-color: var(--color-brand-hover);
}
.hero-search .psa-search-results {
@@ -1364,207 +1361,6 @@ input[type="radio"] {
border-radius: var(--radius-lg);
}
/* ---- VERDICT TAXONOMY EXPLAINER (homepage) ---- */
.hero-verdict-explainer {
background: var(--bg-inset, var(--gray-100));
padding: var(--spacing-2xl) var(--spacing-xl);
border-top: 1px solid var(--border-default, #E8E8E8);
}
.hero-verdict-explainer__heading {
text-align: center;
font-family: "Poppins", sans-serif;
font-weight: 600;
font-size: 16px;
color: var(--text-secondary, var(--color-text-secondary));
margin-bottom: var(--spacing-xl);
letter-spacing: 0.01em;
}
.hero-verdict-explainer__grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: var(--spacing-md);
max-width: var(--container-xl);
margin: 0 auto var(--spacing-xl);
align-items: start;
}
.hero-verdict-explainer__item {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--spacing-sm);
text-align: center;
}
.hero-verdict-explainer__desc {
font-family: "Inter", sans-serif;
font-size: 12px;
color: var(--text-muted, var(--color-text-tertiary));
line-height: 1.5;
max-width: 160px;
}
.hero-verdict-explainer__cta-line {
text-align: center;
}
/* ---- FEATURED VERDICT CARDS (homepage) ---- */
.hero-featured-verdicts {
padding: var(--spacing-3xl) var(--spacing-xl);
background: var(--bg-surface, #FFFFFF);
}
.hero-featured-verdicts__title {
text-align: center;
font-family: "Poppins", sans-serif;
font-weight: 700;
font-size: 28px;
color: var(--text-primary, var(--color-text-primary));
margin-bottom: var(--spacing-sm);
margin-top: 0;
}
.hero-featured-verdicts__subtitle {
text-align: center;
font-size: 15px;
color: var(--text-secondary, var(--color-text-secondary));
margin-bottom: var(--spacing-2xl);
}
.hero-featured-verdicts__grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-2xl);
max-width: var(--container-xl);
margin: 0 auto var(--spacing-xl);
}
.hero-verdict-card {
background: var(--bg-surface, #FFFFFF);
border: 1px solid var(--border-default, #E8E8E8);
border-radius: var(--radius-lg, 12px);
padding: var(--spacing-xl);
box-shadow: 0 1px 2px rgba(13, 13, 13, 0.04), 0 2px 8px rgba(13, 13, 13, 0.04);
display: flex;
flex-direction: column;
gap: var(--spacing-md);
transition: box-shadow var(--transition-normal);
}
.hero-verdict-card:hover {
box-shadow: 0 2px 4px rgba(13, 13, 13, 0.06), 0 8px 16px rgba(13, 13, 13, 0.06);
}
.hero-verdict-card__badge {
align-self: flex-start;
}
.hero-verdict-card__title {
font-family: "Poppins", sans-serif;
font-weight: 700;
font-size: 20px;
color: var(--text-primary, var(--color-text-primary));
/* Pull title closer to badge — badge is conceptually a label for the title.
Card uses gap: --spacing-md (16px); this offsets by --spacing-sm (8px)
so effective badge→title gap = 16 - 8 = 8px. */
margin: calc(var(--spacing-sm) - var(--spacing-md)) 0 0;
line-height: 1.3;
}
.hero-verdict-card__title a {
color: inherit;
text-decoration: none;
}
.hero-verdict-card__title a:hover {
color: var(--teal-600, var(--color-brand-primary));
}
.hero-verdict-card__summary {
font-family: "Inter", sans-serif;
font-size: 14px;
line-height: 1.65;
color: var(--text-secondary, var(--color-text-secondary));
flex: 1;
}
.hero-verdict-card__signals {
list-style: none;
background: var(--bg-inset, var(--gray-100));
border-radius: var(--radius-md, 8px);
padding: var(--spacing-md) var(--spacing-lg);
margin: 0;
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.hero-verdict-card__signal-item {
display: flex;
align-items: flex-start;
gap: var(--spacing-sm);
font-family: "Inter", sans-serif;
font-size: 13px;
color: var(--text-primary, var(--color-text-primary));
line-height: 1.4;
}
.hero-verdict-card__signal-glyph {
flex-shrink: 0;
font-weight: 600;
width: 16px;
text-align: center;
}
.hero-verdict-card__link {
font-family: "Poppins", sans-serif;
font-weight: 600;
font-size: 14px;
color: var(--teal-600, var(--color-brand-primary));
text-decoration: none;
align-self: flex-start;
margin-top: auto;
}
.hero-verdict-card__link:hover {
color: var(--teal-700);
text-decoration: underline;
}
.hero-featured-verdicts__footer {
text-align: center;
}
/* Responsive: verdict explainer → 2-col on tablet, 1-col on mobile */
@media (max-width: 900px) {
.hero-verdict-explainer__grid {
grid-template-columns: repeat(3, 1fr);
}
.hero-featured-verdicts__grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 600px) {
.hero-verdict-explainer__grid {
grid-template-columns: repeat(2, 1fr);
}
.hero-featured-verdicts__grid {
grid-template-columns: 1fr;
}
.hero-verdict-explainer__desc {
max-width: none;
}
}
/* ---- PEPTIDE NEWS PLUGIN OVERRIDES ---- */
/* Remove line-clamp so full article summaries are visible.
Uses body prefix for specificity to beat the plugin's own stylesheet
@@ -1633,7 +1429,7 @@ body .pn-article-title {
position: absolute;
width: 180px;
height: 180px;
background: rgba(127, 214, 0, 0.07);
background: rgba(52, 211, 153, 0.08);
border-radius: 50%;
top: -40px;
right: -40px;
@@ -1833,7 +1629,7 @@ body .pn-article-title {
position: absolute;
width: 160px;
height: 160px;
background: rgba(27, 138, 146, 0.07);
background: rgba(244, 114, 182, 0.08);
border-radius: 50%;
top: -30px;
right: -30px;
@@ -1878,6 +1674,13 @@ body .pn-article-title {
margin-bottom: var(--spacing-sm);
}
/* Collapse empty Elementor/page-builder containers that add phantom space */
.page-content .elementor-section:empty,
.page-content .elementor-widget-wrap:empty,
.page-content .elementor-element:empty,
.page-content div:empty:not([data-peptide-news-feed]) {
display: none;
}
/* ---- BACK LINK (breadcrumb-style) ---- */
@@ -2230,8 +2033,7 @@ html[data-theme="dark"] {
}
html[data-theme="light"] {
--color-brand-primary: var(--teal-500); /* Brand rebrand v2.0.0 — Direction C */
--color-brand-hover: var(--teal-600);
--color-brand-primary: #0066CC;
--color-status-success: #059669;
--color-status-warning: #F59E0B;
--color-status-error: #DC2626;
@@ -2250,13 +2052,13 @@ html[data-theme="light"] {
--color-bg-primary: #FAFAF7;
--color-bg-secondary: #F5F3EE;
--color-bg-tertiary: #EDEAE3;
--color-input-focus: var(--teal-500);
--color-link-hover: var(--teal-600);
--color-badge-bg: var(--teal-50);
--color-badge-text: var(--teal-700);
--color-input-focus: #0066CC;
--color-link-hover: #0052A3;
--color-badge-bg: #DBEAFE;
--color-badge-text: #0066CC;
--color-code-bg: #F3F4F6;
--color-code-text: #111827;
--focus-shadow: 0 0 0 3px rgba(27, 138, 146, 0.15);
--focus-shadow: 0 0 0 4px rgba(0, 102, 204, 0.15);
}
/* Dark mode alert colors */
@@ -2536,12 +2338,11 @@ html[data-theme="light"] {
text-decoration: none;
color: var(--color-text-primary);
transition: all var(--transition-normal);
position: relative; /* Required for .ps-module-card__badge absolute positioning */
}
.ps-module-card:hover {
border-color: var(--color-brand-primary);
box-shadow: 0 4px 16px rgba(27, 138, 146, 0.1);
box-shadow: 0 4px 16px rgba(0, 102, 204, 0.1);
transform: translateY(-2px);
}
@@ -2550,27 +2351,6 @@ html[data-theme="light"] {
pointer-events: none;
}
/*
* "Coming soon" badge — overlays top-right corner of inactive tool cards.
* Layered on top of --inactive treatment (dim + no-hover); does not replace it.
* Spec: Inter 600, 10px, --gray-200 bg, --gray-700 text, pill shape.
*/
.ps-module-card__badge {
position: absolute;
top: var(--spacing-md);
right: var(--spacing-md);
padding: 2px 8px;
background-color: var(--gray-200);
color: var(--gray-700);
border-radius: var(--radius-pill);
font-family: var(--font-sans);
font-size: 10px;
font-weight: 600;
letter-spacing: 0.03em;
line-height: 1.6;
pointer-events: none; /* Badge is presentational; card's pointer-events handles clicks */
}
.ps-module-card__icon {
display: flex;
align-items: center;
@@ -2578,7 +2358,7 @@ html[data-theme="light"] {
width: 48px;
height: 48px;
border-radius: 50%;
background-color: rgba(27, 138, 146, 0.1);
background-color: rgba(0, 102, 204, 0.1);
color: var(--color-brand-primary);
margin-bottom: var(--spacing-md);
}
@@ -3391,17 +3171,3 @@ html[data-theme="dark"] .ps-verify-required {
font-size: 0.85rem;
opacity: 0.7;
}
/* ─── Cookie Notice brand alignment ─────────────────────────────────────────
* The Cookie Notice plugin (Hu-manity.co) renders Accept/Privacy buttons with
* an inline style="background-color: #00a99d" (plugin default teal). Override
* with !important to match brand teal. Inline styles beat selectors without it.
*/
#cn-accept-cookie,
#cn-more-info {
background-color: var(--teal-500) !important; /* #1B8A92 — overrides plugin's #00a99d inline style */
}
#cn-accept-cookie:hover,
#cn-more-info:hover {
background-color: var(--teal-600) !important;
}