/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * ---------------------------------------------------------------------
 *
 * Portions of this file were modified and ported to Vala by Victor Vintorez in 2026.
 * These modifications are licensed under the European Union Public License (EUPL),
 * Version 1.2 or later. You may obtain a copy of the License at:
 * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 */

using GLib;

namespace MaterialColorUtilities {
	public sealed class ColorSpec2026 : ColorSpec2025 {

		private static double find_best_tone_for_chroma(double hue, double chroma, double tone, bool by_decreasing_tone) {
			double answer = tone;
			Hct best_candidate = Hct.from(hue, chroma, answer);
			while (best_candidate.chroma < chroma) {
				if (tone < 0 || tone > 100) {
					break;
				}
				tone += by_decreasing_tone ? -1.0 : 1.0;
				Hct new_candidate = Hct.from(hue, chroma, tone);
				if (best_candidate.chroma < new_candidate.chroma) {
					best_candidate = new_candidate;
					answer = tone;
				}
			}
			return answer;
		}

		private static double t_max_c(TonalPalette palette, double lower_bound = 0, double upper_bound = 100, double chroma_multipler = 1) {
			double answer = find_best_tone_for_chroma(palette.hue, palette.chroma * chroma_multipler, 100, true);
			return MathUtils.clamp_double(lower_bound, upper_bound, answer);
		}

		private static double t_min_c(TonalPalette palette, double lower_bound = 0, double upper_bound = 100) {
			double answer = find_best_tone_for_chroma(palette.hue, palette.chroma, 0, false);
			return MathUtils.clamp_double(lower_bound, upper_bound, answer);
		}

		private static ContrastCurve get_contrast_curve(double default_contrast) {
			if (default_contrast == 1.5) {
				return new ContrastCurve(1.5, 1.5, 3.0, 5.5);
			} else if (default_contrast == 3.0) {
				return new ContrastCurve(3.0, 3.0, 4.5, 7.0);
			} else if (default_contrast == 4.5) {
				return new ContrastCurve(4.5, 4.5, 7.0, 11.0);
			} else if (default_contrast == 6.0) {
				return new ContrastCurve(6.0, 6.0, 7.0, 11.0);
			} else if (default_contrast == 7.0) {
				return new ContrastCurve(7.0, 7.0, 11.0, 21.0);
			} else if (default_contrast == 9.0) {
				return new ContrastCurve(9.0, 9.0, 11.0, 21.0);
			} else if (default_contrast == 11.0) {
				return new ContrastCurve(11.0, 11.0, 21.0, 21.0);
			} else if (default_contrast == 21.0) {
				return new ContrastCurve(21.0, 21.0, 21.0, 21.0);
			} else {
				return new ContrastCurve(default_contrast, default_contrast, 7.0, 21.0);
			}
		}

		public override DynamicColor surface {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 4.0 : 98.0;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor surface_dim {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface_dim")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 4.0 : 87.0;
					} else {
						return 0.0;
					}
				})
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 1.0 : 1.7;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor surface_bright {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface_bright")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 18.0 : 98.0;
					} else {
						return 0.0;
					}
				})
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 1.7 : 1.0;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface_bright
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor surface_container_lowest {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface_container_lowest")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 0.0 : 100.0;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface_container_lowest
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor surface_container_low {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface_container_low")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 6.0 : 96.0;
					} else {
						return 0.0;
					}
				})
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.25;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface_container_low
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor surface_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface_container")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 9.0 : 94.0;
					} else {
						return 0.0;
					}
				})
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.4;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor surface_container_high {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface_container_high")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 12.0 : 92.0;
					} else {
						return 0.0;
					}
				})
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.5;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface_container_high
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor surface_container_highest {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("surface_container_highest")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => {
					if (s.variant == Variant.CMF) {
						return s.is_dark ? 15.0 : 90.0;
					} else {
						return 0.0;
					}
				})
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.7;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.surface_container_highest
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_surface {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_surface")
				     .set_palette((s) => s.neutral_palette)
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.7;
					} else {
						return 0.0;
					}
				})
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => s.is_dark ? get_contrast_curve(11) : get_contrast_curve(9))
				     .build();
				return base.on_surface
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_surface_variant {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_surface_variant")
				     .set_palette((s) => s.neutral_palette)
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.7;
					} else {
						return 0.0;
					}
				})
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => s.is_dark ? get_contrast_curve(6) : get_contrast_curve(4.5))
				     .build();
				return base.on_surface_variant
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor outline {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("outline")
				     .set_palette((s) => s.neutral_palette)
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.7;
					} else {
						return 0.0;
					}
				})
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => get_contrast_curve(3))
				     .build();
				return base.outline
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor outline_variant {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("outline_variant")
				     .set_palette((s) => s.neutral_palette)
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.7;
					} else {
						return 0.0;
					}
				})
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => get_contrast_curve(1.5))
				     .build();
				return base.outline_variant
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor inverse_surface {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("inverse_surface")
				     .set_palette((s) => s.neutral_palette)
				     .set_tone((s) => s.is_dark ? 98.0 : 4.0)
				     .set_chroma_multiplier((s) => {
					if (s.variant == Variant.CMF) {
						return 1.7;
					} else {
						return 0.0;
					}
				})
				     .set_is_background(true)
				     .build();
				return base.inverse_surface
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor inverse_on_surface {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("inverse_on_surface")
				     .set_palette((s) => s.neutral_palette)
				     .set_background((s) => inverse_surface)
				     .set_contrast_curve((s) => get_contrast_curve(7))
				     .build();
				return base.inverse_on_surface
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor primary {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("primary")
				     .set_palette((s) => s.primary_palette)
				     .set_tone((s) => s.source_color_hct.chroma <= 12 ? (s.is_dark ? 80.0 : 40.0) : s.source_color_hct.tone)
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => get_contrast_curve(4.5))
				     .set_tone_delta_pair((s) => s.platform == Platform.PHONE ?
				                          new ToneDeltaPair(primary_container, primary, 5, TonePolarity.RELATIVE_LIGHTER, true, DeltaConstraint.FARTHER) : null)
				     .build();
				return base.primary
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor? primary_dim {
			owned get {
				DynamicColor color_2026 = primary
				     .to_builder()
				     .set_name("primary_dim")
				     .build();
				return base.primary_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_primary {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_primary")
				     .set_palette((s) => s.primary_palette)
				     .set_background((s) => primary)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_primary
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor primary_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("primary_container")
				     .set_palette((s) => s.primary_palette)
				     .set_tone((s) => {
					if (!s.is_dark && s.source_color_hct.chroma <= 12) {
						return 90.0;
					}
					return s.source_color_hct.tone > 55 ? MathUtils.clamp_double(61, 90, s.source_color_hct.tone) : MathUtils.clamp_double(30, 49, s.source_color_hct.tone);
				})
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_tone_delta_pair((s) => new ToneDeltaPair(primary_container, primary, 5, TonePolarity.RELATIVE_LIGHTER, true, DeltaConstraint.FARTHER))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.primary_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_primary_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_primary_container")
				     .set_palette((s) => s.primary_palette)
				     .set_background((s) => primary_container)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_primary_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor primary_fixed {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("primary_fixed")
				     .set_palette((s) => s.primary_palette)
				     .set_tone((s) => {
					DynamicScheme temp_s = DynamicScheme.from(s, false, 0.0);
					return primary_container.get_tone(temp_s);
				})
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.primary_fixed
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor primary_fixed_dim {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("primary_fixed_dim")
				     .set_palette((s) => s.primary_palette)
				     .set_tone((s) => primary_fixed.get_tone(s))
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_tone_delta_pair((s) => new ToneDeltaPair(primary_fixed_dim, primary_fixed, 5, TonePolarity.DARKER, true, DeltaConstraint.EXACT))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.primary_fixed_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_primary_fixed {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_primary_fixed")
				     .set_palette((s) => s.primary_palette)
				     .set_background((s) => primary_fixed.get_tone(s) > 57 ? primary_fixed_dim : primary_fixed)
				     .set_contrast_curve((s) => get_contrast_curve(7))
				     .build();
				return base.on_primary_fixed
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_primary_fixed_variant {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_primary_fixed_variant")
				     .set_palette((s) => s.primary_palette)
				     .set_background((s) => primary_fixed.get_tone(s) > 57 ? primary_fixed_dim : primary_fixed)
				     .set_contrast_curve((s) => get_contrast_curve(4.5))
				     .build();
				return base.on_primary_fixed_variant
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor secondary {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("secondary")
				     .set_palette((s) => s.secondary_palette)
				     .set_tone((s) => s.is_dark ? t_min_c(s.secondary_palette) : t_max_c(s.secondary_palette))
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => get_contrast_curve(4.5))
				     .set_tone_delta_pair((s) => s.platform == Platform.PHONE ?
				                          new ToneDeltaPair(secondary_container, secondary, 5, TonePolarity.RELATIVE_LIGHTER, true, DeltaConstraint.FARTHER) : null)
				     .build();
				return base.secondary
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor? secondary_dim {
			owned get {
				DynamicColor color_2026 = secondary
				     .to_builder()
				     .set_name("secondary_dim")
				     .build();
				return base.secondary_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_secondary {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_secondary")
				     .set_palette((s) => s.secondary_palette)
				     .set_background((s) => secondary)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_secondary
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor secondary_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("secondary_container")
				     .set_palette((s) => s.secondary_palette)
				     .set_tone((s) => s.is_dark ? t_min_c(s.secondary_palette, 20, 49) : t_max_c(s.secondary_palette, 61, 90))
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.secondary_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_secondary_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_secondary_container")
				     .set_palette((s) => s.secondary_palette)
				     .set_background((s) => secondary_container)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_secondary_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor secondary_fixed {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("secondary_fixed")
				     .set_palette((s) => s.secondary_palette)
				     .set_tone((s) => {
					DynamicScheme temp_s = DynamicScheme.from(s, false, 0.0);
					return secondary_container.get_tone(temp_s);
				})
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.secondary_fixed
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor secondary_fixed_dim {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("secondary_fixed_dim")
				     .set_palette((s) => s.secondary_palette)
				     .set_tone((s) => secondary_fixed.get_tone(s))
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_tone_delta_pair((s) => new ToneDeltaPair(secondary_fixed_dim, secondary_fixed, 5, TonePolarity.DARKER, true, DeltaConstraint.EXACT))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.secondary_fixed_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_secondary_fixed {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_secondary_fixed")
				     .set_palette((s) => s.secondary_palette)
				     .set_background((s) => secondary_fixed.get_tone(s) > 57 ? secondary_fixed_dim : secondary_fixed)
				     .set_contrast_curve((s) => get_contrast_curve(7))
				     .build();
				return base.on_secondary_fixed
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_secondary_fixed_variant {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_secondary_fixed_variant")
				     .set_palette((s) => s.secondary_palette)
				     .set_background((s) => secondary_fixed.get_tone(s) > 57 ? secondary_fixed_dim : secondary_fixed)
				     .set_contrast_curve((s) => get_contrast_curve(4.5))
				     .build();
				return base.on_secondary_fixed_variant
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor tertiary {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("tertiary")
				     .set_palette((s) => s.tertiary_palette)
				     .set_tone((s) => s.source_color_hct_list.length > 1 ? s.source_color_hct_list[1].tone : s.source_color_hct.tone)
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => get_contrast_curve(4.5))
				     .set_tone_delta_pair((s) => s.platform == Platform.PHONE ?
				                          new ToneDeltaPair(tertiary_container, tertiary, 5, TonePolarity.RELATIVE_LIGHTER, true, DeltaConstraint.FARTHER) : null)
				     .build();
				return base.tertiary
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor? tertiary_dim {
			owned get {
				DynamicColor color_2026 = tertiary
				     .to_builder()
				     .set_name("tertiary_dim")
				     .build();
				return base.tertiary_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_tertiary {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_tertiary")
				     .set_palette((s) => s.tertiary_palette)
				     .set_background((s) => tertiary)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_tertiary
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor tertiary_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("tertiary_container")
				     .set_palette((s) => s.tertiary_palette)
				     .set_tone((s) => {
					Hct secondary_source_color_hct = s.source_color_hct_list.length > 1 ? s.source_color_hct_list[1] : s.source_color_hct;
					return secondary_source_color_hct.tone > 55 ? MathUtils.clamp_double(61, 90, secondary_source_color_hct.tone) : MathUtils.clamp_double(20, 49, secondary_source_color_hct.tone);
				})
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_tone_delta_pair((s) => new ToneDeltaPair(tertiary_container, tertiary, 5, TonePolarity.RELATIVE_LIGHTER, true, DeltaConstraint.FARTHER))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.tertiary_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_tertiary_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_tertiary_container")
				     .set_palette((s) => s.tertiary_palette)
				     .set_background((s) => tertiary_container)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_tertiary_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor tertiary_fixed {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("tertiary_fixed")
				     .set_palette((s) => s.tertiary_palette)
				     .set_tone((s) => {
					DynamicScheme temp_s = DynamicScheme.from(s, false, 0.0);
					return tertiary_container.get_tone(temp_s);
				})
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.tertiary_fixed
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor tertiary_fixed_dim {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("tertiary_fixed_dim")
				     .set_palette((s) => s.tertiary_palette)
				     .set_tone((s) => tertiary_fixed.get_tone(s))
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_tone_delta_pair((s) => new ToneDeltaPair(tertiary_fixed_dim, tertiary_fixed, 5, TonePolarity.DARKER, true, DeltaConstraint.EXACT))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.tertiary_fixed_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_tertiary_fixed {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_tertiary_fixed")
				     .set_palette((s) => s.tertiary_palette)
				     .set_background((s) => tertiary_fixed.get_tone(s) > 57 ? tertiary_fixed_dim : tertiary_fixed)
				     .set_contrast_curve((s) => get_contrast_curve(7))
				     .build();
				return base.on_tertiary_fixed
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_tertiary_fixed_variant {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_tertiary_fixed_variant")
				     .set_palette((s) => s.tertiary_palette)
				     .set_background((s) => tertiary_fixed.get_tone(s) > 57 ? tertiary_fixed_dim : tertiary_fixed)
				     .set_contrast_curve((s) => get_contrast_curve(4.5))
				     .build();
				return base.on_tertiary_fixed_variant
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor error {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("error")
				     .set_palette((s) => s.error_palette)
				     .set_tone((s) => t_max_c(s.error_palette))
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_contrast_curve((s) => get_contrast_curve(4.5))
				     .set_tone_delta_pair((s) => s.platform == Platform.PHONE ?
				                          new ToneDeltaPair(error_container, error, 5, TonePolarity.RELATIVE_LIGHTER, true, DeltaConstraint.FARTHER) : null)
				     .build();
				return base.error
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor? error_dim {
			owned get {
				DynamicColor color_2026 = error
				     .to_builder()
				     .set_name("error_dim")
				     .build();
				return base.error_dim
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_error {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_error")
				     .set_palette((s) => s.error_palette)
				     .set_background((s) => error)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_error
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor error_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("error_container")
				     .set_palette((s) => s.error_palette)
				     .set_tone((s) => s.is_dark ? t_min_c(s.error_palette) : t_max_c(s.error_palette))
				     .set_is_background(true)
				     .set_background((s) => highest_surface(s))
				     .set_tone_delta_pair((s) => new ToneDeltaPair(error_container, error, 5, TonePolarity.RELATIVE_LIGHTER, true, DeltaConstraint.FARTHER))
				     .set_contrast_curve((s) => s.contrast_level > 0 ? get_contrast_curve(1.5) : null)
				     .build();
				return base.error_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}

		public override DynamicColor on_error_container {
			owned get {
				DynamicColor color_2026 = new DynamicColorBuilder()
				     .set_name("on_error_container")
				     .set_palette((s) => s.error_palette)
				     .set_background((s) => error_container)
				     .set_contrast_curve((s) => get_contrast_curve(6))
				     .build();
				return base.on_error_container
				        .to_builder()
				        .extend_spec_version(SpecVersion.SPEC_2026, color_2026)
				        .build();
			}
		}
	}
}
