max / makeover
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+70 insertions,
-0 deletions
| @@ -1876,6 +1876,76 @@ | |||
| 1876 | 1876 | ); | |
| 1877 | 1877 | } | |
| 1878 | 1878 | ||
| 1879 | + | // The three tests above each measure a derived color against the face it was | |
| 1880 | + | // derived from, so a theme can pass all of them and still have nothing lift | |
| 1881 | + | // off anything: the face itself sits on the page, and that relationship is | |
| 1882 | + | // the one a bevel needs in order to read as an object rather than as a | |
| 1883 | + | // rectangle with decorated edges. makenot.work passed all three and could | |
| 1884 | + | // not hold a bevel, which is what this covers. | |
| 1885 | + | // | |
| 1886 | + | // The threshold is picked against the ramps already ruled on rather than | |
| 1887 | + | // against a round number. makenot.work shipped at 0.024 and was invisible, | |
| 1888 | + | // was tried at 0.036 and rejected as marginal on badges and chips, and was | |
| 1889 | + | // accepted at 0.058; goingson and audiofiles sit at 0.119 and 0.065. Every | |
| 1890 | + | // ramp judged inadequate is below 0.036 and every one judged adequate is | |
| 1891 | + | // above 0.058, so the line goes in the gap between them. Note the unit: this | |
| 1892 | + | // is oklab L on 0 to 1, not the CIE L* on 0 to 100 that the theme files quote | |
| 1893 | + | // in their comments, and the two are not interchangeable. | |
| 1894 | + | // | |
| 1895 | + | // Most of the list is imported palettes, which were authored for syntax | |
| 1896 | + | // highlighting and owe our depth model nothing. Failing here says a theme | |
| 1897 | + | // cannot hold a bevel, not that it is wrong. Shrinking the list is the fix; | |
| 1898 | + | // growing it is a regression in the theme, not in this derivation. | |
| 1899 | + | #[test] | |
| 1900 | + | fn raised_is_distinct_from_page() { | |
| 1901 | + | // Below this, a raised surface and the page under it are one surface to | |
| 1902 | + | // a reader, whichever direction the theme ramps in. | |
| 1903 | + | const MIN_DELTA_L: f32 = 0.05; | |
| 1904 | + | const CANNOT_LIFT_OFF_THE_PAGE: &[&str] = &[ | |
| 1905 | + | "akari-dawn", | |
| 1906 | + | "akari-night", | |
| 1907 | + | "ayu-light", | |
| 1908 | + | "ayu-mirage", | |
| 1909 | + | "catppuccin-latte", | |
| 1910 | + | "catppuccin-mocha", | |
| 1911 | + | "dawnfox", | |
| 1912 | + | "dracula", | |
| 1913 | + | "everforest", | |
| 1914 | + | "flatwhite", | |
| 1915 | + | "gruvbox-light", | |
| 1916 | + | "neobrute", | |
| 1917 | + | "one-dark", | |
| 1918 | + | "oxocarbon-dark", | |
| 1919 | + | "oxocarbon-light", | |
| 1920 | + | "poimandres", | |
| 1921 | + | "rosepine", | |
| 1922 | + | "rosepine-dawn", | |
| 1923 | + | "solarized-dark", | |
| 1924 | + | "tokyonight", | |
| 1925 | + | ]; | |
| 1926 | + | ||
| 1927 | + | let mut flat: Vec<String> = Vec::new(); | |
| 1928 | + | for (id, source) in embedded_themes() { | |
| 1929 | + | let theme = parse_theme_str(id, source, false).unwrap(); | |
| 1930 | + | let t = resolve(&theme); | |
| 1931 | + | let (Some(page), Some(raised)) = ( | |
| 1932 | + | t.hex("surface-page").and_then(Rgb::from_hex), | |
| 1933 | + | t.hex("surface-raised").and_then(Rgb::from_hex), | |
| 1934 | + | ) else { | |
| 1935 | + | continue; | |
| 1936 | + | }; | |
| 1937 | + | if (raised.to_oklab().l - page.to_oklab().l).abs() < MIN_DELTA_L { | |
| 1938 | + | flat.push(id.to_string()); | |
| 1939 | + | } | |
| 1940 | + | } | |
| 1941 | + | flat.sort(); | |
| 1942 | + | ||
| 1943 | + | assert_eq!( | |
| 1944 | + | flat, CANNOT_LIFT_OFF_THE_PAGE, | |
| 1945 | + | "themes whose raised surface is too close to the page to lift off it" | |
| 1946 | + | ); | |
| 1947 | + | } | |
| 1948 | + | ||
| 1879 | 1949 | // What the bevel pair does on a sixteen-color terminal, measured across the | |
| 1880 | 1950 | // shipped set rather than assumed. Two results, both load-bearing for a | |
| 1881 | 1951 | // consumer that has to render one there. |