Compare commits

..

No commits in common. "8a4216f497e01c1f71a7903c97f231bfa7323a6a" and "2db3c63e5abc52d33055c5478beb977702edad5f" have entirely different histories.

10 changed files with 1467 additions and 1875 deletions

View file

@ -1,307 +0,0 @@
<?php
/**
* Archive Strain Template
* Strain catalog page grid layout with filters.
*
* @package Weedops
*/
get_header(); ?>
<main id="main" class="weedops-main">
<div class="strain-archive-wrap">
<!-- Page Header -->
<header class="strain-archive-header">
<h1 class="strain-archive-title">Strain Catalog</h1>
<p class="strain-archive-subtitle">Browse our curated database of cannabis strains. Filter by type, potency, and effects.</p>
</header>
<!-- Filter Bar -->
<div class="strain-filters" id="strainFilters">
<button class="strain-filter-btn active" data-filter="all">All Strains</button>
<button class="strain-filter-btn" data-filter="indica">Indica</button>
<button class="strain-filter-btn" data-filter="sativa">Sativa</button>
<button class="strain-filter-btn" data-filter="hybrid">Hybrid</button>
</div>
<!-- Results Count -->
<div class="strain-results-meta">
<?php
global $wp_query;
$total = $wp_query->found_posts;
?>
<span class="strain-results-count">
<?php echo esc_html( $total ); ?> strain<?php echo $total !== 1 ? 's' : ''; ?> found
</span>
</div>
<!-- Strain Grid -->
<?php if ( have_posts() ) : ?>
<div class="strain-grid" id="strainGrid">
<?php while ( have_posts() ) : the_post(); ?>
<?php
$strain_type = get_post_meta( get_the_ID(), '_strain_type', true );
$thc = get_post_meta( get_the_ID(), '_strain_thc', true );
$cbd = get_post_meta( get_the_ID(), '_strain_cbd', true );
$effects_raw = get_post_meta( get_the_ID(), '_strain_effects', true );
$effects = array_filter( array_map( 'trim', explode( ',', $effects_raw ) ) );
?>
<article
id="strain-<?php the_ID(); ?>"
class="strain-card"
data-type="<?php echo esc_attr( $strain_type ); ?>"
>
<a href="<?php the_permalink(); ?>" class="strain-card__link" tabindex="-1" aria-hidden="true">
<div class="strain-card__image">
<?php if ( has_post_thumbnail() ) : ?>
<?php the_post_thumbnail( 'medium', [ 'class' => 'strain-card__img' ] ); ?>
<?php else : ?>
<div class="strain-card__placeholder">
<span class="strain-card__placeholder-icon">🌿</span>
</div>
<?php endif; ?>
<div class="strain-card__badge strain-card__badge--<?php echo esc_attr( $strain_type ); ?>">
<?php echo esc_html( ucfirst( $strain_type ? $strain_type : 'Unknown' ) ); ?>
</div>
</div>
</a>
<div class="strain-card__body">
<h2 class="strain-card__title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h2>
<div class="strain-card__potency">
<?php if ( $thc !== '' ) : ?>
<div class="strain-card__stat strain-card__stat--thc">
<span class="strain-card__stat-label">THC</span>
<span class="strain-card__stat-value"><?php echo esc_html( $thc ); ?>%</span>
</div>
<?php endif; ?>
<?php if ( $cbd !== '' ) : ?>
<div class="strain-card__stat strain-card__stat--cbd">
<span class="strain-card__stat-label">CBD</span>
<span class="strain-card__stat-value"><?php echo esc_html( $cbd ); ?>%</span>
</div>
<?php endif; ?>
</div>
<?php if ( ! empty( $effects ) ) : ?>
<div class="strain-card__effects">
<?php foreach ( array_slice( $effects, 0, 3 ) as $effect ) : ?>
<span class="strain-card__effect-tag"><?php echo esc_html( $effect ); ?></span>
<?php endforeach; ?>
<?php if ( count( $effects ) > 3 ) : ?>
<span class="strain-card__effect-more">+<?php echo count( $effects ) - 3; ?> more</span>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ( get_the_excerpt() ) : ?>
<p class="strain-card__excerpt"><?php echo esc_html( wp_trim_words( get_the_excerpt(), 15, '…' ) ); ?></p>
<?php endif; ?>
<a href="<?php the_permalink(); ?>" class="strain-card__cta">View Strain </a>
</div>
</article>
<?php endwhile; ?>
</div><!-- .strain-grid -->
<!-- Pagination -->
<div class="strain-pagination">
<?php
echo paginate_links( [
'prev_text' => '← Previous',
'next_text' => 'Next →',
'before_page_number' => '<span class="screen-reader-text">Page </span>',
] );
?>
</div>
<?php else : ?>
<div class="strain-no-results">
<span class="strain-no-results__icon">🔍</span>
<h2>No strains found</h2>
<p>Check back soon we're always adding to the catalog.</p>
</div>
<?php endif; ?>
</div><!-- .strain-archive-wrap -->
</main>
<style>
/* ── Strain Archive / Catalog Styles ─────────────────── */
.strain-archive-wrap { max-width: 1200px; margin: 0 auto; padding: 2rem 1.5rem; }
/* Header */
.strain-archive-header { text-align: center; margin-bottom: 2.5rem; }
.strain-archive-title {
font-size: 2.8rem; font-weight: 900; color: #1a3a1a;
margin: 0 0 .5rem;
background: linear-gradient(135deg, #2e7d32, #66bb6a);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
background-clip: text;
}
.strain-archive-subtitle { color: #555; font-size: 1.1rem; margin: 0; }
/* Filter Bar */
.strain-filters {
display: flex; gap: .5rem; justify-content: center;
flex-wrap: wrap; margin-bottom: 1.5rem;
}
.strain-filter-btn {
padding: .5rem 1.4rem; border-radius: 999px;
border: 2px solid #a5d6a7; background: #fff;
color: #2e7d32; font-weight: 600; font-size: .9rem;
cursor: pointer; transition: all .2s;
}
.strain-filter-btn:hover,
.strain-filter-btn.active { background: #2e7d32; color: #fff; border-color: #2e7d32; }
/* Results meta */
.strain-results-meta { text-align: right; font-size: .85rem; color: #777; margin-bottom: 1rem; }
/* Grid */
.strain-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 2.5rem;
}
/* Card */
.strain-card {
background: #fff;
border-radius: 14px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0,0,0,.07);
border: 1px solid #e8f5e9;
transition: transform .2s, box-shadow .2s;
display: flex; flex-direction: column;
}
.strain-card:hover { transform: translateY(-4px); box-shadow: 0 8px 28px rgba(46,125,50,.15); }
/* Card Image */
.strain-card__link { display: block; position: relative; }
.strain-card__img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; }
.strain-card__placeholder {
width: 100%; aspect-ratio: 4/3;
background: linear-gradient(135deg, #1a3a1a 0%, #2d5a2d 100%);
display: flex; align-items: center; justify-content: center;
}
.strain-card__placeholder-icon { font-size: 3rem; }
/* Type Badge on card image */
.strain-card__badge {
position: absolute; top: .8rem; right: .8rem;
padding: .25rem .75rem; border-radius: 999px;
font-size: .7rem; font-weight: 700;
text-transform: uppercase; letter-spacing: .08em;
}
.strain-card__badge--indica { background: #4a148c; color: #e1bee7; }
.strain-card__badge--sativa { background: #e65100; color: #ffe0b2; }
.strain-card__badge--hybrid { background: #1b5e20; color: #c8e6c9; }
/* Card Body */
.strain-card__body { padding: 1.2rem; display: flex; flex-direction: column; flex: 1; }
.strain-card__title { font-size: 1.25rem; font-weight: 800; margin: 0 0 .8rem; }
.strain-card__title a { color: #1a3a1a; text-decoration: none; }
.strain-card__title a:hover { color: #2e7d32; }
/* Potency stats */
.strain-card__potency { display: flex; gap: .8rem; margin-bottom: .8rem; }
.strain-card__stat {
flex: 1; padding: .5rem .7rem; border-radius: 8px;
display: flex; flex-direction: column; align-items: center;
}
.strain-card__stat--thc { background: #e8f5e9; }
.strain-card__stat--cbd { background: #e3f2fd; }
.strain-card__stat-label { font-size: .65rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #666; }
.strain-card__stat-value { font-size: 1.4rem; font-weight: 900; color: #1a3a1a; line-height: 1.1; }
.strain-card__stat--thc .strain-card__stat-value { color: #2e7d32; }
.strain-card__stat--cbd .strain-card__stat-value { color: #0277bd; }
/* Effect tags */
.strain-card__effects { display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: .8rem; }
.strain-card__effect-tag {
background: #f1f8e9; color: #388e3c;
border: 1px solid #c5e1a5;
border-radius: 999px; padding: .15rem .6rem;
font-size: .75rem; font-weight: 500;
}
.strain-card__effect-more { font-size: .75rem; color: #999; padding: .15rem .4rem; }
/* Excerpt */
.strain-card__excerpt { font-size: .85rem; color: #666; line-height: 1.5; margin: 0 0 1rem; flex: 1; }
/* CTA */
.strain-card__cta {
display: inline-block; margin-top: auto;
color: #2e7d32; font-weight: 700; font-size: .9rem;
text-decoration: none; border-top: 1px solid #e8f5e9;
padding-top: .8rem; transition: color .2s;
}
.strain-card__cta:hover { color: #1b5e20; }
/* Pagination */
.strain-pagination { display: flex; justify-content: center; gap: .5rem; flex-wrap: wrap; }
.strain-pagination .page-numbers {
padding: .5rem 1rem; border-radius: 6px;
border: 1px solid #a5d6a7; color: #2e7d32;
text-decoration: none; font-weight: 600; transition: all .2s;
}
.strain-pagination .page-numbers.current,
.strain-pagination .page-numbers:hover { background: #2e7d32; color: #fff; border-color: #2e7d32; }
/* No Results */
.strain-no-results { text-align: center; padding: 4rem 2rem; color: #777; }
.strain-no-results__icon { font-size: 3rem; display: block; margin-bottom: 1rem; }
.strain-no-results h2 { color: #1a3a1a; }
</style>
<script>
// Simple client-side filter — filters visible cards by strain type without a page reload
(function() {
const btns = document.querySelectorAll('.strain-filter-btn');
const cards = document.querySelectorAll('.strain-card');
const meta = document.querySelector('.strain-results-count');
btns.forEach(function(btn) {
btn.addEventListener('click', function() {
btns.forEach(function(b) { b.classList.remove('active'); });
btn.classList.add('active');
const filter = btn.dataset.filter;
let visible = 0;
cards.forEach(function(card) {
if (filter === 'all' || card.dataset.type === filter) {
card.style.display = '';
visible++;
} else {
card.style.display = 'none';
}
});
if (meta) {
meta.textContent = visible + ' strain' + (visible !== 1 ? 's' : '') + ' found';
}
});
});
})();
</script>
<?php get_footer(); ?>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 KiB

View file

@ -1,91 +1,15 @@
</div><!-- .wo-container (opened in header.php) -->
</main><!-- #main-content -->
</main>
<?php // ── Site Footer ───────────────────────────────────────── ?>
<footer class="wo-footer" role="contentinfo">
<div class="wo-container">
<div class="wo-footer__grid">
<?php // Brand column ?>
<div class="wo-footer__brand">
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="wo-logo" rel="home">
<svg width="22" height="22" viewBox="0 0 28 28" fill="none" aria-hidden="true" focusable="false">
<path d="M14 2C8.5 2 4 6.5 4 12c0 3.5 2 6.5 5 8.5L14 26l5-5.5c3-2 5-5 5-8.5C24 6.5 19.5 2 14 2z" fill="#4a9e68"/>
<path d="M14 6c-3.3 0-6 2.7-6 6 0 2 1 3.8 2.5 4.8L14 20l3.5-3.2c1.5-1 2.5-2.8 2.5-4.8 0-3.3-2.7-6-6-6z" fill="#c8a951"/>
</svg>
Weed<span>ops</span>
</a>
<p class="wo-mt-2" style="color:rgba(255,255,255,0.6);font-size:0.85rem;max-width:220px;">
<?php echo esc_html( get_bloginfo( 'description' ) ?: __( 'Cannabis industry product management and compliance platform.', 'weedops' ) ); ?>
</p>
</div>
<?php // Platform column ?>
<div>
<h4><?php esc_html_e( 'Platform', 'weedops' ); ?></h4>
<ul>
<li><a href="<?php echo esc_url( home_url( '/strains' ) ); ?>"><?php esc_html_e( 'Strain Database', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/products' ) ); ?>"><?php esc_html_e( 'Product Catalog', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/dispensaries' ) ); ?>"><?php esc_html_e( 'Dispensaries', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/compliance' ) ); ?>"><?php esc_html_e( 'Compliance', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/inventory' ) ); ?>"><?php esc_html_e( 'Inventory', 'weedops' ); ?></a></li>
</ul>
</div>
<?php // Footer nav widget area or fallback links ?>
<div>
<h4><?php esc_html_e( 'Company', 'weedops' ); ?></h4>
<?php if ( is_active_sidebar( 'footer-col-2' ) ) : ?>
<?php dynamic_sidebar( 'footer-col-2' ); ?>
<?php else : ?>
<ul>
<li><a href="<?php echo esc_url( home_url( '/about' ) ); ?>"><?php esc_html_e( 'About', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/blog' ) ); ?>"><?php esc_html_e( 'Blog', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/contact' ) ); ?>"><?php esc_html_e( 'Contact', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/careers' ) ); ?>"><?php esc_html_e( 'Careers', 'weedops' ); ?></a></li>
</ul>
<?php endif; ?>
</div>
<?php // Legal column ?>
<div>
<h4><?php esc_html_e( 'Legal', 'weedops' ); ?></h4>
<ul>
<li><a href="<?php echo esc_url( home_url( '/privacy-policy' ) ); ?>"><?php esc_html_e( 'Privacy Policy', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/terms' ) ); ?>"><?php esc_html_e( 'Terms of Service', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/age-verification' ) ); ?>"><?php esc_html_e( 'Age Verification', 'weedops' ); ?></a></li>
<li><a href="<?php echo esc_url( home_url( '/compliance-disclosure' ) ); ?>"><?php esc_html_e( 'Compliance Disclosure', 'weedops' ); ?></a></li>
</ul>
</div>
</div><!-- .wo-footer__grid -->
<div class="wo-footer__bottom">
<span>
&copy; <?php echo esc_html( gmdate( 'Y' ) ); ?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" style="color:rgba(255,255,255,0.7);">Weedops</a>.
<?php esc_html_e( 'All rights reserved.', 'weedops' ); ?>
</span>
<span style="color:rgba(255,255,255,0.4);font-size:0.75rem;">
<?php esc_html_e( 'For use in jurisdictions where cannabis is legal. Must be 21+.', 'weedops' ); ?>
</span>
<?php
// Optional: footer nav
wp_nav_menu( [
'theme_location' => 'footer',
'container' => false,
'depth' => 1,
'fallback_cb' => false,
'menu_class' => 'wo-footer__nav',
] );
?>
</div><!-- .wo-footer__bottom -->
</div><!-- .wo-container -->
<footer class="site-footer">
<div class="container">
<div class="footer-content">
<span class="footer-location">WeedOps &middot; Los Angeles, California</span>
<span class="footer-copy">&copy; <?php echo date('Y'); ?> WeedOps</span>
</div>
<p class="footer-disclaimer">This is a confidential investor overview. Not a public offering.</p>
</div>
</footer>
<?php wp_footer(); ?>
</body>
</html>

View file

@ -1,153 +1,341 @@
<?php
/**
* Weedops Front Page Template
*
* Full-width hero with photography-style imagery,
* followed by featured sections.
*
* @package Weedops
* Template Name: Home
* Home page investor-facing landing page
*/
get_header();
$form_result = weedops_get_form_result();
?>
</div><!-- close .wo-container from header -->
</main><!-- close .wo-main from header we'll reopen after hero -->
<?php // ── Hero Section ──────────────────────────────────────── ?>
<section class="wo-hero" role="banner" aria-label="<?php esc_attr_e( 'Welcome to Weedops', 'weedops' ); ?>">
<div class="wo-hero__overlay"></div>
<div class="wo-hero__content">
<span class="wo-hero__eyebrow"><?php esc_html_e( 'Cannabis Intelligence Platform', 'weedops' ); ?></span>
<h1 class="wo-hero__title">
<?php esc_html_e( 'Smarter Product Management for the Cannabis Industry', 'weedops' ); ?>
</h1>
<p class="wo-hero__subtitle">
<?php esc_html_e( 'Compliance tracking, strain databases, and inventory tools built for dispensaries, growers, and brands.', 'weedops' ); ?>
</p>
<div class="wo-hero__actions">
<a href="<?php echo esc_url( home_url( '/strains' ) ); ?>" class="wo-btn wo-btn--primary wo-btn--lg">
<?php esc_html_e( 'Browse Strains', 'weedops' ); ?>
</a>
<a href="<?php echo esc_url( home_url( '/products' ) ); ?>" class="wo-btn wo-btn--ghost wo-btn--lg">
<?php esc_html_e( 'View Products', 'weedops' ); ?>
</a>
<!-- Hero -->
<section class="hero">
<div class="container">
<div class="hero-content">
<p class="section-label">A Confidential Investor Overview</p>
<h1>Your home. Your plants.<br>Our expertise. <span class="green">Your check.</span></h1>
<p class="subhead">California adults can legally grow cannabis at home. Almost none of them do. We built the company that changes that and makes money at every step of the process.</p>
<p class="hero-note">$500,000 Convertible Notes Private Party Round Now Open</p>
<div class="hero-ctas">
<a href="#deck" class="btn btn-primary">Request the Deck</a>
<a href="#opportunity" class="btn btn-secondary">Learn How It Works</a>
</div>
</div>
</div>
</section>
<?php // ── Features Grid ─────────────────────────────────────── ?>
<main class="wo-main" id="main-content" role="main">
<div class="wo-container">
<section class="wo-section wo-mt-3">
<div class="wo-text-center wo-mb-3">
<h2><?php esc_html_e( 'Built for Cannabis Professionals', 'weedops' ); ?></h2>
<p class="wo-text-muted" style="max-width:600px;margin:0.75rem auto 0;">
<?php esc_html_e( 'Everything you need to manage products, stay compliant, and grow your operation.', 'weedops' ); ?>
</p>
<!-- The Opportunity -->
<section class="opportunity" id="opportunity">
<div class="container">
<p class="section-label">The Opportunity</p>
<div class="opportunity-content">
<h2>A category that doesn't exist yet. We're defining it.</h2>
<p>Millions of California adults consume cannabis. A fraction grow it. The gap isn't desire — it's <span class="emphasis">expertise, equipment, and time</span>. WeedOps is the first company to solve all three with a fully managed, fully licensed, recurring service model.</p>
<p>This is not a dispensary. Not a delivery app. Not a brand.</p>
<p class="emphasis" style="color: var(--white);">This is infrastructure.</p>
</div>
</div>
</section>
<div class="wo-grid wo-grid--3">
<div class="wo-card wo-text-center" style="padding:2rem;">
<div class="wo-feature-icon" style="font-size:2.4rem;margin-bottom:1rem;">&#x1F33F;</div>
<h3 style="font-size:1.15rem;margin-bottom:0.5rem;">
<?php esc_html_e( 'Strain Database', 'weedops' ); ?>
</h3>
<p class="wo-text-muted" style="font-size:0.9rem;">
<?php esc_html_e( 'Comprehensive profiles with THC/CBD levels, terpenes, effects, and grow data.', 'weedops' ); ?>
</p>
<!-- The Problem -->
<section id="problem">
<div class="container">
<p class="section-label">The Problem</p>
<h2>Many adults want craft cannabis.<br>Almost none of them grow it.</h2>
<div class="problem-grid">
<div class="problem-card">
<h3>The expertise gap</h3>
<p>A successful home grow requires strain knowledge, lighting science, training techniques, and timing. Most adults never get past seed-to-sprout.</p>
</div>
<div class="wo-card wo-text-center" style="padding:2rem;">
<div class="wo-feature-icon" style="font-size:2.4rem;margin-bottom:1rem;">&#x1F4CB;</div>
<h3 style="font-size:1.15rem;margin-bottom:0.5rem;">
<?php esc_html_e( 'Compliance Tracking', 'weedops' ); ?>
</h3>
<p class="wo-text-muted" style="font-size:0.9rem;">
<?php esc_html_e( 'Lab results, COA management, and regulatory status for every product in your catalog.', 'weedops' ); ?>
</p>
<div class="problem-card">
<h3>The time barrier</h3>
<p>Daily monitoring. Biweekly maintenance. Processing at harvest. A full-time job on top of your actual job.</p>
</div>
<div class="wo-card wo-text-center" style="padding:2rem;">
<div class="wo-feature-icon" style="font-size:2.4rem;margin-bottom:1rem;">&#x1F4E6;</div>
<h3 style="font-size:1.15rem;margin-bottom:0.5rem;">
<?php esc_html_e( 'Inventory Management', 'weedops' ); ?>
</h3>
<p class="wo-text-muted" style="font-size:0.9rem;">
<?php esc_html_e( 'Real-time stock levels, batch tracking, and automated low-stock alerts.', 'weedops' ); ?>
</p>
<div class="problem-card">
<h3>The equipment wall</h3>
<p>A quality grow tent setup costs $800 - $2,000 upfront before you've grown a single gram. Most people quit before they start.</p>
</div>
</div>
</section>
</div>
</section>
<?php // ── Latest Strains ────────────────────────────────────── ?>
<?php
$strains = new WP_Query( [
'post_type' => 'wo_strain',
'posts_per_page' => 6,
'orderby' => 'date',
'order' => 'DESC',
] );
if ( $strains->have_posts() ) :
?>
<section class="wo-section wo-mt-3">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap;gap:0.5rem;">
<h2><?php esc_html_e( 'Latest Strains', 'weedops' ); ?></h2>
<a href="<?php echo esc_url( home_url( '/strains' ) ); ?>" class="wo-btn wo-btn--outline" style="font-size:0.85rem;">
<?php esc_html_e( 'View All &rarr;', 'weedops' ); ?>
</a>
<!-- The Solution -->
<section class="opportunity" id="model">
<div class="container">
<p class="section-label">The Solution</p>
<h2>We bring the entire operation to your home.</h2>
<p class="subhead">WeedOps handles everything equipment, setup, clones, biweekly visits, harvesting, and processing. You provide the space. We provide the rest.</p>
<div class="solution-features">
<div class="solution-feature">
<h3>Full equipment setup</h3>
<p>We bring it. We install it. All of it.</p>
</div>
<div class="solution-feature">
<h3>Expert grow management</h3>
<p>Biweekly site visits.</p>
</div>
<div class="solution-feature">
<h3>Monthly product supply</h3>
<p>Your share, delivered.</p>
</div>
<div class="solution-feature">
<h3>Revenue share check</h3>
<p>Every harvest cycle.</p>
</div>
</div>
</div>
</section>
<div class="wo-grid wo-grid--3">
<?php while ( $strains->have_posts() ) : $strains->the_post(); ?>
<article <?php post_class( 'wo-card' ); ?>>
<?php if ( has_post_thumbnail() ) : ?>
<a href="<?php the_permalink(); ?>" aria-hidden="true" tabindex="-1">
<?php the_post_thumbnail( 'medium', [
'class' => 'wo-card__img',
'loading' => 'lazy',
'style' => 'width:100%;height:180px;object-fit:cover;border-radius:8px;margin-bottom:1rem;',
] ); ?>
</a>
<?php endif; ?>
<!-- How It Works -->
<section id="how-it-works">
<div class="container">
<p class="section-label">How It Works</p>
<h2>Six steps from empty bedroom to monthly check.</h2>
<div class="steps-grid">
<div class="step-card">
<span class="step-number">01</span>
<h3>Register</h3>
<p>Tell us about your space and household. We send a proposal.</p>
</div>
<div class="step-card">
<span class="step-number">02</span>
<h3>Setup Day</h3>
<p>We arrive with all equipment. Full grow tent installed, clones planted.</p>
</div>
<div class="step-card">
<span class="step-number">03</span>
<h3>Biweekly Visits</h3>
<p>Our tech stops by every two weeks maintenance, monitoring, training if desired.</p>
</div>
<div class="step-card">
<span class="step-number">04</span>
<h3>Harvest</h3>
<p>Every ~9 weeks. We take the product for processing. You watch if you want, get an estimate.</p>
</div>
<div class="step-card">
<span class="step-number">05</span>
<h3>Your Supply</h3>
<p>Next week: 30-day supply for every registered adult flower, edible, cart, extract. You choose your format.</p>
</div>
<div class="step-card">
<span class="step-number">06</span>
<h3>Your Check</h3>
<p>Remaining product processed and sold on consignment. Revenue share check every cycle.</p>
</div>
</div>
</div>
</section>
<div class="wo-card__meta" style="margin-bottom:0.5rem;">
<?php
$types = get_the_terms( get_the_ID(), 'wo_strain_type' );
if ( $types && ! is_wp_error( $types ) ) {
foreach ( $types as $t ) {
weedops_strain_badge( $t->slug );
}
}
?>
<!-- What You Get as a WeedOpper -->
<section class="opportunity">
<div class="container">
<p class="section-label">What You Get as a WeedOpper</p>
<h2>You had a hand in growing it. That's the whole point.</h2>
<div class="weedopper-stats">
<div class="stat-card">
<div class="stat-value">$0</div>
<div class="stat-label">Out of Pocket</div>
<p>Refundable $500 deposit is the only ask. Equipment, clones, nutrients all on us.</p>
</div>
<div class="stat-card">
<div class="stat-value">30</div>
<div class="stat-label">Day Supply / Mo</div>
<p>Every registered adult in the home gets their full monthly supply, first.</p>
</div>
<div class="stat-card">
<div class="stat-value" style="font-size: clamp(1.5rem, 3vw, 2rem);">Revenue Share</div>
<div class="stat-label">Per Harvest</div>
<p>Your cut from processed excess, every ~9-week cycle. Passive income.</p>
</div>
</div>
<p class="text-center" style="color: var(--gray);">Optional webcam inside your grow. Video consultations. And a service you can learn to run yourself.</p>
</div>
</section>
<!-- The Campus -->
<section class="opportunity" id="campus">
<div class="container">
<p class="section-label">The WeedOps Campus</p>
<h2>The home service is the foundation. The Superstore is the destination.</h2>
<p class="subhead" style="max-width: 800px; margin-bottom: 48px;">This isn't a boutique. It's a floor. WeedOps Superstore is where serious growers come to outfit an operation flat carts for 50-pound soil runs, shopping carts for accessories and nutrients, a full retail floor with every brand, format, and supply a home grower or commercial operation needs. Think Home Depot. Now think cannabis. Nobody has built it. That's the point.</p>
<div class="campus-grid">
<div class="campus-card">
<h3>Processing</h3>
<p>Glass wall. Watch your product get made. Like a brewery.</p>
</div>
<div class="campus-card">
<h3>Retail Store</h3>
<p>WeedOps product + curated shelf. You know what's in it.</p>
</div>
<div class="campus-card">
<h3>Farmers Market</h3>
<p>Third-party growers. Community. Foot traffic engine.</p>
</div>
<div class="campus-card">
<h3>2nd Floor</h3>
<p>Indoor grow suites for lease. No home required.</p>
</div>
<div class="campus-card">
<h3>Rooftop</h3>
<p>Outdoor grow plots for lease. Seasonal. Instagrammable.</p>
</div>
<div class="campus-card">
<h3>Supply Shop</h3>
<p>All supplies available onsite. Everything a grower needs, where growers already are.</p>
</div>
<div class="campus-card">
<h3>Superstore Floor</h3>
<p>Flat carts. Shopping carts. Bulk supply. Full equipment. The complete grow operation, ready to walk out the door.</p>
</div>
</div>
<p class="campus-tagline">The cannabis superstore. Finally.</p>
</div>
</section>
<!-- Revenue Streams -->
<section>
<div class="container">
<p class="section-label">Revenue Streams</p>
<h2>This is not a single-product cannabis company.</h2>
<div class="streams-grid">
<div class="stream-card">
<span class="stream-tag core">Core</span>
<h3>Service Contracts</h3>
<p>Monthly fee per home grow site. Predictable, recurring, scalable.</p>
</div>
<div class="stream-card">
<span class="stream-tag margin">Margin</span>
<h3>Processing</h3>
<p>Licensed processing of all harvested product.</p>
</div>
<div class="stream-card">
<span class="stream-tag margin">Margin</span>
<h3>Distribution</h3>
<p>Licensed distribution of processed product to retail.</p>
</div>
<div class="stream-card">
<span class="stream-tag campus">Campus</span>
<h3>Campus Retail</h3>
<p>WeedOps-branded product on our own shelf.</p>
</div>
<div class="stream-card">
<span class="stream-tag campus">Campus</span>
<h3>Grow Suite Rental</h3>
<p>Second floor and rooftop leasable grow spaces.</p>
</div>
<div class="stream-card">
<span class="stream-tag campus">Campus</span>
<h3>Supply Sales</h3>
<p>Equipment, nutrients, accessories sold where growers already are.</p>
</div>
</div>
</div>
</section>
<!-- Why Now -->
<section class="opportunity">
<div class="container">
<p class="section-label">Why Now. Why LA. Why Us.</p>
<h2>First mover in distributed home cultivation services.</h2>
<div class="why-grid">
<div class="why-card">
<h3>Greater LA launch</h3>
<p>5M+ adults in the LA metro. Cannabis-normalized culture. Word travels fast in every neighborhood on the westside.</p>
</div>
<div class="why-card">
<h3>Fully licensed</h3>
<p>Every required California license cultivation, processing, distribution. 100% compliant. Taxes paid. Federal/state tension is real and acknowledged; our structure keeps commercial activity entirely within the state-licensed chain.</p>
</div>
<div class="why-card">
<h3>Referral flywheel</h3>
<p>Happy growers share what they grew. That's the whole pitch deck at a dinner party.</p>
</div>
<div class="why-card">
<h3>First mover edge</h3>
<p>Nobody has built this. The managed home grow service category doesn't exist yet. We're defining it.</p>
</div>
</div>
</div>
</section>
<!-- The Ask -->
<section class="ask-section" id="ask">
<div class="container">
<p class="section-label">The Ask</p>
<div class="ask-headline">
<div class="amount">$500,000</div>
<p class="terms">Convertible Notes &middot; Private Party &middot; No VC</p>
<p class="terms-detail">Individual investors only &middot; No institutional money</p>
</div>
<div class="use-of-funds">
<div class="fund-item">
<div class="fund-percent">40%</div>
<h3>Licensing & Legal</h3>
<p>All required CA licenses. Cannabis counsel.</p>
</div>
<div class="fund-item">
<div class="fund-percent">30%</div>
<h3>First Cohort Ops</h3>
<p>Equipment for first 25 sites. Clones. Setup labor.</p>
</div>
<div class="fund-item">
<div class="fund-percent">20%</div>
<h3>Processing Setup</h3>
<p>Licensed facility, equipment, first cycle.</p>
</div>
<div class="fund-item">
<div class="fund-percent">10%</div>
<h3>Technology & Brand</h3>
<p>Customer portal. Ops dashboard. Marketing.</p>
</div>
</div>
</div>
</section>
<!-- Deck Request CTA -->
<section class="cta-section" id="deck">
<div class="container">
<?php if ($form_result === true): ?>
<div class="form-success">
<h3>Request received.</h3>
<p>We'll send the full investor overview to your email shortly.</p>
</div>
<?php else: ?>
<h2>Interested in the round?</h2>
<p class="subhead">Request the full investor overview. This is a confidential offering to individual investors.</p>
<?php if (is_string($form_result)): ?>
<div class="form-error"><?php echo esc_html($form_result); ?></div>
<?php endif; ?>
<form class="deck-form" method="post" action="#deck">
<?php wp_nonce_field('weedops_deck_request'); ?>
<input type="hidden" name="weedops_deck_request" value="1">
<div class="form-row">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name" placeholder="Your name" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" placeholder="you@email.com" required>
</div>
</div>
<h3 style="font-size:1.05rem;margin-bottom:0.4rem;">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<div class="form-group">
<label for="note">Anything you'd like us to know (optional)</label>
<textarea id="note" name="note" rows="3" placeholder="How you heard about us, questions, etc."></textarea>
</div>
<?php $canna = weedops_get_cannabinoid_str( get_the_ID() ); ?>
<?php if ( $canna ) : ?>
<p style="font-size:0.82rem;font-weight:600;color:var(--wo-green-mid);margin-bottom:0.5rem;">
<?php echo esc_html( $canna ); ?>
</p>
<?php endif; ?>
<?php if (WEEDOPS_TURNSTILE_SITE_KEY): ?>
<div class="cf-turnstile mb-24" data-sitekey="<?php echo WEEDOPS_TURNSTILE_SITE_KEY; ?>" data-theme="dark"></div>
<?php endif; ?>
<a href="<?php the_permalink(); ?>" class="wo-btn wo-btn--outline" style="font-size:0.8rem;padding:0.4rem 0.8rem;">
<?php esc_html_e( 'View Details', 'weedops' ); ?>
</a>
</article>
<?php endwhile; ?>
</div>
</section>
<?php
wp_reset_postdata();
endif;
?>
<button type="submit" class="btn btn-primary" style="width: 100%;">Request the Deck</button>
</form>
<?php endif; ?>
</div>
</section>
<?php
get_footer();
<?php get_footer(); ?>

View file

@ -1,192 +1,130 @@
<?php
/**
* Weedops Theme Functions
*
* Cannabis industry platform theme setup, enqueues, custom post types,
* taxonomies, REST API extensions, and helper utilities.
*
* @package Weedops
* @version 1.0.0
* WeedOps Theme Functions
*/
defined( 'ABSPATH' ) || exit;
define( 'WEEDOPS_VERSION', '1.0.0' );
define( 'WEEDOPS_DIR', get_template_directory() );
define( 'WEEDOPS_URI', get_template_directory_uri() );
// ─────────────────────────────────────────────────────────────────────────────
// Theme Setup
// ─────────────────────────────────────────────────────────────────────────────
function weedops_setup(): void {
load_theme_textdomain( 'weedops', WEEDOPS_DIR . '/languages' );
add_theme_support( 'title-tag' );
add_theme_support( 'post-thumbnails' );
add_theme_support( 'html5', [ 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption', 'style', 'script' ] );
add_theme_support( 'customize-selective-refresh-widgets' );
add_theme_support( 'woocommerce' );
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
register_nav_menus( [
'primary' => __( 'Primary Navigation', 'weedops' ),
'footer' => __( 'Footer Navigation', 'weedops' ),
'account' => __( 'Account Menu', 'weedops' ),
] );
// Theme setup
function weedops_setup() {
add_theme_support('title-tag');
add_theme_support('post-thumbnails');
add_theme_support('html5', array('search-form', 'comment-form', 'comment-list', 'gallery', 'caption'));
}
add_action( 'after_setup_theme', 'weedops_setup' );
add_action('after_setup_theme', 'weedops_setup');
// ─────────────────────────────────────────────────────────────────────────────
// Scripts & Styles
// ─────────────────────────────────────────────────────────────────────────────
function weedops_enqueue_assets(): void {
// Google Fonts — Inter
wp_enqueue_style(
'weedops-fonts',
'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap',
[],
null
);
// Main stylesheet
wp_enqueue_style(
'weedops-style',
get_stylesheet_uri(),
[ 'weedops-fonts' ],
WEEDOPS_VERSION
);
// Main JS bundle
wp_enqueue_script(
'weedops-main',
WEEDOPS_URI . '/assets/js/main.js',
[],
WEEDOPS_VERSION,
true
);
// Pass data to JS
wp_localize_script( 'weedops-main', 'WeedopsData', [
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'restUrl' => esc_url_raw( rest_url( 'weedops/v1/' ) ),
'nonce' => wp_create_nonce( 'wp_rest' ),
'siteUrl' => get_site_url(),
'isLoggedIn'=> is_user_logged_in(),
] );
// Enqueue styles
function weedops_scripts() {
wp_enqueue_style('weedops-style', get_stylesheet_uri(), array(), '1.0');
}
add_action( 'wp_enqueue_scripts', 'weedops_enqueue_assets' );
add_action('wp_enqueue_scripts', 'weedops_scripts');
// ─────────────────────────────────────────────────────────────────────────────
// Custom Post Types, Taxonomies & Meta Fields
// ─────────────────────────────────────────────────────────────────────────────
// Remove WordPress junk from head
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wp_shortlink_wp_head');
remove_action('wp_head', 'rest_output_link_wp_head');
remove_action('wp_head', 'wp_oembed_add_discovery_links');
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
// Post types, taxonomies, and meta field registration live in their own file.
require_once WEEDOPS_DIR . '/inc/custom-post-types.php';
// Remove WP block library CSS (not using Gutenberg blocks)
function weedops_remove_block_css() {
wp_dequeue_style('wp-block-library');
wp_dequeue_style('wp-block-library-theme');
wp_dequeue_style('classic-theme-styles');
wp_dequeue_style('global-styles');
}
add_action('wp_enqueue_scripts', 'weedops_remove_block_css', 100);
// ─────────────────────────────────────────────────────────────────────────────
// Widget Areas
// ─────────────────────────────────────────────────────────────────────────────
// Disable Gutenberg for pages
function weedops_disable_gutenberg($current_status, $post_type) {
if ($post_type === 'page') return false;
return $current_status;
}
add_filter('use_block_editor_for_post_type', 'weedops_disable_gutenberg', 10, 2);
function weedops_register_sidebars(): void {
$sidebars = [
[ 'id' => 'sidebar-main', 'name' => __( 'Main Sidebar', 'weedops' ) ],
[ 'id' => 'sidebar-catalog', 'name' => __( 'Catalog Sidebar', 'weedops' ) ],
[ 'id' => 'footer-col-1', 'name' => __( 'Footer Column 1', 'weedops' ) ],
[ 'id' => 'footer-col-2', 'name' => __( 'Footer Column 2', 'weedops' ) ],
[ 'id' => 'footer-col-3', 'name' => __( 'Footer Column 3', 'weedops' ) ],
];
// Cloudflare Turnstile (for deck request form)
define('WEEDOPS_TURNSTILE_SITE_KEY', '');
define('WEEDOPS_TURNSTILE_SECRET_KEY', '');
foreach ( $sidebars as $s ) {
register_sidebar( [
'id' => $s['id'],
'name' => $s['name'],
'before_widget' => '<div id="%1$s" class="wo-widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="wo-widget__title">',
'after_title' => '</h4>',
] );
function weedops_turnstile_scripts() {
if (WEEDOPS_TURNSTILE_SITE_KEY) {
wp_enqueue_script('turnstile', 'https://challenges.cloudflare.com/turnstile/v0/api.js', array(), null, true);
}
}
add_action( 'widgets_init', 'weedops_register_sidebars' );
add_action('wp_enqueue_scripts', 'weedops_turnstile_scripts');
// ─────────────────────────────────────────────────────────────────────────────
// Helper Functions
// ─────────────────────────────────────────────────────────────────────────────
function weedops_verify_turnstile($token) {
if (!WEEDOPS_TURNSTILE_SECRET_KEY || empty($token)) return !WEEDOPS_TURNSTILE_SECRET_KEY;
/**
* Render a strain type badge.
*
* @param string $type indica | sativa | hybrid | cbd
* @param bool $echo Echo or return.
*/
function weedops_strain_badge( string $type, bool $echo = true ): string {
$label = ucfirst( $type );
$class = 'wo-badge wo-badge--' . sanitize_html_class( strtolower( $type ) );
$html = sprintf( '<span class="%s">%s</span>', esc_attr( $class ), esc_html( $label ) );
if ( $echo ) echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return $html;
$response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', array(
'body' => array(
'secret' => WEEDOPS_TURNSTILE_SECRET_KEY,
'response' => $token,
'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
),
));
if (is_wp_error($response)) return false;
$body = json_decode(wp_remote_retrieve_body($response), true);
return !empty($body['success']);
}
/**
* Return formatted THC/CBD string for a strain.
*
* @param int $post_id
*/
function weedops_get_cannabinoid_str( int $post_id ): string {
$thc = get_post_meta( $post_id, 'wo_thc_percent', true );
$cbd = get_post_meta( $post_id, 'wo_cbd_percent', true );
$parts = [];
if ( $thc !== '' ) $parts[] = 'THC ' . number_format( (float) $thc, 1 ) . '%';
if ( $cbd !== '' ) $parts[] = 'CBD ' . number_format( (float) $cbd, 1 ) . '%';
return implode( ' · ', $parts );
// Handle deck request form submission (early, before headers sent)
function weedops_handle_deck_request_init() {
if (!isset($_POST['weedops_deck_request'])) return;
// Verify nonce
if (!wp_verify_nonce($_POST['_wpnonce'] ?? '', 'weedops_deck_request')) {
set_transient('weedops_form_error_' . $_SERVER['REMOTE_ADDR'], 'Invalid request.', 60);
wp_redirect(home_url('/#deck'));
exit;
}
// Verify Turnstile if configured
if (WEEDOPS_TURNSTILE_SITE_KEY && !weedops_verify_turnstile($_POST['cf-turnstile-response'] ?? '')) {
set_transient('weedops_form_error_' . $_SERVER['REMOTE_ADDR'], 'Verification failed. Please try again.', 60);
wp_redirect(home_url('/#deck'));
exit;
}
$name = sanitize_text_field($_POST['name'] ?? '');
$email = sanitize_email($_POST['email'] ?? '');
$note = sanitize_textarea_field($_POST['note'] ?? '');
if (empty($name) || empty($email)) {
set_transient('weedops_form_error_' . $_SERVER['REMOTE_ADDR'], 'Name and email are required.', 60);
wp_redirect(home_url('/#deck'));
exit;
}
// Send notification email
$to = 'john@weedops.site';
$subject = 'WeedOps Deck Request: ' . $name;
$body = "Name: {$name}\nEmail: {$email}\n\nNote:\n{$note}";
$headers = array('Reply-To: ' . $name . ' <' . $email . '>');
wp_mail($to, $subject, $body, $headers);
set_transient('weedops_form_success_' . $_SERVER['REMOTE_ADDR'], true, 60);
wp_redirect(home_url('/#deck'));
exit;
}
add_action('template_redirect', 'weedops_handle_deck_request_init');
/**
* Check if a product has a valid COA (lab test certificate).
*/
function weedops_has_valid_coa( int $post_id ): bool {
$coa = get_post_meta( $post_id, 'wo_coa_url', true );
$tested = get_post_meta( $post_id, 'wo_lab_tested', true );
return ! empty( $coa ) && (bool) $tested;
// Get form result from transient (after redirect)
function weedops_get_form_result() {
$ip = $_SERVER['REMOTE_ADDR'];
$success = get_transient('weedops_form_success_' . $ip);
if ($success) {
delete_transient('weedops_form_success_' . $ip);
return true;
}
$error = get_transient('weedops_form_error_' . $ip);
if ($error) {
delete_transient('weedops_form_error_' . $ip);
return $error;
}
return null;
}
/**
* Age-gate: returns true if the user has confirmed they are 21+.
* Stored in a session cookie.
*/
function weedops_age_verified(): bool {
return ! empty( $_COOKIE['wo_age_verified'] );
}
// ─────────────────────────────────────────────────────────────────────────────
// Age Verification AJAX Handler
// ─────────────────────────────────────────────────────────────────────────────
function weedops_ajax_age_verify(): void {
check_ajax_referer( 'wo_age_verify', 'nonce' );
setcookie( 'wo_age_verified', '1', time() + ( 30 * DAY_IN_SECONDS ), COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
wp_send_json_success( [ 'verified' => true ] );
}
add_action( 'wp_ajax_nopriv_wo_age_verify', 'weedops_ajax_age_verify' );
add_action( 'wp_ajax_wo_age_verify', 'weedops_ajax_age_verify' );
// ─────────────────────────────────────────────────────────────────────────────
// Title Tag
// ─────────────────────────────────────────────────────────────────────────────
function weedops_document_title_parts( array $parts ): array {
$parts['tagline'] = get_bloginfo( 'description' );
return $parts;
}
add_filter( 'document_title_parts', 'weedops_document_title_parts' );
// ─────────────────────────────────────────────────────────────────────────────
// Excerpt length
// ─────────────────────────────────────────────────────────────────────────────
add_filter( 'excerpt_length', fn() => 30 );
add_filter( 'excerpt_more', fn() => '&hellip;' );

View file

@ -1,91 +1,33 @@
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#1a3d2b">
<link rel="profile" href="https://gmpg.org/xfn/11">
<meta name="description" content="WeedOps — managed home cannabis cultivation. A confidential investor overview.">
<meta name="robots" content="noindex, nofollow">
<link rel="icon" type="image/svg+xml" href="<?php echo get_template_directory_uri(); ?>/images/favicon.svg">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<header class="site-header">
<nav class="nav-container">
<a href="<?php echo home_url(); ?>" class="logo">Weed<span>Ops</span></a>
<?php // ── Age-gate compliance notice ─────────────────────────── ?>
<div class="wo-age-notice" role="note" aria-label="<?php esc_attr_e( 'Age compliance notice', 'weedops' ); ?>">
<?php esc_html_e( '21+ only. Cannabis products are for adults. Comply with your local laws.', 'weedops' ); ?>
</div>
<button class="nav-toggle" aria-label="Toggle navigation" onclick="document.querySelector('.nav-links').classList.toggle('active')">
<span></span>
<span></span>
<span></span>
</button>
<?php // ── Site Header ───────────────────────────────────────── ?>
<header class="wo-header" role="banner">
<div class="wo-container">
<div class="wo-header__inner">
<?php // Logo ?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="wo-logo" rel="home">
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" aria-hidden="true" focusable="false">
<path d="M14 2C8.5 2 4 6.5 4 12c0 3.5 2 6.5 5 8.5L14 26l5-5.5c3-2 5-5 5-8.5C24 6.5 19.5 2 14 2z" fill="#4a9e68"/>
<path d="M14 6c-3.3 0-6 2.7-6 6 0 2 1 3.8 2.5 4.8L14 20l3.5-3.2c1.5-1 2.5-2.8 2.5-4.8 0-3.3-2.7-6-6-6z" fill="#c8a951"/>
</svg>
Weed<span>ops</span>
</a>
<?php // Primary navigation ?>
<nav class="wo-nav" id="wo-primary-nav" role="navigation" aria-label="<?php esc_attr_e( 'Primary', 'weedops' ); ?>">
<?php
wp_nav_menu( [
'theme_location' => 'primary',
'menu_class' => '',
'container' => false,
'fallback_cb' => 'weedops_fallback_nav',
] );
?>
</nav>
<?php // Header actions ?>
<div class="wo-header__actions">
<?php if ( is_user_logged_in() ) : ?>
<a href="<?php echo esc_url( get_dashboard_url() ); ?>" class="wo-btn wo-btn--outline" style="font-size:0.82rem;padding:0.45rem 0.9rem;">
<?php esc_html_e( 'Dashboard', 'weedops' ); ?>
</a>
<?php else : ?>
<a href="<?php echo esc_url( wp_login_url() ); ?>" class="wo-btn wo-btn--primary" style="font-size:0.82rem;padding:0.45rem 0.9rem;">
<?php esc_html_e( 'Sign In', 'weedops' ); ?>
</a>
<?php endif; ?>
</div>
<?php // Mobile hamburger ?>
<button
class="wo-nav-toggle"
aria-controls="wo-primary-nav"
aria-expanded="false"
aria-label="<?php esc_attr_e( 'Toggle navigation', 'weedops' ); ?>"
style="display:none;background:none;border:none;cursor:pointer;padding:0.5rem;"
>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true">
<rect y="3" width="22" height="2.5" rx="1.25" fill="#fff"/>
<rect y="10" width="22" height="2.5" rx="1.25" fill="#fff"/>
<rect y="17" width="22" height="2.5" rx="1.25" fill="#fff"/>
</svg>
</button>
</div><!-- .wo-header__inner -->
</div><!-- .wo-container -->
<ul class="nav-links">
<li><a href="<?php echo home_url('/#opportunity'); ?>">The Opportunity</a></li>
<li><a href="<?php echo home_url('/#model'); ?>">The Model</a></li>
<li><a href="<?php echo home_url('/#campus'); ?>">Campus</a></li>
<li><a href="<?php echo home_url('/#ask'); ?>">The Ask</a></li>
<li><a href="<?php echo home_url('/#deck'); ?>" class="btn-nav">Request the Deck</a></li>
</ul>
</nav>
</header>
<?php
// Fallback nav when no menu is assigned
function weedops_fallback_nav(): void {
echo '<ul>';
echo '<li><a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Home', 'weedops' ) . '</a></li>';
echo '<li><a href="' . esc_url( home_url( '/strains' ) ) . '">' . esc_html__( 'Strains', 'weedops' ) . '</a></li>';
echo '<li><a href="' . esc_url( home_url( '/products' ) ) . '">' . esc_html__( 'Products', 'weedops' ) . '</a></li>';
echo '<li><a href="' . esc_url( home_url( '/dispensaries' ) ) . '">' . esc_html__( 'Dispensaries', 'weedops' ) . '</a></li>';
echo '</ul>';
}
?>
<main class="wo-main" id="main-content" role="main">
<div class="wo-container">
<main>

View file

@ -1,391 +0,0 @@
<?php
/**
* Weedops Custom Post Types, Taxonomies & Meta Fields
*
* Registers the 'strain' post type (and related CPTs) with full
* meta support: THC %, CBD %, strain type, effects, and more.
*
* @package Weedops
* @version 1.0.0
*/
defined( 'ABSPATH' ) || exit;
// ─────────────────────────────────────────────────────────────────────────────
// Post Types
// ─────────────────────────────────────────────────────────────────────────────
function weedops_register_post_types(): void {
// ── Strains ──────────────────────────────────────────────────────────────
register_post_type( 'wo_strain', [
'label' => __( 'Strains', 'weedops' ),
'labels' => [
'name' => __( 'Strains', 'weedops' ),
'singular_name' => __( 'Strain', 'weedops' ),
'add_new' => __( 'Add New', 'weedops' ),
'add_new_item' => __( 'Add New Strain', 'weedops' ),
'edit_item' => __( 'Edit Strain', 'weedops' ),
'new_item' => __( 'New Strain', 'weedops' ),
'view_item' => __( 'View Strain', 'weedops' ),
'search_items' => __( 'Search Strains', 'weedops' ),
'not_found' => __( 'No strains found', 'weedops' ),
'not_found_in_trash' => __( 'No strains in trash', 'weedops' ),
'menu_name' => __( 'Strains', 'weedops' ),
],
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => true,
'rest_base' => 'strains',
'menu_icon' => 'dashicons-palmtree',
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'revisions' ],
'has_archive' => true,
'rewrite' => [ 'slug' => 'strains', 'with_front' => false ],
'capability_type' => 'post',
'map_meta_cap' => true,
] );
// ── Cannabis Products ─────────────────────────────────────────────────────
register_post_type( 'wo_product', [
'label' => __( 'Cannabis Products', 'weedops' ),
'labels' => [
'name' => __( 'Cannabis Products', 'weedops' ),
'singular_name' => __( 'Cannabis Product', 'weedops' ),
'add_new_item' => __( 'Add New Product', 'weedops' ),
'edit_item' => __( 'Edit Product', 'weedops' ),
'not_found' => __( 'No products found', 'weedops' ),
],
'public' => true,
'show_in_rest' => true,
'rest_base' => 'cannabis-products',
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ],
'menu_icon' => 'dashicons-archive',
'has_archive' => true,
'rewrite' => [ 'slug' => 'products', 'with_front' => false ],
'capability_type' => 'post',
] );
// ── Compliance Records ────────────────────────────────────────────────────
register_post_type( 'wo_compliance', [
'label' => __( 'Compliance Records', 'weedops' ),
'labels' => [
'name' => __( 'Compliance Records', 'weedops' ),
'singular_name' => __( 'Compliance Record', 'weedops' ),
'add_new_item' => __( 'Add Record', 'weedops' ),
],
'public' => false,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => true,
'rest_base' => 'compliance',
'supports' => [ 'title', 'custom-fields' ],
'menu_icon' => 'dashicons-shield',
'capability_type' => 'post',
] );
// ── Dispensaries / Locations ──────────────────────────────────────────────
register_post_type( 'wo_dispensary', [
'label' => __( 'Dispensaries', 'weedops' ),
'public' => true,
'show_in_rest' => true,
'rest_base' => 'dispensaries',
'supports' => [ 'title', 'editor', 'thumbnail', 'custom-fields' ],
'menu_icon' => 'dashicons-location-alt',
'has_archive' => true,
'rewrite' => [ 'slug' => 'dispensaries', 'with_front' => false ],
] );
}
add_action( 'init', 'weedops_register_post_types' );
// ─────────────────────────────────────────────────────────────────────────────
// Taxonomies
// ─────────────────────────────────────────────────────────────────────────────
function weedops_register_taxonomies(): void {
// ── Strain Type: indica / sativa / hybrid / cbd ───────────────────────────
register_taxonomy( 'wo_strain_type', [ 'wo_strain', 'wo_product' ], [
'label' => __( 'Strain Type', 'weedops' ),
'labels' => [
'name' => __( 'Strain Types', 'weedops' ),
'singular_name' => __( 'Strain Type', 'weedops' ),
'add_new_item' => __( 'Add Strain Type', 'weedops' ),
'search_items' => __( 'Search Types', 'weedops' ),
],
'hierarchical' => true,
'show_in_rest' => true,
'rest_base' => 'strain-types',
'rewrite' => [ 'slug' => 'strain-type' ],
'show_admin_column' => true,
] );
// ── Effects (relaxed, euphoric, creative, …) ──────────────────────────────
register_taxonomy( 'wo_effect', [ 'wo_strain', 'wo_product' ], [
'label' => __( 'Effects', 'weedops' ),
'labels' => [
'name' => __( 'Effects', 'weedops' ),
'singular_name' => __( 'Effect', 'weedops' ),
'add_new_item' => __( 'Add Effect', 'weedops' ),
],
'hierarchical' => false,
'show_in_rest' => true,
'rest_base' => 'effects',
'rewrite' => [ 'slug' => 'effect' ],
'show_admin_column' => true,
] );
// ── Terpenes ──────────────────────────────────────────────────────────────
register_taxonomy( 'wo_terpene', [ 'wo_strain', 'wo_product' ], [
'label' => __( 'Terpenes', 'weedops' ),
'hierarchical' => false,
'show_in_rest' => true,
'rest_base' => 'terpenes',
'rewrite' => [ 'slug' => 'terpene' ],
] );
// ── Product Category (flower / concentrate / edible / topical / …) ────────
register_taxonomy( 'wo_product_cat', [ 'wo_product' ], [
'label' => __( 'Product Category', 'weedops' ),
'hierarchical' => true,
'show_in_rest' => true,
'rest_base' => 'product-categories',
'rewrite' => [ 'slug' => 'product-category' ],
] );
// ── Compliance Status ─────────────────────────────────────────────────────
register_taxonomy( 'wo_compliance_status', [ 'wo_compliance', 'wo_product' ], [
'label' => __( 'Compliance Status', 'weedops' ),
'hierarchical' => true,
'show_in_rest' => true,
'public' => false,
'show_ui' => true,
] );
}
add_action( 'init', 'weedops_register_taxonomies' );
// ─────────────────────────────────────────────────────────────────────────────
// Meta Field Registration (REST API + Gutenberg)
// ─────────────────────────────────────────────────────────────────────────────
function weedops_register_meta_fields(): void {
// Strain meta
$strain_meta = [
'wo_thc_percent' => [ 'type' => 'number', 'label' => 'THC %', 'sanitize' => 'floatval' ],
'wo_cbd_percent' => [ 'type' => 'number', 'label' => 'CBD %', 'sanitize' => 'floatval' ],
'wo_genetics' => [ 'type' => 'string', 'label' => 'Genetics / Lineage', 'sanitize' => 'sanitize_text_field' ],
'wo_flowering_time' => [ 'type' => 'integer', 'label' => 'Flowering Time (days)', 'sanitize' => 'absint' ],
'wo_yield_indoor' => [ 'type' => 'string', 'label' => 'Indoor Yield', 'sanitize' => 'sanitize_text_field' ],
'wo_yield_outdoor' => [ 'type' => 'string', 'label' => 'Outdoor Yield', 'sanitize' => 'sanitize_text_field' ],
'wo_difficulty' => [ 'type' => 'string', 'label' => 'Grow Difficulty', 'sanitize' => 'sanitize_text_field' ],
];
foreach ( $strain_meta as $key => $config ) {
register_post_meta( 'wo_strain', $key, [
'type' => $config['type'],
'single' => true,
'show_in_rest' => true,
'description' => $config['label'],
'sanitize_callback' => $config['sanitize'],
'auth_callback' => fn() => current_user_can( 'edit_posts' ),
] );
}
// Product meta
$product_meta = [
'wo_sku' => [ 'type' => 'string', 'label' => 'SKU / License #', 'sanitize' => 'sanitize_text_field' ],
'wo_batch_id' => [ 'type' => 'string', 'label' => 'Batch ID', 'sanitize' => 'sanitize_text_field' ],
'wo_lab_tested' => [ 'type' => 'boolean', 'label' => 'Lab Tested', 'sanitize' => 'rest_sanitize_boolean' ],
'wo_coa_url' => [ 'type' => 'string', 'label' => 'COA (Certificate of Analysis) URL','sanitize' => 'esc_url_raw' ],
'wo_price_gram' => [ 'type' => 'number', 'label' => 'Price per Gram', 'sanitize' => 'floatval' ],
'wo_inventory_qty' => [ 'type' => 'integer', 'label' => 'Inventory Qty (g)', 'sanitize' => 'absint' ],
'wo_origin_state' => [ 'type' => 'string', 'label' => 'Origin State', 'sanitize' => 'sanitize_text_field' ],
'wo_license_no' => [ 'type' => 'string', 'label' => 'Producer License #', 'sanitize' => 'sanitize_text_field' ],
];
foreach ( $product_meta as $key => $config ) {
register_post_meta( 'wo_product', $key, [
'type' => $config['type'],
'single' => true,
'show_in_rest' => true,
'description' => $config['label'],
'sanitize_callback' => $config['sanitize'],
'auth_callback' => fn() => current_user_can( 'edit_posts' ),
] );
}
}
add_action( 'init', 'weedops_register_meta_fields' );
// ─────────────────────────────────────────────────────────────────────────────
// Admin Meta Box — Strain Details
// ─────────────────────────────────────────────────────────────────────────────
function weedops_add_strain_meta_box(): void {
add_meta_box(
'wo_strain_details',
__( 'Strain Details', 'weedops' ),
'weedops_render_strain_meta_box',
'wo_strain',
'normal',
'high'
);
}
add_action( 'add_meta_boxes', 'weedops_add_strain_meta_box' );
function weedops_render_strain_meta_box( WP_Post $post ): void {
wp_nonce_field( 'wo_save_strain_details', 'wo_strain_nonce' );
$thc = get_post_meta( $post->ID, 'wo_thc_percent', true );
$cbd = get_post_meta( $post->ID, 'wo_cbd_percent', true );
$genetics = get_post_meta( $post->ID, 'wo_genetics', true );
$difficulty = get_post_meta( $post->ID, 'wo_difficulty', true );
// Strain type from taxonomy
$strain_types = get_the_terms( $post->ID, 'wo_strain_type' );
$current_type = ( $strain_types && ! is_wp_error( $strain_types ) )
? $strain_types[0]->slug
: '';
// Effects from taxonomy
$effects_terms = get_terms( [ 'taxonomy' => 'wo_effect', 'hide_empty' => false ] );
$assigned_effects = wp_get_post_terms( $post->ID, 'wo_effect', [ 'fields' => 'ids' ] );
?>
<style>
.wo-metabox-grid { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:16px; }
.wo-metabox-field label { display:block; font-weight:600; margin-bottom:4px; }
.wo-metabox-field input,
.wo-metabox-field select { width:100%; }
.wo-effects-list { columns:3; gap:12px; }
.wo-effects-list label { display:block; font-weight:normal; margin-bottom:4px; }
</style>
<div class="wo-metabox-grid">
<div class="wo-metabox-field">
<label for="wo_thc_percent"><?php esc_html_e( 'THC %', 'weedops' ); ?></label>
<input type="number" id="wo_thc_percent" name="wo_thc_percent"
value="<?php echo esc_attr( $thc ); ?>"
step="0.1" min="0" max="100" placeholder="e.g. 22.5" />
</div>
<div class="wo-metabox-field">
<label for="wo_cbd_percent"><?php esc_html_e( 'CBD %', 'weedops' ); ?></label>
<input type="number" id="wo_cbd_percent" name="wo_cbd_percent"
value="<?php echo esc_attr( $cbd ); ?>"
step="0.1" min="0" max="100" placeholder="e.g. 0.5" />
</div>
<div class="wo-metabox-field">
<label for="wo_strain_type_select"><?php esc_html_e( 'Strain Type', 'weedops' ); ?></label>
<select id="wo_strain_type_select" name="wo_strain_type_select">
<option value=""><?php esc_html_e( '— Select type —', 'weedops' ); ?></option>
<?php foreach ( [ 'indica' => 'Indica', 'sativa' => 'Sativa', 'hybrid' => 'Hybrid', 'cbd' => 'CBD / High-CBD' ] as $slug => $label ) : ?>
<option value="<?php echo esc_attr( $slug ); ?>"
<?php selected( $current_type, $slug ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="wo-metabox-field">
<label for="wo_difficulty"><?php esc_html_e( 'Grow Difficulty', 'weedops' ); ?></label>
<select id="wo_difficulty" name="wo_difficulty">
<option value=""><?php esc_html_e( '— Select —', 'weedops' ); ?></option>
<?php foreach ( [ 'beginner' => 'Beginner', 'intermediate' => 'Intermediate', 'advanced' => 'Advanced' ] as $val => $lbl ) : ?>
<option value="<?php echo esc_attr( $val ); ?>"
<?php selected( $difficulty, $val ); ?>>
<?php echo esc_html( $lbl ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="wo-metabox-field" style="margin-bottom:16px;">
<label for="wo_genetics"><?php esc_html_e( 'Genetics / Lineage', 'weedops' ); ?></label>
<input type="text" id="wo_genetics" name="wo_genetics"
value="<?php echo esc_attr( $genetics ); ?>"
placeholder="e.g. OG Kush × Durban Poison" style="width:100%;" />
</div>
<?php if ( ! is_wp_error( $effects_terms ) && ! empty( $effects_terms ) ) : ?>
<div class="wo-metabox-field">
<label><?php esc_html_e( 'Effects', 'weedops' ); ?></label>
<div class="wo-effects-list">
<?php foreach ( $effects_terms as $effect ) : ?>
<label>
<input type="checkbox" name="wo_effect_terms[]"
value="<?php echo esc_attr( $effect->term_id ); ?>"
<?php checked( in_array( $effect->term_id, (array) $assigned_effects, true ) ); ?> />
<?php echo esc_html( $effect->name ); ?>
</label>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php
}
function weedops_save_strain_meta( int $post_id ): void {
// Bail on autosave / AJAX / wrong post type
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( ! isset( $_POST['wo_strain_nonce'] ) ) return;
if ( ! wp_verify_nonce( sanitize_key( $_POST['wo_strain_nonce'] ), 'wo_save_strain_details' ) ) return;
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
if ( get_post_type( $post_id ) !== 'wo_strain' ) return;
// THC %
if ( isset( $_POST['wo_thc_percent'] ) ) {
$thc = (float) $_POST['wo_thc_percent'];
update_post_meta( $post_id, 'wo_thc_percent', $thc );
}
// CBD %
if ( isset( $_POST['wo_cbd_percent'] ) ) {
$cbd = (float) $_POST['wo_cbd_percent'];
update_post_meta( $post_id, 'wo_cbd_percent', $cbd );
}
// Genetics
if ( isset( $_POST['wo_genetics'] ) ) {
update_post_meta( $post_id, 'wo_genetics', sanitize_text_field( wp_unslash( $_POST['wo_genetics'] ) ) );
}
// Difficulty
if ( isset( $_POST['wo_difficulty'] ) ) {
$allowed = [ 'beginner', 'intermediate', 'advanced', '' ];
$diff = in_array( $_POST['wo_difficulty'], $allowed, true ) ? $_POST['wo_difficulty'] : '';
update_post_meta( $post_id, 'wo_difficulty', $diff );
}
// Strain type — set taxonomy term by slug
if ( isset( $_POST['wo_strain_type_select'] ) ) {
$type_slug = sanitize_key( $_POST['wo_strain_type_select'] );
if ( ! empty( $type_slug ) ) {
// Make sure the term exists (create if needed)
$term = get_term_by( 'slug', $type_slug, 'wo_strain_type' );
if ( ! $term ) {
$inserted = wp_insert_term( ucfirst( $type_slug ), 'wo_strain_type', [ 'slug' => $type_slug ] );
$term_id = is_wp_error( $inserted ) ? 0 : $inserted['term_id'];
} else {
$term_id = $term->term_id;
}
if ( $term_id ) {
wp_set_post_terms( $post_id, [ $term_id ], 'wo_strain_type' );
}
} else {
wp_set_post_terms( $post_id, [], 'wo_strain_type' );
}
}
// Effects — array of term IDs
$effect_ids = isset( $_POST['wo_effect_terms'] )
? array_map( 'absint', (array) $_POST['wo_effect_terms'] )
: [];
wp_set_post_terms( $post_id, $effect_ids, 'wo_effect' );
}
add_action( 'save_post_wo_strain', 'weedops_save_strain_meta' );

154
index.php
View file

@ -1,144 +1,26 @@
<?php
/**
* Weedops Main Template File
*
* Fallback template used when no more specific template matches.
* Also serves as the blog/post archive.
*
* @package Weedops
* Default template fallback redirect to home
*/
get_header();
?>
<?php if ( is_home() && ! is_front_page() ) : ?>
<header class="wo-page-header wo-mb-3">
<h1 class="wo-page-title"><?php esc_html_e( 'Latest Posts', 'weedops' ); ?></h1>
</header>
<?php endif; ?>
<section style="padding-top: calc(var(--nav-height) + 80px); padding-bottom: 64px;">
<div class="container">
<h1><?php the_title(); ?></h1>
</div>
</section>
<?php if ( have_posts() ) : ?>
<section>
<div class="container">
<?php
if (have_posts()) :
while (have_posts()) : the_post();
the_content();
endwhile;
endif;
?>
</div>
</section>
<div class="wo-grid wo-grid--3">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class( 'wo-card' ); ?>>
<?php if ( has_post_thumbnail() ) : ?>
<a href="<?php the_permalink(); ?>" class="wo-card__thumb" aria-hidden="true" tabindex="-1">
<?php
the_post_thumbnail( 'medium', [
'class' => 'wo-card__img',
'loading' => 'lazy',
'style' => 'width:100%;height:180px;object-fit:cover;border-radius:8px 8px 0 0;margin:-1.5rem -1.5rem 1rem;width:calc(100% + 3rem);',
] );
?>
</a>
<?php endif; ?>
<?php // Post type / taxonomy badges ?>
<div class="wo-card__meta" style="margin-bottom:0.6rem;">
<?php
$post_type = get_post_type();
if ( 'wo_strain' === $post_type ) {
$types = get_the_terms( get_the_ID(), 'wo_strain_type' );
if ( $types && ! is_wp_error( $types ) ) {
foreach ( $types as $t ) {
weedops_strain_badge( $t->slug );
}
}
} elseif ( 'wo_product' === $post_type ) {
$cats = get_the_terms( get_the_ID(), 'wo_product_cat' );
if ( $cats && ! is_wp_error( $cats ) ) {
echo '<span class="wo-badge" style="background:#1a2e3d;color:#b3d9ff;">';
echo esc_html( $cats[0]->name );
echo '</span>';
}
} else {
echo '<span class="wo-text-muted" style="font-size:0.78rem;">';
echo esc_html( get_the_category_list( ', ' ) );
echo '</span>';
}
?>
</div>
<h2 class="wo-card__title" style="font-size:1.1rem;margin-bottom:0.5rem;">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h2>
<?php // Cannabinoid info for strains/products ?>
<?php if ( in_array( $post_type, [ 'wo_strain', 'wo_product' ], true ) ) : ?>
<?php $canna_str = weedops_get_cannabinoid_str( get_the_ID() ); ?>
<?php if ( $canna_str ) : ?>
<p style="font-size:0.82rem;font-weight:600;color:var(--wo-green-mid);margin-bottom:0.5rem;">
<?php echo esc_html( $canna_str ); ?>
</p>
<?php endif; ?>
<?php endif; ?>
<div class="wo-card__excerpt" style="font-size:0.875rem;color:var(--wo-text-muted);margin-bottom:1rem;">
<?php the_excerpt(); ?>
</div>
<div class="wo-card__footer" style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:0.5rem;">
<a href="<?php the_permalink(); ?>" class="wo-btn wo-btn--outline" style="font-size:0.8rem;padding:0.4rem 0.8rem;">
<?php esc_html_e( 'View Details', 'weedops' ); ?>
</a>
<?php // COA badge for lab-tested products ?>
<?php if ( 'wo_product' === $post_type && weedops_has_valid_coa( get_the_ID() ) ) : ?>
<span class="wo-compliance-tag wo-compliance-tag--ok">
<?php esc_html_e( 'Lab Tested', 'weedops' ); ?>
</span>
<?php endif; ?>
<?php // Date for blog posts ?>
<?php if ( 'post' === $post_type ) : ?>
<time datetime="<?php echo esc_attr( get_the_date( 'c' ) ); ?>" style="font-size:0.78rem;color:var(--wo-text-muted);">
<?php echo esc_html( get_the_date() ); ?>
</time>
<?php endif; ?>
</div>
</article>
<?php endwhile; ?>
</div><!-- .wo-grid -->
<?php // Pagination ?>
<nav class="wo-pagination wo-mt-3" role="navigation" aria-label="<?php esc_attr_e( 'Posts pagination', 'weedops' ); ?>">
<?php
the_posts_pagination( [
'mid_size' => 2,
'prev_text' => '&larr; ' . __( 'Previous', 'weedops' ),
'next_text' => __( 'Next', 'weedops' ) . ' &rarr;',
'before_page_number' => '<span class="wo-sr-only">' . __( 'Page', 'weedops' ) . ' </span>',
] );
?>
</nav>
<?php else : ?>
<?php // No posts found ?>
<section class="wo-card wo-text-center" style="max-width:560px;margin:4rem auto;">
<svg width="56" height="56" viewBox="0 0 28 28" fill="none" aria-hidden="true" style="margin:0 auto 1rem;display:block;opacity:0.25;">
<path d="M14 2C8.5 2 4 6.5 4 12c0 3.5 2 6.5 5 8.5L14 26l5-5.5c3-2 5-5 5-8.5C24 6.5 19.5 2 14 2z" fill="#1a3d2b"/>
</svg>
<h2 style="font-size:1.3rem;"><?php esc_html_e( 'Nothing found', 'weedops' ); ?></h2>
<p class="wo-text-muted wo-mt-1">
<?php esc_html_e( 'No content matches your query. Try searching or browse our strain database.', 'weedops' ); ?>
</p>
<div class="wo-mt-2">
<?php get_search_form(); ?>
</div>
<div class="wo-mt-2">
<a href="<?php echo esc_url( home_url( '/strains' ) ); ?>" class="wo-btn wo-btn--primary">
<?php esc_html_e( 'Browse Strains', 'weedops' ); ?>
</a>
</div>
</section>
<?php endif; ?>
<?php
get_footer();
<?php get_footer(); ?>

View file

@ -1,224 +0,0 @@
<?php
/**
* Single Strain Template
* Displays individual strain details: THC%, CBD%, type, effects, and product image.
*
* @package Weedops
*/
get_header(); ?>
<main id="main" class="weedops-main">
<?php while ( have_posts() ) : the_post(); ?>
<article id="strain-<?php the_ID(); ?>" <?php post_class( 'strain-single' ); ?>>
<div class="strain-hero">
<div class="strain-hero__image">
<?php if ( has_post_thumbnail() ) : ?>
<?php the_post_thumbnail( 'large', [ 'class' => 'strain-hero__img' ] ); ?>
<?php else : ?>
<div class="strain-hero__placeholder">
<div class="strain-hero__placeholder-inner">
<span class="strain-hero__placeholder-icon">🌿</span>
<span class="strain-hero__placeholder-text">Product Image Coming Soon</span>
</div>
</div>
<?php endif; ?>
</div>
<div class="strain-hero__info">
<div class="strain-badge strain-badge--<?php echo esc_attr( get_post_meta( get_the_ID(), '_strain_type', true ) ); ?>">
<?php
$strain_type = get_post_meta( get_the_ID(), '_strain_type', true );
echo esc_html( ucfirst( $strain_type ? $strain_type : 'Unknown' ) );
?>
</div>
<h1 class="strain-title"><?php the_title(); ?></h1>
<div class="strain-potency">
<?php
$thc = get_post_meta( get_the_ID(), '_strain_thc', true );
$cbd = get_post_meta( get_the_ID(), '_strain_cbd', true );
?>
<?php if ( $thc !== '' ) : ?>
<div class="potency-card potency-card--thc">
<span class="potency-card__label">THC</span>
<span class="potency-card__value"><?php echo esc_html( $thc ); ?>%</span>
<div class="potency-bar">
<div class="potency-bar__fill potency-bar__fill--thc" style="width: <?php echo esc_attr( min( floatval( $thc ), 35 ) / 35 * 100 ); ?>%"></div>
</div>
</div>
<?php endif; ?>
<?php if ( $cbd !== '' ) : ?>
<div class="potency-card potency-card--cbd">
<span class="potency-card__label">CBD</span>
<span class="potency-card__value"><?php echo esc_html( $cbd ); ?>%</span>
<div class="potency-bar">
<div class="potency-bar__fill potency-bar__fill--cbd" style="width: <?php echo esc_attr( min( floatval( $cbd ), 25 ) / 25 * 100 ); ?>%"></div>
</div>
</div>
<?php endif; ?>
</div>
<?php
$effects_raw = get_post_meta( get_the_ID(), '_strain_effects', true );
$effects = array_filter( array_map( 'trim', explode( ',', $effects_raw ) ) );
if ( ! empty( $effects ) ) :
?>
<div class="strain-effects">
<h3 class="strain-effects__heading">Effects</h3>
<div class="strain-effects__tags">
<?php foreach ( $effects as $effect ) : ?>
<span class="effect-tag"><?php echo esc_html( $effect ); ?></span>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php if ( get_the_content() ) : ?>
<div class="strain-description">
<h2 class="strain-description__heading">About This Strain</h2>
<div class="strain-description__content">
<?php the_content(); ?>
</div>
</div>
<?php endif; ?>
<div class="strain-compliance-notice">
<p>⚠️ For use only by adults 21+. Keep out of reach of children. This product has not been evaluated by the FDA.</p>
</div>
<nav class="strain-nav">
<?php
$prev = get_previous_post();
$next = get_next_post();
if ( $prev ) :
?>
<a href="<?php echo esc_url( get_permalink( $prev ) ); ?>" class="strain-nav__link strain-nav__link--prev">
<?php echo esc_html( get_the_title( $prev ) ); ?>
</a>
<?php endif; ?>
<a href="<?php echo esc_url( get_post_type_archive_link( 'strain' ) ); ?>" class="strain-nav__link strain-nav__link--archive">
All Strains
</a>
<?php if ( $next ) : ?>
<a href="<?php echo esc_url( get_permalink( $next ) ); ?>" class="strain-nav__link strain-nav__link--next">
<?php echo esc_html( get_the_title( $next ) ); ?>
</a>
<?php endif; ?>
</nav>
</article>
<?php endwhile; ?>
</main>
<style>
/* ── Single Strain Styles ─────────────────────────────── */
.strain-single { max-width: 1100px; margin: 0 auto; padding: 2rem 1.5rem; }
.strain-hero {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
align-items: start;
margin-bottom: 3rem;
}
@media (max-width: 768px) {
.strain-hero { grid-template-columns: 1fr; gap: 1.5rem; }
}
/* Image / Placeholder */
.strain-hero__img { width: 100%; border-radius: 12px; object-fit: cover; aspect-ratio: 4/3; }
.strain-hero__placeholder {
width: 100%; aspect-ratio: 4/3;
background: linear-gradient(135deg, #1a3a1a 0%, #2d5a2d 100%);
border-radius: 12px;
display: flex; align-items: center; justify-content: center;
border: 2px dashed #4a8c4a;
}
.strain-hero__placeholder-inner { text-align: center; color: #8ec88e; }
.strain-hero__placeholder-icon { font-size: 3rem; display: block; margin-bottom: .5rem; }
.strain-hero__placeholder-text { font-size: .9rem; letter-spacing: .05em; }
/* Badge */
.strain-badge {
display: inline-block;
padding: .3rem .9rem;
border-radius: 999px;
font-size: .75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .08em;
margin-bottom: 1rem;
}
.strain-badge--indica { background: #4a148c; color: #e1bee7; }
.strain-badge--sativa { background: #e65100; color: #ffe0b2; }
.strain-badge--hybrid { background: #1b5e20; color: #c8e6c9; }
/* Title */
.strain-title { font-size: 2.5rem; font-weight: 800; margin: 0 0 1.5rem; color: #1a3a1a; line-height: 1.2; }
/* Potency */
.strain-potency { display: flex; gap: 1rem; margin-bottom: 1.5rem; flex-wrap: wrap; }
.potency-card {
flex: 1; min-width: 120px;
background: #f4f9f4;
border-radius: 10px;
padding: 1rem;
border-left: 4px solid;
}
.potency-card--thc { border-color: #388e3c; }
.potency-card--cbd { border-color: #0288d1; }
.potency-card__label { display: block; font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #666; }
.potency-card__value { display: block; font-size: 2rem; font-weight: 800; color: #1a3a1a; line-height: 1.1; margin-bottom: .4rem; }
.potency-bar { height: 6px; background: #ddd; border-radius: 3px; overflow: hidden; }
.potency-bar__fill--thc { height: 100%; background: #388e3c; border-radius: 3px; transition: width .4s ease; }
.potency-bar__fill--cbd { height: 100%; background: #0288d1; border-radius: 3px; transition: width .4s ease; }
/* Effects */
.strain-effects__heading { font-size: .85rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: #555; margin-bottom: .6rem; }
.strain-effects__tags { display: flex; flex-wrap: wrap; gap: .4rem; }
.effect-tag {
background: #e8f5e9; color: #2e7d32;
border: 1px solid #a5d6a7;
border-radius: 999px;
padding: .25rem .8rem;
font-size: .85rem;
font-weight: 500;
}
/* Description */
.strain-description { background: #f9fafb; border-radius: 12px; padding: 2rem; margin-bottom: 2rem; }
.strain-description__heading { font-size: 1.3rem; font-weight: 700; color: #1a3a1a; margin-top: 0; }
/* Compliance */
.strain-compliance-notice {
background: #fff8e1; border-left: 4px solid #fbc02d;
border-radius: 6px; padding: .8rem 1.2rem;
font-size: .8rem; color: #5d4037;
margin-bottom: 2rem;
}
.strain-compliance-notice p { margin: 0; }
/* Nav */
.strain-nav { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem; padding-top: 1.5rem; border-top: 1px solid #e0e0e0; }
.strain-nav__link {
color: #2e7d32; font-weight: 600; text-decoration: none;
padding: .5rem 1rem; border-radius: 6px;
border: 1px solid #a5d6a7;
transition: background .2s;
}
.strain-nav__link:hover { background: #e8f5e9; }
.strain-nav__link--archive { background: #2e7d32; color: #fff; border-color: #2e7d32; }
.strain-nav__link--archive:hover { background: #1b5e20; }
</style>
<?php get_footer(); ?>

1348
style.css

File diff suppressed because it is too large Load diff