=== SSC Career Hub ===
Contributors: ssc
Tags: security jobs, cv review, careers, woocommerce
Requires at least: 6.0
Requires PHP: 7.4
Stable tag: 1.4.6
License: GPLv2 or later

Curated NY/NJ security job directory, CSV/Google Sheet sync, saved-job activity, CV paste/upload review queue with shareable readiness reports, attribution tracking, optional OpenRouter LLM enrichment for paid reviews, and admin pages for SSC Security Guard Training.

V1.4.6 CV form vertical stretch fix:
* The form card was rendering ~1200px tall with only ~370px of content, producing huge dead space between the wizard chips, the step heading, the fields, and the Continue button. Root cause: the parent .ssc-ch-cv-shell is a 2-column grid (form + aside) with default align-items:stretch, so the form was being stretched to match the taller aside (credit balance + 4 top-up cards). The form is itself display:grid, so it then distributed the extra height across its internal rows — pushing chips, legend, fields, and nav far apart.
* Fix: align-items:start on the parent shell (form sizes to its own content), plus align-self:start + align-content:start on the form (defensive, pack rows at top regardless of container height). Both gaps collapse to the intended 14px row gap.

V1.4.5 dashboard hero + KPI layout fix:
* The dashboard hero was rendering "My Security Career Dashboard" as four stacked words ("My / Security / Career / Dashboard") at giant size — root cause: the hero is a 2-column grid (minmax(0,1fr) 320px) but the template loose-leafed three direct children (kicker, h2, reminder p), so the h2 landed in the 320px-wide column and word-wrapped.
* Restructured dashboard.php to match the Jobs hero pattern — content wrapped in a <div> + new <aside class="ssc-ch-hero-card"> that holds the stats (tracked / applied / CV reviews / credits) and the pathway chips. Now they live INSIDE the dark hero where the existing white-on-dark styling actually works.
* Added defensive CSS: any hero without an aside/hero-card child collapses to a single column (fixes [ssc_my_credits], [ssc_my_cvs], and the logged-out dashboard, all of which have no aside).
* Forced kicker pill to sizeof-content with higher specificity in case a parent theme applies "p { width: 100% }".
* Saved/tracked jobs table got proper styling — uppercase muted column headers, hover state, status pill in SSC blue, "View" link in SSC blue instead of inheriting the theme's anchor red.
* Stats grid switched to 2x2 inside the hero aside so the 4th stat doesn't orphan.

V1.4.4 jobs-page filter strip visual fix:
* Filter labels (State track / Role type / Training) were rendering as white-on-white because the v1.4.0 chip styles assumed the filter strip was on the dark hero gradient (legacy 1.3.x layout). Rewrote the entire chip/label/collapse block for the actual light background — labels are now uppercase muted ink, chips are blue-ink-on-white pills with solid SSC blue when active, collapsible City/Training panels have a clean +/− toggle.
* Broke the legacy 6-column grid (.ssc-ch-filters at line 425) for chip-mode forms — the chip form is now a clean vertical flex column so State / City / Role / Training / Search-Clear stack naturally instead of sprawling across the row.
* Search/Clear actions row has a top border + proper button styling so it reads as the form's commit zone.
* Improved focus state on inputs/selects (3px blue outline + ink border).

V1.4.3 spacing + UX patch on the CV Optimizer form:
* Fixed ~150px of dead vertical space inside the wizard fieldset by resetting Chrome's default fieldset min-inline-size and the legend's implicit top anchoring. Wizard steps now sit flush below the progress chips.
* Tightened wizard progress chips bottom spacing (was 22+24+border, now 14+16+border).
* Empty submit-row container no longer takes vertical space on non-last wizard steps (hidden via data-wizard-last="0").
* Success card no longer renders "Your CV scored 0/100" when the URL has ?submitted=1 without a real score. Falls through to a generic "received" message unless cv, t, and a positive score are all present.

V1.4.2 adds secure OpenRouter integration:
* New SSC_CH_OpenRouter helper. The API key is read ONLY from a wp-config.php constant (SSC_CH_OPENROUTER_KEY) — never from wp_options, so it does not appear in DB backups (JetBackup → Google Drive in this hosting setup). Optional SSC_CH_OPENROUTER_MODEL constant overrides the default model (anthropic/claude-haiku-4.5). Optional SSC_CH_OPENROUTER_HOST for self-hosted gateways.
* When a candidate spends credits for an ultimate CV review (status → priority_review), a WP-cron event fires SSC_CH_OpenRouter::run_for_cv() which calls OpenRouter, stores the draft narrative in cv_reviews.ai_narrative, and logs token usage + cost in ssc_ch_ai_usage.
* Admin gate: the AI draft is NEVER auto-published. It appears as an admin-only details panel on the CV Reviews row with a "Use this as candidate feedback" button that copies the draft into the candidate_feedback textarea. The admin reviews, edits, and saves before anything reaches the candidate.
* Per-call cost cap (openrouter_cost_cap_usd setting) is enforced as a 100× daily ceiling. If today's cumulative AI cost exceeds the ceiling, requests are skipped and logged to abuse_events.
* Settings page shows "Configured via wp-config.php (…last4)" or "Not configured" — the key value itself is never echoed to the page.
* Prompt-injection defence: CV text is wrapped in explicit ===CV BEGINS=== / ===CV ENDS=== markers, system prompt fixes the role, output is capped at 600 tokens, and the model is instructed not to mention being AI.
* New columns on ssc_ch_cv_reviews: ai_narrative, ai_narrative_at. Existing CVs are unaffected.
* If the constant is absent, the plugin degrades to the prior behaviour (local heuristic + human-fulfilled priority reviews). No errors, no half-broken state.

V1.4.1 sanity-check pass on top of 1.4.0:
* CV form wizard is now progressive enhancement — without JS the form renders as a single page with a working submit button; with JS the multi-step nav + per-step validation kicks in.
* [ssc_my_cvs] cards now expose a "View report" button per scored CV (was missing the link in v1.4.0).
* Candidate confirmation email goes out automatically after CV submission, with the shareable report link and clear NY/NJ disclaimer.
* New candidate_feedback field on CV reviews — admins can write public-facing reviewer notes (rendered on the CV report) separately from internal admin_notes, and can tick "Email the candidate" to push the update.
* Candidate dashboard now includes a "CV score trend" bar chart of the last 5 reviews, with score-delta vs previous and a one-click link to the latest report.
* Chart.js admin enqueue keeps the CDN dependency but the placeholder SRI was removed (a wrong digest would brick the charts); doc-comment explains how to pin the real hash post-install.
* New DB columns on ssc_ch_cv_reviews: candidate_feedback, candidate_notified_at.

V1.4.0 was a major design + capability pass:
* Shareable token-based CV report at [ssc_cv_report] — full score breakdown, six dimension bars, strengths, next-step checklist, recommendation CTA, score-over-time delta, and OG/Twitter share-card metadata.
* Pure-PHP PDF and DOCX text extraction (no Composer deps, no shelling out) — text-based uploads now get scored automatically; only scanned/encrypted PDFs fall through to manual review.
* UTM/source attribution capture (cookie-based, sendBeacon ingest) joins to CV submissions and credit purchases, surfacing a "where candidates come from" widget on the analytics page.
* Admin analytics rebuilt: date-range filter with 7/30/90/all presets, Chart.js daily activity + credits-purchased charts, conversion funnel (saves → applied → CV → credits), CSV export of the credit ledger, and tone-coded ledger rows.
* Mobile CV form is now a 3-step wizard with progress chips and per-step validation.
* Mobile jobs filter swaps native multi-select for tap-friendly chip groups in collapsible details panels.
* Bug fixes: word-boundary keyword matching in the CV analyzer (no more "patrol" inside "patrol-style"), removed all three unused legacy CSS files, dropped legacy 0000-00-00 deleted_at fallbacks, hardened error reflection on the CV form.
* New DB tables: ssc_ch_attribution (UTM/referrer/device per session) and ssc_ch_report_views (CV report engagement). New columns on ssc_ch_cv_reviews: share_token, share_views, share_first_viewed_at, extraction_source, attribution_id. Existing CVs are backfilled with share tokens on upgrade.

V1.3.4 added admin manual credit adjustments, a fuller analytics control room, recent credit ledger visibility, CV status breakdowns, and stronger candidate dashboard stats. V1.3.3 tightened the CV/credit flow review: empty submissions are blocked, file-only CVs are queued for manual review, priority credit spend uses the logged-in account identity. V1.3.2 preserved manually uploaded WooCommerce product images. V1.3.1 fixed WooCommerce variation checkout links. V1.3.0 added credit top-ups, My Credits/My CVs shortcodes, CV scoring, safer PDF/DOCX/TXT uploads, credit analytics, and API-cost tracking.

== Description ==
SSC Career Hub provides shortcodes:
* [ssc_jobs] — searchable job directory from local DB synced from CSV/published Google Sheet.
* [ssc_job_dashboard] — simple seeker dashboard for saved/applied activity.
* [ssc_cv_optimizer] — three-step CV intake wizard with readiness score and admin review.
* [ssc_cv_report] — public token-shareable CV readiness report (place on its own page, e.g. /cv-report/).
* [ssc_my_credits] — logged-in candidate credit balance and smooth top-up cards.
* [ssc_my_cvs] — logged-in candidate CV review tracker.

Important: SSC provides training and career preparation support. Job listings are informational and employment is not guaranteed. New York DCJS training and New Jersey SORA are distinct requirements.

== Installation ==
Upload/activate the plugin, place the shortcodes on pages, configure CSV URL under SSC Career Hub > Sync Jobs, then run Manual Sync.

== CSV Columns ==
Supports common headers: id, title/job_title, company/employer, city/location, state, job_type/type, pay/pay_text, schedule, training_requirement/training, tags, summary/description, requirements, apply_url/url, source_name, source_url, verified_at, expires_at.

== Security ==
Uses nonces/capabilities, fixed file allowlist (txt/pdf/docx only; legacy .doc is blocked), private upload folder protection, hashed IP/email for rate/abuse events, formula-safe CSV helper, and WooCommerce buyer detection only when WooCommerce functions exist.
