@womp/mcp-ui 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ // GENERATED by scripts/gen-pantone.mjs from swan-frontend's PantoneCoatedColors.js — do not edit.
2
+ // 2390 Pantone coated colours, the list the web print panel snaps to.
3
+ // Packed as "code|hex;code|hex;…": codes without the trailing " C", hex without "#".
4
+ export const PANTONE_COATED_PACKED =
5
+ "100|f6eb61;101|f7ea48;102|fce300;103|c5a900;104|af9800;105|897a27;106|f9e547;107|fbe122;108|fedb00;109|ffd100;110|daaa00;111|aa8a00;112|9c8412;113|fae053;114|fbde40;115|fdda25;116|ffcd00;117|c99700;118|ac8400;119|897322;120|fbdb65;1205|f8e08e;121|fcd757;1215|fbd872;122|fed141;1225|ffc845;123|ffc72c;1235|ffb81c;124|eaaa00;1245|c69214;125|b58500;1255|ad841f;1265|886b25;126|9a7611;127|f3dd6d;128|f3d54e;129|f3d03e;130|f2a900;131|cc8a00;132|a07400;133|6c571b;134|fdd26e;1345|fdd086;135|ffc658;1355|ffc56e;136|ffbf3f;1365|ffb549;137|ffa400;1375|ff9e1b;138|de7c00;1385|d57800;139|af6d04;1395|996017;140|74531c;1405|6e4c1e;141|f2c75c;142|f1be48;143|f1b434;144|ed8b00;145|cf7f00;146|a76d11;147|715c2a;148|fecb8b;1485|ffae62;149|ffc27b;1495|ff8f1c;150|ffb25b;1505|ff6900;151|ff8200;152|e57200;1525|b94700;153|be6a14;1535|94450b;154|9b5a1a;1545|653818;155|efd19f;1555|ffb990;156|efbe7d;1565|ffa06a;157|eca154;1575|ff7f32;158|e87722;1585|ff6a14;159|cb6015;1595|d86018;160|a1561c;1605|a65523;161|603d20;1615|8b4720;162|ffbe9f;1625|ffa38b;163|ff9d6e;1635|ff8d6d;164|ff7f41;1645|ff6a39;165|ff6720;1655|fc4c02;166|e35205;1665|dc4405;167|be531c;1675|a9431e;168|73391d;1685|833921;169|ffb3ab;170|ff8674;171|ff5c39;172|fa4616;173|cf4520;174|963821;175|6b3529;176|ffb1bb;1765|ffa3b5;1767|fcafc0;177|ff808b;1775|ff8da1;1777|fb637e;178|ff585d;1785|f8485e;1787|f4364c;1788|ee2737;179|e03c31;1795|d22730;1797|cb333b;180|be3a34;1805|af272f;1807|a4343a;181|81312f;1815|7c2629;1817|643335;182|fabbcb;183|fc9bb3;184|f65275;185|e4002b;186|c8102e;187|a6192e;188|76232f;189|f8a3bc;1895|f5b6cd;190|f67599;1905|f59bbb;191|ef426f;1915|ef4b81;192|e40046;1925|e0004d;193|bf0d3e;1935|c5003e;194|9b2743;1945|a60a3d;195|782f40;1955|8a1538;196|ecc7cd;197|e89cae;198|df4661;199|d50032;200|ba0c2f;2001|f8e59a;2002|f9e27d;2003|f9e267;2004|fbdd7a;2005|fed880;2006|ebbc4e;2007|e0a526;2008|efc06e;2009|efb661;201|9d2235;2010|ffad00;2011|ed9b33;2012|ef9600;2013|ff9800;2014|b97000;2015|f8cfa9;2016|ffb673;2017|f8ad6d;2018|ff7500;2019|d76b00;202|862633;2020|be5400;2021|9d4815;2022|faaa8d;2023|fa9370;2024|f87c56;2025|ff8a3d;2026|f4633a;2027|ee5340;2028|eb3300;2029|f2827f;203|ecb3cb;2030|dd7975;2031|d66965;2032|d05a57;2033|c54644;2034|e73c3e;2035|d6001c;2036|f8bed6;2037|f395c7;2038|ef60a3;2039|e63888;204|e782a9;2040|db0b5b;2041|a1224e;2042|70273d;2043|eac4d2;2044|e793b7;2045|dd74a1;2046|cf578a;2047|a64570;2048|973961;2049|852c4d;205|e0457b;2050|efd7e5;2051|ddc2cf;2052|c89fb6;2053|b3809d;2054|9e708b;2055|905e7b;2056|7e4966;2057|cf92b7;2058|bb85ab;2059|b87ba1;206|ce0037;2060|c86ba8;2061|ad5389;2062|b4458d;2063|a5307c;2064|e0a2d4;2065|dea8dd;2066|d28dd3;2067|c069c2;2068|b14eb5;2069|a438a8;207|a50034;2070|8f1a95;2071|c7b2de;2072|b896d4;2073|af95d3;2074|9569be;2075|8866bc;2076|8659b5;2077|6e3fa3;2078|b59dbb;2079|9b7ea4;208|862041;2080|9873ac;2081|865e9c;2082|784e90;2083|965ec7;2084|7f35b2;2085|decde7;2086|a08bcb;2087|9b7dd4;2088|825dc7;2089|7248bd;209|6f263d;2090|6638b6;2091|4c12a1;2092|b8acd6;2093|a699c1;2094|8e7fae;2095|7965b2;2096|654ea3;2097|6244bb;2098|4a25aa;2099|b1a2ca;210|f99fc9;2100|9f8fca;2101|8a75d1;2102|6558b1;2103|5949a7;2104|483698;2105|39207c;2106|b1b5ce;2107|9099ba;2108|777fa8;2109|676d99;211|f57eb6;2110|5b618f;2111|464e7e;2112|351f65;2113|a5b0e3;2114|838dc8;2115|6f79bd;2116|6068b2;2117|44499c;2118|343579;2119|2c2e65;212|f04e98;2120|becae9;2121|8facd8;2122|9baee4;2123|7a93dc;2124|6f7bd4;2125|5461c8;2126|303ab2;2127|b8c9e1;2128|98b6e4;2129|5f8dda;2130|5576d1;2131|365abd;2132|0857c3;2133|1d57a5;2134|93a5cf;2135|758cc0;2136|8394b8;2137|6e80a9;2138|647692;2139|4d6995;213|e31c79;2140|395382;2141|8bbee8;2142|7fade3;2143|3d87cb;2144|0067b9;2145|004ea8;2146|00358e;2147|002677;2148|6191b4;2149|4c82a8;214|ce0f69;215|ac145a;2150|36749d;2151|256ba2;2152|1a658f;2153|00567e;2154|004680;2155|9eb5cb;2156|8ba6c1;2157|7594b3;2158|5c82a5;2159|4e769b;216|7d2248;2160|3e6991;2161|285780;2162|9ea6b4;2163|869cae;2164|7e93a7;2165|688197;2166|57728b;2167|506d85;2168|254a5d;2169|81b0d2;217|eabedb;2170|5f9bc6;2171|489fdf;2172|147bd1;2173|0084d5;2174|0076ce;2175|006ac6;2176|a6b8c1;2177|7fa0ac;2178|6b8f9c;2179|527a8a;218|e56db1;2180|3f6c7d;2181|2b5b6c;2182|174a5b;2183|0092bd;2184|0084d4;2185|0076a5;2186|004986;2187|004677;2188|00426a;2189|003349;219|da1984;2190|56b7e6;2191|00a3e1;2192|0091da;2193|0090da;2194|0086d6;2195|0077cf;2196|0069b1;2197|74d2e7;2198|4ac9e3;2199|00bbdc;220|a50050;2200|05a9c7;2201|00aed6;2202|00a5df;2203|0087ae;2204|afcdd7;2205|89b2c4;2206|779fb5;2207|659ab1;2208|5489a3;2209|4a86a0;221|910048;2210|074f71;2211|6f9ba4;2212|508590;2213|337179;2214|2f6f7a;2215|2e5665;2216|2d4d58;2217|003a40;2218|72b0bd;2219|5da3b2;222|6c1d45;2220|4797a8;2221|2d8c9e;2222|1d8296;2223|00788d;2224|006980;2225|78d5e1;2226|3ccbda;2227|59bec9;2228|00a5bd;2229|009cb6;223|ef95cf;2230|008ca0;2231|007c91;2232|71b0b4;2233|58a7af;2234|4f9fa6;2235|28939c;2236|2c9199;2237|05868e;2238|006975;2239|00cfb4;224|eb6fbd;2240|00c19f;2241|58a291;2242|00a376;2243|00957a;2244|1b806d;2245|008655;2246|a8d5ba;2247|77c19a;2248|71b790;2249|5caa7f;225|df1995;2250|00b373;2251|00ad6f;2252|00a74a;2253|bde9c9;2254|addfb3;2255|86d295;2256|56c271;2257|00ad50;2258|008522;2259|027223;226|d00070;2260|b6cfae;2261|9abb91;2262|8cac89;2263|74956c;2264|6b9560;2265|5c7e51;2266|335525;2267|9be198;2268|79d97c;2269|7ccc6c;2270|2cc84d;2271|00bb31;2272|009a17;2273|257226;2274|cfdcb1;2275|c3dc93;2276|89a84f;2277|55951b;2278|4e801f;2279|5e7e29;227|aa0061;228|890c58;2280|4a6a1d;2281|d9ea9a;2282|c7e995;2283|a7e163;2284|b3d57c;2285|93da49;2286|7acc00;2287|5bc500;2288|c8e379;2289|c5d97a;229|672146;2290|aadb1e;2291|a7d500;2292|93c90f;2293|8bc400;2294|78aa00;2295|e0ec89;2296|d6e865;2297|c0df16;2298|b7db57;2299|a4d233;230|f4a6d7;2300|a9c23f;2301|8fad15;2302|aeb862;2303|9eb356;2304|a0ab4d;2305|9ea700;2306|808c24;2307|686f12;2308|5d551d;2309|e7ceb5;231|f277c6;2310|d9c0a9;2311|cda786;2312|b79a81;2313|c39367;2314|ac7644;2315|914910;2316|bd9a7a;2317|b4875e;2318|a47449;2319|8c5c30;232|e93cac;2320|714623;2321|6f5138;2322|4e3524;2323|b8b298;2324|b2a384;2325|a09074;2326|8b7c5e;2327|837a58;2328|786748;2329|68593c;233|c6007e;2330|cfcdc9;2331|aea8a5;2332|8c8985;2333|716e6a;2334|6c6463;2335|5e5047;2336|4e4b48;2337|f8c1b8;2338|dea39c;2339|f09491;234|a20067;2340|cf6f77;2341|b66c6d;2342|b65a65;2343|a85566;2344|f18070;2345|ff6d6a;2346|ff5869;2347|e10600;2348|e5554f;2349|ca3604;235|840b55;2350|af231c;2351|bd7ab3;2352|b565a7;2353|bf4da5;2354|924e8c;2355|87037b;2356|720062;2357|621244;2358|ada4ae;2359|7f7384;236|f1a7dc;2360|7b798e;2361|70708d;2362|6c6a81;2363|605d75;2364|66596c;2365|efbae1;2366|6a6dcd;2367|4f4cb1;2368|4d49be;2369|3b3fb6;237|ec86d0;2370|2f2a95;2371|33058d;2372|281e78;2373|73829f;2374|4d5f80;2375|e277cd;2376|4e5b73;2377|315470;2378|384967;2379|3b4559;238|e45dbf;2380|28334a;2381|5e93db;2382|008ad8;2383|2774ae;2384|0061a0;2385|d539b5;2386|2d68c4;2387|0762c8;2388|0050b5;2389|4c9fc8;239|db3eb1;2390|077cab;2391|0081a6;2392|166886;2393|0092cb;2394|008bce;2395|c800a1;2396|0099b2;2397|00b7bd;2398|00bab3;2399|00aca0;240|c5299b;2400|00b097;2401|34a798;2402|009d85;2403|00897b;2404|a5b99c;2405|b0008e;2406|819e87;2407|6b8d73;2408|497b55;2409|4e6548;241|af1685;2410|445a3e;2411|1c4220;2412|48d597;2413|34b78f;2414|00bb7e;2415|9e007e;2416|00b176;2417|249e6b;2418|00873e;2419|007c58;242|80225f;2420|00c65e;2421|30b700;2422|00a82d;2423|00aa13;2424|279f00;2425|830065;2426|008c15;2427|025f1d;2428|de882d;2429|c25e1c;243|eab8e4;2430|d7a179;2431|de9353;2432|de8c59;2433|db7b51;2434|e3785e;2435|c17059;2436|b6533e;2437|f2bfa0;2438|e3a184;2439|c48672;244|e59bdc;2440|b59289;2441|a86f5f;2442|9f5f54;2443|8e3a22;2444|dda69d;2445|dd878d;2446|d0858b;2447|b06f76;2448|da6254;2449|472426;245|dd7fd3;2450|d74388;2451|b74271;2452|c3366f;2453|b996c3;2454|287da1;2455|93bdb4;2456|319c8a;2457|8baa99;2458|689881;2459|56b093;246|c724b1;2460|6aafaa;2461|259591;2462|5a8d84;2463|5b7671;2464|79be70;2465|1e6f30;2466|2a514d;2467|b7926c;2468|986a4c;2469|8f583b;247|bb16a3;2470|9a7f62;2471|a58877;2472|5f4029;2473|c4b8bd;2474|b0a198;2475|a1877f;2476|826b6a;2477|705854;2478|4c363a;2479|3e342f;248|a51890;249|80286c;250|e7bae4;251|dd9cdf;252|c964cf;253|ad1aac;254|981e97;255|72246c;256|d6bfdd;2562|d7a9e3;2563|cba3d8;2567|c1a0da;257|c6a1cf;2572|c98bdb;2573|b884cb;2577|a77bca;258|8c4799;2582|ac4fc6;2583|a05eb5;2587|8246af;259|6d2077;2592|9b26b6;2593|84329b;2597|5c068c;260|642667;2602|87189d;2603|702082;2607|500878;261|5d295f;2612|772583;2613|671e75;2617|470a68;262|51284f;2622|653165;2623|5f2167;2627|3c1053;263|d7c6e6;2635|c5b4e3;264|c1a7e2;2645|ad96dc;265|9063cd;2655|9678d3;266|753bbd;2665|7d55c7;267|5f249f;268|582c83;2685|330072;269|512d6d;2695|2e1a47;270|b4b5df;2705|a7a4e0;2706|cbd3ea;2707|c3d7ee;2708|b8ccea;271|9595d2;2715|8b84d7;2716|9faee5;2717|a7c6ed;2718|5c88da;272|7474c1;2725|685bc7;2726|485cc7;2727|307fe2;2728|0047bb;273|24125f;2735|2e008b;2736|1e22aa;2738|06038d;274|221551;2745|280071;2746|171c8f;2747|001a72;2748|001871;275|211747;2755|250e62;2756|151f6d;2757|001e60;2758|001e62;276|221c35;2765|201547;2766|141b4d;2767|13294b;2768|071d49;277|abcae9;278|8bb8e8;279|418fde;280|012169;281|00205b;282|041e42;283|92c1e9;284|6cace4;285|0072ce;286|0032a0;287|003087;288|002d72;289|0c2340;290|b9d9eb;2905|8dc8e8;291|9bcbeb;2915|62b5e5;292|69b3e7;2925|009cde;293|003da5;2935|0057b7;294|002f6c;2945|004c97;295|002855;2955|003865;296|051c2c;2965|00263e;297|71c5e8;2975|99d6ea;298|41b6e6;2985|5bc2e7;299|00a3e0;2995|00a9e0;300|005eb8;3005|0077c8;301|004b87;3015|00629b;302|003b5c;3025|004f71;303|002a3a;3035|003e51;304|9adbe8;305|59cbe8;306|00b5e2;307|006ba6;308|00587c;309|003b49;310|6ad1e3;3105|67d2df;311|05c3dd;3115|00c1d4;312|00a9ce;3125|00aec7;313|0092bc;3135|008eaa;314|007fa3;3145|00778b;315|00677f;3155|006271;316|004851;3165|004f59;317|b1e4e3;318|88dbdf;319|2cccd3;320|009ca6;321|008c95;322|007377;323|005f61;324|9cdbd9;3242|71dbd4;3245|7ce0d3;3248|6dcdb8;325|64ccc9;3252|2ad2c9;3255|2cd5c4;3258|49c5b1;326|00b2a9;3262|00bfb2;3265|00c7b1;3268|00ab8e;327|008675;3272|00a499;3275|00b398;3278|009b77;328|007367;3282|008578;3285|009681;3288|008264;329|00685e;3292|00594f;3295|007864;3298|006a52;330|00534c;3302|004c45;3305|004e42;3308|024638;331|a7e6d7;332|8ce2d0;333|3cdbc0;334|009775;335|007b5f;336|00664f;337|8fd6bd;3375|7ae1bf;338|6eceb2;3385|47d7ac;339|00b388;3395|00c389;340|00965e;3405|00af66;341|007a53;3415|007749;342|006747;3425|006341;343|115740;3435|154734;344|a0dab3;345|91d6ac;346|71cc98;347|009a44;348|00843d;349|046a38;350|2c5234;3500|006e33;3501|4cae04;3506|1961ae;3507|aed000;3508|5e7930;351|a2e4b8;3514|f6b700;3515|61007d;3516|dc3513;3517|c10016;3519|e1a6ad;352|8fe2b0;3520|b27bc4;3522|00892f;3523|742e34;3524|2f2951;3526|7a939c;3527|d5419e;3529|1fa824;353|80e0a7;3533|69dbc8;3534|00b2a2;3535|400186;3536|007737;3537|00491e;3538|0094d5;3539|3e9a2c;354|00b140;3541|00939d;3542|31137c;3543|a48dd1;3544|dfb8a7;3545|00bce1;3546|cd001a;3547|c59014;355|009739;3551|00a6c8;3553|006eb3;3555|512179;3556|ee3831;3557|007c80;3558|919cd4;3559|8e51a8;356|007a33;3560|00a497;3561|79c300;3564|ef6a00;3566|472b74;3568|f0c8d9;357|215732;3570|b1d600;3572|ff9da2;3574|5c4580;3575|9672c4;3577|8abadd;358|addc91;3581|22326e;3582|d173a6;3583|511e84;3584|2e3e80;3588|ff9425;359|a1d884;3590|3c57a1;3591|03257e;3593|9b6eb6;3595|f1bcd5;3596|debc8b;3597|1c3775;3599|dac287;360|6cc24a;361|43b02a;362|509e2f;363|4c8d2b;364|4a7729;365|c2e189;366|b7dd79;367|a4d65e;368|78be21;369|64a70b;370|658d1b;371|546223;372|d4ec8e;373|cdea80;374|c5e86c;375|97d700;376|84bd00;377|7a9a01;378|59621d;379|e2e868;380|dbe442;381|cedc00;382|c4d600;383|a8ad00;384|949300;385|787121;386|e9ec6b;387|e3e935;388|e0e722;389|d0df00;390|b5bd00;391|9a9500;392|827a04;393|f0ec74;3935|f3ea5d;394|ede939;3945|f3e600;395|ece81a;3955|efdf00;396|e1e000;3965|eedc00;397|bfb800;3975|bba600;398|ada400;3985|9a8700;399|a09200;3995|685c20;400|c4bfb6;4001|e9db9c;4002|dcc681;4003|d5c897;4004|c9b777;4005|c0ad7b;4006|bba370;4007|ad965f;4008|f4af23;4009|f19c49;401|afa9a0;4010|e56910;4011|de754c;4012|ea733d;4013|cc6c27;4014|b86748;4015|d3c763;4016|d5bf39;4017|deb83b;4018|d1b249;4019|c2a84d;402|9d968d;4020|bf9f00;4021|af9335;4022|ceb47e;4023|d2b467;4024|d4ad67;4025|d7a048;4026|bc8c3d;4027|8e6320;4028|83602b;4029|e9cda5;403|8c857b;4030|f1caad;4031|eacbbb;4032|f5cabf;4033|f7bcac;4034|cb9576;4035|c79674;4036|c09a97;4037|b47d75;4038|b17368;4039|ad6960;404|776e64;4040|956a64;4041|815e58;4042|7a5d53;4043|e1c4ae;4044|c4a28a;4045|ba9682;4046|b29780;4047|ab8c75;4048|a18269;4049|96826d;405|696158;4050|d9ac95;4051|df8877;4052|da8879;4053|cf7b69;4054|a9533f;4055|a55343;4056|874f47;4057|e2665c;4058|e44b55;4059|c12f41;406|c4bcb7;4060|bd3742;4061|bd625e;4062|a84544;4063|9b3f34;4064|ebb4bb;4065|e4aeb1;4066|eaa09c;4067|e89e9d;4068|e48f93;4069|c74e61;407|b2a8a2;4070|b53b50;4071|cf879d;4072|df7a99;4073|c64771;4074|7d1b49;4075|823550;4076|824259;4077|834553;4078|e7c1d5;4079|cda7c1;408|978c87;4080|d0b0ca;4081|af90a7;4082|a86590;4083|865991;4084|713c62;4085|c8b7ad;4086|bca5a5;4087|b79f97;4088|a88b80;4089|a48c88;409|857874;4090|8f7368;4091|7b605e;4092|caa7b5;4093|ae9093;4094|916976;4095|8b5a6b;4096|78494d;4097|744d51;4098|65443d;4099|ac8584;410|746661;4100|7e4d4d;4101|622128;4102|551c25;4103|51252f;4104|543a3b;4105|663f34;4106|c4aab2;4107|ad92a4;4108|a58496;4109|9e7889;411|5e514d;4110|8a6d7f;4111|7c576a;4112|8c6d73;4113|a38d91;4114|9b8c92;4115|948082;4116|988383;4117|726477;4118|46394e;4119|403845;412|382f2d;4120|b8acd0;4121|9b8bb5;4122|776cb1;4123|a5a7bc;4124|8f91b0;4125|5f5e77;4126|514163;4127|808194;4128|6e7185;4129|676f7f;413|babbb1;4130|515a6c;4131|484b5d;4132|3b3a4a;4133|3b3b46;4134|a0a2b0;4135|7b859b;4136|606e81;4137|475d76;4138|4c5f71;4139|4f5a6b;414|a8a99e;4140|393d47;4141|4964a2;4142|3d4e80;4143|435570;4144|3a3a59;4145|2e334e;4146|1b1d36;4147|26213f;4148|6197b0;4149|8aaac5;415|919388;4150|517db9;4151|0067ac;4152|135193;4153|1a4e8a;4154|0e4174;4155|b9c9cc;4156|97bfcb;4157|65aec1;4158|387f97;4159|005683;416|7e7f74;4160|004860;4161|304c5a;4162|a8d3c4;4163|8fcab9;4164|1c8172;4165|1d6960;4166|417571;4167|32645c;4168|244545;4169|b6c8c2;417|65665c;4170|a4bdba;4171|9bb9b5;4172|81b0aa;4173|84c4c0;4174|83c1c0;4175|93bbc2;4176|c4cec2;4177|bbbeae;4178|a8af99;4179|96a480;418|51534a;4180|8f9980;4181|738670;4182|6a7866;4183|b9c1b4;4184|9aab9e;4185|88a29a;4186|6a8e89;4187|687c7b;4188|445d5c;4189|1c4a50;419|212322;4190|a7b2a3;4191|94a59e;4192|859587;4193|62685a;4194|566361;4195|646566;4196|47565a;4197|8a9b8e;4198|697e70;4199|59695c;420|c7c9c7;4200|596c62;4201|4f685d;4202|384e46;4203|2e483e;4204|c1d1a6;4205|a7c186;4206|8dae81;4207|7da177;4208|3e7054;4209|38584b;421|b2b4b2;4210|304f42;4211|cfd993;4212|86ad3f;4213|6a9033;4214|5b7954;4215|526e3e;4216|3e5824;4217|4b5e23;4218|afb59d;4219|a4aa96;422|9ea2a2;4220|888a77;4221|7b7d60;4222|727563;4223|626951;4224|3e4938;4225|8b8372;4226|868165;4227|6a6851;4228|59563e;4229|5b5c4a;423|898d8d;4230|58534b;4231|635c4f;4232|d2cf05;4233|c0be00;4234|bbc25c;4235|b0b07c;4236|bfbe69;4237|aba360;4238|8d8b53;4239|c8c3b3;424|707372;4240|cabfa5;4241|baac88;4242|88764f;4243|836a4d;4244|7e694f;4245|5a5040;4246|cdc4aa;4247|d1c1a8;4248|d5c2a5;4249|c3ad8b;425|545859;4250|bba887;4251|b8a279;4252|b6a284;4253|baa58d;4254|bf9972;4255|ad9677;4256|aa9071;4257|947d6f;4258|6f5d58;4259|322923;426|25282a;4260|cda890;4261|9d6e46;4262|a8714e;4263|ab6e49;4264|ac7052;4265|9b6448;4266|9a5f3a;4267|c1b2a2;4268|b3a08e;4269|ab9278;427|d0d3d4;4270|95866f;4271|8e7a6b;4272|7e6a5d;4273|4e4544;4274|b0b7b9;4275|abaeab;4276|9d9c9e;4277|8f8b90;4278|7e7e82;4279|5a5357;428|c1c6c8;4280|252a36;4281|b2b1b2;4282|b0aaab;4283|a9a2a1;4284|736b74;4285|69616c;4286|5f555d;4287|454142;4288|b7bcb4;4289|999998;429|a2aaad;4290|928b8a;4291|746e6e;4292|716d6e;4293|645b64;4294|575257;430|7c878e;431|5b6770;432|333f48;433|1d252d;434|d0c4c5;435|c1b2b6;436|ab989d;437|7b6469;438|584446;439|453536;440|382e2c;441|bec6c4;442|a2acab;443|919d9d;444|717c7d;445|505759;446|3f4443;447|373a36;448|4a412a;4485|614f25;449|524627;4495|8c7732;450|594a25;4505|998542;451|9b945f;4515|b3a369;452|b0aa7e;4525|c5b783;453|bfbb98;4535|cfc493;454|cac7a7;4545|d5cb9f;455|695b24;456|a28e2a;457|b89d18;458|d9c756;459|decd63;460|e4d77e;461|e9df97;462|5c462b;4625|4f2c1d;463|744f28;4635|946037;464|8b5b29;4645|ad7c59;465|b9975b;4655|bf9474;466|c6aa76;4665|cda788;467|d3bc8d;4675|dcbfa6;468|ddcba4;4685|e0c6ad;469|693f23;4695|5b3427;470|a45a2a;4705|7c4d3a;471|b86125;4715|956c58;472|e59e6d;4725|ae8a79;473|f0bf9b;4735|c0a392;474|f1c6a6;4745|cdb5a7;475|f3cfb3;4755|d7c4b7;476|4e3629;477|623b2a;478|713f2a;479|aa8066;480|c6a992;481|d3bba8;482|dbc8b6;483|653024;484|9a3324;485|da291c;486|e8927c;487|eaa794;488|ecbaa8;489|ecc3b2;490|5d2a2c;491|7f3035;492|8f3237;493|dc8699;494|e9a2b2;495|f1bdc8;496|f2c6cf;497|512f2e;4975|3f2021;498|6a3735;4985|874b52;499|7a3e3a;4995|9c6169;500|c6858f;5005|b07c83;501|daa5ad;5015|cca1a6;502|e5bac1;5025|dbb7bb;503|e9c5c7;5035|dfc2c3;504|572932;505|6f2c3f;506|84344e;507|d592aa;508|e4a9bb;509|e8b3c3;510|ebbecb;511|612c51;5115|512a44;512|833177;5125|693c5e;513|93328e;5135|7e5475;514|d48bc8;5145|9b7793;515|e2acd7;5155|bfa5b8;516|e6bedd;5165|d3c0cd;517|ebc6df;5175|d8c8d1;518|4b3048;5185|4a3041;519|59315f;5195|66435a;520|642f6c;5205|86647a;521|a57fb2;5215|af95a6;522|ba9cc5;5225|c6b0bc;523|c9b1d0;5235|d0bec7;524|d5c2d8;5245|dbcdd3;525|572c5f;5255|1e1a34;526|702f8a;5265|403a60;527|8031a7;5275|595478;528|b580d1;5285|8d89a5;529|caa2dd;5295|b3b0c4;530|d7b9e4;5305|c6c4d2;531|dfc8e7;5315|d8d7df;532|1d1f2a;533|202a44;534|1b365d;535|8e9fbc;536|a2b2c8;537|bbc7d6;538|c5cfda;539|00263a;5395|091f2c;540|003057;5405|4f758b;541|003c71;5415|5b7f95;542|7bafd4;5425|7a99ac;543|a4c8e1;5435|a6bbc8;544|bdd6e6;5445|b7c9d3;545|c6dae7;5455|bfced6;546|072b31;5463|07272d;5467|18332f;547|00313c;5473|115e67;5477|3e5d58;548|003d4c;5483|4f868e;5487|5e7975;549|6ba4b8;5493|7fa9ae;5497|829995;550|8db9ca;5503|94b7bb;5507|9db0ac;551|a3c7d2;5513|abc7c9;5517|b1c0bc;552|b9d3dc;5523|b6cfd0;5527|bcc9c5;553|284734;5535|183029;554|205c40;5545|43695b;555|28724f;5555|5c7f71;556|6fa287;5565|7f9c90;557|85b09a;5575|92aca0;558|9abeaa;5585|a7bdb1;559|adcab8;5595|bfcec2;560|1d3c34;5605|22372b;561|00594c;5615|5e7461;562|006f62;5625|708573;563|6bbbae;5635|94a596;564|86c8bc;5645|a3b2a4;5655|b0bdb0;565|a1d6ca;566|b9dcd2;5665|bac5b9;567|173f35;568|006c5b;569|00816d;570|6bcaba;571|98dbce;572|a5dfd3;573|b5e3d8;574|4e5b31;5743|3e4827;5747|3d441e;575|67823a;5753|5e6738;5757|6d712e;576|789d4a;5763|737b4c;5767|8a8d4a;577|a9c47f;5773|899064;5777|a2a568;578|b7ce95;5783|a3aa83;5787|babd8b;579|bcd19b;5793|b3b995;5797|c6c89b;580|c4d6a4;5803|c3c6a8;5807|d0d1ab;581|625d20;5815|555025;582|8e8c13;5825|89813d;583|b7bf10;5835|a09958;584|d2d755;5845|afa96e;585|dbde70;5855|c0bb87;586|e0e27c;5865|cbc793;587|e3e48d;5875|d2ce9e;600|f1eb9c;6001|e7d083;6002|e8c871;6003|e1b74c;6004|ddad33;6005|d9a51b;6006|cf9616;6007|bc7b28;6008|bc9e7a;6009|af8c62;601|f0e991;6010|a47f54;6011|9d7748;6012|875f32;6013|7b5127;6014|67502d;6015|f0b285;6016|f49d61;6017|fb914a;6018|f58132;6019|ef6b0d;602|f0e87b;6020|e25800;6021|d75a1b;6022|f5c0b5;6023|eab19e;6024|e69684;6025|dc826b;6026|d57559;6027|c3623f;6028|ba5b3f;6029|d1afad;603|ede04b;6030|c79e99;6031|ba8f85;6032|b18278;6033|a97669;6034|a06a5a;6035|945e4b;6036|be8e98;6037|ac767e;6038|a2666e;6039|93565c;604|eada24;6040|864549;6041|7b393c;6042|612e2e;6043|f3909e;6044|f08592;6045|ed7b86;6046|e56c73;6047|d04d46;6048|d24f4e;6049|bb452e;605|e1cd00;6050|fba8d0;6051|fb83ad;6052|e76e93;6053|f65c87;6054|dd5681;6055|d34368;6056|ca3a57;6057|d25ea1;6058|c94c91;6059|c4448a;606|cfb500;6060|be3c80;6061|b43174;6062|b22e6d;6063|a42b5f;6064|d0aec6;6065|c89bb2;6066|c08ea7;6067|b48098;6068|ab758f;6069|9c637d;607|ebe49a;6070|98627a;6071|937898;6072|745276;6073|674568;6074|613e5f;6075|583756;6076|462a42;6077|392734;6078|c094ce;6079|b37ec0;608|e9e186;6080|a369b1;6081|9e60ac;6082|90509b;6083|833e8d;6084|773580;6085|c8ceea;6086|aeb5d8;6087|9ea7cd;6088|8b96c2;6089|7c89c1;609|e6de77;6090|6b74ac;6091|54609a;6092|8c8fc7;6093|8488c2;6094|7779b7;6095|6f72b4;6096|5f5fa5;6097|4f529b;6098|42458e;6099|90a5db;610|e1d555;6100|7992cb;6101|6680c3;6102|5c77b6;6103|405397;6104|213b8b;6105|283883;6106|b5bfd5;6107|a5b3ce;6108|8fa4c0;6109|7890b0;611|d7c826;6110|7188a8;6111|627a9d;6112|3b5c7f;6113|6c8797;6114|668090;6115|597482;6116|4b6775;6117|46616f;6118|32464d;6119|2e3c41;612|c4b000;6120|3aa5d5;6121|009ccf;6122|008bc4;6123|0085bf;6124|007cb7;6125|0074aa;6126|005d9c;6127|63b3ca;6128|36a2bc;6129|0093ad;613|b39b00;6130|00859d;6131|00728b;6132|007a99;6133|00657f;6134|82cad3;6135|71b9bf;6136|4ba6aa;6137|369da0;6138|049193;6139|008587;614|dcd59a;6140|007d7e;6141|84cec3;6142|63c0ad;6143|27b093;6144|00a481;6145|00966e;6146|008a60;6147|008153;6148|d3e0ea;6149|bcd5da;615|d6cf8d;6150|9ec6c6;6151|81b8b6;6152|63a193;6153|458b77;6154|267859;6155|72a694;6156|5a9680;6157|48896f;6158|337f60;6159|167254;616|d0c883;6160|0d5d3f;6161|174c38;6162|3aac79;6163|00a26c;6164|009f64;6165|009353;6166|008c48;6167|00753a;6168|007742;6169|74bb7d;617|c0b661;6170|67b171;6171|5ba763;6172|509659;6173|2e8840;6174|2b7e3d;6175|2f723e;6176|9ac0a5;6177|87b18f;6178|71a37b;6179|5b9768;618|ac9f3c;6180|498759;6181|40814e;6182|367542;6183|798772;6184|6f8067;6185|637158;6186|57664d;6187|4f5c43;6188|43523b;6189|2d3d32;619|9f912a;6190|e3eaba;6191|e2e9a6;6192|d2e177;6193|c6d843;6194|b5c900;6195|97b300;6196|94b000;6197|d7d9d2;6198|c9ccc0;6199|bdbeae;620|8a7b19;6200|b5b5a0;6201|a1a288;6202|949778;6203|90906f;6204|a7a392;6205|999179;6206|8f866e;6207|898067;6208|786f55;6209|6d6448;621|d1e0d7;6210|60583d;6211|8d949b;6212|7e8389;6213|72787d;6214|6b7073;6215|606667;6216|505250;6217|464946;6218|949fac;6219|83909b;622|b7cdc2;6220|76828d;6221|6a7883;6222|5f6e77;6223|4f5e67;6224|47555d;623|9ab9ad;624|789f90;625|507f70;626|285c4d;627|13322b;628|b7dde1;629|9bd3dd;630|77c5d5;631|3eb1c8;632|0093b2;633|007396;634|005f83;635|a4dbe8;636|8bd3e6;637|4ec3e0;638|00afd7;639|0095c8;640|0082ba;641|0067a0;642|d1dde6;643|c6d6e3;644|9bb8d3;645|7da1c4;646|5e8ab4;647|236192;648|002e5d;649|dbe2e9;650|ced9e5;651|a7bcd6;652|7d9cc0;653|326295;654|003a70;655|002554;656|dde5ed;657|c8d8eb;658|b1c9e8;659|7ba4db;660|407ec9;661|003594;662|001a70;663|e5e1e6;664|e0dbe3;665|c6bcd0;666|a192b2;667|7c6992;668|614b79;669|3f2a56;670|ead3e2;671|e6bcd7;672|dfa0c9;673|d986ba;674|c7579a;675|ae2573;676|960051;677|e5cedb;678|e3c8d8;679|debed2;680|c996b6;681|b06c95;682|994878;683|7c2855;684|e4c6d4;685|dcb6c9;686|d0a1ba;687|be84a3;688|a76389;689|893b67;690|612141;691|e9cdd0;692|e3bec3;693|d7a3ab;694|c48490;695|b46b7a;696|984857;697|893c47;698|f2d4d7;699|f4c3cc;700|f2acb9;701|e68699;702|d25b73;703|b83a4b;704|9e2b2f;705|f5dadf;706|f7ced7;707|f8b5c4;708|f891a5;709|ef6079;710|e03e52;711|cb2c30;712|fcc89b;713|fdbe87;714|fdaa63;715|f68d2e;716|ea7600;717|d45d00;718|be4d00;719|edc8a3;720|e7b78a;721|dda46f;722|c88242;723|b36924;724|934d11;725|7d4016;726|e0c09f;727|d9b48f;728|cda177;729|b58150;730|9e652e;731|774212;732|623412;7401|f5e1a4;7402|ecd898;7403|eed484;7404|f4da40;7405|f2cd00;7406|f1c400;7407|cba052;7408|f6be00;7409|f0b323;7410|fead77;7411|e6a65d;7412|d38235;7413|dc8633;7414|c16c18;7415|e6baa8;7416|e56a54;7417|e04f39;7418|cd545b;7419|b04a5a;7420|9b2242;7421|651c32;7422|f4cdd4;7423|e06287;7424|e24585;7425|b52555;7426|a4123f;7427|971b2f;7428|6a2c3e;7429|e2bccb;7430|dca9bf;7431|c9809e;7432|b55c80;7433|a73a64;7434|9b3359;7435|872651;7436|eedaea;7437|ccaed0;7438|d59ed7;7439|b288b9;7440|a277a6;7441|9f5cc0;7442|963cbd;7443|dddae8;7444|b6b8dc;7445|a7a2c3;7446|8986ca;7447|5d4777;7448|4b384c;7449|41273b;7450|bdc5db;7451|89abe3;7452|8194dd;7453|7ca6de;7454|5f8fb4;7455|3a5dae;7456|606eb2;7457|bbdde6;7458|71b2c9;7459|4298b5;7460|0086bf;7461|007dba;7462|00558c;7463|002b49;7464|a0d1ca;7465|40c1ac;7466|00b0b9;7467|00a3ad;7468|007398;7469|005f86;7470|005a6f;7471|7eddd3;7472|5cb8b2;7473|279989;7474|007681;7475|477a7b;7476|0d5257;7477|244c5a;7478|9be3bf;7479|26d07c;7480|00bf6f;7481|00b74f;7482|009f4d;7483|275d38;7484|00573f;7485|d0debb;7486|bce194;7487|8edd65;7488|78d64b;7489|74aa50;7490|719949;7491|79863c;7492|bfcc80;7493|bbc592;7494|9caf88;7495|8f993e;7496|76881d;7497|7a7256;7498|5b6236;7499|f1e6b2;7500|dfd1a7;7501|d9c89d;7502|ceb888;7503|a89968;7504|94795d;7505|816040;7506|efdbb2;7507|fcd299;7508|e1b87f;7509|d6a461;7510|c6893f;7511|b77729;7512|a6631b;7513|e1b7a7;7514|d5a286;7515|c58b68;7516|99552b;7517|85431e;7518|6d4f47;7519|5d4b3c;7520|eabeb0;7521|c09c83;7522|b46a55;7523|ab5c57;7524|a45248;7525|9a6a4f;7526|8a391b;7527|d6d2c4;7528|c5b9ac;7529|b7a99a;7530|a39382;7531|7a6855;7532|63513d;7533|473729;7534|d1ccbd;7535|b7b09c;7536|a69f88;7537|a7aca2;7538|949a90;7539|8e9089;7540|4b4f54;7541|d9e1e2;7542|a4bcc2;7543|98a4ae;7544|768692;7545|425563;7546|253746;7547|131e29;7548|ffc600;7549|ffb600;7550|d19000;7551|b47e00;7552|73531d;7553|5a4522;7554|4b3d2a;7555|d29f13;7556|b78b20;7557|9f7d23;7558|967126;7559|8f6a2a;7560|7d622e;7561|6c5d34;7562|bd9b60;7563|d69a2d;7564|db8a06;7565|cd7925;7566|ad6433;7567|89532f;7568|785135;7569|d78825;7570|d3832b;7571|c67d30;7572|b67233;7573|a7662b;7574|9e6a37;7575|835d32;7576|db864e;7577|e07e3c;7578|db6b30;7579|dc582a;7580|c05131;7581|864a33;7582|674736;7583|c4622d;7584|ba5826;7585|b05c37;7586|9e5330;7587|924c2e;7588|7b4d35;7589|5c4738;7590|d4b59e;7591|c07d59;7592|b15533;7593|9d432c;7594|7c3a2d;7595|6b3d2e;7596|5c3d31;7597|d14124;7598|bd472a;7599|b33d26;7600|8d3f2b;7601|83412c;7602|7b4931;7603|674230;7604|e4d5d3;7605|e1bbb4;7606|d6938a;7607|c26e60;7608|a4493d;7609|823b34;7610|683431;7611|ddbcb0;7612|ca9a8e;7613|bc8a7e;7614|a47f74;7615|866761;7616|6b4c4c;7617|583d3e;7618|c66e4e;7619|c04c36;7620|b7312c;7621|ab2328;7622|93282c;7623|8a2b2b;7624|802f2d;7625|e1523e;7626|c63527;7627|a72b2a;7628|9e2a2b;7629|6d3332;7630|633231;7631|572d2d;7632|d6c9ca;7633|c4a4a7;7634|c16784;7635|c63663;7636|bc204b;7637|912f46;7638|7e2d40;7639|936d73;7640|934054;7641|8e2c48;7642|732e4a;7643|672e45;7644|582d40;7645|502b3a;7646|a56e87;7647|a83d72;7648|991e66;7649|8a1b61;7650|722257;7651|6a2a5b;7652|5e2751;7653|948794;7654|a2789c;7655|a15a95;7656|8e3a80;7657|6e2b62;7658|6a3460;7659|5d3754;7660|9991a4;7661|8d6e97;7662|7a4282;7663|6b3077;7664|653379;7665|5e366e;7666|5c4e63;7667|6e7ca0;7668|676e9f;7669|615e9b;7670|565294;7671|514689;7672|4c4084;7673|535486;7674|878cb4;7675|7c7fab;7676|7566a0;7677|6f5091;7678|68478d;7679|563d82;7680|523178;7681|94a9cb;7682|6787b7;7683|426da9;7684|385e9d;7685|2c5697;7686|1d4f91;7687|1d4289;7688|4698ca;7689|298fc2;7690|0076a8;7691|006298;7692|005687;7693|004976;7694|01426a;7695|7ba7bc;7696|6399ae;7697|4e87a0;7698|41748d;7699|34657f;7700|165c7d;7701|005776;7702|48a9c5;7703|009cbd;7704|0085ad;7705|007096;7706|006a8e;7707|00617f;7708|005670;7709|63b1bc;7710|00a7b5;7711|0097a9;7712|00859b;7713|007d8a;7714|007680;7715|006269;7716|00968f;7717|00857d;7718|007672;7719|006d68;7720|00635b;7721|005e5d;7722|005151;7723|50a684;7724|00966c;7725|008755;7726|007b4b;7727|006f44;7728|006845;7729|005844;7730|4b9560;7731|228848;7732|007a3e;7733|007041;7734|286140;7735|36573b;7736|385542;7737|6ba539;7738|47a23f;7739|309b42;7740|3a913f;7741|44883e;7742|4a783c;7743|44693d;7744|babc16;7745|abad23;7746|999b30;7747|888d30;7748|7c8034;7749|727337;7750|656635;7751|cab64b;7752|cfb023;7753|c1a01f;7754|a08629;7755|897630;7756|736635;7757|675e33;7758|d4c304;7759|c4b200;7760|91852c;7761|747136;7762|5d6439;7763|585c3b;7764|535435;7765|bbb323;7766|b4a91f;7767|aa9d2e;7768|8f7e35;7769|716135;7770|635939;7771|4e4934;801|009ace;802|44d62c;803|ffe900;804|ffaa4d;805|ff7276;806|ff3eb5;807|ea27c2;871|84764d;872|8b734a;873|896e4b;874|8a6f4c;875|8e6d4f;876|95694c;877|8d9092;Black 0961|9e978e;Black 2|332f21;Black 3|212721;Black 4|31261d;Black 5|3e2b2e;Black 6|101820;Black 7|3d3935;Black|2d2926;Blue 072|10069f;Blue 0821|74d1ea;Bright Red|f93822;Cool Gray 1|d9d9d6;Cool Gray 10|63666a;Cool Gray 11|53565a;Cool Gray 2|d0d0ce;Cool Gray 3|c8c9c7;Cool Gray 4|bbbcbc;Cool Gray 5|b1b3b3;Cool Gray 6|a7a8a9;Cool Gray 7|97999b;Cool Gray 8|888b8d;Cool Gray 9|75787b;Dark Blue|00249c;Green 0921|9de7d7;Green|00ab84;Magenta 0521|f1b2dc;Medium Purple|4e008e;Orange 016|ff5600;Orange 021|fe5000;Pink|d62598;Process Blue|0085ca;Purple|bb29bb;Purple v2|b041b1;Real Purple|c92fbf;Red 032|ef3340;Red 0331|fcaebb;Reflex Blue|001489;Rhodamine Red|e10098;Rubine Red|ce0058;Violet 0631|bf9bde;Violet|440099;Violet v2|3d0385;Warm Gray 1|d7d2cb;Warm Gray 10|796e65;Warm Gray 11|6e6259;Warm Gray 2|cbc4bc;Warm Gray 3|bfb8af;Warm Gray 4|b6ada5;Warm Gray 5|aca39a;Warm Gray 6|a59c94;Warm Gray 7|968c83;Warm Gray 8|8c8279;Warm Gray 9|83786f;Warm Red|f9423a;Yellow 012|ffd700;Yellow 0131|f2f0a1;Yellow|fedd00;Yellow PY12|f6dd00";
@@ -0,0 +1,224 @@
1
+ import { PANTONE_COATED_PACKED } from "./pantone-coated";
2
+
3
+ /**
4
+ * Pantone coated matching for the print card — the card's half of what the
5
+ * web print panel does in `NearestPantone.ts` / `PrintingColorEditor`.
6
+ *
7
+ * The panel lets the user pick any colour, snaps it to the nearest of 2390
8
+ * Pantone coated shades (`color-diff`'s `closest`, i.e. CIEDE2000 in Lab), shows
9
+ * "Pantone 2386 C" under the picker, and sends the Pantone CODE with the order.
10
+ * Chat orders send a hex (`OrderItem.color` is read either way), so the card
11
+ * does the same snap and sends the snapped shade's OWN hex: a chat order and a
12
+ * panel order for the same tint then land on the same printed colour, and the
13
+ * user sees the same Pantone name in both places.
14
+ *
15
+ * CIEDE2000 is implemented here rather than pulled from `color-diff` because
16
+ * the card is one self-contained file that crosses the wire on every
17
+ * `resources/read`; the formula is ~40 lines, the dependency is not. The Lab
18
+ * conversion is the standard sRGB (D65) one `color-diff` uses, so the snap
19
+ * agrees with the panel's.
20
+ */
21
+ export interface Pantone {
22
+ /** Display code, e.g. "2386 C". */
23
+ code: string;
24
+ /** Lowercase "#rrggbb". */
25
+ hex: string;
26
+ }
27
+
28
+ interface Table {
29
+ codes: string[];
30
+ hexes: string[];
31
+ /** L, a, b triples, flat. */
32
+ lab: Float64Array;
33
+ }
34
+
35
+ let table: Table | undefined;
36
+
37
+ function load(): Table {
38
+ if (table) return table;
39
+ const parts = PANTONE_COATED_PACKED.split(";");
40
+ const codes: string[] = [];
41
+ const hexes: string[] = [];
42
+ const lab = new Float64Array(parts.length * 3);
43
+ parts.forEach((part, i) => {
44
+ const bar = part.indexOf("|");
45
+ codes.push(`${part.slice(0, bar)} C`);
46
+ const hex = part.slice(bar + 1);
47
+ hexes.push(`#${hex}`);
48
+ const [L, a, b] = hexToLab(hex);
49
+ lab[i * 3] = L;
50
+ lab[i * 3 + 1] = a;
51
+ lab[i * 3 + 2] = b;
52
+ });
53
+ table = { codes, hexes, lab };
54
+ return table;
55
+ }
56
+
57
+ /** "#abc" / "abc" / "#AABBCC" → "#aabbcc"; anything else → undefined. */
58
+ export function normalizeHex(input: string | null | undefined): string | undefined {
59
+ if (!input) return undefined;
60
+ let s = input.trim().toLowerCase().replace(/^#/, "");
61
+ if (/^[0-9a-f]{3}$/.test(s)) s = s.replace(/./g, (c) => c + c);
62
+ return /^[0-9a-f]{6}$/.test(s) ? `#${s}` : undefined;
63
+ }
64
+
65
+ /**
66
+ * What the panel's hex field does on commit: a 1–5 digit shorthand is expanded
67
+ * to six digits rather than rejected, so "f" is white and "27e" a blue.
68
+ */
69
+ export function expandHexInput(raw: string): string | undefined {
70
+ const s = raw.trim().toLowerCase().replace(/^#/, "");
71
+ if (!s || /[^0-9a-f]/.test(s) || s.length > 6) return undefined;
72
+ if (s.length === 6) return `#${s}`;
73
+ if (s.length === 3) return `#${s.replace(/./g, (c) => c + c)}`;
74
+ if (s.length === 1) return `#${s.repeat(6)}`;
75
+ if (s.length === 2) return `#${s.repeat(3)}`;
76
+ return `#${s.padEnd(6, s[s.length - 1])}`;
77
+ }
78
+
79
+ /** The Pantone coated shade nearest to `hex`, by CIEDE2000 — the panel's rule. */
80
+ export function nearestPantone(hex: string): Pantone {
81
+ const t = load();
82
+ const [L, a, b] = hexToLab(hex.replace(/^#/, ""));
83
+ let best = 0;
84
+ let bestD = Infinity;
85
+ for (let i = 0; i < t.codes.length; i++) {
86
+ const d = ciede2000(L, a, b, t.lab[i * 3], t.lab[i * 3 + 1], t.lab[i * 3 + 2]);
87
+ if (d < bestD) {
88
+ bestD = d;
89
+ best = i;
90
+ }
91
+ }
92
+ return { code: t.codes[best], hex: t.hexes[best] };
93
+ }
94
+
95
+ /**
96
+ * One-tap choices: a spread of hues plus neutrals, each snapped to a real
97
+ * Pantone coated shade so a chip IS a Pantone, not an approximation of one.
98
+ * Computed once — 24 × 2390 CIEDE2000 evaluations, a few milliseconds.
99
+ */
100
+ const CHIP_TARGETS = [
101
+ "#fedd00", // yellow
102
+ "#ffb81c", // amber
103
+ "#ff8200", // orange
104
+ "#fe5000", // red-orange
105
+ "#ef3340", // red
106
+ "#ce0058", // rubine
107
+ "#e10098", // magenta
108
+ "#f7a8c4", // soft pink
109
+ "#bb29bb", // purple
110
+ "#440099", // violet
111
+ "#7d55c7", // lavender
112
+ "#001489", // navy
113
+ "#2d68c4", // the panel's default tint (2386 C)
114
+ "#0085ca", // process blue
115
+ "#41b6e6", // sky
116
+ "#00b2a9", // teal
117
+ "#00ad50", // green
118
+ "#78be20", // lime
119
+ "#a37b45", // brown
120
+ "#f3e5ab", // cream
121
+ "#d9d9d6", // cool gray 1
122
+ "#75787b", // cool gray 9
123
+ "#2d2926", // black
124
+ "#ffffff", // white
125
+ ];
126
+
127
+ let chips: Pantone[] | undefined;
128
+
129
+ export function pantoneChips(): Pantone[] {
130
+ if (chips) return chips;
131
+ const seen = new Set<string>();
132
+ chips = [];
133
+ for (const target of CHIP_TARGETS) {
134
+ const p = nearestPantone(target);
135
+ if (seen.has(p.code)) continue;
136
+ seen.add(p.code);
137
+ chips.push(p);
138
+ }
139
+ return chips;
140
+ }
141
+
142
+ // --- colour science -------------------------------------------------------
143
+
144
+ function hexToLab(hex: string): [number, number, number] {
145
+ const r = parseInt(hex.slice(0, 2), 16) / 255;
146
+ const g = parseInt(hex.slice(2, 4), 16) / 255;
147
+ const b = parseInt(hex.slice(4, 6), 16) / 255;
148
+ const lin = (c: number) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
149
+ const R = lin(r);
150
+ const G = lin(g);
151
+ const B = lin(b);
152
+ // sRGB → XYZ (D65), then XYZ → Lab against the D65 white point.
153
+ const X = (R * 0.4124564 + G * 0.3575761 + B * 0.1804375) / 0.95047;
154
+ const Y = R * 0.2126729 + G * 0.7151522 + B * 0.072175;
155
+ const Z = (R * 0.0193339 + G * 0.119192 + B * 0.9503041) / 1.08883;
156
+ const f = (t: number) => (t > 0.008856 ? Math.cbrt(t) : 7.787 * t + 16 / 116);
157
+ const fx = f(X);
158
+ const fy = f(Y);
159
+ const fz = f(Z);
160
+ return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)];
161
+ }
162
+
163
+ const rad = (deg: number) => (deg * Math.PI) / 180;
164
+ const deg = (r: number) => (r * 180) / Math.PI;
165
+
166
+ function hueOf(a: number, b: number): number {
167
+ if (a === 0 && b === 0) return 0;
168
+ const h = deg(Math.atan2(b, a));
169
+ return h < 0 ? h + 360 : h;
170
+ }
171
+
172
+ /** CIEDE2000 colour difference (Sharma, Wu & Dalal 2005), kL = kC = kH = 1. */
173
+ function ciede2000(L1: number, a1: number, b1: number, L2: number, a2: number, b2: number): number {
174
+ const C1 = Math.hypot(a1, b1);
175
+ const C2 = Math.hypot(a2, b2);
176
+ const Cbar = (C1 + C2) / 2;
177
+ const Cbar7 = Cbar ** 7;
178
+ const G = 0.5 * (1 - Math.sqrt(Cbar7 / (Cbar7 + 25 ** 7)));
179
+ const a1p = (1 + G) * a1;
180
+ const a2p = (1 + G) * a2;
181
+ const C1p = Math.hypot(a1p, b1);
182
+ const C2p = Math.hypot(a2p, b2);
183
+ const h1p = hueOf(a1p, b1);
184
+ const h2p = hueOf(a2p, b2);
185
+
186
+ const dLp = L2 - L1;
187
+ const dCp = C2p - C1p;
188
+ let dhp = 0;
189
+ if (C1p * C2p !== 0) {
190
+ dhp = h2p - h1p;
191
+ if (dhp > 180) dhp -= 360;
192
+ else if (dhp < -180) dhp += 360;
193
+ }
194
+ const dHp = 2 * Math.sqrt(C1p * C2p) * Math.sin(rad(dhp / 2));
195
+
196
+ const Lbp = (L1 + L2) / 2;
197
+ const Cbp = (C1p + C2p) / 2;
198
+ let hbp: number;
199
+ if (C1p * C2p === 0) hbp = h1p + h2p;
200
+ else {
201
+ const sum = h1p + h2p;
202
+ if (Math.abs(h1p - h2p) <= 180) hbp = sum / 2;
203
+ else hbp = sum < 360 ? (sum + 360) / 2 : (sum - 360) / 2;
204
+ }
205
+
206
+ const T =
207
+ 1 -
208
+ 0.17 * Math.cos(rad(hbp - 30)) +
209
+ 0.24 * Math.cos(rad(2 * hbp)) +
210
+ 0.32 * Math.cos(rad(3 * hbp + 6)) -
211
+ 0.2 * Math.cos(rad(4 * hbp - 63));
212
+ const dTheta = 30 * Math.exp(-(((hbp - 275) / 25) ** 2));
213
+ const Cbp7 = Cbp ** 7;
214
+ const RC = 2 * Math.sqrt(Cbp7 / (Cbp7 + 25 ** 7));
215
+ const SL = 1 + (0.015 * (Lbp - 50) ** 2) / Math.sqrt(20 + (Lbp - 50) ** 2);
216
+ const SC = 1 + 0.045 * Cbp;
217
+ const SH = 1 + 0.015 * Cbp * T;
218
+ const RT = -Math.sin(rad(2 * dTheta)) * RC;
219
+
220
+ const l = dLp / SL;
221
+ const c = dCp / SC;
222
+ const h = dHp / SH;
223
+ return Math.sqrt(l * l + c * c + h * h + RT * c * h);
224
+ }
@@ -0,0 +1,277 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Womp upload</title>
6
+ <style>
7
+ /* Same var()-with-fallback discipline as the other cards: host style
8
+ variables arrive over the bridge after the handshake, not as CSS
9
+ custom properties, so the card must look right without them. */
10
+ :root {
11
+ color-scheme: light dark;
12
+ --bg: var(--color-background-secondary, #1b1b1d);
13
+ --bg2: var(--color-background-tertiary, #27272b);
14
+ --fg: var(--color-text-primary, #ececec);
15
+ --fg2: var(--color-text-secondary, rgba(236, 236, 236, 0.62));
16
+ --line: var(--color-border-primary, rgba(255, 255, 255, 0.1));
17
+ --accent: var(--color-background-accent, #5867dd);
18
+ --ring: var(--color-ring-primary, #7aa2ff);
19
+ --danger: var(--color-text-danger, #ff8080);
20
+ --ok: #4fbf7a;
21
+ --warn: #e0a83a;
22
+ --r-md: var(--border-radius-md, 10px);
23
+ --r-lg: var(--border-radius-lg, 14px);
24
+ --fs-xs: var(--font-text-xs-size, 11px);
25
+ --fs-sm: var(--font-text-sm-size, 13px);
26
+ }
27
+ body {
28
+ margin: 0;
29
+ font-family: var(--font-sans, system-ui, -apple-system, "Segoe UI", sans-serif);
30
+ color: var(--fg);
31
+ }
32
+ button {
33
+ font: inherit;
34
+ color: inherit;
35
+ }
36
+ [hidden] {
37
+ display: none !important;
38
+ }
39
+
40
+ .card {
41
+ max-width: 360px;
42
+ padding: 14px;
43
+ border-radius: var(--r-lg);
44
+ background: var(--bg);
45
+ border: 1px solid var(--line);
46
+ box-sizing: border-box;
47
+ display: grid;
48
+ grid-template-columns: minmax(0, 1fr);
49
+ gap: 12px;
50
+ }
51
+ :root[data-display-mode="fullscreen"] .card {
52
+ max-width: 560px;
53
+ margin: 16px auto;
54
+ }
55
+
56
+ .head {
57
+ display: grid;
58
+ gap: 2px;
59
+ }
60
+ .title {
61
+ font-size: var(--fs-sm);
62
+ font-weight: 600;
63
+ overflow-wrap: anywhere;
64
+ }
65
+ .sub {
66
+ font-size: var(--fs-xs);
67
+ color: var(--fg2);
68
+ }
69
+
70
+ /* --- The drop zone. Drag-and-drop from the desktop, or the button for a
71
+ picker; both hand the same File to the same upload. ------------- */
72
+ .drop {
73
+ display: grid;
74
+ justify-items: center;
75
+ gap: 8px;
76
+ padding: 18px 14px;
77
+ border: 1.5px dashed var(--line);
78
+ border-radius: var(--r-md);
79
+ background: var(--bg2);
80
+ text-align: center;
81
+ transition: border-color 120ms ease, background 120ms ease;
82
+ }
83
+ .drop.active {
84
+ border-color: var(--ring);
85
+ background: color-mix(in srgb, var(--ring) 12%, var(--bg2));
86
+ }
87
+ .drop-icon {
88
+ width: 26px;
89
+ height: 26px;
90
+ color: var(--fg2);
91
+ }
92
+ .drop-text {
93
+ font-size: var(--fs-sm);
94
+ }
95
+ .drop-hint {
96
+ font-size: var(--fs-xs);
97
+ color: var(--fg2);
98
+ }
99
+ .drop input {
100
+ display: none;
101
+ }
102
+
103
+ .btn {
104
+ height: 32px;
105
+ padding: 0 14px;
106
+ border-radius: var(--r-md);
107
+ border: 1px solid var(--line);
108
+ background: var(--bg);
109
+ cursor: pointer;
110
+ font-size: var(--fs-sm);
111
+ font-weight: 500;
112
+ }
113
+ .btn:hover:not(:disabled) {
114
+ border-color: var(--ring);
115
+ }
116
+ .btn:focus-visible {
117
+ outline: 2px solid var(--ring);
118
+ outline-offset: 1px;
119
+ }
120
+ .btn:disabled {
121
+ opacity: 0.6;
122
+ cursor: default;
123
+ }
124
+ .btn.primary {
125
+ background: var(--accent);
126
+ border-color: transparent;
127
+ color: #fff;
128
+ }
129
+
130
+ /* --- Progress. Holds at 99% until the server answers: the last byte
131
+ leaving the browser is not the end, the store still has to happen,
132
+ and a stalled "100%" reads as a hang. ---------------------------- */
133
+ .progress {
134
+ display: grid;
135
+ gap: 6px;
136
+ }
137
+ .bar {
138
+ height: 6px;
139
+ border-radius: 999px;
140
+ background: var(--bg2);
141
+ overflow: hidden;
142
+ }
143
+ .fill {
144
+ height: 100%;
145
+ width: 0%;
146
+ border-radius: inherit;
147
+ background: var(--accent);
148
+ transition: width 160ms ease;
149
+ }
150
+ .progress-text {
151
+ display: flex;
152
+ justify-content: space-between;
153
+ font-size: var(--fs-xs);
154
+ color: var(--fg2);
155
+ font-variant-numeric: tabular-nums;
156
+ }
157
+
158
+ /* --- Outcome strips: done (green), expired (amber), error (red). ------ */
159
+ .strip {
160
+ display: flex;
161
+ gap: 10px;
162
+ align-items: flex-start;
163
+ padding: 10px 12px;
164
+ border-radius: var(--r-md);
165
+ border-left: 3px solid var(--ok);
166
+ background: color-mix(in srgb, var(--ok) 12%, transparent);
167
+ font-size: var(--fs-sm);
168
+ }
169
+ .strip.warn {
170
+ border-left-color: var(--warn);
171
+ background: color-mix(in srgb, var(--warn) 12%, transparent);
172
+ }
173
+ .strip.error {
174
+ border-left-color: var(--danger);
175
+ background: color-mix(in srgb, var(--danger) 12%, transparent);
176
+ }
177
+ .strip svg {
178
+ flex: none;
179
+ width: 16px;
180
+ height: 16px;
181
+ margin-top: 1px;
182
+ }
183
+ .strip .body {
184
+ display: grid;
185
+ gap: 4px;
186
+ min-width: 0;
187
+ }
188
+ .strip .body b {
189
+ overflow-wrap: anywhere;
190
+ }
191
+ .strip .muted {
192
+ font-size: var(--fs-xs);
193
+ color: var(--fg2);
194
+ }
195
+
196
+ .actions {
197
+ display: flex;
198
+ gap: 8px;
199
+ flex-wrap: wrap;
200
+ }
201
+
202
+ /* Names the failing layer instead of going blank — there is no console
203
+ inside the sandboxed iframe. Empty collapses. */
204
+ .status {
205
+ font-size: var(--fs-xs);
206
+ color: var(--fg2);
207
+ }
208
+ .status.error {
209
+ color: var(--danger);
210
+ }
211
+ .status:empty {
212
+ display: none;
213
+ }
214
+ </style>
215
+ </head>
216
+ <body>
217
+ <div class="card" id="card">
218
+ <div class="head">
219
+ <div class="title" id="title">Send your 3D model to Womp</div>
220
+ <div class="sub" id="sub">so it can be quoted and printed</div>
221
+ </div>
222
+
223
+ <div class="drop" id="drop" hidden>
224
+ <svg class="drop-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true">
225
+ <path d="M12 16V4m0 0-4 4m4-4 4 4" stroke-linecap="round" stroke-linejoin="round" />
226
+ <path d="M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" stroke-linecap="round" />
227
+ </svg>
228
+ <div class="drop-text" id="drop-text">Drop the file here</div>
229
+ <button class="btn" id="choose" type="button">Choose file</button>
230
+ <div class="drop-hint" id="drop-hint"></div>
231
+ <input type="file" id="file" aria-label="3D model file" />
232
+ </div>
233
+
234
+ <div class="progress" id="progress" hidden>
235
+ <div class="bar"><div class="fill" id="fill"></div></div>
236
+ <div class="progress-text"><span id="progress-name"></span><span id="progress-pct">0%</span></div>
237
+ </div>
238
+
239
+ <div class="strip" id="done" hidden>
240
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
241
+ <path d="M5 12.5 9.5 17 19 7" stroke-linecap="round" stroke-linejoin="round" />
242
+ </svg>
243
+ <div class="body">
244
+ <div><b id="done-name"></b><span id="done-size"></span> is on Womp.</div>
245
+ <div class="muted">Reply in the chat and your assistant will quote the print.</div>
246
+ </div>
247
+ </div>
248
+
249
+ <div class="strip warn" id="expired" hidden>
250
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
251
+ <circle cx="12" cy="12" r="9" />
252
+ <path d="M12 7v5l3 2" stroke-linecap="round" />
253
+ </svg>
254
+ <div class="body">
255
+ <div>This upload link expired before <b id="expired-name"></b> arrived.</div>
256
+ <div class="muted">Ask your assistant for a new one.</div>
257
+ </div>
258
+ </div>
259
+
260
+ <div class="strip error" id="error" hidden>
261
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
262
+ <circle cx="12" cy="12" r="9" />
263
+ <path d="M12 8v5m0 3v.5" stroke-linecap="round" />
264
+ </svg>
265
+ <div class="body">
266
+ <div id="error-text"></div>
267
+ <div class="actions" id="error-actions" hidden>
268
+ <button class="btn" id="open-page" type="button">Open the upload page instead</button>
269
+ </div>
270
+ </div>
271
+ </div>
272
+
273
+ <div class="status" id="status">Connecting&hellip;</div>
274
+ </div>
275
+ <script type="module" src="./main.ts"></script>
276
+ </body>
277
+ </html>