                     multiplier: 1,
                     constant: 0))
             }
+            
+            canonicalKeyGap = nil
         }
         
         for constraint in allConstraints {

                else {
                    allConstraints += "[key\(j-1)x\(i)][\(keyGapName)]" // QQQ: this is where the gap width was
                    
                    // the width is determined as a percentage of the total container size
                    self.view.addConstraint(NSLayoutConstraint(
                        item: keyGap,
                        attribute: NSLayoutAttribute.Width,
                        relatedBy: NSLayoutRelation.Equal,
                        toItem: self.view,
                        attribute: NSLayoutAttribute.Width,
                        multiplier: 5/320.0,
                        constant: 0))
                }
                
                // each gap has the same height

    }
    
    // TODO: make this a single constraint string??
    // TODO: third row: side gaps come AFTER special buttons on sides
    // TODO: last row: flexible gaps w/no edges
    func createKeyGapConstraints(keyboard: Keyboard) {
        var allConstraints: Array<String> = []
        
        var canonicalMarginGap: String? = nil
        
        for i in 0..<keyboard.rows.count {
            // TODO: both of these should be determined based on the model data, not the row #
            let isSideButtonRow = (i == 2)
            let isEquallySpacedRow = (i == 3)
            
            var canonicalKeyGap: String? = nil
            
            for j in 0...keyboard.rows[i].count {
                let keyGapName = "keyGap\(j)x\(i)"
                let keyGap = self.elements[keyGapName]
