0,
'style' => '',
], $atts, 'sfaq' );
$post_id = $atts['id'] ? (int) $atts['id'] : get_the_ID();
if ( ! $post_id ) return '';
$style_override = $atts['style'] ? 'style' . (int) $atts['style'] : '';
return $this->render_faq( $post_id, $style_override );
}
/* ------------------------------------------------------------------ */
/* Auto-inject after post content */
/* ------------------------------------------------------------------ */
public function auto_inject( $content ) {
if ( ! is_singular() || is_admin() ) return $content;
$post_id = get_the_ID();
if ( ! $post_id ) return $content;
// Only inject once per page (prevents Elementor double-render issues)
static $injected = [];
if ( isset( $injected[ $post_id ] ) ) return $content;
$injected[ $post_id ] = true;
$html = $this->render_faq( $post_id );
return $content . $html;
}
/* ------------------------------------------------------------------ */
/* Core Render */
/* ------------------------------------------------------------------ */
public function render_faq( $post_id, $style_override = '' ) {
if ( ! SFAQ_Plugin::has_faqs( $post_id ) ) return '';
// --- Resolve per-post visibility ---
$raw_visible = get_post_meta( $post_id, '_sfaq_visible', true );
if ( $raw_visible === '0' ) return ''; // hidden by per-post setting
if ( $raw_visible === '' ) {
// Use global
if ( ! SFAQ_Plugin::get_setting( 'faq_visible', '1' ) ) return '';
}
$items = SFAQ_Plugin::get_faq_items( $post_id );
if ( empty( $items ) ) return '';
// --- Resolve style ---
$style = $style_override ?: SFAQ_Plugin::get_setting( 'ui_style', 'style1' );
if ( ! preg_match( '/^style[1-5]$/', $style ) ) $style = 'style1';
// --- Resolve title ---
$show_title = $this->resolve_meta( $post_id, '_sfaq_title_enabled', 'faq_title_enabled', '1' );
$custom_title = get_post_meta( $post_id, '_sfaq_title', true );
$title_text = $custom_title ?: SFAQ_Plugin::get_setting( 'faq_title_text', 'Frequently Asked Questions' );
$uid = 'sfaq-' . $post_id . '-' . wp_rand( 100, 999 );
ob_start();
?>
$item ) :
$item_id = $uid . '-item-' . $idx;
$panel_id = $uid . '-panel-' . $idx;
?>
build_dynamic_css();
set_transient( $transient_key, $css, DAY_IN_SECONDS );
}
wp_add_inline_style( 'sfaq-frontend', $css );
wp_enqueue_script(
'sfaq-frontend',
SFAQ_PLUGIN_URL . 'assets/js/frontend.js',
[],
SFAQ_VERSION,
true
);
}
private function build_dynamic_css() {
$s = function( $key ) { return SFAQ_Plugin::get_setting( $key ); };
$q_bg = esc_attr( $s( 'q_bg' ) ?: '#ffffff' );
$q_text = esc_attr( $s( 'q_text' ) ?: '#000000' );
$q_border = esc_attr( $s( 'q_border' ) ?: '#cccccc' );
$q_radius = (int) ( $s( 'q_radius' ) ?: 10 );
$q_hover_bg = esc_attr( $s( 'q_hover_bg' ) ?: '#f5f5f5' );
$q_hover_text = esc_attr( $s( 'q_hover_text' ) ?: '#000000' );
$q_active_bg = esc_attr( $s( 'q_active_bg' ) ?: '#d8222b' );
$q_active_text = esc_attr( $s( 'q_active_text' ) ?: '#ffffff' );
$a_bg = esc_attr( $s( 'a_bg' ) ?: '#ffffff' );
$a_text = esc_attr( $s( 'a_text' ) ?: '#000000' );
$title_color = esc_attr( $s( 'title_color' ) ?: '#000000' );
$font_family = $s( 'font_family' ) ?: 'inherit';
$font_size_title = (int) ( $s( 'font_size_title' ) ?: 24 );
$font_size_q = (int) ( $s( 'font_size_q' ) ?: 16 );
$font_size_a = (int) ( $s( 'font_size_a' ) ?: 15 );
$font_weight_q = esc_attr( $s( 'font_weight_q' ) ?: '600' );
$font_family_css = esc_attr( $font_family );
$q_padding_v = (int) ( $s( 'q_padding_v' ) ?: 14 );
$q_padding_h = (int) ( $s( 'q_padding_h' ) ?: 18 );
$a_padding_v = (int) ( $s( 'a_padding_v' ) ?: 14 );
$a_padding_h = (int) ( $s( 'a_padding_h' ) ?: 18 );
$item_gap = (int) ( $s( 'item_gap' ) ?: 10 );
/*
* Every colour rule uses !important so that theme/Elementor button styles
* (e.g. "button { background: #000 }") can never win.
* Selectors are also prefixed with .sfaq-wrap for extra specificity.
*/
return "
/* ===== Smart FAQ Schema — Dynamic CSS ===== */
.sfaq-wrap { font-family: {$font_family_css}; }
.sfaq-wrap .sfaq-section-title {
color: {$title_color} !important;
font-size: {$font_size_title}px !important;
}
/* ---- Ensure closed panels are TRULY invisible ---- */
.sfaq-wrap .sfaq-answer { max-height: 0 !important; overflow: hidden !important; }
.sfaq-wrap .sfaq-answer[hidden] { display: none !important; max-height: 0 !important; }
.sfaq-wrap .sfaq-item--open .sfaq-answer { max-height: 2000px !important; display: block !important; }
/* ---- Default question state ---- */
.sfaq-wrap .sfaq-question {
background-color: {$q_bg} !important;
color: {$q_text} !important;
font-size: {$font_size_q}px !important;
font-weight: {$font_weight_q} !important;
padding: {$q_padding_v}px {$q_padding_h}px !important;
border: none !important;
outline: none !important;
text-align: left !important;
}
/* ---- Hover state ---- */
.sfaq-wrap .sfaq-question:hover {
background-color: {$q_hover_bg} !important;
color: {$q_hover_text} !important;
}
/* ---- Active / open state (two selectors for robustness) ---- */
.sfaq-wrap .sfaq-question[aria-expanded='true'] {
background-color: {$q_active_bg} !important;
color: {$q_active_text} !important;
}
.sfaq-wrap .sfaq-item--open > .sfaq-question-wrap > .sfaq-question,
.sfaq-wrap .sfaq-item--open .sfaq-question {
background-color: {$q_active_bg} !important;
color: {$q_active_text} !important;
}
/* ---- Borders / radius (style1 + style3) ---- */
.sfaq-wrap.sfaq-style1 .sfaq-item,
.sfaq-wrap.sfaq-style3 .sfaq-item {
border-radius: {$q_radius}px !important;
overflow: hidden;
}
.sfaq-wrap.sfaq-style1 .sfaq-item {
border: 1px solid {$q_border} !important;
}
/* ---- Answer panel ---- */
.sfaq-wrap .sfaq-answer-inner {
background-color: {$a_bg} !important;
color: {$a_text} !important;
font-size: {$font_size_a}px !important;
padding: {$a_padding_v}px {$a_padding_h}px !important;
}
/* ---- Item gap (applied per style) ---- */
.sfaq-wrap.sfaq-style1 .sfaq-accordion,
.sfaq-wrap.sfaq-style3 .sfaq-accordion,
.sfaq-wrap.sfaq-style4 .sfaq-accordion,
.sfaq-wrap.sfaq-style5 .sfaq-accordion {
gap: {$item_gap}px !important;
}
/* ---- Icon colour follows active text ---- */
.sfaq-wrap .sfaq-question[aria-expanded='true'] .sfaq-icon {
color: {$q_active_text} !important;
}
.sfaq-wrap .sfaq-item--open .sfaq-question .sfaq-icon {
color: {$q_active_text} !important;
}
/* ---- Style 4 left border ---- */
.sfaq-wrap.sfaq-style4 .sfaq-item {
border-left-color: {$q_active_bg} !important;
}
.sfaq-wrap.sfaq-style4 .sfaq-question[aria-expanded='true'] {
border-left-color: {$q_active_bg} !important;
}
/* ---- Style 5 pill ---- */
.sfaq-wrap.sfaq-style5 .sfaq-question[aria-expanded='true'] {
background-color: {$q_active_bg} !important;
color: {$q_active_text} !important;
}
";
}
/* ------------------------------------------------------------------ */
/* Helper: resolve per-post vs global */
/* ------------------------------------------------------------------ */
private function resolve_meta( $post_id, $meta_key, $global_key, $default ) {
$val = get_post_meta( $post_id, $meta_key, true );
if ( $val === '1' ) return true;
if ( $val === '0' ) return false;
// fall back to global
return (bool) SFAQ_Plugin::get_setting( $global_key, $default );
}
}