{
  "config": {
    "step": {
      "account_choice": {
        "title": "Choose Account",
        "description": "You can add another home of an existing Tibber account or enter a new API token for a different account.",
        "data": {
          "account_choice": "Account"
        },
        "submit": "Continue →"
      },
      "new_token": {
        "title": "Enter API Token",
        "description": "Set up Tibber Price Information & Ratings.\n\nTo generate an API access token, visit [{tibber_url}]({tibber_url}).",
        "data": {
          "access_token": "API access token"
        },
        "submit": "Validate Token"
      },
      "user": {
        "description": "Set up Tibber Price Information & Ratings.\n\nTo generate an API access token, visit [{tibber_url}]({tibber_url}).",
        "data": {
          "access_token": "API access token"
        },
        "submit": "Validate Token"
      },
      "select_home": {
        "description": "Select a home to fetch price information and ratings.",
        "data": {
          "home_id": "Home"
        },
        "title": "Pick a Home",
        "submit": "Select Home"
      },
      "finish": {
        "description": "Select a home to fetch price information and ratings.",
        "data": {
          "home_id": "Home ID"
        },
        "title": "Pick a home",
        "submit": "Select Home"
      },
      "reauth_confirm": {
        "title": "Reauthenticate Tibber Price Integration",
        "description": "The access token for Tibber is no longer valid. Please enter a new API access token to continue using this integration.\n\nTo generate a new API access token, visit [{tibber_url}]({tibber_url}).",
        "data": {
          "access_token": "API access token"
        },
        "submit": "Update Token"
      }
    },
    "error": {
      "auth": "The Tibber Access Token is invalid.",
      "connection": "Unable to connect to Tibber. Please check your internet connection.",
      "unknown": "Unexpected error",
      "cannot_connect": "Failed to connect",
      "invalid_access_token": "Invalid access token",
      "missing_homes": "The new access token does not have access to all configured homes. Please use an access token that has access to the same Tibber homes.",
      "home_already_configured": "This home is already configured in another entry. Each home can only be configured once.",
      "no_active_subscription": "This home does not have an active Tibber contract. Only homes with active electricity contracts can be added to Home Assistant.",
      "subscription_expired": "The Tibber contract for this home has expired. Only homes with active or future electricity contracts can be added to Home Assistant.",
      "future_subscription_warning": "Note: This home's Tibber contract has not started yet. Functionality may be limited until the contract becomes active."
    },
    "abort": {
      "already_configured": "All available Tibber homes are already configured. Each home can only be configured once.",
      "entry_not_found": "Tibber configuration entry not found.",
      "setup_complete": "Setup complete! You can change additional options for Tibber Prices in the integration's options after closing this dialog.",
      "reauth_successful": "Reauthentication successful. The integration has been updated with the new access token."
    }
  },
  "common": {
    "step_progress": "{step_num} / {total_steps}",
    "override_warning_template": "⚠️ {fields} controlled by config entity",
    "override_warning_and": "and",
    "override_field_label_best_price_min_period_length": "Minimum Period Length",
    "override_field_label_best_price_max_level_gap_count": "Gap Tolerance",
    "override_field_label_best_price_flex": "Flexibility",
    "override_field_label_best_price_min_distance_from_avg": "Minimum Distance",
    "override_field_label_enable_min_periods_best": "Achieve Minimum Count",
    "override_field_label_min_periods_best": "Minimum Periods",
    "override_field_label_relaxation_attempts_best": "Relaxation Attempts",
    "override_field_label_peak_price_min_period_length": "Minimum Period Length",
    "override_field_label_peak_price_max_level_gap_count": "Gap Tolerance",
    "override_field_label_peak_price_flex": "Flexibility",
    "override_field_label_peak_price_min_distance_from_avg": "Minimum Distance",
    "override_field_label_enable_min_periods_peak": "Achieve Minimum Count",
    "override_field_label_min_periods_peak": "Minimum Periods",
    "override_field_label_relaxation_attempts_peak": "Relaxation Attempts"
  },
  "config_subentries": {
    "home": {
      "entry_type": "Time-Travel View",
      "initiate_flow": {
        "user": "Create Time-Travel View"
      },
      "title": "Create Time-Travel View",
      "step": {
        "user": {
          "title": "Select Configuration Entry",
          "description": "Select the configuration entry for which you want to create a time-travel view.\n\n**Time-travel views** allow you to see historical price data as if it were the current time. This is useful for testing automations or analyzing past price patterns.",
          "data": {
            "parent_entry_id": "Configuration Entry"
          }
        },
        "time_offset": {
          "title": "Configure Time Offset",
          "description": "Configure how far back in time this view should travel.\n\n**Recommended:** Use **≥2 days** offset to avoid conflicts with \"yesterday\" entities that also provide historical data.\n\n**Examples:**\n• **-7 days**: View prices from 7 days ago\n• **-2 days, 3 hours**: View prices from 2 days and 3 hours ago\n• **-14 days**: View prices from 2 weeks ago",
          "data": {
            "virtual_time_offset_days": "Days Back",
            "time_offset": "Additional Time Offset"
          },
          "data_description": {
            "virtual_time_offset_days": "How many days to travel back in time. Slider range: 0 to 374 days (≈1 year). Recommended: ≥2 days to avoid conflicts with \"yesterday\" entities.",
            "time_offset": "Optional fine-tuning: Add hours and/or minutes to the day offset. The time will be automatically subtracted (travel back further). Note: Seconds are ignored - only minute-level precision is supported."
          }
        },
        "init": {
          "title": "Reconfigure Time Offset",
          "description": "Update the time offset for this time-travel view.",
          "data": {
            "virtual_time_offset_days": "Days Back",
            "time_offset": "Additional Time Offset"
          },
          "data_description": {
            "virtual_time_offset_days": "How many days to travel back in time. Slider range: 0 to 374 days (≈1 year). Recommended: ≥2 days to avoid conflicts with \"yesterday\" entities.",
            "time_offset": "Optional fine-tuning: Add hours and/or minutes to the day offset. The time will be automatically subtracted (travel back further). Note: Seconds are ignored - only minute-level precision is supported."
          }
        }
      },
      "error": {
        "no_time_offset": "At least one time offset value must be negative (historical data only)."
      },
      "abort": {
        "already_configured": "**A time-travel view with this exact time offset already exists.**\n\nPlease choose a different offset.",
        "no_main_entries": "No main configuration entries found. Please add a Tibber home first.",
        "parent_entry_not_found": "Selected configuration entry not found."
      }
    }
  },
  "options": {
    "step": {
      "init": {
        "menu_options": {
          "general_settings": "⚙️ General Settings",
          "display_settings": "💱 Currency Display",
          "current_interval_price_rating": "📊 Price Rating",
          "price_level": "🏷️ Price Level",
          "volatility": "💨 Price Volatility",
          "best_price": "💚 Best Price Period",
          "peak_price": "🔴 Peak Price Period",
          "price_trend": "📈 Price Trend",
          "chart_data_export": "📊 Chart Data Export Sensor",
          "reset_to_defaults": "🔄 Reset to Defaults",
          "finish": "⬅️ Back"
        }
      },
      "general_settings": {
        "title": "⚙️ General Settings",
        "description": "**Configure general settings for Tibber Price Information & Ratings.**\n\n---\n\n**User:** {user_login}",
        "data": {
          "extended_descriptions": "Extended Descriptions",
          "average_sensor_display": "Average Sensor Display"
        },
        "data_description": {
          "extended_descriptions": "Controls whether entity attributes include detailed explanations and usage tips.\n\n• Disabled (default): Brief description only\n• Enabled: Detailed explanation + practical usage examples\n\nExample:\nDisabled = 1 attribute\nEnabled = 2 additional attributes",
          "average_sensor_display": "Choose which statistical measure to display in the sensor state for average price sensors. The other value will be shown as an attribute.\n\n• **Median (default)**: Shows the 'typical' price, resistant to extreme spikes - best for display and human interpretation\n• **Arithmetic Mean**: Shows the true mathematical average including all prices - best when you need exact cost calculations\n\nFor automations, use the attribute `price_mean` or `price_median` to access both values regardless of this setting."
        },
        "submit": "↩ Save & Back"
      },
      "display_settings": {
        "title": "💱 Currency Display Settings",
        "description": "**Configure how electricity prices are displayed - in base currency (€, kr) or subunit (ct, øre).**\n\n---",
        "data": {
          "currency_display_mode": "Display Mode"
        },
        "data_description": {
          "currency_display_mode": "Choose how prices are displayed:\n\n• **Base Currency** (€/kWh, kr/kWh): Decimal values (e.g., 0.25 €/kWh) - differences visible from 3rd-4th decimal place\n• **Subunit Currency** (ct/kWh, øre/kWh): Larger values (e.g., 25.00 ct/kWh) - differences visible from 1st decimal place\n\nDefault depends on your currency:\n• EUR → Subunit (cents) - German/Dutch preference\n• NOK/SEK/DKK → Base (kroner) - Scandinavian preference\n• USD/GBP → Base currency\n\n**💡 Tip:** When selecting Subunit Currency, you can enable the additional \"Current Electricity Price (Energy Dashboard)\" sensor (disabled by default)."
        },
        "submit": "↩ Save & Back"
      },
      "current_interval_price_rating": {
        "title": "📊 Price Rating Settings",
        "description": "**Configure thresholds and stabilization for price rating levels (low/normal/high) based on comparison with trailing 24-hour average.**{entity_warning}",
        "data": {
          "price_rating_threshold_low": "Low Threshold",
          "price_rating_threshold_high": "High Threshold",
          "price_rating_hysteresis": "Hysteresis",
          "price_rating_gap_tolerance": "Gap Tolerance"
        },
        "data_description": {
          "price_rating_threshold_low": "Percentage below the trailing 24-hour average that the current price must be to qualify as 'low' rating. Example: -10 means at least 10% below average. Sensors with this rating indicate favorable time windows. Default: -10%",
          "price_rating_threshold_high": "Percentage above the trailing 24-hour average that the current price must be to qualify as 'high' rating. Example: 10 means at least 10% above average. Sensors with this rating warn about expensive time windows. Default: 10%",
          "price_rating_hysteresis": "Percentage band around thresholds to prevent rapid state changes. When the rating is already LOW, the price must rise above (threshold + hysteresis) to switch to NORMAL. Similarly, HIGH requires the price to fall below (threshold - hysteresis) to leave. This provides stability for automations that react to rating changes. Set to 0 to disable. Default: 2%",
          "price_rating_gap_tolerance": "Maximum number of consecutive intervals that can be 'smoothed out' if they differ from surrounding ratings. Small isolated rating changes are merged into the dominant neighboring block. This provides stability for automations by preventing brief rating spikes from triggering unnecessary actions. Example: 1 means a single 'normal' interval surrounded by 'high' intervals gets corrected to 'high'. Set to 0 to disable. Default: 1"
        },
        "submit": "↩ Save & Back"
      },
      "price_level": {
        "title": "🏷️ Price Level Settings",
        "description": "**Configure stabilization for Tibber's price level classification (very cheap/cheap/normal/expensive/very expensive).**\n\nTibber's API provides a price level field for each interval. This setting smooths out brief fluctuations to prevent automation instability.{entity_warning}",
        "data": {
          "price_level_gap_tolerance": "Gap Tolerance"
        },
        "data_description": {
          "price_level_gap_tolerance": "Maximum number of consecutive intervals that can be 'smoothed out' if they differ from surrounding price levels. Small isolated level changes are merged into the dominant neighboring block. Example: 1 means a single 'normal' interval surrounded by 'cheap' intervals gets corrected to 'cheap'. Set to 0 to disable. Default: 1"
        },
        "submit": "↩ Save & Back"
      },
      "best_price": {
        "title": "💚 Best Price Period Settings",
        "description": "**Configure settings for the Best Price Period binary sensor. This sensor is active during periods with the lowest electricity prices.**{entity_warning}{override_warning}\n\n---",
        "sections": {
          "period_settings": {
            "name": "Period Duration & Levels",
            "description": "Configure how long periods should be and which price levels to include.",
            "data": {
              "best_price_min_period_length": "Minimum Period Length",
              "best_price_max_level": "Price Level Filter",
              "best_price_max_level_gap_count": "Gap Tolerance"
            },
            "data_description": {
              "best_price_min_period_length": "Minimum duration for a period to be considered as 'best price'. Longer periods are more practical for running appliances like dishwashers or heat pumps. Best price periods require 60 minutes minimum (vs. 30 minutes for peak price warnings) because they should provide meaningful time windows for consumption planning, not just brief opportunities.",
              "best_price_max_level": "Only show best price periods if they contain intervals with price levels ≤ selected value. For example, selecting '**Cheap**' means the period must have at least one '**Very cheap**' or '**Cheap**' interval. This ensures 'best price' periods are not just relatively cheap for the day, but actually cheap in absolute terms. Select '**Any**' to show best prices regardless of their absolute price level.",
              "best_price_max_level_gap_count": "Maximum number of consecutive intervals allowed that deviate by exactly one level step from the required level. For example: with '**Cheap**' filter and gap count 1, a sequence '**Cheap**, **Cheap**, **Normal**, **Cheap**' is accepted (**Normal** is one step above **Cheap**). This prevents periods from being split by occasional level deviations. **Note:** Gap tolerance requires periods ≥90 minutes (6 intervals) to detect outliers effectively. Default: 0 (strict filtering, no tolerance)."
            }
          },
          "flexibility_settings": {
            "name": "Flexibility & Thresholds",
            "description": "Control how much prices can deviate and still qualify as 'best price'.",
            "data": {
              "best_price_flex": "Flexibility",
              "best_price_min_distance_from_avg": "Minimum Distance"
            },
            "data_description": {
              "best_price_flex": "Maximum above the daily minimum price that intervals can be and still qualify as 'best price'. Recommended: 15-20 with relaxation enabled (default), or 25-35 without relaxation. Maximum: 50 (hard cap for reliable period detection).",
              "best_price_min_distance_from_avg": "Ensures periods are significantly cheaper than the daily average, not just marginally below it. This filters out noise and prevents marking slightly-below-average periods as 'best price' on days with flat prices. Higher values = stricter filtering (only truly cheap periods qualify). Default: 5 means periods must be at least 5% below the daily average."
            }
          },
          "relaxation_and_target_periods": {
            "name": "Relaxation & Target Periods",
            "description": "Configure automatic filter relaxation and target period counts. Enable 'Achieve Minimum Count' to activate relaxation.",
            "data": {
              "enable_min_periods_best": "Achieve Minimum Count",
              "min_periods_best": "Minimum Periods",
              "relaxation_attempts_best": "Relaxation Attempts"
            },
            "data_description": {
              "enable_min_periods_best": "When enabled, filters will be gradually relaxed if not enough periods are found. This attempts to reach the desired minimum number of periods, which may include less optimal time windows as best-price periods.",
              "min_periods_best": "Minimum number of best price periods to aim for per day. Filters will be relaxed step-by-step to try achieving this count. Only active when 'Achieve Minimum Count' is enabled. Default: 1",
              "relaxation_attempts_best": "How many flex levels (attempts) to try before giving up. Each attempt runs all filter combinations at the new flex level. More attempts increase the chance of finding additional periods at the cost of longer processing time."
            }
          },
          "extension_settings": {
            "name": "Period Edge Extension",
            "description": "Optionally extend detected best price periods at both edges to absorb adjacent very cheap intervals.",
            "data": {
              "best_price_extend_to_very_cheap": "Extend to Very Cheap Intervals",
              "best_price_max_extension_intervals": "Maximum Extension Intervals",
              "best_price_geometric_flex": "Geometric Flex Bonus",
              "best_price_segment_forcing": "W-Shape Segment Forcing",
              "best_price_segment_min_periods": "Periods per Segment"
            },
            "data_description": {
              "best_price_extend_to_very_cheap": "When enabled, detected best price periods expand outward to absorb adjacent intervals with a 'Very cheap' price level. This widens low-price windows to better capture extremely cheap intervals at the edges of detected periods.",
              "best_price_max_extension_intervals": "Maximum number of additional intervals to absorb per side (left and right edge). Each interval is 15 minutes. Example: 4 intervals = up to 1 hour extension per edge. Default: 4",
              "best_price_geometric_flex": "Extra flex percentage applied to intervals that fall inside a detected price valley (V-shape). When a valley pattern is detected for the day, intervals within the valley zone get this additional tolerance, making the period detector more likely to include them. 0 = disabled. Default: 0",
              "best_price_segment_forcing": "When enabled, days with a W-shaped price curve (two valleys separated by a central peak) split at the central peak. Period detection runs independently for each valley side, ensuring each valley has the required number of periods. This prevents both periods from clustering in the same valley. Requires the day pattern sensor to detect a 'double_dip' pattern.",
              "best_price_segment_min_periods": "Minimum number of best price periods required per valley side when W-shape segment forcing is enabled. Each side must independently produce at least this many periods. Default: 1"
            }
          }
        },
        "submit": "↩ Save & Back"
      },
      "peak_price": {
        "title": "🔴 Peak Price Period Settings",
        "description": "**Configure settings for the Peak Price Period binary sensor. This sensor is active during periods with the highest electricity prices.**{entity_warning}{override_warning}\n\n---",
        "sections": {
          "period_settings": {
            "name": "Period Settings",
            "description": "Configure period duration and price level constraints.",
            "data": {
              "peak_price_min_period_length": "Minimum Period Length",
              "peak_price_min_level": "Price Level Filter",
              "peak_price_max_level_gap_count": "Gap Tolerance"
            },
            "data_description": {
              "peak_price_min_period_length": "Minimum duration for a period to be considered as 'peak price'. Peak price warnings are allowed for shorter periods (30 minutes minimum vs. 60 minutes for best price) because brief expensive spikes are worth alerting about, even if they're too short for consumption planning.",
              "peak_price_min_level": "Only show peak price periods if they contain intervals with price levels ≥ selected value. For example, selecting '**Expensive**' means the period must have at least one '**Expensive**' or '**Very expensive**' interval. This ensures 'peak price' periods are not just relatively expensive for the day, but actually expensive in absolute terms. Select '**Any**' to show peak prices regardless of their absolute price level.",
              "peak_price_max_level_gap_count": "Maximum number of consecutive intervals allowed that deviate by exactly one level step from the required level. For example: with '**Expensive**' filter and gap count 2, a sequence '**Expensive**, **Normal**, **Normal**, **Expensive**' is accepted (**Normal** is one step below **Expensive**). This prevents periods from being split by occasional level deviations. **Note:** Gap tolerance requires periods ≥90 minutes (6 intervals) to detect outliers effectively. Default: 0 (strict filtering, no tolerance)."
            }
          },
          "flexibility_settings": {
            "name": "Flexibility Settings",
            "description": "Configure price comparison thresholds and filtering.",
            "data": {
              "peak_price_flex": "Flexibility",
              "peak_price_min_distance_from_avg": "Minimum Distance"
            },
            "data_description": {
              "peak_price_flex": "Maximum below the daily maximum price that intervals can be and still qualify as 'peak price'. Recommended: -15 to -20 with relaxation enabled (default), or -25 to -35 without relaxation. Maximum: -50 (hard cap for reliable period detection). Note: Negative values indicate distance below maximum.",
              "peak_price_min_distance_from_avg": "Ensures periods are significantly more expensive than the daily average, not just marginally above it. This filters out noise and prevents marking slightly-above-average periods as 'peak price' on days with flat prices. Higher values = stricter filtering (only truly expensive periods qualify). Default: 5 means periods must be at least 5% above the daily average."
            }
          },
          "relaxation_and_target_periods": {
            "name": "Relaxation & Target Periods",
            "description": "Configure automatic filter relaxation and target period counts. Enable 'Achieve Minimum Count' to activate relaxation.",
            "data": {
              "enable_min_periods_peak": "Achieve Minimum Count",
              "min_periods_peak": "Minimum Periods",
              "relaxation_attempts_peak": "Relaxation Attempts"
            },
            "data_description": {
              "enable_min_periods_peak": "When enabled, filters will be gradually relaxed if not enough periods are found. This attempts to reach the desired minimum number of periods to ensure you're warned about expensive periods even on days with unusual price patterns.",
              "min_periods_peak": "Minimum number of peak price periods to aim for per day. Filters will be relaxed step-by-step to try achieving this count. Only active when 'Achieve Minimum Count' is enabled. Default: 1",
              "relaxation_attempts_peak": "How many flex levels (attempts) to try before giving up. Each attempt runs all filter combinations at the new flex level. More attempts increase the chance of finding additional peak periods at the cost of longer processing time."
            }
          },
          "extension_settings": {
            "name": "Period Edge Extension",
            "description": "Optionally extend detected peak price periods at both edges to absorb adjacent very expensive intervals.",
            "data": {
              "peak_price_extend_to_very_expensive": "Extend to Very Expensive Intervals",
              "peak_price_max_extension_intervals": "Maximum Extension Intervals",
              "peak_price_geometric_flex": "Geometric Flex Bonus",
              "peak_price_segment_forcing": "M-Shape Segment Forcing",
              "peak_price_segment_min_periods": "Periods per Segment"
            },
            "data_description": {
              "peak_price_extend_to_very_expensive": "When enabled, detected peak price periods expand outward to absorb adjacent intervals with a 'Very expensive' price level. This widens high-price windows to better capture extremely expensive intervals at the edges of detected periods.",
              "peak_price_max_extension_intervals": "Maximum number of additional intervals to absorb per side (left and right edge). Each interval is 15 minutes. Example: 4 intervals = up to 1 hour extension per edge. Default: 4",
              "peak_price_geometric_flex": "Extra flex percentage applied to intervals that fall inside a detected price peak (Λ-shape). When a peak pattern is detected for the day, intervals within the peak zone get this additional tolerance, making the period detector more likely to include them. 0 = disabled. Default: 0",
              "peak_price_segment_forcing": "When enabled, days with an M-shaped price curve (two peaks separated by a central valley) split at the central valley. Period detection runs independently for each peak side, ensuring each peak has the required number of periods. This prevents both periods from clustering in the same peak. Requires the day pattern sensor to detect a 'duck_curve' pattern.",
              "peak_price_segment_min_periods": "Minimum number of peak price periods required per peak side when M-shape segment forcing is enabled. Each side must independently produce at least this many periods. Default: 1"
            }
          }
        },
        "submit": "↩ Save & Back"
      },
      "price_trend": {
        "title": "📈 Price Trend Thresholds",
        "description": "**Configure thresholds for price trend sensors.** These sensors compare current price with the average of the next N hours to determine if prices are rising, falling, or stable.\n\n**5-Level Scale:** Uses strongly_falling (-2), falling (-1), stable (0), rising (+1), strongly_rising (+2) for automation comparisons via trend_value attribute.{entity_warning}",
        "data": {
          "price_trend_threshold_rising": "Rising Threshold",
          "price_trend_threshold_strongly_rising": "Strongly Rising Threshold",
          "price_trend_threshold_falling": "Falling Threshold",
          "price_trend_threshold_strongly_falling": "Strongly Falling Threshold",
          "price_trend_change_confirmation": "Trend Change Confirmation",
          "price_trend_min_price_change": "Min. Price Change (Trend)",
          "price_trend_min_price_change_strongly": "Min. Price Change (Strong Trend)"
        },
        "data_description": {
          "price_trend_threshold_rising": "Percentage that the average of the next N hours must be above the current price to qualify as 'rising' trend. Example: 3 means average is at least 3% higher → prices will rise. Typical values: 3-10%. Default: 3%",
          "price_trend_threshold_strongly_rising": "Percentage for 'strongly rising' trend. Must be higher than rising threshold. Example: 9 means average is at least 9% higher → prices will rise significantly. Typical values: 6-20%. Default: 9%",
          "price_trend_threshold_falling": "Percentage (negative) that the average of the next N hours must be below the current price to qualify as 'falling' trend. Example: -3 means average is at least 3% lower → prices will fall. Typical values: -3 to -10%. Default: -3%",
          "price_trend_threshold_strongly_falling": "Percentage (negative) for 'strongly falling' trend. Must be lower (more negative) than falling threshold. Example: -9 means average is at least 9% lower → prices will fall significantly. Typical values: -6 to -20%. Default: -9%",
          "price_trend_change_confirmation": "Number of consecutive 15-minute intervals that must confirm a new trend direction before reporting a trend change. Higher values mean more stability and fewer false changes, lower values mean faster detection. Range: 2 (30 min) to 6 (90 min). Default: 3 (45 min)",
          "price_trend_min_price_change": "Minimum absolute price difference (in ct/øre) required for a 'rising' or 'falling' trend. Prevents tiny price changes from triggering trends at low price levels. Set to 0 to disable (pure percentage mode). Default: 0.5",
          "price_trend_min_price_change_strongly": "Minimum absolute price difference (in ct/øre) required for a 'strongly rising' or 'strongly falling' trend. Should be higher than the regular trend minimum. Set to 0 to disable. Default: 1.5"
        },
        "submit": "↩ Save & Back"
      },
      "volatility": {
        "title": "💨 Price Volatility Thresholds",
        "description": "**Configure thresholds for volatility classification.** Volatility measures relative price variation using the coefficient of variation (CV = standard deviation / mean × 100%). These thresholds are percentage values that work across all price levels.\n\nUsed by:\n• Volatility sensors (classification)\n• Trend sensors (adaptive threshold adjustment: &lt;moderate = more sensitive, ≥high = less sensitive){entity_warning}",
        "data": {
          "volatility_threshold_moderate": "Moderate Threshold",
          "volatility_threshold_high": "High Threshold",
          "volatility_threshold_very_high": "Very High Threshold"
        },
        "data_description": {
          "volatility_threshold_moderate": "Coefficient of Variation (CV) at which prices are considered 'moderately volatile'. CV = (standard deviation / mean) × 100%. Example: 15 means price fluctuations of ±15% around average. Sensors show this classification, trend sensors become more sensitive. Default: 15%",
          "volatility_threshold_high": "Coefficient of Variation (CV) at which prices are considered 'highly volatile'. Example: 30 means price fluctuations of ±30% around average. Larger price jumps expected, trend sensors become less sensitive. Default: 30%",
          "volatility_threshold_very_high": "Coefficient of Variation (CV) at which prices are considered 'very highly volatile'. Example: 50 means extreme price fluctuations of ±50% around average. On such days, strong price spikes are likely. Default: 50%"
        },
        "submit": "↩ Save & Back"
      },
      "chart_data_export": {
        "title": "📊 Chart Data Export Sensor",
        "description": "The Chart Data Export Sensor provides price data as sensor attributes.\n\n⚠️ **Note:** This sensor is a legacy feature for compatibility with older tools.\n\n**Recommended for new setups:** Use the `tibber_prices.get_chartdata` **service directly** - it's more flexible, efficient, and the modern Home Assistant approach.\n\n**When this sensor makes sense:**\n\n✅ Your dashboard tool can **only** read attributes (no service calls)\n✅ You need static data that updates automatically\n❌ **Not for automations:** Use `tibber_prices.get_chartdata` directly there - more flexible and efficient!\n\n---\n\n{sensor_status_info}",
        "submit": "↩ Ok & Back"
      },
      "reset_to_defaults": {
        "title": "🔄 Reset to Defaults",
        "description": "⚠️ **Warning:** This will reset **ALL** settings to factory defaults.\n\n**What will be reset:**\n• All price rating thresholds\n• All volatility thresholds\n• All price trend thresholds\n• All best price period settings\n• All peak price period settings\n• Display settings\n• General settings\n\n**What will NOT be reset:**\n• Your Tibber API token\n• Selected home\n• Currency\n\n**💡 Tip:** This is useful if you want to start fresh after experimenting with settings.",
        "data": {
          "confirm_reset": "Yes, reset everything to defaults"
        },
        "submit": "Reset Now"
      }
    },
    "error": {
      "auth": "The Tibber Access Token is invalid.",
      "connection": "Unable to connect to Tibber. Please check your internet connection.",
      "unknown": "An unexpected error occurred. Please check the logs for details.",
      "cannot_connect": "Failed to connect",
      "invalid_access_token": "Invalid access token",
      "different_home": "The access token is not valid for the home ID this integration is configured for.",
      "invalid_period_length": "Period length must be at least 15 minutes (multiples of 15).",
      "invalid_flex": "Flexibility percentage must be between -50% and +50%",
      "invalid_best_price_distance": "Distance percentage must be between -50% and 0% (negative = below average)",
      "invalid_peak_price_distance": "Distance percentage must be between 0% and 50% (positive = above average)",
      "invalid_min_periods": "Minimum periods count must be between 1 and 10",
      "invalid_gap_count": "Gap count must be between 0 and 8",
      "invalid_relaxation_attempts": "Relaxation attempts must be between 1 and 12",
      "invalid_price_rating_low": "Low price rating threshold must be between -50% and -5%",
      "invalid_price_rating_high": "High price rating threshold must be between 5% and 50%",
      "invalid_price_rating_thresholds": "Low threshold must be less than high threshold",
      "invalid_volatility_threshold_moderate": "Moderate volatility threshold must be between 5% and 25%",
      "invalid_volatility_threshold_high": "High volatility threshold must be between 20% and 40%",
      "invalid_volatility_threshold_very_high": "Very high volatility threshold must be between 35% and 80%",
      "invalid_volatility_thresholds": "Thresholds must be in ascending order: moderate < high < very high",
      "invalid_price_trend_rising": "Rising trend threshold must be between 1% and 50%",
      "invalid_price_trend_falling": "Falling trend threshold must be between -50% and -1%",
      "invalid_price_trend_strongly_rising": "Strongly rising trend threshold must be between 2% and 100%",
      "invalid_price_trend_strongly_falling": "Strongly falling trend threshold must be between -100% and -2%",
      "invalid_trend_strongly_rising_less_than_rising": "Strongly rising threshold must be greater than rising threshold",
      "invalid_trend_strongly_falling_greater_than_falling": "Strongly falling threshold must be less (more negative) than falling threshold"
    },
    "abort": {
      "entry_not_found": "Tibber configuration entry not found.",
      "reset_cancelled": "Reset cancelled. No changes were made to your configuration.",
      "reset_successful": "✅ All settings have been reset to factory defaults. Your configuration is now like a fresh installation.",
      "finished": "Configuration completed."
    }
  },
  "entity": {
    "sensor": {
      "current_interval_price": {
        "name": "Current Electricity Price"
      },
      "current_interval_price_base": {
        "name": "Current Electricity Price (Energy Dashboard)"
      },
      "next_interval_price": {
        "name": "Next Electricity Price"
      },
      "previous_interval_price": {
        "name": "Previous Electricity Price"
      },
      "current_hour_average_price": {
        "name": "⌀ Hourly Price Current"
      },
      "next_hour_average_price": {
        "name": "⌀ Hourly Price Next"
      },
      "current_interval_price_level": {
        "name": "Current Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "next_interval_price_level": {
        "name": "Next Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "previous_interval_price_level": {
        "name": "Previous Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "current_hour_price_level": {
        "name": "Current Hour Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "next_hour_price_level": {
        "name": "Next Hour Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "lowest_price_today": {
        "name": "Today's Lowest Price"
      },
      "highest_price_today": {
        "name": "Today's Highest Price"
      },
      "average_price_today": {
        "name": "⌀ Price Today"
      },
      "lowest_price_tomorrow": {
        "name": "Tomorrow's Lowest Price"
      },
      "highest_price_tomorrow": {
        "name": "Tomorrow's Highest Price"
      },
      "average_price_tomorrow": {
        "name": "⌀ Price Tomorrow"
      },
      "yesterday_price_level": {
        "name": "Yesterday's Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "today_price_level": {
        "name": "Today's Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "tomorrow_price_level": {
        "name": "Tomorrow's Price Level",
        "state": {
          "very_cheap": "Very Cheap",
          "cheap": "Cheap",
          "normal": "Normal",
          "expensive": "Expensive",
          "very_expensive": "Very Expensive"
        }
      },
      "yesterday_price_rating": {
        "name": "Yesterday's Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "today_price_rating": {
        "name": "Today's Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "tomorrow_price_rating": {
        "name": "Tomorrow's Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "trailing_price_average": {
        "name": "⌀ Price Trailing 24h"
      },
      "leading_price_average": {
        "name": "⌀ Price Leading 24h"
      },
      "trailing_price_min": {
        "name": "Trailing 24h Minimum Price"
      },
      "trailing_price_max": {
        "name": "Trailing 24h Maximum Price"
      },
      "leading_price_min": {
        "name": "Leading 24h Minimum Price"
      },
      "leading_price_max": {
        "name": "Leading 24h Maximum Price"
      },
      "current_interval_price_rating": {
        "name": "Current Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "next_interval_price_rating": {
        "name": "Next Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "previous_interval_price_rating": {
        "name": "Previous Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "current_hour_price_rating": {
        "name": "Current Hour Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "next_hour_price_rating": {
        "name": "Next Hour Price Rating",
        "state": {
          "low": "Low",
          "normal": "Normal",
          "high": "High"
        }
      },
      "next_avg_1h": {
        "name": "⌀ Price Next 1h"
      },
      "next_avg_2h": {
        "name": "⌀ Price Next 2h"
      },
      "next_avg_3h": {
        "name": "⌀ Price Next 3h"
      },
      "next_avg_4h": {
        "name": "⌀ Price Next 4h"
      },
      "next_avg_5h": {
        "name": "⌀ Price Next 5h"
      },
      "next_avg_6h": {
        "name": "⌀ Price Next 6h"
      },
      "next_avg_8h": {
        "name": "⌀ Price Next 8h"
      },
      "next_avg_12h": {
        "name": "⌀ Price Next 12h"
      },
      "price_outlook_1h": {
        "name": "Price Outlook (1h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_outlook_2h": {
        "name": "Price Outlook (2h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_outlook_3h": {
        "name": "Price Outlook (3h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_outlook_4h": {
        "name": "Price Outlook (4h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_outlook_5h": {
        "name": "Price Outlook (5h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_outlook_6h": {
        "name": "Price Outlook (6h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_outlook_8h": {
        "name": "Price Outlook (8h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_outlook_12h": {
        "name": "Price Outlook (12h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_trajectory_2h": {
        "name": "Price Trajectory (2h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_trajectory_3h": {
        "name": "Price Trajectory (3h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_trajectory_4h": {
        "name": "Price Trajectory (4h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_trajectory_5h": {
        "name": "Price Trajectory (5h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_trajectory_6h": {
        "name": "Price Trajectory (6h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_trajectory_8h": {
        "name": "Price Trajectory (8h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "price_trajectory_12h": {
        "name": "Price Trajectory (12h)",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "current_price_trend": {
        "name": "Current Price Trend",
        "state": {
          "strongly_rising": "Strongly Rising",
          "rising": "Rising",
          "stable": "Stable",
          "falling": "Falling",
          "strongly_falling": "Strongly Falling"
        }
      },
      "next_price_trend_change": {
        "name": "Next Price Trend Change"
      },
      "next_price_trend_change_in": {
        "name": "Next Price Trend Change In"
      },
      "daily_rating": {
        "name": "Daily Price Rating"
      },
      "monthly_rating": {
        "name": "Monthly Price Rating"
      },
      "data_lifecycle_status": {
        "name": "Data Lifecycle Status",
        "state": {
          "cached": "Cached",
          "fresh": "Fresh",
          "refreshing": "Refreshing",
          "searching_tomorrow": "Searching Tomorrow",
          "turnover_pending": "Turnover Pending",
          "error": "Error"
        }
      },
      "today_volatility": {
        "name": "Today's Price Volatility",
        "state": {
          "low": "Low",
          "moderate": "Moderate",
          "high": "High",
          "very_high": "Very High"
        }
      },
      "tomorrow_volatility": {
        "name": "Tomorrow's Price Volatility",
        "state": {
          "low": "Low",
          "moderate": "Moderate",
          "high": "High",
          "very_high": "Very High"
        }
      },
      "next_24h_volatility": {
        "name": "Next 24h Price Volatility",
        "state": {
          "low": "Low",
          "moderate": "Moderate",
          "high": "High",
          "very_high": "Very High"
        }
      },
      "today_tomorrow_volatility": {
        "name": "Today+Tomorrow Price Volatility",
        "state": {
          "low": "Low",
          "moderate": "Moderate",
          "high": "High",
          "very_high": "Very High"
        }
      },
      "best_price_end_time": {
        "name": "Best Price End"
      },
      "best_price_period_duration": {
        "name": "Best Price Duration"
      },
      "best_price_remaining_minutes": {
        "name": "Best Price Remaining Time"
      },
      "best_price_progress": {
        "name": "Best Price Progress"
      },
      "best_price_next_start_time": {
        "name": "Best Price Start"
      },
      "best_price_next_in_minutes": {
        "name": "Best Price Starts In"
      },
      "peak_price_end_time": {
        "name": "Peak Price End"
      },
      "peak_price_period_duration": {
        "name": "Peak Price Duration"
      },
      "peak_price_remaining_minutes": {
        "name": "Peak Price Remaining Time"
      },
      "peak_price_progress": {
        "name": "Peak Price Progress"
      },
      "peak_price_next_start_time": {
        "name": "Peak Price Start"
      },
      "peak_price_next_in_minutes": {
        "name": "Peak Price Starts In"
      },
      "home_type": {
        "name": "Home Type",
        "state": {
          "apartment": "Apartment",
          "rowhouse": "Rowhouse",
          "house": "House",
          "cottage": "Cottage"
        }
      },
      "home_size": {
        "name": "Home Size"
      },
      "main_fuse_size": {
        "name": "Main Fuse Size"
      },
      "number_of_residents": {
        "name": "Number of Residents"
      },
      "primary_heating_source": {
        "name": "Primary Heating Source",
        "state": {
          "air2air_heatpump": "Air-to-Air Heat Pump",
          "air2water_heatpump": "Air-to-Water Heat Pump",
          "boiler": "Boiler",
          "central_heating": "Central Heating",
          "district_heating": "District Heating",
          "district": "District Heating",
          "electric_boiler": "Electric Boiler",
          "electricity": "Electricity",
          "floor": "Floor Heating",
          "gas": "Gas",
          "ground_heatpump": "Ground Heat Pump",
          "ground": "Ground Heat Pump",
          "oil": "Oil",
          "other": "Other",
          "waste": "Waste Heat"
        }
      },
      "grid_company": {
        "name": "Grid Company"
      },
      "grid_area_code": {
        "name": "Grid Area Code"
      },
      "price_area_code": {
        "name": "Price Area Code"
      },
      "consumption_ean": {
        "name": "Consumption EAN"
      },
      "production_ean": {
        "name": "Production EAN"
      },
      "energy_tax_type": {
        "name": "Energy Tax Type"
      },
      "vat_type": {
        "name": "VAT Type"
      },
      "estimated_annual_consumption": {
        "name": "Estimated Annual Consumption"
      },
      "subscription_status": {
        "name": "Subscription Status",
        "state": {
          "running": "Running",
          "ended": "Ended",
          "pending": "Pending",
          "unknown": "Unknown"
        }
      },
      "day_pattern_yesterday": {
        "name": "Yesterday's Price Pattern",
        "state": {
          "valley": "Valley",
          "peak": "Peak",
          "double_dip": "Double Dip",
          "duck_curve": "Duck Curve",
          "flat": "Flat",
          "rising": "Rising",
          "falling": "Falling",
          "mixed": "Mixed"
        }
      },
      "day_pattern_today": {
        "name": "Today's Price Pattern",
        "state": {
          "valley": "Valley",
          "peak": "Peak",
          "double_dip": "Double Dip",
          "duck_curve": "Duck Curve",
          "flat": "Flat",
          "rising": "Rising",
          "falling": "Falling",
          "mixed": "Mixed"
        }
      },
      "day_pattern_tomorrow": {
        "name": "Tomorrow's Price Pattern",
        "state": {
          "valley": "Valley",
          "peak": "Peak",
          "double_dip": "Double Dip",
          "duck_curve": "Duck Curve",
          "flat": "Flat",
          "rising": "Rising",
          "falling": "Falling",
          "mixed": "Mixed"
        }
      },
      "current_price_phase": {
        "name": "Current Price Phase",
        "state": {
          "rising": "Rising",
          "falling": "Falling",
          "flat": "Flat"
        }
      },
      "next_price_phase": {
        "name": "Next Price Phase",
        "state": {
          "rising": "Rising",
          "falling": "Falling",
          "flat": "Flat"
        }
      },
      "current_price_phase_end_time": {
        "name": "Current Phase End Time"
      },
      "current_price_phase_remaining_minutes": {
        "name": "Current Phase Remaining"
      },
      "current_price_phase_duration": {
        "name": "Current Phase Duration"
      },
      "current_price_phase_progress": {
        "name": "Current Phase Progress"
      },
      "next_rising_phase_start_time": {
        "name": "Next Rising Phase Start"
      },
      "next_falling_phase_start_time": {
        "name": "Next Falling Phase Start"
      },
      "next_flat_phase_start_time": {
        "name": "Next Flat Phase Start"
      },
      "next_rising_phase_in_minutes": {
        "name": "Time to Next Rising Phase"
      },
      "next_falling_phase_in_minutes": {
        "name": "Time to Next Falling Phase"
      },
      "next_flat_phase_in_minutes": {
        "name": "Time to Next Flat Phase"
      },
      "chart_data_export": {
        "name": "Chart Data Export",
        "state": {
          "pending": "Pending",
          "ready": "Ready",
          "error": "Error"
        }
      },
      "chart_metadata": {
        "name": "Chart Metadata",
        "state": {
          "pending": "Pending",
          "ready": "Ready",
          "error": "Error"
        }
      },
      "current_interval_price_rank_today": {
        "name": "Current Price Rank (Today)"
      },
      "current_interval_price_rank_tomorrow": {
        "name": "Current Price Rank (Tomorrow)"
      },
      "current_interval_price_rank_today_tomorrow": {
        "name": "Current Price Rank (Today+Tomorrow)"
      },
      "next_interval_price_rank_today": {
        "name": "Next Price Rank (Today)"
      },
      "next_interval_price_rank_today_tomorrow": {
        "name": "Next Price Rank (Today+Tomorrow)"
      },
      "previous_interval_price_rank_today": {
        "name": "Previous Price Rank (Today)"
      },
      "previous_interval_price_rank_today_tomorrow": {
        "name": "Previous Price Rank (Today+Tomorrow)"
      },
      "current_hour_price_rank_today": {
        "name": "⌀ Hourly Price Current Rank (Today)"
      },
      "current_hour_price_rank_today_tomorrow": {
        "name": "⌀ Hourly Price Current Rank (Today+Tomorrow)"
      },
      "next_hour_price_rank_today": {
        "name": "⌀ Hourly Price Next Rank (Today)"
      },
      "next_hour_price_rank_today_tomorrow": {
        "name": "⌀ Hourly Price Next Rank (Today+Tomorrow)"
      }
    },
    "binary_sensor": {
      "peak_price_period": {
        "name": "Peak Price Period"
      },
      "best_price_period": {
        "name": "Best Price Period"
      },
      "in_rising_price_phase": {
        "name": "In Rising Price Phase"
      },
      "in_falling_price_phase": {
        "name": "In Falling Price Phase"
      },
      "in_flat_price_phase": {
        "name": "In Flat Price Phase"
      },
      "connection": {
        "name": "Tibber API Connection"
      },
      "tomorrow_data_available": {
        "name": "Tomorrow's Data Available"
      },
      "has_ventilation_system": {
        "name": "Has Ventilation System"
      },
      "realtime_consumption_enabled": {
        "name": "Realtime Consumption Enabled"
      }
    },
    "number": {
      "best_price_flex_override": {
        "name": "Best Price: Flexibility"
      },
      "best_price_min_distance_override": {
        "name": "Best Price: Minimum Distance"
      },
      "best_price_min_period_length_override": {
        "name": "Best Price: Minimum Period Length"
      },
      "best_price_min_periods_override": {
        "name": "Best Price: Minimum Periods"
      },
      "best_price_relaxation_attempts_override": {
        "name": "Best Price: Relaxation Attempts"
      },
      "best_price_gap_count_override": {
        "name": "Best Price: Gap Tolerance"
      },
      "peak_price_flex_override": {
        "name": "Peak Price: Flexibility"
      },
      "peak_price_min_distance_override": {
        "name": "Peak Price: Minimum Distance"
      },
      "peak_price_min_period_length_override": {
        "name": "Peak Price: Minimum Period Length"
      },
      "peak_price_min_periods_override": {
        "name": "Peak Price: Minimum Periods"
      },
      "peak_price_relaxation_attempts_override": {
        "name": "Peak Price: Relaxation Attempts"
      },
      "peak_price_gap_count_override": {
        "name": "Peak Price: Gap Tolerance"
      }
    },
    "switch": {
      "best_price_enable_relaxation_override": {
        "name": "Best Price: Achieve Minimum Count"
      },
      "peak_price_enable_relaxation_override": {
        "name": "Peak Price: Achieve Minimum Count"
      }
    }
  },
  "issues": {
    "new_homes_available": {
      "title": "New Tibber homes detected",
      "description": "We detected {count} new home(s) on your Tibber account: {homes}. You can add them to Home Assistant through the Tibber integration configuration."
    },
    "homes_removed": {
      "title": "Tibber homes removed",
      "description": "We detected that {count} home(s) have been removed from your Tibber account: {homes}. Please review your Tibber integration configuration."
    },
    "tomorrow_data_missing": {
      "title": "Tomorrow's price data missing for {home_name}",
      "description": "Tomorrow's electricity price data is still unavailable after {warning_hour}:00. This is unusual, as Tibber typically publishes tomorrow's prices in the afternoon (around 13:00-14:00 CET).\n\nPossible causes:\n- Tibber has not yet published tomorrow's prices\n- Temporary API issues\n- Your electricity provider has not submitted prices to Tibber\n\nThis issue will automatically resolve once tomorrow's data becomes available. If this persists beyond 20:00, please check the Tibber app or contact Tibber support."
    },
    "rate_limit_exceeded": {
      "title": "API rate limit exceeded for {home_name}",
      "description": "The Tibber API has rate-limited this integration after {error_count} consecutive errors. This means requests are being made too frequently.\n\nThe integration will automatically retry with increasing delays. This issue will resolve once the rate limit expires.\n\nIf this persists for several hours, consider:\n- Checking if multiple Home Assistant instances are using the same API token\n- Verifying no other applications are heavily using your Tibber API token\n- Reducing the update frequency if you've customized it"
    },
    "home_not_found": {
      "title": "Home {home_name} not found in Tibber account",
      "description": "The home configured in this integration (entry ID: {entry_id}) is no longer available in your Tibber account. This typically happens when:\n- The home was deleted from your Tibber account\n- The home was moved to a different Tibber account\n- Access to this home was revoked\n\nPlease remove this integration entry and re-add it if the home should still be monitored. To remove this entry, go to Settings → Devices & Services → Tibber Prices and delete the {home_name} configuration."
    },
    "entity_migration": {
      "title": "Tibber Prices: Action required after update ({home_name})",
      "description": "This update includes breaking changes that were applied automatically.\n\n**Renamed Entities ({count})**\n\nThe following entity keys were renamed. Your existing entity IDs and automations remain intact:\n\n{entity_list}\n\n**Duration Sensor Value Change**\n\nAll duration sensors (remaining time, starts in, period duration, trend change countdown) now report their state value in **minutes** instead of hours. The display unit in dashboards remains hours by default.\n\nIf you have automations using numeric comparisons on these sensors, update your thresholds:\n- Old: `state < 0.25` (15 minutes as hours)\n- New: `state < 15` (15 minutes)\n\nDismiss this notice after reviewing your automations."
    },
    "currency_display_mode_changed": {
      "title": "Currency display unit changed for {home_name}",
      "description": "You changed the currency display mode for **{home_name}**. All price sensor values and attributes now use the new unit (e.g. 25.34 ct → 0.2534 € or vice versa).\n\nHome Assistant’s Recorder will separately show a **“The unit has changed”** dialog for affected sensors — this may take a few minutes or until the next statistics run (log warnings appear earlier). When it appears, choose **Delete all old statistic data** to start fresh. Do not choose “Update the unit without converting”: that re-labels the old numbers without adjusting their values, making the historic data factually incorrect.\n\n**Review manually:**\n\n1. **Automations & Templates:** Update all automations and template sensors that use numeric price thresholds.\n2. **Dashboard Cards:** Update any cards with hardcoded thresholds or unit labels.\n\nDismiss this notice once you have reviewed your automations, dashboards, and statistics."
    }
  },
  "exceptions": {
    "no_entries_found": {
      "message": "No Tibber Prices integration entries found. Please set up the integration first."
    },
    "multiple_entries_no_entry_id": {
      "message": "Multiple Tibber Prices entries found. Please specify 'entry_id' to select which entry to use."
    },
    "invalid_entry_id": {
      "message": "Invalid or unavailable config entry. Please check the entry ID and ensure the integration is loaded."
    },
    "missing_home_id": {
      "message": "Home ID not found in the config entry. Please reconfigure the integration."
    },
    "user_data_not_available": {
      "message": "User data is not yet available. Please wait for the first data update to complete."
    },
    "timezone_not_found": {
      "message": "Could not determine the home timezone. Please verify the home configuration in your Tibber account."
    },
    "end_before_start": {
      "message": "End time ({search_end}) must be after start time ({search_start}). Check your time parameters and any day offsets."
    },
    "price_fetch_failed": {
      "message": "Unable to fetch price data for the requested search range."
    },
    "invalid_search_scope": {
      "message": "Invalid search scope value. Valid scopes are: today, tomorrow, remaining_today, next_24h, next_48h."
    },
    "scope_conflicts_with_range": {
      "message": "search_scope cannot be combined with explicit range parameters: {params}. Use either search_scope OR explicit start/end parameters."
    },
    "day_offset_requires_time": {
      "message": "{offset_param} requires {time_param} to be set. Day offset only modifies the date of an explicit time parameter."
    },
    "min_level_exceeds_max": {
      "message": "min_price_level {min_level} is higher than max_price_level {max_level}. The minimum level must be equal to or lower than the maximum level."
    },
    "power_profile_length_mismatch": {
      "message": "power_profile has {profile_length} entries but the duration requires {interval_count} intervals ({duration_minutes} minutes). The power_profile must have exactly one entry per 15-minute interval."
    },
    "level_and_rating_filter_conflict": {
      "message": "level_filter and rating_level_filter cannot be used together. Use only one filter type per request."
    },
    "insert_nulls_requires_filter": {
      "message": "insert_nulls mode {mode} requires a level_filter, rating_level_filter, or period_filter to define segments. Without a filter, use insert_nulls: none."
    },
    "connect_segments_requires_segments_mode": {
      "message": "connect_segments requires insert_nulls to be set to 'segments'. Set insert_nulls: segments to use segment connection."
    },
    "array_fields_requires_array_format": {
      "message": "array_fields can only be used with output_format: array_of_arrays. Change the output format or remove array_fields."
    },
    "invalid_array_fields": {
      "message": "The array_fields value {template} is invalid. Field names must be wrapped in curly braces, e.g. '{start_time}, {price_per_kwh}, {level}'."
    },
    "min_segment_exceeds_duration": {
      "message": "min_segment_duration ({min_segment_minutes} min) cannot exceed the total duration ({duration_minutes} min). Reduce min_segment_duration or increase duration."
    },
    "start_time_conflict": {
      "message": "search_start and search_start_time both specify the start time — use only one. Choose search_start for an exact datetime or search_start_time for a time of day."
    },
    "end_time_conflict": {
      "message": "search_end and search_end_time both specify the end time — use only one. Choose search_end for an exact datetime or search_end_time for a time of day."
    },
    "insert_nulls_all_with_period_filter": {
      "message": "insert_nulls: all is not supported with period_filter. Use insert_nulls: segments instead — this adds gaps between separate periods in the chart."
    },
    "connect_segments_with_period_filter": {
      "message": "connect_segments cannot be used with period_filter. Periods are already contiguous — connect_segments only has effect with level_filter or rating_level_filter."
    },
    "duplicate_task_names": {
      "message": "Task names must be unique. Duplicate: {names}. Give each task a different name so the results can be matched to the correct task."
    },
    "tasks_exceed_search_window": {
      "message": "Total task time including gaps ({total_minutes} min) exceeds the search window ({window_minutes} min). Reduce task durations, lower gap_minutes, or extend the search range."
    },
    "must_finish_by_conflicts_with_end": {
      "message": "must_finish_by cannot be combined with end-boundary parameters ({params}). Use must_finish_by alone — it sets the search end to the deadline automatically."
    },
    "invalid_entity_reference": {
      "message": "'{reference}' is not a valid entity reference. Use the format 'domain.entity_id' or 'domain.entity_id@attribute'."
    },
    "entity_not_found": {
      "message": "Entity '{entity_id}' not found. Verify the entity exists and is available."
    },
    "entity_attribute_not_found": {
      "message": "Entity '{entity_id}' does not have attribute '{attribute}'."
    },
    "entity_state_unavailable": {
      "message": "Entity '{entity_id}' state is '{state}'. The entity must have a valid state value."
    },
    "entity_value_conversion_failed": {
      "message": "Cannot convert value '{raw_value}' from '{entity_id}' ({attribute}) to {expected_type}. Verify the entity provides a compatible value."
    },
    "capacity_required_for_percent": {
      "message": "battery_capacity_kwh is required when current or target SoC is provided as a percentage."
    },
    "ambiguous_soc_input": {
      "message": "The field {field} was provided both as percent and as kWh. Use only one representation."
    },
    "already_at_target": {
      "message": "Current state of charge is already at or above the target. No charging schedule is needed."
    },
    "target_exceeds_capacity": {
      "message": "Target SoC ({target_soc_kwh} kWh) exceeds battery capacity ({capacity_kwh} kWh)."
    },
    "energy_unreachable": {
      "message": "The requested charging target cannot be reached within the available search window and charging constraints."
    },
    "missing_current_soc": {
      "message": "Provide either current_soc_percent or current_soc_kwh."
    },
    "missing_target_soc": {
      "message": "Provide either target_soc_percent or target_soc_kwh."
    },
    "missing_deadline_for_must_reach": {
      "message": "Provide must_reach_by or must_reach_by_event when using must_reach_soc_percent or must_reach_soc_kwh."
    },
    "missing_must_reach_soc": {
      "message": "Provide must_reach_soc_percent or must_reach_soc_kwh when using a must_reach deadline."
    },
    "invalid_must_reach_soc": {
      "message": "The minimum state of charge by deadline must be between current and target state of charge."
    },
    "power_strategy_conflict": {
      "message": "Use either min_charge_power_w or charge_power_steps_w, not both at the same time."
    },
    "grid_limit_too_low": {
      "message": "grid_import_limit_w is lower than the minimum required charging power."
    },
    "deadline_conflict": {
      "message": "Use either must_reach_by or must_reach_by_event, not both at the same time."
    },
    "deadline_event_not_available": {
      "message": "The selected deadline event is not available in the current coordinator data."
    },
    "deadline_outside_search_range": {
      "message": "The resolved deadline must be inside the selected search range."
    }
  },
  "services": {
    "get_price": {
      "name": "Get Price Data",
      "description": "Fetch price data for a specific time range with automatic routing. Development and testing service for the price_info_for_range API function. Automatically uses PRICE_INFO, PRICE_INFO_RANGE, or both based on the time range boundary.",
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "start_time": {
          "name": "Start Time",
          "description": "Start of the time range (inclusive, timezone-aware)."
        },
        "end_time": {
          "name": "End Time",
          "description": "End of the time range (exclusive, timezone-aware)."
        }
      }
    },
    "get_apexcharts_yaml": {
      "name": "Get ApexCharts Card YAML",
      "description": "⚠️ IMPORTANT: This service generates a BASIC EXAMPLE configuration for ApexCharts Card as a starting point. It is NOT a complete solution for all ApexCharts features. This integration is primarily a DATA PROVIDER. The generated YAML demonstrates how to use the `get_chartdata` service to fetch price data. Due to the segmented nature of our data (different time periods per series) and the use of Home Assistant's service API instead of entity attributes, many advanced ApexCharts features (like in_header, certain transformations) are not compatible or require manual customization. You are welcome to customize the generated YAML for your specific needs, but please understand that comprehensive ApexCharts configuration support is beyond the scope of this integration. Community contributions with improved configurations are always appreciated - if you find a better setup that works, please share it so everyone can benefit! For direct data access to build your own charts, use the `get_chartdata` service instead.",
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "day": {
          "name": "Day",
          "description": "Which day to visualize (default: Rolling Window). Fixed day options (Yesterday/Today/Tomorrow) show 24h spans without additional dependencies. Dynamic options require config-template-card: Rolling Window displays a fixed 48h window that automatically shifts between yesterday+today and today+tomorrow based on data availability. Rolling Window (Auto-Zoom) behaves the same but additionally auto-zooms in (2h lookback + remaining time until midnight, graph_span decreases every 15 minutes)."
        },
        "level_type": {
          "name": "Level Type",
          "description": "Select which price level classification to visualize: 'rating_level' (low/normal/high based on your configured thresholds) or 'level' (Tibber API levels: very cheap/cheap/normal/expensive/very expensive)."
        },
        "highlight_best_price": {
          "name": "Highlight Best Price Periods",
          "description": "Add a semi-transparent green overlay to highlight the best price periods on the chart. This makes it easy to visually identify the optimal times for energy consumption."
        },
        "highlight_peak_price": {
          "name": "Highlight Peak Price Periods",
          "description": "Add a semi-transparent red overlay to highlight the peak price periods on the chart. This makes it easy to visually identify times when energy is most expensive."
        },
        "resolution": {
          "name": "Resolution",
          "description": "Time resolution for the chart data. 'interval' (default): Original 15-minute intervals (96 points per day). 'hourly': Aggregated hourly values using a rolling 60-minute window (24 points per day) for a cleaner, less cluttered chart."
        }
      }
    },
    "get_chartdata": {
      "name": "Get Chart Data",
      "description": "Returns price data in a simple chart-friendly format compatible with the Tibber Core integration output structure. Perfect for use with popular chart cards like ha-price-timeline-card, ApexCharts Card, Plotly Graph Card, Mini Graph Card, or the built-in History Graph Card. Field names and data structure can be customized to match your specific chart requirements.",
      "sections": {
        "general": {
          "name": "General",
          "description": "General settings for fetching chart data."
        },
        "selection": {
          "name": "Selection",
          "description": "Select which data to include in the output."
        },
        "filters": {
          "name": "Filters",
          "description": "Filter data based on price levels, rating levels, or special periods."
        },
        "transformation": {
          "name": "Transform Data",
          "description": "Transform the data output for better chart compatibility."
        },
        "format": {
          "name": "Format",
          "description": "Customize the output format."
        },
        "arrays_of_arrays": {
          "name": "Advanced Output Settings: Array of Arrays",
          "description": "Settings for output format when using an array of arrays."
        },
        "arrays_of_objects": {
          "name": "Advanced Output Settings: Array of Objects",
          "description": "Settings for output format when using an array of objects."
        }
      },
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "day": {
          "name": "Day",
          "description": "Which day(s) to fetch prices for. You can select multiple days. If not specified, returns a rolling 2-day window: today+tomorrow (when tomorrow data is available) or yesterday+today (when tomorrow data is not yet available). This provides continuous chart display without gaps."
        },
        "resolution": {
          "name": "Resolution",
          "description": "Time resolution for the returned data. Options: 'interval' (default, 15-minute intervals, 96 points per day), 'hourly' (hourly averages, 24 points per day)."
        },
        "output_format": {
          "name": "Output Format",
          "description": "Output format for the returned data. Options: 'array_of_objects' (default, array of objects with customizable field names), 'array_of_arrays' (array of [timestamp, price] arrays with trailing null point for stepline charts)."
        },
        "array_fields": {
          "name": "Array Fields",
          "description": "Define which fields to include. Use field names in curly braces, separated by commas. Available fields: start_time, price_per_kwh, level, rating_level, average. Fields will be automatically enabled even if include_* options are not set. Leave empty for default (timestamp and price only)."
        },
        "subunit_currency": {
          "name": "Subunit Currency",
          "description": "Return prices in subunit currency units (cents for EUR, øre for NOK/SEK) instead of base currency units. Disabled by default."
        },
        "round_decimals": {
          "name": "Round Decimals",
          "description": "Number of decimal places to round prices to (0-10). If not specified, uses default precision (4 decimals for base currency, 2 for subunit currency)."
        },
        "data_key": {
          "name": "Data Key",
          "description": "Custom name for the top-level data key in the response. Defaults to 'data' if not specified."
        },
        "include_level": {
          "name": "Include Level",
          "description": "Include the Tibber price level field (very cheap/cheap/normal/expensive/very expensive) in each data point."
        },
        "include_rating_level": {
          "name": "Include Rating Level",
          "description": "Include the calculated rating level field (low/normal/high) based on your configured thresholds in each data point."
        },
        "include_average": {
          "name": "Include Average",
          "description": "Include the daily average price in each data point for comparison."
        },
        "include_energy": {
          "name": "Include Energy Price",
          "description": "Include the raw energy/spot price (excluding taxes and fees) in each data point. This is the 'energy' field from the Tibber API, useful for feed-in/net metering calculations."
        },
        "include_tax": {
          "name": "Include Tax",
          "description": "Include the tax component of the price in each data point. This is the 'tax' field from the Tibber API, representing fees, taxes, and grid charges."
        },
        "level_filter": {
          "name": "Level Filter",
          "description": "Filter intervals to include only specific Tibber price levels (very cheap/cheap/normal/expensive/very expensive). If not specified, all levels are included."
        },
        "rating_level_filter": {
          "name": "Rating Level Filter",
          "description": "Filter intervals to include only specific rating levels (low/normal/high). If not specified, all rating levels are included."
        },
        "period_filter": {
          "name": "Period Filter",
          "description": "Filter intervals to include only those within Best Price or Peak Price periods. Options: 'best_price' (only intervals in Best Price periods), 'peak_price' (only intervals in Peak Price periods). If not specified, all intervals are included. This uses the precomputed period data from binary sensors."
        },
        "insert_nulls": {
          "name": "Insert NULL Values",
          "description": "Control NULL value insertion for filtered data. 'none' (default): No NULL values, only matching intervals. 'segments': Add NULL points at segment boundaries for clean gaps in charts (recommended for stepline charts). 'all': Insert NULL for all timestamps where filter doesn't match (useful for continuous time series visualization)."
        },
        "connect_segments": {
          "name": "Connect Segments",
          "description": "[ONLY WITH 'Insert NULL Values'] When enabled, adds connecting points at segment boundaries to visually connect different price level segments in stepline charts. When price goes DOWN at a boundary, adds a point with the lower price at the end of the current segment. When price goes UP, adds a hold point before the gap. This creates smooth visual transitions between segments instead of abrupt gaps."
        },
        "add_trailing_null": {
          "name": "Add Trailing Null Point",
          "description": "Add a final data point with null values (except timestamp) at the end. Some chart libraries need this to prevent extrapolation/interpolation to the viewport edge when using stepline rendering. Leave disabled unless your chart requires it."
        },
        "start_time_field": {
          "name": "Start Time Field Name",
          "description": "Custom name for the start time field in the output. Defaults to 'start_time' if not specified."
        },
        "end_time_field": {
          "name": "End Time Field Name",
          "description": "Custom name for the end time field in the output. Defaults to 'end_time' if not specified. Only used with period_filter."
        },
        "price_field": {
          "name": "Price Field Name",
          "description": "Custom name for the price field in the output. Defaults to 'price_per_kwh' if not specified."
        },
        "level_field": {
          "name": "Level Field Name",
          "description": "Custom name for the level field in the output. Defaults to 'level' if not specified. Only used when include_level is enabled."
        },
        "rating_level_field": {
          "name": "Rating Level Field Name",
          "description": "Custom name for the rating_level field in the output. Defaults to 'rating_level' if not specified. Only used when include_rating_level is enabled."
        },
        "average_field": {
          "name": "Average Field Name",
          "description": "Custom name for the average field in the output. Defaults to 'average' if not specified. Only used when include_average is enabled."
        },
        "energy_field": {
          "name": "Energy Field Name",
          "description": "Custom name for the energy price field in the output. Defaults to 'energy_price' if not specified. Only used when include_energy is enabled."
        },
        "tax_field": {
          "name": "Tax Field Name",
          "description": "Custom name for the tax field in the output. Defaults to 'tax' if not specified. Only used when include_tax is enabled."
        },
        "metadata": {
          "name": "Metadata",
          "description": "Control metadata inclusion in the response. 'include' (default): Returns both chart data and metadata with price statistics, currency info, Y-axis suggestions, and time range. 'only': Returns only metadata without processing chart data (fast, useful for dynamic Y-axis configuration). 'none': Returns only chart data without metadata."
        }
      }
    },
    "refresh_user_data": {
      "name": "Refresh User Data",
      "description": "Forces a refresh of the user data (homes, profile information) from the Tibber API. This can be useful after making changes to your Tibber account or when troubleshooting connectivity issues.",
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        }
      }
    },
    "find_cheapest_block": {
      "name": "Find Cheapest Block",
      "description": "Finds the cheapest contiguous time window of a given duration. Designed for appliance scheduling: dishwasher, washing machine, dryer, etc. Returns the single cheapest window with start/end times and price statistics. If no window is found, the response includes a stable reason code in the reason field (for example: no_data_in_range, no_intervals_matching_level_filter, insufficient_intervals_after_filter, insufficient_contiguous_window).",
      "sections": {
        "search_range": {
          "name": "Custom Search Range",
          "description": "Define precise start and end times for the search. Overrides Search Scope when set."
        },
        "time_alternatives": {
          "name": "Advanced Time Options",
          "description": "Alternative ways to define the search range using time-of-day and minute offsets."
        },
        "price_filter": {
          "name": "Price Level Filter",
          "description": "Restrict search to intervals within the specified Tibber price level range."
        },
        "search_tuning": {
          "name": "Search Algorithm Tuning",
          "description": "Fine-tune how the search handles outliers, minimum quality thresholds, and fallback behavior."
        },
        "cost_estimation": {
          "name": "Cost Estimation",
          "description": "Provide a power profile to get accurate energy cost estimates based on actual consumption."
        },
        "output": {
          "name": "Output Options",
          "description": "Control output format: comparison details and currency unit."
        }
      },
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "duration": {
          "name": "Duration",
          "description": "Length of the desired contiguous window. Automatically rounded up to the next quarter-hour. Maximum: 12 hours."
        },
        "search_start": {
          "name": "Search Start",
          "description": "Start of the search range as exact date and time. Highest priority — overrides all other start options. Defaults to now if not specified."
        },
        "search_end": {
          "name": "Search End",
          "description": "End of the search range as exact date and time. Highest priority — overrides all other end options. Defaults to end of tomorrow if not specified."
        },
        "must_finish_by": {
          "name": "Must Finish By",
          "description": "Deadline: the appliance must be finished by this time. The search range ends at this deadline — the service finds the cheapest window that completes before it. Cannot be combined with Search End, Search End Time, or Search End Offset."
        },
        "search_start_time": {
          "name": "Search Start Time",
          "description": "Alternative: start searching at this time of day. Combine with day offset. Ignored if Search Start (datetime) is set."
        },
        "search_start_day_offset": {
          "name": "Search Start Day Offset",
          "description": "Day offset for Search Start Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search Start Time."
        },
        "search_end_time": {
          "name": "Search End Time",
          "description": "Alternative: stop searching at this time of day. Combine with day offset. Ignored if Search End (datetime) is set."
        },
        "search_end_day_offset": {
          "name": "Search End Day Offset",
          "description": "Day offset for Search End Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search End Time."
        },
        "search_start_offset_minutes": {
          "name": "Search Start Offset (minutes)",
          "description": "Alternative: start searching this many minutes from now. Positive = future (60 = in 1 hour), negative = past (-60 = 1 hour ago). Ignored if Search Start or Search Start Time is set."
        },
        "search_end_offset_minutes": {
          "name": "Search End Offset (minutes)",
          "description": "Alternative: stop searching this many minutes from now. Positive = future (480 = in 8 hours), negative = past (-60 = 1 hour ago). Ignored if Search End or Search End Time is set."
        },
        "include_current_interval": {
          "name": "Include Current Interval",
          "description": "Include the currently running 15-minute interval in the search. When enabled (default), the search starts at the beginning of the current interval so it can be part of the result."
        },
        "use_base_unit": {
          "name": "Use Base Currency Unit",
          "description": "Force prices in base currency (EUR, NOK) instead of the configured display unit (ct, øre). Useful for calculations."
        },
        "search_scope": {
          "name": "Search Scope",
          "description": "Shorthand for common search ranges. Overrides all other time range options. today / tomorrow = full calendar day, remaining_today = now until midnight, next_24h / next_48h = rolling window from now."
        },
        "max_price_level": {
          "name": "Maximum Price Level",
          "description": "Only consider intervals at or below this Tibber price level. very_cheap = most restrictive, very_expensive = no restriction."
        },
        "min_price_level": {
          "name": "Minimum Price Level",
          "description": "Only consider intervals at or above this Tibber price level. Useful for find_most_expensive to focus on truly expensive intervals."
        },
        "include_comparison_details": {
          "name": "Include Comparison Details",
          "description": "Enrich the price_comparison result with additional fields: comparison_price_min, comparison_price_max, and (block only) comparison_window_end."
        },
        "power_profile": {
          "name": "Power Profile",
          "description": "Variable power draw in watts per 15-minute interval. When set, estimated_total_cost reflects actual consumption instead of a flat 1 kW load. The profile is extended by repeating the last value if shorter than the window."
        },
        "smooth_outliers": {
          "name": "Smooth Outliers",
          "description": "Smooth price outliers before searching. Outlier intervals are temporarily replaced by the average of their neighbors, so a single spike or dip does not dominate the result. The response always shows the original (unsmoothed) prices. Default: enabled."
        },
        "min_distance_from_avg": {
          "name": "Min. Distance from Average",
          "description": "Require the found result to differ from the search-range average by at least this percentage. For cheapest: result must be at least X% below average. For most expensive: at least X% above. If the condition is not met, no result is returned (reason: selection_above/below_distance_threshold). Leave empty to disable."
        },
        "allow_relaxation": {
          "name": "Allow relaxation",
          "description": "Progressively relax filters to guarantee a result when possible. Phases: 1) Reduce/remove distance threshold 2) Expand level filters 3) Reduce duration. Default: enabled."
        },
        "duration_flexibility_minutes": {
          "name": "Duration flexibility",
          "description": "Maximum minutes the duration may be shortened during relaxation (0–120, step 15). Leave empty for automatic calculation (~20% of duration, max 60 min)."
        }
      }
    },
    "find_most_expensive_block": {
      "name": "Find Most Expensive Block",
      "description": "Finds the most expensive contiguous time window of a given duration. Useful for identifying peak price periods to avoid. Returns the single most expensive window with start/end times and price statistics.",
      "sections": {
        "search_range": {
          "name": "Custom Search Range",
          "description": "Define precise start and end times for the search. Overrides Search Scope when set."
        },
        "time_alternatives": {
          "name": "Advanced Time Options",
          "description": "Alternative ways to define the search range using time-of-day and minute offsets."
        },
        "price_filter": {
          "name": "Price Level Filter",
          "description": "Restrict search to intervals within the specified Tibber price level range."
        },
        "search_tuning": {
          "name": "Search Algorithm Tuning",
          "description": "Fine-tune how the search handles outliers, minimum quality thresholds, and fallback behavior."
        },
        "cost_estimation": {
          "name": "Cost Estimation",
          "description": "Provide a power profile to get accurate energy cost estimates based on actual consumption."
        },
        "output": {
          "name": "Output Options",
          "description": "Control output format: comparison details and currency unit."
        }
      },
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "duration": {
          "name": "Duration",
          "description": "Length of the desired contiguous window. Automatically rounded up to the next quarter-hour. Maximum: 12 hours."
        },
        "search_start": {
          "name": "Search Start",
          "description": "Start of the search range as exact date and time. Highest priority — overrides all other start options. Defaults to now if not specified."
        },
        "search_end": {
          "name": "Search End",
          "description": "End of the search range as exact date and time. Highest priority — overrides all other end options. Defaults to end of tomorrow if not specified."
        },
        "must_finish_by": {
          "name": "Must Finish By",
          "description": "Deadline: the appliance must be finished by this time. The search range ends at this deadline — the service finds the most expensive window that completes before it. Cannot be combined with Search End, Search End Time, Search End Offset, or Search Scope."
        },
        "search_start_time": {
          "name": "Search Start Time",
          "description": "Alternative: start searching at this time of day. Combine with day offset. Ignored if Search Start (datetime) is set."
        },
        "search_start_day_offset": {
          "name": "Search Start Day Offset",
          "description": "Day offset for Search Start Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search Start Time."
        },
        "search_end_time": {
          "name": "Search End Time",
          "description": "Alternative: stop searching at this time of day. Combine with day offset. Ignored if Search End (datetime) is set."
        },
        "search_end_day_offset": {
          "name": "Search End Day Offset",
          "description": "Day offset for Search End Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search End Time."
        },
        "search_start_offset_minutes": {
          "name": "Search Start Offset (minutes)",
          "description": "Alternative: start searching this many minutes from now. Positive = future (60 = in 1 hour), negative = past (-60 = 1 hour ago). Ignored if Search Start or Search Start Time is set."
        },
        "search_end_offset_minutes": {
          "name": "Search End Offset (minutes)",
          "description": "Alternative: stop searching this many minutes from now. Positive = future (480 = in 8 hours), negative = past (-60 = 1 hour ago). Ignored if Search End or Search End Time is set."
        },
        "include_current_interval": {
          "name": "Include Current Interval",
          "description": "Include the currently running 15-minute interval in the search. When enabled (default), the search starts at the beginning of the current interval so it can be part of the result."
        },
        "use_base_unit": {
          "name": "Use Base Currency Unit",
          "description": "Force prices in base currency (EUR, NOK) instead of the configured display unit (ct, øre). Useful for calculations."
        },
        "search_scope": {
          "name": "Search Scope",
          "description": "Shorthand for common search ranges. Overrides all other time range options. today / tomorrow = full calendar day, remaining_today = now until midnight, next_24h / next_48h = rolling window from now."
        },
        "max_price_level": {
          "name": "Maximum Price Level",
          "description": "Only consider intervals at or below this Tibber price level. very_cheap = most restrictive, very_expensive = no restriction."
        },
        "min_price_level": {
          "name": "Minimum Price Level",
          "description": "Only consider intervals at or above this Tibber price level. Useful for find_most_expensive to focus on truly expensive intervals."
        },
        "include_comparison_details": {
          "name": "Include Comparison Details",
          "description": "Enrich the price_comparison result with additional fields: comparison_price_min, comparison_price_max, and (block only) comparison_window_end."
        },
        "power_profile": {
          "name": "Power Profile",
          "description": "Variable power draw in watts per 15-minute interval. When set, estimated_total_cost reflects actual consumption instead of a flat 1 kW load. The profile is extended by repeating the last value if shorter than the window."
        },
        "smooth_outliers": {
          "name": "Smooth Outliers",
          "description": "Smooth price outliers before searching. Outlier intervals are temporarily replaced by the average of their neighbors, so a single spike or dip does not dominate the result. The response always shows the original (unsmoothed) prices. Default: enabled."
        },
        "min_distance_from_avg": {
          "name": "Min. Distance from Average",
          "description": "Require the found result to differ from the search-range average by at least this percentage. For cheapest: result must be at least X% below average. For most expensive: at least X% above. If the condition is not met, no result is returned (reason: selection_above/below_distance_threshold). Leave empty to disable."
        },
        "allow_relaxation": {
          "name": "Allow relaxation",
          "description": "Progressively relax filters to guarantee a result when possible. Phases: 1) Reduce/remove distance threshold 2) Expand level filters 3) Reduce duration. Default: enabled."
        },
        "duration_flexibility_minutes": {
          "name": "Duration flexibility",
          "description": "Maximum minutes the duration may be shortened during relaxation (0–120, step 15). Leave empty for automatic calculation (~20% of duration, max 60 min)."
        }
      }
    },
    "find_cheapest_hours": {
      "name": "Find Cheapest Hours",
      "description": "Finds the cheapest intervals totaling a given duration, not necessarily contiguous. Designed for flexible loads: battery charging, EV, water heater. Returns a schedule of intervals grouped into contiguous segments. If no schedule is found, the response includes a stable reason code in the reason field (for example: no_data_in_range, no_intervals_matching_level_filter, insufficient_intervals_after_filter, insufficient_intervals_for_constraints).",
      "sections": {
        "search_range": {
          "name": "Custom Search Range",
          "description": "Define precise start and end times for the search. Overrides Search Scope when set."
        },
        "time_alternatives": {
          "name": "Advanced Time Options",
          "description": "Alternative ways to define the search range using time-of-day and minute offsets."
        },
        "price_filter": {
          "name": "Price Level Filter",
          "description": "Restrict search to intervals within the specified Tibber price level range."
        },
        "search_tuning": {
          "name": "Search Algorithm Tuning",
          "description": "Fine-tune how the search handles outliers, minimum quality thresholds, and fallback behavior."
        },
        "cost_estimation": {
          "name": "Cost Estimation",
          "description": "Provide a power profile to get accurate energy cost estimates based on actual consumption."
        },
        "output": {
          "name": "Output Options",
          "description": "Control output format: comparison details and currency unit."
        }
      },
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "duration": {
          "name": "Duration",
          "description": "Total cheap time needed. Automatically rounded up to the next quarter-hour. Maximum: 24 hours."
        },
        "search_start": {
          "name": "Search Start",
          "description": "Start of the search range as exact date and time. Highest priority — overrides all other start options. Defaults to now if not specified."
        },
        "search_end": {
          "name": "Search End",
          "description": "End of the search range as exact date and time. Highest priority — overrides all other end options. Defaults to end of tomorrow if not specified."
        },
        "must_finish_by": {
          "name": "Must Finish By",
          "description": "Deadline: the appliance must be finished by this time. The search range ends at this deadline — the service finds the cheapest window that completes before it. Cannot be combined with Search End, Search End Time, or Search End Offset."
        },
        "search_start_time": {
          "name": "Search Start Time",
          "description": "Alternative: start searching at this time of day. Combine with day offset. Ignored if Search Start (datetime) is set."
        },
        "search_start_day_offset": {
          "name": "Search Start Day Offset",
          "description": "Day offset for Search Start Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search Start Time."
        },
        "search_end_time": {
          "name": "Search End Time",
          "description": "Alternative: stop searching at this time of day. Combine with day offset. Ignored if Search End (datetime) is set."
        },
        "search_end_day_offset": {
          "name": "Search End Day Offset",
          "description": "Day offset for Search End Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search End Time."
        },
        "search_start_offset_minutes": {
          "name": "Search Start Offset (minutes)",
          "description": "Alternative: start searching this many minutes from now. Positive = future (60 = in 1 hour), negative = past (-60 = 1 hour ago). Ignored if Search Start or Search Start Time is set."
        },
        "search_end_offset_minutes": {
          "name": "Search End Offset (minutes)",
          "description": "Alternative: stop searching this many minutes from now. Positive = future (480 = in 8 hours), negative = past (-60 = 1 hour ago). Ignored if Search End or Search End Time is set."
        },
        "include_current_interval": {
          "name": "Include Current Interval",
          "description": "Include the currently running 15-minute interval in the search. When enabled (default), the search starts at the beginning of the current interval so it can be part of the result."
        },
        "min_segment_duration": {
          "name": "Minimum Segment Duration",
          "description": "Minimum contiguous run length. Prevents rapid on/off cycling for devices with minimum run times. Automatically rounded up to the next quarter-hour. Default: 15 minutes. Maximum: 4 hours."
        },
        "use_base_unit": {
          "name": "Use Base Currency Unit",
          "description": "Force prices in base currency (EUR, NOK) instead of the configured display unit (ct, øre). Useful for calculations."
        },
        "search_scope": {
          "name": "Search Scope",
          "description": "Shorthand for common search ranges. Overrides all other time range options. today / tomorrow = full calendar day, remaining_today = now until midnight, next_24h / next_48h = rolling window from now."
        },
        "max_price_level": {
          "name": "Maximum Price Level",
          "description": "Only consider intervals at or below this Tibber price level. very_cheap = most restrictive, very_expensive = no restriction."
        },
        "min_price_level": {
          "name": "Minimum Price Level",
          "description": "Only consider intervals at or above this Tibber price level. Useful for find_most_expensive to focus on truly expensive intervals."
        },
        "include_comparison_details": {
          "name": "Include Comparison Details",
          "description": "Enrich the price_comparison result with additional fields: comparison_price_min, comparison_price_max, and (block only) comparison_window_end."
        },
        "power_profile": {
          "name": "Power Profile",
          "description": "Variable power draw in watts per 15-minute interval. When set, estimated_total_cost reflects actual consumption instead of a flat 1 kW load. The profile is extended by repeating the last value if shorter than the window."
        },
        "smooth_outliers": {
          "name": "Smooth Outliers",
          "description": "Smooth price outliers before searching. Outlier intervals are temporarily replaced by the average of their neighbors, so a single spike or dip does not dominate the result. The response always shows the original (unsmoothed) prices. Default: enabled."
        },
        "min_distance_from_avg": {
          "name": "Min. Distance from Average",
          "description": "Require the found result to differ from the search-range average by at least this percentage. For cheapest: result must be at least X% below average. For most expensive: at least X% above. If the condition is not met, no result is returned (reason: selection_above/below_distance_threshold). Leave empty to disable."
        },
        "allow_relaxation": {
          "name": "Allow relaxation",
          "description": "Progressively relax filters to guarantee a result when possible. Phases: 1) Reduce/remove distance threshold 2) Expand level filters 3) Reduce duration. Default: enabled."
        },
        "duration_flexibility_minutes": {
          "name": "Duration flexibility",
          "description": "Maximum minutes the duration may be shortened during relaxation (0–120, step 15). Leave empty for automatic calculation (~20% of duration, max 60 min)."
        }
      }
    },
    "find_most_expensive_hours": {
      "name": "Find Most Expensive Hours",
      "description": "Finds the most expensive intervals totaling a given duration, not necessarily contiguous. Useful for identifying peak price periods to avoid. Returns a schedule of intervals grouped into contiguous segments.",
      "sections": {
        "search_range": {
          "name": "Custom Search Range",
          "description": "Define precise start and end times for the search. Overrides Search Scope when set."
        },
        "time_alternatives": {
          "name": "Advanced Time Options",
          "description": "Alternative ways to define the search range using time-of-day and minute offsets."
        },
        "price_filter": {
          "name": "Price Level Filter",
          "description": "Restrict search to intervals within the specified Tibber price level range."
        },
        "search_tuning": {
          "name": "Search Algorithm Tuning",
          "description": "Fine-tune how the search handles outliers, minimum quality thresholds, and fallback behavior."
        },
        "cost_estimation": {
          "name": "Cost Estimation",
          "description": "Provide a power profile to get accurate energy cost estimates based on actual consumption."
        },
        "output": {
          "name": "Output Options",
          "description": "Control output format: comparison details and currency unit."
        }
      },
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "duration": {
          "name": "Duration",
          "description": "Total expensive time to find. Automatically rounded up to the next quarter-hour. Maximum: 24 hours."
        },
        "search_start": {
          "name": "Search Start",
          "description": "Start of the search range as exact date and time. Highest priority — overrides all other start options. Defaults to now if not specified."
        },
        "search_end": {
          "name": "Search End",
          "description": "End of the search range as exact date and time. Highest priority — overrides all other end options. Defaults to end of tomorrow if not specified."
        },
        "must_finish_by": {
          "name": "Must Finish By",
          "description": "Deadline: the appliance must be finished by this time. The search range ends at this deadline — the service finds the most expensive window that completes before it. Cannot be combined with Search End, Search End Time, Search End Offset, or Search Scope."
        },
        "search_start_time": {
          "name": "Search Start Time",
          "description": "Alternative: start searching at this time of day. Combine with day offset. Ignored if Search Start (datetime) is set."
        },
        "search_start_day_offset": {
          "name": "Search Start Day Offset",
          "description": "Day offset for Search Start Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search Start Time."
        },
        "search_end_time": {
          "name": "Search End Time",
          "description": "Alternative: stop searching at this time of day. Combine with day offset. Ignored if Search End (datetime) is set."
        },
        "search_end_day_offset": {
          "name": "Search End Day Offset",
          "description": "Day offset for Search End Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Negative values search in the past. Only used with Search End Time."
        },
        "search_start_offset_minutes": {
          "name": "Search Start Offset (minutes)",
          "description": "Alternative: start searching this many minutes from now. Positive = future (60 = in 1 hour), negative = past (-60 = 1 hour ago). Ignored if Search Start or Search Start Time is set."
        },
        "search_end_offset_minutes": {
          "name": "Search End Offset (minutes)",
          "description": "Alternative: stop searching this many minutes from now. Positive = future (480 = in 8 hours), negative = past (-60 = 1 hour ago). Ignored if Search End or Search End Time is set."
        },
        "include_current_interval": {
          "name": "Include Current Interval",
          "description": "Include the currently running 15-minute interval in the search. When enabled (default), the search starts at the beginning of the current interval so it can be part of the result."
        },
        "min_segment_duration": {
          "name": "Minimum Segment Duration",
          "description": "Minimum contiguous run length. Prevents rapid on/off cycling for devices with minimum run times. Automatically rounded up to the next quarter-hour. Default: 15 minutes. Maximum: 4 hours."
        },
        "use_base_unit": {
          "name": "Use Base Currency Unit",
          "description": "Force prices in base currency (EUR, NOK) instead of the configured display unit (ct, øre). Useful for calculations."
        },
        "search_scope": {
          "name": "Search Scope",
          "description": "Shorthand for common search ranges. Overrides all other time range options. today / tomorrow = full calendar day, remaining_today = now until midnight, next_24h / next_48h = rolling window from now."
        },
        "max_price_level": {
          "name": "Maximum Price Level",
          "description": "Only consider intervals at or below this Tibber price level. very_cheap = most restrictive, very_expensive = no restriction."
        },
        "min_price_level": {
          "name": "Minimum Price Level",
          "description": "Only consider intervals at or above this Tibber price level. Useful for find_most_expensive to focus on truly expensive intervals."
        },
        "include_comparison_details": {
          "name": "Include Comparison Details",
          "description": "Enrich the price_comparison result with additional fields: comparison_price_min, comparison_price_max, and (block only) comparison_window_end."
        },
        "power_profile": {
          "name": "Power Profile",
          "description": "Variable power draw in watts per 15-minute interval. When set, estimated_total_cost reflects actual consumption instead of a flat 1 kW load. The profile is extended by repeating the last value if shorter than the window."
        },
        "smooth_outliers": {
          "name": "Smooth Outliers",
          "description": "Smooth price outliers before searching. Outlier intervals are temporarily replaced by the average of their neighbors, so a single spike or dip does not dominate the result. The response always shows the original (unsmoothed) prices. Default: enabled."
        },
        "min_distance_from_avg": {
          "name": "Min. Distance from Average",
          "description": "Require the found result to differ from the search-range average by at least this percentage. For cheapest: result must be at least X% below average. For most expensive: at least X% above. If the condition is not met, no result is returned (reason: selection_above/below_distance_threshold). Leave empty to disable."
        },
        "allow_relaxation": {
          "name": "Allow relaxation",
          "description": "Progressively relax filters to guarantee a result when possible. Phases: 1) Reduce/remove distance threshold 2) Expand level filters 3) Reduce duration. Default: enabled."
        },
        "duration_flexibility_minutes": {
          "name": "Duration flexibility",
          "description": "Maximum minutes the duration may be shortened during relaxation (0–120, step 15). Leave empty for automatic calculation (~20% of duration, max 60 min)."
        }
      }
    },
    "find_cheapest_schedule": {
      "name": "Find Cheapest Schedule",
      "description": "Schedules multiple appliances optimally without time overlap. Each task gets the cheapest available contiguous window; tasks are placed greedily in ascending cost order. Returns a per-task schedule with start/end times and price stats. If scheduling is incomplete, the response includes a stable reason code in the reason field (for example: no_data_in_range, no_intervals_matching_level_filter, insufficient_contiguous_window, insufficient_contiguous_window_for_some_tasks).",
      "sections": {
        "search_range": {
          "name": "Custom Search Range",
          "description": "Define precise start and end times for the search. Overrides Search Scope when set."
        },
        "time_alternatives": {
          "name": "Advanced Time Options",
          "description": "Alternative ways to define the search range using time-of-day and minute offsets."
        },
        "price_filter": {
          "name": "Price Level Filter",
          "description": "Restrict search to intervals within the specified Tibber price level range."
        },
        "search_tuning": {
          "name": "Search Algorithm Tuning",
          "description": "Fine-tune how the search handles outliers, minimum quality thresholds, and fallback behavior."
        },
        "output": {
          "name": "Output Options",
          "description": "Control output format: comparison details and currency unit."
        }
      },
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "tasks": {
          "name": "Tasks",
          "description": "List of tasks to schedule. Each task requires name (string) and duration (hh:mm:ss). Optionally add power_profile (list of watts per 15-min interval). Maximum 4 tasks."
        },
        "gap_minutes": {
          "name": "Gap Between Tasks (minutes)",
          "description": "Minimum gap in minutes between consecutive scheduled tasks. Rounded up to 15 minutes. Default: 0 (no gap)."
        },
        "sequential": {
          "name": "Sequential Ordering",
          "description": "Schedule tasks in the order they appear in the task list. Each task starts after the previous one ends (plus gap). Use this for dependent appliances like washing machine → dryer. Default: disabled (tasks are sorted by duration for optimal packing)."
        },
        "search_scope": {
          "name": "Search Scope",
          "description": "Shorthand for common search ranges. Overrides all other time range options. today / tomorrow = full calendar day, remaining_today = now until midnight, next_24h / next_48h = rolling window from now."
        },
        "search_start": {
          "name": "Search Start",
          "description": "Start of the search range as exact date and time. Highest priority — overrides all other start options. Defaults to now if not specified."
        },
        "search_end": {
          "name": "Search End",
          "description": "End of the search range as exact date and time. Highest priority — overrides all other end options. Defaults to end of tomorrow if not specified."
        },
        "must_finish_by": {
          "name": "Must Finish By",
          "description": "Deadline: the appliance must be finished by this time. The search range ends at this deadline — the service finds the cheapest window that completes before it. Cannot be combined with Search End, Search End Time, or Search End Offset."
        },
        "search_start_time": {
          "name": "Search Start Time",
          "description": "Alternative: start searching at this time of day. Combine with day offset. Ignored if Search Start (datetime) is set."
        },
        "search_start_day_offset": {
          "name": "Search Start Day Offset",
          "description": "Day offset for Search Start Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Only used with Search Start Time."
        },
        "search_end_time": {
          "name": "Search End Time",
          "description": "Alternative: stop searching at this time of day. Combine with day offset. Ignored if Search End (datetime) is set."
        },
        "search_end_day_offset": {
          "name": "Search End Day Offset",
          "description": "Day offset for Search End Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Only used with Search End Time."
        },
        "search_start_offset_minutes": {
          "name": "Search Start Offset (minutes)",
          "description": "Alternative: start searching this many minutes from now. Positive = future, negative = past. Ignored if Search Start or Search Start Time is set."
        },
        "search_end_offset_minutes": {
          "name": "Search End Offset (minutes)",
          "description": "Alternative: stop searching this many minutes from now. Positive = future, negative = past. Ignored if Search End or Search End Time is set."
        },
        "max_price_level": {
          "name": "Maximum Price Level",
          "description": "Only consider intervals at or below this Tibber price level. very_cheap = most restrictive, very_expensive = no restriction."
        },
        "min_price_level": {
          "name": "Minimum Price Level",
          "description": "Only consider intervals at or above this Tibber price level. Useful for find_most_expensive to focus on truly expensive intervals."
        },
        "include_comparison_details": {
          "name": "Include Comparison Details",
          "description": "Add per-task price_comparison details (comparison_price_min, comparison_price_max, comparison_window_end) to compare each selected task window against the opposite extreme window of the same duration."
        },
        "use_base_unit": {
          "name": "Use Base Currency Unit",
          "description": "Force prices in base currency (EUR, NOK) instead of the configured display unit (ct, øre). Useful for calculations."
        },
        "smooth_outliers": {
          "name": "Smooth Outliers",
          "description": "Smooth price outliers before searching. Outlier intervals are temporarily replaced by the average of their neighbors, so a single spike or dip does not dominate the result. The response always shows the original (unsmoothed) prices. Default: enabled."
        },
        "allow_relaxation": {
          "name": "Allow relaxation",
          "description": "Progressively relax filters to guarantee a result when possible. Phases: 1) Reduce/remove distance threshold 2) Expand level filters 3) Reduce duration. Default: enabled."
        },
        "duration_flexibility_minutes": {
          "name": "Duration flexibility",
          "description": "Maximum minutes the duration may be shortened during relaxation (0–120, step 15). Leave empty for automatic calculation (~20% of duration, max 60 min)."
        }
      }
    },
    "plan_charging": {
      "name": "Plan Charging",
      "description": "Creates a lowest-cost charging schedule from battery parameters instead of a fixed duration. Supports fixed, continuous, or stepped charging power, optional deadline-aware minimum SoC planning, and economic filtering for later discharge use cases. Returns a per-interval charging plan with power, energy, SoC progression, segment grouping, total cost, and profitability details. If no schedule is found, the response includes a stable reason code in the reason field (for example: already_at_target, no_data_in_range, no_intervals_matching_level_filter, no_intervals_after_economic_filter, energy_unreachable, energy_unreachable_by_deadline, selection_above_distance_threshold).",
      "sections": {
        "battery": {
          "name": "Battery Parameters",
          "description": "Describe the battery: usable capacity, current and target SoC, and charging efficiency. You can provide SoC in percent (requires capacity) or directly in kWh."
        },
        "charging": {
          "name": "Charging Strategy",
          "description": "Configure variable-power charging behavior, grid limits, and minimum run-time constraints."
        },
        "deadline": {
          "name": "Deadline Planning",
          "description": "Require a minimum state of charge by a specific moment (for example before a peak period). Set both the Minimum SoC by Deadline and when it must be reached — either as an absolute time (Must Reach By) or from a known event (Deadline Event)."
        },
        "search_range": {
          "name": "Custom Search Range",
          "description": "Define precise start and end times for the search. Overrides Search Scope when set."
        },
        "time_alternatives": {
          "name": "Advanced Time Options",
          "description": "Alternative ways to define the search range using time-of-day and minute offsets."
        },
        "price_filter": {
          "name": "Price Level Filter",
          "description": "Restrict search to intervals within the specified Tibber price level range."
        },
        "search_tuning": {
          "name": "Search Algorithm Tuning",
          "description": "Fine-tune how the search handles outliers, minimum quality thresholds, and fallback behavior."
        },
        "economics": {
          "name": "Economic Filters",
          "description": "Filter charging intervals by maximum cost or expected later discharge value."
        },
        "output": {
          "name": "Output Options",
          "description": "Control output format: comparison details and currency unit."
        }
      },
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "The config entry ID for the Tibber integration."
        },
        "max_charge_power_w": {
          "name": "Maximum Charge Power",
          "description": "Maximum charging power in watts. This defines the upper bound for fixed, continuous, or stepped charging schedules."
        },
        "battery_capacity_kwh": {
          "name": "Battery Capacity",
          "description": "Usable battery capacity in kWh. Required when current or target SoC is provided as a percentage."
        },
        "current_soc_percent": {
          "name": "Current SoC (%)",
          "description": "Current battery state of charge in percent. Cannot be combined with Current SoC (kWh)."
        },
        "current_soc_kwh": {
          "name": "Current SoC (kWh)",
          "description": "Current battery state of charge in kWh. Cannot be combined with Current SoC (%)."
        },
        "target_soc_percent": {
          "name": "Target SoC (%)",
          "description": "Desired battery state of charge in percent. Cannot be combined with Target SoC (kWh)."
        },
        "target_soc_kwh": {
          "name": "Target SoC (kWh)",
          "description": "Desired battery state of charge in kWh. Cannot be combined with Target SoC (%)."
        },
        "charging_efficiency": {
          "name": "Charging Efficiency",
          "description": "Fraction of grid energy that is stored in the battery. Example: 0.92 means 8% charging losses."
        },
        "search_scope": {
          "name": "Search Scope",
          "description": "Shorthand for common search ranges. Overrides all other time range options. today / tomorrow = full calendar day, remaining_today = now until midnight, next_24h / next_48h = rolling window from now."
        },
        "include_current_interval": {
          "name": "Include Current Interval",
          "description": "Include the currently running 15-minute interval in the search. When enabled, charging may begin in the current interval if it is part of the cheapest result."
        },
        "search_start": {
          "name": "Search Start",
          "description": "Start of the search range as exact date and time. Highest priority — overrides all other start options. Defaults to now if not specified."
        },
        "search_end": {
          "name": "Search End",
          "description": "End of the search range as exact date and time. Highest priority — overrides all other end options. Defaults to end of tomorrow if not specified."
        },
        "must_finish_by": {
          "name": "Must Finish By",
          "description": "Deadline: charging must be finished by this time. The search range ends at this deadline — the service finds the cheapest intervals that complete before it. Cannot be combined with Search End, Search End Time, or Search End Offset."
        },
        "search_start_time": {
          "name": "Search Start Time",
          "description": "Alternative: start searching at this time of day. Combine with day offset. Ignored if Search Start (datetime) is set."
        },
        "search_start_day_offset": {
          "name": "Search Start Day Offset",
          "description": "Day offset for Search Start Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Only used with Search Start Time."
        },
        "search_end_time": {
          "name": "Search End Time",
          "description": "Alternative: stop searching at this time of day. Combine with day offset. Ignored if Search End (datetime) is set."
        },
        "search_end_day_offset": {
          "name": "Search End Day Offset",
          "description": "Day offset for Search End Time. -7 to 2: -1 = yesterday, 0 = today, 1 = tomorrow. Only used with Search End Time."
        },
        "search_start_offset_minutes": {
          "name": "Search Start Offset (minutes)",
          "description": "Alternative: start searching this many minutes from now. Positive = future, negative = past. Ignored if Search Start or Search Start Time is set."
        },
        "search_end_offset_minutes": {
          "name": "Search End Offset (minutes)",
          "description": "Alternative: stop searching this many minutes from now. Positive = future, negative = past. Ignored if Search End or Search End Time is set."
        },
        "max_price_level": {
          "name": "Maximum Price Level",
          "description": "Only consider intervals at or below this Tibber price level. very_cheap = most restrictive, very_expensive = no restriction."
        },
        "min_price_level": {
          "name": "Minimum Price Level",
          "description": "Only consider intervals at or above this Tibber price level. Useful to exclude unrealistically cheap negative-price-only windows from mixed searches."
        },
        "include_comparison_details": {
          "name": "Include Comparison Details",
          "description": "Enrich the price_comparison result with additional fields: comparison_price_min and comparison_price_max."
        },
        "use_base_unit": {
          "name": "Use Base Currency Unit",
          "description": "Force prices in base currency (EUR, NOK) instead of the configured display unit (ct, øre). Useful for calculations."
        },
        "smooth_outliers": {
          "name": "Smooth Outliers",
          "description": "Smooth price outliers before searching. Outlier intervals are temporarily replaced by the average of their neighbors, so a single spike or dip does not dominate the result. The response always shows the original (unsmoothed) prices. Default: enabled."
        },
        "min_distance_from_avg": {
          "name": "Min. Distance from Average",
          "description": "Require the selected charging intervals to be at least this percentage below the average price of the full search range. Leave empty to disable."
        },
        "allow_relaxation": {
          "name": "Allow relaxation",
          "description": "Progressively relax filters to guarantee a result when possible. Phases: 1) Reduce/remove distance threshold 2) Expand level filters 3) Reduce duration. Default: enabled."
        },
        "duration_flexibility_minutes": {
          "name": "Duration flexibility",
          "description": "Maximum minutes the automatically calculated charging duration may be shortened during relaxation (0–120, step 15). Leave empty for automatic calculation."
        },
        "must_reach_soc_percent": {
          "name": "Minimum SoC by Deadline (%)",
          "description": "Minimum battery state of charge that must be reached by the deadline. Cannot be combined with Minimum SoC by Deadline (kWh)."
        },
        "must_reach_soc_kwh": {
          "name": "Minimum SoC by Deadline (kWh)",
          "description": "Minimum battery state of charge that must be reached by the deadline. Cannot be combined with Minimum SoC by Deadline (%)."
        },
        "min_charge_power_w": {
          "name": "Minimum Charge Power",
          "description": "Enable continuous charging mode. The planner may reduce the last interval down to this minimum power instead of always using the maximum."
        },
        "charge_power_steps_w": {
          "name": "Charge Power Steps",
          "description": "Enable stepped charging mode. Provide the allowed power steps in watts as a list, for example [1380, 4140, 11000]. The planner picks the smallest step that still covers the remaining energy in the final interval. Mutually exclusive with Minimum Charge Power."
        },
        "grid_import_limit_w": {
          "name": "Grid Import Limit",
          "description": "Upper limit for charging power drawn from the grid in watts. Useful when the charger must share available power with other loads."
        },
        "must_reach_by": {
          "name": "Must Reach By",
          "description": "Absolute deadline for must_reach_soc_*. The planner first guarantees the minimum SoC before this moment, then continues with the remaining target if possible."
        },
        "must_reach_by_event": {
          "name": "Deadline Event",
          "description": "Alternative deadline derived from coordinator data. Use this instead of Must Reach By to plan around midnight, the next peak period, or the next best-price period end."
        },
        "discharging_efficiency": {
          "name": "Discharging Efficiency",
          "description": "Fraction of stored battery energy that is still usable when later discharged. Used for profitability calculations."
        },
        "expected_discharge_price": {
          "name": "Expected Discharge Price",
          "description": "Expected value of each discharged kWh. Intervals above the break-even price can be filtered when Reserve For Discharge is enabled."
        },
        "reserve_for_discharge": {
          "name": "Reserve For Discharge",
          "description": "Keep only intervals that are economically sensible for a later discharge based on expected discharge price and round-trip efficiency."
        },
        "max_cost_per_kwh": {
          "name": "Maximum Charge Price",
          "description": "Discard candidate intervals above this price per kWh before scheduling. Uses the selected price unit."
        },
        "min_charge_duration_minutes": {
          "name": "Minimum Charge Duration",
          "description": "Merge short isolated intervals into longer charging blocks where possible. Useful for chargers that should avoid very short runs."
        },
        "max_cycles_per_day": {
          "name": "Maximum Charge Cycles Per Day",
          "description": "Limit how many separate charging segments may be used per day. The planner keeps the cheapest segments within this limit."
        }
      }
    },
    "debug_clear_tomorrow": {
      "name": "Debug: Clear Tomorrow Data",
      "description": "DEBUG/TESTING: Removes tomorrow's price data from the interval pool cache. Use this to test the tomorrow data refresh cycle without waiting for the next day. After calling this service, the lifecycle sensor will show 'searching_tomorrow' (after 13:00) and the next Timer #1 cycle will fetch new data from the API.",
      "fields": {
        "entry_id": {
          "name": "Entry ID",
          "description": "Optional config entry ID. If not provided, uses the first available entry."
        }
      }
    }
  },
  "selector": {
    "account_choice": {
      "options": {
        "new_token": "Add new Tibber account API token"
      }
    },
    "day": {
      "options": {
        "yesterday": "Yesterday",
        "today": "Today",
        "tomorrow": "Tomorrow",
        "rolling_window": "Rolling Window",
        "rolling_window_autozoom": "Rolling Window (Auto-Zoom)"
      }
    },
    "resolution": {
      "options": {
        "interval": "Interval (15 min)",
        "hourly": "Hourly"
      }
    },
    "output_format": {
      "options": {
        "array_of_objects": "Array of Objects",
        "array_of_arrays": "Array of Arrays"
      }
    },
    "level_type": {
      "options": {
        "rating_level": "Rating Level (low/normal/high)",
        "level": "Tibber Level (very cheap to very expensive)"
      }
    },
    "level_filter": {
      "options": {
        "very_cheap": "Very cheap",
        "cheap": "Cheap",
        "normal": "Normal",
        "expensive": "Expensive",
        "very_expensive": "Very expensive"
      }
    },
    "rating_level_filter": {
      "options": {
        "low": "Low",
        "normal": "Normal",
        "high": "High"
      }
    },
    "insert_nulls": {
      "options": {
        "none": "None",
        "segments": "Segments",
        "all": "All"
      }
    },
    "period_filter": {
      "options": {
        "best_price": "Best Price Periods",
        "peak_price": "Peak Price Periods"
      }
    },
    "metadata": {
      "options": {
        "include": "Include (data + metadata)",
        "only": "Only metadata",
        "none": "None (data only)"
      }
    },
    "volatility": {
      "options": {
        "low": "Low",
        "moderate": "Moderate",
        "high": "High",
        "very_high": "Very high"
      }
    },
    "current_interval_price_level": {
      "options": {
        "any": "Any",
        "very_cheap": "Very cheap",
        "cheap": "Cheap",
        "normal": "Normal",
        "expensive": "Expensive",
        "very_expensive": "Very expensive"
      }
    },
    "currency_display_mode": {
      "options": {
        "base": "Base Currency (€, kr)",
        "subunit": "Subunit Currency (ct, øre)"
      }
    },
    "average_sensor_display": {
      "options": {
        "median": "Median",
        "mean": "Arithmetic Mean"
      }
    },
    "search_scope": {
      "options": {
        "today": "Today",
        "tomorrow": "Tomorrow",
        "remaining_today": "Remaining Today",
        "next_24h": "Next 24 Hours",
        "next_48h": "Next 48 Hours"
      }
    },
    "charging_deadline_event": {
      "options": {
        "midnight": "Midnight",
        "next_peak_period": "Next Peak Period",
        "next_best_period_end": "End of Next Best-Price Period"
      }
    }
  }
}
