use lazy vals because we don't need to recalc these values every call