'Rooster Contracts' ) ); $raw = isset( $data['contracts'] ) ? trim( (string) $data['contracts'] ) : ''; if ( '' === $raw ) { continue; } foreach ( preg_split( '/[\s,]+/', $raw ) as $token ) { if ( preg_match( '/^(C\d+)(?:@(\d+))?$/i', $token, $m ) ) { self::$declared[ strtoupper( $m[1] ) ] = isset( $m[2] ) ? (int) $m[2] : 1; } } break; } return self::$declared; } public static function declares( $contract, $min_version = 1 ) { $declared = self::declared(); $contract = strtoupper( (string) $contract ); return isset( $declared[ $contract ] ) && $declared[ $contract ] >= (int) $min_version; } public static function design_authority() { $authority = function_exists( 'rooster_design_authority' ) ? (string) rooster_design_authority() : ( function_exists( 'roosterx_design_authority' ) ? (string) roosterx_design_authority() : 'plugins' ); return 'theme' === $authority ? 'theme' : 'plugins'; } public static function theme_has_authority() { return self::declares( 'C2' ) && 'theme' === self::design_authority(); } public static function print_shape_roles() { if ( is_admin() || ! self::declares( 'C2', 2 ) ) { return; } $roles = array( 'button' => '4px', 'control' => '4px', 'card' => '8px', 'panel' => '8px', 'media' => '4px', 'chip' => '999px' ); $css = ''; foreach ( $roles as $role => $fallback ) { $css .= '--aieo-shape-' . $role . ':var(--wp--custom--rooster--shape--' . $role . ',' . $fallback . ');'; } $css .= '--aieo-color-success:var(--wp--preset--color--success,#15803d);--aieo-color-warning:var(--wp--preset--color--warning,#b45309);--aieo-color-danger:var(--wp--preset--color--danger,#b91c1c);--aieo-color-info:var(--wp--preset--color--accent,#1d4ed8);--aieo-color-bg:var(--wp--preset--color--bg,#fff);--aieo-color-fg:var(--wp--preset--color--fg,#1f2937);'; echo '' . "\n"; } public static function hex_to_rgb( $hex ) { $hex = ltrim( trim( (string) $hex ), '#' ); if ( 3 === strlen( $hex ) ) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } if ( ! preg_match( '/^[0-9a-f]{6}$/i', $hex ) ) { return null; } return array( hexdec( substr( $hex, 0, 2 ) ), hexdec( substr( $hex, 2, 2 ) ), hexdec( substr( $hex, 4, 2 ) ) ); } public static function luminance( array $rgb ) { $lin = array(); foreach ( $rgb as $c ) { $c = max( 0, min( 255, (int) $c ) ) / 255; $lin[] = $c <= 0.03928 ? $c / 12.92 : pow( ( $c + 0.055 ) / 1.055, 2.4 ); } return 0.2126 * $lin[0] + 0.7152 * $lin[1] + 0.0722 * $lin[2]; } public static function contrast( $hex_a, $hex_b ) { $a = self::hex_to_rgb( $hex_a ); $b = self::hex_to_rgb( $hex_b ); if ( ! $a || ! $b ) { return 0.0; } $la = self::luminance( $a ); $lb = self::luminance( $b ); return ( max( $la, $lb ) + 0.05 ) / ( min( $la, $lb ) + 0.05 ); } public static function readable_on_white( $hex, $ratio = 4.5 ) { $rgb = self::hex_to_rgb( $hex ); if ( ! $rgb ) { return (string) $hex; } for ( $i = 0; $i < 40; $i++ ) { $lum = self::luminance( $rgb ); if ( ( 1.05 / ( $lum + 0.05 ) ) >= $ratio ) { break; } $rgb = array( (int) floor( $rgb[0] * 0.92 ), (int) floor( $rgb[1] * 0.92 ), (int) floor( $rgb[2] * 0.92 ) ); } return sprintf( '#%02x%02x%02x', $rgb[0], $rgb[1], $rgb[2] ); } } }