feat: brand identity v1.0.0 — Direction C Trusted Guide (theme v2.0.0-alpha.1)
Implements weeks 1–4 of the CMO brand identity sprint. Complete theme reskin with: - CSS token system (brand.css) with Teal/Lime/Orange palette - Poppins/Inter/IBM Plex Mono font loading - Full favicon/PWA/OG asset pack - 5-state verdict badge + card + evidence row components - verdict_state post meta on pr_peptide CPT with meta box - Affiliate disclosure component (3 contexts: inline, banner, footer) - How we review peptides page template - About & Editorial Standards page template - Footer Our Method links + disclosure - SVG logo support (logo-horizontal.svg inline) - OG image fallback meta tag - Accessibility: role=img on badges, skip-to-content link, prefers-reduced-motion support Theme version bumped to 2.0.0-alpha.1.
67
CHANGELOG.md
@@ -2,6 +2,73 @@
|
||||
|
||||
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
|
||||
|
||||
BIN
apple-touch-icon.png
Executable file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/brand/apple-touch-icon.png
Executable file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/brand/favicon-16.png
Executable file
|
After Width: | Height: | Size: 481 B |
BIN
assets/brand/favicon-32.png
Executable file
|
After Width: | Height: | Size: 906 B |
BIN
assets/brand/favicon-48.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/brand/icon-192.png
Executable file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
assets/brand/icon-512.png
Executable file
|
After Width: | Height: | Size: 15 KiB |
7
assets/brand/logo-horizontal-on-teal.svg
Executable file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 96" role="img" aria-label="Peptide Repo">
|
||||
<rect x="8" y="8" width="80" height="80" rx="16" fill="#FFFFFF"/>
|
||||
<text x="48" y="58" text-anchor="middle" font-family="Poppins, sans-serif" font-weight="700" font-size="38" fill="#1B8A92" letter-spacing="1">PR</text>
|
||||
<circle cx="82" cy="82" r="14" fill="#7FD600"/>
|
||||
<path d="M 76 82 l 4 4 l 8 -8" stroke="#0D0D0D" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<text x="108" y="58" font-family="Poppins, sans-serif" font-weight="700" font-size="30" fill="#FFFFFF" letter-spacing="-0.5">Peptide Repo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 652 B |
7
assets/brand/logo-horizontal-reverse.svg
Executable file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 96" role="img" aria-label="Peptide Repo">
|
||||
<rect x="8" y="8" width="80" height="80" rx="16" fill="#1B8A92"/>
|
||||
<text x="48" y="58" text-anchor="middle" font-family="Poppins, sans-serif" font-weight="700" font-size="38" fill="#FFFFFF" letter-spacing="1">PR</text>
|
||||
<circle cx="82" cy="82" r="14" fill="#7FD600"/>
|
||||
<path d="M 76 82 l 4 4 l 8 -8" stroke="#0D0D0D" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<text x="108" y="58" font-family="Poppins, sans-serif" font-weight="700" font-size="30" fill="#FFFFFF" letter-spacing="-0.5">Peptide Repo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 652 B |
7
assets/brand/logo-horizontal.svg
Executable file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 96" role="img" aria-label="Peptide Repo">
|
||||
<rect x="8" y="8" width="80" height="80" rx="16" fill="#1B8A92"/>
|
||||
<text x="48" y="58" text-anchor="middle" font-family="Poppins, sans-serif" font-weight="700" font-size="38" fill="#FFFFFF" letter-spacing="1">PR</text>
|
||||
<circle cx="82" cy="82" r="14" fill="#7FD600"/>
|
||||
<path d="M 76 82 l 4 4 l 8 -8" stroke="#0D0D0D" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<text x="108" y="58" font-family="Poppins, sans-serif" font-weight="700" font-size="30" fill="#0D0D0D" letter-spacing="-0.5">Peptide Repo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 652 B |
5
assets/brand/logo-mark-small.svg
Executable file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" role="img" aria-label="Peptide Repo">
|
||||
<rect x="0" y="0" width="72" height="72" rx="14" fill="#1B8A92"/>
|
||||
<text x="36" y="52" text-anchor="middle" font-family="Poppins, sans-serif" font-weight="700" font-size="38" fill="#FFFFFF" letter-spacing="0.5">PR</text>
|
||||
<circle cx="66" cy="66" r="13" fill="#7FD600"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 378 B |
6
assets/brand/logo-mark.svg
Executable file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" role="img" aria-label="Peptide Repo">
|
||||
<rect x="0" y="0" width="72" height="72" rx="14" fill="#1B8A92"/>
|
||||
<text x="36" y="51" text-anchor="middle" font-family="Poppins, sans-serif" font-weight="700" font-size="34" fill="#FFFFFF" letter-spacing="0.5">PR</text>
|
||||
<circle cx="66" cy="66" r="13" fill="#7FD600"/>
|
||||
<path d="M 60.5 66.5 l 3.5 3.5 l 7.5 -7.5" stroke="#0D0D0D" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 518 B |
8
assets/brand/logo-mono.svg
Executable file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 96" role="img" aria-label="Peptide Repo">
|
||||
<rect x="8" y="8" width="80" height="80" rx="16" fill="#0D0D0D"/>
|
||||
<text x="48" y="58" text-anchor="middle" font-family="Poppins, sans-serif" font-weight="700" font-size="38" fill="#FFFFFF" letter-spacing="1">PR</text>
|
||||
<circle cx="82" cy="82" r="14" fill="#0D0D0D" stroke="#0D0D0D" stroke-width="2"/>
|
||||
<circle cx="82" cy="82" r="11" fill="#FFFFFF"/>
|
||||
<path d="M 76 82 l 4 4 l 8 -8" stroke="#0D0D0D" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<text x="108" y="58" font-family="Poppins, sans-serif" font-weight="700" font-size="30" fill="#0D0D0D" letter-spacing="-0.5">Peptide Repo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 736 B |
3
assets/brand/logo-wordmark-reverse.svg
Executable file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 56" role="img" aria-label="Peptide Repo">
|
||||
<text x="0" y="40" font-family="Poppins, sans-serif" font-weight="700" font-size="36" fill="#FFFFFF" letter-spacing="-0.5">Peptide Repo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 250 B |
3
assets/brand/logo-wordmark.svg
Executable file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 56" role="img" aria-label="Peptide Repo">
|
||||
<text x="0" y="40" font-family="Poppins, sans-serif" font-weight="700" font-size="36" fill="#0D0D0D" letter-spacing="-0.5">Peptide Repo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 250 B |
BIN
assets/brand/og-default.png
Executable file
|
After Width: | Height: | Size: 34 KiB |
30
assets/brand/og-default.svg
Executable file
@@ -0,0 +1,30 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" role="img" aria-label="Peptide Repo - What the research really says.">
|
||||
<!-- Background: cream with a subtle teal-corner accent -->
|
||||
<rect x="0" y="0" width="1200" height="630" fill="#FAFAF7"/>
|
||||
<rect x="0" y="610" width="1200" height="20" fill="#1B8A92"/>
|
||||
|
||||
<!-- Logo lockup, top-left, scaled larger -->
|
||||
<g transform="translate(80, 80)">
|
||||
<rect x="0" y="0" width="120" height="120" rx="22" fill="#1B8A92"/>
|
||||
<text x="60" y="86" text-anchor="middle" font-family="Poppins, sans-serif" font-weight="700" font-size="56" fill="#FFFFFF" letter-spacing="1.5">PR</text>
|
||||
<circle cx="111" cy="111" r="20" fill="#7FD600"/>
|
||||
<path d="M 102 111 l 6 6 l 12 -12" stroke="#0D0D0D" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<text x="148" y="80" font-family="Poppins, sans-serif" font-weight="700" font-size="44" fill="#0D0D0D" letter-spacing="-0.8">Peptide Repo</text>
|
||||
</g>
|
||||
|
||||
<!-- Tagline / hero copy -->
|
||||
<g transform="translate(80, 320)">
|
||||
<text x="0" y="0" font-family="Poppins, sans-serif" font-weight="700" font-size="84" fill="#0D0D0D" letter-spacing="-2">What the research</text>
|
||||
<text x="0" y="100" font-family="Poppins, sans-serif" font-weight="700" font-size="84" fill="#1B8A92" letter-spacing="-2">really says.</text>
|
||||
</g>
|
||||
|
||||
<!-- Verdict-state mini-row, bottom-right, signaling the brand's signature taxonomy -->
|
||||
<g transform="translate(720, 540)" font-family="Inter, sans-serif" font-weight="600" font-size="14">
|
||||
<rect x="0" y="0" width="120" height="32" rx="16" fill="#1B8A92"/>
|
||||
<text x="60" y="22" text-anchor="middle" fill="#FFFFFF" letter-spacing="0.4">Established</text>
|
||||
<rect x="130" y="0" width="120" height="32" rx="16" fill="#7FD600"/>
|
||||
<text x="190" y="22" text-anchor="middle" fill="#0D0D0D" letter-spacing="0.4">Promising</text>
|
||||
<rect x="260" y="0" width="160" height="32" rx="16" fill="#FF8A3D"/>
|
||||
<text x="340" y="22" text-anchor="middle" fill="#0D0D0D" letter-spacing="0.4">Investigational</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
202
assets/css/brand.css
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Peptide Repo Brand Identity v1.0.0
|
||||
* Direction C: "The Trusted Guide"
|
||||
*
|
||||
* Contains CSS custom property tokens and brand component styles.
|
||||
* Enqueued before style.css so tokens cascade into existing theme.
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Base palette */
|
||||
--color-teal: #1B8A92;
|
||||
--color-ink: #0D0D0D;
|
||||
--color-lime: #7FD600;
|
||||
--color-orange: #FF8A3D;
|
||||
--color-neutral: #D0D0D0;
|
||||
--color-light: #F5F5F5;
|
||||
--color-white: #FFFFFF;
|
||||
|
||||
/* Teal scale (primary) */
|
||||
--teal-50: #EBF5F6;
|
||||
--teal-100: #CEE7EA;
|
||||
--teal-200: #A6D2D7;
|
||||
--teal-300: #74B8C0;
|
||||
--teal-400: #429DA6;
|
||||
--teal-500: #1B8A92;
|
||||
--teal-600: #147178;
|
||||
--teal-700: #0F585E;
|
||||
--teal-800: #0A3F44;
|
||||
--teal-900: #072A2E;
|
||||
|
||||
/* Lime scale (accent — badge/button only, never body text) */
|
||||
--lime-50: #F5FFE0;
|
||||
--lime-100: #E8FFB8;
|
||||
--lime-200: #D4FF85;
|
||||
--lime-300: #BDFF4D;
|
||||
--lime-400: #A5EE20;
|
||||
--lime-500: #7FD600;
|
||||
--lime-600: #66B000;
|
||||
--lime-700: #4D8A00;
|
||||
--lime-800: #365F00;
|
||||
--lime-900: #1F3700;
|
||||
|
||||
/* Orange scale (caution) */
|
||||
--orange-50: #FFF3EB;
|
||||
--orange-100: #FFDEC4;
|
||||
--orange-200: #FFC299;
|
||||
--orange-300: #FFA66E;
|
||||
--orange-400: #FF9455;
|
||||
--orange-500: #FF8A3D;
|
||||
--orange-600: #E46B1F;
|
||||
--orange-700: #B8520F;
|
||||
--orange-800: #833708;
|
||||
--orange-900: #4F2003;
|
||||
|
||||
/* Gray scale (neutral) */
|
||||
--gray-50: #FAFAFA;
|
||||
--gray-100: #F5F5F5;
|
||||
--gray-200: #E8E8E8;
|
||||
--gray-300: #D0D0D0;
|
||||
--gray-400: #A8A8A8;
|
||||
--gray-500: #808080;
|
||||
--gray-600: #5C5C5C;
|
||||
--gray-700: #3D3D3D;
|
||||
--gray-800: #1F1F1F;
|
||||
--gray-900: #0D0D0D;
|
||||
|
||||
/* Semantic tokens */
|
||||
--text-primary: var(--gray-900);
|
||||
--text-secondary: var(--gray-700);
|
||||
--text-muted: var(--gray-500);
|
||||
--text-inverse: var(--color-white);
|
||||
|
||||
--bg-page: var(--color-white);
|
||||
--bg-surface: var(--color-white);
|
||||
--bg-inset: var(--gray-100);
|
||||
--bg-brand: var(--teal-500);
|
||||
--bg-brand-deep: var(--teal-700);
|
||||
|
||||
--border-default: var(--gray-200);
|
||||
--border-strong: var(--gray-300);
|
||||
--border-brand: var(--teal-500);
|
||||
|
||||
/* Verdict system tokens (the signature) */
|
||||
--verdict-established-bg: var(--teal-500);
|
||||
--verdict-established-fg: var(--color-white);
|
||||
--verdict-promising-bg: var(--lime-500);
|
||||
--verdict-promising-fg: var(--gray-900);
|
||||
--verdict-investigational-bg: var(--orange-500);
|
||||
--verdict-investigational-fg: var(--gray-900);
|
||||
--verdict-insufficient-bg: var(--gray-300);
|
||||
--verdict-insufficient-fg: var(--gray-700);
|
||||
--verdict-cautionary-bg: #C0392B;
|
||||
--verdict-cautionary-fg: var(--color-white);
|
||||
|
||||
/* Spacing & sizing primitives */
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 8px;
|
||||
--radius-lg: 12px;
|
||||
--radius-pill: 999px;
|
||||
|
||||
--shadow-card: 0 1px 2px rgba(13,13,13,0.04), 0 2px 8px rgba(13,13,13,0.04);
|
||||
--shadow-card-hover: 0 2px 4px rgba(13,13,13,0.06), 0 8px 16px rgba(13,13,13,0.06);
|
||||
}
|
||||
|
||||
.pr-verdict {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 14px 6px 10px;
|
||||
border-radius: var(--radius-pill);
|
||||
font-family: "Poppins", sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.01em;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.pr-verdict__glyph {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: var(--radius-pill);
|
||||
background: rgba(255,255,255,0.25);
|
||||
font-size: 13px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.pr-verdict--established { background: var(--verdict-established-bg); color: var(--verdict-established-fg); }
|
||||
.pr-verdict--promising { background: var(--verdict-promising-bg); color: var(--verdict-promising-fg); }
|
||||
.pr-verdict--investigational { background: var(--verdict-investigational-bg); color: var(--verdict-investigational-fg); }
|
||||
.pr-verdict--insufficient { background: var(--verdict-insufficient-bg); color: var(--verdict-insufficient-fg); }
|
||||
.pr-verdict--cautionary { background: var(--verdict-cautionary-bg); color: var(--verdict-cautionary-fg); }
|
||||
|
||||
.pr-verdict--insufficient .pr-verdict__glyph { background: rgba(13,13,13,0.10); color: var(--gray-700); }
|
||||
.pr-verdict--promising .pr-verdict__glyph,
|
||||
.pr-verdict--investigational .pr-verdict__glyph { background: rgba(13,13,13,0.12); color: var(--gray-900); }
|
||||
|
||||
.pr-verdict-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 32px;
|
||||
box-shadow: var(--shadow-card);
|
||||
}
|
||||
|
||||
.pr-verdict-card__header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 24px; }
|
||||
.pr-verdict-card__updated { font-size: 13px; color: var(--text-muted); }
|
||||
.pr-verdict-card__title { font-family: "Poppins", sans-serif; font-weight: 700; font-size: 36px; line-height: 1.2; margin: 0 0 8px; color: var(--text-primary); }
|
||||
.pr-verdict-card__summary { font-family: "Inter", sans-serif; font-size: 18px; line-height: 1.4; color: var(--text-secondary); margin-bottom: 24px; }
|
||||
|
||||
.pr-evidence-row {
|
||||
background: var(--bg-inset);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 16px 20px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.pr-evidence-row__item { display: flex; align-items: flex-start; gap: 12px; font-family: "Inter", sans-serif; font-size: 15px; line-height: 1.5; color: var(--text-primary); }
|
||||
.pr-evidence-row__item + .pr-evidence-row__item { margin-top: 10px; }
|
||||
.pr-evidence-row__glyph { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex-shrink: 0; font-weight: 600; }
|
||||
|
||||
.pr-verdict-card__verdict-label { font-family: "Poppins", sans-serif; font-weight: 600; font-size: 14px; color: var(--text-secondary); margin-bottom: 8px; }
|
||||
.pr-verdict-card__verdict-text { font-family: "Inter", sans-serif; font-size: 16px; line-height: 1.6; color: var(--text-primary); margin-bottom: 24px; }
|
||||
.pr-verdict-card__cta-group { display: flex; gap: 16px; flex-wrap: wrap; }
|
||||
.pr-verdict-card__cta-link { color: var(--teal-600); text-decoration: none; font-weight: 600; font-size: 15px; }
|
||||
.pr-verdict-card__cta-link:hover { color: var(--teal-700); text-decoration: underline; }
|
||||
|
||||
.pr-disclosure {
|
||||
background: var(--bg-inset);
|
||||
border-left: 4px solid var(--teal-500);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 12px 16px;
|
||||
font-family: "Inter", sans-serif;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.pr-disclosure__label { font-family: "Poppins", sans-serif; font-weight: 600; color: var(--text-secondary); }
|
||||
.pr-disclosure--inline { margin: 12px 0; }
|
||||
.pr-disclosure--banner { background: var(--teal-50); border: 1px solid var(--teal-200); border-left: 4px solid var(--teal-500); padding: 20px 24px; margin-bottom: 24px; font-size: 14px; }
|
||||
.pr-disclosure--footer { font-size: 13px; }
|
||||
|
||||
.pr-chip-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }
|
||||
.pr-chip { display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border: 1.5px solid var(--border-default); border-radius: var(--radius-pill); background: transparent; color: var(--text-primary); text-decoration: none; font-family: "Inter", sans-serif; font-weight: 600; font-size: 14px; cursor: pointer; transition: all 0.2s ease; }
|
||||
.pr-chip:hover { border-color: var(--teal-500); color: var(--teal-600); }
|
||||
.pr-chip--active { background: var(--teal-500); border-color: var(--teal-500); color: var(--color-white); }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.pr-chip { transition: none; }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.pr-verdict-card { padding: 20px; }
|
||||
.pr-verdict-card__title { font-size: 28px; }
|
||||
.pr-verdict-card__summary { font-size: 16px; }
|
||||
}
|
||||
BIN
favicon-16.png
Executable file
|
After Width: | Height: | Size: 481 B |
BIN
favicon-32.png
Executable file
|
After Width: | Height: | Size: 906 B |
BIN
favicon-48.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
favicon.ico
Executable file
|
After Width: | Height: | Size: 485 B |
17
footer.php
@@ -23,7 +23,7 @@
|
||||
<!-- Footer Grid -->
|
||||
<div class="footer-grid">
|
||||
<?php
|
||||
for ( $i = 1; $i <= 4; $i++ ) {
|
||||
for ( $i = 1; $i <= 5; $i++ ) {
|
||||
echo '<div class="footer-section">';
|
||||
if ( is_active_sidebar( 'footer-' . $i ) ) {
|
||||
dynamic_sidebar( 'footer-' . $i );
|
||||
@@ -52,6 +52,12 @@
|
||||
echo '<ul>';
|
||||
echo '<li><a href="https://github.com/peptiderepo" target="_blank" rel="noopener">' . esc_html__( 'GitHub', 'peptide-starter' ) . '</a></li>';
|
||||
echo '</ul>';
|
||||
} elseif ( 5 === $i ) {
|
||||
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( '/about' ) ) . '">' . esc_html__( 'Editorial Standards', 'peptide-starter' ) . '</a></li>';
|
||||
echo '</ul>';
|
||||
}
|
||||
}
|
||||
echo '</div>';
|
||||
@@ -65,6 +71,15 @@
|
||||
<?php echo wp_kses_post( peptide_starter_get_footer_copyright() ); ?>
|
||||
</p>
|
||||
|
||||
<!-- Disclosure -->
|
||||
<?php
|
||||
get_template_part(
|
||||
'template-parts/affiliate-disclosure',
|
||||
null,
|
||||
array( 'context' => 'footer' )
|
||||
);
|
||||
?>
|
||||
|
||||
<!-- Disclaimer -->
|
||||
<p class="footer-disclaimer">
|
||||
<?php esc_html_e( 'All data is provided for informational and educational purposes only. This platform does not provide medical advice, diagnoses, or treatment recommendations. Always consult qualified professionals.', 'peptide-starter' ); ?>
|
||||
|
||||
@@ -26,7 +26,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
}
|
||||
|
||||
// Theme constants.
|
||||
define( 'PEPTIDE_STARTER_VERSION', '1.6.0' );
|
||||
define( 'PEPTIDE_STARTER_VERSION', '2.0.0-alpha.1' );
|
||||
define( 'PEPTIDE_STARTER_DIR', get_template_directory() );
|
||||
define( 'PEPTIDE_STARTER_URI', get_template_directory_uri() );
|
||||
|
||||
@@ -44,6 +44,7 @@ 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';
|
||||
|
||||
/**
|
||||
* Set up theme defaults and register support for WordPress features.
|
||||
@@ -79,6 +80,7 @@ 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 );
|
||||
@@ -137,7 +139,7 @@ add_action( 'wp_enqueue_scripts', 'peptide_starter_plugin_overrides', 99 );
|
||||
* @return void
|
||||
*/
|
||||
function peptide_starter_widgets_init() {
|
||||
for ( $i = 1; $i <= 4; $i++ ) {
|
||||
for ( $i = 1; $i <= 5; $i++ ) {
|
||||
register_sidebar(
|
||||
array(
|
||||
/* translators: %d: footer column number */
|
||||
|
||||
13
header.php
@@ -20,6 +20,19 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="profile" href="https://gmpg.org/xfn/11">
|
||||
<?php wp_head(); ?>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Poppins:wght@600;700&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@600;700&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap">
|
||||
<link rel="icon" type="image/x-icon" href="<?php echo get_stylesheet_directory_uri(); ?>/favicon.ico">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="<?php echo get_stylesheet_directory_uri(); ?>/assets/brand/favicon-16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="<?php echo get_stylesheet_directory_uri(); ?>/assets/brand/favicon-32.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo get_stylesheet_directory_uri(); ?>/apple-touch-icon.png">
|
||||
<link rel="manifest" href="<?php echo get_stylesheet_directory_uri(); ?>/site.webmanifest">
|
||||
<meta name="theme-color" content="#1B8A92">
|
||||
<?php if ( ! function_exists( 'wp_is_block_theme' ) || ! wp_is_block_theme() ) : ?>
|
||||
<meta property="og:image" content="<?php echo esc_url( get_stylesheet_directory_uri() . '/assets/brand/og-default.png' ); ?>">
|
||||
<?php endif; ?>
|
||||
</head>
|
||||
|
||||
<body <?php body_class(); ?>>
|
||||
|
||||
BIN
icon-192.png
Executable file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
icon-512.png
Executable file
|
After Width: | Height: | Size: 15 KiB |
@@ -136,6 +136,15 @@ function peptide_starter_the_custom_logo() {
|
||||
the_custom_logo();
|
||||
return;
|
||||
}
|
||||
// Use SVG logo if available
|
||||
$logo_path = get_template_directory() . '/assets/brand/logo-horizontal.svg';
|
||||
if ( file_exists( $logo_path ) ) {
|
||||
echo '<a class="site-logo" href="' . esc_url( home_url( '/' ) ) . '" rel="home" aria-label="' . esc_attr( get_bloginfo( 'name' ) ) . '">';
|
||||
include $logo_path;
|
||||
echo '</a>';
|
||||
return;
|
||||
}
|
||||
// Fallback to text
|
||||
$site_name = get_bloginfo( 'name' );
|
||||
echo '<a class="site-logo" href="' . esc_url( home_url( '/' ) ) . '" rel="home">' . esc_html( $site_name ) . '</a>';
|
||||
}
|
||||
|
||||
179
inc/verdict-meta.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
/**
|
||||
* Verdict System Post Meta Registration & Meta Box
|
||||
*
|
||||
* Registers post meta for pr_peptide CPT:
|
||||
* - verdict_state (required): one of 5 states
|
||||
* - signal_row_1, signal_row_2, signal_row_3 (optional): evidence signal labels
|
||||
*
|
||||
* Adds a meta box to the pr_peptide edit screen for managing these fields.
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register verdict post meta for pr_peptide CPT.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function peptide_starter_register_verdict_meta() {
|
||||
$allowed_states = array( 'established', 'promising', 'investigational', 'insufficient', 'cautionary' );
|
||||
|
||||
// Register verdict_state meta.
|
||||
register_post_meta(
|
||||
'pr_peptide',
|
||||
'verdict_state',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'Verdict classification state',
|
||||
'single' => true,
|
||||
'show_in_rest' => true,
|
||||
'auth_callback' => '__return_true',
|
||||
'sanitize_callback' => function ( $value ) use ( $allowed_states ) {
|
||||
return in_array( $value, $allowed_states, true ) ? $value : '';
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
// Register signal row meta (up to 3).
|
||||
for ( $i = 1; $i <= 3; $i++ ) {
|
||||
register_post_meta(
|
||||
'pr_peptide',
|
||||
'signal_row_' . $i,
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => 'Evidence signal row ' . $i,
|
||||
'single' => true,
|
||||
'show_in_rest' => true,
|
||||
'auth_callback' => '__return_true',
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
add_action( 'init', 'peptide_starter_register_verdict_meta' );
|
||||
|
||||
/**
|
||||
* Add verdict meta box to pr_peptide edit screen.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function peptide_starter_add_verdict_meta_box() {
|
||||
add_meta_box(
|
||||
'peptide_starter_verdict',
|
||||
esc_html__( 'Verdict System', 'peptide-starter' ),
|
||||
'peptide_starter_render_verdict_meta_box',
|
||||
'pr_peptide',
|
||||
'normal',
|
||||
'high'
|
||||
);
|
||||
}
|
||||
add_action( 'add_meta_boxes', 'peptide_starter_add_verdict_meta_box' );
|
||||
|
||||
/**
|
||||
* Render verdict meta box HTML.
|
||||
*
|
||||
* @param WP_Post $post The post object.
|
||||
* @return void
|
||||
*/
|
||||
function peptide_starter_render_verdict_meta_box( $post ) {
|
||||
wp_nonce_field( 'peptide_starter_verdict_nonce', 'peptide_starter_verdict_nonce' );
|
||||
|
||||
$verdict_state = get_post_meta( $post->ID, 'verdict_state', true );
|
||||
$signal_row_1 = get_post_meta( $post->ID, 'signal_row_1', true );
|
||||
$signal_row_2 = get_post_meta( $post->ID, 'signal_row_2', true );
|
||||
$signal_row_3 = get_post_meta( $post->ID, 'signal_row_3', true );
|
||||
$allowed_states = array(
|
||||
'established' => esc_html__( 'Established', 'peptide-starter' ),
|
||||
'promising' => esc_html__( 'Promising', 'peptide-starter' ),
|
||||
'investigational' => esc_html__( 'Investigational', 'peptide-starter' ),
|
||||
'insufficient' => esc_html__( 'Insufficient Evidence', 'peptide-starter' ),
|
||||
'cautionary' => esc_html__( 'Cautionary', 'peptide-starter' ),
|
||||
);
|
||||
?>
|
||||
<div style="padding: 12px 0;">
|
||||
<label for="verdict_state" style="display: block; margin-bottom: 8px;">
|
||||
<strong><?php esc_html_e( 'Verdict State', 'peptide-starter' ); ?></strong>
|
||||
</label>
|
||||
<select id="verdict_state" name="verdict_state" style="width: 100%; padding: 8px; font-size: 14px;">
|
||||
<option value=""><?php esc_html_e( '— Select —', 'peptide-starter' ); ?></option>
|
||||
<?php foreach ( $allowed_states as $key => $label ) : ?>
|
||||
<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $verdict_state, $key ); ?>>
|
||||
<?php echo esc_html( $label ); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<label style="display: block; margin-bottom: 4px;">
|
||||
<strong><?php esc_html_e( 'Signal Row 1', 'peptide-starter' ); ?></strong>
|
||||
</label>
|
||||
<input type="text" name="signal_row_1" value="<?php echo esc_attr( $signal_row_1 ); ?>" placeholder="<?php esc_attr_e( 'e.g., Strong animal evidence', 'peptide-starter' ); ?>" style="width: 100%; padding: 8px; font-size: 14px; margin-bottom: 12px;">
|
||||
|
||||
<label style="display: block; margin-bottom: 4px;">
|
||||
<strong><?php esc_html_e( 'Signal Row 2', 'peptide-starter' ); ?></strong>
|
||||
</label>
|
||||
<input type="text" name="signal_row_2" value="<?php echo esc_attr( $signal_row_2 ); ?>" placeholder="<?php esc_attr_e( 'e.g., Limited human data', 'peptide-starter' ); ?>" style="width: 100%; padding: 8px; font-size: 14px; margin-bottom: 12px;">
|
||||
|
||||
<label style="display: block; margin-bottom: 4px;">
|
||||
<strong><?php esc_html_e( 'Signal Row 3', 'peptide-starter' ); ?></strong>
|
||||
</label>
|
||||
<input type="text" name="signal_row_3" value="<?php echo esc_attr( $signal_row_3 ); ?>" placeholder="<?php esc_attr_e( 'e.g., Regulatory status varies', 'peptide-starter' ); ?>" style="width: 100%; padding: 8px; font-size: 14px;">
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save verdict meta on post save.
|
||||
*
|
||||
* @param int $post_id The post ID.
|
||||
* @param WP_Post $post The post object.
|
||||
* @return void
|
||||
*/
|
||||
function peptide_starter_save_verdict_meta( $post_id, $post ) {
|
||||
// Verify nonce.
|
||||
if ( ! isset( $_POST['peptide_starter_verdict_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['peptide_starter_verdict_nonce'] ), 'peptide_starter_verdict_nonce' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only run for pr_peptide CPT.
|
||||
if ( 'pr_peptide' !== $post->post_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow only editors and admins.
|
||||
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$allowed_states = array( 'established', 'promising', 'investigational', 'insufficient', 'cautionary' );
|
||||
|
||||
// Save verdict_state.
|
||||
if ( isset( $_POST['verdict_state'] ) ) {
|
||||
$state = sanitize_text_field( wp_unslash( $_POST['verdict_state'] ) );
|
||||
if ( in_array( $state, $allowed_states, true ) ) {
|
||||
update_post_meta( $post_id, 'verdict_state', $state );
|
||||
} else {
|
||||
delete_post_meta( $post_id, 'verdict_state' );
|
||||
}
|
||||
}
|
||||
|
||||
// Save signal rows.
|
||||
for ( $i = 1; $i <= 3; $i++ ) {
|
||||
$field_name = 'signal_row_' . $i;
|
||||
if ( isset( $_POST[ $field_name ] ) ) {
|
||||
$value = sanitize_text_field( wp_unslash( $_POST[ $field_name ] ) );
|
||||
if ( ! empty( $value ) ) {
|
||||
update_post_meta( $post_id, $field_name, $value );
|
||||
} else {
|
||||
delete_post_meta( $post_id, $field_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'save_post', 'peptide_starter_save_verdict_meta', 10, 2 );
|
||||
BIN
og-default.png
Executable file
|
After Width: | Height: | Size: 34 KiB |
45
page-about.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: About & Editorial Standards
|
||||
*
|
||||
* Editorial standards, disclosure, and about page template.
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="main" class="site-main">
|
||||
<div class="page-about">
|
||||
<?php
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
?>
|
||||
<article id="post-<?php the_ID(); ?>" <?php post_class( 'entry-about' ); ?>>
|
||||
<header class="entry-header">
|
||||
<h1 class="entry-title"><?php the_title(); ?></h1>
|
||||
</header>
|
||||
<div class="entry-content">
|
||||
<?php the_content(); ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- Affiliate Disclosure Block -->
|
||||
<section class="page-about__disclosures">
|
||||
<h2><?php esc_html_e( 'How We Make Money', 'peptide-starter' ); ?></h2>
|
||||
<?php
|
||||
get_template_part(
|
||||
'template-parts/affiliate-disclosure',
|
||||
null,
|
||||
array( 'context' => 'banner' )
|
||||
);
|
||||
?>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer();
|
||||
44
page-how-we-review.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: How We Review Peptides
|
||||
*
|
||||
* Two-column layout with sticky sidebar ToC for the verdict system explainer.
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="main" class="site-main">
|
||||
<div class="page-how-we-review">
|
||||
<div class="page-how-we-review__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>
|
||||
|
||||
<?php if ( ! empty( get_the_content() ) ) : ?>
|
||||
<aside class="page-how-we-review__sidebar">
|
||||
<nav class="page-toc" aria-label="<?php esc_attr_e( 'Page contents', 'peptide-starter' ); ?>">
|
||||
<h3><?php esc_html_e( 'Contents', 'peptide-starter' ); ?></h3>
|
||||
<!-- JavaScript-generated ToC will be inserted here -->
|
||||
</nav>
|
||||
</aside>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php get_footer();
|
||||
14
site.webmanifest
Executable file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Peptide Repo",
|
||||
"short_name": "Peptide Repo",
|
||||
"description": "What the research really says — verdict-driven peptide science.",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#FAFAF7",
|
||||
"theme_color": "#1B8A92",
|
||||
"icons": [
|
||||
{"src": "/wp-content/themes/peptide-starter/assets/brand/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable"},
|
||||
{"src": "/wp-content/themes/peptide-starter/assets/brand/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable"}
|
||||
]
|
||||
}
|
||||
@@ -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: 1.7.1
|
||||
Version: 2.0.0-alpha.1
|
||||
License: GPL v2 or later
|
||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
Text Domain: peptide-starter
|
||||
|
||||
52
template-parts/affiliate-disclosure.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Affiliate Disclosure Component
|
||||
*
|
||||
* Displays FTC-compliant disclosure about affiliate commissions.
|
||||
* Three contexts: inline (default), banner, footer.
|
||||
* Accepts $args['context'].
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$context = isset( $args['context'] ) ? sanitize_text_field( $args['context'] ) : 'inline';
|
||||
|
||||
// Copy variants (verbatim per CMO spec).
|
||||
$inline_copy = 'If you buy through this link, the seller pays Peptide Repo a commission. We don\'t pay to feature any peptide, and our verdicts don\'t change based on who pays.';
|
||||
|
||||
$banner_copy = 'Peptide Repo earns a commission when readers buy through links to our fulfillment partners. We are funded by those commissions, not by the peptide brands themselves. No peptide on this site appears here because someone paid us. Our verdicts are decided before we negotiate any partnership, and we drop partners whose product or process degrades.';
|
||||
|
||||
$footer_copy = 'Peptide Repo earns a commission on some links. <a href="' . esc_url( home_url( '/about/' ) ) . '#disclosures">' . esc_html__( 'How we work', 'peptide-starter' ) . ' →</a>';
|
||||
|
||||
switch ( $context ) {
|
||||
case 'banner':
|
||||
?>
|
||||
<aside class="pr-disclosure pr-disclosure--banner" aria-label="<?php esc_attr_e( 'Affiliate disclosure', 'peptide-starter' ); ?>">
|
||||
<span class="pr-disclosure__label"><?php esc_html_e( 'A note on commerce.', 'peptide-starter' ); ?></span>
|
||||
<?php echo wp_kses_post( $banner_copy ); ?>
|
||||
</aside>
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'footer':
|
||||
?>
|
||||
<p class="pr-disclosure pr-disclosure--footer">
|
||||
<?php echo wp_kses_post( $footer_copy ); ?>
|
||||
</p>
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'inline':
|
||||
default:
|
||||
?>
|
||||
<aside class="pr-disclosure pr-disclosure--inline" aria-label="<?php esc_attr_e( 'Affiliate disclosure', 'peptide-starter' ); ?>">
|
||||
<span class="pr-disclosure__label"><?php esc_html_e( 'How we make money:', 'peptide-starter' ); ?></span>
|
||||
<?php echo wp_kses_post( $inline_copy ); ?>
|
||||
</aside>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
39
template-parts/verdict/badge.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Verdict Badge Component
|
||||
*
|
||||
* Displays a verdict state badge with glyph, label, and colors.
|
||||
* Accepts $args['verdict_state'] and $args['show_label'].
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$verdict_state = isset( $args['verdict_state'] ) ? sanitize_text_field( $args['verdict_state'] ) : '';
|
||||
$show_label = isset( $args['show_label'] ) ? (bool) $args['show_label'] : true;
|
||||
|
||||
// State configuration.
|
||||
$states = array(
|
||||
'established' => array( 'glyph' => '✓', 'label' => 'Established' ),
|
||||
'promising' => array( 'glyph' => '◐', 'label' => 'Promising' ),
|
||||
'investigational' => array( 'glyph' => '?', 'label' => 'Investigational' ),
|
||||
'insufficient' => array( 'glyph' => '⊘', 'label' => 'Insufficient Evidence' ),
|
||||
'cautionary' => array( 'glyph' => '⚠', 'label' => 'Cautionary' ),
|
||||
);
|
||||
|
||||
// Early exit if invalid state.
|
||||
if ( ! isset( $states[ $verdict_state ] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$state_info = $states[ $verdict_state ];
|
||||
?>
|
||||
<span class="pr-verdict pr-verdict--<?php echo esc_attr( $verdict_state ); ?>" role="img" aria-label="<?php echo esc_attr( 'Verdict: ' . $state_info['label'] ); ?>">
|
||||
<span class="pr-verdict__glyph" aria-hidden="true"><?php echo $state_info['glyph']; ?></span>
|
||||
<?php if ( $show_label ) : ?>
|
||||
<span class="pr-verdict__label"><?php echo esc_html( $state_info['label'] ); ?></span>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
99
template-parts/verdict/card.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* Verdict Card Component (Monograph Hero)
|
||||
*
|
||||
* Displays a full verdict card for a pr_peptide post.
|
||||
* Reads verdict_state and signal_row_1/2/3 from post meta.
|
||||
* Accepts $args['post_id'].
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$post_id = isset( $args['post_id'] ) ? absint( $args['post_id'] ) : get_the_ID();
|
||||
|
||||
// Get verdict state from post meta.
|
||||
$verdict_state = get_post_meta( $post_id, 'verdict_state', true );
|
||||
|
||||
// Early exit if no verdict state is set.
|
||||
if ( empty( $verdict_state ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Collect signal rows.
|
||||
$signals = array();
|
||||
for ( $i = 1; $i <= 3; $i++ ) {
|
||||
$signal_text = get_post_meta( $post_id, 'signal_row_' . $i, true );
|
||||
if ( ! empty( $signal_text ) ) {
|
||||
$signals[] = array(
|
||||
'glyph' => $i === 1 ? '✓' : ( $i === 2 ? '!' : '?' ),
|
||||
'label' => $signal_text,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$post = get_post( $post_id );
|
||||
?>
|
||||
<div class="pr-verdict-card">
|
||||
<div class="pr-verdict-card__header">
|
||||
<div>
|
||||
<?php
|
||||
get_template_part(
|
||||
'template-parts/verdict/badge',
|
||||
null,
|
||||
array(
|
||||
'verdict_state' => $verdict_state,
|
||||
'show_label' => true,
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<time class="pr-verdict-card__updated" datetime="<?php echo esc_attr( get_the_date( 'c', $post_id ) ); ?>">
|
||||
<?php echo esc_html( 'Updated ' . get_the_date( 'M d, Y', $post_id ) ); ?>
|
||||
</time>
|
||||
</div>
|
||||
|
||||
<h1 class="pr-verdict-card__title"><?php echo esc_html( get_the_title( $post_id ) ); ?></h1>
|
||||
|
||||
<p class="pr-verdict-card__summary">
|
||||
<?php
|
||||
// Get post excerpt or first 100 chars of content.
|
||||
$summary = get_the_excerpt( $post_id );
|
||||
if ( empty( $summary ) ) {
|
||||
$content = get_the_content( null, false, $post_id );
|
||||
$summary = wp_trim_words( $content, 20 );
|
||||
}
|
||||
echo wp_kses_post( $summary );
|
||||
?>
|
||||
</p>
|
||||
|
||||
<?php if ( ! empty( $signals ) ) : ?>
|
||||
<?php
|
||||
get_template_part(
|
||||
'template-parts/verdict/evidence-row',
|
||||
null,
|
||||
array( 'signals' => $signals )
|
||||
);
|
||||
?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="pr-verdict-card__verdict-label"><?php esc_html_e( 'Our verdict:', 'peptide-starter' ); ?></div>
|
||||
<div class="pr-verdict-card__verdict-text">
|
||||
<?php
|
||||
// Placeholder verdict text; can be extended with a custom meta field.
|
||||
echo esc_html__( 'This peptide merits careful scientific review. Please consult with a healthcare provider before use.', 'peptide-starter' );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="pr-verdict-card__cta-group">
|
||||
<a href="#evidence" class="pr-verdict-card__cta-link">
|
||||
<?php esc_html_e( 'Read the full evidence', 'peptide-starter' ); ?> →
|
||||
</a>
|
||||
<a href="#dosing" class="pr-verdict-card__cta-link">
|
||||
<?php esc_html_e( 'Jump to dosing', 'peptide-starter' ); ?> →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
34
template-parts/verdict/evidence-row.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Verdict Evidence Signal Row Component
|
||||
*
|
||||
* Displays an inset row of evidence signals with glyphs.
|
||||
* Accepts $args['signals'] as array of ['glyph' => '...', 'label' => '...']
|
||||
*
|
||||
* @package peptide-starter
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$signals = isset( $args['signals'] ) && is_array( $args['signals'] ) ? $args['signals'] : array();
|
||||
|
||||
if ( empty( $signals ) ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="pr-evidence-row">
|
||||
<?php foreach ( $signals as $signal ) : ?>
|
||||
<?php
|
||||
$glyph = isset( $signal['glyph'] ) ? sanitize_text_field( $signal['glyph'] ) : '';
|
||||
$label = isset( $signal['label'] ) ? sanitize_text_field( $signal['label'] ) : '';
|
||||
?>
|
||||
<?php if ( ! empty( $glyph ) && ! empty( $label ) ) : ?>
|
||||
<div class="pr-evidence-row__item">
|
||||
<span class="pr-evidence-row__glyph"><?php echo esc_html( $glyph ); ?></span>
|
||||
<span><?php echo esc_html( $label ); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||