///|
/// SIMD is limited to backends with contiguous UTF-16 string storage. The
/// experimental core API is confined to these private scanners. Scalar
/// prefixes protect short CSS tokens; scalar tails avoid out-of-range loads.
#cfg(any(target="native", target="wasm"))
#warnings("-alert_experimental")
#borrow(input)
#inline
fn scan_name(input : String, start : Int32, end : Int32) -> Int32 {
  // Common CSS property names fit here; defer SIMD setup until longer runs.
  let prefix_end = if end - start < 32 { end } else { start + 32 }
  let mut pos = scan_name_scalar(input, start, prefix_end)
  if pos < prefix_end || pos == end {
    return pos
  }
  if end - pos < 8 {
    return scan_name_scalar(input, pos, end)
  }
  let fold = @v128.i16x8_splat(0x20)
  let a = @v128.i16x8_splat('a')
  let alphabet_range = @v128.i16x8_splat(25)
  let zero = @v128.i16x8_splat('0')
  let digit_range = @v128.i16x8_splat(9)
  let underscore = @v128.i16x8_splat('_')
  let dash = @v128.i16x8_splat('-')
  let ascii_limit = @v128.i16x8_splat(127)
  while end - pos >= 8 {
    let block = @v128.v128_load_i16x8(input, pos)
    let letters = @v128.i16x8_le_u(
      @v128.i16x8_sub(@v128.v128_or_(block, fold), a),
      alphabet_range,
    )
    let digits = @v128.i16x8_le_u(@v128.i16x8_sub(block, zero), digit_range)
    let valid = @v128.v128_or_(
      @v128.v128_or_(letters, digits),
      @v128.v128_or_(
        @v128.i16x8_gt_u(block, ascii_limit),
        @v128.v128_or_(
          @v128.i16x8_eq(block, underscore),
          @v128.i16x8_eq(block, dash),
        ),
      ),
    )
    if !@v128.i16x8_all_true(valid) {
      let mask = @v128.i16x8_bitmask(valid)
      return pos + (mask ^ 0xFF).ctz()
    }
    pos += 8
  }
  scan_name_scalar(input, pos, end)
}

///|
#cfg(any(target="native", target="wasm"))
#warnings("-alert_experimental")
#borrow(input)
#inline
fn scan_whitespace(input : String, start : Int32, end : Int32) -> Int32 {
  let prefix_end = if end - start < 4 { end } else { start + 4 }
  let mut pos = scan_whitespace_scalar(input, start, prefix_end)
  if pos < prefix_end || pos == end {
    return pos
  }
  if end - pos < 8 {
    return scan_whitespace_scalar(input, pos, end)
  }
  let space = @v128.i16x8_splat(' ')
  let tab = @v128.i16x8_splat('\t')
  let lf = @v128.i16x8_splat('\n')
  let cr = @v128.i16x8_splat('\r')
  while end - pos >= 8 {
    let block = @v128.v128_load_i16x8(input, pos)
    let valid = @v128.v128_or_(
      @v128.v128_or_(@v128.i16x8_eq(block, space), @v128.i16x8_eq(block, tab)),
      @v128.v128_or_(@v128.i16x8_eq(block, lf), @v128.i16x8_eq(block, cr)),
    )
    if !@v128.i16x8_all_true(valid) {
      let mask = @v128.i16x8_bitmask(valid)
      return pos + (mask ^ 0xFF).ctz()
    }
    pos += 8
  }
  scan_whitespace_scalar(input, pos, end)
}

///|
#cfg(any(target="native", target="wasm"))
#warnings("-alert_experimental")
#borrow(input)
#inline
fn find_string_special(
  input : String,
  start : Int32,
  end : Int32,
  quote : UInt16,
) -> Int32 {
  let prefix_end = if end - start < 8 { end } else { start + 8 }
  let mut pos = find_string_special_scalar(input, start, prefix_end, quote)
  if pos < prefix_end || pos == end {
    return pos
  }
  if end - pos < 8 {
    return find_string_special_scalar(input, pos, end, quote)
  }
  let quote_lanes = @v128.i16x8_splat(quote)
  let slash = @v128.i16x8_splat('\\')
  let lf = @v128.i16x8_splat('\n')
  let cr = @v128.i16x8_splat('\r')
  while end - pos >= 8 {
    let block = @v128.v128_load_i16x8(input, pos)
    let special = @v128.v128_or_(
      @v128.v128_or_(
        @v128.i16x8_eq(block, quote_lanes),
        @v128.i16x8_eq(block, slash),
      ),
      @v128.v128_or_(@v128.i16x8_eq(block, lf), @v128.i16x8_eq(block, cr)),
    )
    if @v128.v128_any_true(special) {
      return pos + @v128.i16x8_bitmask(special).ctz()
    }
    pos += 8
  }
  find_string_special_scalar(input, pos, end, quote)
}

///|
#cfg(any(target="native", target="wasm"))
#warnings("-alert_experimental")
#borrow(input)
#inline
fn find_comment_end(input : String, start : Int32, end : Int32) -> Int32 {
  let star = @v128.i16x8_splat('*')
  let mut pos = start
  while end - pos >= 8 {
    let block = @v128.v128_load_i16x8(input, pos)
    let stars = @v128.i16x8_eq(block, star)
    if @v128.v128_any_true(stars) {
      let mut candidates = @v128.i16x8_bitmask(stars)
      while candidates != 0 {
        let candidate = pos + candidates.ctz()
        if end - candidate >= 2 && input[candidate + 1] == '/' {
          return candidate
        }
        candidates = candidates & (candidates - 1)
      }
    }
    pos += 8
  }
  find_comment_end_scalar(input, pos, end)
}