From 964206684676ac08413ec0ecf8c73660a5b660ec Mon Sep 17 00:00:00 2001 From: peptiderepo Date: Wed, 8 Apr 2026 01:30:16 +0700 Subject: [PATCH] Initial commit: peptide-starter theme v1.3.1 --- .github/workflows/deploy.yml | 58 + .gitignore | 17 + 404.php | 36 + README.md | 267 ++++ archive-peptide.php | 73 ++ assets/js/navigation.js | 84 ++ assets/js/theme.js | 210 +++ footer.php | 80 ++ front-page.php | 78 ++ functions.php | 429 ++++++ header.php | 130 ++ index.php | 27 + page.php | 53 + screenshot.png | Bin 0 -> 32579 bytes searchform.php | 27 + single-peptide.php | 100 ++ style.css | 1948 ++++++++++++++++++++++++++++ template-parts/content-none.php | 51 + template-parts/content-peptide.php | 48 + template-parts/content.php | 96 ++ 20 files changed, 3812 insertions(+) create mode 100644 .github/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 404.php create mode 100644 README.md create mode 100644 archive-peptide.php create mode 100644 assets/js/navigation.js create mode 100644 assets/js/theme.js create mode 100644 footer.php create mode 100644 front-page.php create mode 100644 functions.php create mode 100644 header.php create mode 100644 index.php create mode 100644 page.php create mode 100644 screenshot.png create mode 100644 searchform.php create mode 100644 single-peptide.php create mode 100644 style.css create mode 100644 template-parts/content-none.php create mode 100644 template-parts/content-peptide.php create mode 100644 template-parts/content.php diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..767d4fd --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,58 @@ +name: Deploy Theme to Hostinger + +on: + push: + branches: [main] + +jobs: + deploy: + name: Deploy to Production + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Deploy via SSH + uses: appleboy/ssh-action@v1 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + port: ${{ secrets.SSH_PORT }} + script: | + THEME_DIR="/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter" + REPO_URL="https://github.com/peptiderepo/peptide-starter-theme.git" + + # If this is the first deploy, clone the repo + if [ ! -d "$THEME_DIR/.git" ]; then + echo "First deploy — cloning repo..." + rm -rf "$THEME_DIR" + git clone "$REPO_URL" "$THEME_DIR" + else + echo "Pulling latest changes..." + cd "$THEME_DIR" + git fetch origin main + git reset --hard origin/main + fi + + echo "Theme deployed successfully." + + - name: Purge LiteSpeed Cache + uses: appleboy/ssh-action@v1 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USERNAME }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + port: ${{ secrets.SSH_PORT }} + script: | + # Purge LiteSpeed cache so visitors see the update immediately + CACHE_DIR="/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/litespeed/cssjs" + if [ -d "$CACHE_DIR" ]; then + rm -rf "$CACHE_DIR"/* + echo "LiteSpeed CSS/JS cache purged." + fi + + # Touch a file to signal LiteSpeed to rebuild + touch "/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/.lscache_purge" 2>/dev/null || true + echo "Cache purge signal sent." diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bac679c --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# OS files +.DS_Store +Thumbs.db + +# Editor files +*.swp +*.swo +*~ +.vscode/ +.idea/ + +# Node (if ever used for build tooling) +node_modules/ +package-lock.json + +# Zip artifacts (built by CI) +*.zip diff --git a/404.php b/404.php new file mode 100644 index 0000000..7a92bc8 --- /dev/null +++ b/404.php @@ -0,0 +1,36 @@ + + +
+
+
+

+

+ + + + +
+
+
+ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..ffe5238 --- /dev/null +++ b/README.md @@ -0,0 +1,267 @@ +# Peptide Starter Theme + +A premium, accessible WordPress theme for the Peptide Repo scientific peptide reference database. + +## Features + +- **Modern Design** - Clean, minimalist aesthetic inspired by Apple's human interface guidelines +- **Dark Mode Support** - Full dark mode via `prefers-color-scheme` and manual toggle +- **Accessibility** - WCAG AA compliant with proper focus indicators and semantic HTML +- **Plugin Harmony** - Respects plugin CSS namespaces (`.pn-*` for Peptide News plugin) +- **Responsive Design** - Mobile-first approach with proper breakpoints (480px, 768px, 1024px, 1440px) +- **Typography** - Inter font with 1.125x modular scale for excellent readability +- **Component Library** - Pre-built buttons, cards, forms, badges, alerts, and pagination +- **Customizer Support** - Theme options for hero title, subtitle, search placeholder, footer text +- **Performance** - Lightweight CSS architecture using custom properties instead of !important + +## Installation + +1. Download `peptide-starter.zip` +2. Go to WordPress Admin → Appearance → Themes +3. Click "Add New" → "Upload Theme" +4. Select the zip file and click "Install Now" +5. Click "Activate" to use the theme + +## Theme Structure + +``` +peptide-starter/ +├── style.css # Main stylesheet with all CSS +├── functions.php # Theme setup and functionality +├── header.php # Global header with navigation +├── footer.php # Global footer with widgets +├── index.php # Fallback template +├── front-page.php # Home page with hero + news feed +├── page.php # Generic page template +├── archive-peptide.php # Peptide archive/database view +├── single-peptide.php # Single peptide detail page +├── 404.php # 404 error page +├── searchform.php # Search form template +├── screenshot.png # Theme screenshot for WordPress +├── assets/ +│ └── js/ +│ ├── navigation.js # Mobile menu and nav functionality +│ └── theme.js # Dark mode toggle and utilities +├── template-parts/ +│ ├── content.php # Post/page content template +│ └── content-none.php # Empty state template +└── languages/ # Translation files +``` + +## Design System + +### Color Palette + +**Light Mode:** +- Primary: `#0066CC` (Blue) +- Text Primary: `#111827` (Near Black) +- Text Secondary: `#6B7280` (Gray) +- Background: `#FFFFFF` (White) + +**Dark Mode:** +- Primary: `#3B82F6` (Bright Blue) +- Text Primary: `#F9FAFB` (Near White) +- Text Secondary: `#D1D5DB` (Light Gray) +- Background: `#111827` (Near Black) + +### Typography + +All sizes use a **1.125x modular scale** with **8px grid base**: + +- **H1**: 48px, 700 weight +- **H2**: 40px, 700 weight +- **H3**: 32px, 600 weight +- **H4**: 24px, 600 weight +- **H5**: 20px, 700 weight (fixed from 18px per Design Director) +- **H6**: 16px, 500 weight +- **Body**: 14px, 400 weight (fixed from 16px per Design Director) + +Font family: Inter (with system font fallback) + +### Spacing + +8px base unit grid: +- `--spacing-xs`: 4px +- `--spacing-sm`: 8px +- `--spacing-md`: 16px +- `--spacing-lg`: 24px +- `--spacing-xl`: 32px +- `--spacing-2xl`: 48px +- `--spacing-3xl`: 64px +- `--spacing-4xl`: 80px +- `--spacing-5xl`: 96px + +### Components + +**Buttons:** +- `.ps-btn` - Base button +- `.ps-btn-primary` - Primary action (blue) +- `.ps-btn-secondary` - Secondary action (outlined) +- `.ps-btn-tertiary` - Tertiary action (transparent) +- `.ps-btn-sm`, `.ps-btn-lg`, `.ps-btn-full` - Size variants + +**Cards:** +- `.ps-card` - Standard card with border and hover effect + +**Forms:** +- Proper focus states with 15% opacity focus ring +- Error states with red border and light red background +- Support for text, email, password, search, number, url inputs + +**Alerts:** +- `.ps-alert-info` - Blue alert +- `.ps-alert-success` - Green alert +- `.ps-alert-warning` - Amber alert +- `.ps-alert-error` - Red alert + +**Badges & Tags:** +- `.ps-badge` - Static badge +- `.ps-tag` - Dismissible tag + +## Dark Mode + +### How it Works + +The theme detects dark mode in this order: +1. User's explicit choice via toggle (stored in `localStorage`) +2. System preference via `prefers-color-scheme: dark` +3. Default to light mode + +The theme applies dark colors via: +- `@media (prefers-color-scheme: dark)` - System preference +- `html[data-theme="dark"]` - User override (takes precedence) + +### Plugin Integration + +The theme broadcasts dark mode changes to plugins via: + +1. **Custom Event**: `themechange` event on `document` + ```javascript + document.addEventListener('themechange', (e) => { + console.log('Theme is now:', e.detail.theme); + }); + ``` + +2. **Data Attribute**: `data-theme` on `` + ```javascript + const theme = document.documentElement.getAttribute('data-theme'); + ``` + +3. **CSS Custom Properties**: All colors controlled via CSS variables + +## Plugin Compatibility + +### Peptide News Plugin +The theme provides optimal styling for the Peptide News plugin: +- News feed grid adapts to screen size (1-4 columns) +- Plugin `.pn-*` classes are untouched by theme +- Plugin handles its own card styling +- Dark mode colors available via CSS custom properties + +### WooCommerce +- Cart icon in header (if WooCommerce is active) +- Lightweight integration without full theme styling + +## Customizer Options + +Go to **Appearance → Customize** to modify: +- **Hero Title** - Main headline on home page +- **Hero Subtitle** - Subheading under title +- **Search Placeholder** - Text in search input +- **Footer Copyright** - Copyright/attribution text +- **Dark Mode Default** - Enable dark mode on first visit + +## Accessibility + +The theme meets **WCAG AA standards**: +- All color combinations have 4.5:1+ contrast ratio +- Proper heading hierarchy (H1-H6) +- Focus indicators on all interactive elements (2px outline) +- Keyboard navigation support +- Skip-to-main-content link +- Semantic HTML with proper landmarks +- Form labels properly associated with inputs +- Alt text for images + +## Responsive Breakpoints + +- **Mobile**: 320px - 479px +- **Tablet**: 480px - 767px +- **Desktop**: 768px - 1023px +- **Large**: 1024px - 1439px +- **Extra Large**: 1440px+ + +The theme uses **mobile-first CSS** - styles start mobile and add complexity at larger breakpoints. + +## Performance + +- **No `!important` on global elements** - Prevents plugin conflicts +- **CSS Custom Properties** - Single source of truth for design tokens +- **Minimal JavaScript** - Only essential interactivity +- **Font loading** - Inter from Google Fonts with `display=swap` +- **Proper scoping** - Theme classes prefixed with `.ps-` to avoid conflicts + +## Development + +### Adding Custom Styles + +Modify `style.css` sections: +1. Components - Add new component classes +2. Pages - Add page-specific styles +3. Responsive - Add mobile/tablet/desktop rules + +### CSS Architecture + +The stylesheet is organized in this order: +1. Reset +2. CSS Custom Properties (variables) +3. Typography +4. Global Styles +5. Components +6. Regions (header, footer) +7. Pages +8. Animations +9. Accessibility +10. Dark Mode +11. Responsive + +### Adding New Templates + +Create new template files following WordPress standards: +- `page-{slug}.php` - Specific page templates +- `archive-{post-type}.php` - Archive templates +- `single-{post-type}.php` - Single post templates +- `template-parts/{name}.php` - Reusable template parts + +## Browser Support + +- Chrome/Edge (latest 2 versions) +- Firefox (latest 2 versions) +- Safari (latest 2 versions) +- iOS Safari 12+ +- Chrome Android + +## License + +GPL v2 or later - See LICENSE file + +## Credits + +Designed with principles from: +- Apple Human Interface Guidelines (2025) +- Modern Scientific Databases (PubMed, Nature) +- Premium SaaS Design (Linear, Stripe, Vercel) +- WordPress Best Practices + +## Support + +For issues and feature requests, visit: https://github.com/peptiderepo/peptide-starter + +## Changelog + +### Version 1.0.0 (Initial Release) +- Initial theme launch +- All core features implemented +- Full dark mode support +- Plugin harmony architecture +- Accessibility compliance (WCAG AA) diff --git a/archive-peptide.php b/archive-peptide.php new file mode 100644 index 0000000..34cf42c --- /dev/null +++ b/archive-peptide.php @@ -0,0 +1,73 @@ + + +
+ +
+
+

+ +

+
+
+ + +
+ + +
+ +
+ + + + +
+ +
+ + + +
+

+

+ + + +
+ +
+
+ + { + link.addEventListener('click', closeMenu); + }); + + // Close menu on Escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + closeMenu(); + } + }); + + // Set initial aria-expanded state + menuToggle.setAttribute('aria-expanded', 'false'); + + // Close menu when window is resized above mobile breakpoint + const mediaQuery = window.matchMedia('(min-width: 768px)'); + mediaQuery.addEventListener('change', (e) => { + if (e.matches) { + closeMenu(); + } + }); +})(); diff --git a/assets/js/theme.js b/assets/js/theme.js new file mode 100644 index 0000000..2db7774 --- /dev/null +++ b/assets/js/theme.js @@ -0,0 +1,210 @@ +/** + * Theme Utilities + * Peptide Starter Theme + * + * Handles: + * - Dark mode toggle functionality + * - Dark mode preference persistence + * - Plugin dark mode coordination + * - Smooth transitions + */ + +(function() { + 'use strict'; + + const html = document.documentElement; + const darkModeToggle = document.querySelector('.dark-mode-toggle'); + const sunIcon = document.querySelector('.sun-icon'); + const moonIcon = document.querySelector('.moon-icon'); + + if (!darkModeToggle) { + return; + } + + /** + * Get current theme preference + * @returns {string} 'dark' or 'light' + */ + function getCurrentTheme() { + const stored = localStorage.getItem('peptide-starter-theme'); + if (stored) { + return stored; + } + + const currentAttr = html.getAttribute('data-theme'); + if (currentAttr) { + return currentAttr; + } + + const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + return systemDark ? 'dark' : 'light'; + } + + /** + * Set theme preference + * @param {string} theme - 'dark' or 'light' + */ + function setTheme(theme) { + html.setAttribute('data-theme', theme); + localStorage.setItem('peptide-starter-theme', theme); + + // Update icon visibility + updateIcons(theme); + + // Notify plugins about theme change via custom event + const event = new CustomEvent('themechange', { + detail: { theme: theme } + }); + document.dispatchEvent(event); + + // Also update body class for CSS hooks + document.body.classList.remove('dark-mode', 'light-mode'); + document.body.classList.add(theme === 'dark' ? 'dark-mode' : 'light-mode'); + } + + /** + * Update icon visibility based on theme + * @param {string} theme - 'dark' or 'light' + */ + function updateIcons(theme) { + if (theme === 'dark') { + sunIcon.style.display = 'block'; + moonIcon.style.display = 'none'; + } else { + sunIcon.style.display = 'none'; + moonIcon.style.display = 'block'; + } + } + + /** + * Toggle between dark and light mode + */ + function toggleDarkMode() { + const currentTheme = getCurrentTheme(); + const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; + setTheme(newTheme); + } + + // Initialize theme on page load + const initialTheme = getCurrentTheme(); + setTheme(initialTheme); + + // Dark mode toggle button click + darkModeToggle.addEventListener('click', toggleDarkMode); + + // Listen for system preference changes + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + mediaQuery.addEventListener('change', (e) => { + const stored = localStorage.getItem('peptide-starter-theme'); + if (!stored) { + setTheme(e.matches ? 'dark' : 'light'); + } + }); + + // Expose API for plugins to read/listen to theme changes + window.peptideStarterTheme = { + getCurrentTheme: getCurrentTheme, + setTheme: setTheme, + toggleDarkMode: toggleDarkMode, + }; + + /** + * Plugin Integration Example: + * Plugins can listen to theme changes via: + * + * 1. Custom event listener: + * document.addEventListener('themechange', function(e) { + * console.log('Theme changed to:', e.detail.theme); + * }); + * + * 2. MutationObserver on data-theme: + * const observer = new MutationObserver((mutations) => { + * const theme = html.getAttribute('data-theme'); + * console.log('Theme is now:', theme); + * }); + * observer.observe(html, { attributes: true }); + * + * 3. Direct access to CSS custom properties which theme controls + */ + + /** + * Smooth scroll behavior + */ + function initSmoothScroll() { + const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; + if (!prefersReducedMotion) { + document.documentElement.style.scrollBehavior = 'smooth'; + } + } + + initSmoothScroll(); + + /** + * Add focus-visible polyfill for older browsers + */ + function initFocusVisible() { + const isKeyboardEvent = (e) => { + return e.mozInputSource === MOZ_SOURCE_KEYBOARD || + e.detail === 0 || + (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents === false); + }; + + document.addEventListener('mousedown', (e) => { + document.body.classList.remove('keyboard-focus'); + }, true); + + document.addEventListener('keydown', () => { + document.body.classList.add('keyboard-focus'); + }, true); + } + + // Search overlay functionality (Peptide Search AI integration) + const searchToggle = document.querySelector('.search-toggle'); + const searchOverlay = document.getElementById('search-overlay'); + const searchOverlayClose = document.querySelector('.search-overlay-close'); + + function openSearchOverlay() { + if (!searchOverlay) return; + searchOverlay.classList.add('active'); + searchOverlay.setAttribute('aria-hidden', 'false'); + document.body.style.overflow = 'hidden'; + // Focus the search input inside the overlay + const input = searchOverlay.querySelector('.psa-search-input, .ps-search-input, input[type="search"], input[type="text"]'); + if (input) { + setTimeout(() => input.focus(), 100); + } + } + + function closeSearchOverlay() { + if (!searchOverlay) return; + searchOverlay.classList.remove('active'); + searchOverlay.setAttribute('aria-hidden', 'true'); + document.body.style.overflow = ''; + // Return focus to search toggle + if (searchToggle) searchToggle.focus(); + } + + if (searchToggle) { + searchToggle.addEventListener('click', openSearchOverlay); + } + + if (searchOverlayClose) { + searchOverlayClose.addEventListener('click', closeSearchOverlay); + } + + if (searchOverlay) { + // Close overlay when clicking the backdrop + searchOverlay.addEventListener('click', (e) => { + if (e.target === searchOverlay) { + closeSearchOverlay(); + } + }); + + // Close on Escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && searchOverlay.classList.contains('active')) { + closeSearchOverlay(); + } + }); + } +})(); diff --git a/footer.php b/footer.php new file mode 100644 index 0000000..f88f815 --- /dev/null +++ b/footer.php @@ -0,0 +1,80 @@ + + + + + + + + diff --git a/front-page.php b/front-page.php new file mode 100644 index 0000000..77d4fa0 --- /dev/null +++ b/front-page.php @@ -0,0 +1,78 @@ + + +
+ +
+
+

+

+ + + + + + +
+
+ + + +
+
+
+

+

+ +

+
+ +
+
+ + + +
+ + diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..170adfc --- /dev/null +++ b/functions.php @@ -0,0 +1,429 @@ + esc_html__( 'Primary Menu', 'peptide-starter' ), + 'footer' => esc_html__( 'Footer Menu', 'peptide-starter' ), + ) ); + + // Add support for wide blocks + add_theme_support( 'align-wide' ); + + // Load text domain + load_theme_textdomain( 'peptide-starter', PEPTIDE_STARTER_DIR . '/languages' ); +} +add_action( 'after_setup_theme', 'peptide_starter_setup' ); + +/** + * Register and enqueue stylesheets and scripts + */ +function peptide_starter_scripts() { + // Register and enqueue main stylesheet + wp_enqueue_style( 'peptide-starter-style', PEPTIDE_STARTER_URI . '/style.css', array(), PEPTIDE_STARTER_VERSION ); + + // Add conditional scripts + wp_enqueue_script( 'peptide-starter-navigation', PEPTIDE_STARTER_URI . '/assets/js/navigation.js', array(), PEPTIDE_STARTER_VERSION, true ); + wp_enqueue_script( 'peptide-starter-theme', PEPTIDE_STARTER_URI . '/assets/js/theme.js', array(), PEPTIDE_STARTER_VERSION, true ); + + // Pass PHP data to JavaScript + wp_localize_script( 'peptide-starter-theme', 'peptideStarterData', array( + 'siteUrl' => home_url( '/' ), + 'isDarkMode' => get_theme_mod( 'dark_mode_default', false ), + ) ); + + // Dequeue comment reply script if comments are not open + if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) { + wp_enqueue_script( 'comment-reply' ); + } +} +add_action( 'wp_enqueue_scripts', 'peptide_starter_scripts' ); + +/** + * Enqueue plugin override styles at a late priority so they load AFTER plugin stylesheets. + * This ensures theme overrides (e.g. removing line-clamp on article excerpts) beat plugin CSS. + */ +function peptide_starter_plugin_overrides() { + wp_add_inline_style( 'peptide-starter-style', ' + /* Override Peptide News plugin line-clamp — show full summaries */ + p.pn-article-excerpt, + .pn-article-card p.pn-article-excerpt, + body .pn-article-excerpt { + -webkit-line-clamp: unset !important; + -webkit-box-orient: unset !important; + display: block !important; + overflow: visible !important; + } + ' ); +} +add_action( 'wp_enqueue_scripts', 'peptide_starter_plugin_overrides', 99 ); + +/** + * Register widget areas + */ +function peptide_starter_widgets_init() { + register_sidebar( array( + 'name' => esc_html__( 'Footer - Column 1', 'peptide-starter' ), + 'id' => 'footer-1', + 'description' => esc_html__( 'Footer widget area 1', 'peptide-starter' ), + 'before_widget' => '', + 'before_title' => '

', + 'after_title' => '

', + ) ); + + register_sidebar( array( + 'name' => esc_html__( 'Footer - Column 2', 'peptide-starter' ), + 'id' => 'footer-2', + 'description' => esc_html__( 'Footer widget area 2', 'peptide-starter' ), + 'before_widget' => '', + 'before_title' => '

', + 'after_title' => '

', + ) ); + + register_sidebar( array( + 'name' => esc_html__( 'Footer - Column 3', 'peptide-starter' ), + 'id' => 'footer-3', + 'description' => esc_html__( 'Footer widget area 3', 'peptide-starter' ), + 'before_widget' => '', + 'before_title' => '

', + 'after_title' => '

', + ) ); + + register_sidebar( array( + 'name' => esc_html__( 'Footer - Column 4', 'peptide-starter' ), + 'id' => 'footer-4', + 'description' => esc_html__( 'Footer widget area 4', 'peptide-starter' ), + 'before_widget' => '', + 'before_title' => '

', + 'after_title' => '

', + ) ); +} +add_action( 'widgets_init', 'peptide_starter_widgets_init' ); + +/** + * Register theme customizer options + */ +function peptide_starter_customize_register( $wp_customize ) { + // Logo section + $wp_customize->add_section( 'peptide_starter_branding', array( + 'title' => esc_html__( 'Branding', 'peptide-starter' ), + 'priority' => 30, + ) ); + + // Hero settings section + $wp_customize->add_section( 'peptide_starter_hero', array( + 'title' => esc_html__( 'Hero Section', 'peptide-starter' ), + 'priority' => 40, + ) ); + + // Hero Title + $wp_customize->add_setting( 'hero_title', array( + 'default' => get_bloginfo( 'name' ), + 'transport' => 'postMessage', + ) ); + + $wp_customize->add_control( 'hero_title', array( + 'label' => esc_html__( 'Hero Title', 'peptide-starter' ), + 'section' => 'peptide_starter_hero', + 'type' => 'text', + ) ); + + // Hero Subtitle + $wp_customize->add_setting( 'hero_subtitle', array( + 'default' => esc_html__( 'A scientific peptide reference database', 'peptide-starter' ), + 'transport' => 'postMessage', + ) ); + + $wp_customize->add_control( 'hero_subtitle', array( + 'label' => esc_html__( 'Hero Subtitle', 'peptide-starter' ), + 'section' => 'peptide_starter_hero', + 'type' => 'textarea', + ) ); + + // Hero Search Placeholder + $wp_customize->add_setting( 'hero_search_placeholder', array( + 'default' => esc_html__( 'Search peptides, sequences, or research...', 'peptide-starter' ), + 'transport' => 'postMessage', + ) ); + + $wp_customize->add_control( 'hero_search_placeholder', array( + 'label' => esc_html__( 'Search Placeholder', 'peptide-starter' ), + 'section' => 'peptide_starter_hero', + 'type' => 'text', + ) ); + + // Footer section + $wp_customize->add_section( 'peptide_starter_footer', array( + 'title' => esc_html__( 'Footer', 'peptide-starter' ), + 'priority' => 50, + ) ); + + // Footer Copyright Text + $wp_customize->add_setting( 'footer_copyright', array( + 'default' => esc_html__( 'Copyright © 2026 Peptide Repo. All rights reserved.', 'peptide-starter' ), + 'transport' => 'postMessage', + ) ); + + $wp_customize->add_control( 'footer_copyright', array( + 'label' => esc_html__( 'Copyright Text', 'peptide-starter' ), + 'section' => 'peptide_starter_footer', + 'type' => 'textarea', + ) ); + + // Dark mode section + $wp_customize->add_section( 'peptide_starter_theme_mode', array( + 'title' => esc_html__( 'Theme Mode', 'peptide-starter' ), + 'priority' => 60, + ) ); + + // Dark mode default + $wp_customize->add_setting( 'dark_mode_default', array( + 'default' => false, + 'transport' => 'refresh', + ) ); + + $wp_customize->add_control( 'dark_mode_default', array( + 'label' => esc_html__( 'Enable Dark Mode by Default', 'peptide-starter' ), + 'section' => 'peptide_starter_theme_mode', + 'type' => 'checkbox', + ) ); +} +add_action( 'customize_register', 'peptide_starter_customize_register' ); + +/** + * Add custom logo support + */ +function peptide_starter_get_custom_logo() { + if ( function_exists( 'get_custom_logo' ) ) { + return get_custom_logo(); + } + return ''; +} + +/** + * Navigation Menu Walker for handling active states + */ +class Peptide_Starter_Nav_Walker extends Walker_Nav_Menu { + public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { + if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) { + $t = ''; + $n = ''; + } else { + $t = "\t"; + $n = "\n"; + } + $indent = ( $depth ) ? str_repeat( $t, $depth ) : ''; + + $classes = empty( $item->classes ) ? array() : (array) $item->classes; + $classes[] = 'menu-item-' . $item->ID; + + if ( in_array( 'current-menu-item', $classes, true ) || in_array( 'current-menu-parent', $classes, true ) ) { + $classes[] = 'active'; + } + + $args = apply_filters( 'nav_menu_item_args', $args, $item, $depth ); + + $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) ); + $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : ''; + + $id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth ); + $id = $id ? ' id="' . esc_attr( $id ) . '"' : ''; + + $output .= $indent . ''; + + $atts = array(); + $atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : ''; + $atts['target'] = ! empty( $item->target ) ? $item->target : ''; + $atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : ''; + $atts['href'] = ! empty( $item->url ) ? $item->url : ''; + + $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth ); + + $attributes = ''; + foreach ( $atts as $attr => $value ) { + if ( ! empty( $value ) ) { + $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value ); + $attributes .= ' ' . $attr . '="' . $value . '"'; + } + } + + $title = apply_filters( 'nav_menu_item_title', $item->title, $item, $args, $depth ); + $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth ); + + $link = $args->before; + $link .= ''; + $link .= $args->link_before . $title . $args->link_after; + $link .= ''; + $link .= $args->after; + + $output .= apply_filters( 'nav_menu_item_title', $link, $item, $args, $depth ); + + $output .= '' . $n; + } +} + +/** + * Display custom logo + */ +function peptide_starter_the_custom_logo() { + if ( function_exists( 'the_custom_logo' ) ) { + the_custom_logo(); + } else { + $site_name = get_bloginfo( 'name' ); + echo ''; + } +} + +/** + * Get hero title + */ +function peptide_starter_get_hero_title() { + return get_theme_mod( 'hero_title', get_bloginfo( 'name' ) ); +} + +/** + * Get hero subtitle + */ +function peptide_starter_get_hero_subtitle() { + return get_theme_mod( 'hero_subtitle', esc_html__( 'A scientific peptide reference database', 'peptide-starter' ) ); +} + +/** + * Get search placeholder + */ +function peptide_starter_get_search_placeholder() { + return get_theme_mod( 'hero_search_placeholder', esc_html__( 'Search peptides, sequences, or research...', 'peptide-starter' ) ); +} + +/** + * Get footer copyright text + */ +function peptide_starter_get_footer_copyright() { + return get_theme_mod( 'footer_copyright', esc_html__( 'Copyright © 2026 Peptide Repo. All rights reserved.', 'peptide-starter' ) ); +} + +/** + * Apply dark mode class to body if enabled + */ +function peptide_starter_dark_mode_body_class( $classes ) { + if ( get_theme_mod( 'dark_mode_default', false ) ) { + $classes[] = 'dark-mode-default'; + } + return $classes; +} +add_filter( 'body_class', 'peptide_starter_dark_mode_body_class' ); + +/** + * Register pagination function + */ +function peptide_starter_pagination() { + global $wp_query; + + if ( $wp_query->max_num_pages <= 1 ) { + return; + } + + $current_page = max( 1, get_query_var( 'paged' ) ); + $total_pages = $wp_query->max_num_pages; + + echo ''; +} + +/** + * Get the excerpt + */ +function peptide_starter_get_excerpt( $post_id = 0, $length = 20 ) { + if ( ! $post_id ) { + $post_id = get_the_ID(); + } + + $excerpt = get_the_excerpt( $post_id ); + + if ( ! $excerpt ) { + $excerpt = wp_trim_words( get_the_content( $post_id ), $length ); + } + + return $excerpt; +} + +/** + * Check if we should show footer newsletter signup + */ +function peptide_starter_show_newsletter_form() { + return apply_filters( 'peptide_starter_show_newsletter', true ); +} + +/** + * Enqueue inline script for dark mode toggle (output in footer) + */ +function peptide_starter_inline_dark_mode_script() { + $default_dark = get_theme_mod( 'dark_mode_default', false ) ? 'dark' : 'light'; + ?> + + +> + + + + + + + +> + + + + + + + + + + + + diff --git a/index.php b/index.php new file mode 100644 index 0000000..9de0354 --- /dev/null +++ b/index.php @@ -0,0 +1,27 @@ + + +
+
+ +
+
+ + diff --git a/page.php b/page.php new file mode 100644 index 0000000..fe0652d --- /dev/null +++ b/page.php @@ -0,0 +1,53 @@ + + +
+ + + + + +
+
> + %s', 'peptide-starter' ), + array( 'span' => array( 'class' => array() ) ) + ), + get_the_title() + ), + '' + ); + ?> +
+
+ +
+ + diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..e1451990e0198af65e979cdfb40123bdf3da1f78 GIT binary patch literal 32579 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 literal 0 HcmV?d00001 diff --git a/searchform.php b/searchform.php new file mode 100644 index 0000000..3608a11 --- /dev/null +++ b/searchform.php @@ -0,0 +1,27 @@ + + diff --git a/single-peptide.php b/single-peptide.php new file mode 100644 index 0000000..8aff085 --- /dev/null +++ b/single-peptide.php @@ -0,0 +1,100 @@ + + +
+ + + + + +
+
> + + + + + + +
+ +
+ + +
+
+ +
+
+ + + +
+
+ + + +
+
Da
+ + + +
+
+ +
+
+ + + %s', 'peptide-starter' ), + array( 'span' => array( 'class' => array() ) ) + ), + get_the_title() + ), + '' + ); + ?> +
+ + + +
+ +
+ + diff --git a/style.css b/style.css new file mode 100644 index 0000000..e68c4e9 --- /dev/null +++ b/style.css @@ -0,0 +1,1948 @@ +/* +Theme Name: Peptide Starter +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.3.1 +License: GPL v2 or later +License URI: https://www.gnu.org/licenses/gpl-2.0.html +Text Domain: peptide-starter +Domain Path: /languages +Requires at least: 6.0 +Requires PHP: 7.4 +*/ + +/* ============================================================================ + CSS ARCHITECTURE + ============================================================================ + + This stylesheet organizes theme styles in the following order: + 1. CSS Reset + 2. CSS Custom Properties (design tokens) + 3. Typography & Font Loading + 4. Global Styles & Layout + 5. Components (buttons, cards, forms, badges) + 6. Regions (header, footer, main) + 7. Pages (home, archive, single) + 8. Animations & Transitions + 9. Accessibility (focus, reduced motion) + 10. Dark Mode (color overrides) + 11. Responsive (mobile-first breakpoints) + + Philosophy: + - Use CSS custom properties for all design tokens + - Avoid !important on global elements (breaks plugins) + - Scope styles with specificity, not cascade tricks + - Respect plugin namespaces (.pn-*, .ps-*) + - Mobile-first responsive approach + + ============================================================================ */ + +/* ============================================================================ + 1. CSS RESET + ============================================================================ */ + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + margin: 0; + padding: 0; + line-height: 1.5; +} + +h1, h2, h3, h4, h5, h6 { + margin: 0; + padding: 0; +} + +p { + margin: 0; +} + +ul, ol { + list-style: none; +} + +a { + color: inherit; + text-decoration: none; +} + +button, input, textarea, select { + font: inherit; + color: inherit; +} + +img, svg { + max-width: 100%; + display: block; +} + +/* ============================================================================ + 2. CSS CUSTOM PROPERTIES (Design Tokens) + ============================================================================ */ + +:root { + /* ---- FONT FAMILIES ---- */ + --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", system-ui, sans-serif; + --font-mono: "Monaco", "Menlo", "Ubuntu Mono", "Courier New", monospace; + + /* ---- TYPOGRAPHY SCALE (tightened for better content density) ---- */ + /* H1 */ + --text-h1: 36px; + --text-h1-weight: 700; + --text-h1-lh: 1.2; + --text-h1-ls: -0.02em; + + /* H2 */ + --text-h2: 30px; + --text-h2-weight: 700; + --text-h2-lh: 1.25; + --text-h2-ls: -0.015em; + + /* H3 */ + --text-h3: 24px; + --text-h3-weight: 600; + --text-h3-lh: 1.3; + --text-h3-ls: -0.01em; + + /* H4 */ + --text-h4: 20px; + --text-h4-weight: 600; + --text-h4-lh: 1.35; + --text-h4-ls: 0; + + /* H5 */ + --text-h5: 17px; + --text-h5-weight: 700; + --text-h5-lh: 1.4; + --text-h5-ls: 0; + + /* H6 */ + --text-h6: 15px; + --text-h6-weight: 500; + --text-h6-lh: 1.4; + --text-h6-ls: 0; + + /* Body (slightly smaller for density — still readable) */ + --text-body-lg: 15px; + --text-body-md: 13px; + --text-body-sm: 12px; + + /* Labels & Captions */ + --text-label: 11px; + --text-label-weight: 500; + --text-caption: 11px; + --text-overline: 10px; + --text-overline-weight: 600; + + /* Code */ + --text-code-inline: 14px; + --text-code-block: 13px; + --text-code-lh: 1.6; + + /* ---- SPACING SCALE (8px base grid) ---- */ + --spacing-xs: 4px; + --spacing-sm: 8px; + --spacing-md: 16px; + --spacing-lg: 24px; + --spacing-xl: 32px; + --spacing-2xl: 48px; + --spacing-3xl: 64px; + --spacing-4xl: 80px; + --spacing-5xl: 96px; + + /* ---- BUTTON PADDING (unified per Design Director) ---- */ + --btn-padding-y: var(--spacing-md); + --btn-padding-x: var(--spacing-xl); + + /* ---- LIGHT MODE COLOR PALETTE ---- */ + /* Brand Colors */ + --color-brand-primary: #0066CC; + --color-status-success: #059669; + --color-status-warning: #F59E0B; + --color-status-error: #DC2626; + + /* Note: Secondary accent (#7C3AED) removed per Design Director */ + /* (Option A: Simplify to primary + status colors) */ + + /* Text Colors */ + --color-text-primary: #111827; + --color-text-secondary: #6B7280; + --color-text-tertiary: #9CA3AF; + + /* Border Colors */ + --color-border-default: #E5E7EB; + --color-border-subtle: #F3F4F6; + + /* Background Colors */ + --color-bg-primary: #FFFFFF; + --color-bg-secondary: #F9FAFB; + --color-bg-tertiary: #F3F4F6; + + /* Component-Specific Colors */ + --color-input-focus: #0066CC; + --color-link-hover: #0052A3; + --color-badge-bg: #DBEAFE; + --color-badge-text: #0066CC; + --color-code-bg: #F3F4F6; + --color-code-text: #111827; + + /* ---- SHADOWS & ELEVATION ---- */ + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1); + --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); + --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15); + + /* ---- BORDERS & RADIUS ---- */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + + /* ---- TRANSITIONS ---- */ + --transition-fast: 150ms ease-out; + --transition-normal: 200ms ease-out; + --transition-slow: 300ms ease-in-out; + + /* ---- FOCUS RING (per Design Director fix: 15% opacity) ---- */ + --focus-color: #0066CC; + --focus-width: 2px; + --focus-offset: 2px; + --focus-shadow: 0 0 0 4px rgba(0, 102, 204, 0.15); + + /* ---- CONTAINER WIDTHS ---- */ + --container-sm: 640px; + --container-md: 768px; + --container-lg: 900px; + --container-xl: 1024px; + --container-2xl: 1280px; + + /* ---- Z-INDEX SCALE ---- */ + --z-dropdown: 10; + --z-sticky: 20; + --z-fixed: 30; + --z-modal-backdrop: 40; + --z-modal: 50; +} + +/* ============================================================================ + 3. TYPOGRAPHY & FONT LOADING + ============================================================================ */ + +/* Load Inter from Google Fonts */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); + +/* Base typography */ +body { + font-family: var(--font-sans); + font-size: var(--text-body-md); + line-height: 1.6; + color: var(--color-text-primary); + background-color: var(--color-bg-primary); +} + +/* Headings */ +h1 { + font-size: var(--text-h1); + font-weight: var(--text-h1-weight); + line-height: var(--text-h1-lh); + letter-spacing: var(--text-h1-ls); + color: var(--color-text-primary); + margin-bottom: var(--spacing-md); +} + +h2 { + font-size: var(--text-h2); + font-weight: var(--text-h2-weight); + line-height: var(--text-h2-lh); + letter-spacing: var(--text-h2-ls); + color: var(--color-text-primary); + margin-bottom: var(--spacing-md); + margin-top: var(--spacing-lg); +} + +h3 { + font-size: var(--text-h3); + font-weight: var(--text-h3-weight); + line-height: var(--text-h3-lh); + letter-spacing: var(--text-h3-ls); + color: var(--color-text-primary); + margin-bottom: var(--spacing-sm); + margin-top: var(--spacing-lg); +} + +h4 { + font-size: var(--text-h4); + font-weight: var(--text-h4-weight); + line-height: var(--text-h4-lh); + color: var(--color-text-primary); + margin-bottom: var(--spacing-sm); + margin-top: var(--spacing-md); +} + +h5 { + font-size: var(--text-h5); + font-weight: var(--text-h5-weight); + line-height: var(--text-h5-lh); + color: var(--color-text-primary); + margin-bottom: var(--spacing-sm); +} + +h6 { + font-size: var(--text-h6); + font-weight: var(--text-h6-weight); + line-height: var(--text-h6-lh); + color: var(--color-text-primary); + margin-bottom: var(--spacing-sm); +} + +/* Paragraph */ +p { + font-size: var(--text-body-md); + line-height: 1.6; + color: var(--color-text-primary); + margin-bottom: var(--spacing-md); +} + +/* Small text */ +small, .text-small { + font-size: var(--text-body-sm); + color: var(--color-text-secondary); +} + +/* Code */ +code { + font-family: var(--font-mono); + font-size: var(--text-code-inline); + background-color: var(--color-code-bg); + color: var(--color-code-text); + padding: 2px 6px; + border-radius: var(--radius-sm); +} + +pre { + font-family: var(--font-mono); + font-size: var(--text-code-block); + line-height: var(--text-code-lh); + background-color: var(--color-code-bg); + color: var(--color-code-text); + padding: var(--spacing-md); + border-radius: var(--radius-md); + overflow-x: auto; + margin-bottom: var(--spacing-md); +} + +pre code { + background: none; + padding: 0; + border-radius: 0; +} + +/* ============================================================================ + 4. GLOBAL STYLES & LAYOUT + ============================================================================ */ + +html { + scroll-behavior: smooth; + overflow-x: hidden; +} + +body { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +/* Skip Link (accessibility) */ +.skip-link { + position: absolute; + left: -9999px; + z-index: var(--z-modal); + padding: var(--spacing-md); + background: var(--color-brand-primary); + color: white; + text-decoration: none; + border-radius: var(--radius-sm); +} + +.skip-link:focus { + left: var(--spacing-md); + top: var(--spacing-md); +} + +/* Main content area */ +#main { + flex: 1; + width: 100%; +} + +/* Container for page content */ +.ps-container { + max-width: var(--container-lg); + margin: 0 auto; + padding: 0 var(--spacing-lg); + width: 100%; +} + +.ps-container-wide { + max-width: var(--container-2xl); + margin: 0 auto; + padding: 0 var(--spacing-lg); + width: 100%; +} + +/* ============================================================================ + 5. LINK STYLING (Scope: body content vs navigation) + ============================================================================ */ + +/* Body content links: underlined */ +.site-content a, +.post-content a, +article a, +.page-content a { + color: var(--color-brand-primary); + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 3px; + transition: color var(--transition-normal); +} + +.site-content a:hover, +.post-content a:hover, +article a:hover, +.page-content a:hover { + color: var(--color-link-hover); +} + +.site-content a:focus, +.post-content a:focus, +article a:focus, +.page-content a:focus { + outline: var(--focus-width) solid var(--focus-color); + outline-offset: var(--focus-offset); +} + +/* Footer links: underlined */ +.site-footer a { + color: var(--color-brand-primary); + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 3px; + transition: color var(--transition-normal); +} + +.site-footer a:hover { + color: var(--color-link-hover); +} + +/* Navigation links: NO underline (context is clear) */ +nav a { + text-decoration: none; +} + +/* ============================================================================ + 6. COMPONENTS + ============================================================================ */ + +/* ---- BUTTONS ---- */ + +.ps-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + padding: var(--btn-padding-y) var(--btn-padding-x); + border: none; + border-radius: var(--radius-md); + font-family: var(--font-sans); + font-size: var(--text-body-md); + font-weight: 500; + cursor: pointer; + transition: all var(--transition-normal); + text-decoration: none; + white-space: nowrap; + user-select: none; +} + +.ps-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.ps-btn:focus { + outline: none; + box-shadow: var(--focus-shadow); +} + +/* Primary Button */ +.ps-btn-primary { + background-color: var(--color-brand-primary); + color: white; +} + +.ps-btn-primary:hover { + background-color: var(--color-link-hover); + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(0, 102, 204, 0.2); +} + +.ps-btn-primary:active { + transform: translateY(0); +} + +/* Secondary Button */ +.ps-btn-secondary { + background-color: var(--color-bg-tertiary); + color: var(--color-text-primary); + border: 1px solid var(--color-border-default); +} + +.ps-btn-secondary:hover { + background-color: var(--color-bg-secondary); + border-color: var(--color-brand-primary); +} + +/* Tertiary Button */ +.ps-btn-tertiary { + background-color: transparent; + color: var(--color-brand-primary); + border: 1px solid var(--color-brand-primary); +} + +.ps-btn-tertiary:hover { + background-color: var(--color-brand-primary); + color: white; +} + +/* Button Sizes */ +.ps-btn-sm { + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--text-body-sm); +} + +.ps-btn-lg { + padding: var(--spacing-lg) var(--spacing-2xl); + font-size: var(--text-body-lg); +} + +.ps-btn-full { + width: 100%; +} + +/* ---- CARDS ---- */ + +.ps-card { + background-color: var(--color-bg-primary); + border: 1px solid var(--color-border-default); + border-radius: var(--radius-lg); + padding: var(--spacing-lg); + transition: all var(--transition-normal); +} + +.ps-card:hover { + border-color: var(--color-brand-primary); + box-shadow: 0 4px 12px rgba(0, 102, 204, 0.1); +} + +.ps-card-header { + margin-bottom: var(--spacing-md); +} + +.ps-card-title { + font-size: var(--text-h5); + font-weight: 600; + color: var(--color-text-primary); + margin-bottom: var(--spacing-sm); +} + +.ps-card-meta { + font-size: var(--text-caption); + color: var(--color-text-secondary); +} + +.ps-card-content { + font-size: var(--text-body-md); + line-height: 1.6; + color: var(--color-text-primary); +} + +/* ---- BADGES & TAGS ---- */ + +.ps-badge { + display: inline-block; + padding: 4px 8px; + border-radius: var(--radius-md); + font-size: var(--text-label); + font-weight: var(--text-label-weight); + background-color: var(--color-badge-bg); + color: var(--color-badge-text); + white-space: nowrap; +} + +.ps-badge-success { + background-color: #D1FAE5; + color: var(--color-status-success); +} + +.ps-badge-warning { + background-color: #FEF3C7; + color: var(--color-status-warning); +} + +.ps-badge-error { + background-color: #FEE2E2; + color: var(--color-status-error); +} + +.ps-tag { + display: inline-flex; + align-items: center; + gap: var(--spacing-xs); + padding: 4px 8px; + border-radius: var(--radius-md); + font-size: var(--text-label); + background-color: var(--color-bg-tertiary); + color: var(--color-text-primary); + cursor: pointer; + transition: all var(--transition-normal); +} + +.ps-tag:hover { + background-color: var(--color-border-default); +} + +.ps-tag-close { + width: 16px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-weight: 600; +} + +/* ---- FORMS ---- */ + +input[type="text"], +input[type="email"], +input[type="password"], +input[type="search"], +input[type="number"], +input[type="url"], +textarea, +select { + width: 100%; + padding: var(--spacing-md); + border: 1px solid var(--color-border-default); + border-radius: var(--radius-md); + font-family: var(--font-sans); + font-size: var(--text-body-md); + background-color: var(--color-bg-primary); + color: var(--color-text-primary); + transition: all var(--transition-normal); +} + +input[type="text"]:focus, +input[type="email"]:focus, +input[type="password"]:focus, +input[type="search"]:focus, +input[type="number"]:focus, +input[type="url"]:focus, +textarea:focus, +select:focus { + outline: none; + border-color: var(--color-brand-primary); + box-shadow: var(--focus-shadow); + background-color: var(--color-bg-secondary); +} + +/* Form labels */ +label { + display: block; + margin-bottom: var(--spacing-sm); + font-size: var(--text-label); + font-weight: var(--text-label-weight); + color: var(--color-text-primary); +} + +/* Form groups */ +.ps-form-group { + margin-bottom: var(--spacing-lg); +} + +/* Form error state (per Design Director) */ +input.ps-error, +textarea.ps-error, +select.ps-error { + border-color: var(--color-status-error); + background-color: rgba(220, 38, 38, 0.02); +} + +.ps-form-error { + color: var(--color-status-error); + font-size: var(--text-caption); + margin-top: 4px; + font-weight: var(--text-label-weight); +} + +/* Checkboxes & Radios */ +input[type="checkbox"], +input[type="radio"] { + width: 18px; + height: 18px; + margin: 0; + margin-right: var(--spacing-sm); + cursor: pointer; + accent-color: var(--color-brand-primary); +} + +/* ---- ALERTS & CALLOUTS ---- */ + +.ps-alert { + padding: var(--spacing-lg); + border-radius: var(--radius-md); + border-left: 4px solid; + margin-bottom: var(--spacing-md); +} + +.ps-alert-info { + background-color: #DBEAFE; + border-color: var(--color-brand-primary); + color: #0652CD; +} + +.ps-alert-success { + background-color: #D1FAE5; + border-color: var(--color-status-success); + color: #065F46; +} + +.ps-alert-warning { + background-color: #FEF3C7; + border-color: var(--color-status-warning); + color: #78350F; +} + +.ps-alert-error { + background-color: #FEE2E2; + border-color: var(--color-status-error); + color: #7F1D1D; +} + +/* ---- SEARCH FORM ---- */ + +.ps-search-form { + position: relative; + width: 100%; +} + +.ps-search-input { + width: 100%; + padding: var(--spacing-md) var(--spacing-md) var(--spacing-md) var(--spacing-lg); + border: 1px solid var(--color-border-default); + border-radius: var(--radius-lg); + font-size: var(--text-body-md); +} + +.ps-search-input:focus { + outline: none; + border-color: var(--color-brand-primary); + box-shadow: var(--focus-shadow); +} + +.ps-search-icon { + position: absolute; + right: var(--spacing-md); + top: 50%; + transform: translateY(-50%); + color: var(--color-text-secondary); + pointer-events: none; +} + +/* ---- PAGINATION ---- */ + +.ps-pagination { + display: flex; + gap: var(--spacing-sm); + align-items: center; + justify-content: center; + margin: var(--spacing-2xl) 0; + flex-wrap: wrap; +} + +.ps-pagination a, +.ps-pagination span { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 40px; + height: 40px; + padding: 0 var(--spacing-sm); + border: 1px solid var(--color-border-default); + border-radius: var(--radius-md); + text-decoration: none; + color: var(--color-text-primary); + transition: all var(--transition-normal); +} + +.ps-pagination a:hover { + border-color: var(--color-brand-primary); + background-color: var(--color-brand-primary); + color: white; +} + +.ps-pagination .current { + background-color: var(--color-brand-primary); + border-color: var(--color-brand-primary); + color: white; +} + +/* ============================================================================ + 7. REGIONS (Header, Footer, Main) + ============================================================================ */ + +/* ---- HEADER ---- */ + +.site-header { + background-color: var(--color-bg-primary); + border-bottom: 1px solid var(--color-border-subtle); + padding: var(--spacing-lg) var(--spacing-xl); + position: sticky; + top: 0; + z-index: var(--z-sticky); + box-shadow: var(--shadow-sm); +} + +/* Account for WP admin bar when logged in */ +.admin-bar .site-header { + top: 32px; +} + +@media screen and (max-width: 782px) { + .admin-bar .site-header { + top: 46px; + } +} + +.site-header-wrapper { + max-width: var(--container-2xl); + margin: 0 auto; + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--spacing-lg); +} + +/* Logo */ +.site-logo { + flex: 0 0 auto; + font-size: 24px; + font-weight: 700; + color: var(--color-brand-primary); + text-decoration: none; + line-height: 1; + transition: color var(--transition-normal); +} + +.site-logo:hover { + color: var(--color-link-hover); +} + +.site-logo img { + height: 32px; + width: auto; +} + +/* Primary Navigation */ +.primary-navigation { + display: flex; + align-items: center; + flex: 1; + margin-left: var(--spacing-lg); + margin-right: auto; +} + +.primary-navigation ul { + display: flex; + gap: var(--spacing-xl); + align-items: center; + list-style: none; + margin: 0; + padding: 0; +} + +.primary-navigation li { + display: flex; + align-items: center; +} + +.primary-navigation a { + font-size: var(--text-body-md); + font-weight: 500; + color: var(--color-text-primary); + text-decoration: none; + position: relative; + transition: color var(--transition-normal); +} + +.primary-navigation a:hover { + color: var(--color-brand-primary); +} + +.primary-navigation a::after { + content: ''; + position: absolute; + bottom: -2px; + left: 0; + right: 0; + height: 2px; + background: var(--color-brand-primary); + transform: scaleX(0); + transform-origin: right; + transition: transform var(--transition-normal); +} + +.primary-navigation a:hover::after, +.primary-navigation a.active::after { + transform: scaleX(1); + transform-origin: left; +} + +/* Header Icons */ +.header-icons { + display: flex; + align-items: center; + gap: var(--spacing-md); +} + +.header-icon-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + border: none; + background: none; + color: var(--color-text-primary); + cursor: pointer; + transition: color var(--transition-normal); + padding: 0; +} + +.header-icon-btn:hover { + color: var(--color-brand-primary); +} + +.header-icon-btn:focus { + outline: none; + box-shadow: var(--focus-shadow); + border-radius: var(--radius-md); +} + +/* Hamburger Menu */ +.menu-toggle { + display: none; + width: 40px; + height: 40px; + border: none; + background: none; + cursor: pointer; + padding: 0; + color: var(--color-text-primary); +} + +/* Mobile Navigation */ +.nav-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.3); + opacity: 0; + pointer-events: none; + z-index: var(--z-modal-backdrop); + transition: opacity var(--transition-slow); +} + +.nav-overlay.active { + opacity: 1; + pointer-events: auto; +} + +/* ---- FOOTER ---- */ + +.site-footer { + background-color: var(--color-bg-secondary); + border-top: 1px solid var(--color-border-subtle); + padding: var(--spacing-3xl) var(--spacing-lg); + margin-top: auto; +} + +.footer-wrapper { + max-width: var(--container-2xl); + margin: 0 auto; +} + +.footer-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--spacing-2xl); + margin-bottom: var(--spacing-3xl); +} + +.footer-section h3 { + font-size: var(--text-h5); + margin-bottom: var(--spacing-lg); +} + +.footer-section ul { + list-style: none; + display: flex; + flex-direction: column; + gap: var(--spacing-md); +} + +.footer-section a { + color: var(--color-brand-primary); + text-decoration: underline; + transition: color var(--transition-normal); +} + +.footer-section a:hover { + color: var(--color-link-hover); +} + +.footer-newsletter { + background-color: var(--color-bg-tertiary); + padding: var(--spacing-2xl); + border-radius: var(--radius-lg); + margin-bottom: var(--spacing-3xl); +} + +.footer-newsletter h3 { + margin-top: 0; +} + +.newsletter-form { + display: flex; + gap: var(--spacing-sm); + margin-top: var(--spacing-lg); +} + +.newsletter-form input { + flex: 1; + min-width: 200px; +} + +.newsletter-form button { + flex: 0 0 auto; +} + +.footer-bottom { + border-top: 1px solid var(--color-border-default); + padding-top: var(--spacing-2xl); + text-align: center; + color: var(--color-text-secondary); + font-size: var(--text-body-sm); +} + +/* ============================================================================ + 8. PAGES + ============================================================================ */ + +/* ---- HOME PAGE / HERO ---- */ + +.hero-section { + background: linear-gradient(135deg, var(--color-bg-primary) 0%, var(--color-bg-secondary) 100%); + padding: var(--spacing-4xl) var(--spacing-xl); + text-align: center; +} + +.hero-content { + max-width: var(--container-lg); + margin: 0 auto; +} + +.hero-title { + font-size: var(--text-h1); + font-weight: 700; + margin-bottom: var(--spacing-md); + color: var(--color-text-primary); +} + +.hero-subtitle { + font-size: var(--text-body-lg); + color: var(--color-text-secondary); + margin-bottom: var(--spacing-2xl); + max-width: 600px; + margin-left: auto; + margin-right: auto; +} + +.hero-search { + margin-bottom: var(--spacing-2xl); +} + +/* Legacy theme search form (fallback when PSA plugin is not active) */ +.hero-search .ps-search-form { + max-width: 500px; + margin: 0 auto; +} + +.hero-search .ps-search-input { + width: 100%; + padding-right: 48px; + background-color: var(--color-bg-secondary); + color: var(--color-text-primary); +} + +/* ---- PEPTIDE SEARCH AI PLUGIN INTEGRATION ---- */ + +/* Hero search — constrain the PSA form to match hero layout */ +.hero-search .psa-search-wrap { + max-width: 560px; + margin: 0 auto; +} + +.hero-search .psa-search-input { + background-color: var(--color-bg-secondary); + color: var(--color-text-primary); + border: 1px solid var(--color-border-default); + border-radius: var(--radius-lg); + font-size: var(--text-body-md); + padding: var(--spacing-md) var(--spacing-lg); +} + +.hero-search .psa-search-input::placeholder { + color: var(--color-text-tertiary); +} + +.hero-search .psa-search-input:focus { + outline: none; + border-color: var(--color-brand-primary); + box-shadow: var(--focus-shadow); +} + +.hero-search .psa-search-btn { + background-color: var(--color-brand-primary); + color: white; + border: none; + border-radius: 0 var(--radius-lg) var(--radius-lg) 0; + cursor: pointer; + transition: background-color var(--transition-normal); +} + +.hero-search .psa-search-btn:hover { + background-color: var(--color-brand-hover); +} + +.hero-search .psa-search-results { + text-align: left; + max-height: 400px; + overflow-y: auto; + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + background-color: var(--color-bg-primary); + border: 1px solid var(--color-border-default); +} + +/* Search overlay — full-screen overlay triggered from header search icon */ +.search-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(4px); + z-index: var(--z-modal, 1000); + display: flex; + align-items: flex-start; + justify-content: center; + padding-top: 120px; + opacity: 0; + visibility: hidden; + transition: opacity var(--transition-normal), visibility var(--transition-normal); +} + +.search-overlay.active { + opacity: 1; + visibility: visible; +} + +.search-overlay-inner { + background-color: var(--color-bg-primary); + border-radius: var(--radius-xl); + padding: var(--spacing-xl); + width: 90%; + max-width: 600px; + position: relative; + box-shadow: var(--shadow-xl); + transform: translateY(-20px); + transition: transform var(--transition-normal); +} + +.search-overlay.active .search-overlay-inner { + transform: translateY(0); +} + +.search-overlay-close { + position: absolute; + top: var(--spacing-md); + right: var(--spacing-md); + background: none; + border: none; + color: var(--color-text-secondary); + cursor: pointer; + padding: var(--spacing-xs); + border-radius: var(--radius-md); + transition: color var(--transition-normal), background-color var(--transition-normal); + z-index: 1; +} + +.search-overlay-close:hover { + color: var(--color-text-primary); + background-color: var(--color-bg-secondary); +} + +.search-overlay-content { + padding-top: var(--spacing-sm); +} + +/* PSA plugin styling inside the overlay */ +.search-overlay .psa-search-input { + background-color: var(--color-bg-secondary); + color: var(--color-text-primary); + border: 1px solid var(--color-border-default); + border-radius: var(--radius-lg); + font-size: var(--text-body-md); + padding: var(--spacing-md) var(--spacing-lg); +} + +.search-overlay .psa-search-input::placeholder { + color: var(--color-text-tertiary); +} + +.search-overlay .psa-search-input:focus { + outline: none; + border-color: var(--color-brand-primary); + box-shadow: var(--focus-shadow); +} + +.search-overlay .psa-search-btn { + background-color: var(--color-brand-primary); + color: white; + border: none; + border-radius: 0 var(--radius-lg) var(--radius-lg) 0; + cursor: pointer; + transition: background-color var(--transition-normal); +} + +.search-overlay .psa-search-btn:hover { + background-color: var(--color-brand-hover); +} + +.search-overlay .psa-search-results { + max-height: 350px; + overflow-y: auto; + border-radius: var(--radius-lg); + margin-top: var(--spacing-md); +} + +.search-overlay .psa-checking, +.search-overlay .psa-pending, +.search-overlay .psa-invalid, +.search-overlay .psa-error { + margin-top: var(--spacing-md); + border-radius: var(--radius-lg); +} + +/* ---- 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 + which loads after the theme. */ +body .pn-article-excerpt, +body p.pn-article-excerpt { + -webkit-line-clamp: unset; + -webkit-box-orient: unset; + display: block; + overflow: visible; + font-size: var(--text-body-md); + line-height: 1.6; +} + +/* Tighten article card title for density */ +body .pn-article-title { + font-size: var(--text-h4); + line-height: 1.3; +} + +.hero-ctas { + display: flex; + gap: var(--spacing-md); + justify-content: center; + flex-wrap: wrap; +} + +.hero-ctas .ps-btn { + padding: var(--btn-padding-y) var(--btn-padding-x); +} + +/* News Feed Area */ +.news-feed-section { + padding: var(--spacing-3xl) var(--spacing-lg); + background-color: var(--color-bg-primary); +} + +.news-feed-header { + max-width: var(--container-lg); + margin: 0 auto var(--spacing-2xl); + text-align: center; +} + +.news-feed-title { + font-size: var(--text-h2); + margin-bottom: var(--spacing-md); +} + +.news-feed-description { + color: var(--color-text-secondary); + font-size: var(--text-body-md); +} + +/* ---- ARCHIVE PAGE ---- */ + +.archive-header { + padding: var(--spacing-2xl) var(--spacing-lg) var(--spacing-3xl); + background-color: var(--color-bg-secondary); + border-bottom: 1px solid var(--color-border-subtle); +} + +.archive-title { + max-width: var(--container-lg); + margin: 0 auto; + font-size: var(--text-h2); + color: var(--color-text-primary); +} + +.archive-content { + padding: var(--spacing-3xl) var(--spacing-lg); +} + +.archive-filters { + max-width: var(--container-lg); + margin: 0 auto var(--spacing-2xl); + display: flex; + gap: var(--spacing-md); + flex-wrap: wrap; + align-items: center; +} + +.archive-search { + flex: 1; + min-width: 200px; +} + +.archive-grid { + max-width: var(--container-lg); + margin: 0 auto; + display: grid; + grid-template-columns: 1fr; + gap: var(--spacing-2xl); +} + +.peptides-grid { + max-width: var(--container-2xl); + margin: 0 auto; + display: grid; + grid-template-columns: 1fr; + gap: var(--spacing-2xl); + padding: var(--spacing-3xl) var(--spacing-lg); +} + +/* Peptide Card */ +.peptide-card { + background-color: var(--color-bg-secondary); + border: 1px solid var(--color-border-subtle); + border-radius: var(--radius-lg); + padding: var(--spacing-xl); + display: flex; + flex-direction: column; + transition: transform var(--transition-normal), box-shadow var(--transition-normal); +} + +.peptide-card:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +.peptide-card__header { + margin-bottom: var(--spacing-md); +} + +.peptide-card__title { + font-size: var(--text-h4); + font-weight: 700; + line-height: 1.3; + margin: 0 0 var(--spacing-sm) 0; +} + +.peptide-card__title a { + color: var(--color-brand-primary); + text-decoration: none; + transition: color var(--transition-fast); +} + +.peptide-card__title a:hover { + color: var(--color-link-hover); +} + +.peptide-card__meta { + display: flex; + gap: var(--spacing-xs); + flex-wrap: wrap; +} + +.peptide-card__badge { + display: inline-block; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + padding: 2px 8px; + border-radius: var(--radius-full); + background-color: var(--color-brand-primary); + color: #ffffff; +} + +.peptide-card__excerpt { + font-size: var(--text-body-md); + line-height: 1.65; + color: var(--color-text-secondary); + margin-bottom: var(--spacing-lg); + flex: 1; + overflow: hidden; +} + +.peptide-card__footer { + margin-top: auto; + padding-top: var(--spacing-md); + border-top: 1px solid var(--color-border-subtle); +} + +.peptide-card__link { + display: inline-flex; + align-items: center; + gap: var(--spacing-xs); + font-size: var(--text-body-sm); + font-weight: 600; + color: var(--color-brand-primary); + text-decoration: none; + transition: gap var(--transition-fast), color var(--transition-fast); +} + +.peptide-card__link:hover { + color: var(--color-link-hover); + gap: var(--spacing-sm); +} + +.peptide-card__link svg { + transition: transform var(--transition-fast); +} + +.peptide-card__link:hover svg { + transform: translateX(2px); +} + +.archive-empty { + text-align: center; + padding: var(--spacing-4xl) var(--spacing-lg); +} + +.archive-empty h2 { + margin-top: 0; +} + +.archive-empty p { + color: var(--color-text-secondary); + margin-bottom: var(--spacing-2xl); +} + +/* ---- SINGLE PAGE / PEPTIDE ---- */ + +.page-header { + padding: var(--spacing-2xl) var(--spacing-lg); + background-color: var(--color-bg-secondary); + border-bottom: 1px solid var(--color-border-subtle); +} + +.page-title { + max-width: var(--container-lg); + margin: 0 auto; + font-size: var(--text-h2); +} + +.page-content { + max-width: var(--container-lg); + margin: 0 auto; + padding: var(--spacing-3xl) var(--spacing-lg); +} + +.page-content h2 { + font-size: var(--text-h3); + margin-top: var(--spacing-2xl); + margin-bottom: var(--spacing-md); +} + +.page-content h3 { + font-size: var(--text-h4); + margin-top: var(--spacing-xl); + margin-bottom: var(--spacing-md); +} + +.page-content ul, +.page-content ol { + margin-left: var(--spacing-lg); + margin-bottom: var(--spacing-md); +} + +.page-content li { + 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; +} + +/* ---- 404 PAGE ---- */ + +.error-404 { + text-align: center; + padding: var(--spacing-4xl) var(--spacing-lg); +} + +.error-404 h1 { + font-size: var(--text-h1); + margin-bottom: var(--spacing-lg); +} + +.error-404 p { + color: var(--color-text-secondary); + margin-bottom: var(--spacing-2xl); + font-size: var(--text-body-md); +} + +/* ============================================================================ + 9. ANIMATIONS & TRANSITIONS + ============================================================================ */ + +/* Fade in animation */ +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.fade-in { + animation: fadeIn var(--transition-slow) ease-out; +} + +/* Slide in from left */ +@keyframes slideInLeft { + from { + transform: translateX(-100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +.slide-in-left { + animation: slideInLeft var(--transition-slow) ease-out; +} + +/* Skeleton loading animation */ +@keyframes shimmer { + 0% { + background-position: -1000px 0; + } + 100% { + background-position: 1000px 0; + } +} + +.ps-skeleton { + background: linear-gradient( + 90deg, + var(--color-bg-tertiary) 25%, + var(--color-border-default) 50%, + var(--color-bg-tertiary) 75% + ); + background-size: 1000px 100%; + animation: shimmer 1.5s infinite; + border-radius: var(--radius-md); +} + +/* ============================================================================ + 10. ACCESSIBILITY + ============================================================================ */ + +/* Focus visible style (keyboard focus) */ +*:focus-visible { + outline: var(--focus-width) solid var(--focus-color); + outline-offset: var(--focus-offset); +} + +/* Skip to main content link */ +.skip-to-main { + position: absolute; + top: -40px; + left: 0; + background: var(--color-brand-primary); + color: white; + padding: var(--spacing-md); + text-decoration: none; + z-index: var(--z-modal); +} + +.skip-to-main:focus { + top: 0; +} + +/* Visually hidden but accessible to screen readers */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +/* Reduced motion preferences */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} + +/* ============================================================================ + 11. DARK MODE + ============================================================================ + + Precedence (highest to lowest): + 1. html[data-theme="light"] or html[data-theme="dark"] (explicit user choice) + 2. @media (prefers-color-scheme: dark) (system preference) + 3. Default light mode (above) + + Plugin dark mode coordination: + - Theme broadcasts dark mode changes via data-theme attribute on + - Plugin must watch this attribute and update colors accordingly + - Plugin can also use CSS custom properties which theme controls + + ============================================================================ */ + +@media (prefers-color-scheme: dark) { + :root { + /* Brand Colors */ + --color-brand-primary: #3B82F6; + --color-status-success: #10B981; + --color-status-warning: #F59E0B; + --color-status-error: #EF4444; + + /* Text Colors */ + --color-text-primary: #F9FAFB; + --color-text-secondary: #D1D5DB; + --color-text-tertiary: #9CA3AF; + + /* Border Colors */ + --color-border-default: #374151; + --color-border-subtle: #1F2937; + + /* Background Colors */ + --color-bg-primary: #111827; + --color-bg-secondary: #1F2937; + --color-bg-tertiary: #374151; + + /* Component-Specific Colors */ + --color-input-focus: #3B82F6; + --color-link-hover: #60A5FA; + --color-badge-bg: #0F172A; + --color-badge-text: #60A5FA; + --color-code-bg: #1F2937; + --color-code-text: #F9FAFB; + + /* Focus shadow adjusted for dark mode */ + --focus-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15); + } +} + +/* Allow manual dark mode toggle (explicit override) */ +html[data-theme="dark"] { + --color-brand-primary: #3B82F6; + --color-status-success: #10B981; + --color-status-warning: #F59E0B; + --color-status-error: #EF4444; + --color-text-primary: #F9FAFB; + --color-text-secondary: #D1D5DB; + --color-text-tertiary: #9CA3AF; + --color-border-default: #374151; + --color-border-subtle: #1F2937; + --color-bg-primary: #111827; + --color-bg-secondary: #1F2937; + --color-bg-tertiary: #374151; + --color-input-focus: #3B82F6; + --color-link-hover: #60A5FA; + --color-badge-bg: #0F172A; + --color-badge-text: #60A5FA; + --color-code-bg: #1F2937; + --color-code-text: #F9FAFB; + --focus-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15); +} + +html[data-theme="light"] { + --color-brand-primary: #0066CC; + --color-status-success: #059669; + --color-status-warning: #F59E0B; + --color-status-error: #DC2626; + --color-text-primary: #111827; + --color-text-secondary: #6B7280; + --color-text-tertiary: #9CA3AF; + --color-border-default: #E5E7EB; + --color-border-subtle: #F3F4F6; + --color-bg-primary: #FFFFFF; + --color-bg-secondary: #F9FAFB; + --color-bg-tertiary: #F3F4F6; + --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 4px rgba(0, 102, 204, 0.15); +} + +/* Dark mode alert colors */ +@media (prefers-color-scheme: dark) { + .ps-alert-info { + background-color: #0C2340; + border-color: #3B82F6; + color: #BFDBFE; + } + + .ps-alert-success { + background-color: #064E3B; + border-color: #10B981; + color: #DCFCE7; + } + + .ps-alert-warning { + background-color: #78350F; + border-color: #F59E0B; + color: #FEF3C7; + } + + .ps-alert-error { + background-color: #7F1D1D; + border-color: #EF4444; + color: #FEE2E2; + } + + .footer-newsletter { + background-color: var(--color-bg-secondary); + } +} + +/* ============================================================================ + 12. RESPONSIVE DESIGN (Mobile-first) + ============================================================================ */ + +/* Extra Small (320px - 479px) */ +@media (max-width: 479px) { + .hero-section { + padding: var(--spacing-2xl) var(--spacing-md); + } + + .hero-title { + font-size: 32px; + } + + .hero-ctas { + gap: var(--spacing-sm); + } + + .hero-ctas .ps-btn { + padding: var(--spacing-sm) var(--spacing-lg); + font-size: var(--text-body-sm); + } + + .page-content { + padding: var(--spacing-lg) var(--spacing-md); + } + + .peptides-grid { + padding: var(--spacing-2xl) var(--spacing-md); + } + + .news-feed-section { + padding: var(--spacing-2xl) var(--spacing-md); + } + + h1 { + font-size: 32px; + } + + h2 { + font-size: 24px; + } + + .site-header-wrapper { + gap: var(--spacing-sm); + } + + .primary-navigation { + display: none; + } + + .menu-toggle { + display: flex; + } + + .header-icons { + gap: var(--spacing-sm); + } + + .newsletter-form { + flex-direction: column; + } + + .newsletter-form button { + width: 100%; + } + + .footer-grid { + grid-template-columns: 1fr; + gap: var(--spacing-lg); + } +} + +/* Small (480px - 767px) */ +@media (min-width: 480px) { + .site-header { + padding: var(--spacing-lg) var(--spacing-lg); + } +} + +/* Medium (768px - 1023px) */ +@media (min-width: 768px) { + .menu-toggle { + display: none; + } + + .primary-navigation { + display: flex !important; + position: static; + width: auto; + height: auto; + flex-direction: row; + background: none; + padding: 0; + transition: none; + } + + .nav-overlay { + display: none; + } + + .peptides-grid { + grid-template-columns: repeat(2, 1fr); + } + + .archive-grid { + grid-template-columns: repeat(2, 1fr); + } + + .hero-title { + font-size: 40px; + } + + .newsletter-form { + flex-direction: row; + } + + .newsletter-form button { + width: auto; + } +} + +/* Large (1024px - 1439px) */ +@media (min-width: 1024px) { + .peptides-grid { + grid-template-columns: repeat(3, 1fr); + } + + .archive-grid { + grid-template-columns: repeat(3, 1fr); + } + + .site-header { + padding: var(--spacing-lg) var(--spacing-xl); + } + + .footer-grid { + grid-template-columns: repeat(4, 1fr); + } +} + +/* Extra Large (1440px+) */ +@media (min-width: 1440px) { + .peptides-grid { + grid-template-columns: repeat(4, 1fr); + } + + .site-header { + padding: var(--spacing-lg) var(--spacing-2xl); + } +} + +/* ============================================================================ + 13. UTILITY CLASSES + ============================================================================ */ + +/* 404 Page Utilities */ +.ps-404-search-form { + margin: var(--spacing-2xl) 0; +} + +.ps-404-cta-group { + display: flex; + gap: var(--spacing-md); + justify-content: center; + flex-wrap: wrap; +} + +/* ============================================================================ + END OF STYLESHEET + ============================================================================ */ diff --git a/template-parts/content-none.php b/template-parts/content-none.php new file mode 100644 index 0000000..846cc3f --- /dev/null +++ b/template-parts/content-none.php @@ -0,0 +1,51 @@ + +
diff --git a/template-parts/content-peptide.php b/template-parts/content-peptide.php new file mode 100644 index 0000000..5906de0 --- /dev/null +++ b/template-parts/content-peptide.php @@ -0,0 +1,48 @@ + + +
> +
+

+ +

+ '; + foreach ( array_slice( $categories, 0, 2 ) as $cat ) { + echo '' . esc_html( $cat->name ) . ''; + } + echo ''; + } + ?> +
+ +
+ +
+ + +
diff --git a/template-parts/content.php b/template-parts/content.php new file mode 100644 index 0000000..feccbf2 --- /dev/null +++ b/template-parts/content.php @@ -0,0 +1,96 @@ + +
id="post-"> +
+ ', '' ); + } else { + the_title( '

', '

' ); + } + + if ( 'post' === get_post_type() ) { + ?> + + +
+ +
+ +
+ +
+ "%s"', 'peptide-starter' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + wp_kses_post( get_the_title() ) + ) + ); + + wp_link_pages( + array( + 'before' => '', + ) + ); + ?> +
+ + +
+ '; + echo esc_html__( 'Categories: ', 'peptide-starter' ); + foreach ( $categories as $category ) { + echo '' . esc_html( $category->name ) . ' '; + } + echo ''; + } + + $tags = get_the_tags(); + if ( $tags ) { + echo '
'; + echo esc_html__( 'Tags: ', 'peptide-starter' ); + foreach ( $tags as $tag ) { + echo '' . esc_html( $tag->name ) . ' '; + } + echo '
'; + } + ?> +
+ +
+
+

+
+ +
+ +

+ +

+ Get started here.', 'peptide-starter' ), + array( + 'a' => array( + 'href' => array(), + ), + ) + ), + esc_url( admin_url( 'post-new.php' ) ) + ); + ?> +

+ +

+ +

+ +
+