/**
 * Constant-time string equality (web-standard; no Node `crypto.timingSafeEqual` on Workers).
 * Length difference is folded into the accumulator — NO early return on length mismatch,
 * so comparison time does not leak the secret's length.
 */
export function timingSafeEqualStr(a: string, b: string): boolean {
  const enc = new TextEncoder();
  const ab = enc.encode(a);
  const bb = enc.encode(b);
  let diff = ab.length ^ bb.length;
  const max = Math.max(ab.length, bb.length);
  for (let i = 0; i < max; i++) {
    diff |= (ab[i] ?? 0) ^ (bb[i] ?? 0);
  }
  return diff === 0;
}
