arduinocc
Published © GPL3+

Voice Controlled Arduino

Control your Arduino project from anywhere using your mobile or home voice assistant!

IntermediateFull instructions provided1,086
Voice Controlled Arduino

Things used in this project

Hardware components

ESP32
Espressif ESP32
Any Wifi Connected Arduino Compatible board can be used
×1

Software apps and online services

Visual Studio 2017
Microsoft Visual Studio 2017
Assistant SDK
Google Assistant SDK
Visual Micro
Maker service
IFTTT Maker service
Arduino IDE
Arduino IDE

Story

Read more

Schematics

ESP Power Plug Wiring Example

An Example of wiring an RF Transmitter to an ESP32 to allow a set of RF Power sockets to be controlled from the Arduino platform.

Code

Arduino Example Software for ESP32/ESP8266

Arduino
Example software which is triggered by Google Assistant and turns on / off a power socket.

Also has web UI which allows for web page control of the socket as well.

Change headers if using a different board
/*
 Name:		ESP32_WebServerApp_Example.ino
 Created:	3/14/2019 12:06:43 AM
 Author:	Simon

 Simple WebApp on SPIFFS Served Locally via mDNS Name or IP
 Example #1 - RF Lightswitches - ESP32 as WiFi Client, Simple AJAX Requests or whole page loads for now (no WS yet)

 Upload and go to http://esp32.local (or inspect Serial monitor if connecting via IP)

 */
#ifdef ESP32
	#include <spiffs.h>
	#include <WiFi.h>
	#include <ESPmDNS.h>
    #define FORMAT_SPIFFS_IF_FAILED false		// You may have to set this to true the first time you run this
#endif 

#ifdef ESP8266
	#include <FS.h>
	#include <ESP8266WiFi.h>
	#include <ESP8266mDNS.h>
	#define FORMAT_SPIFFS_IF_FAILED                 // Leave Empty on ESP8266
#endif

#include <RCSwitch.h>

// WiFi Client Settings
const char* ssid = "**************";
const char* password = "**************";
const char* mDnsName = "esp32";
const byte hwPin_rfTx = 2;

WiFiServer server(9090);
RCSwitch mySwitch = RCSwitch();
File root;
void setup() {
	Serial.begin(115200);
	delay(5000);
	// Setup our File System in SPIFFS
	if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) {
		Serial.println("SPIFFS Mount Failed");
		return;
	}
	root = SPIFFS.open("/", "r");

	// Static IP Configuration
	IPAddress local_IP(192, 168, 0, 55);
	IPAddress gateway(192, 168, 0, 1);
	IPAddress subnet(255, 255, 255, 0);
	IPAddress primaryDNS(192, 168, 0, 1);
	IPAddress secondaryDNS(8, 8, 4, 4); // fake

	WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);

	// Setup the Web Connection
	WiFi.begin(ssid, password);

	Serial.println(F("Connecting to Wifi. "));
	while (!WL_CONNECTED || WiFi.localIP().toString() == "0.0.0.0") {
		delay(500); // Yield() sdasdasdasd
		Serial.print(". ");
	}

	// Setup our Remote Controlled Wall Socket
	mySwitch.enableTransmit(2);
	Serial.print("Connected to ");
	Serial.print(ssid);
	Serial.print(" on IP address: ");
	Serial.println(WiFi.localIP());

	// Set up mDNS responder:
	// - first argument is the domain name, in this example
	//   the fully-qualified domain name is "mDnsName.local"
	if (!MDNS.begin(mDnsName)) {
		Serial.println("Error setting up MDNS responder!");
	}
	else {
		Serial.println("mDNS responder started");
	}

	// Finally startup the web server
	server.begin();
	Serial.println("TCP server started.");

	// Bind the HTTP requests via MDNS
	MDNS.addService("http", "tcp", 9090);
}


void loop(void) {
	WiFiClient client = server.available();   // listen for incoming clients

	if (client) { // Someone is talking to us...


		String currentLine = "";											// make a String to hold incoming data from the client
		while (client.connected()) {									    // loop while the client's connected

			String req = client.readStringUntil('\r');						// Read the first line of HTTP request

			// First line of HTTP request looks like "GET /path HTTP/1.1"
			// Retrieve the "/path" part by finding the spaces
			int addr_start = req.indexOf(' ');
			int addr_end = req.indexOf(' ', addr_start + 1);
			if (addr_start == -1 || addr_end == -1) {
				Serial.print("Invalid request: ");
				Serial.println(req);
				break;
			}
			req = req.substring(addr_start + 1, addr_end);
			Serial.print("Request: ");
			Serial.println(req);

			// Set Access Control Policy to allow CORS (Not actually needed here at present...)
			client.println("HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: text/html\r\n\r\n");
			handleFileRead(req, client);
		}

		// close the connection:
		client.stop();
		Serial.println("Client Disconnected.");
	}
}

// Handle all the content types we may get asked for from our SPIFFS
String getContentType(String filename) {
	if (filename.endsWith(".htm")) return "text/html";
	else if (filename.endsWith(".html")) return "text/html";
	else if (filename.endsWith(".css")) return "text/css";
	else if (filename.endsWith(".js")) return "application/javascript";
	else if (filename.endsWith(".png")) return "image/png";
	else if (filename.endsWith(".gif")) return "image/gif";
	else if (filename.endsWith(".jpg")) return "image/jpeg";
	else if (filename.endsWith(".ico")) return "image/x-icon";
	else if (filename.endsWith(".xml")) return "text/xml";
	return "text/plain";
}

// Handle a File request either via our custom handlers, or simply serving a file...
bool handleFileRead(String path, WiFiClient &client) {
	Serial.println("handleFileRead: " + path);
	if (path.endsWith("/")) path += "index.html";         // If a folder is requested, send the index file
	String contentType = getContentType(path);            // Get the MIME type

	// Simple hardcoding for now but can easily be expanded into the below
	// If we used a command with a number it would map in but "turn the light 1" sounds odd..
	if (path.startsWith("/on")) {
		mySwitch.switchOn(1, 1);
	}
	else if (path.startsWith("/off")) {
		mySwitch.switchOff(1, 1);
	}
	else
	// Handle our "custom" (non-file) requests first 
	// We Expect the URL  in format /socket/1/1/1 meaning:Socket 1, Address 1, Action ON
	if (path.startsWith("/socket/")) {
		int socket = path.charAt(8) - 48;
		int address = path.charAt(10) - 48;
		int action = path.charAt(12) - 48;

		client.print("Socket ");
		client.print(socket);	
		client.print(":");
		client.print(address);

		if (action == 1) {
			mySwitch.switchOn(socket, address);
			client.println(" ON");
			return true;
		}
		else {
			mySwitch.switchOff(socket, address);
			client.println(" OFF");
			return true;
		}
	}
	else if (SPIFFS.exists(path)) {                            // If the file exists
		File file = SPIFFS.open(path, "r");					   // Open it
		client.print(file.readStringUntil(EOF));			   // Read Until End Of File back to client
		file.close();                                          // Then close the file again
		return true;
	}

	Serial.println("\tFile Not Found");
	client.print("<b>Invalid Request</b>");		          // Show the user some info on web page
	return false;                                         // If the file doesn't exist, return false
}

data\Index.html

HTML
Web Page for data partition of ESP board (or PROGMEM / Webserver).
For ESP place in "sketchFolder\data" for upload via SPIFFS

Uses simple responsive framework (included in other files)
<HTML>
<HEAD>
    <!-- Basic Page Needs  -->
    <meta charset="utf-8">
    <title>ESP Web App</title>
    <meta name="description" content="Starting you Off with IoT">
    <meta name="author" content="vMicro">

    <!-- Mobile Specific Metas   -->
    <meta name="viewport" content="width=device-width, initial-scale=1; maximum-scale=5.0; user-scalable=0;">
    <meta name="apple-mobile-web-app-capable" content="yes" />

    <!-- CSS   -->
    <link rel="stylesheet" href="normalize.css">
    <link rel="stylesheet" href="skeleton.css">

    <!-- Client Scripts  -->
    <script type="text/javascript" src="/ClientSideScript.js"></script>
</HEAD>
<BODY>
    
    <div class="container">
        <div class="row">
            <h2>Embedded SPIFFS ESP Application (8266/8285/32)</h2>
            <p>About as simple as it can be made, and all simplistic, easy to edit code.....</p>
        </div>
        <div class="row">
            <button id="on" class="button-primary">1-1 On</button>
            <button id="off">1-1 Off</button>
        </div>
        <div class="row">
            <div>Response: <span id="infoPanel"></span></div>
        </div>
    </div>
</BODY>


</HTML>

ClientSideScript.js

JavaScript
Client JS to support web page.

For ESP place in "sketchFolder\data" for upload via SPIFFS
// Everything in pure JS to save codespace for your preferred Libs
window.addEventListener("load", onWindowLoad);

// This all kicks in when the page lands on the client browser
function onWindowLoad() {
    console.log("Page Loaded");
    // Add some Listeners to our buttons to send requests back
    document.getElementById("on").addEventListener("click", sendOnRequest);
    document.getElementById("off").addEventListener("click", sendOffRequest);
}

function sendOnRequest() {
    sendAjaxRequest(
        function () {
            document.getElementById("infoPanel").innerHTML = this.responseText;
        }
        , "GET"
        , "/socket/1/1/1"
    );
}

function sendOffRequest() {
    sendAjaxRequest(
        function () {
            document.getElementById("infoPanel").innerHTML = this.responseText;
        }
        , "GET"
        , "/socket/1/1/0"
    );
}

// Generic wrapper to send requests to the server
function sendAjaxRequest(onReplyFunction, method, url) {
    var xhttp = new XMLHttpRequest()
    // What happens when the server replies with an answer
    xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
            onReplyFunction.call(this);
        }
    };
    xhttp.open(method, url, true);
    xhttp.send();

}

normalize.css

CSS
Responsive CSS to support web page.

For ESP place in "sketchFolder\data" for upload via SPIFFS
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */

/**
 * 1. Set default font family to sans-serif.
 * 2. Prevent iOS text size adjust after orientation change, without disabling
 *    user zoom.
 */

html {
  font-family: sans-serif; /* 1 */
  -ms-text-size-adjust: 100%; /* 2 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/**
 * Remove default margin.
 */

body {
  margin: 0;
}

/* HTML5 display definitions
   ========================================================================== */

/**
 * Correct `block` display not defined for any HTML5 element in IE 8/9.
 * Correct `block` display not defined for `details` or `summary` in IE 10/11
 * and Firefox.
 * Correct `block` display not defined for `main` in IE 11.
 */

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
  display: block;
}

/**
 * 1. Correct `inline-block` display not defined in IE 8/9.
 * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
 */

audio,
canvas,
progress,
video {
  display: inline-block; /* 1 */
  vertical-align: baseline; /* 2 */
}

/**
 * Prevent modern browsers from displaying `audio` without controls.
 * Remove excess height in iOS 5 devices.
 */

audio:not([controls]) {
  display: none;
  height: 0;
}

/**
 * Address `[hidden]` styling not present in IE 8/9/10.
 * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
 */

[hidden],
template {
  display: none;
}

/* Links
   ========================================================================== */

/**
 * Remove the gray background color from active links in IE 10.
 */

a {
  background-color: transparent;
}

/**
 * Improve readability when focused and also mouse hovered in all browsers.
 */

a:active,
a:hover {
  outline: 0;
}

/* Text-level semantics
   ========================================================================== */

/**
 * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
 */

abbr[title] {
  border-bottom: 1px dotted;
}

/**
 * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
 */

b,
strong {
  font-weight: bold;
}

/**
 * Address styling not present in Safari and Chrome.
 */

dfn {
  font-style: italic;
}

/**
 * Address variable `h1` font-size and margin within `section` and `article`
 * contexts in Firefox 4+, Safari, and Chrome.
 */

h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

/**
 * Address styling not present in IE 8/9.
 */

mark {
  background: #ff0;
  color: #000;
}

/**
 * Address inconsistent and variable font size in all browsers.
 */

small {
  font-size: 80%;
}

/**
 * Prevent `sub` and `sup` affecting `line-height` in all browsers.
 */

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sup {
  top: -0.5em;
}

sub {
  bottom: -0.25em;
}

/* Embedded content
   ========================================================================== */

/**
 * Remove border when inside `a` element in IE 8/9/10.
 */

img {
  border: 0;
}

/**
 * Correct overflow not hidden in IE 9/10/11.
 */

svg:not(:root) {
  overflow: hidden;
}

/* Grouping content
   ========================================================================== */

/**
 * Address margin not present in IE 8/9 and Safari.
 */

figure {
  margin: 1em 40px;
}

/**
 * Address differences between Firefox and other browsers.
 */

hr {
  -moz-box-sizing: content-box;
  box-sizing: content-box;
  height: 0;
}

/**
 * Contain overflow in all browsers.
 */

pre {
  overflow: auto;
}

/**
 * Address odd `em`-unit font size rendering in all browsers.
 */

code,
kbd,
pre,
samp {
  font-family: monospace, monospace;
  font-size: 1em;
}

/* Forms
   ========================================================================== */

/**
 * Known limitation: by default, Chrome and Safari on OS X allow very limited
 * styling of `select`, unless a `border` property is set.
 */

/**
 * 1. Correct color not being inherited.
 *    Known issue: affects color of disabled elements.
 * 2. Correct font properties not being inherited.
 * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
 */

button,
input,
optgroup,
select,
textarea {
  color: inherit; /* 1 */
  font: inherit; /* 2 */
  margin: 0; /* 3 */
}

/**
 * Address `overflow` set to `hidden` in IE 8/9/10/11.
 */

button {
  overflow: visible;
}

/**
 * Address inconsistent `text-transform` inheritance for `button` and `select`.
 * All other form control elements do not inherit `text-transform` values.
 * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
 * Correct `select` style inheritance in Firefox.
 */

button,
select {
  text-transform: none;
}

/**
 * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
 *    and `video` controls.
 * 2. Correct inability to style clickable `input` types in iOS.
 * 3. Improve usability and consistency of cursor style between image-type
 *    `input` and others.
 */

button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
  -webkit-appearance: button; /* 2 */
  cursor: pointer; /* 3 */
}

/**
 * Re-set default cursor for disabled elements.
 */

button[disabled],
html input[disabled] {
  cursor: default;
}

/**
 * Remove inner padding and border in Firefox 4+.
 */

button::-moz-focus-inner,
input::-moz-focus-inner {
  border: 0;
  padding: 0;
}

/**
 * Address Firefox 4+ setting `line-height` on `input` using `!important` in
 * the UA stylesheet.
 */

input {
  line-height: normal;
}

/**
 * It's recommended that you don't attempt to style these elements.
 * Firefox's implementation doesn't respect box-sizing, padding, or width.
 *
 * 1. Address box sizing set to `content-box` in IE 8/9/10.
 * 2. Remove excess padding in IE 8/9/10.
 */

input[type="checkbox"],
input[type="radio"] {
  box-sizing: border-box; /* 1 */
  padding: 0; /* 2 */
}

/**
 * Fix the cursor style for Chrome's increment/decrement buttons. For certain
 * `font-size` values of the `input`, it causes the cursor style of the
 * decrement button to change from `default` to `text`.
 */

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  height: auto;
}

/**
 * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
 * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
 *    (include `-moz` to future-proof).
 */

input[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  -moz-box-sizing: content-box;
  -webkit-box-sizing: content-box; /* 2 */
  box-sizing: content-box;
}

/**
 * Remove inner padding and search cancel button in Safari and Chrome on OS X.
 * Safari (but not Chrome) clips the cancel button when the search input has
 * padding (and `textfield` appearance).
 */

input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
 * Define consistent border, margin, and padding.
 */

fieldset {
  border: 1px solid #c0c0c0;
  margin: 0 2px;
  padding: 0.35em 0.625em 0.75em;
}

/**
 * 1. Correct `color` not being inherited in IE 8/9/10/11.
 * 2. Remove padding so people aren't caught out if they zero out fieldsets.
 */

legend {
  border: 0; /* 1 */
  padding: 0; /* 2 */
}

/**
 * Remove default vertical scrollbar in IE 8/9/10/11.
 */

textarea {
  overflow: auto;
}

/**
 * Don't inherit the `font-weight` (applied by a rule above).
 * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
 */

optgroup {
  font-weight: bold;
}

/* Tables
   ========================================================================== */

/**
 * Remove most spacing between table cells.
 */

table {
  border-collapse: collapse;
  border-spacing: 0;
}

td,
th {
  padding: 0;
}

skeleton.css

CSS
Responsive CSS to support web page.

For ESP place in "sketchFolder\data" for upload via SPIFFS
/*
* Skeleton V2.0.4
* Copyright 2014, Dave Gamache
* www.getskeleton.com
* Free to use under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
* 12/29/2014
*/


/* Table of contents

- Grid
- Base Styles
- Typography
- Links
- Buttons
- Forms
- Lists
- Code
- Tables
- Spacing
- Utilities
- Clearing
- Media Queries
*/


/* Grid
 */
.container {
  position: relative;
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: 0 20px;
  box-sizing: border-box; }
.column,
.columns {
  width: 100%;
  float: left;
  box-sizing: border-box; }

/* For devices larger than 400px */
@media (min-width: 400px) {
  .container {
    width: 85%;
    padding: 0; }
}

/* For devices larger than 550px */
/* HACKED To ensure it remains the same on mobile */
@media (min-width: 320px) {
  .container {
    width: 80%; }
  .column,
  .columns {
    margin-left: 4%; }
  .column:first-child,
  .columns:first-child {
    margin-left: 0; }

  .one.column,
  .one.columns                    { width: 4.66666666667%; }
  .two.columns                    { width: 13.3333333333%; }
  .three.columns                  { width: 22%;            }
  .four.columns                   { width: 30.6666666667%; }
  .five.columns                   { width: 39.3333333333%; }
  .six.columns                    { width: 48%;            }
  .seven.columns                  { width: 56.6666666667%; }
  .eight.columns                  { width: 65.3333333333%; }
  .nine.columns                   { width: 74.0%;          }
  .ten.columns                    { width: 82.6666666667%; }
  .eleven.columns                 { width: 91.3333333333%; }
  .twelve.columns                 { width: 100%; margin-left: 0; }

  .one-third.column               { width: 30.6666666667%; }
  .two-thirds.column              { width: 65.3333333333%; }

  .one-half.column                { width: 48%; }

  /* Offsets */
  .offset-by-one.column,
  .offset-by-one.columns          { margin-left: 8.66666666667%; }
  .offset-by-two.column,
  .offset-by-two.columns          { margin-left: 17.3333333333%; }
  .offset-by-three.column,
  .offset-by-three.columns        { margin-left: 26%;            }
  .offset-by-four.column,
  .offset-by-four.columns         { margin-left: 34.6666666667%; }
  .offset-by-five.column,
  .offset-by-five.columns         { margin-left: 43.3333333333%; }
  .offset-by-six.column,
  .offset-by-six.columns          { margin-left: 52%;            }
  .offset-by-seven.column,
  .offset-by-seven.columns        { margin-left: 60.6666666667%; }
  .offset-by-eight.column,
  .offset-by-eight.columns        { margin-left: 69.3333333333%; }
  .offset-by-nine.column,
  .offset-by-nine.columns         { margin-left: 78.0%;          }
  .offset-by-ten.column,
  .offset-by-ten.columns          { margin-left: 86.6666666667%; }
  .offset-by-eleven.column,
  .offset-by-eleven.columns       { margin-left: 95.3333333333%; }

  .offset-by-one-third.column,
  .offset-by-one-third.columns    { margin-left: 34.6666666667%; }
  .offset-by-two-thirds.column,
  .offset-by-two-thirds.columns   { margin-left: 69.3333333333%; }

  .offset-by-one-half.column,
  .offset-by-one-half.columns     { margin-left: 52%; }

}


/* Base Styles
 */
/* NOTE
html is set to 62.5% so that all the REM measurements throughout Skeleton
are based on 10px sizing. So basically 1.5rem = 15px :) */
html {
  font-size: 62.5%; }
body {
  font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
  line-height: 1.6;
  font-weight: 400;
  font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
  color: #222; }


/* Typography
 */
h1, h2, h3, h4, h5, h6 {
  margin-top: 0;
  margin-bottom: 2rem;
  font-weight: 300; }
h1 { font-size: 4.0rem; line-height: 1.2;  letter-spacing: -.1rem;}
h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
h3 { font-size: 3.0rem; line-height: 1.3;  letter-spacing: -.1rem; }
h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
h5 { font-size: 1.8rem; line-height: 1.5;  letter-spacing: -.05rem; }
h6 { font-size: 1.5rem; line-height: 1.6;  letter-spacing: 0; }

/* Larger than phablet */
@media (min-width: 550px) {
  h1 { font-size: 5.0rem; }
  h2 { font-size: 4.2rem; }
  h3 { font-size: 3.6rem; }
  h4 { font-size: 3.0rem; }
  h5 { font-size: 2.4rem; }
  h6 { font-size: 1.5rem; }
}

p {
  margin-top: 0; }


/* Links
 */
a {
  color: #1EAEDB; }
a:hover {
  color: #0FA0CE; }


/* Buttons
 */
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
  display: inline-block;
  height: 38px;
  padding: 0 30px;
  color: #555;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  line-height: 38px;
  letter-spacing: .1rem;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  background-color: transparent;
  border-radius: 4px;
  border: 1px solid #bbb;
  cursor: pointer;
  box-sizing: border-box; }
.button:hover,
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
input[type="button"]:hover,
.button:focus,
button:focus,
input[type="submit"]:focus,
input[type="reset"]:focus,
input[type="button"]:focus {
  color: #333;
  border-color: #888;
  outline: 0; }
.button.button-primary,
button.button-primary,
input[type="submit"].button-primary,
input[type="reset"].button-primary,
input[type="button"].button-primary {
  color: #FFF;
  background-color: #33C3F0;
  border-color: #33C3F0; }
.button.button-primary:hover,
button.button-primary:hover,
input[type="submit"].button-primary:hover,
input[type="reset"].button-primary:hover,
input[type="button"].button-primary:hover,
.button.button-primary:focus,
button.button-primary:focus,
input[type="submit"].button-primary:focus,
input[type="reset"].button-primary:focus,
input[type="button"].button-primary:focus {
  color: #FFF;
  background-color: #1EAEDB;
  border-color: #1EAEDB; }


/* Forms
 */
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea,
select {
  height: 38px;
  padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
  background-color: #fff;
  border: 1px solid #D1D1D1;
  border-radius: 4px;
  box-shadow: none;
  box-sizing: border-box; }
/* Removes awkward default styles on some inputs for iOS */
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none; }
textarea {
  min-height: 65px;
  padding-top: 6px;
  padding-bottom: 6px; }
input[type="email"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="text"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
textarea:focus,
select:focus {
  border: 1px solid #33C3F0;
  outline: 0; }
label,
legend {
  display: block;
  margin-bottom: .5rem;
  font-weight: 600; }
fieldset {
  padding: 0;
  border-width: 0; }
input[type="checkbox"],
input[type="radio"] {
  display: inline; }
label > .label-body {
  display: inline-block;
  margin-left: .5rem;
  font-weight: normal; }


/* Lists
 */
ul {
  list-style: circle inside; }
ol {
  list-style: decimal inside; }
ol, ul {
  padding-left: 0;
  margin-top: 0; }
ul ul,
ul ol,
ol ol,
ol ul {
  margin: 1.5rem 0 1.5rem 3rem;
  font-size: 90%; }
li {
  margin-bottom: 1rem; }


/* Code
 */
code {
  padding: .2rem .5rem;
  margin: 0 .2rem;
  font-size: 90%;
  white-space: nowrap;
  background: #F1F1F1;
  border: 1px solid #E1E1E1;
  border-radius: 4px; }
pre > code {
  display: block;
  padding: 1rem 1.5rem;
  white-space: pre; }


/* Tables
 */
th,
td {
  padding: 12px 15px;
  text-align: left;
  border-bottom: 1px solid #E1E1E1; }
th:first-child,
td:first-child {
  padding-left: 0; }
th:last-child,
td:last-child {
  padding-right: 0; }


/* Spacing
 */
button,
.button {
  margin-bottom: 1rem; }
input,
textarea,
select,
fieldset {
  margin-bottom: 1.5rem; }
pre,
blockquote,
dl,
figure,
table,
p,
ul,
ol,
form {
  margin-bottom: 2.5rem; }


/* Utilities
 */
.u-full-width {
  width: 100%;
  box-sizing: border-box; }
.u-max-full-width {
  max-width: 100%;
  box-sizing: border-box; }
.u-pull-right {
  float: right; }
.u-pull-left {
  float: left; }


/* Misc
 */
hr {
  margin-top: 3rem;
  margin-bottom: 3.5rem;
  border-width: 0;
  border-top: 1px solid #E1E1E1; }


/* Clearing
 */

/* Self Clearing Goodness */
.container:after,
.row:after,
.u-cf {
  content: "";
  display: table;
  clear: both; }


/* Media Queries
 */
/*
Note: The best way to structure the use of media queries is to create the queries
near the relevant code. For example, if you wanted to change the styles for buttons
on small devices, paste the mobile query code up in the buttons section and style it
there.
*/


/* Larger than mobile */
@media (min-width: 400px) {}

/* Larger than phablet (also point when grid becomes active) */
@media (min-width: 550px) {}

/* Larger than tablet */
@media (min-width: 750px) {}

/* Larger than desktop */
@media (min-width: 1000px) {}

/* Larger than Desktop HD */
@media (min-width: 1200px) {}

Credits

arduinocc

arduinocc

2 projects • 13 followers

Comments