' . $icon_inner . '
';
// legacy stores/echoes title/desc raw (admin authors badge markup
// such as ' . aksrt_icon_card_kses($title) . '
';
}
if (trim(wp_strip_all_tags($desc)) !== '' || str_contains($desc, '<')) {
$text .= ' ' . aksrt_icon_card_kses($desc) . '
';
}
$html = '';
if ($url !== '') {
// legacy: ';
}
// Keep every horizontal icon card on the same compact visual contract,
// regardless of the page-specific wrapper that renders it.
$html .= '';
$html .= $icon;
$html .= $text !== '' ? '
' . $text . '
' : '';
$html .= '
';
if ($url !== '') {
$html .= '';
}
if ($echo) {
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return '';
}
return $html;
}
endif;
if (!function_exists('aksrt_obs_animate_attrs')) :
/**
* Build class + attribute string for scroll-in animation (maps to data-aksrt-animate).
*
* @param string $animation fade|slideup|slidedown|slideright|slideleft|zoomin|zoomout|''
* @param bool $repeat
* @param float|int $delay_s
* @return array{class:string,attr:string}
*/
function aksrt_obs_animate_attrs(string $animation, bool $repeat = false, $delay_s = 0): array {
$animation = sanitize_key($animation);
$map = [
'fade' => 'fadeIn',
'slideup' => 'fadeInUp',
'slidedown' => 'fadeInDown',
'slideright' => 'fadeInRight',
'slideleft' => 'fadeInLeft',
'zoomin' => 'zoomIn',
'zoomout' => 'fadeIn',
'fadein' => 'fadeIn',
'fadeinup' => 'fadeInUp',
];
if ($animation === '' || !isset($map[$animation]) && !in_array($animation, $map, true)) {
if (!isset($map[$animation])) {
return ['class' => '', 'attr' => ''];
}
}
$aksrt = $map[$animation] ?? $animation;
$delay_ms = (int) round(((float) $delay_s) * 1000);
$class = ' obs-animate ani-' . $animation;
$attr = ' data-aksrt-animate="' . esc_attr($aksrt) . '"';
if ($delay_ms > 0) {
$attr .= ' data-aksrt-animate-delay="' . esc_attr((string) $delay_ms) . '"';
}
if ($repeat) {
$attr .= ' data-animation-repeat="true"';
}
return ['class' => $class, 'attr' => $attr];
}
endif;