Added a loop that retries getLocationOnScreen until it gets a value

package com.robotium.solo;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import junit.framework.Assert;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.TextView;

/**
 * Contains various click methods. Examples are: clickOn(),
 * clickOnText(), clickOnScreen().
 *
 * @author Renas Reda, renas.reda@robotium.com
 *
 */

class Clicker {

	private final String LOG_TAG = "Robotium";
	private final ActivityUtils activityUtils;
	private final ViewFetcher viewFetcher;
	private final Instrumentation inst;
	private final Sender sender;
	private final Sleeper sleeper;
	private final Waiter waiter;
	private final WebUtils webUtils;
	private final DialogUtils dialogUtils;
	private final int MINI_WAIT = 300;
	private final int WAIT_TIME = 1500;

	/**
	 * Constructs this object.
	 *
	 * @param activityUtils the {@code ActivityUtils} instance
	 * @param viewFetcher the {@code ViewFetcher} instance
	 * @param sender the {@code Sender} instance
	 * @param inst the {@code android.app.Instrumentation} instance
	 * @param sleeper the {@code Sleeper} instance
	 * @param waiter the {@code Waiter} instance
	 * @param webUtils the {@code WebUtils} instance
	 * @param dialogUtils the {@code DialogUtils} instance
	 */

	public Clicker(ActivityUtils activityUtils, ViewFetcher viewFetcher, Sender sender, Instrumentation inst, Sleeper sleeper, Waiter waiter, WebUtils webUtils, DialogUtils dialogUtils) {

		this.activityUtils = activityUtils;
		this.viewFetcher = viewFetcher;
		this.sender = sender;
		this.inst = inst;
		this.sleeper = sleeper;
		this.waiter = waiter;
		this.webUtils = webUtils;
		this.dialogUtils = dialogUtils;
	}

	/**
	 * Clicks on a given coordinate on the screen.
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 */

	public void clickOnScreen(float x, float y, View view) {
		boolean successfull = false;
		int retry = 0;
		SecurityException ex = null;

		while(!successfull && retry < 20) {
			long downTime = SystemClock.uptimeMillis();
			long eventTime = SystemClock.uptimeMillis();
			MotionEvent event = MotionEvent.obtain(downTime, eventTime,
					MotionEvent.ACTION_DOWN, x, y, 0);
			MotionEvent event2 = MotionEvent.obtain(downTime, eventTime,
					MotionEvent.ACTION_UP, x, y, 0);
			try{
				inst.sendPointerSync(event);
				inst.sendPointerSync(event2);
				successfull = true;
			}catch(SecurityException e){
				ex = e;
				dialogUtils.hideSoftKeyboard(null, false, true);
				sleeper.sleep(MINI_WAIT);
				retry++;
				View identicalView = viewFetcher.getIdenticalView(view);
				if(identicalView != null){
					float[] xyToClick = getClickCoordinates(identicalView);
					x = xyToClick[0];
					y = xyToClick[1];
				}
			}
		}
		if(!successfull) {
			Assert.fail("Click at ("+x+", "+y+") can not be completed! ("+(ex != null ? ex.getClass().getName()+": "+ex.getMessage() : "null")+")");
		}
	}

	/**
	 * Long clicks a given coordinate on the screen.
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @param time the amount of time to long click
	 */

	public void clickLongOnScreen(float x, float y, int time, View view) {
		boolean successfull = false;
		int retry = 0;
		SecurityException ex = null;
		long downTime = SystemClock.uptimeMillis();
		long eventTime = SystemClock.uptimeMillis();
		MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);

		while(!successfull && retry < 20) {
			try{
				inst.sendPointerSync(event);
				successfull = true;
				sleeper.sleep(MINI_WAIT);
			}catch(SecurityException e){
				ex = e;
				dialogUtils.hideSoftKeyboard(null, false, true);
				sleeper.sleep(MINI_WAIT);
				retry++;
				View identicalView = viewFetcher.getIdenticalView(view);
				if(identicalView != null){
					float[] xyToClick = getClickCoordinates(identicalView);
					x = xyToClick[0];
					y = xyToClick[1];
				}
			}
		}
		if(!successfull) {
			Assert.fail("Long click at ("+x+", "+y+") can not be completed! ("+(ex != null ? ex.getClass().getName()+": "+ex.getMessage() : "null")+")");
		}

		eventTime = SystemClock.uptimeMillis();
		event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x + 1.0f, y + 1.0f, 0);
		inst.sendPointerSync(event);
		if(time > 0)
			sleeper.sleep(time);
		else
			sleeper.sleep((int)(ViewConfiguration.getLongPressTimeout() * 2.5f));

		eventTime = SystemClock.uptimeMillis();
		event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
		inst.sendPointerSync(event);
		sleeper.sleep();
	}

	/**
	 * Clicks on a given {@link View}.
	 *
	 * @param view the view that should be clicked
	 */

	public void clickOnScreen(View view) {
		clickOnScreen(view, false, 0);
	}

	/**
	 * Private method used to click on a given view.
	 *
	 * @param view the view that should be clicked
	 * @param longClick true if the click should be a long click
	 * @param time the amount of time to long click
	 */

	public void clickOnScreen(View view, boolean longClick, int time) {
		if(view == null)
			Assert.fail("View is null and can therefore not be clicked!");

		float[] xyToClick = getClickCoordinates(view);
		float x = xyToClick[0];
		float y = xyToClick[1];

		if(x == 0 || y == 0){
			sleeper.sleepMini();
			try {
				view = viewFetcher.getIdenticalView(view);
			} catch (Exception ignored){}

			if(view != null){
				xyToClick = getClickCoordinates(view);
				x = xyToClick[0];
				y = xyToClick[1];
			}
		}

		if (longClick)
			clickLongOnScreen(x, y, time, view);
		else
			clickOnScreen(x, y, view);
	}

	/**
	 * Returns click coordinates for the specified view.
	 *
	 * @param view the view to get click coordinates from
	 * @return click coordinates for a specified view
	 */

	private float[] getClickCoordinates(View view){
		sleeper.sleep(200);
		int[] xyLocation = new int[2];
		float[] xyToClick = new float[2];

		view.getLocationOnScreen(xyLocation);

		final int viewWidth = view.getWidth();
		final int viewHeight = view.getHeight();
		final float x = xyLocation[0] + (viewWidth / 2.0f);
		float y = xyLocation[1] + (viewHeight / 2.0f);

		xyToClick[0] = x;
		xyToClick[1] = y;

		return xyToClick;
	}

	/**
	 * Long clicks on a specific {@link TextView} and then selects
	 * an item from the context menu that appears. Will automatically scroll when needed.
	 *
	 * @param text the text that should be clicked on. The parameter will be interpreted as a regular expression.
	 * @param index the index of the menu item that should be pressed
	 */

	public void clickLongOnTextAndPress(String text, int index)
	{
		clickOnText(text, true, 0, true, 0);
		dialogUtils.waitForDialogToOpen(Timeout.getSmallTimeout(), true);
		try{
			inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
		}catch(SecurityException e){
			Assert.fail("Can not press the context menu!");
		}
		for(int i = 0; i < index; i++)
		{
			sleeper.sleepMini();
			inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
		}
		inst.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
	}

	/**
	 * Opens the menu and waits for it to open.
	 */

	private void openMenu(){
		sleeper.sleepMini();

		if(!dialogUtils.waitForDialogToOpen(MINI_WAIT, false)) {
			try{
				sender.sendKeyCode(KeyEvent.KEYCODE_MENU);
				dialogUtils.waitForDialogToOpen(WAIT_TIME, true);
			}catch(SecurityException e){
				Assert.fail("Can not open the menu!");
			}
		}
	}

	/**
	 * Clicks on a menu item with a given text.
	 *
	 * @param text the menu text that should be clicked on. The parameter will be interpreted as a regular expression.
	 */

	public void clickOnMenuItem(String text)
	{
		openMenu();
		clickOnText(text, false, 1, true, 0);
	}

	/**
	 * Clicks on a menu item with a given text.
	 *
	 * @param text the menu text that should be clicked on. The parameter will be interpreted as a regular expression.
	 * @param subMenu true if the menu item could be located in a sub menu
	 */

	public void clickOnMenuItem(String text, boolean subMenu)
	{
		sleeper.sleepMini();

		TextView textMore = null;
		int [] xy = new int[2];
		int x = 0;
		int y = 0;

		if(!dialogUtils.waitForDialogToOpen(MINI_WAIT, false)) {
			try{
				sender.sendKeyCode(KeyEvent.KEYCODE_MENU);
				dialogUtils.waitForDialogToOpen(WAIT_TIME, true);
			}catch(SecurityException e){
				Assert.fail("Can not open the menu!");
			}
		}
		boolean textShown = waiter.waitForText(text, 1, WAIT_TIME, true) != null;

		if(subMenu && (viewFetcher.getCurrentViews(TextView.class, true).size() > 5) && !textShown){
			for(TextView textView : viewFetcher.getCurrentViews(TextView.class, true)){
				x = xy[0];
				y = xy[1];
				textView.getLocationOnScreen(xy);

				if(xy[0] > x || xy[1] > y)
					textMore = textView;
			}
		}
		if(textMore != null)
			clickOnScreen(textMore);

		clickOnText(text, false, 1, true, 0);
	}

	/**
	 * Clicks on an ActionBar item with a given resource id
	 *
	 * @param resourceId the R.id of the ActionBar item
	 */

	public void clickOnActionBarItem(int resourceId){
		sleeper.sleep();
		Activity activity = activityUtils.getCurrentActivity();
		if(activity != null){
			inst.invokeMenuActionSync(activity, resourceId, 0);
		}
	}

	/**
	 * Clicks on an ActionBar Home/Up button.
	 */

	public void clickOnActionBarHomeButton() {
		Activity activity = activityUtils.getCurrentActivity();
		MenuItem homeMenuItem = null;

		try {
			Class<?> cls = Class.forName("com.android.internal.view.menu.ActionMenuItem");
			Class<?> partypes[] = new Class[6];
			partypes[0] = Context.class;
			partypes[1] = Integer.TYPE;
			partypes[2] = Integer.TYPE;
			partypes[3] = Integer.TYPE;
			partypes[4] = Integer.TYPE;
			partypes[5] = CharSequence.class;
			Constructor<?> ct = cls.getConstructor(partypes);
			Object argList[] = new Object[6];
			argList[0] = activity;
			argList[1] = 0;
			argList[2] = android.R.id.home;
			argList[3] = 0;
			argList[4] = 0;
			argList[5] = "";
			homeMenuItem = (MenuItem) ct.newInstance(argList);
		} catch (Exception ex) {
			Log.d(LOG_TAG, "Can not find methods to invoke Home button!");
		}

		if (homeMenuItem != null) {
			try{
				activity.getWindow().getCallback().onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, homeMenuItem);
			}catch(Exception ignored) {}
		}
	}

	/**
	 * Clicks on a web element using the given By method.
	 *
	 * @param by the By object e.g. By.id("id");
	 * @param match if multiple objects match, this determines which one will be clicked
	 * @param scroll true if scrolling should be performed
	 * @param useJavaScriptToClick true if click should be perfomed through JavaScript
	 */

	public void clickOnWebElement(By by, int match, boolean scroll, boolean useJavaScriptToClick){
		WebElement webElement = null;

		if(useJavaScriptToClick){
			webElement = waiter.waitForWebElement(by, match, Timeout.getSmallTimeout(), false);
			if(webElement == null){
				Assert.fail("WebElement with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' is not found!");
			}
			webUtils.executeJavaScript(by, true);
			return;
		}

		WebElement webElementToClick = waiter.waitForWebElement(by, match, Timeout.getSmallTimeout(), scroll);

		if(webElementToClick == null){
			if(match > 1) {
				Assert.fail(match + " WebElements with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' are not found!");
			}
			else {
				Assert.fail("WebElement with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' is not found!");
			}
		}

		clickOnScreen(webElementToClick.getLocationX(), webElementToClick.getLocationY(), null);
	}

	/**
	 * Clicks on a specific {@link TextView} displaying a given text.
	 *
	 * @param regex the text that should be clicked on. The parameter will be interpreted as a regular expression.
	 * @param longClick {@code true} if the click should be a long click
	 * @param match the regex match that should be clicked on
	 * @param scroll true if scrolling should be performed
	 * @param time the amount of time to long click
	 */

	public void clickOnText(String regex, boolean longClick, int match, boolean scroll, int time) {
		TextView textToClick = waiter.waitForText(regex, match, Timeout.getSmallTimeout(), scroll, true, false);

		if (textToClick != null) {
			clickOnScreen(textToClick, longClick, time);
		}

		else {

			if(match > 1){
				Assert.fail(match + " matches of text string: '" + regex +  "' are not found!");
			}

			else{
				ArrayList<TextView> allTextViews = RobotiumUtils.removeInvisibleViews(viewFetcher.getCurrentViews(TextView.class, true));
				allTextViews.addAll((Collection<? extends TextView>) webUtils.getTextViewsFromWebView());

				for (TextView textView : allTextViews) {
					Log.d(LOG_TAG, "'" + regex + "' not found. Have found: '" + textView.getText() + "'");
				}
				allTextViews = null;
				Assert.fail("Text string: '" + regex + "' is not found!");
			}
		}
	}

	/**
	 * Clicks on a {@code View} of a specific class, with a given text.
	 *
	 * @param viewClass what kind of {@code View} to click, e.g. {@code Button.class} or {@code TextView.class}
	 * @param nameRegex the name of the view presented to the user. The parameter will be interpreted as a regular expression.
	 */

	public <T extends TextView> void clickOn(Class<T> viewClass, String nameRegex) {
		T viewToClick = (T) waiter.waitForText(viewClass, nameRegex, 0, Timeout.getSmallTimeout(), true, true, false);

		if (viewToClick != null) {
			clickOnScreen(viewToClick);
		} else {
			ArrayList <T> allTextViews = RobotiumUtils.removeInvisibleViews(viewFetcher.getCurrentViews(viewClass, true));

			for (T view : allTextViews) {
				Log.d(LOG_TAG, "'" + nameRegex + "' not found. Have found: '" + view.getText() + "'");
			}
			Assert.fail(viewClass.getSimpleName() + " with text: '" + nameRegex + "' is not found!");
		}
	}

	/**
	 * Clicks on a {@code View} of a specific class, with a certain index.
	 *
	 * @param viewClass what kind of {@code View} to click, e.g. {@code Button.class} or {@code ImageView.class}
	 * @param index the index of the {@code View} to be clicked, within {@code View}s of the specified class
	 */

	public <T extends View> void clickOn(Class<T> viewClass, int index) {
		clickOnScreen(waiter.waitForAndGetView(index, viewClass));
	}

	/**
	 * Clicks on a certain list line and returns the {@link TextView}s that
	 * the list line is showing. Will use the first list it finds.
	 *
	 * @param line the line that should be clicked
	 * @return a {@code List} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInList(int line) {
		return clickInList(line, 0, 0, false, 0);
	}

	/**
	 * Clicks on a View with a specified resource id located in a specified list line
	 *
	 * @param line the line where the View is located
	 * @param id the resource id of the View
	 */

	public void clickInList(int line, int id) {
		clickInList(line, 0, id, false, 0);
	}

	/**
	 * Clicks on a certain list line on a specified List and
	 * returns the {@link TextView}s that the list line is showing.
	 *
	 * @param line the line that should be clicked
	 * @param index the index of the list. E.g. Index 1 if two lists are available
	 * @param id the resource id of the View to click
	 * @return an {@code ArrayList} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInList(int line, int index, int id, boolean longClick, int time) {
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();

		int lineIndex = line - 1;
		if(lineIndex < 0)
			lineIndex = 0;

		ArrayList<View> views = new ArrayList<View>();
		final AbsListView absListView = waiter.waitForAndGetView(index, AbsListView.class);

		if(absListView == null)
			Assert.fail("AbsListView is null!");

		failIfIndexHigherThenChildCount(absListView, lineIndex, endTime);

		View viewOnLine = getViewOnAbsListLine(absListView, index, lineIndex);

		if(viewOnLine != null){
			views = viewFetcher.getViews(viewOnLine, true);
			views = RobotiumUtils.removeInvisibleViews(views);

			if(id == 0){
				clickOnScreen(viewOnLine, longClick, time);
			}
			else{
				clickOnScreen(getView(id, views));
			}
		}
		return RobotiumUtils.filterViews(TextView.class, views);
	}

	/**
	 * Clicks on a certain list line and returns the {@link TextView}s that
	 * the list line is showing. Will use the first list it finds.
	 *
	 * @param line the line that should be clicked
	 * @return a {@code List} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInRecyclerView(int line) {
		return clickInRecyclerView(line, 0, 0, false, 0);
	}

	/**
	 * Clicks on a View with a specified resource id located in a specified RecyclerView itemIndex
	 *
	 * @param itemIndex the index where the View is located
	 * @param id the resource id of the View
	 */

	public void clickInRecyclerView(int itemIndex, int id) {
		clickInRecyclerView(itemIndex, 0, id, false, 0);
	}

	/**
	 * Clicks on a certain list line on a specified List and
	 * returns the {@link TextView}s that the list line is showing.
	 *
	 * @param itemIndex the item index that should be clicked
	 * @param recyclerViewIndex the index of the RecyclerView. E.g. Index 1 if two RecyclerViews are available
	 * @param id the resource id of the View to click
	 * @return an {@code ArrayList} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInRecyclerView(int itemIndex, int recyclerViewIndex, int id, boolean longClick, int time) {
		View viewOnLine = null;
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();

		if(itemIndex < 0)
			itemIndex = 0;

		ArrayList<View> views = new ArrayList<View>();
		ViewGroup recyclerView = viewFetcher.getRecyclerView(recyclerViewIndex, Timeout.getSmallTimeout());

		if(recyclerView == null){
			Assert.fail("RecyclerView is not found!");
		}
		else{
			failIfIndexHigherThenChildCount(recyclerView, itemIndex, endTime);
			viewOnLine = getViewOnRecyclerItemIndex((ViewGroup) recyclerView, recyclerViewIndex, itemIndex);
		}

		if(viewOnLine != null){
			views = viewFetcher.getViews(viewOnLine, true);
			views = RobotiumUtils.removeInvisibleViews(views);

			if(id == 0){
				clickOnScreen(viewOnLine, longClick, time);
			}
			else{
				clickOnScreen(getView(id, views));
			}
		}
		return RobotiumUtils.filterViews(TextView.class, views);
	}

	private View getView(int id, List<View> views){
		for(View view : views){
			if(id == view.getId()){
				return view;
			}
		}
		return null;
	}

	private void failIfIndexHigherThenChildCount(ViewGroup viewGroup, int index, long endTime){
		while(index > viewGroup.getChildCount()){
			final boolean timedOut = SystemClock.uptimeMillis() > endTime;
			if (timedOut){
				int numberOfIndexes = viewGroup.getChildCount();
				Assert.fail("Can not click on index " + index + " as there are only " + numberOfIndexes + " indexes available");
			}
			sleeper.sleep();
		}
	}

	/**
	 * Returns the view in the specified list line
	 *
	 * @param absListView the ListView to use
	 * @param index the index of the list. E.g. Index 1 if two lists are available
	 * @param lineIndex the line index of the View
	 * @return the View located at a specified list line
	 */

	private View getViewOnAbsListLine(AbsListView absListView, int index, int lineIndex){
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();
		View view = absListView.getChildAt(lineIndex);

		while(view == null){
			final boolean timedOut = SystemClock.uptimeMillis() > endTime;
			if (timedOut){
				Assert.fail("View is null and can therefore not be clicked!");
			}

			sleeper.sleep();
			absListView = (AbsListView) viewFetcher.getIdenticalView(absListView);

			if(absListView == null){
				absListView = waiter.waitForAndGetView(index, AbsListView.class);
			}

			view = absListView.getChildAt(lineIndex);
		}
		return view;
	}

	/**
	 * Returns the view in the specified item index
	 *
	 * @param recyclerView the RecyclerView to use
	 * @param itemIndex the item index of the View
	 * @return the View located at a specified item index
	 */

	private View getViewOnRecyclerItemIndex(ViewGroup recyclerView, int recyclerViewIndex, int itemIndex){
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();
		View view = recyclerView.getChildAt(itemIndex);

		while(view == null){
			final boolean timedOut = SystemClock.uptimeMillis() > endTime;
			if (timedOut){
				Assert.fail("View is null and can therefore not be clicked!");
			}

			sleeper.sleep();
			recyclerView = (ViewGroup) viewFetcher.getIdenticalView(recyclerView);

			if(recyclerView == null){
				recyclerView = (ViewGroup) viewFetcher.getRecyclerView(false, recyclerViewIndex);
			}

			if(recyclerView != null){
				view = recyclerView.getChildAt(itemIndex);
			}
		}
		return view;
	}

}

package com.robotium.solo;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import junit.framework.Assert;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.TextView;

/**
 * Contains various click methods. Examples are: clickOn(),
 * clickOnText(), clickOnScreen().
 *
 * @author Renas Reda, renas.reda@robotium.com
 *
 */

class Clicker {

	private final String LOG_TAG = "Robotium";
	private final ActivityUtils activityUtils;
	private final ViewFetcher viewFetcher;
	private final Instrumentation inst;
	private final Sender sender;
	private final Sleeper sleeper;
	private final Waiter waiter;
	private final WebUtils webUtils;
	private final DialogUtils dialogUtils;
	private final int MINI_WAIT = 300;
	private final int WAIT_TIME = 1500;

	/**
	 * Constructs this object.
	 *
	 * @param activityUtils the {@code ActivityUtils} instance
	 * @param viewFetcher the {@code ViewFetcher} instance
	 * @param sender the {@code Sender} instance
	 * @param inst the {@code android.app.Instrumentation} instance
	 * @param sleeper the {@code Sleeper} instance
	 * @param waiter the {@code Waiter} instance
	 * @param webUtils the {@code WebUtils} instance
	 * @param dialogUtils the {@code DialogUtils} instance
	 */

	public Clicker(ActivityUtils activityUtils, ViewFetcher viewFetcher, Sender sender, Instrumentation inst, Sleeper sleeper, Waiter waiter, WebUtils webUtils, DialogUtils dialogUtils) {

		this.activityUtils = activityUtils;
		this.viewFetcher = viewFetcher;
		this.sender = sender;
		this.inst = inst;
		this.sleeper = sleeper;
		this.waiter = waiter;
		this.webUtils = webUtils;
		this.dialogUtils = dialogUtils;
	}

	/**
	 * Clicks on a given coordinate on the screen.
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 */

	public void clickOnScreen(float x, float y, View view) {
		boolean successfull = false;
		int retry = 0;
		SecurityException ex = null;

		while(!successfull && retry < 20) {
			long downTime = SystemClock.uptimeMillis();
			long eventTime = SystemClock.uptimeMillis();
			MotionEvent event = MotionEvent.obtain(downTime, eventTime,
					MotionEvent.ACTION_DOWN, x, y, 0);
			MotionEvent event2 = MotionEvent.obtain(downTime, eventTime,
					MotionEvent.ACTION_UP, x, y, 0);
			try{
				inst.sendPointerSync(event);
				inst.sendPointerSync(event2);
				successfull = true;
			}catch(SecurityException e){
				ex = e;
				dialogUtils.hideSoftKeyboard(null, false, true);
				sleeper.sleep(MINI_WAIT);
				retry++;
				View identicalView = viewFetcher.getIdenticalView(view);
				if(identicalView != null){
					float[] xyToClick = getClickCoordinates(identicalView);
					x = xyToClick[0];
					y = xyToClick[1];
				}
			}
		}
		if(!successfull) {
			Assert.fail("Click at ("+x+", "+y+") can not be completed! ("+(ex != null ? ex.getClass().getName()+": "+ex.getMessage() : "null")+")");
		}
	}

	/**
	 * Long clicks a given coordinate on the screen.
	 *
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @param time the amount of time to long click
	 */

	public void clickLongOnScreen(float x, float y, int time, View view) {
		boolean successfull = false;
		int retry = 0;
		SecurityException ex = null;
		long downTime = SystemClock.uptimeMillis();
		long eventTime = SystemClock.uptimeMillis();
		MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);

		while(!successfull && retry < 20) {
			try{
				inst.sendPointerSync(event);
				successfull = true;
				sleeper.sleep(MINI_WAIT);
			}catch(SecurityException e){
				ex = e;
				dialogUtils.hideSoftKeyboard(null, false, true);
				sleeper.sleep(MINI_WAIT);
				retry++;
				View identicalView = viewFetcher.getIdenticalView(view);
				if(identicalView != null){
					float[] xyToClick = getClickCoordinates(identicalView);
					x = xyToClick[0];
					y = xyToClick[1];
				}
			}
		}
		if(!successfull) {
			Assert.fail("Long click at ("+x+", "+y+") can not be completed! ("+(ex != null ? ex.getClass().getName()+": "+ex.getMessage() : "null")+")");
		}

		eventTime = SystemClock.uptimeMillis();
		event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x + 1.0f, y + 1.0f, 0);
		inst.sendPointerSync(event);
		if(time > 0)
			sleeper.sleep(time);
		else
			sleeper.sleep((int)(ViewConfiguration.getLongPressTimeout() * 2.5f));

		eventTime = SystemClock.uptimeMillis();
		event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
		inst.sendPointerSync(event);
		sleeper.sleep();
	}

	/**
	 * Clicks on a given {@link View}.
	 *
	 * @param view the view that should be clicked
	 */

	public void clickOnScreen(View view) {
		clickOnScreen(view, false, 0);
	}

	/**
	 * Private method used to click on a given view.
	 *
	 * @param view the view that should be clicked
	 * @param longClick true if the click should be a long click
	 * @param time the amount of time to long click
	 */

	public void clickOnScreen(View view, boolean longClick, int time) {
		if(view == null)
			Assert.fail("View is null and can therefore not be clicked!");

		float[] xyToClick = getClickCoordinates(view);
		float x = xyToClick[0];
		float y = xyToClick[1];

		if(x == 0 || y == 0){
			sleeper.sleepMini();
			try {
				view = viewFetcher.getIdenticalView(view);
			} catch (Exception ignored){}

			if(view != null){
				xyToClick = getClickCoordinates(view);
				x = xyToClick[0];
				y = xyToClick[1];
			}
		}

		sleeper.sleep(300);
		if (longClick)
			clickLongOnScreen(x, y, time, view);
		else
			clickOnScreen(x, y, view);
	}

	/**
	 * Returns click coordinates for the specified view.
	 *
	 * @param view the view to get click coordinates from
	 * @return click coordinates for a specified view
	 */

	private float[] getClickCoordinates(View view){
		int[] xyLocation = new int[2];
		float[] xyToClick = new float[2];
		int trialCount = 0;

		view.getLocationOnScreen(xyLocation);
		while(xyLocation[0] == 0 && xyLocation[1] == 0 && trialCount < 10) {
			sleeper.sleep(300);
			view.getLocationOnScreen(xyLocation);
			trialCount++;
		}

		final int viewWidth = view.getWidth();
		final int viewHeight = view.getHeight();
		final float x = xyLocation[0] + (viewWidth / 2.0f);
		float y = xyLocation[1] + (viewHeight / 2.0f);

		xyToClick[0] = x;
		xyToClick[1] = y;

		return xyToClick;
	}

	/**
	 * Long clicks on a specific {@link TextView} and then selects
	 * an item from the context menu that appears. Will automatically scroll when needed.
	 *
	 * @param text the text that should be clicked on. The parameter will be interpreted as a regular expression.
	 * @param index the index of the menu item that should be pressed
	 */

	public void clickLongOnTextAndPress(String text, int index)
	{
		clickOnText(text, true, 0, true, 0);
		dialogUtils.waitForDialogToOpen(Timeout.getSmallTimeout(), true);
		try{
			inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
		}catch(SecurityException e){
			Assert.fail("Can not press the context menu!");
		}
		for(int i = 0; i < index; i++)
		{
			sleeper.sleepMini();
			inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
		}
		inst.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
	}

	/**
	 * Opens the menu and waits for it to open.
	 */

	private void openMenu(){
		sleeper.sleepMini();

		if(!dialogUtils.waitForDialogToOpen(MINI_WAIT, false)) {
			try{
				sender.sendKeyCode(KeyEvent.KEYCODE_MENU);
				dialogUtils.waitForDialogToOpen(WAIT_TIME, true);
			}catch(SecurityException e){
				Assert.fail("Can not open the menu!");
			}
		}
	}

	/**
	 * Clicks on a menu item with a given text.
	 *
	 * @param text the menu text that should be clicked on. The parameter will be interpreted as a regular expression.
	 */

	public void clickOnMenuItem(String text)
	{
		openMenu();
		clickOnText(text, false, 1, true, 0);
	}

	/**
	 * Clicks on a menu item with a given text.
	 *
	 * @param text the menu text that should be clicked on. The parameter will be interpreted as a regular expression.
	 * @param subMenu true if the menu item could be located in a sub menu
	 */

	public void clickOnMenuItem(String text, boolean subMenu)
	{
		sleeper.sleepMini();

		TextView textMore = null;
		int [] xy = new int[2];
		int x = 0;
		int y = 0;

		if(!dialogUtils.waitForDialogToOpen(MINI_WAIT, false)) {
			try{
				sender.sendKeyCode(KeyEvent.KEYCODE_MENU);
				dialogUtils.waitForDialogToOpen(WAIT_TIME, true);
			}catch(SecurityException e){
				Assert.fail("Can not open the menu!");
			}
		}
		boolean textShown = waiter.waitForText(text, 1, WAIT_TIME, true) != null;

		if(subMenu && (viewFetcher.getCurrentViews(TextView.class, true).size() > 5) && !textShown){
			for(TextView textView : viewFetcher.getCurrentViews(TextView.class, true)){
				x = xy[0];
				y = xy[1];
				textView.getLocationOnScreen(xy);

				if(xy[0] > x || xy[1] > y)
					textMore = textView;
			}
		}
		if(textMore != null)
			clickOnScreen(textMore);

		clickOnText(text, false, 1, true, 0);
	}

	/**
	 * Clicks on an ActionBar item with a given resource id
	 *
	 * @param resourceId the R.id of the ActionBar item
	 */

	public void clickOnActionBarItem(int resourceId){
		sleeper.sleep();
		Activity activity = activityUtils.getCurrentActivity();
		if(activity != null){
			inst.invokeMenuActionSync(activity, resourceId, 0);
		}
	}

	/**
	 * Clicks on an ActionBar Home/Up button.
	 */

	public void clickOnActionBarHomeButton() {
		Activity activity = activityUtils.getCurrentActivity();
		MenuItem homeMenuItem = null;

		try {
			Class<?> cls = Class.forName("com.android.internal.view.menu.ActionMenuItem");
			Class<?> partypes[] = new Class[6];
			partypes[0] = Context.class;
			partypes[1] = Integer.TYPE;
			partypes[2] = Integer.TYPE;
			partypes[3] = Integer.TYPE;
			partypes[4] = Integer.TYPE;
			partypes[5] = CharSequence.class;
			Constructor<?> ct = cls.getConstructor(partypes);
			Object argList[] = new Object[6];
			argList[0] = activity;
			argList[1] = 0;
			argList[2] = android.R.id.home;
			argList[3] = 0;
			argList[4] = 0;
			argList[5] = "";
			homeMenuItem = (MenuItem) ct.newInstance(argList);
		} catch (Exception ex) {
			Log.d(LOG_TAG, "Can not find methods to invoke Home button!");
		}

		if (homeMenuItem != null) {
			try{
				activity.getWindow().getCallback().onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, homeMenuItem);
			}catch(Exception ignored) {}
		}
	}

	/**
	 * Clicks on a web element using the given By method.
	 *
	 * @param by the By object e.g. By.id("id");
	 * @param match if multiple objects match, this determines which one will be clicked
	 * @param scroll true if scrolling should be performed
	 * @param useJavaScriptToClick true if click should be perfomed through JavaScript
	 */

	public void clickOnWebElement(By by, int match, boolean scroll, boolean useJavaScriptToClick){
		WebElement webElement = null;

		if(useJavaScriptToClick){
			webElement = waiter.waitForWebElement(by, match, Timeout.getSmallTimeout(), false);
			if(webElement == null){
				Assert.fail("WebElement with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' is not found!");
			}
			webUtils.executeJavaScript(by, true);
			return;
		}

		WebElement webElementToClick = waiter.waitForWebElement(by, match, Timeout.getSmallTimeout(), scroll);

		if(webElementToClick == null){
			if(match > 1) {
				Assert.fail(match + " WebElements with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' are not found!");
			}
			else {
				Assert.fail("WebElement with " + webUtils.splitNameByUpperCase(by.getClass().getSimpleName()) + ": '" + by.getValue() + "' is not found!");
			}
		}

		clickOnScreen(webElementToClick.getLocationX(), webElementToClick.getLocationY(), null);
	}

	/**
	 * Clicks on a specific {@link TextView} displaying a given text.
	 *
	 * @param regex the text that should be clicked on. The parameter will be interpreted as a regular expression.
	 * @param longClick {@code true} if the click should be a long click
	 * @param match the regex match that should be clicked on
	 * @param scroll true if scrolling should be performed
	 * @param time the amount of time to long click
	 */

	public void clickOnText(String regex, boolean longClick, int match, boolean scroll, int time) {
		TextView textToClick = waiter.waitForText(regex, match, Timeout.getSmallTimeout(), scroll, true, false);

		if (textToClick != null) {
			clickOnScreen(textToClick, longClick, time);
		}

		else {

			if(match > 1){
				Assert.fail(match + " matches of text string: '" + regex +  "' are not found!");
			}

			else{
				ArrayList<TextView> allTextViews = RobotiumUtils.removeInvisibleViews(viewFetcher.getCurrentViews(TextView.class, true));
				allTextViews.addAll((Collection<? extends TextView>) webUtils.getTextViewsFromWebView());

				for (TextView textView : allTextViews) {
					Log.d(LOG_TAG, "'" + regex + "' not found. Have found: '" + textView.getText() + "'");
				}
				allTextViews = null;
				Assert.fail("Text string: '" + regex + "' is not found!");
			}
		}
	}

	/**
	 * Clicks on a {@code View} of a specific class, with a given text.
	 *
	 * @param viewClass what kind of {@code View} to click, e.g. {@code Button.class} or {@code TextView.class}
	 * @param nameRegex the name of the view presented to the user. The parameter will be interpreted as a regular expression.
	 */

	public <T extends TextView> void clickOn(Class<T> viewClass, String nameRegex) {
		T viewToClick = (T) waiter.waitForText(viewClass, nameRegex, 0, Timeout.getSmallTimeout(), true, true, false);

		if (viewToClick != null) {
			clickOnScreen(viewToClick);
		} else {
			ArrayList <T> allTextViews = RobotiumUtils.removeInvisibleViews(viewFetcher.getCurrentViews(viewClass, true));

			for (T view : allTextViews) {
				Log.d(LOG_TAG, "'" + nameRegex + "' not found. Have found: '" + view.getText() + "'");
			}
			Assert.fail(viewClass.getSimpleName() + " with text: '" + nameRegex + "' is not found!");
		}
	}

	/**
	 * Clicks on a {@code View} of a specific class, with a certain index.
	 *
	 * @param viewClass what kind of {@code View} to click, e.g. {@code Button.class} or {@code ImageView.class}
	 * @param index the index of the {@code View} to be clicked, within {@code View}s of the specified class
	 */

	public <T extends View> void clickOn(Class<T> viewClass, int index) {
		clickOnScreen(waiter.waitForAndGetView(index, viewClass));
	}

	/**
	 * Clicks on a certain list line and returns the {@link TextView}s that
	 * the list line is showing. Will use the first list it finds.
	 *
	 * @param line the line that should be clicked
	 * @return a {@code List} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInList(int line) {
		return clickInList(line, 0, 0, false, 0);
	}

	/**
	 * Clicks on a View with a specified resource id located in a specified list line
	 *
	 * @param line the line where the View is located
	 * @param id the resource id of the View
	 */

	public void clickInList(int line, int id) {
		clickInList(line, 0, id, false, 0);
	}

	/**
	 * Clicks on a certain list line on a specified List and
	 * returns the {@link TextView}s that the list line is showing.
	 *
	 * @param line the line that should be clicked
	 * @param index the index of the list. E.g. Index 1 if two lists are available
	 * @param id the resource id of the View to click
	 * @return an {@code ArrayList} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInList(int line, int index, int id, boolean longClick, int time) {
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();

		int lineIndex = line - 1;
		if(lineIndex < 0)
			lineIndex = 0;

		ArrayList<View> views = new ArrayList<View>();
		final AbsListView absListView = waiter.waitForAndGetView(index, AbsListView.class);

		if(absListView == null)
			Assert.fail("AbsListView is null!");

		failIfIndexHigherThenChildCount(absListView, lineIndex, endTime);

		View viewOnLine = getViewOnAbsListLine(absListView, index, lineIndex);

		if(viewOnLine != null){
			views = viewFetcher.getViews(viewOnLine, true);
			views = RobotiumUtils.removeInvisibleViews(views);

			if(id == 0){
				clickOnScreen(viewOnLine, longClick, time);
			}
			else{
				clickOnScreen(getView(id, views));
			}
		}
		return RobotiumUtils.filterViews(TextView.class, views);
	}

	/**
	 * Clicks on a certain list line and returns the {@link TextView}s that
	 * the list line is showing. Will use the first list it finds.
	 *
	 * @param line the line that should be clicked
	 * @return a {@code List} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInRecyclerView(int line) {
		return clickInRecyclerView(line, 0, 0, false, 0);
	}

	/**
	 * Clicks on a View with a specified resource id located in a specified RecyclerView itemIndex
	 *
	 * @param itemIndex the index where the View is located
	 * @param id the resource id of the View
	 */

	public void clickInRecyclerView(int itemIndex, int id) {
		clickInRecyclerView(itemIndex, 0, id, false, 0);
	}

	/**
	 * Clicks on a certain list line on a specified List and
	 * returns the {@link TextView}s that the list line is showing.
	 *
	 * @param itemIndex the item index that should be clicked
	 * @param recyclerViewIndex the index of the RecyclerView. E.g. Index 1 if two RecyclerViews are available
	 * @param id the resource id of the View to click
	 * @return an {@code ArrayList} of the {@code TextView}s located in the list line
	 */

	public ArrayList<TextView> clickInRecyclerView(int itemIndex, int recyclerViewIndex, int id, boolean longClick, int time) {
		View viewOnLine = null;
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();

		if(itemIndex < 0)
			itemIndex = 0;

		ArrayList<View> views = new ArrayList<View>();
		ViewGroup recyclerView = viewFetcher.getRecyclerView(recyclerViewIndex, Timeout.getSmallTimeout());

		if(recyclerView == null){
			Assert.fail("RecyclerView is not found!");
		}
		else{
			failIfIndexHigherThenChildCount(recyclerView, itemIndex, endTime);
			viewOnLine = getViewOnRecyclerItemIndex((ViewGroup) recyclerView, recyclerViewIndex, itemIndex);
		}

		if(viewOnLine != null){
			views = viewFetcher.getViews(viewOnLine, true);
			views = RobotiumUtils.removeInvisibleViews(views);

			if(id == 0){
				clickOnScreen(viewOnLine, longClick, time);
			}
			else{
				clickOnScreen(getView(id, views));
			}
		}
		return RobotiumUtils.filterViews(TextView.class, views);
	}

	private View getView(int id, List<View> views){
		for(View view : views){
			if(id == view.getId()){
				return view;
			}
		}
		return null;
	}

	private void failIfIndexHigherThenChildCount(ViewGroup viewGroup, int index, long endTime){
		while(index > viewGroup.getChildCount()){
			final boolean timedOut = SystemClock.uptimeMillis() > endTime;
			if (timedOut){
				int numberOfIndexes = viewGroup.getChildCount();
				Assert.fail("Can not click on index " + index + " as there are only " + numberOfIndexes + " indexes available");
			}
			sleeper.sleep();
		}
	}

	/**
	 * Returns the view in the specified list line
	 *
	 * @param absListView the ListView to use
	 * @param index the index of the list. E.g. Index 1 if two lists are available
	 * @param lineIndex the line index of the View
	 * @return the View located at a specified list line
	 */

	private View getViewOnAbsListLine(AbsListView absListView, int index, int lineIndex){
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();
		View view = absListView.getChildAt(lineIndex);

		while(view == null){
			final boolean timedOut = SystemClock.uptimeMillis() > endTime;
			if (timedOut){
				Assert.fail("View is null and can therefore not be clicked!");
			}

			sleeper.sleep();
			absListView = (AbsListView) viewFetcher.getIdenticalView(absListView);

			if(absListView == null){
				absListView = waiter.waitForAndGetView(index, AbsListView.class);
			}

			view = absListView.getChildAt(lineIndex);
		}
		return view;
	}

	/**
	 * Returns the view in the specified item index
	 *
	 * @param recyclerView the RecyclerView to use
	 * @param itemIndex the item index of the View
	 * @return the View located at a specified item index
	 */

	private View getViewOnRecyclerItemIndex(ViewGroup recyclerView, int recyclerViewIndex, int itemIndex){
		final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout();
		View view = recyclerView.getChildAt(itemIndex);

		while(view == null){
			final boolean timedOut = SystemClock.uptimeMillis() > endTime;
			if (timedOut){
				Assert.fail("View is null and can therefore not be clicked!");
			}

			sleeper.sleep();
			recyclerView = (ViewGroup) viewFetcher.getIdenticalView(recyclerView);

			if(recyclerView == null){
				recyclerView = (ViewGroup) viewFetcher.getRecyclerView(false, recyclerViewIndex);
			}

			if(recyclerView != null){
				view = recyclerView.getChildAt(itemIndex);
			}
		}
		return view;
	}

}


1140 Grid added

require 'rubygems'
require 'sinatra/base'
require 'slim'
require 'sass'
require 'mongoid'

Mongoid.load!("config/mongoid.yml")

Slim::Engine.set_default_options :sections => false

class App < Sinatra::Base

  set :public, File.join(File.dirname(__FILE__), 'public')
  set :views, File.join(File.dirname(__FILE__), 'views')

  helpers do
    def partial(page, options={})
      haml page, options.merge!(:layout => false)
    end
  end

  get('/') do
    slim :index
  end

  get('/styles') do
    slim :styles
  end

end

/*
Syntax error: Invalid CSS after "...nge: background": expected selector or at-rule, was ": $orange; /* f..."
        on line 11 of public/stylesheets/styles.scss

6: $vine: #ac3900;
7: $white: #ffffff;
8: $black: #000000;
9: $lightgrey: #e6e5e5;
10: $textgrey: #959494;
11: $gradientorange: background: $orange; /* for non-css3 browsers */
12: filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$orange', endColorstr='$orangered'); /* for IE */
13: background: -webkit-gradient(linear, left top, left bottom, from($orange), to($orangered)); /* for webkit browsers */
14: background: -moz-linear-gradient(top,  $orange,  $orangered); /* for firefox 3.6+ */
15: ;
16:

Backtrace:
public/stylesheets/styles.scss:11
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/scss/parser.rb:1130:in `expected'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/scss/parser.rb:1066:in `expected'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/scss/parser.rb:28:in `parse'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/engine.rb:342:in `_to_tree'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/engine.rb:315:in `_render'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/engine.rb:262:in `render'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/plugin/compiler.rb:340:in `update_stylesheet'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/plugin/compiler.rb:202:in `block in update_stylesheets'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/plugin/compiler.rb:200:in `each'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/plugin/compiler.rb:200:in `update_stylesheets'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/lib/sass/plugin/compiler.rb:298:in `block in watch'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/vendor/listen/lib/listen/multi_listener.rb:86:in `call'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/vendor/listen/lib/listen/multi_listener.rb:86:in `on_change'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/vendor/listen/lib/listen/multi_listener.rb:95:in `block in initialize_adapter'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/vendor/listen/lib/listen/adapters/polling.rb:55:in `call'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/vendor/listen/lib/listen/adapters/polling.rb:55:in `poll'
/Users/bellatrix/.rvm/gems/ruby-1.9.3-p0@bartender/gems/sass-3.2.1/vendor/listen/lib/listen/adapters/polling.rb:31:in `block in start'
*/
body:before {
  white-space: pre;
  font-family: monospace;
  content: "Syntax error: Invalid CSS after \"...nge: background\": expected selector or at-rule, was \": $orange; /* f...\"\A         on line 11 of public/stylesheets/styles.scss\A \A 6: $vine: #ac3900;\A 7: $white: #ffffff;\A 8: $black: #000000;\A 9: $lightgrey: #e6e5e5;\A 10: $textgrey: #959494;\A 11: $gradientorange: background: $orange; /* for non-css3 browsers */\A 12: filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$orange', endColorstr='$orangered'); /* for IE */\A 13: background: -webkit-gradient(linear, left top, left bottom, from($orange), to($orangered)); /* for webkit browsers */\A 14: background: -moz-linear-gradient(top,  $orange,  $orangered); /* for firefox 3.6+ */ \A 15: ;\A 16: "; }

require 'rubygems'
require 'sinatra/base'
require 'slim'
require 'sass'
require 'mongoid'

Mongoid.load!("config/mongoid.yml")

Slim::Engine.set_default_options :sections => false

class App < Sinatra::Base

  set :public, File.join(File.dirname(__FILE__), 'public')
  set :views, File.join(File.dirname(__FILE__), 'views')

  helpers do
    def partial(page, options={})
      haml page, options.merge!(:layout => false)
    end
  end

  get('/') do
    slim :index
  end

  get('/styles') do
    slim :styles
  end

  get('/grid') do
    slim :grid
  end

end

if(typeof Object.create!=="function"){
Object.create=function(o){
function F(){
};
F.prototype=o;
return new F();
};
}
var ua={toString:function(){
return navigator.userAgent;
},test:function(s){
return this.toString().toLowerCase().indexOf(s.toLowerCase())>-1;
}};
ua.version=(ua.toString().toLowerCase().match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1];
ua.webkit=ua.test("webkit");
ua.gecko=ua.test("gecko")&&!ua.webkit;
ua.opera=ua.test("opera");
ua.ie=ua.test("msie")&&!ua.opera;
ua.ie6=ua.ie&&document.compatMode&&typeof document.documentElement.style.maxHeight==="undefined";
ua.ie7=ua.ie&&document.documentElement&&typeof document.documentElement.style.maxHeight!=="undefined"&&typeof XDomainRequest==="undefined";
ua.ie8=ua.ie&&typeof XDomainRequest!=="undefined";
var domReady=function(){
var _1=[];
var _2=function(){
if(!arguments.callee.done){
arguments.callee.done=true;
for(var i=0;i<_1.length;i++){
_1[i]();
}
}
};
if(document.addEventListener){
document.addEventListener("DOMContentLoaded",_2,false);
}
if(ua.ie){
(function(){
try{
document.documentElement.doScroll("left");
}
catch(e){
setTimeout(arguments.callee,50);
return;
}
_2();
})();
document.onreadystatechange=function(){
if(document.readyState==="complete"){
document.onreadystatechange=null;
_2();
}
};
}
if(ua.webkit&&document.readyState){
(function(){
if(document.readyState!=="loading"){
_2();
}else{
setTimeout(arguments.callee,10);
}
})();
}
window.onload=_2;
return function(fn){
if(typeof fn==="function"){
_1[_1.length]=fn;
}
return fn;
};
}();
var cssHelper=function(){
var _3={BLOCKS:/[^\s{][^{]*\{(?:[^{}]*\{[^{}]*\}[^{}]*|[^{}]*)*\}/g,BLOCKS_INSIDE:/[^\s{][^{]*\{[^{}]*\}/g,DECLARATIONS:/[a-zA-Z\-]+[^;]*:[^;]+;/g,RELATIVE_URLS:/url\(['"]?([^\/\)'"][^:\)'"]+)['"]?\)/g,REDUNDANT_COMPONENTS:/(?:\/\*([^*\\\\]|\*(?!\/))+\*\/|@import[^;]+;)/g,REDUNDANT_WHITESPACE:/\s*(,|:|;|\{|\})\s*/g,MORE_WHITESPACE:/\s{2,}/g,FINAL_SEMICOLONS:/;\}/g,NOT_WHITESPACE:/\S+/g};
var _4,_5=false;
var _6=[];
var _7=function(fn){
if(typeof fn==="function"){
_6[_6.length]=fn;
}
};
var _8=function(){
for(var i=0;i<_6.length;i++){
_6[i](_4);
}
};
var _9={};
var _a=function(n,v){
if(_9[n]){
var _b=_9[n].listeners;
if(_b){
for(var i=0;i<_b.length;i++){
_b[i](v);
}
}
}
};
var _c=function(_d,_e,_f){
if(ua.ie&&!window.XMLHttpRequest){
window.XMLHttpRequest=function(){
return new ActiveXObject("Microsoft.XMLHTTP");
};
}
if(!XMLHttpRequest){
return "";
}
var r=new XMLHttpRequest();
try{
r.open("get",_d,true);
r.setRequestHeader("X_REQUESTED_WITH","XMLHttpRequest");
}
catch(e){
_f();
return;
}
var _10=false;
setTimeout(function(){
_10=true;
},5000);
document.documentElement.style.cursor="progress";
r.onreadystatechange=function(){
if(r.readyState===4&&!_10){
if(!r.status&&location.protocol==="file:"||(r.status>=200&&r.status<300)||r.status===304||navigator.userAgent.indexOf("Safari")>-1&&typeof r.status==="undefined"){
_e(r.responseText);
}else{
_f();
}
document.documentElement.style.cursor="";
r=null;
}
};
r.send("");
};
var _11=function(_12){
_12=_12.replace(_3.REDUNDANT_COMPONENTS,"");
_12=_12.replace(_3.REDUNDANT_WHITESPACE,"$1");
_12=_12.replace(_3.MORE_WHITESPACE," ");
_12=_12.replace(_3.FINAL_SEMICOLONS,"}");
return _12;
};
var _13={mediaQueryList:function(s){
var o={};
var idx=s.indexOf("{");
var lt=s.substring(0,idx);
s=s.substring(idx+1,s.length-1);
var mqs=[],rs=[];
var qts=lt.toLowerCase().substring(7).split(",");
for(var i=0;i<qts.length;i++){
mqs[mqs.length]=_13.mediaQuery(qts[i],o);
}
var rts=s.match(_3.BLOCKS_INSIDE);
if(rts!==null){
for(i=0;i<rts.length;i++){
rs[rs.length]=_13.rule(rts[i],o);
}
}
o.getMediaQueries=function(){
return mqs;
};
o.getRules=function(){
return rs;
};
o.getListText=function(){
return lt;
};
o.getCssText=function(){
return s;
};
return o;
},mediaQuery:function(s,mql){
s=s||"";
var not=false,_14;
var exp=[];
var _15=true;
var _16=s.match(_3.NOT_WHITESPACE);
for(var i=0;i<_16.length;i++){
var _17=_16[i];
if(!_14&&(_17==="not"||_17==="only")){
if(_17==="not"){
not=true;
}
}else{
if(!_14){
_14=_17;
}else{
if(_17.charAt(0)==="("){
var _18=_17.substring(1,_17.length-1).split(":");
exp[exp.length]={mediaFeature:_18[0],value:_18[1]||null};
}
}
}
}
return {getList:function(){
return mql||null;
},getValid:function(){
return _15;
},getNot:function(){
return not;
},getMediaType:function(){
return _14;
},getExpressions:function(){
return exp;
}};
},rule:function(s,mql){
var o={};
var idx=s.indexOf("{");
var st=s.substring(0,idx);
var ss=st.split(",");
var ds=[];
var dts=s.substring(idx+1,s.length-1).split(";");
for(var i=0;i<dts.length;i++){
ds[ds.length]=_13.declaration(dts[i],o);
}
o.getMediaQueryList=function(){
return mql||null;
};
o.getSelectors=function(){
return ss;
};
o.getSelectorText=function(){
return st;
};
o.getDeclarations=function(){
return ds;
};
o.getPropertyValue=function(n){
for(var i=0;i<ds.length;i++){
if(ds[i].getProperty()===n){
return ds[i].getValue();
}
}
return null;
};
return o;
},declaration:function(s,r){
var idx=s.indexOf(":");
var p=s.substring(0,idx);
var v=s.substring(idx+1);
return {getRule:function(){
return r||null;
},getProperty:function(){
return p;
},getValue:function(){
return v;
}};
}};
var _19=function(el){
if(typeof el.cssHelperText!=="string"){
return;
}
var o={mediaQueryLists:[],rules:[],selectors:{},declarations:[],properties:{}};
var _1a=o.mediaQueryLists;
var ors=o.rules;
var _1b=el.cssHelperText.match(_3.BLOCKS);
if(_1b!==null){
for(var i=0;i<_1b.length;i++){
if(_1b[i].substring(0,7)==="@media "){
_1a[_1a.length]=_13.mediaQueryList(_1b[i]);
ors=o.rules=ors.concat(_1a[_1a.length-1].getRules());
}else{
ors[ors.length]=_13.rule(_1b[i]);
}
}
}
var oss=o.selectors;
var _1c=function(r){
var ss=r.getSelectors();
for(var i=0;i<ss.length;i++){
var n=ss[i];
if(!oss[n]){
oss[n]=[];
}
oss[n][oss[n].length]=r;
}
};
for(i=0;i<ors.length;i++){
_1c(ors[i]);
}
var ods=o.declarations;
for(i=0;i<ors.length;i++){
ods=o.declarations=ods.concat(ors[i].getDeclarations());
}
var ops=o.properties;
for(i=0;i<ods.length;i++){
var n=ods[i].getProperty();
if(!ops[n]){
ops[n]=[];
}
ops[n][ops[n].length]=ods[i];
}
el.cssHelperParsed=o;
_4[_4.length]=el;
return o;
};
var _1d=function(el,s){
el.cssHelperText=_11(s||el.innerHTML);
return _19(el);
};
var _1e=function(){
_5=true;
_4=[];
var _1f=[];
var _20=function(){
for(var i=0;i<_1f.length;i++){
_19(_1f[i]);
}
var _21=document.getElementsByTagName("style");
for(i=0;i<_21.length;i++){
_1d(_21[i]);
}
_5=false;
_8();
};
var _22=document.getElementsByTagName("link");
for(var i=0;i<_22.length;i++){
var _23=_22[i];
if(_23.getAttribute("rel").indexOf("style")>-1&&_23.href&&_23.href.length!==0&&!_23.disabled){
_1f[_1f.length]=_23;
}
}
if(_1f.length>0){
var c=0;
var _24=function(){
c++;
if(c===_1f.length){
_20();
}
};
var _25=function(_26){
var _27=_26.href;
_c(_27,function(_28){
_28=_11(_28).replace(_3.RELATIVE_URLS,"url("+_27.substring(0,_27.lastIndexOf("/"))+"/$1)");
_26.cssHelperText=_28;
_24();
},_24);
};
for(i=0;i<_1f.length;i++){
_25(_1f[i]);
}
}else{
_20();
}
};
var _29={mediaQueryLists:"array",rules:"array",selectors:"object",declarations:"array",properties:"object"};
var _2a={mediaQueryLists:null,rules:null,selectors:null,declarations:null,properties:null};
var _2b=function(_2c,v){
if(_2a[_2c]!==null){
if(_29[_2c]==="array"){
return (_2a[_2c]=_2a[_2c].concat(v));
}else{
var c=_2a[_2c];
for(var n in v){
if(v.hasOwnProperty(n)){
if(!c[n]){
c[n]=v[n];
}else{
c[n]=c[n].concat(v[n]);
}
}
}
return c;
}
}
};
var _2d=function(_2e){
_2a[_2e]=(_29[_2e]==="array")?[]:{};
for(var i=0;i<_4.length;i++){
_2b(_2e,_4[i].cssHelperParsed[_2e]);
}
return _2a[_2e];
};
domReady(function(){
var els=document.body.getElementsByTagName("*");
for(var i=0;i<els.length;i++){
els[i].checkedByCssHelper=true;
}
if(document.implementation.hasFeature("MutationEvents","2.0")||window.MutationEvent){
document.body.addEventListener("DOMNodeInserted",function(e){
var el=e.target;
if(el.nodeType===1){
_a("DOMElementInserted",el);
el.checkedByCssHelper=true;
}
},false);
}else{
setInterval(function(){
var els=document.body.getElementsByTagName("*");
for(var i=0;i<els.length;i++){
if(!els[i].checkedByCssHelper){
_a("DOMElementInserted",els[i]);
els[i].checkedByCssHelper=true;
}
}
},1000);
}
});
var _2f=function(d){
if(typeof window.innerWidth!="undefined"){
return window["inner"+d];
}else{
if(typeof document.documentElement!="undefined"&&typeof document.documentElement.clientWidth!="undefined"&&document.documentElement.clientWidth!=0){
return document.documentElement["client"+d];
}
}
};
return {addStyle:function(s,_30){
var el=document.createElement("style");
el.setAttribute("type","text/css");
document.getElementsByTagName("head")[0].appendChild(el);
if(el.styleSheet){
el.styleSheet.cssText=s;
}else{
el.appendChild(document.createTextNode(s));
}
el.addedWithCssHelper=true;
if(typeof _30==="undefined"||_30===true){
cssHelper.parsed(function(_31){
var o=_1d(el,s);
for(var n in o){
if(o.hasOwnProperty(n)){
_2b(n,o[n]);
}
}
_a("newStyleParsed",el);
});
}else{
el.parsingDisallowed=true;
}
return el;
},removeStyle:function(el){
return el.parentNode.removeChild(el);
},parsed:function(fn){
if(_5){
_7(fn);
}else{
if(typeof _4!=="undefined"){
if(typeof fn==="function"){
fn(_4);
}
}else{
_7(fn);
_1e();
}
}
},mediaQueryLists:function(fn){
cssHelper.parsed(function(_32){
fn(_2a.mediaQueryLists||_2d("mediaQueryLists"));
});
},rules:function(fn){
cssHelper.parsed(function(_33){
fn(_2a.rules||_2d("rules"));
});
},selectors:function(fn){
cssHelper.parsed(function(_34){
fn(_2a.selectors||_2d("selectors"));
});
},declarations:function(fn){
cssHelper.parsed(function(_35){
fn(_2a.declarations||_2d("declarations"));
});
},properties:function(fn){
cssHelper.parsed(function(_36){
fn(_2a.properties||_2d("properties"));
});
},broadcast:_a,addListener:function(n,fn){
if(typeof fn==="function"){
if(!_9[n]){
_9[n]={listeners:[]};
}
_9[n].listeners[_9[n].listeners.length]=fn;
}
},removeListener:function(n,fn){
if(typeof fn==="function"&&_9[n]){
var ls=_9[n].listeners;
for(var i=0;i<ls.length;i++){
if(ls[i]===fn){
ls.splice(i,1);
i-=1;
}
}
}
},getViewportWidth:function(){
return _2f("Width");
},getViewportHeight:function(){
return _2f("Height");
}};
}();
domReady(function enableCssMediaQueries(){
var _37;
var _38={LENGTH_UNIT:/[0-9]+(em|ex|px|in|cm|mm|pt|pc)$/,RESOLUTION_UNIT:/[0-9]+(dpi|dpcm)$/,ASPECT_RATIO:/^[0-9]+\/[0-9]+$/,ABSOLUTE_VALUE:/^[0-9]*(\.[0-9]+)*$/};
var _39=[];
var _3a=function(){
var id="css3-mediaqueries-test";
var el=document.createElement("div");
el.id=id;
var _3b=cssHelper.addStyle("@media all and (width) { #"+id+" { width: 1px !important; } }",false);
document.body.appendChild(el);
var ret=el.offsetWidth===1;
_3b.parentNode.removeChild(_3b);
el.parentNode.removeChild(el);
_3a=function(){
return ret;
};
return ret;
};
var _3c=function(){
_37=document.createElement("div");
_37.style.cssText="position:absolute;top:-9999em;left:-9999em;"+"margin:0;border:none;padding:0;width:1em;font-size:1em;";
document.body.appendChild(_37);
if(_37.offsetWidth!==16){
_37.style.fontSize=16/_37.offsetWidth+"em";
}
_37.style.width="";
};
var _3d=function(_3e){
_37.style.width=_3e;
var _3f=_37.offsetWidth;
_37.style.width="";
return _3f;
};
var _40=function(_41,_42){
var l=_41.length;
var min=(_41.substring(0,4)==="min-");
var max=(!min&&_41.substring(0,4)==="max-");
if(_42!==null){
var _43;
var _44;
if(_38.LENGTH_UNIT.exec(_42)){
_43="length";
_44=_3d(_42);
}else{
if(_38.RESOLUTION_UNIT.exec(_42)){
_43="resolution";
_44=parseInt(_42,10);
var _45=_42.substring((_44+"").length);
}else{
if(_38.ASPECT_RATIO.exec(_42)){
_43="aspect-ratio";
_44=_42.split("/");
}else{
if(_38.ABSOLUTE_VALUE){
_43="absolute";
_44=_42;
}else{
_43="unknown";
}
}
}
}
}
var _46,_47;
if("device-width"===_41.substring(l-12,l)){
_46=screen.width;
if(_42!==null){
if(_43==="length"){
return ((min&&_46>=_44)||(max&&_46<_44)||(!min&&!max&&_46===_44));
}else{
return false;
}
}else{
return _46>0;
}
}else{
if("device-height"===_41.substring(l-13,l)){
_47=screen.height;
if(_42!==null){
if(_43==="length"){
return ((min&&_47>=_44)||(max&&_47<_44)||(!min&&!max&&_47===_44));
}else{
return false;
}
}else{
return _47>0;
}
}else{
if("width"===_41.substring(l-5,l)){
_46=document.documentElement.clientWidth||document.body.clientWidth;
if(_42!==null){
if(_43==="length"){
return ((min&&_46>=_44)||(max&&_46<_44)||(!min&&!max&&_46===_44));
}else{
return false;
}
}else{
return _46>0;
}
}else{
if("height"===_41.substring(l-6,l)){
_47=document.documentElement.clientHeight||document.body.clientHeight;
if(_42!==null){
if(_43==="length"){
return ((min&&_47>=_44)||(max&&_47<_44)||(!min&&!max&&_47===_44));
}else{
return false;
}
}else{
return _47>0;
}
}else{
if("device-aspect-ratio"===_41.substring(l-19,l)){
return _43==="aspect-ratio"&&screen.width*_44[1]===screen.height*_44[0];
}else{
if("color-index"===_41.substring(l-11,l)){
var _48=Math.pow(2,screen.colorDepth);
if(_42!==null){
if(_43==="absolute"){
return ((min&&_48>=_44)||(max&&_48<_44)||(!min&&!max&&_48===_44));
}else{
return false;
}
}else{
return _48>0;
}
}else{
if("color"===_41.substring(l-5,l)){
var _49=screen.colorDepth;
if(_42!==null){
if(_43==="absolute"){
return ((min&&_49>=_44)||(max&&_49<_44)||(!min&&!max&&_49===_44));
}else{
return false;
}
}else{
return _49>0;
}
}else{
if("resolution"===_41.substring(l-10,l)){
var res;
if(_45==="dpcm"){
res=_3d("1cm");
}else{
res=_3d("1in");
}
if(_42!==null){
if(_43==="resolution"){
return ((min&&res>=_44)||(max&&res<_44)||(!min&&!max&&res===_44));
}else{
return false;
}
}else{
return res>0;
}
}else{
return false;
}
}
}
}
}
}
}
}
};
var _4a=function(mq){
var _4b=mq.getValid();
var _4c=mq.getExpressions();
var l=_4c.length;
if(l>0){
for(var i=0;i<l&&_4b;i++){
_4b=_40(_4c[i].mediaFeature,_4c[i].value);
}
var not=mq.getNot();
return (_4b&&!not||not&&!_4b);
}
};
var _4d=function(mql){
var mqs=mql.getMediaQueries();
var t={};
for(var i=0;i<mqs.length;i++){
if(_4a(mqs[i])){
t[mqs[i].getMediaType()]=true;
}
}
var s=[],c=0;
for(var n in t){
if(t.hasOwnProperty(n)){
if(c>0){
s[c++]=",";
}
s[c++]=n;
}
}
if(s.length>0){
_39[_39.length]=cssHelper.addStyle("@media "+s.join("")+"{"+mql.getCssText()+"}",false);
}
};
var _4e=function(_4f){
for(var i=0;i<_4f.length;i++){
_4d(_4f[i]);
}
if(ua.ie){
document.documentElement.style.display="block";
setTimeout(function(){
document.documentElement.style.display="";
},0);
setTimeout(function(){
cssHelper.broadcast("cssMediaQueriesTested");
},100);
}else{
cssHelper.broadcast("cssMediaQueriesTested");
}
};
var _50=function(){
for(var i=0;i<_39.length;i++){
cssHelper.removeStyle(_39[i]);
}
_39=[];
cssHelper.mediaQueryLists(_4e);
};
var _51=0;
var _52=function(){
var _53=cssHelper.getViewportWidth();
var _54=cssHelper.getViewportHeight();
if(ua.ie){
var el=document.createElement("div");
el.style.position="absolute";
el.style.top="-9999em";
el.style.overflow="scroll";
document.body.appendChild(el);
_51=el.offsetWidth-el.clientWidth;
document.body.removeChild(el);
}
var _55;
var _56=function(){
var vpw=cssHelper.getViewportWidth();
var vph=cssHelper.getViewportHeight();
if(Math.abs(vpw-_53)>_51||Math.abs(vph-_54)>_51){
_53=vpw;
_54=vph;
clearTimeout(_55);
_55=setTimeout(function(){
if(!_3a()){
_50();
}else{
cssHelper.broadcast("cssMediaQueriesTested");
}
},500);
}
};
window.onresize=function(){
var x=window.onresize||function(){
};
return function(){
x();
_56();
};
}();
};
var _57=document.documentElement;
_57.style.marginLeft="-32767px";
setTimeout(function(){
_57.style.marginTop="";
},20000);
return function(){
if(!_3a()){
cssHelper.addListener("newStyleParsed",function(el){
_4e(el.cssHelperParsed.mediaQueryLists);
});
cssHelper.addListener("cssMediaQueriesTested",function(){
if(ua.ie){
_57.style.width="1px";
}
setTimeout(function(){
_57.style.width="";
_57.style.marginLeft="";
},0);
cssHelper.removeListener("cssMediaQueriesTested",arguments.callee);
});
_3c();
_50();
}else{
_57.style.marginLeft="";
}
_52();
};
}());
try{
document.execCommand("BackgroundImageCache",false,true);
}
catch(e){
}

/* CSS Resets */

html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,address,cite,code,del,dfn,em,img,ins,q,small,strong,sub,sup,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{border:0;margin:0;padding:0}article,aside,figure,figure img,figcaption,hgroup,footer,header,nav,section,video,object{display:block}a img{border:0}figure{position:relative}figure img{width:100%}

/* ==================================================================================================================== */
/* ! The 1140px Grid V2 by Andy Taylor \ http://cssgrid.net \ http://www.twitter.com/andytlr \ http://www.andytlr.com   */
/* ==================================================================================================================== */

.container {
padding-left: 20px;
padding-right: 20px;
}

.row {
width: 100%;
max-width: 1140px;
min-width: 755px;
margin: 0 auto;
overflow: hidden;
}

.onecol, .twocol, .threecol, .fourcol, .fivecol, .sixcol, .sevencol, .eightcol, .ninecol, .tencol, .elevencol {
margin-right: 3.8%;
float: left;
min-height: 1px;
}

.row .onecol {
width: 4.85%;
}

.row .twocol {
width: 13.45%;
}

.row .threecol {
width: 22.05%;
}

.row .fourcol {
width: 30.75%;
}

.row .fivecol {
width: 39.45%;
}

.row .sixcol {
width: 48%;
}

.row .sevencol {
width: 56.75%;
}

.row .eightcol {
width: 65.4%;
}

.row .ninecol {
width: 74.05%;
}

.row .tencol {
width: 82.7%;
}

.row .elevencol {
width: 91.35%;
}

.row .twelvecol {
width: 100%;
float: left;
}

.last {
margin-right: 0px;
}

img, object, embed {
max-width: 100%;
}

img {
	height: auto;
}

/* Smaller screens */

@media only screen and (max-width: 1023px) {

	body {
	font-size: 0.8em;
	line-height: 1.5em;
	}

	}

/* Mobile */

@media handheld, only screen and (max-width: 767px) {

	body {
	font-size: 16px;
	-webkit-text-size-adjust: none;
	}

	.row, body, .container {
	width: 100%;
	min-width: 0;
	margin-left: 0px;
	margin-right: 0px;
	padding-left: 0px;
	padding-right: 0px;
	}

	.row .onecol, .row .twocol, .row .threecol, .row .fourcol, .row .fivecol, .row .sixcol, .row .sevencol, .row .eightcol, .row .ninecol, .row .tencol, .row .elevencol, .row .twelvecol {
	width: auto;
	float: none;
	margin-left: 0px;
	margin-right: 0px;
	padding-left: 20px;
	padding-right: 20px;
	}

}

.onecol {
width: 4.7%;
}

.twocol {
width: 13.2%;
}

.threecol {
width: 22.05%;
}

.fourcol {
width: 30.6%;
}

.fivecol {
width: 39%;
}

.sixcol {
width: 48%;
}

.sevencol {
width: 56.75%;
}

.eightcol {
width: 61.6%;
}

.ninecol {
width: 74.05%;
}

.tencol {
width: 82%;
}

.elevencol {
width: 91.35%;
}

.clear {
  clear: both; }

#wrapper {
  width: 1024px;
  margin: 50px auto; }

hr {
  border-bottom: #e6e5e5;
  opacity: 0.3; }

h1, h2, h3, h4, p, a, li {
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
  font-weight: 100;
  color: #282827; }

h1 {
  font-size: 6em;
  letter-spacing: -6px;
  line-height: 0.95em;
  margin: 10px 0;
  color: black; }

h2 {
  font-size: 4em;
  letter-spacing: -4px;
  line-height: 0.85em; }

h3 {
  font-size: 3em;
  letter-spacing: -3px;
  line-height: 0.85em;
  margin: 10px 0 20px 0; }

h4 {
  font-size: 2em;
  letter-spacing: -0.5px;
  line-height: 0.85em;
  margin: 10px 0 20px 0; }

p, a, li {
  font-size: 1.2em; }

a {
  color: #fc5401; }
  a:hover {
    color: #282827; }

li {
  line-height: 30px; }

.button.orange {
  border: 1px solid #fc5401;
  -webkit-border-radius: 4px;
  border-radius: 4px;
  float: left;
  color: white;
  padding: 10px 20px;
  box-shadow: 0 3px 2px -2px gray;
  margin: 20px 0;
  background: #e37600;
  /* for non-css3 browsers */
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e37600', endColorstr='#fc5401');
  /* for IE */
  background: -webkit-gradient(linear, left top, left bottom, from(#e37600), to(#fc5401));
  /* for webkit browsers */
  background: -moz-linear-gradient(top, #e37600, #fc5401);
  /* for firefox 3.6+ */
  border: 1px solid #fc5401; }
  .button.orange a {
    text-decoration: none; }
  .button.orange p {
    margin: 0;
    font-size: 1em;
    color: white; }
  .button.orange:hover {
    background: #fc5401;
    /* for non-css3 browsers */
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fc5401', endColorstr='#e37600');
    /* for IE */
    background: -webkit-gradient(linear, left top, left bottom, from(#fc5401), to(#e37600));
    /* for webkit browsers */
    background: -moz-linear-gradient(top, #fc5401, #e37600);
    /* for firefox 3.6+ */
    border: 1px solid #fc5401; }

.title {
  width: 100%;
  border-bottom: 3px solid black;
  margin: 0 0 40px 0; }

.twocolumn {
  width: 50%;
  float: left;
  margin: 0 0 50px 0; }

form {
  width: 100%;
  padding: 10px;
  background: white;
  /* for non-css3 browsers */
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$white', endColorstr='$lightgrey');
  /* for IE */
  background: -webkit-gradient(linear, left top, left bottom, from(white), to(#e6e5e5));
  /* for webkit browsers */
  background: -moz-linear-gradient(top, white, #e6e5e5);
  /* for firefox 3.6+ */
  border: 1px solid #e6e5e5;
  position: relative;
  margin: 20px 0 50px 0; }

form:before, form:after {
  content: "";
  position: absolute;
  z-index: -1;
  bottom: 8px;
  left: 10px;
  width: 60%;
  height: 20%;
  max-width: 300px;
  -webkit-box-shadow: 0 10px 10px rgba(0, 0, 0, 0.5);
  -moz-box-shadow: 0 10px 10px rgba(0, 0, 0, 0.5);
  box-shadow: 0 10px 10px rgba(0, 0, 0, 0.5);
  -webkit-transform: rotate(-3deg);
  -moz-transform: rotate(-3deg);
  -o-transform: rotate(-3deg);
  transform: rotate(-3deg); }

form:after {
  right: 10px;
  left: auto;
  -webkit-transform: rotate(3deg);
  -moz-transform: rotate(3deg);
  -o-transform: rotate(3deg);
  transform: rotate(3deg); }

input, textarea, select {
  width: 95%;
  border: 1px solid #e6e5e5;
  height: 35px;
  padding: 5px 10px;
  margin: 0 0 10px 0;
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
  font-size: 18px;
  color: #959494; }

select {
  width: 99%;
  height: 40px;
  font-size: 1.2em; }

textarea {
  height: 100px; }

label.label_input {
  width: 95%;
  position: absolute;
  top: 1px;
  right: 1px;
  bottom: 1px;
  left: 2px;
  z-index: 1;
  padding: 13px 3px 13px 10px;
  line-height: 20px;
  white-space: nowrap;
  cursor: text;
  display: block;
  font-size: 1.1em;
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
  color: #959494; }

label {
  font-size: 1.2em;
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
  color: #959494;
  float: left; }

.input-placeholder {
  position: relative; }

.button.orange.send {
  width: 30%;
  margin: 10px 0 10px 150px;
  line-height: 0;
  letter-spacing: 0; }

.boxui.header, .boxui.box {
  width: 100%;
  -webkit-border-radius: 4px 4px 0 0;
  border-radius: 4px 4px 0 0;
  background: white;
  border: 1px solid #e6e5e5;
  margin: 40px 0 0 0;
  background: white;
  /* for non-css3 browsers */
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$white', endColorstr='$lightgrey');
  /* for IE */
  background: -webkit-gradient(linear, left top, left bottom, from(white), to(#e6e5e5));
  /* for webkit browsers */
  background: -moz-linear-gradient(top, white, #e6e5e5);
  /* for firefox 3.6+ */
  padding: 10px; }
  .boxui.header p, .boxui.box p {
    margin: 0; }

.boxui.box {
  -webkit-border-radius: 0 0 4px 4px;
  border-radius: 0 0 4px 4px;
  margin: 0;
  background: white; }

label, select {
  font-size: 1.1em; }

.radio {
  width: 5%;
  float: left;
  height: 22px; }

.container p {
  color: #fff;
  line-height: 100px;
  background: #000;
  text-align: center;
  margin: 20px 0 0 0; }