$context]; $context['version']=GP_DARKMODE_VERSION; $context['level']=$level; try{ if(function_exists('gp_omnilog')) gp_omnilog('dark-mode',$event,array_merge(['message'=>$message],$context)); }catch(\Throwable $e){} try{ if(function_exists('gp_log')) gp_log($message,'DARKMODE',array_merge(['event'=>$event],$context)); }catch(\Throwable $e){} } register_deactivation_hook(__FILE__,function(){ gp_darkmode_log('Dark Mode engine deactivated.','deactivated'); }); register_activation_hook(__FILE__, function() { if(get_option('gp_dm_brightness') === false) update_option('gp_dm_brightness', 95); if(get_option('gp_dm_contrast') === false) update_option('gp_dm_contrast', 90); if(get_option('gp_dm_dim_level') === false) update_option('gp_dm_dim_level', 85); if(get_option('gracepress_dark_admin_enable') === false) update_option('gracepress_dark_admin_enable', '1'); if(get_option('gp_dm_veil_ms') === false) update_option('gp_dm_veil_ms', 160); if(get_option('gp_dm_veil_effect') === false) update_option('gp_dm_veil_effect', 'fade'); gp_darkmode_log('Dark Mode engine activated.','activated'); }); add_action('admin_init', function() { if (get_option('gp_dm_adminbar_toggle_restored') === '1') return; update_option('gracepress_dark_admin_enable', '1'); update_option('gp_dm_adminbar_toggle_restored', '1'); }); // Dynamic Self-Aware Router add_action('admin_menu',function(){ $s='gracepress-dark-mode'; $t='Dark Mode'; $is_theme_active = (get_template() === 'gracepress-theme'); $is_theme_required = false; if (!function_exists('get_plugin_data')) include_once(ABSPATH . 'wp-admin/includes/plugin.php'); $plugin_data = get_plugin_data(__FILE__); if (isset($plugin_data['Category']) && strtolower(trim($plugin_data['Category'])) === 'theme required') { $is_theme_required = true; } if(class_exists('GracePress_Central_Hub')) { $parent_slug = ($is_theme_active && $is_theme_required) ? 'gracepress-plugins' : 'gracepress-central'; add_submenu_page($parent_slug, $t, $t, 'manage_options', $s, 'gp_darkmode_admin_page'); } else { add_options_page($t, $t, 'manage_options', $s, 'gp_darkmode_admin_page'); } },100); function gp_darkmode_is_excluded(){ $ex_pages = get_option('gracepress_dark_exclude_pages',''); if(!empty($ex_pages) && (is_page() || is_single())){ $pid = get_the_ID(); $arr = array_map('trim', explode(',', $ex_pages)); if(in_array($pid, $arr)) return true; } return false; } function gp_darkmode_icons($s=''){ $s=$s?$s:get_option('gracepress_dark_icon_style','classic'); if($s=='minimal')return['l'=>'⚫','d'=>'⚪']; if($s=='bulbs')return['l'=>'🌑','d'=>'💡']; if($s=='text')return['l'=>'DARK','d'=>'LIGHT']; return['l'=>'🌙','d'=>'☀️']; } function gp_darkmode_btn($f=false,$s=''){ $sz=get_option('gracepress_dark_button_size','normal'); $s=$s?$s:get_option('gracepress_dark_icon_style','classic'); $i=gp_darkmode_icons($s);$l=$i['l'];$d=$i['d'];$c="gracepress-dark-toggle-trigger"; if($f){$p=get_option('gracepress_dark_button_position','bottom-right');$c.=" gracepress-floating gracepress-pos-$p";} if($s==='switch'){ $c.=" gracepress-pill-switch gracepress-size-$sz"; return "
$l
"; }else{ $c.=" gracepress-dark-toggle-btn gracepress-size-$sz".($s==='text'?' gracepress-text-btn':''); return ""; } } add_action('wp_head','gp_darkmode_head',1); add_action('admin_head','gp_darkmode_head',1); function gp_darkmode_head(){ if(!is_admin()&&gp_darkmode_is_excluded())return; $ds=get_option('gracepress_dark_default_state','light');$sp=get_option('gracepress_dark_transition_speed','0.3s');$pl=get_option('gracepress_dark_pulse_effect','0');$ex=get_option('gracepress_dark_exclusions','');$cus=get_option('gp_dm_css',''); if(!preg_match('/^(?:\d+(?:\.\d+)?|\.\d+)(?:ms|s)$/',$sp))$sp='0.3s'; $br=get_option('gp_dm_brightness',95); $ct=get_option('gp_dm_contrast',90); $dim=get_option('gp_dm_dim_level',85); $root_br = max(100, (int)$br); $root_ct = max(100, (int)$ct); $xstr="";if(!empty($ex)){$xp=explode(',',$ex);$xc=[];foreach($xp as $p){$p=trim($p);if(!empty($p)&&!preg_match('/[{};<>]|\/\*/',$p))$xc[]="html.gracepress-dark-active ".$p;}if(!empty($xc))$xstr=",".implode(',',$xc);} $veil_ms=max(0,min(800,absint(get_option('gp_dm_veil_ms',160)))); $veil_effect=sanitize_key(get_option('gp_dm_veil_effect','fade')); if(!in_array($veil_effect,['fade','wipe-right','wipe-down','iris','zoom'],true))$veil_effect='fade'; $site_dt=function_exists('current_datetime')?current_datetime():new DateTimeImmutable('now',function_exists('wp_timezone')?wp_timezone():null); $site_hour=(int)$site_dt->format('G'); $site_tz=wp_json_encode(function_exists('wp_timezone_string')?wp_timezone_string():''); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Values are JSON encoded before entering this early inline state script. echo ""; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Numeric, enum and selector values are validated; administrator-authored CSS is an intentional manage_options feature. echo ""; echo ""; echo ""; echo ""; } /** * Builder hero images are CSS backgrounds rather than img elements. Counter the * root dark-mode inversion on their composed surface so they retain the same * color and contrast as the original artwork. */ function gp_darkmode_builder_hero_correction(){ if(!is_admin()&&gp_darkmode_is_excluded())return; echo ''; } add_action('wp_head','gp_darkmode_builder_hero_correction',2); add_action('wp_footer','gp_darkmode_ftr',99); add_action('admin_footer','gp_darkmode_ftr',99); function gp_darkmode_ftr(){ if(!is_admin()&&gp_darkmode_is_excluded())return; if(!is_admin()&&get_option('gracepress_dark_frontend_enable','1')==='1')echo wp_kses_post(gp_darkmode_btn(true)); $kbd=get_option('gp_dm_kbd',1)?'true':'false'; $effect_json=wp_json_encode(sanitize_key(get_option('gp_dm_veil_effect','fade'))); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- The effect is allowlisted and the keyboard flag is a PHP-generated boolean literal. echo ""; } add_shortcode('gracepress_dark_toggle',function($a){$a=shortcode_atts(['style'=>''],is_array($a)?$a:[]);return gp_darkmode_btn(false,$a['style']);}); add_action('admin_bar_menu', function($wp_admin_bar) { if (!is_user_logged_in() || !is_admin_bar_showing()) return; $wp_admin_bar->add_node([ 'id' => 'gracepress-dark-admin-toggle', 'title' => 'Dark Mode', 'href' => '#', 'meta' => [ 'class' => 'gracepress-dark-menu-trigger', 'title' => 'Toggle GracePress dark mode', ], ]); }, 95); add_filter('wp_nav_menu_items',function($i,$a){static $d=false;if(get_option('gracepress_dark_menu_integration','0')==='1'&&!$d){$ic=gp_darkmode_icons();$i.="";$d=true;}return $i;},10,2); // ADMIN UI RESTORATION function gp_darkmode_admin_page(){ if(!current_user_can('manage_options'))return; $post_url = esc_url(admin_url('admin.php?page=gracepress-dark-mode')); if(isset($_POST['gp_dm_reset_filters']) && isset($_POST['_gp_dm_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_gp_dm_nonce'])), 'gp_dm_save_action')){ update_option('gp_dm_brightness', 95); update_option('gp_dm_contrast', 90); update_option('gp_dm_dim_level', 85); gp_darkmode_log('Dark Mode engine reset visual filters to factory defaults.','filters_reset',['brightness'=>95,'contrast'=>90,'media_dim'=>85]); echo '

Visual filters instantly restored to factory default levels (95/90/85).

'; } elseif(isset($_POST['gp_dm_save']) && isset($_POST['_gp_dm_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_gp_dm_nonce'])), 'gp_dm_save_action')){ foreach(['gracepress_dark_default_state','gracepress_dark_icon_style','gracepress_dark_button_size','gracepress_dark_button_position','gracepress_dark_transition_speed','gracepress_dark_exclusions','gracepress_dark_exclude_pages'] as $k) if(isset($_POST[$k])) update_option($k,sanitize_text_field(wp_unslash($_POST[$k]))); foreach(['gracepress_dark_frontend_enable','gracepress_dark_pulse_effect','gracepress_dark_menu_integration','gracepress_dark_admin_enable'] as $k) update_option($k,isset($_POST[$k])?'1':'0'); update_option('gp_dm_kbd',isset($_POST['gp_dm_kbd'])?1:0); update_option('gp_dm_brightness',isset($_POST['gp_dm_brightness'])?absint(wp_unslash($_POST['gp_dm_brightness'])):95); update_option('gp_dm_contrast',isset($_POST['gp_dm_contrast'])?absint(wp_unslash($_POST['gp_dm_contrast'])):90); update_option('gp_dm_dim_level',isset($_POST['gp_dm_dim_level'])?absint(wp_unslash($_POST['gp_dm_dim_level'])):85); update_option('gp_dm_veil_ms',max(0,min(800,absint($_POST['gp_dm_veil_ms'] ?? 160)))); $posted_veil_effect=sanitize_key($_POST['gp_dm_veil_effect'] ?? 'fade'); if(!in_array($posted_veil_effect,['fade','wipe-right','wipe-down','iris','zoom'],true))$posted_veil_effect='fade'; update_option('gp_dm_veil_effect',$posted_veil_effect); if(isset($_POST['gp_dm_css'])) update_option('gp_dm_css',sanitize_textarea_field(wp_unslash($_POST['gp_dm_css']))); gp_darkmode_log('Dark Mode configuration updated successfully.','settings_saved',[ 'default_state'=>get_option('gracepress_dark_default_state','light'), 'frontend_enabled'=>get_option('gracepress_dark_frontend_enable','1')==='1', 'admin_enabled'=>get_option('gracepress_dark_admin_enable','0')==='1', 'menu_integration'=>get_option('gracepress_dark_menu_integration','0')==='1', 'keyboard_shortcut'=>get_option('gp_dm_kbd',1)==1, 'brightness'=>absint(get_option('gp_dm_brightness',95)), 'contrast'=>absint(get_option('gp_dm_contrast',90)), 'media_dim'=>absint(get_option('gp_dm_dim_level',85)), 'veil_ms'=>absint(get_option('gp_dm_veil_ms',160)), 'veil_effect'=>sanitize_key(get_option('gp_dm_veil_effect','fade')), ]); echo '

Dark Mode configurations securely locked in.

'; } $ds=get_option('gracepress_dark_default_state','light');$ic=get_option('gracepress_dark_icon_style','classic');$sz=get_option('gracepress_dark_button_size','normal');$ps=get_option('gracepress_dark_button_position','bottom-right');$sp=get_option('gracepress_dark_transition_speed','0.3s');$ex=get_option('gracepress_dark_exclusions','');$exp=get_option('gracepress_dark_exclude_pages',''); $fe=get_option('gracepress_dark_frontend_enable','1');$pl=get_option('gracepress_dark_pulse_effect','0');$mi=get_option('gracepress_dark_menu_integration','0');$ad=get_option('gracepress_dark_admin_enable','0');$kbd=get_option('gp_dm_kbd',1);$cus=get_option('gp_dm_css',''); $br=get_option('gp_dm_brightness',95); $ct=get_option('gp_dm_contrast',90); $dim=get_option('gp_dm_dim_level',85); $veil_ms=max(0,min(800,absint(get_option('gp_dm_veil_ms',160)))); $veil_effect=sanitize_key(get_option('gp_dm_veil_effect','fade')); if(!in_array($veil_effect,['fade','wipe-right','wipe-down','iris','zoom'],true))$veil_effect='fade'; $admin_sunrise_url=plugin_dir_url(__FILE__).'assets/images/admin-sunrise.png'; ?>

🌓 Dark Mode Engine

Version . Features absolute Anti-FOUC synchronization, hardware-accelerated CSS inversion, precise filter tuning, variable media correction, configurable two-phase transitions, and optional local OmniLog integration.

1. Core Behavior

2. Visual Aesthetics

0 disables the transition veil. The duration is split into a cover phase and a reveal phase, so 220ms feels like a crisp two-way transition.

3. Integration & Rendering

Manual Shortcode: Use [gracepress_dark_toggle] to place the button exactly where you want it. You can also override the style locally: [gracepress_dark_toggle style="switch"]

Matrix Filter Preview Hub

Drag the sliders on the left to real-time sync and balance text opacity variables before saving configurations.

4. Advanced Customization

Completely disables the Dark Mode engine on these specific Post/Page IDs.
Protects specific HTML elements from the inversion filter.
Configure');return $l;});