Periodic discontinuity or jump in pattern

I have made a tiger print pattern that I like, but occasionally it has a discontinuity where the bright parts of the pattern change, looking like the pattern jumps rather than flowing. Then it will shift smoothly for around 50-70 seconds and then jump again? Does this have to do with the way I use time() or some kind of beforeRender(delta) artifact? Code follows:

// Waving Tiger Stripes 2D Pattern for Pixelblaze
// Creates orange and black stripes that wave across a 2D matrix

// Pattern parameters
export var speed = 0.1        // Wave speed
export var stripeWidth = 0.2  // Width of each stripe 
export var waveHeight = 0.4   // Height of the wave effect
export var brightness = 1.0   // Overall brightness
export var angle = 0.3        // Stripe angle (0 = horizontal, 0.5 = diagonal, 1 = vertical)


// Color definitions for tiger stripes
var orangeR = 1.0, orangeG = 0.4, orangeB = 0.0  // Tiger orange
var blackR = 0.0, blackG = 0.0, blackB = 0.0     // Black stripes

export function beforeRender(delta) {
  // Update time for animation
  t1 = time(speed)
  t2 = time(speed * 0.7) // Secondary wave for more complex motion
}

export function render2D(index, x, y) {
  // Create diagonal stripe pattern based on angle parameter
  var stripePos = x * (1 - angle) + y * angle
  
  // Create wave motion that varies across both X and Y
  var wave1 = sin(x * PI * 3 + y * PI * 2 + t1 * PI2) * waveHeight
  var wave2 = sin(x * PI * 1.5 + y * PI * 4 + t2 * PI2) * waveHeight * 0.5
  var wave3 = sin(y * PI * 2.7 + t1 * PI2 * 1.3) * waveHeight * 0.3
  var combinedWave = wave1 + wave2 + wave3
  
  // Apply wave distortion to stripe position
  // Use triangle() instead of adding time directly to avoid discontinuities
  var timeOffset = triangle(t1) * 4  // Triangle wave for smooth continuous motion
  var distortedStripePos = (stripePos + combinedWave) * (1 / stripeWidth) + timeOffset
  var stripeValue = sin(distortedStripePos * PI)
  
  // Determine if this pixel should be orange or black
  var isOrange = stripeValue > 0
  
  if (isOrange) {
    // Orange stripe with some variation based on position
    var intensity = (stripeValue * 0.3 + 0.7) * brightness
    // Add subtle variation based on Y position
    intensity *= (0.8 + 0.2 * sin(y * PI * 2))
    rgb(orangeR * intensity, orangeG * intensity, orangeB * intensity)
  } else {
    // Black stripe (very dim orange for subtle effect)
    var dimIntensity = abs(stripeValue) * 0.1 * brightness
    rgb(blackR + dimIntensity * 0.1, blackG + dimIntensity * 0.05, blackB)
  }
}

Try PI2 here. For sin to wrap properly it has to be in a range of 2 pi. Using wave might be easier with similar results, its input is 0-1 wrapped and outputs 0-1.