commit 964206684676ac08413ec0ecf8c73660a5b660ec Author: peptiderepo Date: Wed Apr 8 01:30:16 2026 +0700 Initial commit: peptide-starter theme v1.3.1 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 0000000..e145199 Binary files /dev/null and b/screenshot.png differ 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 @@ + +
+
+

+
+ +
+ +

+ +

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

+ +

+ +

+ +
+
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 '
'; + } + ?> +
+ +