docs: function expandEngine( that ) {
  			that.debug.groupStart( 'expandEngine' ); // %REMOVE_LINE%
  
  			var startElement = that.element,
  				upper, lower, trigger;
  
  			if ( !isHtml( startElement ) || startElement.contains( that.editable ) ) {
  				that.debug.logEnd( 'ABORT. No start element, or start element contains editable.' ); // %REMOVE_LINE%
  				return null;
  			}
  
  			// Stop searching if element is in non-editable branch of DOM.
  			if ( startElement.isReadOnly() )
  				return null;
  
  			trigger = verticalSearch( that,
  				function( current, startElement ) {
  					return !startElement.equals( current );	// stop when start element and the current one differ
  				}, function( that, mouse ) {
  					return elementFromMouse( that, true, mouse );
  				}, startElement ),
  
  			upper = trigger.upper,
  			lower = trigger.lower;
  
  			that.debug.logElements( [ upper, lower ], [ 'Upper', 'Lower' ], 'Pair found' ); // %REMOVE_LINE%
  
  			// Success: two siblings have been found
  			if ( areSiblings( that, upper, lower ) ) {
  				that.debug.logEnd( 'SUCCESS. Expand trigger created.' ); // %REMOVE_LINE%
  				return trigger.set( EDGE_MIDDLE, TYPE_EXPAND );
  			}
  
  			that.debug.logElements( [ startElement, upper, lower ], // %REMOVE_LINE%
  				[ 'Start', 'Upper', 'Lower' ], 'Post-processing' ); // %REMOVE_LINE%
  
  			// Danger. Dragons ahead.
  			// No siblings have been found during previous phase, post-processing may be necessary.
  			// We can traverse DOM until a valid pair of elements around the pointer is found.
  
  			// Prepare for post-processing:
  			// 	1. Determine if upper and lower are children of startElement.
  			// 		1.1. If so, find their ascendants that are closest to startElement (one level deeper than startElement).
  			// 		1.2. Otherwise use first/last-child of the startElement as upper/lower. Why?:
  			// 			a) 	upper/lower belongs to another branch of the DOM tree.
  			// 			b) 	verticalSearch encountered an edge of the viewport and failed.
  			// 		1.3. Make sure upper and lower still exist. Why?:
  			// 			a) 	Upper and lower may be not belong to the branch of the startElement (may not exist at all) and
  			// 				startElement has no children.
  			// 	2. Perform the post-processing.
  			// 		2.1. Gather dimensions of an upper element.
  			// 		2.2. Abort if lower edge of upper is already under the mouse pointer. Why?:
  			// 			a) 	We expect upper to be above and lower below the mouse pointer.
  			// 	3. Perform iterative search while upper != lower.
  			// 		3.1. Find the upper-next element. If there's no such element, break current search. Why?:
  			// 			a)	There's no point in further search if there are only text nodes ahead.
  			// 		3.2. Calculate the distance between the middle point of ( upper, upperNext ) and mouse-y.
  			// 		3.3. If the distance is shorter than the previous best, save it (save upper, upperNext as well).
  			// 		3.4. If the optimal pair is found, assign it back to the trigger.
  
  			// 1.1., 1.2.
  			if ( upper && startElement.contains( upper ) ) {
  				while ( !upper.getParent().equals( startElement ) )
  					upper = upper.getParent();
  			} else {
  				upper = startElement.getFirst( function( node ) {
  					return expandSelector( that, node );
  				} );
  			}
  
  			if ( lower && startElement.contains( lower ) ) {
  				while ( !lower.getParent().equals( startElement ) )
  					lower = lower.getParent();
  			} else {
  				lower = startElement.getLast( function( node ) {
  					return expandSelector( that, node );
  				} );
  			}
  
  			// 1.3.
  			if ( !upper || !lower ) {
  				that.debug.logEnd( 'ABORT. There is no upper or no lower element.' ); // %REMOVE_LINE%
  				return null;
  			}
  
  			// 2.1.
  			updateSize( that, upper );
  			updateSize( that, lower );
  
  			if ( !checkMouseBetweenElements( that, upper, lower ) ) {
  				that.debug.logEnd( 'ABORT. Mouse is already above upper or below lower.' ); // %REMOVE_LINE%
  				return null;
  			}
  
  			var minDistance = Number.MAX_VALUE,
  				currentDistance, upperNext, minElement, minElementNext;
  
  			while ( lower && !lower.equals( upper ) ) {
  				// 3.1.
  				if ( !( upperNext = upper.getNext( that.isRelevant ) ) )
  					break;
  
  				// 3.2.
  				currentDistance = Math.abs( getMidpoint( that, upper, upperNext ) - that.mouse.y );
  
  				// 3.3.
  				if ( currentDistance < minDistance ) {
  					minDistance = currentDistance;
  					minElement = upper;
  					minElementNext = upperNext;
  				}
  
  				upper = upperNext;
  				updateSize( that, upper );
  			}
  
  			that.debug.logElements( [ minElement, minElementNext ], // %REMOVE_LINE%
  				[ 'Min', 'MinNext' ], 'Post-processing results' ); // %REMOVE_LINE%
  
  			// 3.4.
  			if ( !minElement || !minElementNext ) {
  				that.debug.logEnd( 'ABORT. No Min or MinNext' ); // %REMOVE_LINE%
  				return null;
  			}
  
  			if ( !checkMouseBetweenElements( that, minElement, minElementNext ) ) {
  				that.debug.logEnd( 'ABORT. Mouse is already above minElement or below minElementNext.' ); // %REMOVE_LINE%
  				return null;
  			}
  
  			// An element of minimal distance has been found. Assign it to the trigger.
  			trigger.upper = minElement;
  			trigger.lower = minElementNext;
  
  			// Success: post-processing revealed a pair of elements.
  			that.debug.logEnd( 'SUCCESSFUL post-processing. Trigger created.' ); // %REMOVE_LINE%
  			return trigger.set( EDGE_MIDDLE, TYPE_EXPAND );
  		}