#if !defined(NETHER) && !defined(END)
    #define OVERWORLD
#endif

// Returns the horizon-level sky color for the current time of day.
// Used by fog calculations so border fog matches the custom sky horizon.
vec3 customHorizonFogColor(float _sunAngle, vec3 _viewDir, float _rainStrength) {
    // Day/night weights (mirrors gbuffers_skybasic time helpers)
    float _day  = smoothstep(0.50, 0.44, _sunAngle);
    float _rise = smoothstep(0.97, 1.00, _sunAngle);
    float _morn = 1.0 - smoothstep(0.00, 0.05, _sunAngle);
    float _dayF = clamp(_day + _rise + _morn, 0.0, 1.0);

    // Transition (sunrise/sunset)
    float _sunW = clamp(smoothstep(0.96, 1.00, _sunAngle) + (1.0 - smoothstep(0.00, 0.06, _sunAngle)), 0.0, 1.0);
    float _setW = smoothstep(0.44, 0.50, _sunAngle) * (1.0 - smoothstep(0.50, 0.56, _sunAngle));
    float _transW = clamp(_sunW + _setW, 0.0, 1.0);

    // Twilight
    float _afterSet    = smoothstep(0.50, 0.54, _sunAngle) * (1.0 - smoothstep(0.54, 0.62, _sunAngle));
    float _beforeRise  = smoothstep(0.88, 0.93, _sunAngle) * (1.0 - smoothstep(0.97, 1.00, _sunAngle));
    float _twilW = clamp(_afterSet + _beforeRise, 0.0, 1.0);

    // Base horizon blend
    vec3 _dayHorizon   = vec3(SKY_DAY_HORIZON_R,   SKY_DAY_HORIZON_G,   SKY_DAY_HORIZON_B);
    vec3 _nightHorizon = vec3(SKY_NIGHT_HORIZON_R,  SKY_NIGHT_HORIZON_G, SKY_NIGHT_HORIZON_B);
    vec3 _col = mix(_nightHorizon, _dayHorizon, _dayF);

    // Sunset/sunrise tint — directionally biased toward the sun when a view
    // direction is provided, matching the sky dome shading in gbuffers_skybasic.
    vec3 _sunsetTint = vec3(SKY_SUNSET_R, SKY_SUNSET_G, SKY_SUNSET_B);

    // Reconstruct the world-space sun direction the same way gbuffers_skybasic does.
    float _sunAngleClamped = clamp(_sunAngle < 0.5 ? _sunAngle : 1.0 - _sunAngle, 0.001, 0.499);
    vec3  _worldSunDir = normalize(vec3(
        cos(_sunAngleClamped * 2.0 * 3.14159265),
        sin(_sunAngleClamped * 2.0 * 3.14159265),
        0.0
    ));

    // sunDot: +1 = looking straight at sun, -1 = looking away.
    // Only computed when a real view direction is supplied (len > 0).
    float _dirLen = length(_viewDir);
    float _sunDot = (_dirLen > 0.001) ? dot(normalize(_viewDir), _worldSunDir) : 0.0;

    // Bias: sun-facing horizon gets full tint, anti-sun side gets ~30 % of it.
    float _tintDirBias = _sunDot * 0.35 + 0.65;

    _col = mix(_col, _sunsetTint, _transW * SKY_SUNSET_TINT_STRENGTH * _tintDirBias);

    // Directional hot-spot: a concentrated warm glow right around the sun position,
    float _hotspot = pow(max(_sunDot, 0.0), 1.0 / max(SKY_SUNSET_HOTSPOT_WIDTH, 0.001));
    _col += _sunsetTint * _hotspot * _transW * SKY_SUNSET_HOTSPOT_STRENGTH * 0.5;

    // Twilight tint (uniform — twilight glow wraps the whole horizon evenly)
    vec3 _twilCol = vec3(SKY_TWILIGHT_R, SKY_TWILIGHT_G, SKY_TWILIGHT_B);
    _col = mix(_col, _twilCol, _twilW * SKY_TWILIGHT_STRENGTH);

    // Rain modulation
    // Desaturate: mix toward luminance-preserving grey.
    float _luma = dot(_col, vec3(0.299, 0.587, 0.114));
    _col = mix(_col, vec3(_luma), _rainStrength * RAIN_SKY_DESATURATE);
    // Darken: scale brightness down.
    _col *= 1.0 - _rainStrength * RAIN_SKY_DARKEN;

    return clamp(_col, 0.0, 1.0);
}

vec3 customHorizonFogColor(float _sunAngle, vec3 _viewDir) {
    return customHorizonFogColor(_sunAngle, _viewDir, 0.0);
}
vec3 customHorizonFogColor(float _sunAngle) {
    return customHorizonFogColor(_sunAngle, vec3(0.0), 0.0);
}

vec3 distortShadow(vec3 pos) {
    #if SHADOW_DISTORTION == 1
        float factor = length(pos.xy) + SHADOW_DISTORT_REDUCTION;
        return vec3(pos.xy / factor, pos.z * 0.5);
    #else
        return pos;
    #endif
}
