Full Code of mrflix/LayerStyles for AI

master 0f8679a39ce7 cached
23 files
199.2 KB
51.9k tokens
11 symbols
1 requests
Download .txt
Showing preview only (207K chars total). Download the full file or copy to clipboard to get everything.
Repository: mrflix/LayerStyles
Branch: master
Commit: 0f8679a39ce7
Files: 23
Total size: 199.2 KB

Directory structure:
gitextract_kja_9fna/

├── .project
├── README.markdown
├── builder.html
├── css/
│   ├── index.css
│   └── style.css
├── index.html
└── js/
    ├── application.js
    ├── codebox.js
    ├── color.js
    ├── colorpicker.js
    ├── css.js
    ├── gradienteditor.js
    ├── localization.js
    ├── numbers.js
    ├── style.js
    ├── styleStore.js
    ├── tools.js
    ├── ui.js
    ├── universe.js
    └── zeroclipboard/
        ├── ZeroClipboard.as
        ├── ZeroClipboard.fla
        ├── ZeroClipboard.js
        └── ZeroClipboard.swf

================================================
FILE CONTENTS
================================================

================================================
FILE: .project
================================================
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>LayerStyles</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
	</buildSpec>
	<natures>
	</natures>
</projectDescription>


================================================
FILE: README.markdown
================================================
Layer Styles
============

A HTML5 app for creating CSS3 in a intuitive way.

Highlights
----------

- Colorpicker can pick any color of the element your working on
- Drag and Drop images onto the page to use them as a background or to pick their colors
- Color Swatches, Gradients and Styles are locally stored

================================================
FILE: builder.html
================================================
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Layer Styles</title>
    <link rel="icon" type="image/png" href="favicon.png" />
    <script type="text/javascript" src="js/modernizr-1.7.min.js"></script>
    <link rel="stylesheet" href="css/style.css" type="text/css" />
</head>
<body>
    <div id="main" class="box vertical flex">
        <span id="codeBoxToggle">CSS Code</span>
        <div id="workspace" class="box vertical flex">
            <div id="overlay"></div>
            <canvas id="innerShadow_universe"></canvas>
            <canvas id="parallel_universe"></canvas>
            <div id="background_layer" class="flex"></div>
            <div id="layer"><div id="resize" class="resize"></div></div>
        </div> <!-- /workspace -->
        <div id="codeBox" class="paper">
            <div class="dragger y"><div class="dragBox"></div></div>
            <div class="body">
                <div class="scroll paper">
                    <div id="copyCode">copy</div>
                    <div id="colorSwitch" class="toggle">
                        <div class="slidePanel">
                            <span class="left">rgb</span><span class="button"></span><span class="right">hex</span>
                        </div>
                    </div>
                    <code></code>
                </div>
            </div>
        </div> <!-- /codeBox -->
    </div> <!-- /main -->
    <div id="layerstyle">
		<div id="headerBg"></div>
		<div id="dialog" class="window">
			<div class="head moveable">
				<h2>Layer Style</h2>
			</div>
			<div class="body">
	       		<div class="main">
	                <div id="nav">
	                    <ul>
	                        <li>Styles</li>
	                        <li class="nav-dropShadow active"><input type="checkbox" checked="checked">Drop Shadow</li>
	                        <li class="nav-innerShadow"><input type="checkbox">Inner Shadow</li>
	                        <li class="nav-background"><input type="checkbox" checked="checked">Background</li>
	                        <li class="nav-border"><input type="checkbox" checked="checked">Border</li>
	                        <li class="nav-borderRadius"><input type="checkbox">Border Radius</li>
	                    </ul>
	                </div>
	                <div class="styles">
	                    <div id="holder" class="holder">
	                        <div>
	                            <h3>Styles</h3>
								<div id="stylePresets" class="border_box">
									
								</div>
	                        </div>
	                        <div id="dropShadow">
	                            <h3>Drop Shadow</h3>
	                            <label>Color:</label>
	                            <div>
	                                <div class="color_field"></div>
	                            </div>
	                            <label for="ds-opacity">Opacity:</label>
	                            <div>
	                                <div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="opacity" id="ds-opacity" type="text" data-min="0" data-max="100" data-restrict="digits" value="75">
	                                %
	                            </div>
	                            <label class="angle_holder" for="ds-angle">Angle:</label>
	                            <div>
	                                <div class="pot"><div class="pointer"><div class="dot"></div><div class="line"></div></div></div>
	                                <div class="angle_holder">
	                                    <input class="angle" id="ds-angle" type="text" data-min="0" data-max="360" data-restrict="digits" value="90">
	                                    &deg;
	                                    <input type="checkbox" class="globalLight" id="ds-globalLight"><label for="ds-globalLight">Use Global Light</label>
	                                </div>
	                            </div>
	                            <label for="ds-distance">Distance:</label>
	                            <div>
	                                <div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="distance" id="ds-distance" type="text" data-min="0" data-max="100" value="1">
	                                px
	                            </div>
	                            <label for="ds-blur">Blur:</label>
	                            <div>
	                                <div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="blur" id="ds-blur" type="text" data-min="0" data-max="100" value="5">
	                                px
	                            </div>
	                            <label for="ds-size">Size:</label>
	                            <div>
	                                <div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="size" id="ds-size" type="text" data-min="0" data-max="255" value="0">
	                                px
	                            </div>
	                            <div class="clear"></div>
	                        </div>
							<div id="innerShadow">
	                            <h3>Inner Shadow</h3>
	                            <label>Color:</label>
	                            <div>
	                                <div class="color_field"></div>
	                            </div>
	                            <label for="is-opacity">Opacity:</label>
	                            <div>
	                                <div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="opacity" id="is-opacity" type="text" data-min="0" data-max="100" data-restrict="digits" value="90">
	                                %
	                            </div>
	                            <label class="angle_holder" for="is-angle">Angle:</label>
	                            <div>
	                                <div class="pot"><div class="pointer"><div class="dot"></div><div class="line"></div></div></div>
	                                <div class="angle_holder">
	                                    <input class="angle" id="is-angle" type="text" data-min="0" data-max="360" data-restrict="digits" value="90">
	                                    &deg;
	                                    <input type="checkbox" class="globalLight" id="is-globalLight"><label for="is-globalLight">Use Global Light</label>
	                                </div>
	                            </div>
	                            <label for="is-distance">Distance:</label>
	                            <div>
	                                <div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="distance" id="is-distance" type="text" data-min="0" data-max="100" value="1">
	                                px
	                            </div>
	                            <label for="is-blur">Blur:</label>
	                            <div>
	                                <div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="blur" id="is-blur" type="text" data-min="0" data-max="100" value="0">
	                                px
	                            </div>
	                            <label for="is-size">Size:</label>
	                            <div>
	                                <div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="size" id="is-size" type="text" data-min="0" data-max="255" value="0">
	                                px
	                            </div>
	                            <div class="clear"></div>
	                        </div>
	                        <div id="background">
	                            <h3>Background</h3>
								<label for="bg-opacity">Opacity:</label>
	                            <div>
	                                <div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="opacity" id="bg-opacity" type="text" data-min="0" data-max="100" value="100">
	                                %
	                            </div>
								<label>Gradient</label>
								<div>
									<div class="gradientField"></div>
									<input type="checkbox" class="reverse" id="bg-reverse"><label for="bg-reverse">Reverse</label>
								</div>
								<label>Style</label>
								<div>
									<select id="background_style">
										<option value="linear">Linear</option>
										<option value="reflected">Reflected</option>
										<option value="contain">Radial - contain</option>
										<option value="cover">Radial - cover</option>
									</select>
								</div>
	                            <label class="angle_holder" for="bg-angle">Angle:</label>
	                            <div>
	                                <div class="pot"><div class="pointer"><div class="dot"></div><div class="line"></div></div></div>
	                                <div class="angle_holder">
	                                    <input class="angle" id="bg-angle" type="text" data-min="0" data-max="360" value="90">
	                                    &deg;
	                                    <input type="checkbox" class="globalLight" id="bg-globalLight"><label for="bg-globalLight">Use Global Light</label>
	                                </div>
	                            </div>
		                       	<div class="clear"></div>
	                        </div>
							<div id="border">
	                            <h3>Border</h3>
								<label>Color:</label>
	                            <div>
	                                <div class="color_field"></div>
	                            </div>
	                            <label for="bd-opacity">Opacity:</label>
	                            <div>
	                                <div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="opacity" id="bd-opacity" type="text" data-min="0" data-max="100" value="100">
	                                %
	                            </div>
	                            <label for="bd-size">Size:</label>
	                            <div>
	                                <div class="slider"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
	                                <input class="size" id="bd-size" type="text" data-min="0" data-max="10" value="1">
	                                px
	                            </div>
	                            <label>Style:</label>
	                            <div id="border_styles" class="previews">
									<div id="border_style_solid" title="solid" data-style="solid" class="active"></div>
									<div id="border_style_dashed" title="dashed" data-style="dashed"></div>
									<div id="border_style_dotted" title="dotted" data-style="dotted"></div>
									<div id="border_style_double" title="double" data-style="double"></div>
	                            </div>
	                            <div class="clear"></div>
	                        </div><!-- /border -->
							<div id="borderRadius">
	                            <h3>Border Radius</h3>
								<label for="br-radius">Radius:</label>
								<div>
									<div class="slider" data-easing="true"><div class="bar"></div><div class="arrow"><div class="spike"></div><div class="rear"></div></div></div>
									<input class="radius" id="br-radius" type="text" data-min="0" data-max="200" value="0">
	                                <span class="options" id="border_radius_unit"><span id="border_radius_pixel" data-unit="px" class="active">px</span><span id="border_radius_percent" data-unit="%">%</span></span>
								</div>
								<label>Corners:</label>
								<div id="border_radius_preview">
									<div id="topLeft" class="active"></div>
									<div id="topRight" class="active"></div>
									<div id="bottomRight" class="active"></div>
									<div id="bottomLeft" class="active"></div>
								</div>
								<div class="clear"></div>
							</div>
	                    </div>
	                </div>
	                <div class="clear"></div>
	            </div>
	            <div class="controls">
	                <button id="ok">OK</button>
	                <button id="cancel">Cancel</button>
	                <button id="new_style">New Style...</button>
	            </div>
			</div>
        </div>
		<div id="gradient_editor" class="window">
			<div class="head moveable">
				<h2>Gradient Editor</h2>
			</div>
			<div class="body">
	           <div class="static_right">
	                <div class="main">
	                    <div class="holder">
	                        <h3>Presets</h3>
	                        <div id="gradient_presets_holder" class="border_box">
	                            <div id="gradient_presets">
	                            </div>
	                        </div>
	                    </div>
	                </div>
	                <div class="controls sidebar">
	                    <button id="gradient_ok">OK</button>
	                    <button id="gradient_cancel">Cancel</button>
	                </div>
	                <div class="clear"></div>
	            </div>
	            <div class="static_right">
	                <div class="main">
	                    <div class="static_left">
	                        <span>Name:</span><input id="gradient_name" type="text">
	                    </div>
	                </div>
	                <div class="controls sidebar">
	                    <button id="gradient_new">New</button>
	                </div>
	                <div class="clear"></div>
	            </div>
	            <div class="holder">
	                <h3>Gradient</h3>
	                <div id="gradient_holder">
	                    <div class="frame">
	                        <div id="gradient">
	                        </div>
	                    </div>
	                </div>
	                <div id="stops" class="holder">
	                    <h3>Stops</h3>
	                    <div id="color_stops">
	                        <div class="disabled">
	                            <span>Color:</span><div id="stop_color" class="color_field"></div>
	                        </div>
	                        <div class="disabled">
	                            <label for="stop_location">Location:</label>
									<input type="text" id="stop_location" data-min="0" data-max="100" data-restrict="digits" disabled="disabled">%
	                        </div>
	                        <button id="remove_stop" disabled="disabled">Delete</button>
	                    </div>
	                </div>
	            </div>
	        </div>
		</div>
		<div id="colorpicker" class="window">
			<div class="head moveable">
				<h2>Colorpicker</h2>
			</div>
			<div class="body">
            	<div class="main">
	                <div id="color_field" class="border_box">
	                    <canvas id="field" width="256" height="256"></canvas>
	                    <canvas id="circle" class="colorcircle" width="256" height="256"></canvas>
	                </div> 
	                <div id="color_slider">
	                    <canvas class="border_box" width="19" height="256"></canvas>
	                    <div>
	                        <div class="arrow left"><div class="spike"></div><div class="rear"></div></div>
	                        <div class="arrow right"><div class="spike"></div><div class="rear"></div></div>
	                    </div>
	                </div>
	                <div class="color_preview lightbox">
	                    <label>new</label>
	                    <div id="new_color"></div>
	                    <label>current</label>
	                    <div id="current_color"></div>
	                </div>
	                <div class="color_inputs">
	                    <ul>
	                        <li>
								<input type="radio" id="hsb_h-radio" name="color" value="hsb_h">
								<label for="hsb_h-radio">H:</label>
								<input id="hsb_h" type="text" data-min="0" data-max="360" data-restrict="digits" value="0">
								&deg;
							</li>
	                        <li>
								<input type="radio" id="hsb_s-radio" name="color" value="hsb_s">
								<label for="hsb_s-radio">S:</label>
								<input id="hsb_s" type="text" data-min="0" data-max="100" data-restrict="digits" value="0">
								%
							</li>
	                        <li>
								<input type="radio" id="hsb_b-radio" name="color" value="hsb_b" checked="checked">
								<label for="hsb_b-radio">B:</label>
								<input id="hsb_b" type="text" data-min="0" data-max="100" data-restrict="digits" value="0">
								%
							</li>
	                    </ul>
	                    <ul>
	                        <li>
								<input type="radio" id="rgb_r-radio" name="color" value="rgb_r">
								<label for="rgb_r-radio">R:</label>
								<input id="rgb_r" type="text" data-min="0" data-max="255" data-restrict="digits" value="0">
							</li>
	                        <li>
								<input type="radio" id="rgb_g-radio" name="color" value="rgb_g">
								<label for="rgb_g-radio">G:</label>
								<input id="rgb_g" type="text" data-min="0" data-max="255" data-restrict="digits" value="0">
							</li>
	                        <li>
								<input type="radio" id="rgb_b-radio" name="color" value="rgb_b">
								<label for="rgb_b-radio">B:</label>
								<input id="rgb_b" type="text" data-min="0" data-max="255" data-restrict="digits" value="0">
							</li>
	                    </ul>
	                    <div id="hex_holder">
							<label for="hex">#</label>
							<input type="text" id="hex" size="10" maxlength="6" data-restrict="hexcode">
						</div>
	                </div>
	            </div>
	            <div class="controls">
	                <button id="color_ok">OK</button>
	                <button id="color_cancel">Cancel</button>
	                <button id="color_add">Add to Swatches</button>
	                <div id="swatches_holder">
	                    <div id="swatches" class="paint_bucket">
	                    </div>
	                </div>
	            </div>
	        </div>
		</div><!-- /ColorPicker -->
	</div> <!-- /LayerStyle -->
<script type="text/javascript" src="js/jquery-1.6.min.js"></script>
<script type="text/javascript" src="js/ui.js"></script>
<script type="text/javascript" src="js/zeroclipboard/ZeroClipboard.js"></script>
<script type="text/javascript" src="js/localization.js"></script>
<script type="text/javascript" src="js/color.js"></script>
<script type="text/javascript" src="js/numbers.js"></script>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/css.js"></script>
<script type="text/javascript" src="js/style.js"></script>
<script type="text/javascript" src="js/colorpicker.js"></script>
<script type="text/javascript" src="js/gradienteditor.js"></script>
<script type="text/javascript" src="js/codebox.js"></script>
<script type="text/javascript" src="js/universe.js"></script>
<script type="text/javascript" src="js/styleStore.js"></script>
<script type="text/javascript" src="js/application.js"></script>
</body>
</html>

================================================
FILE: css/index.css
================================================
* { margin: 0; padding: 0; }
html { height: 100%; }
body {
	font: 12px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif;
	background-color: #fcfcfc;
	background-image: -moz-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
	background-image: -webkit-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
	background-image: -o-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
	background-image: -ms-linear-gradient(top, rgba(52,154,227,0.21), rgba(52,154,227,0) 13px);
}
#arche {
	padding-top: 55px;
	width: 556px;
	margin: 0 auto;
	text-transform: uppercase;
	text-shadow: 0 1px white;
	z-index: 200;
	position: relative;
	-moz-transition: 320ms;
	-webkit-transition: 320ms;
	transition: 320ms;
}
h1 span { color: #349ae3; text-transform: none; font-size: 16px; }
h3 { color: #666; font-weight: normal; }
a { text-decoration: none; color: #349ae3; }
em { font-weight: bold; font-style: normal; }
img { border: none; }
#header {
	margin-top: 14px;
	padding-left: 100px;
	position: relative;
	background: url(../img/logo.png) no-repeat 24px 5px;
}
.hero {
	top: 0;
    -webkit-border-top-left-radius: 4px;
    -webkit-border-top-right-radius: 4px;
    -moz-border-radius-topleft: 4px;
    -moz-border-radius-topright: 4px;
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    -moz-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
    -webkit-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
    box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
	position: relative;
}
#ready {
	margin: 17px 0 21px;
	display: none;
}
	#ready .hero {
		-moz-transition: 240ms ease;
		-webkit-transition: 240ms ease;
		transition: 240ms ease;
	}
	#ready:hover .hero { 
		top: 3px;
	    -moz-box-shadow: 0 12px 40px 8px rgba(0,0,0,.20), 0 0 0 1px rgba(0,0,0,.16);
	    -webkit-box-shadow: 0 12px 40px 8px rgba(0,0,0,.20), 0 0 0 1px rgba(0,0,0,.16);
	    box-shadow: 0 12px 40px 8px rgba(0,0,0,.20), 0 0 0 1px rgba(0,0,0,.16);
	}
#not-ready { 
	margin: 17px 0 21px;
	display: none;
	position: relative;
}
	#not-ready .holder { 
		left: 153px;
		top: 76px;
		width: 276px;
		-moz-border-radius: 4px;
		-webkit-border-radius: 4px;
		border-radius: 4px;
	    -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.21), 0 15px 40px 10px rgba(0, 0, 0, 0.34);
	    -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.21), 0 15px 40px 10px rgba(0, 0, 0, 0.34);
	    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.21), 0 15px 40px 10px rgba(0, 0, 0, 0.34);
		position: absolute;
		text-shadow: none;
		text-transform: none;
	}
	#not-ready .upper {
		padding: 13px;
		border: 1px solid #A6281C;
    	background: #F03432;
    	-webkit-border-top-left-radius: 4px;
	    -webkit-border-top-right-radius: 4px;
	    -moz-border-radius-topleft: 4px;
	    -moz-border-radius-topright: 4px;
	    border-top-left-radius: 4px;
	    border-top-right-radius: 4px;
		-moz-box-shadow: 0 0 0 1px #F25146 inset;
		-webkit-box-shadow: 0 0 0 1px #F25146 inset;
		box-shadow: 0 0 0 1px #F25146 inset;
	}
	#not-ready h2 { padding-bottom: 13px; font-size: 14px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.21); border-bottom: 1px solid rgba(0, 0, 0, 0.34); } 
	.features { border-top: 1px solid rgba(255,255,255,.13); padding-top: 8px;  line-height: 2; }
	.features span { 
		display: none;
		padding: 1px 8px;
		color: white;
		white-space: nowrap;
		background: #F25146;
		text-shadow: 0 1px 0 rgba(255,255,255,0.21);
		-moz-border-radius: 7px;
		-webkit-border-radius: 7px;
		border-radius: 7px;
	}
	#not-ready .bottom {
		padding: 13px;
		color: white;
		text-shadow: 0 2px black;
		background: black;
		background: rgba(0,0,0,.8);
		-webkit-border-bottom-left-radius: 4px;
	    -webkit-border-bottom-right-radius: 4px;
	    -moz-border-radius-bottomleft: 4px;
	    -moz-border-radius-bottomright: 4px;
	    border-bottom-left-radius: 4px;
	    border-bottom-right-radius: 4px;
	}
.js.nativejson.flexbox.canvas.rgba.borderradius.boxshadow.cssgradients #ready { display: block; }
.no-js #not-ready,
.no-flexbox #not-ready,
.no-canvas #not-ready,
.no-rgba #not-ready,
.no-borderradius #not-ready,
.no-boxshadow #not-ready,
.no-cssgradients #not-ready { display: block; }
.no-js .feature-js { display: inline; }
.no-nativejson .feature-json { display: inline; }
.no-flexbox .feature-flexbox { display: inline; }
.no-canvas .feature-canvas { display: inline; }
.no-rgba .feature-rgba { display: inline; }
.no-borderradius .feature-borderradius { display: inline; }
.no-boxshadow .feature-boxshadow { display: inline; }
.no-cssgradients .feature-cssgradients { display: inline; }
footer {
	padding: 0 21px;
	color: rgba(0,0,0,.34);
}

================================================
FILE: css/style.css
================================================
* { margin: 0; padding: 0; }
body, html { height: 100%; overflow: hidden; }
body {
    width: 100%;
    font: 12px/14px "Helvetica Neue", Helvetica, Arial, sans-serif;
    background: url(../img/transparent.gif);
}
.box {
    display: -moz-box;
    display: -webkit-box;
    display: box;
}
.box.vertical {
    -moz-box-orient: vertical;
    -webkit-box-orient: vertical;
    box-orient: vertical;
}
.flex {
    -webkit-box-flex: 1;
    -moz-box-flex: 1;
    box-flex: 1;
}
ul { list-style: none; }
#helper { top: 5px; right: 5px; padding: 8px 13px; position: absolute; z-index: 9999; background: rgba(0,0,0,.5); 
    -moz-border-radius: 13px;
    -webkit-border-radius: 13px;
    border-radius: 13px;
}
#layer { 
    top: 50%;
    left: 50%;
    margin: -150px 0 0 -150px;
    width: 300px;
    height: 300px;
    position: absolute;
    z-index: 99;
    -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
    opacity: 1;
}
    #resize { bottom: -15px; right: -15px; width: 30px; height: 30px; position: absolute; }
    #layer.borderRadius:hover #resize { border-right: 1px solid rgba(0, 0, 0, 0.1); border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
#main { position: relative; height: 100%; width: 100%; }
#workspace { position: relative; }
    #parallel_universe { position: absolute; z-index: -1; }
    #innerShadow_universe { position: absolute; z-index: -1; }
    #background_layer {
        background: -moz-linear-gradient(top, #e2e2e2, #ababab);
        background: -webkit-gradient(linear, left top, left bottom, from(#e2e2e2), to(#ababab));
        background: -o-linear-gradient(top, #e2e2e2, #ababab);
        display: block;
    }
    #codeBoxToggle {
        bottom: 0; 
        left: 0; 
        padding: 5px 13px 4px; 
        line-height: 18px; 
        color: rgba(0, 0, 0, 0.75);
        background: rgba(0,0,0,.08); 
        border-radius: 2px 2px 0 0; 
        position: absolute; 
        cursor: pointer;
        display: inline-block;
        z-index: 101;
        -moz-transition: background-color 240ms ease;
        -webkit-transition: background-color 240ms ease;
        transition: background-color 240ms ease;
    }
        #codeBoxToggle:hover {
            background: rgba(0,0,0,.13);
        }
#overlay { width: 100%; height: 100%; position: absolute; top: 0; background-color: transparent;
    -moz-transition: background-color 240ms ease;
    -webkit-transition: background-color 240ms ease;
    transition: background-color 240ms ease;
}
    .dragging #overlay { z-index: 101; background-color: rgba(0,0,0,.21); }
    .pick #overlay { z-index: 100; cursor: url(../img/eyedropper.gif) 0 15, auto; }
#infoButton { 
    position: absolute; 
    left: 0; 
    padding: 13px; 
    color: black; 
    text-decoration: none; 
    text-transform: uppercase; 
    opacity: 0.21; 
    z-index: 99; 
    display: block;
    -moz-transition: 240ms;
    -webkit-transition: 240ms;
    transition: 240ms;
}
    #infoButton:hover { opacity: 0.55; }
#codeBox {
    height: 0;
    position: relative;
    overflow: hidden;
    background-position: 0 2px;
    -webkit-transition: 300ms ease-out;
    -moz-transition: 300ms ease-out;
    transition: 300ms ease-out;
}
    #codeBox.resizing {
        -webkit-transition: none;
        -moz-transition: none;
        transition: none;
    }
    #codeBox .dragger.y {
        top: 0;
        height: 21px;
        background: -moz-linear-gradient(#9E9E9E, #999);
        background: -webkit-gradient(linear, center top, center bottom, from(#9E9E9E), to(#999));
        background: -webkit-linear-gradient(#9E9E9E, #99);
        border-bottom: 1px solid #666;
        -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
        display: block;
        position: relative;
        z-index: 1;
    }
    #copyCode { 
        top: 21px;
        left: 1px;
        width: 78px;
        height: 15px;
        color: #444;
        font-family: "Consolas", "Monaco", monospace;
        line-height: 15px; 
        font-size: 10px;
        text-align: center;
        border: 1px solid #edc59c;
        border-radius: 4px;
        background-image: -moz-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
        background-image: -webkit-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
        background-size: 4px 4px;
        position: absolute;
        cursor: pointer;
    }
        #copyCode:active { color: black; }
        #copyCode embed { left: 0; position: absolute; outline: none; }
        #colorSwitch {
            top: 41px;
            left: 1px;
            width: 78px;
            height: 15px;
            color: #444;
            border: 1px solid #edc59c;
            border-radius: 4px;
            overflow: hidden;
            position: absolute;
        }
            .toggle { cursor: pointer; }
            #colorSwitch .slidePanel {
                width: 150%;
                height: 100%;
                left: -50%;
                margin: 1px;
                position: absolute;
                -moz-transition: 320ms ease;
                -webkit-transition: 320ms ease;
            }
            #colorSwitch.moving .slidePanel {
                -moz-transition: none;
                -webkit-transition: none;
            }
            #colorSwitch .button {
                top: 0;
                left: 33.33%;
                width: 35px;
                height: 11px;
                position: absolute;
                border: 1px solid #edc59c;
                border-radius: 3px;
                background-image: -moz-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
                background-image: -webkit-repeating-linear-gradient(-45deg, transparent, transparent 2px, #edc59c 2px, #edc59c 3px);
                background-size: 4px 4px;
            }
            #colorSwitch .left,
            #colorSwitch .right { right: 0; width: 33.33%; height: 100%; line-height: 13px; font-size: 10px; text-align: center; position: absolute; }
            #colorSwitch .left { left: 0; right: auto; }
    #codeBox .body {
        color: #444;
        height: 100%;
        border-top: 1px solid rgba(0,0,0,.13);
        overflow: auto;
        position: relative;
    }
    .paper {
        background-color: #ffe4b5;
        /* lines */
        background-image:
            -moz-linear-gradient(left, transparent 82px, rgba(128,0,0,.08) 82px, rgba(128,0,0,.08) 82px, transparent 83px),
            -moz-repeating-linear-gradient(transparent, transparent 19px, rgba(128, 0, 0, 0.08) 19px, rgba(128, 0, 0, 0.08) 20px);
        background-image: 
            -webkit-linear-gradient(left, transparent 82px, rgba(128,0,0,.08) 82px, rgba(128,0,0,.08) 82px, transparent 83px),
            -webkit-repeating-linear-gradient(transparent, transparent 19px, rgba(128, 0, 0, 0.08) 19px, rgba(128, 0, 0, 0.08) 20px);
    }
        #codeBox .scroll {
            padding: 20px 0 0 108px;
        }
        #codeBox code { 
            padding-bottom: 20px;
            border: none;
            font-family: "Consolas", monospace;
            line-height: 20px;
            display: block;
        }
.dragger { position: absolute; z-index: 100; }
    .dragger.x { width: 10px; left: -5px; top: 0; height: 100%; cursor: w-resize; }
    .dragger.y { width: 100%; top: -5px; left: 0; height: 10px; cursor: n-resize; }
    .dragBox { bottom: 0; left: 5px; height: 20px; width: 20px; border: 1px solid rgba(0,0,0,.13); background: url(../img/dragger.png) no-repeat 6px 6px; position: absolute; }
    .dragger.y .dragBox {
        bottom: -1px;
        border: none;
        -moz-transform: rotate(90deg);
        -webkit-transform: rotate(90deg);
        transform: rotate(90deg);
        -moz-transform-origin: center center;
        -webkit-transform-origin: center center;
        transform-origin: center center;
    }
.moveable { cursor: move; }
#layerstyle {
    top: 11px;
    left: 51px;
    width: 556px;
    height: 393px;
    color: black;
    background: #EDEDED;
    -webkit-border-top-left-radius: 4px;
    -webkit-border-top-right-radius: 4px;
    -moz-border-radius-topleft: 4px;
    -moz-border-radius-topright: 4px;
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    -moz-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
    -webkit-box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
    box-shadow: 0 15px 40px 10px rgba(0,0,0,.25), 0 0 0 1px rgba(0,0,0,.16);
    position: absolute;
    z-index: 100;
    display: block;
    -webkit-user-select: none;
    -moz-user-select: none;
    -o-user-select: none;
    user-select: none;
}
#headerBg {
    top: 0;
    left: 0;
    width: 100%;
    height: 24px;
    border-top: 1px solid #E2E2E2;
    border-bottom: 1px solid #515151;
    background: -moz-linear-gradient(#CFCFCF, #A8A8A8);
    background: -webkit-gradient(linear, center top, center bottom, from(#CFCFCF), to(#A8A8A8));
    -webkit-border-top-left-radius: 4px;
    -webkit-border-top-right-radius: 4px;
    -moz-border-radius-topleft: 4px;
    -moz-border-radius-topright: 4px;
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    position: absolute;
}
.window { top: 0; width: 100%; position: absolute; }
    .window .head {
        padding: 6px;
        position: relative;
    }
    .window .head h2 {
        font-size: 13px;
        font-weight: normal;
        text-align: center;
        color: black;
        text-shadow: 0 1px 0 #cfcfcf;
    }
        .window .head > button {
            position: absolute;
            left: 3px;
            top: 3px;
            width: auto;
            padding: 1px 9px;
            text-shadow: 0 1px 0 white;
            background: -moz-linear-gradient(top, #ebebeb, #d7d7d7);
            background: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#d7d7d7));
            border: 1px solid #999999;
            -moz-border-radius: 3px;
            -webkit-border-radius: 3px;
            border-radius: 3px;
            -moz-box-shadow: 0 1px 0 rgba(255,255,255,0.5), 0 1px 0 white inset;
            -webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.5), 0 1px 0 white inset;
            box-shadow: 0 1px 0 rgba(255,255,255,0.5), 0 1px 0 white inset;
            cursor: pointer;
        }
.window .body { padding: 15px 10px; position: relative; }
.inactive {
    color: gray;
}
#dialog { visibility: hidden; }
.main { width: 82%; float: left; font-size: 10px; }
    .main > .styles { width: 72%; float: left; }
        #holder { margin: 0 16px; }
        #holder > div { width: 100%; visibility: hidden; position: absolute; top: 0; padding: 12px 0; border: 1px solid #909090; }
        #holder > div.active { visibility: visible; }
        .holder { position: relative; }
        .holder h3 { left: 9px; top: -8px; padding: 0 3px 0 2px; font-size: 10px; position: absolute; background: #ededed; }
        .styles > div > div > label { width: 22%; padding-top: 1px; margin-right: 2%; text-align: right; float: left; clear: right; }
        .styles label + div { width: 75%; float: right; }
        .styles label, .styles label + div { margin-top: 2px; }
        .styles .color_field { height: 13px; width: 33px; border: 1px solid #909090; background: white; cursor: pointer; }
        .styles input[type=checkbox] { margin: 0 6px; vertical-align: middle; width: auto; }
        .styles input[type=checkbox] + label { vertical-align: middle; }
        .styles .angle_holder { top: 13px; position: relative; display: inline-block; vertical-align: top; }
        input[type=text] { 
            width: 40px;
            padding: 1px;
            font-size: 10px;
            border: 1px solid #909090;
            border-bottom-width: 0;
            -moz-box-shadow: inset 0 0 0 1px #bababa, 0 1px 0 rgba(0,0,0,.04);
            -webkit-box-shadow: inset 0 0 0 1px #bababa, 0 1px 0 rgba(0,0,0,.04);
            box-shadow: inset 0 0 0 1px #bababa, 0 1px 0 rgba(0,0,0,.04);
        }
        .styles .slider { width: 100px; margin: 0 5px 0 3px; }
    #stylePresets { margin: -2px 9px 0; height: 230px; overflow: auto; }
    #stylePresets .swatch { width: 31px; height: 31px; border-right: 1px solid #909090; border-bottom: 1px solid #909090; float: left;
            -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
        }
    #stylePresets .swatch.active { border: 2px solid black; }
            #stylePresets .swatch > div { width: 17px; height: 17px; margin: 7px 0 0 7px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
            #stylePresets .swatch.active > div { margin: 5px 0 0 5px; }
    #holder #background { }
        .gradientField {
            margin: 2px 0;
            width: 109px;
            height: 15px;
            vertical-align: middle;
            border: 1px solid black;
            display: inline-block;
            cursor: pointer;
        }
        .previews > div { margin: 2px 2px 2px 0; width: 24px; height: 24px; border: 1px solid black; display: inline-block; opacity: 0.3; }
        .previews > .active { opacity: 1; background-color: #A7D4F6; }
        .inactive .previews > .active { background-color: rgba(0,0,0,.08); border-color: gray; }
        #border .previews > div { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
        #border_style_dotted { border-style: dotted; }    
        #border_style_dashed { border-style: dashed; }
        #border_style_double { border: 3px double black; }
        #border_radius_preview {
            width: 104px;
            height: 104px;
            margin: 4px 3px;
            float: left;
            border-color: rgba(0,0,0,.25);
            position: relative;
            -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
            overflow: hidden;
        }
            #border_radius_preview > div {
                width: 50%;
                height: 50%;
                float: left;
                -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
            }
            #border_radius_preview #bottomRight { float: right; border-bottom: 1px solid rgba(0,0,0,.25); border-right: 1px solid rgba(0,0,0,.25); }
            #border_radius_preview #topLeft { border-top: 1px solid rgba(0,0,0,.25); border-left: 1px solid rgba(0,0,0,.25); border-bottom: 1px dotted rgba(0,0,0,.25); border-right: 1px dotted rgba(0,0,0,.25); }
            #border_radius_preview #topRight { border-top: 1px solid rgba(0,0,0,.25); border-right: 1px solid rgba(0,0,0,.25); border-bottom: 1px dotted rgba(0,0,0,.25); }
            #border_radius_preview #bottomLeft { border-bottom: 1px solid rgba(0,0,0,.25); border-left: 1px solid rgba(0,0,0,.25); border-right: 1px dotted rgba(0,0,0,.25); }
            #border_radius_preview > div.active { background: #A7D4F6; }
            .inactive #border_radius_preview > div.active { background: rgba(0,0,0,.08); }
            .options { 
                -moz-box-shadow: 0 2px white;
                -webkit-box-shadow: 0 2px white;
                box-shadow: 0 2px white;
                cursor: pointer;
            }
                .options span:first-child { border-right: none; }
                .options span:last-child { border-left: none; }
                .options span {
                    padding: 0 4px;
                    border: 1px solid rgba(0,0,0,.5);
                    background: -moz-linear-gradient(#C1C1C1, #D4D4D4);
                    background: -webkit-linear-gradient(#C1C1C1, #D4D4D4);
                    background: linear-gradient(#C1C1C1, #D4D4D4);
                    -moz-box-shadow: 0 1px white inset;
                    -webkit-box-shadow: 0 1px white inset;
                    box-shadow: 0 1px white inset;
                }
                .options span.active {
                    border: 1px solid rgba(0,0,0,.5);
                    background: -moz-linear-gradient(#999999, #BBBBBB);
                    background: -webkit-linear-gradient(#999999, #BBBBBB);
                    background: linear-gradient(#999999, #BBBBBB);
                    -moz-box-shadow: none;
                    -webkit-box-shadow: none;
                    box-shadow: none;
                }
                .inactive .options span { opacity: 0.5; }
    #nav { width: 28%; height: 100%; float: left; cursor: default; }
        #nav ul {
            border: 1px solid #909090;
            -moz-box-shadow: inset 1px 1px 0 rgba(0,0,0,.3);
            -webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.3);
            box-shadow: inset 1px 1px 0 rgba(0,0,0,.3);
        }
        #nav li { margin: 0 0 0 1px; padding: 4px 6px; border-bottom: 1px solid white; cursor: pointer; }
        #nav li input { margin-right: 5px; vertical-align: bottom; cursor: pointer; }
        #nav li.active { background: #b5d5ff; font-weight: bold; }
        #nav li:first-child { padding-bottom: 6px; 
            -moz-box-shadow: inset 0 -1px 0 black;
            -webkit-box-shadow: inset 0 -1px 0 black;
            box-shadow: inset 0 -1px 0 black;
        }
        #nav li:first-child + li { padding-top: 5px; border-top: 1px solid #909090;
            -moz-box-shadow: inset 0 1px 0 black;
            -webkit-box-shadow: inset 0 1px 0 black;
            box-shadow: inset 0 1px 0 black;
        }
    .controls { width: 18%; float: right; }
        .controls > div { text-align: center; }
        .controls > div input { margin-right: 2px; }
#colorpicker { visibility: hidden; }
    #colorpicker .body { padding-top: 9px; }
    #colorpicker .main { width: 75%; height: 294px; margin-top: 21px; position: relative; }
    #color_field { height: 256px; width: 256px; position: absolute; }
        #field, #circle { position: absolute; }
        #circle { z-index: 999; }
    #color_slider { left: 259px; top: 2px; width: 44px; height: 256px; position: absolute; }
    #color_slider canvas {
        top: -2px;
        left: 11px;
        height: 256px;
        width: 19px;
        position: absolute;
    }
    .border_box { border-color: #909090 #909090 #e4e4e4 #909090; border-width: 2px 1px 1px 2px; border-style: solid; }
    .lightbox { border: 1px solid #909090; border-bottom-color: #e4e4e4; }
    #color_slider > div { left: 11px; top: 256px; width: 21px; position: absolute; }
        #color_slider > div > .arrow.right { right: -3px;  }
        #color_slider > div > .arrow.left { left: -9px; }
        #color_slider .arrow { top: -4px; position: absolute; }
        #color_slider .arrow div { border: 1px solid #747474; background: white; position: absolute; }
        #color_slider .arrow .rear { width: 4px; height: 6px;
            -moz-border-radius: 2px;
            -webkit-border-radius: 2px;
            border-radius: 2px;
        }
        #color_slider .arrow .spike { top: 1px; width: 4px; height: 4px; 
            -moz-transform: rotate(45deg);
            -webkit-transform: rotate(45deg);
            transform: rotate(45deg);
        }
        #color_slider .arrow.left .rear { border-right-width: 0; }
        #color_slider .arrow.left .spike { left: 1px; }
        #color_slider .arrow.right .rear { border-left-width: 0; left: 2px; }
    .color_preview { top: 4px; left: 304px; width: 60px; position: absolute; }
        .color_preview > div { height: 34px; background: black; border: 1px solid black; }
        #new_color { border-bottom: none; }
        #current_color { background: white; border-top: none; }
        .color_preview > label { bottom: -14px; width: 100%; text-align: center; position: absolute; }
        .color_preview > label:first-child { top: -20px; height: 20px; }
    .color_inputs { top: 111px; left: 305px; width: 100px; position: absolute; font-size: 13px; }
        .color_inputs ul { padding-bottom: 4px; }
        .color_inputs li { margin: 2px 0 3px; display: inline-block; }
        .color_inputs input[type=radio] { margin-right: 4px; }
        .color_inputs span { width: 20px; display: inline-block; }
        .color_inputs ul input[type=text] { width: 33px; height: 18px; margin-right: 2px; font-size: 13px; }
        .color_inputs #hex_holder { margin: 2px 3px; }
            .color_inputs #hex { height: 18px; margin-left: 4px; font-size: 13px; width: 68px; }
#colorpicker .controls { width: 25%; }
    #swatches_holder { margin: 5px; background: #d6d6d6; border-top: 1px solid #909090; overflow: hidden; }
    #swatches { padding-bottom: 12px; overflow: hidden; }
    #swatches span { 
        width: 10px; 
        height: 11px;
        border-right: 1px solid black;
        border-bottom: 1px solid black;
        float: left;
        cursor: url(../img/eyedropper.gif) 0 15, auto;
    }
    .alt .swatch { cursor: url(../img/scissor.gif) 6 6, auto; }
#gradient_editor { visibility: hidden; }
    /* overwritings */
    #gradient_editor .holder { padding: 13px 9px 9px; border: 1px solid #909090; }
    #gradient_editor .holder h3 { left: 16px; font-size: 13px; font-weight: normal; }
    #gradient_editor input[type=text] { padding: 2px; font-size: 13px; }
    #gradient_editor .static_right { margin-right: 105px; }
    #gradient_editor .main { width: 100%; font-size: 13px; }
        #gradient_editor .static_left { margin: 16px 4px 22px 56px; }
            #gradient_editor .static_left > span { margin-left: -55px; line-height: 22px; float: left; } 
            #gradient_name { width: 100%; }
            #gradient_new { margin-top: 17px; }
        #gradient_presets_holder { height: 115px; overflow: auto; }
            #gradient_presets div { width: 31px; height: 31px; border-right: 1px solid #909090; border-bottom: 1px solid #909090; float: left; }
    #gradient_editor .sidebar { width: 89px; margin-right: -105px; }
    #gradient_holder { padding: 12px 6px 34px; }
        .frame { border: 1px solid #909090; }
        #gradient { height: 25px; position: relative; }
        #gradient div { cursor: default; }
        #gradient .picker { position: absolute; }
        #gradient .picker.top { top: -19px; }
        #gradient .picker.bottom { top: 33px; }
        #gradient .picker > div { position: absolute; }
        #gradient .picker .arrow { left: -3px; top: 6px; height: 6px; width: 6px; border: 1px solid black;
            -moz-box-shadow: -1px 0 #909090 inset;
            -webkit-box-shadow: -1px 0 #909090 inset;
            box-shadow: -1px 0 #909090 inset;
            -moz-transform: rotate(45deg);
            -webkit-transform: rotate(45deg);
            transform: rotate(45deg);
            -moz-transform-origin: 2px 3px;
            -webkit-transform-origin: 2px 3px;
            transform-origin: 2px 3px;
        }
        #gradient .picker.bottom .arrow { top: -5px; 
            -moz-box-shadow: 0 1px #909090 inset;
            -webkit-box-shadow: 0 1px #909090 inset;
            box-shadow: 0 1px #909090 inset;
        }
        #gradient .picker.selected .arrow { background: black;
            -moz-box-shadow: none;
            -webkit-box-shadow: none;
            box-shadow: none;
        }
        #gradient .picker .box { left: -6px; height: 10px; width: 9px; background: #E4E4E4; border: 1px solid black; border-bottom: none;
            -moz-box-shadow: -1px 0 #909090 inset;
            -webkit-box-shadow: -1px 0 #909090 inset;
            box-shadow: -1px 0 #909090 inset;
        }
        #gradient .picker.bottom .box { height: 9px; padding-top: 1px; border-bottom: 1px solid black; border-top: none;
            -moz-box-shadow: 0 1px #909090 inset;
            -webkit-box-shadow: 0 1px #909090 inset;
            box-shadow: 0 1px #909090 inset;
        }
        #gradient .picker .color_field { height: 7px; width: 7px; border-width: 1px; border-style: solid; border-color: #E4E4E4 #909090 #909090 #E4E4E4; background: black; }
        #gradient .middlepoint { top: -9px; position: absolute; display: none; cursor: default; }
        #gradient .middlepoint.visible { display: block; }
        #gradient .middlepoint.bottom { top: 27px; }
        #gradient .middlepoint span { margin-left: -4px; width: 7px; height: 7px; background: url(../img/middlepoint.gif); display: block; }
        #gradient .middlepoint.selected span { background-position: 0 -7px; }
    #gradient_editor #stops { padding: 9px 9px 2px; font-size: 13px; }
    #stops .disabled { color: #7f7f7f; }
    #stops button { width: 89px; display: inline; }
    #stops > div > div { width: 140px; display: inline-block; }
        #stops span { width: 54px; margin-right: 4px; text-align: right; display: inline-block; }
        #stops input[type="text"] { margin-right: 2px; }
        #stop_color { width: 45px; height: 18px; margin-bottom: -5px; border: 1px solid #909090; display: inline-block; cursor: pointer; }
        .disabled #stop_color { cursor: auto; }
.eyedropper { cursor: url(../img/eyedropper.gif) 0 15, auto; }
.colorcircle { cursor: url(../img/colorcircle.gif) 8 8, auto; }
.paint_bucket { cursor: url(../img/paint_bucket.gif) 13 14, auto; }
.resize { cursor: url(../img/resize.gif) 8 8, se-resize; }
.pot {
    margin: 0 3px;
    width: 40px;
    height: 40px;
    background: -moz-linear-gradient(top, #dbdbdb, #e1e1de 20%, #f8f8f3);
    background: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), color-stop(50%, #e1e1de), to(#f8f8f3));
    border: 2px solid #727272;
    -moz-box-shadow: inset 0 2px 3px white, inset 0 -1px 2px #fffef8;
    -webkit-box-shadow: inset 0 2px 3px white, inset 0 -1px 2px #fffef8;
    box-shadow: inset 0 2px 3px white, inset 0 -1px 2px #fffef8;
    -moz-border-radius: 40px;
    -webkit-border-radius: 40px;
    border-radius: 40px;
    position: relative;
    display: inline-block;
}
    .pointer {
        top: 50%;
        left: 50%;
        margin: -1.5px 0 0 -1.5px;
        width: 50%;
        -moz-transform: rotate(-90deg);
        -webkit-transform: rotate(-90deg);
        transform: rotate(-90deg);
        -moz-transform-origin: 1.5px 1.5px;
        -webkit-transform-origin: 1.5px 1.5px;
        transform-origin: 1.5px 1.5px;
        position: absolute;
    }
        .dot {
            height: 3px;
            width: 3px;
            background: #909090;
            position: absolute;
        }
        .line {
            margin-top: 1px;
            height: 1px;
            background: #909090;
        }
.slider {
    padding: 4px 0 2px 1px;
    position: relative;
    display: inline-block;
}
    .slider .bar {
        margin-top: 3px;
        height: 3px;
        background: -moz-linear-gradient(top, #adadad, #b2b2b2);
        background: -webkit-gradient(linear, left top, left bottom, from(#adadad), to(#b2b2b2));
        -moz-box-shadow: inset 0 1px 0 #929292;
        -webkit-box-shadow: inset 0 1px 0 #929292;
        box-shadow: inset 0 1px 0 #929292;
        border: 1px solid #686868;
        border-bottom-color: #aaa;
        -moz-border-radius: 3px;
        -webkit-border-radius: 3px;
        border-radius: 3px;
    }
    .inactive .slider .bar {
        background: -moz-linear-gradient(top, #bfbfbf, #d0d0d0);
        background: -webkit-linear-gradient(top, #bfbfbf, #d0d0d0);
        background: linear-gradient(top, #bfbfbf, #d0d0d0);
        -moz-box-shadow: inset 0 1px 0 #bfbfbf;
        -webkit-box-shadow: inset 0 1px 0 #bfbfbf;
        box-shadow: inset 0 1px 0 #bfbfbf;
        border-color: #aaa #aaa #cacaca;
    }
    .slider .arrow {
        left: 0;
        top: 3px;
        position: absolute;
    }
        .slider .rear {
            left: -3px;
            top: 4px;
            height: 5px;
            width: 7px;
            background: -moz-linear-gradient(top, #a7d4f6, #73bbf2, #b0e9fd);
            background: -webkit-gradient(linear, left top, left bottom, from(#a7d4f6), color-stop(50%,#73bbf2), to(#b0e9fd));
            border: 1px solid #787a96;
            border-top-width: 0;
            -moz-border-radius: 0 0 2px 2px;
            -webkit-border-radius: 2px;
            border-radius: 2px;
            -moz-box-shadow: 0 1px 0 rgba(0,0,0,.05);
            position: relative;
        }
        .slider .spike {
            left: -4px;
            height: 4px;
            width: 4px;
            background: -moz-linear-gradient(-45deg, #e4f1fc, #88c4f2);
            background: -webkit-gradient(linear, left top, right bottom, from(#e4f1fc), to(#88c4f2));
            border: 1px solid #8d84ae;
            -moz-transform-origin: 3px 7px;
            -webkit-transform-origin: 3px 7px;
            transform-origin: 3px 7px;
            -moz-transform: rotate(45deg);
            -webkit-transform: rotate(45deg);
            transform: rotate(45deg);
            position: absolute;
        }
        .inactive .slider .rear {
            background: -moz-linear-gradient(#ECEDED, #DBDBDB, #EBEBEB);
            background: -webkit-linear-gradient(#ECEDED, #DBDBDB, #EBEBEB);
            background: linear-gradient(#ECEDED, #DBDBDB, #EBEBEB);
            border-color: #7F7D7D;
        }
        .inactive .slider .spike {
            background: -moz-linear-gradient(-45deg, #E1E1E1, white);
            background: -webkit-linear-gradient(-45deg, #E1E1E1, white);
            background: linear-gradient(-45deg, #E1E1E1, white);
            border-color: #9E9E9E;
        }
button {
    width: 100%;
    margin: 8px 0;
    padding: 1px 0;
    background: -moz-linear-gradient(top, #fcfcfc, #f4f4f4 40%, #e6e6e5 42%, #f5f5f5 75%, #fff);
    background: -webkit-gradient(linear, left top, left bottom, from(#fcfcfc), color-stop(40%,#f4f4f4), color-stop(42%,#e6e6e5), color-stop(75%,#f5f5f5), to(#fff));
    font-size: 12px;
    border: 1px solid #7d7d7d;
    -moz-border-radius: 17px;
    -webkit-border-radius: 17px;
    border-radius: 17px;
    -moz-box-shadow: 0 1px 0 rgba(0,0,0,.2);
    -webkit-box-shadow: 0 1px 0 rgba(0,0,0,.2);
    box-shadow: 0 1px 0 rgba(0,0,0,.2);
    display: block;
    outline: none;
    cursor: pointer;
}
button::-moz-focus-inner { border: 0; } /* firefox outline removed */
button:first-child { margin-top: 0; }
label[for] { cursor: pointer; }
#puff { width: 22px; height: 22px; background: url(../img/puff.png); position: absolute; display: block; z-index: 110; }
.clear { clear: both; }

================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Layer Styles</title>
	<link rel="icon" type="image/png" href="favicon.png" />
	<script type="text/javascript" src="js/modernizr-1.7.min.js"></script>
	<link rel="stylesheet" href="css/index.css" type="text/css" />
</head>
<body>
<div id="arche">
	<header>
		<div id="logo">LS</div>
		<div id="headline">
			<h1>LayerStyles</h1>
			<h3 class="tagline">just like your favorite graphics editor</h3>
			<h3 class="tagline">but in your browser. And it creates CSS.</h3>
		</div>
	</header>
	
	<section id="ready">
		<a href="builder.html"><img class="hero" src="img/hero.png" width="556" height="393" alt="Layerstyles main interface" /></a>
	</section>
	<section id="not-ready">
		<img class="hero" src="img/hero.png" width="556" height="393" alt="Layerstyles main interface" />
		<div class="holder">
			<div class="upper">
				<h2>Unfortunately your browser doesn't support the following requirements:</h2>
				<div class="features">
					<span class="feature-js">Javascript enabled</span>
					<span class="feature-json">Native JSON</span>
					<span class="feature-cssgradients">CSS Background Gradients</span>
					<span class="feature-borderradius">Border Radius</span>
					<span class="feature-canvas">HTML5 Canvas</span>
					<span class="feature-flexbox">HTML5 Flexbox</span>
					<span class="feature-rgba">RGB Alpha-Channel</span>
					<span class="feature-boxshadow">Box Shadows</span>
				</div>
			</div>
			<div class="bottom">
				<p>
					Please update your browser.
				</p>
			</div>
		</div>
	</section>
	<footer>
		<p>LayerStyles is <em>Open Source</em> and on <a href="https://github.com/mrflix/LayerStyles">Github</a></p>
		<p>made by <a href="http://www.felixniklas.de">Felix Niklas</a> &copy 2011 <em>follow me on mastodon:</em> <a href="https://mastodon.social/@mrflix">@mrflix</a>.</p>
	</footer>
</div><!-- /arche -->
<script type="text/javascript" src="js/jquery-1.6.min.js"></script>
<script type="text/javascript" src="js/ui.js"></script>
<script type="text/javascript" src="js/zeroclipboard/ZeroClipboard.js"></script>
<script type="text/javascript" src="js/localization.js"></script>
<script type="text/javascript" src="js/color.js"></script>
<script type="text/javascript" src="js/numbers.js"></script>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/css.js"></script>
<script type="text/javascript" src="js/style.js"></script>
<script type="text/javascript" src="js/colorpicker.js"></script>
<script type="text/javascript" src="js/gradienteditor.js"></script>
<script type="text/javascript" src="js/codebox.js"></script>
<script type="text/javascript" src="js/universe.js"></script>
<script type="text/javascript" src="js/styleStore.js"></script>
</body>
</html>

================================================
FILE: js/application.js
================================================
/*!
 *     _                                       ________                  _
 *    | |                                     |  ______|                | |
 *    | |                                     | |          _            | |
 *    | |       _____ ___  ___ _____  _____   | |______  _| |_ ___  ___ | |     _____  _____
 *    | |      |  _  |\  \/  /|  _  ||   __|  |______  ||_   _|\  \/  / | |    |  _  ||  ___|
 *    | |_____ | |_| | /   /  |  ___||  |      ______| |  | |   /   /   | |___ |  ___||___  |
 *    |_______||___,\|/___/   |_____||__|     |________|  |_|  /___/    |_____||_____||_____|
 *    
 *       http://www.layerstyles.org
 *    
 *    Copyright (c) 2011 Felix Niklas
 *    This script is freely distributable under the terms of the MIT license.
 */

localStorage['version'] = "0.1";

var movePos = { x: 0, y: 0 }, bytes, reader;
var $body = $('body');
var $overlay = $('#overlay');
var $workspace = $('#workspace');
var dimensions = { width: $workspace.width(), height: $workspace.height() };
var $dialog = $('#dialog');
var $layerstyle = $('#layerstyle');
var $navElements = $('#nav ul li');
var $holderElements = $('#holder > div');
var $pots = $('.pot');
var potDimensions = {'height': 40, 'width': 40};
var $sliders = $('.slider'), shouldEase = false;
var $numericalInputs = $('input[type=text]', $dialog);
var $buttons = { 'ok': $('#ok'), 'cancel': $('#cancel'), 'newStyle': $('#new_style')  };
var $layer = $('#layer');
var resizeArea = $('#resize');
var $backgroundLayer = $('#background_layer');//.css("height", dimensions.height);
var $parallelUniverse = $('#parallel_universe').attr({height: dimensions.height, width: dimensions.width});
var pu = $parallelUniverse.get(0).getContext('2d');
var $innerShadowUniverse = $('#innerShadow_universe').attr({height: dimensions.height, width: dimensions.width});
var iu = $innerShadowUniverse.get(0).getContext('2d');
var moveAreas = $('.moveable'), movingWindow;
var offset = { x: 0, y: 0 };
var $colorfields = $('.color_field');
var currentStyle, lang;
var background = {
        background: [{
                stops: [[255,255,255,1], [255,255,255,0]],
                style: 'radial',
                position: 'center',
                angle: 90
            },
            {
                stops: [[226, 226, 226], [171, 171, 171]],
                style: 'linear',
                angle: 90
            }
        ]
};

// array compare function - thanks to David and Anentropic
// http://stackoverflow.com/questions/1773069/using-jquery-to-compare-two-arrays
// (sort removed and extended to deep comparison)
// syntax: $.compare(a, b);

jQuery.extend({
    compare: function (b, a) {
        if (a.length != b.length) { return false; }
        for (var i = 0, l = a.length; i < l; i++) {
            if (a[i] !== b[i]) { 
                if(typeof a[i] === 'object'){
                    return jQuery.compare(a[i],b[i]);
                } else {
                    return false;
                }
            }
        }
        return true;
    }
});

// Object.create implementation for older browsers
// by Ben Newman

if(Object.create === undefined){
    Object.create = function( proto, props ) {
      var ctor = function( ps ) {
        if ( ps )
          Object.defineProperties( this, ps );
      };
      ctor.prototype = proto;
      return new ctor( props );
    };
}

/*

things to store:
    - styles, gradients and colors
    - layerstyles version
    - currentStyle

*/
var defaults = {
        height: 300,
        width: 300,
        ratio: 1,
        globalAngle: 90,
        dropShadow: {
            isActive: true,
            color: [0,0,0],
            opacity: 75,
            angle: 90,
            hasGlobalLight: false,
            distance: 1,
            blur: 5,
            size: 0
        },
        innerShadow: {
            isActive: false,
            color: [255,255,255],
            opacity: 100,
            angle: 90,
            hasGlobalLight: false,
            distance: 1,
            blur: 0,
            size: 0,
            isInset: true
        },
        background: {
            isActive: true,
            opacity: 100,
            stops: [[252, 252, 252], 23, [[242, 242, 242], 12], 89, [191, 191, 191]],
            isReverse: false,
            style: 'linear',
            angle: 90,
            hasGlobalLight: false
        },
        border: {
            isActive: true,
            color: [0,0,0],
            opacity: 100,
            size: 1,
            style: 'solid'
        },
        borderRadius: {
            isActive: false,
            radii: [[0, "px"],[0, "px"],[0, "px"],[0, "px"]],
            isSelected: [true,true,true,true],
            hasPercentage: [false, false, false, false]
        }
};

var nav = {
    $el: $layerstyle,
    $pages: null,
    width: null,
    page: null,
    prev: null,
    speed: 0,
    goTo: function(pageNr){
        // parse Int
        pageNr = pageNr*1;
        localStorage["pageNr"] = pageNr;
        if(pageNr === -1){
            pageNr = this.prev; // go back
        }
        else {
            pageNr--; // pages area 1,2,3 - but in the array they are 0,1,2
        }
        var goPage = this.$pages.eq(pageNr);
        var currentPage = this.$pages.eq(this.page);
        var direction = pageNr > this.page ? 1 : -1; // 1 = right, -1 = left
        var offset = this.width;
        this.$el.css('overflow', 'hidden');
        currentPage
            .animate({
                'margin-left': -direction*offset+'px',
                'opacity': 0
            }, this.speed, function(){ nav.$pages.eq(nav.page).css('visibility', 'hidden'); });
        goPage
            .css({
                'margin-left': direction*offset+'px',
                'visibility': 'visible',
                'opacity': 0
            })
            .animate({
                'margin-left': 0,
                'opacity': 1
            }, this.speed, function(){ nav.$el.css('overflow', 'visible'); });
        this.prev = this.page;
        this.page = pageNr;
    },
    show: function(pageNr){
        pageNr--;
        $(this.$pages[pageNr]).css('visibility', 'visible');
        this.page = pageNr;
    },
    init: function(){
        this.width = this.$el.width();
        this.$pages = $('> .window', this.$el);
        this.show(1);
    }
}

function moveWindow(event){
    movingWindow.css({ top: event.pageY - movePos.y, left: event.pageX - movePos.x });
}

function resizeLayer(event, x, y){
    var halfWidth, halfHeight, maxWidth, maxHeight;
     halfWidth = parseInt(( x != null ? x/2 : event.pageX - dimensions.width/2 + offset.x), 10);
    halfHeight = event != null && event.shiftKey ? halfWidth / currentStyle.ratio : parseInt(( y != null ? y/2 : event.pageY - dimensions.height/2 + offset.y), 10);
    maxWidth = dimensions.width/2;
    maxHeight = dimensions.height/2;
    halfWidth =  halfWidth < 8 ? 8 : halfWidth > maxWidth ? maxWidth : halfWidth;
    halfHeight = halfHeight < 8 ? 8 : halfHeight > maxHeight ? maxHeight : halfHeight;
    currentStyle.width = halfWidth*2;
    currentStyle.height = halfHeight*2;
    $layer.css({
        'width': currentStyle.width,
        'height': currentStyle.height,
        'margin-top': -halfHeight,
        'margin-left': -halfWidth
    });
}

function showSlide(pos){
    $navElements.removeClass('active');
    $navElements.eq(pos).addClass('active');
    $holderElements.removeClass('active').eq(pos).addClass('active');
}

function dragenter(e) {
      e.stopPropagation();
      e.preventDefault();
    $body.addClass("dragging");
}

function dragleave(e) {
      e.stopPropagation();
      e.preventDefault();
    $body.removeClass("dragging");
}

function dragover(e) {
      e.stopPropagation();
      e.preventDefault();
}

function drop(e) {
      e.stopPropagation();
      e.preventDefault();

    dropPos = { x: e.pageX, y: e.pageY };
    
      var dt = e.dataTransfer;
    var files = dt.files;
    
    for (var i = 0, l=files.length; i < l; i++) {
        var data = files[i];
        //bytes = new Stream(data);
        reader = new FileReader();
        reader.onload = function(e){
            
            var img = new Image(),
                $canvas = $("<canvas></canvas>"),
                ctx = $canvas.get(0).getContext('2d');
            
            img.src = e.target.result;
            
            img.onload = function(){
                
                  $canvas.attr({
                    title: data.name,
                    width: img.width,
                    height: img.height
                });

                $canvas.css({ left: dropPos.x-img.width/2, top: dropPos.y-img.height/2, position: "absolute" });
                $canvas.addClass("moveable");

                ctx.drawImage(img, 0, 0);

                $canvas.appendTo($workspace);
            };
        };
        reader.readAsDataURL(data);
    }
    
    $body.removeClass("dragging");
}

function showPickArea(){
    $body.addClass("pick");
    // draw the parallel Universe for color picking
    parallelUniverse.draw();
    // redraw the parallelUniverse when the layer gets redrawn ("paint" event);
    $(document).bind('paint', $.proxy( parallelUniverse, "draw" ));
    $overlay.bind('mousedown', pick);
}

function hidePickArea(){
    $body.removeClass("pick");
    $(document).unbind('paint', $.proxy( parallelUniverse, "draw" ));
    $overlay.unbind('mousedown');
}

function pick(event){
    var pickedColor = pu.getImageData(event.pageX, event.pageY, 1, 1).data;
    colorpicker.setHex(color.hexFromRgb(pickedColor));
    colorpicker.update('hex');
}

function initialise() {
    // include 'dataTransfer' to jquerys event object
    jQuery.event.props.push('dataTransfer');
    
    // set language 
    // not yet elaborated - whats the best solution to change all titles in the html?
    // - create the html via js in the first place or select and change them all?
    // - regex over the all textnodes?
    lang = localization.en;

    $navElements.click(function(){
        var pos = $navElements.index(this);
        localStorage["slidePos"] = pos;
        showSlide(pos);
    });

    $numericalInputs.bind({
        mousedown: function(e){ e.stopPropagation(); },
        focus: function(e){ numbers.initNumberField(this, 'style'); },
        keydown: numbers.restrictCharacters,
        keyup: numbers.keyUp,
        blur: numbers.validateInput
    });
    
    moveAreas.live('mousedown', function(event){ 
        event.preventDefault();
        movingWindow = $(this).hasClass("head") ? $(this).parents('#layerstyle') : $(this);
        movingWindow.addClass("moving");
        $(document).one('mouseup', function(){ movingWindow.removeClass("moving"); });
        var myOffset = movingWindow.offset();
        movePos = { x:event.pageX-myOffset.left, y:event.pageY-myOffset.top };
        $(document).bind('mousemove.global', moveWindow);
    }); 
    resizeArea.bind({
        mousedown: function(event){
            event.preventDefault();
            event.stopPropagation();
            currentStyle.ratio = currentStyle.width/currentStyle.height;
            $(document).bind('mousemove.global', resizeLayer);
            $body.addClass("resize");
            $(document).one('mouseup', function(){ $body.removeClass('resize'); });
            var my_offset = $(this).offset();
            offset = { x: 15-(event.pageX-my_offset.left), y: 15-(event.pageY-my_offset.top) };
        },
        click: function(event){ event.stopPropagation(); } // prevent bubbling
    });
    $(document).bind({
        mousemove: function(e){ e.preventDefault(); },
        mouseup: function(){ $(this).unbind('mousemove.global'); },
        dragenter: dragenter,
        dragleave: dragleave,
        dragover: dragover,
        drop: drop
    });
    
    $(window).bind({
        resize: function(event){
            dimensions = { width: $workspace.width(), height: $workspace.height() };
            $parallelUniverse.attr({'width': dimensions.width, 'height': dimensions.height});
            $innerShadowUniverse.attr({'width': dimensions.width, 'height': dimensions.height});
            if (dimensions.width < currentStyle.width) { resizeLayer(null, dimensions.width, currentStyle.height); }
            if (dimensions.height < currentStyle.height) { resizeLayer(null, currentStyle.width, dimensions.height); }
        },
        keydown: function(event){
            if(event.altKey){
                $body.addClass('alt');
                $(this).one('keyup', function(){ $body.removeClass('alt'); });
            }
        }
    });
    $layer.dblclick(function(event){ $layerstyle.show(); });
    $buttons.ok.click(function(){ $layerstyle.hide(); });
    $buttons.cancel.click(function(){ $layerstyle.hide(); });
    $buttons.newStyle.click( $.proxy( styleStore, "create" ) );

    $('#infoButton').click(function(){ $body.removeClass('visited'); });

    styleStore.init();
    nav.init();
    colorpicker.init();
    gradienteditor.init();
    codeBox.init();
    style.init();
    showSlide(localStorage["slidePos"] || 1);
    nav.goTo(localStorage["pageNr"] || 1);
    
    $(document)
        .bind('paint', $.proxy( codeBox, "render" ))
        .bind('paint', $.proxy( css, "render" ))
        .trigger('styleChange')
        .trigger('paint');
}

// isEven: (n % 2) == 0 -> true? even : odd

// GET THE BALL ROLLIN
$(document).ready(function(){
    initialise();
});

================================================
FILE: js/codebox.js
================================================
var codeBox = {
    options: {
        visible: true,
        height: 143
    },
    minHeight: 100,
    init: function(){
        if(localStorage["codeBoxOptions"]) this.options = JSON.parse(localStorage["codeBoxOptions"]);
        this.$el = $('#codeBox');
        this.$box = this.$el.find('code');
        this.$body = this.$el.find('.body');
        this.$copyCode = this.$el.find('#copyCode');
        this.$dragger = this.$el.find('.dragger.y');
        this.$codeBoxToggle = $('#codeBoxToggle');
        this.$colorToggle = Object.create(toggle);
        this.$colorToggle.init("colorSwitch", "hex", tools.options, $.proxy( this, "render" ));
        
        this.location = window.location.href.slice(0, window.location.href.lastIndexOf("/"));
        this.initClipboard();
        
        this.$copyCode.add(this.$body).add(this.$box)
            .bind('mousedown', function(e){ e.stopPropagation(); });
        this.$codeBoxToggle.click( $.proxy( this, "toggle" ) );
        this.$dragger.mousedown( $.proxy( this, "drag") );
        
        this.updateView();
    },
    toggle: function(){
        if(this.$el.height() === 0){
            this.options.visible = true;
        } else {
            this.options.visible = false;
        }
        this.storeSettings();
        this.updateView();
        $(window).trigger('resize');
    },
    updateView: function(){
        if(this.options.visible){
            this.$el.height(this.options.height);
        } else {
            this.$el.height(0);
        }
    },
    drag: function(event){
        event.preventDefault();
        var my_offset = $(event.target).offset();
        offset = { y: event.pageY-my_offset.top };
        this.$el.addClass("resizing");
        this.resize(event);
        $(document).one('mouseup', function(){ codeBox.$el.removeClass('resizing') } );
        $(document).bind('mousemove.global', $.proxy( this, "resize") );
    },
    resize: function(event){
        this.options.height = Math.max(this.minHeight, $(document).height() - event.pageY + offset.y);
        this.$el.height(this.options.height);
        $(window).trigger('resize');
        this.storeSettings();
    },
    storeSettings: function(){
        localStorage["codeBoxOptions"] = JSON.stringify(this.options);
    },
    /**
     * @method  initClipboard - a click on the button with the id 'copyCode' will copy 'this.$box.text()' into the clipboard
     * @see        http://code.google.com/p/zeroclipboard/wiki/Instructions
     */
    initClipboard: function(){
        ZeroClipboard.setMoviePath( this.location + '/js/zeroclipboard/ZeroClipboard.swf' );
        this.clip = new ZeroClipboard.Client();
        this.clip.addEventListener( 'onMouseDown', $.proxy( this, "copy" ) );
        this.clip.setHandCursor(true);
        var flash = this.clip.getHTML(this.$copyCode.width(), this.$copyCode.height());
        this.$copyCode.append(flash);
    },
    copy: function(){
        var text = this.code.replace(/<br>/g, "\n").replace(/&nbsp;/g, "");
        this.clip.setText(text);
    },
    tabs: function(count){
        var tabString = "",
            tabs = count || this.options.tabs;
        
        for(;tabs--;){
            tabString += "&nbsp;";
        }
        return tabString;
    },
    render: function(){
        var borderRadiusObject;
        this.code = "";
        // add border
        this.code += currentStyle.border.isActive ? "border: " + css.border(currentStyle) + ";<br>" : "";
        // add border-radius
        if(currentStyle.borderRadius.isActive){
            borderRadiusObject = css.borderRadius(currentStyle);
            for(var key in borderRadiusObject){
                var radius = borderRadiusObject[key];
                if(radius !== 0){
                    this.code += key + ": " + radius + ";<br>";
                }
            }
        }
        // add gradient
        if(currentStyle.background.isActive){
            this.code += "background-image: " + css.drawGradient(currentStyle) + ";<br>";
        }
        // add dropShadow and innerShadow
        if(currentStyle.dropShadow.isActive || currentStyle.innerShadow.isActive){
            this.code += "box-shadow: " + css.boxShadow(currentStyle) + ";<br>";
        }
        this.$box.html(this.code);
    }
};

================================================
FILE: js/color.js
================================================
var color = {
    hsbFromRgb: function(rgb) {
        r = rgb[0]/255, g = rgb[1]/255, b = rgb[2]/255;
        var max = Math.max(r, g, b), min = Math.min(r, g, b);
        var h, s, v = max;

        var d = max - min;
        s = max === 0 ? 0 : d / max;

        if(max === min){
            h = 0;
        }else{
            switch(max){
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        return [Math.round(h * 360), Math.round(s * 100), Math.round(v * 100)];
    },
    rgbFromHsb: function(hsv) {
        var r, g, b;
        h = hsv[0]/360; s = hsv[1]/100; v = hsv[2]/100;

        var i = Math.floor(h * 6);
        var f = h * 6 - i;
        var p = v * (1 - s);
        var q = v * (1 - f * s);
        var t = v * (1 - (1 - f) * s);

        switch(i % 6){
            case 0: r = v; g = t; b = p; break;
            case 1: r = q; g = v; b = p; break;
            case 2: r = p; g = v; b = t; break;
            case 3: r = p; g = q; b = v; break;
            case 4: r = t; g = p; b = v; break;
            case 5: r = v; g = p; b = q; break;
        }
        return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
    },
    rgbFromHex: function(hex){
        if(hex.length === 3){
            return [
                parseInt(hex.substring(0,1)+hex.substring(0,1), 16),
                parseInt(hex.substring(1,2)+hex.substring(1,2), 16),
                parseInt(hex.substring(2,3)+hex.substring(2,3), 16)
            ]
        } else {
               return [
                parseInt(hex.substring(0,2), 16),
                parseInt(hex.substring(2,4), 16),
                parseInt(hex.substring(4,6), 16)
            ]
        }
    },
    hexFromRgb: function(rgb){
        var hexcode = this.toHex(rgb[0])+this.toHex(rgb[1])+this.toHex(rgb[2]),
            parts = hexcode.split("");
        // "000" instead of "000000"
        return (parts[0]===parts[1]) && (parts[2]===parts[3]) && (parts[4]==parts[5]) ? parts[0]+parts[2]+parts[4] : hexcode;
    },
    toHex: function(n) {
        if(n === 0) { return '00'; }
        n = parseInt(n, 10);
        if (n === 0 || isNaN(n)) { return "00"; }
        return "0123456789abcdef".charAt((n-n%16)/16) + "0123456789abcdef".charAt(n%16);
    }
};

================================================
FILE: js/colorpicker.js
================================================
/*
 *      LayerStyles
 *       http://www.layerstyles.org
 *    
 *    Copyright (c) 2011 Felix Niklas
 *    This script is freely distributable under the terms of the MIT license.
 */

var colorpicker = {
    open: false,
    currentColor: "000000", // hex
    callback: null,
    thisArg: null,
    swatches: [
        {'title': 'White', 'hex': 'ffffff'},
        {'title': '10% Gray', 'hex': 'e5e5e5'},
        {'title': '20% Gray', 'hex': 'cccccc'},
        {'title': '30% Gray', 'hex': 'b3b3b3'},
        {'title': '40% Gray', 'hex': '999999'},
        {'title': '50% Gray', 'hex': '808080'},
        {'title': '60% Gray', 'hex': '666666'},
        {'title': '70% Gray', 'hex': '4d4d4d'},
        {'title': '80% Gray', 'hex': '333333'},
        {'title': '90% Gray', 'hex': '1a1a1a'},
        {'title': 'Black', 'hex': '000000'}
    ],
    $selectedInput: null,
    colorHistory: [],
    pointerPos: { 'x': 0, 'y': 0 },
    hsb: { h: 0, s: 0, b: 0 },
    rgb: { r: 0, g: 0, b: 0 },
    hex: '000000',
    mode: 'hsb_b',
    max: 0, // the maximum input value
    ratio: 0, // the ratio for the slider: its 0.7111 (hue), ~1 (rgb) or 2.56 (saturation/brightness)
    offset: 0, // the offset relative to the document will be stored in here to calculate mouse-dragging
    pick: function(rgbArray, callback, thisArg) {
        showPickArea();
        this.callback = callback;
        this.thisArg = thisArg;
        // set rgb
        this.setRgb(parseInt(rgbArray[0],10),parseInt(rgbArray[1],10),parseInt(rgbArray[2],10));
        // update
        this.update('rgb_r');
        // set currentColor
        this.setCurrentColor();
        // show it
        nav.goTo(3);
    },
    setCurrentColor: function(hex) {
        this.currentColor = hex || this.hex;
        this.$currentColor.css('background', '#'+this.currentColor);
    },
    pickCurrentColor: function(){
        this.setHex(this.currentColor);
        this.update('hex');
    },
    clickHex: function(){
        this.$hex.focus();
    },
    update: function(customMode) {
        var updateMode = customMode || this.mode;
        switch(updateMode){
        case 'hsb_h': case 'hsb_s': case 'hsb_b':
            this.getHsb();
            this.hsbToRgb();
            this.rgbToHex();
            break;
        case 'rgb_r': case 'rgb_g': case 'rgb_b':
            this.getRgb();
            this.rgbToHsb();
            this.rgbToHex();
            break;
        case 'hex':
            this.getHex();
            this.hexToRgb();
            this.rgbToHsb();
            break;
        }
        this.paintField();
        this.paintSlider();
        this.setNewColor();
        this.moveSlider(this.$selectedInput.val()*this.ratio);
        if(this.callback) this.callback.call(this.thisArg, color.rgbFromHex(this.hex));
    },
    paintField: function() {
        var xGradient, yGradient;
        this.cf.save();
        this.cf.clearRect(0,0,256,256);
        xGradient = this.cf.createLinearGradient(0, 0, 0, 256);
        yGradient = this.cf.createLinearGradient(0, 0, 256, 0);
        switch (this.mode) {
        case 'hsb_h': // rainbow
            var hue = color.rgbFromHsb([this.hsb.h, 100, 100]);
            yGradient.addColorStop(0, 'white');
            yGradient.addColorStop(1, 'rgb('+hue[0]+','+hue[1]+','+hue[2]+')');
            xGradient.addColorStop(0, 'transparent');
            xGradient.addColorStop(1, 'black');
            break;
        case 'hsb_s': // rainbow
            yGradient.addColorStop(0, 'rgb(255,0,0)');
            yGradient.addColorStop(1/6, 'rgb(255,255,0)');
            yGradient.addColorStop(2/6, 'rgb(0,255,0)');
            yGradient.addColorStop(3/6, 'rgb(0,255,255)');
            yGradient.addColorStop(4/6, 'rgb(0,0,255)');
            yGradient.addColorStop(5/6, 'rgb(255,0,255)');
            yGradient.addColorStop(1, 'rgb(255,0,0)');
            xGradient.addColorStop(0, 'rgba(0,0,0,'+(1-this.hsb.s/100)+')' );
            xGradient.addColorStop(1, 'black' );
            break;
        case 'hsb_b': // rainbow from saturated to unsaturated
            var grey = parseInt(this.hsb.b*2.56, 10);
            yGradient.addColorStop(0, 'rgb(255,0,0)');
            yGradient.addColorStop(1/6, 'rgb(255,255,0)');
            yGradient.addColorStop(2/6, 'rgb(0,255,0)');
            yGradient.addColorStop(3/6, 'rgb(0,255,255)');
            yGradient.addColorStop(4/6, 'rgb(0,0,255)');
            yGradient.addColorStop(5/6, 'rgb(255,0,255)');
            yGradient.addColorStop(1, 'rgb(255,0,0)');
            xGradient.addColorStop(0, 'rgba('+grey+','+grey+','+grey+','+(1-this.hsb.b/100)+')');
            xGradient.addColorStop(1, 'rgb('+grey+','+grey+','+grey+')');
            break;
        case 'rgb_r':
            this.cf.globalCompositeOperation = 'lighter';
            xGradient.addColorStop(0, 'rgb('+this.rgb.r+',255,0)');
            xGradient.addColorStop(1, 'rgb('+this.rgb.r+',0,0)');
            yGradient.addColorStop(0, 'rgb('+this.rgb.r+',0,0)');
            yGradient.addColorStop(1, 'rgb('+this.rgb.r+',0,255)');
            break;
        case 'rgb_g':
            this.cf.globalCompositeOperation = 'lighter';
            xGradient.addColorStop(0, 'rgb(255,'+this.rgb.g+',0)');
            xGradient.addColorStop(1, 'rgb(0,'+this.rgb.g+',0)');
            yGradient.addColorStop(0, 'rgb(0,'+this.rgb.g+',0)');
            yGradient.addColorStop(1, 'rgb(1,'+this.rgb.g+',255)');
            break;
        case 'rgb_b':
            this.cf.globalCompositeOperation = 'lighter';
            xGradient.addColorStop(0, 'rgb(0,255,'+this.rgb.b+')');
            xGradient.addColorStop(1, 'rgb(0,0,'+this.rgb.b+')');
            yGradient.addColorStop(0, 'rgb(0,0,'+this.rgb.b+')');
            yGradient.addColorStop(1, 'rgb(255,0,'+this.rgb.b+')');
            break;
        }
        this.cf.beginPath();
        this.cf.rect(0, 0, 256, 256);
        this.cf.closePath();
        this.cf.fillStyle = yGradient;
        this.cf.fill();
        this.cf.beginPath();
        this.cf.rect(0, 0, 256, 256);
        this.cf.closePath();
        this.cf.fillStyle = xGradient;
        this.cf.fill();
        this.cf.restore();
        this.movePointer();
    },
    startPointer: function(event) {
        this.offset = this.$circleField.offset();
        this.calculatePointer(event);
        $(document).bind('mousemove.global', jQuery.proxy(this, "calculatePointer"));
    },
    calculatePointer: function(event) {
        event.preventDefault();
        this.pointerPos.x = Math.max(0, Math.min(256, event.pageX-this.offset.left));
        this.pointerPos.y = Math.max(0, Math.min(256, event.pageY-this.offset.top));
        switch(this.mode){
        case 'hsb_h':
            this.$hsb_s.val(parseInt(this.pointerPos.x/2.56, 10));
            this.$hsb_b.val(100-parseInt(this.pointerPos.y/2.56, 10));
            break;
        case 'hsb_s':
            this.$hsb_h.val(parseInt(this.pointerPos.x/0.71111, 10));
            this.$hsb_b.val(100-parseInt(this.pointerPos.y/2.56, 10));
            break;
        case 'hsb_b':
            this.$hsb_h.val(parseInt(this.pointerPos.x/0.71111, 10));
            this.$hsb_s.val(100-parseInt(this.pointerPos.y/2.56, 10));
            break;
        case 'rgb_r':
            this.$rgb_b.val(parseInt(this.pointerPos.x/1.003921, 10));
            this.$rgb_g.val(255-parseInt(this.pointerPos.y/1.003921, 10));
            break;
        case 'rgb_g':
            this.$rgb_b.val(parseInt(this.pointerPos.x/1.003921, 10));
            this.$rgb_r.val(255-parseInt(this.pointerPos.y/1.003921, 10));
            break;
        case 'rgb_b':
            this.$rgb_r.val(parseInt(this.pointerPos.x/1.003921, 10));
            this.$rgb_g.val(255-parseInt(this.pointerPos.y/1.003921, 10));
            break;
        }
        this.movePointer();
        this.update();
    },
    movePointer: function(x, y) {
        this.pointerPos.x = x >= 0 ? x : this.pointerPos.x;
        this.pointerPos.y = y >= 0 ? y : this.pointerPos.y;
        this.cc.clearRect(0,0,256,256);
        // limit x and y to 0-255 cause we need +1 (=256) space to detect the underlaying color 
        var detectX = Math.min(255, this.pointerPos.x),
            detectY = Math.min(255, this.pointerPos.y);
        var background = this.cf.getImageData(detectX, detectY, 1, 1).data;
        // check if the underlying color is dark or light and set the circle color according to that
        // -> white circle if the underlying color is dark (treshhold of 128 - where 256 is white) - otherwise black
        this.cc.strokeStyle = ((background[0]+background[1]+background[2])/3) < 128 ? 'white' : 'black';
        this.cc.beginPath();
        this.cc.arc(detectX + 0.5, detectY + 0.5, 5, 0, Math.PI*2, true);
        this.cc.closePath();
        this.cc.stroke();
    },
    drawPointer: function() {
        var posX = 0,
            posY = 0;
        switch(this.mode){
        case 'hsb_h':
            posX = this.hsb.s*2.56;
            posY = (100-this.hsb.b)*2.56;
            break;
        case 'hsb_s':
            posX = this.hsb.h*0.71111;
            posY = (100-this.hsb.b)*2.56;
            break;
        case 'hsb_b':
            posX = this.hsb.h*0.71111;
            posY = (100-this.hsb.s)*2.56;
            break;
        case 'rgb_r':
            posX = this.rgb.b*1.003921;
            posY = (255-this.rgb.g)*1.003921;
            break;
        case 'rgb_g':
            posX = this.rgb.b*1.003921;
            posY = (255-this.rgb.r)*1.003921;
            break;
        case 'rgb_b':
            posX = this.rgb.r*1.003921;
            posY = (255-this.rgb.g)*1.003921;
            break;
        }
        this.movePointer(parseInt(posX, 10), parseInt(posY, 10));
    },
    paintSlider: function() {
        var gradient = this.cs.createLinearGradient(0, 0, 0, 256);
        this.cs.clearRect(0,0,19,256);
        switch (this.mode) {
        case 'hsb_h': // rainbow
            gradient.addColorStop(0, 'rgb(255,0,0)');
            gradient.addColorStop(1/6, 'rgb(255,0,255)');
            gradient.addColorStop(2/6, 'rgb(0,0,255)');
            gradient.addColorStop(3/6, 'rgb(0,255,255)');
            gradient.addColorStop(4/6, 'rgb(0,255,0)');
            gradient.addColorStop(5/6, 'rgb(255,255,0)');
            gradient.addColorStop(1, 'rgb(255,0,0)');
            break;
        case 'hsb_s': // max saturation to unsaturated
            var brightness = this.hsb.b;
            if(brightness <= 33) brightness = 33;
            var saturated = color.rgbFromHsb([this.hsb.h, 100, brightness]);
            var unsaturated = color.rgbFromHsb([this.hsb.h, 0, brightness]);
            gradient.addColorStop(0, 'rgb('+saturated[0]+','+saturated[1]+','+saturated[2]+')');
            gradient.addColorStop(1, 'rgb('+unsaturated[0]+','+unsaturated[1]+','+unsaturated[2]+')');
            break;
        case 'hsb_b': // max brightness to black
            var brightest = color.rgbFromHsb([this.hsb.h, this.hsb.s, 100]);
            gradient.addColorStop(0, 'rgb('+brightest[0]+','+brightest[1]+','+brightest[2]+')');
            gradient.addColorStop(1, 'black');
            break;
        case 'rgb_r':
            gradient.addColorStop(0, 'rgb(255,'+this.rgb.g+','+this.rgb.b+')');
            gradient.addColorStop(1, 'rgb(0,'+this.rgb.g+','+this.rgb.b+')');
            break;
        case 'rgb_g':
            gradient.addColorStop(0, 'rgb('+this.rgb.r+',255,'+this.rgb.b+')');
            gradient.addColorStop(1, 'rgb('+this.rgb.r+',0,'+this.rgb.b+')');
            break;
        case 'rgb_b':
            gradient.addColorStop(0, 'rgb('+this.rgb.r+','+this.rgb.g+',255)');
            gradient.addColorStop(1, 'rgb('+this.rgb.r+','+this.rgb.g+',0)');
            break;
        }
        this.cs.beginPath();
        this.cs.rect(0, 0, 19, 256);
        this.cs.closePath();
        this.cs.fillStyle = gradient;
        this.cs.fill();
    },
    startSlider: function(event) {
        this.offset = this.$slideArea.offset();
        this.slide(event);
        $(document).bind('mousemove.global', jQuery.proxy(this, "slide"));
    },
    slide: function(event) {
        event.preventDefault();
        var relativePosition = event.pageY - this.offset.top;
        if(relativePosition < 0) relativePosition = 0;
        if(relativePosition > 256) relativePosition = 256;
        // invert the value because the browsers coordination system has its origin at the top but the slider has its origin at the bottom
        relativePosition = 256 - relativePosition;
        this.moveSlider(relativePosition);
        this.$selectedInput.val(parseInt(relativePosition/this.ratio, 10));
        this.update();
    },
    moveSlider: function(position) {
        this.$slider.css({'top':(256-position)+'px'});
    },
    getHsb: function() {
        this.hsb.h = this.$hsb_h.val();
        this.hsb.s = this.$hsb_s.val();
        this.hsb.b = this.$hsb_b.val();
    },
    getRgb: function() {
        this.rgb.r = this.$rgb_r.val();
        this.rgb.g = this.$rgb_g.val();
        this.rgb.b = this.$rgb_b.val();
    },
    getHex: function() {
        var hex = this.$hex.val();
        var missingLength = 6 - hex.length;
        if(missingLength === 3){ 
            var parts = hex.split("");
            hex = parts[0]+parts[0]+parts[1]+parts[1]+parts[2]+parts[2];
        } else {
            for(var i = 0; i<missingLength; i++){ 
                hex = "0" + hex;
            }
        }
        this.hex = hex;
    },
    setHsb: function() {
        this.$hsb_h.val(this.hsb.h);
        this.$hsb_s.val(this.hsb.s);
        this.$hsb_b.val(this.hsb.b);
    },
    setRgb: function(r,g,b) {
        this.$rgb_r.val(r != null ? r : this.rgb.r);
        this.$rgb_g.val(g != null ? g : this.rgb.g);
        this.$rgb_b.val(b != null ? b : this.rgb.b);
    },
    setHex: function(hex) {
        var hexcode = hex || this.hex,
            parts = hexcode.split("");
        // "000" instead of "000000"
        hexcode = (parts[0]===parts[1]) && (parts[2]===parts[3]) && (parts[4]==parts[5]) ? parts[0]+parts[2]+parts[4] : hexcode;
        this.$hex.val(hexcode);
    },
    hsbToRgb: function() {
        var rgb = color.rgbFromHsb([this.hsb.h, this.hsb.s, this.hsb.b]);
        this.rgb.r = rgb[0];
        this.rgb.g = rgb[1];
        this.rgb.b = rgb[2];
        this.setRgb();
    },
    rgbToHex: function(){
        this.hex = color.hexFromRgb([this.rgb.r, this.rgb.g, this.rgb.b]);
        this.setHex();
    },
    hexToRgb: function(){
        var rgb = color.rgbFromHex(this.hex);
        this.rgb.r = rgb[0];
        this.rgb.g = rgb[1];
        this.rgb.b = rgb[2];
        this.setRgb();
    },
    setNewColor: function() {
        this.$newColor.css('background', '#'+this.hex);
    },
    rgbToHsb: function() {
        var hsb = color.hsbFromRgb([this.rgb.r, this.rgb.g, this.rgb.b]);
        this.hsb.h = hsb[0];
        this.hsb.s = hsb[1];
        this.hsb.b = hsb[2];
        this.setHsb();
    },
    addSwatch: function(title, hex) {
        return $('<span class="swatch" />')
                .attr({'title': title, 'data-hex': hex})
                .css({'background': '#'+hex})
                .bind('click', {self: this}, this.handleSwatch);
    },
    handleSwatch: function(e){
        e.stopPropagation();
        var self = e.data.self;
        // if alt is pressed while clicking: remove swatch
        if(e.altKey){
            // find out the swatches position in the swatch array
            var position = 0;
            var family = $(this).parent().children();
            for(var i = 0, length = family.length; i<length; i++){
                if(this===family[i]){ position = i; }
            }
            // slice out the swatch from the swatch array (method by John Resig)
            var rest = self.swatches.slice(position + 1);
            self.swatches.length = position;
            self.swatches.push.apply(self.swatches, rest);
            localStorage["swatches"] = JSON.stringify(self.swatches);
            $(this).remove();
        }
        // else get that swatches color
        else {
            var hex = $(this).attr('data-hex');
            self.setHex(hex);
            self.update('hex');
        }
    },
    okAction: function(){
        this.close("ok");
    },
    cancelAction: function(){
        this.close("cancel");
    },
    close: function(mode){
        var rgb;
        switch(mode){
            case "ok":
                this.setCurrentColor();
                this.colorHistory.push(this.currentColor);
                rgb = color.rgbFromHex(this.hex);
                break;
            case "cancel":
                rgb = color.rgbFromHex(this.currentColor);
                break;
        }
        if(this.callback) this.callback.call(this.thisArg, rgb);
        this.callback = null;
        this.open = false;
        hidePickArea();
        nav.goTo(-1);
    },
    newSwatch: function(event){
        var self = event.data.self;
        var title = prompt(lang.ColorSwatchName,"Swatch "+self.swatches.length);
        if(title){
            self.$swatchHolder.append(self.addSwatch(title, self.hex));
            self.swatches.push({'title': title, 'hex': self.hex});
            localStorage["swatches"] = JSON.stringify(self.swatches);
        }
    },
    drawSwatches: function(){
        var swatches = $('<div/>');
        for(var i = 0, length = this.swatches.length; i<length; i++){
            swatches.append( this.addSwatch(this.swatches[i].title, this.swatches[i].hex) );
        }
        this.$swatchHolder.append(swatches);
    },
    selectInput: function(pos){
        this.mode = this.$radioInputs.eq(pos).val();
        this.$selectedInput = this.$textInputs.eq(pos);
        this.$selectedInput.focus();
        this.max = this.$selectedInput.attr('data-max');
        this.ratio = 256/this.max;
        this.moveSlider(this.$selectedInput.val()*this.ratio);
        this.drawPointer();
    },
    findCheckedInput: function(){
        for (var i = 0; i<6; i++) {
            if (this.$radioInputs.eq(i).attr('checked')) {
                this.selectInput(i);
            }
        }
    },
    clickAll: function(event) {
        var self = event.data.self;
        var $currentRadio = $('input[type=radio]', this);
        var $currentText = $('input[type=text]', this);
        var clickTargetType = $(event.target).attr('type');
        switch(clickTargetType){
            case "radio":
                $currentText.focus();
                self.mode = $currentRadio.val();
                self.max = $currentText.attr('data-max');
                self.ratio = 256/self.max;
                self.$selectedInput = $currentText;
                self.update();
                self.moveSlider($currentText.val()*self.ratio);
                self.drawPointer();
                break;
            case "text": self.update(); break;
            case "number": self.update(); break;
            default:
                $currentRadio.attr('checked', 'ckecked');
                $currentText.focus();
                self.mode = $currentRadio.val();
                self.max = $currentText.attr('data-max');
                self.update();
        }
    },
    init: function() {
        this.$element = $('#colorpicker');
        this.$textHolder = this.$element.find('li');
        this.$hexHolder = $('#hex_holder');
        this.$swatchHolder = $('#swatches');
        this.$currentColor = $('#current_color');
        this.$newColor = $('#new_color');
        this.$textInputs = this.$element.find('li input[type=text]');
        this.$radioInputs = this.$element.find('li input[type=radio]');
        this.$hsb_h = $('#hsb_h');
        this.$hsb_s = $('#hsb_s');
        this.$hsb_b = $('#hsb_b');
        this.$rgb_r = $('#rgb_r');
        this.$rgb_g = $('#rgb_g');
        this.$rgb_b = $('#rgb_b');
        this.$hex = $('#hex');
        this.$button_ok = $('#color_ok');
        this.$button_cancel = $('#color_cancel');
        this.$circleField = $('#circle');
        this.$slideArea = $('#color_slider');
        this.$slider = this.$slideArea.find('> div');
        this.cf = $('#field').get(0).getContext('2d');
        this.cc = $('#circle').get(0).getContext('2d');
        this.cs = this.$slideArea.find('canvas').get(0).getContext('2d');
        
        if(localStorage["swatches"]) this.swatches = JSON.parse(localStorage["swatches"]);
        this.$currentColor.click( jQuery.proxy(this, "pickCurrentColor") );
        this.$button_ok.click( jQuery.proxy(this, "okAction") );
        this.$button_cancel.click( jQuery.proxy(this, "cancelAction") );
        this.$circleField.mousedown( jQuery.proxy(this, "startPointer") );
        this.$slideArea.mousedown( jQuery.proxy(this, "startSlider") );
        this.$textHolder.bind('click', {self: this}, this.clickAll);
        this.$hexHolder.click( jQuery.proxy(this, "clickHex") );
        this.$hex.bind({
            focus: function(){ numbers.initHexField(this, 'color'); },
            keydown: numbers.restrictCharacters,
            keyup: numbers.keyUp
        });
        this.$textInputs.bind({
            focus: function(){ numbers.initNumberField(this, 'color'); },
            keydown: numbers.restrictCharacters,
            keyup: numbers.keyUp,
            blur: numbers.validateInput
        });
        this.$swatchHolder.bind('click', {self: this}, this.newSwatch);
        // find initial checked input
        this.findCheckedInput();
        // draw swatches
        this.drawSwatches();
        this.update();
    }
};

================================================
FILE: js/css.js
================================================
var css = {
    colors: {
        'rgb(0,0,0)': "black",
        'rgb(255,255,255)': "white"
    },
    gradientDirections: {
        315: "to bottom right",
        270: "to bottom",
        225: "to bottom left",
        180: "to left",
        135: "to top left",
        90: "to top",
        45: "to top right",
        0: "to right"
    },
    /**
     * @method  cssGradient    
     * @param   gradient {object}
     * @return  {array} decoded color stops: rgb strings
     * @example cssGradient([0,0,0], 10, [255,255,255]) returns "-moz-linear-gradient(top, 'rgb(0,0,0)', 'rgb(25,25,25) 10%', 'rgb(255,255,255)')"
     */
    cssGradient: function(stops, angle, style){
        var tempStops, shape = "", cssString = "", pos;

        switch(style){
            case "linear": case "reflected":
                tempStops = style === "reflected" ? tools.reflectStops(stops) : stops;

                if (this.gradientDirections[angle]) {
                    pos = this.gradientDirections[angle];
                } else {
                    pos = angle+"deg";
                }
                if(pos == "to bottom"){
                    cssString = 'linear-gradient('+ tools.decodeStops(tempStops).join(", ") +')';
                } else {
                    cssString = 'linear-gradient('+ pos +', '+ tools.decodeStops(tempStops).join(", ") +')';
                }
                break;
            case "contain":
                cssString = 'radial-gradient(center center, '+shape+'contain, '+ tools.decodeStops(stops).join(", ") +')';
                break;
            case "cover":
                cssString = 'radial-gradient(center center, '+shape+'cover, '+ tools.decodeStops(stops).join(", ") +')';
                break;
        }
        return cssString;
    },
    drawGradient: function(style){
        var cssString = "",
            model = style.background, 
            tempAngle, tempOpacity, tempStops;
        
        if(model.isActive) {
            tempAngle = model.angle+180;
            if(tempAngle >= 360) tempAngle -= 360;
            tempOpacity = model.opacity;
            if(tempOpacity != 100){
                tempOpacity = model.opacity/100;
            }
            if(!model.translucidStops) model.translucidStops = $.extend(true, [], model.stops);
            
            // inject opacity into the rgb values or slice off the injection if opacity is 100
            for(var i=0, l=model.translucidStops.length; i<l; i++){
                switch(model.stops[i].length){
                case 2: // [[255,255,255], 45]
                    if(tempOpacity === 100){
                        model.translucidStops[i][0] = model.translucidStops[i][0].slice(0,3);
                    } else {
                        model.translucidStops[i][0][3] = tempOpacity;
                    }
                    break;
                case 3: case 4: // [255,255,255] or [255,255,255,0.5]
                    if(tempOpacity === 100){
                        model.translucidStops[i] = model.translucidStops[i].slice(0,3);
                    } else {
                        model.translucidStops[i][3] = tempOpacity;
                    }
                    break;
                }
            }
            tempStops = model.translucidStops.slice(0); // no deep copy!
            if(model.hasGlobalLight) tempAngle = style.globalAngle;
            if(model.isReverse) tempStops = tools.reverseStops(tempStops);
            cssString = this.cssGradient( tempStops, tempAngle, model.style );
        }
        return cssString;
    },
    boxShadow: function(style){
        var cssString = "", radiants, dropColor, tempSize, tempX, tempY, tempBlur,
            shadows = ["dropShadow", "innerShadow"];
        
        for(var i=0; i<shadows.length; i++){
            var model = style[shadows[i]];
            if(model.isActive){
                if(cssString != "") cssString += ", ";
                if(model.hasGlobalLight) model.angle = style.globalAngle;
                radiants = (Math.PI / 180) * model.angle;
                model.dropX = Math.round(-model.distance * Math.cos(radiants));
                model.dropY = Math.round(model.distance * Math.sin(radiants));
                tempX = model.dropX === 0 ? "0 " : model.dropX + "px ";
                tempY = model.dropY === 0 ? "0 " : model.dropY + "px ";
                tempBlur = model.blur === 0 ? "0 " : model.blur + "px ";
                tempSize = model.size === 0 ? "" : model.size+"px ";
                if(model.opacity != 100){
                    dropColor = model.color.slice(0);
                    dropColor.push(model.opacity/100);
                } else {
                    dropColor = model.color;
                }
                if(model.isInset) cssString += "inset ";
                cssString += tempX + tempY + tempBlur + tempSize + tools.toColor(dropColor);
            }
        }
        return cssString;
    },
    border: function(style){
        var cssString = "",
            dropColor, model = style.border;
        if(model.isActive){
            if(model.opacity != 100){
                dropColor = model.color.slice(0);
                dropColor.push(model.opacity/100);
            } else {
                dropColor = model.color;
            }
            cssString += model.size+'px '+model.style+' '+tools.toColor(dropColor);
        }
        return cssString;
    },
    borderRadius: function(style){
        var cssObject = { "border-radius": 0 },
            model = style.borderRadius;
        
        if(model.isActive){
            var radii = [];
            for(var i=0; i<4; i++){
                var radius = model.radii[i]; // [pos, unit]
                if(radius[0] !== 0){
                    radii[i] = radius[0] + radius[1];
                } else {
                    radii[i] = 0;
                }
            }
            // check if radii are the same
            if(    radii[0] === radii[1] &&
                radii[1] === radii[2] &&
                radii[2] === radii[3] &&
                radii[3] === radii[0] ){
                    cssObject["border-radius"] = radii[0];
            } else {
                var topLeft = radii[0],
                    topRight = radii[1],
                    bottomRight = radii[2],
                    bottomLeft = radii[3];
            
                if(topRight === bottomLeft){
                    if(topLeft === bottomRight){
                        cssObject["border-radius"] = topLeft+" "+topRight;
                    } else {
                        cssObject["border-radius"] = topLeft+" "+topRight+" "+bottomRight;
                    }
                } else {
                    delete cssObject["border-radius"];
                    if(topLeft !== 0){
                        $.extend( cssObject, {'border-top-left-radius': topLeft} );
                    }
                    if(topRight !== 0){
                        $.extend( cssObject, {'border-top-right-radius': topRight} );
                    }
                    if(bottomRight !== 0){
                        $.extend( cssObject, {'border-bottom-right-radius': bottomRight} );
                    }
                    if(bottomLeft !== 0){
                        $.extend( cssObject, {'border-bottom-left-radius': bottomLeft} );
                    }
                }
            }
        } // if borderRadius active
        return cssObject;
    },
    displayCss: function(style){
        var cssObj = {
            'background': this.drawGradient(style),
            'border': this.border(style),
            'box-shadow': this.boxShadow(style)
        };

        $.extend(true, cssObj, this.borderRadius(style));
        return cssObj;
    },
    render: function(){
        $layer.css( this.displayCss(currentStyle) );
    }
};

================================================
FILE: js/gradienteditor.js
================================================
var gradienteditor = {
    callback: null,
    thisArg: null,
    changed: false,
    puff: null,
    gradientDimensions: null,
    gradientOffset: null,
    prevStops: null,
    currentGradient: null,
    currentPick: null,
    currentStopColor: null,
    currentPosition: null,
    currentColorField: null,
    tempStops: null,
    gradients: [
        {'name': "Black and White", 'stops': [[255, 255, 255], [0, 0, 0]] },
        {'name': "Plain Gray", 'stops': [[252, 252, 252], 23, [[242, 242, 242], 12], 89, [191, 191, 191]] },
        {'name': "Be Water", 'stops': [[209, 237, 233], 23, [[177, 228, 220], 12], 89, [0, 191, 162]] },
        {'name': "Rainbow", 'stops': [[255, 0, 0], [[255, 0, 255], 15], [[0, 0, 255], 33], [[0, 255, 255], 49], [[0, 255, 0], 67], [[255, 255, 0], 84], [255, 0, 0]] },
        {'name': "Teal, Magenta, Yellow", 'stops': [[255, 185, 13], [[204, 0, 69], 50], [0, 153, 128]] },
        {'name': "Peach", 'stops': [[242, 171, 43], [225, 123, 25]] },
        {'name': "Yellow, Orange", 'stops': [[255, 238, 88], [[252, 199, 54], 28], [[241, 141, 70], 67], [[233, 93, 59], 89], [228, 42, 50]] },
        {'name': "PS i love you", 'stops': [[22,127,232],[0,60,123]] },
        {'name': "Vista", 'stops': [[116,116,116], [[109,109,109], 50], [[126,126,126], 50], [133,133,133]]}
    ],
    edit: function(stops, callback, thisArg){
        var name = lang.Custom;
        this.callback = callback;
        this.thisArg = thisArg;
        this.prevStops = stops;
        // if the gradient is known, display its name
        for(var i=0, l=this.gradients.length; i<l; i++){
            if(this.gradients[i].stops === stops){
                name = this.gradients[i].name;
            }
        }
        // if the gradient is new, set changed to true to allow it to be stored
        if(name === lang.Custom) this.changed = true;
        this.setGradient({ name: name, stops: stops });
        nav.goTo(2);
    },
    picker: {
        init: function(color, position){
            this.color = color;
            this.position = position;
            this.$el = this.create();
            this.$colorField = this.$el.find('.color_field');
            return this.$el;
        },
        create: function(){
            $('<div class="picker bottom" />')
                .css({ 'left': position+'%' })
                .bind({
                    mousedown: $.proxy( this, "select" ),
                    dblclick: $.proxy( this, "pick" )
                })
                .append($('<div class="arrow" />'))
                .append($('<div class="box" />')
                    .append($('<div class="color_field" />').css({ 'background': tools.toColor(color) }))
                );
        },
        select: function(){
            // fire "unselect" event
            // show middlepoints
            // add active class to this one
            // show color and position below
            // add pick event listener to the colorField
            // add event listener to the input field to update the position
            // add event listener on "unselect" to unselect
        },
        blur: function(){
            // remove active class
            // hide middle points
            // remove "unselect" listener
        },
        pick: function(){
            colorpicker.pick(this.color, this.updateColor, this);
        },
        updateColor: function(newColor){
            var colorString = color.toColor(newColor);
            this.color = newColor;
            this.$stopColor.css("background", colorString);
            this.$colorField.css("background", colorString);
            // add color to stops
        },
        updatePosition: function(newPos){
            this.position = newPos;
            // update position at stops
        }
    },
    middlepoint: {
        threshhold: 5,
        position: null,
        percentage: null,
        init: function(position, percentage){
            this.position = position;
            this.percentage = percentage;
            this.$el = this.create();
            return this.$el;
        },
        create: function(){
            return $('<span class="middlepoint bottom"><span /></span>')
                .attr({
                    'data-percentage': this.percentage,
                })
                .css({ 'left': this.position+'%' })
                .bind(mousedown, $.proxy( this, "startMoving" ));
        },
        startMoving: function(event){
            event.preventDefault();
            this.select();
            gradienteditor.gradientOffset = gradienteditor.$gradient.offset();
            $(document).bind('mousemove.global', $.proxy(this, "move") );
            // add event listener to listen to input field changes
            // show percentage in the input field
        },
        move: function(event){
            
            // stay in the range of the previous and following step +/- 5 (min 5, max 95)
            // if position is 55-65 round to 50
            // update input field value
        },
        show: function(){
            this.$el.addClass('visible');
        },
        hide: function(){
            this.$el.removeClass('visible');
        },
        select: function(){
            this.$el.addClass('selected');
        },
        unselect: function(){
            this.$el.removeClass('selected');
        }
    },
    addPicker: function(position, rgb){
        return $('<div class="picker bottom" />')
            .css({ 'left': position+'%' })
            .attr({
                'data-color': JSON.stringify(rgb),
                'data-percentage': position
            })
            .bind({
                mousedown: $.proxy( this, "selectPicker" ),
                dblclick: $.proxy( this, "startPicking" )
            })
            .append($('<div class="arrow" />'))
            .append($('<div class="box" />')
                .append($('<div class="color_field" />').css({ 'background': tools.toColor(rgb) }))
            );
    },
    selectPicker: function(event){
        event.preventDefault();
        var obj = $(event.target).parents('.picker');
        this.selectStop(obj);
        this.showMiddlepoints(obj);
        this.gradientOffset = this.$gradient.offset();
        this.extract();
        $(document).bind('mousemove.global', $.proxy(this, "movePicker") );
        $(document).one('mouseup', $.proxy(this, "stopPicking") );
    },
    startPicking: function(event){
        event.preventDefault();
        colorpicker.pick(this.currentStopColor, this.updatePicker, this);
    },
    stopPicking: function(){
        if(this.changed){
            this.currentPick.attr('data-percentage', this.currentPercentage);
        }
    },
    extract: function(){
        this.tempStops = this.expand( $.extend(true, [], this.currentGradient.stops) );
        this.tempStops.splice(this.currentPosition,1);
    },
    inject: function(percentage){
        if(this._percentage === undefined || percentage !== this._percentage){
            var injectedStops = $.extend(true, [], this.tempStops),
                pos = injectedStops.length,
                stop = [this.currentStopColor, percentage];

            for(var i = 0, l = injectedStops.length; i<l; i++){
                var tempStop = injectedStops[i];
                if(typeof tempStop === 'object' && tempStop[1] > percentage){
                    pos = i;
                    break;
                }
            }
            injectedStops.splice(pos, 0, stop);
            this.updateGradient( this.shrink(injectedStops) );
            this._percentage = percentage;
        }
    },
    expand: function(stops){
        var last = stops.length-1;
        if(stops[0].length === 3) stops[0] = [stops[0], 0];
        if(stops[last].length === 3) stops[last] = [stops[last], 100];
        return stops;
    },
    shrink: function(stops){
        var last = stops.length-1;
        if(stops[0][1] === 0) stops[0] = stops[0][0];
        if(stops[last][1] === 100) stops[last] = stops[last][0];
        return stops;
    },
    getArrayPos: function(percentage, stops){
        for(var i = 0, l = stops.length; i<l; i++){
            var stop = stops[i];
            if(typeof stop === 'object'){
                if(percentage === 0 || percentage === 100){
                    return percentage === 0 ? 0 : l-1;
                }
                if(stop[1] === percentage){
                    return i;
                }
            }
        }
    },
    movePicker: function(event){
        event.preventDefault();
        var x = Math.max(0, Math.min(this.gradientDimensions.width, event.pageX-this.gradientOffset.left)),
            y = 33,
            percentage = Math.round(x/this.gradientDimensions.width*100);
        if( // out of range - remove gesture
            event.pageX < (this.gradientOffset.left - 26) ||
            event.pageX > (this.gradientOffset.left + this.gradientDimensions.width + 26) ||
            event.pageY < (this.gradientOffset.top - 26) ||
            event.pageY > (this.gradientOffset.top + this.gradientDimensions.height + 69) ){
                // more than 2 color stops 
                if(!this._hasMinimumSize){
                    x = event.pageX - this.gradientOffset.left;
                    y = event.pageY - this.gradientOffset.top;
                
                    if (this.puff === null) {
                        this.puff = $('<div id="puff" />').appendTo($body);
                        $(document).bind('mouseup.puff', $.proxy( this, "removeCurrentPicker" ));
                    }
                    this.puff.css({ 'left': event.pageX+2, 'top': event.pageY+16 });
                    this.updateGradient( this.shrink(this.tempStops) );
                }    
        }
        else {
            // move picker
            this.currentPercentage = percentage;
            this.$stopLocation.val(percentage);
            this.inject(percentage);
            
            if(!this.changed){
                this.$gradientName.val(lang.Custom);
                this.changed = true;
            };
            
            if(this.puff != null){
                $(document).unbind('mouseup.puff');
                $('#puff').remove();
                this.puff = null;
            }
        }
        
        $(this.currentPick).css({ 'left': x+'px', 'top': y+'px' });
    },
    removeCurrentPicker: function(event){
        this.puff = null;
        $('#puff').remove();
        $(this).unbind(event);
    },
    updatePicker: function(newColor){
        var colorString, stops;
        // newColor RGB-{Array}
        if(!this.changed){
            this.$gradientName.val(lang.Custom);
            this.changed = true;
        };
        colorString = tools.toColor(newColor);
        $(this.currentPick).attr('data-color', JSON.stringify(newColor));
        this.currentColorField.css("background", colorString);
        this.$stopColor.css("background", colorString);
        stops = gradienteditor.currentGradient.stops;
        // search for the position and inject new color
        if(this.currentPosition > 0 && this.currentPosition < stops.length-1){
            stops[this.currentPosition][1] = newColor;
        }
        else {
            stops[this.currentPosition] = newColor;
        }
        this.updateGradient(stops);
    },
    addMiddlepoint: function(position, realpos){
        return $('<span class="middlepoint bottom"><span /></span>')
            .attr({
                'data-percentage': realpos,
            })
            .css({ 'left': position+'%' })
            .bind({
                mousedown: function(e){ 
                    gradienteditor.selectStop(this);
                    //gradienteditor.selectMiddlePoint(this);
                }
            });
    },
    updateGradient: function(stops){
        gradienteditor.currentGradient.stops = stops;
        this.$gradient.css('background', css.cssGradient( stops, 0, "linear" ));
        if(gradienteditor.callback) gradienteditor.callback.call(gradienteditor.thisArg, stops);
    },
    setGradient: function(gradient){
        this.hideStop();
        this.currentGradient = $.extend(true, [], gradient);
        this.$gradient.css('background', css.cssGradient( this.currentGradient.stops, 0, "linear" ));
        this.$gradientName.val(this.currentGradient.name);
        this.$gradient.children().remove();
        var helpers = $('<div/>');
        for(var i=0,length = this.currentGradient.stops.length; i<length; i++){
            var stop = this.currentGradient.stops[i];
            var pos, color;
            switch(typeof stop){
            case 'object': // => [255,255,255] or [[255,255,255], 33]
                if(stop.length === 3){ // => [255,255,255]
                    color = stop;
                    pos = i === 0 ? 0 : 100;
                }
                else {
                    color = stop[0];
                    pos = stop[1];                  
                }
                helpers.append( this.addPicker(pos, color) );
                if(typeof this.currentGradient.stops[i+1] !== 'number' && i != length-1){
                    var nextStop = this.currentGradient.stops[i+1];
                    var nextPos = nextStop.length !== 3 ? nextStop[1] : 100;
                    helpers.append( this.addMiddlepoint(tools.getCenter(pos, nextPos), 50) );
                }
                break;
            case 'number':
                var middlepoint = tools.getMiddlepoint(this.currentGradient.stops[i-1], stop, this.currentGradient.stops[i+1]);
                helpers.append( this.addMiddlepoint(middlepoint[1], middlepoint[1]) );
                break;
              }
        }
        this.$gradient.append(helpers);
    },
    addGradientPreset: function(name, stops){
        var preset = $('<div class="swatch" />')
                .attr({'title': name})
                .css({
                    'background': css.cssGradient( stops, 135, "linear" )
                })
                .bind('click', $.proxy( this, "handlePreset" ))
         return preset.get(0);
    },
    handlePreset: function(e){
        e.stopPropagation();
        // find out the gradients position in the gradient array
        var family = $(e.target).parent().children();
        var pos = family.index(e.target);
        // if alt is pressed while clicking: remove gradient
        if(e.altKey){
            // slice out the gradient from the gradient array (method by John Resig)
            var rest = this.gradients.slice(pos + 1);
            this.gradients.length = pos;
            this.gradients.push.apply(this.gradients, rest);
            localStorage["gradients"] = JSON.stringify(this.gradients);
            $(e.target).remove();
        }
        else {
            // else get the gradient
            this.setGradient(this.gradients[pos]);
            this.updateGradient(this.gradients[pos].stops);
           }
    },
    showStop: function(pos, color){
        this.$stopLocation.prop("disabled", false).val(pos).parent().removeClass("disabled");
        if (color !== null) {
            if(!this._hasMinimumSize) this.$removeStop.prop("disabled", false);
            this.$stopColor.css({'background-color': color}).parent().removeClass("disabled");
            this.$stopColor.bind('mousedown', $.proxy( this, "startPicking" ));
        }
        else {
            this.$removeStop.prop("disabled", true);
            this.$stopColor.css({'background-color': 'transparent'}).parent().addClass("disabled");
        }
    },
    updateStopColor: function(color){
        this.$stopColor.css({'background-color': color});
    },
    hideStop: function(){
        this.$removeStop.prop("disabled", true);
        this.$stopLocation.prop("disabled", true).val("").parent().addClass("disabled");
        this.$stopColor.css({'background-color': 'transparent'}).parent().addClass("disabled");
    },
    selectStop: function(object){
        var $o = $(object), color;
        this.currentPick = $o;
        this.currentPercentage = parseInt($o.attr('data-percentage'), 10);
        this.currentPosition = this.getArrayPos(this.currentPercentage, this.currentGradient.stops);
        this.currentColorField = $o.find('.color_field');
        color = $o.attr('data-color');
        this.currentStopColor = color ? JSON.parse(color) : null;
        this._hasMinimumSize = this.currentGradient.stops.length == 2 ? true : false;
        this.showStop(this.currentPercentage, this.currentStopColor);
        $o.siblings().removeClass('selected');
        $o.addClass('selected');
    },
    showMiddlepoints: function(object){
        $(object).siblings('span').removeClass('visible');
        $(object).next('span').add($(object).prev('span')).addClass('visible');
    },
    cancelAction: function(){
        gradienteditor.updateGradient(gradienteditor.prevStops);
        nav.goTo(1);
    },
    okAction: function(){
        nav.goTo(1);
    },
    newAction: function(){
        if(this.changed){
            var newGradient = {
                'name': this.$gradientName.val(),
                'stops': this.currentGradient.stops
            };
            this.gradients.push(newGradient);
            this.renderPresets([newGradient]);
            localStorage["gradients"] = JSON.stringify(this.gradients);
            this.changed = false;
        };
    },
    renderPresets: function(gradients){
        var presets = document.createDocumentFragment();
        for(var i = 0, length = gradients.length; i<length; i++){
            presets.appendChild( this.addGradientPreset(gradients[i].name, gradients[i].stops) );
        }
        this.$gradientPresets.append(presets);
    },
    init: function(){
        this.$o = $('#gradient_editor');
        this.$gradientPresets = $('#gradient_presets');
        this.$gradientName = $('#gradient_name');
        this.$gradientHolder = $('#gradient_holder');
        this.$gradient = $('#gradient');
        this.$stopColor = $('#stop_color');
        this.$stopLocation = $('#stop_location');
        this.$removeStop = $('#remove_stop');
        this.$okButton = $('#gradient_ok');
        this.$cancelButton = $('#gradient_cancel');
        this.$newButton = $('#gradient_new');
        
        if(localStorage["gradients"]) this.gradients = JSON.parse(localStorage["gradients"]);
        this.currentGradient = this.gradients[0];
        this.setGradient(this.currentGradient);
        // draw gradient presets
        this.renderPresets(this.gradients);
        
        this.$removeStop.click( $.proxy( this, "removeCurrentPicker") );
        this.$cancelButton.click( $.proxy( this, "cancelAction" ) );
        this.$okButton.click( $.proxy( this, "okAction" ) );
        this.$newButton.click( $.proxy( this, "newAction" ) );
        this.$gradientName.mousedown( function(e){ e.stopPropagation(); });
        this.$stopLocation.bind({
            mousedown: function(e){ e.stopPropagation(); },
            focus: function(e){ numbers.initNumberField(this, 'style'); },
            keydown: numbers.restrictCharacters,
            keyup: numbers.keyUp,
            blur: numbers.validateInput
        });
        
        this.gradientDimensions = { 'width': this.$gradient.width(), 'height': this.$gradient.height() };
    }
};

================================================
FILE: js/localization.js
================================================
var localization = {
        en: {
            "Color": "Color",
            "Opacity": "Opacity",
            "Angle": "Angle",
            "Distance": "Distance",
            "Spread": "Spread",
            "Size": "Size",
            "DropShadow": "Drop Shadow",
            "InnerShadow": "Inner Shadow",
            "Background": "Background",
            "Border": "Border",
            "new": "new",
            "current": "current",
            "PickAColor": "Pick a Color",
            "GradientEditor": "Gradient Editor",
            "Ok": "Ok",
            "Cancel": "Cancel",
            "NewStyle": "New Style",
            "ColorSwatchName": "Color Swatch Name",
            "ClosestValueInserted": "Closest value inserted",
            "AnIntegerBetween": "An integer between",
            "and": "and",
            "isRequired": "is required",
            "Custom": "Custom",
            "DeleteStyle": "Delete Style"
        },
        de: {
            "Color": "Farbe",
            "Opacity": "Transparenz",
            "Angle": "Winkel",
            "Distance": "Abstand",
            "Spread": "Umfang",
            "Size": "Größe",
            "DropShadow": "Schlagschatten",
            "InnerShadow": "Innerer Schatten",
            "Background": "Hintergrund",
            "Border": "Rahmen",
            "new": "neu",
            "current": "momentan",
            "PickAColor": "Wähl eine Farbe",
            "GradientEditor": "Verlaufs Editor",
            "Ok": "Ok",
            "Cancel": "Abbrechen",
            "NewStyle": "Neuer Style",
            "ColorSwatchName": "Farbfeld Name",
            "ClosestValueInserted": "Naheliegendste Zahl eingesetzt",
            "AnIntegerBetween": "Eine Zahl zwischen",
            "and": "und",
            "isRequired": "wird benötigt",
            "Custom": "Unbekannt",
            "DeleteStyle": "Style löschen"
        }
}

================================================
FILE: js/numbers.js
================================================
var numbers = {
    regex: new RegExp(''),
    min: 0,
    max: 0,
    temporaryMode: "",
    match: false,
    pressed: false,
    speed: 0,
    value: "",
    type: "",
    direction: 0,
    DIGITS: /[-1234567890]/g,
    HEXCODE: /[A-Fa-f0-9]/g,
    // control Keys: 8 = backspace, 9 = tab, 13 = enter, 35 = home, 37 = left, 38 = top, 39 = right, 40 = down
    controlKeys: [ 8, 9, 13, 35, 36, 37, 38, 39, 40 ],
    // cut, copy & paste keys are 67 = c, 86 = v and 88 = x additional 65 = a ('select all')
    cutCopyPasteKeys: [ 65, 67, 86, 88 ],
    numpadKeys: { 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9" },
    initNumberField: function(input, type) {
        numbers.type = type;
        numbers.$input = $(input);
        numbers.max = numbers.$input.attr('data-max');
        numbers.min = numbers.$input.attr('data-min');
        numbers.restrict = numbers.DIGITS;
        numbers.temporaryMode = numbers.$input.attr('id');
        switch (numbers.max) {
        case "10": // 0-10
            numbers.regex.compile("^(0|([1-9]{1}|10))$");
            break;
        case "100": // 0-100
            numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|100))$");
            break;
        case "200": // 0-200
            numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|[1]{1}[0-9]{0,2}|200))$");
            break;
        case "255": // 0-255
            numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|[1]{1}[0-9]{0,2}|[2]{1}([0-4]{1}[0-9]{1}|[5]{1}[0-5]{1})))$");
            break;
        case "360": // 0-360
            numbers.regex.compile("^(0|([1-9]{1}[0-9]{0,1}|[1-2]{1}[0-9]{0,2}|[3]{1}([0-5]{1}[0-9]{1}|[6]{1}[0]{1})))$");
            break;
        }
    },
    initHexField: function(input, type) {
        numbers.type = type;
        numbers.$input = $(input);
        numbers.temporaryMode = numbers.$input.attr('id');
        numbers.regex.compile("^([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$");
        numbers.restrict = numbers.HEXCODE;
    },
    keyUp: function(event) {
        var keycode;
        if (event.keyCode) {
            keycode = event.keyCode;
        } 
        else if (event.which) {
            keycode = event.which;
        }
        clearTimeout(numbers.timeout);
        numbers.value = numbers.$input.val();
        if(numbers.regex.test(numbers.value)){
            numbers.match = true;
            if(!numbers.pressed){
                numbers.updateField();
            } else {
                numbers.pressed = false;
            }
        }
        if(keycode === 91){
            numbers.commandKeyPressed = false;
        }
    },
    updateField: function() {
        switch(numbers.type){
        case 'color':
            if (numbers.match && numbers.value !== "") colorpicker.update(numbers.temporaryMode);
            break;
        case 'style':
            if (numbers.value !== "") numbers.$input.change();
            break;
        }
    },
    restrictCharacters: function(event) {
        var keycode, character, isControlKey, isCopyCutPasteKey;
        // future:
        // - allow copy & paste shortcuts ('windows/apple': 91, 'v': 86, 'c': 67, 'x': 88)
        //      set boolean for 91 - next click: check for boolean and set false
        //   oh - on windows it's strg+c and strg+v (check ctrlKey)
        //
        // - allowe to paste hexcodes including a '#' at the beginning: slice it out
        numbers.value = numbers.$input.val();
        if (event.keyCode) {
            keycode = event.keyCode;
        } 
        else if (event.which) {
            keycode = event.which;
        }
        // if pressed key is a numeric pad key use the numpad map object to detect its number
        if(keycode >= 96 && keycode <= 105){
            character = numbers.numpadKeys[keycode];
        } else {
            character = String.fromCharCode(keycode);
        }
        if(numbers.commandKeyPressed){
            isCopyCutPasteKey = numbers.copyCutPasteKeys.join(",").match(new RegExp(keycode));
            if(isCopyCutPasteKey){
                return true;
            }
        }
        if(keycode === 91) {
            numbers.commandKeyPressed = true;
            return false;
        }
        // 1 for key up (keycode 38), -1 for key down (keycode 40), 0 for other keys
        numbers.direction = 0;
        switch(keycode){
            case 38: numbers.direction = 1; break;
            case 40: numbers.direction = -1; break;
        }
        if (numbers.direction !== 0 && numbers.restrict === numbers.DIGITS) {
            numbers.accelerate();
            return false;
        }
        else {
            isControlKey = numbers.controlKeys.join(",").match(new RegExp(keycode));
            if (isControlKey) {
                return true;
            }
            else if (character.match(numbers.restrict)) {
                numbers.value += character;
                return true;
            }
            event.preventDefault();
            return false;
        }
    },
    accelerate: function() {
        if(numbers.timeout) clearTimeout(numbers.timeout);
        if(numbers.value === '') {
            numbers.value = 0;
        }
        var number = parseInt(numbers.value, 10);
        number += numbers.direction;
        number = Math.max(numbers.min, Math.min(numbers.max, number));
        if('-'+numbers.max === numbers.min) { // as in angle from -180 to 180
            if(number === numbers.min) number = numbers.max;
            else if(number === numbers.max) number = numbers.min;
        }
        numbers.$input.val(number);
        numbers.value = number;
        numbers.updateField();
        if(!numbers.pressed){
            numbers.speed = 500;
            numbers.pressed = true;
        }
        else {
            numbers.speed = 150;
        }
        numbers.timeout = setTimeout(function(){ jQuery.proxy(numbers, "accelerate") }, numbers.speed);
    },
    validateInput: function(event) {
        var integer, errorString, nearestInt;
        numbers.value = numbers.$input.val();
        integer = parseInt(numbers.value, 10);
        if(numbers.regex.test(integer)){
            console.log(integer);
            numbers.$input.val(integer ? integer : "");
            return true;
        }
        event.preventDefault();
        errorString = lang.AnIntegerBetween+" "+ numbers.min +" "+lang.and+" "+ numbers.max +" "+lang.isRequired+". "+lang.ClosestValueInserted+".";
        alert(errorString);
        nearestInt = Math.abs(numbers.max - integer) < Math.abs(numbers.min - integer) ? numbers.max : numbers.min;
        numbers.$input.val(nearestInt).focus().change();
    }
};

================================================
FILE: js/style.js
================================================
var style = {
    background: {
        elements: {
            ".opacity": { name: "opacity", handle: "slider" },
            ".gradientField": "gradientField",
            ".reverse": "reverse",
            ".angle": { name: "angle", handle: "pot" },
            ".globalLight": "globalLight"
        },
        $styles: $('#background_style'),
        init: function(el){
            this.$el = $("#"+el);
            this.selector = el;
            this.$menuItem = $('.nav-'+el);
            this.$checkbox = this.$menuItem.find('input[type=checkbox]');
            this.$inputs = this.$el.find('input[type=text]');
            this.initElements();
            this.updateStops();
            this.$gradientField.click( $.proxy( this, "edit" ) );
            this.$reverse.change( $.proxy( this, "switchReverse" ) );
            this.$globalLight.click( $.proxy( this, "switchLight" ) );
            this.$checkbox.click( $.proxy( this, "check" ) );
            this.$menuItem.click( $.proxy( this, "select" ) );
            this.$styles.change( $.proxy( this, "updateStyle" ) );
            $(document).bind('styleChange', $.proxy( this, "populateInputs" ));
        },
        initElements: function(){
            for (var key in this.elements) {
                var el = this.elements[key];
                if(typeof el === 'object'){
                    this["$"+el.name] = $(key, this.$el);
                    switch(el.handle){
                        case "slider":
                            this[el.name+"Slider"] = Object.create(slider);
                            this[el.name+"Slider"].init(this.selector, el.name);
                            break;
                        case "pot":
                            this[el.name+"Pot"] = Object.create(pot);
                            this[el.name+"Pot"].init(this.selector);
                            break;
                    }
                } else {
                    this["$"+el] = $(key, this.$el);
                }
            }
        },
        populateInputs: function(){
            this.setActive();
            this.opacitySlider.update(currentStyle[this.selector].opacity);
            this.updateStops();
            this.setReverse();
            this.displayStyle();
            this.setLight();
        },
        select: function(){
            if(!currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = true;
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
                this.paint();
            }
        },
        check: function(e){
            e.stopPropagation();
            if(currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = false;
            } else {    
                currentStyle[this.selector].isActive = true;
            }    
            this.setActive();
            this.paint();
        },
        setActive: function(){
            if(currentStyle[this.selector].isActive){
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
            } else {    
                this.$checkbox.prop('checked', false);
                this.$el.addClass('inactive');
                this.$inputs.prop('disabled', true);
            }
        },
        edit: function(){
            gradienteditor.edit(currentStyle[this.selector].stops, this.updateStops, this);
        },
        setReverse: function(){
            if(currentStyle[this.selector].isReverse){
                this.$reverse.prop('checked', true);
            } else {    
                this.$reverse.prop('checked', false);
            }    
            this.updateStops();
            this.paint();
        },
        switchReverse: function(){
            if(currentStyle[this.selector].isReverse){
                currentStyle[this.selector].isReverse = false;
            } else {    
                currentStyle[this.selector].isReverse = true;
            }
            this.setReverse();
        },
        setLight: function(){
            if(currentStyle[this.selector].hasGlobalLight){
                this.$globalLight.prop('checked', true);
                this.anglePot.update(currentStyle.globalAngle);
            } else {
                this.$globalLight.prop('checked', false);
                this.anglePot.update(currentStyle[this.selector].angle);
            }    
        },
        switchLight: function(){
            if(currentStyle[this.selector].hasGlobalLight){
                currentStyle[this.selector].hasGlobalLight = false;
            } else {
                currentStyle[this.selector].hasGlobalLight = true;
            }
            this.setLight();
            this.paint();
        },
        updateStyle: function(){
            currentStyle[this.selector].style = this.$styles.val();
            this.paint();
        },
        displayStyle: function(){
            this.$styles.val(currentStyle[this.selector].style);
        },
        updateStops: function(stops){
            if(stops){
                currentStyle[this.selector].stops = stops;
                currentStyle[this.selector].translucidStops = $.extend(true, [], stops);
                this.paint();
            }
            this.$gradientField.css('background', css.cssGradient( currentStyle[this.selector].stops, currentStyle[this.selector].isReverse ? 180 : 0, "linear" ));
        },
        paint: function(){
            $(document).trigger('paint');
        }
    },
    shadow: {
        elements: {
            ".opacity": { name: "opacity", handle: "slider" },
            ".color_field": "color",
            ".angle": { name: "angle", handle: "pot" },
            ".globalLight": "globalLight",
            ".distance": { name: "distance", handle: "slider" },
            ".blur": { name: "blur", handle: "slider" },
            ".size": { name: "size", handle: "slider" }
        },
        init: function(el){
            this.$el = $("#"+el);
            this.selector = el;
            this.$menuItem = $('.nav-'+el);
            this.$checkbox = this.$menuItem.find('input[type=checkbox]');
            this.$inputs = this.$el.find('input[type=text]');
            this.initElements();
            this.updateColor();
            this.$color.click( $.proxy( this, "pick" ) );
            this.$checkbox.click( $.proxy( this, "check" ) );
            this.$menuItem.click( $.proxy( this, "select" ) );
            this.$globalLight.click( $.proxy( this, "switchLight" ) );
            $(document).bind('styleChange', $.proxy( this, "populateInputs" ));
        },
        initElements: function(){
            for (var key in this.elements) {
                var el = this.elements[key];
                if(typeof el === 'object'){
                    this["$"+el.name] = $(key, this.$el);
                    switch(el.handle){
                        case "slider":
                            this[el.name+"Slider"] = Object.create(slider);
                            this[el.name+"Slider"].init(this.selector, el.name);
                            //if(el.autoUpdate) currentStyle[this.selector].__defineSetter__( el.name , $.proxy( this[el.name+"Slider"], "set" ) );
                            break;
                        case "pot":
                            this[el.name+"Pot"] = Object.create(pot);
                            this[el.name+"Pot"].init(this.selector);
                            break;
                    }
                } else {
                    this["$"+el] = $(key, this.$el);
                }
            }
        },
        populateInputs: function(){
            this.setActive();
            this.updateColor();
            this.opacitySlider.update(currentStyle[this.selector].opacity);
            this.distanceSlider.update(currentStyle[this.selector].distance);
            this.blurSlider.update(currentStyle[this.selector].blur);
            this.sizeSlider.update(currentStyle[this.selector].size);
            this.setLight();
        },
        select: function(){
            if(!currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = true;
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
                this.paint();
            }
        },
        check: function(e){
            e.stopPropagation();
            if(currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = false;
            } else {    
                currentStyle[this.selector].isActive = true;
            }    
            this.setActive();
            this.paint();
        },
        setActive: function(){
            if(currentStyle[this.selector].isActive){
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
            } else {    
                this.$checkbox.prop('checked', false);
                this.$el.addClass('inactive');
                this.$inputs.prop('disabled', true);
            }
        },
        pick: function(){
            colorpicker.pick(currentStyle[this.selector].color, this.updateColor, this);
        },
        setLight: function(){
            if(currentStyle[this.selector].hasGlobalLight){
                this.$globalLight.prop('checked', true);
                this.anglePot.update(currentStyle.globalAngle);
            } else {
                this.$globalLight.prop('checked', false);
                this.anglePot.update(currentStyle[this.selector].angle);
            }
        },
        switchLight: function(){
            if(currentStyle[this.selector].hasGlobalLight){
                currentStyle[this.selector].hasGlobalLight = false;
            } else {
                currentStyle[this.selector].hasGlobalLight = true;
            }
            this.setLight();    
            this.paint();
        },
        updateColor: function(currentColor){
            if(currentColor){
                currentStyle[this.selector].color = currentColor;
                this.paint();
            }
            this.$color.css('background', '#'+color.hexFromRgb(currentStyle[this.selector].color));
        },
        paint: function(){
            $(document).trigger('paint');
        }
    },
    border: {
        elements: {
            ".color_field": "color",
            ".opacity": { name: "opacity", handle: "slider" },
            ".size": { name: "size", handle: "slider" }
        },
        $styles: $('#border_styles').find('> div'),
        init: function(el){
            this.$el = $("#"+el);
            this.selector = el;
            this.$menuItem = $('.nav-'+el);
            this.$checkbox = this.$menuItem.find('input[type=checkbox]');
            this.$inputs = this.$el.find('input[type=text]');
            this.initElements();
            this.updateColor();
            this.$color.click( $.proxy( this, "pick" ) );
            this.$checkbox.click( $.proxy( this, "check" ) );
            this.$menuItem.click( $.proxy( this, "select" ) );
            this.$styles.click( $.proxy( this, "updateStyle" ) );
            $(document).bind('styleChange', $.proxy( this, "populateInputs" ));
        },
        initElements: function(){
            for (var key in this.elements) {
                var el = this.elements[key];
                if(typeof el === 'object'){
                    this["$"+el.name] = $(key, this.$el);
                    switch(el.handle){
                        case "slider":
                            this[el.name+"Slider"] = Object.create(slider);
                            this[el.name+"Slider"].init(this.selector, el.name);
                            break;
                        case "pot":
                            this[el.name+"Pot"] = Object.create(pot);
                            this[el.name+"Pot"].init(this.selector);
                            break;
                    }
                } else {
                    this["$"+el] = $(key, this.$el);
                }
            }
        },
        populateInputs: function(){
            this.setActive();
            this.updateColor();
            this.opacitySlider.update(currentStyle[this.selector].opacity);
            this.sizeSlider.update(currentStyle[this.selector].size);
            this.setStyle();
        },
        select: function(){
            if(!currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = true;
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
                this.paint();
            }
        },
        check: function(e){
            e.stopPropagation();
            if(currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = false;
            } else {    
                currentStyle[this.selector].isActive = true;
            }    
            this.setActive();
            this.paint();
        },
        setActive: function(){
            if(currentStyle[this.selector].isActive){
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
            } else {    
                this.$checkbox.prop('checked', false);
                this.$el.addClass('inactive');
                this.$inputs.prop('disabled', true);
            }
        },
        pick: function(){
            colorpicker.pick(currentStyle[this.selector].color, this.updateColor, this);
        },
        setStyle: function(){
            for(var i=0, l=this.$styles.length; i<l; i++){
                if(this.$styles.eq(i).data('style') === currentStyle[this.selector].style){
                    this.updateStyle(null, this.$styles.eq(i));
                    return false;
                }    
            }
        },
        updateStyle: function(event, setStyle){
            var obj = $(setStyle || event.target);
            this.$styles.removeClass('active');
            obj.addClass('active');
            currentStyle[this.selector].style = obj.data('style');
            this.paint();
        },
        updateColor: function(currentColor){
            if(currentColor){
                currentStyle[this.selector].color = currentColor;
                this.paint();
            }
            this.$color.css('background', '#'+color.hexFromRgb(currentStyle[this.selector].color));
        },
        paint: function(){
            $(document).trigger('paint');
        }
    },
    borderRadius: {
        $pixel: $('#border_radius_pixel'),
        $percent: $('#border_radius_percent'),
        $preview: $('#border_radius_preview'),
        $topLeft: $('#topLeft'),
        $topRight: $('#topRight'),
        $bottomLeft: $('#bottomLeft'),
        $bottomRight: $('#bottomRight'),
        maxRadius: 200,
        init: function(el){
            this.$el = $("#"+el);
            this.selector = el;
            this.$menuItem = $('.nav-'+el);
            this.$checkbox = this.$menuItem.find('input[type=checkbox]');
            this.$inputs = this.$el.find('input[type=text]');
            this.$radius = $('.radius', this.$el);
            this.radiusSlider = Object.create(slider);
            this.radiusSlider.init(this.selector, "radius");
            this.$checkbox.click( $.proxy( this, "check" ) );
            this.$menuItem.click( $.proxy( this, "select" ) );
            this.$pixel.add(this.$percent).click( $.proxy( this, "updateUnit" ) );
            this.$preview.mousedown( $.proxy( this, "startSelection" ) );
            this.$fields = this.$preview.children();
            $(document).bind('styleChange', $.proxy( this, "populateInputs" ));
        },
        populateInputs: function(){
            this.setActive();
            currentStyle[this.selector].radius = 0;
            currentStyle[this.selector].__defineSetter__( "radius", $.proxy( this, "updateRadius" ) );
        },
        select: function(){
            if(!currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = true;
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
                this.paint();
            }
        },
        check: function(e){
            e.stopPropagation();
            if(currentStyle[this.selector].isActive){
                currentStyle[this.selector].isActive = false;
            } else {    
                currentStyle[this.selector].isActive = true;
            }    
            this.setActive();
            this.paint();
        },
        setActive: function(){
            if(currentStyle[this.selector].isActive){
                this.$checkbox.prop('checked', true);
                this.$el.removeClass('inactive');
                this.$inputs.prop('disabled', false);
            } else {    
                this.$checkbox.prop('checked', false);
                this.$el.addClass('inactive');
                this.$inputs.prop('disabled', true);
            }
        },
        startSelection: function(event){
            $(document).bind('mousemove.global', $.proxy( this, "updateSelection" ) );
            this.currentTarget = event.target;
            $(event.target).toggleClass("active");
            $(document).one('mouseup', $.proxy( this, "setSelection" ) );
        },
        updateSelection: function(event){
            if(event.target != this.currentTarget){
                $(event.target).toggleClass("active");
                this.currentTarget = event.target;
            }
        },
        updateRadius: function(value){
            for(var i=0; i<4; i++){
                if(currentStyle[this.selector].isSelected[i]){ 
                    currentStyle[this.selector].radii[i] = currentStyle[this.selector].hasPercentage[i] ? [value, "%"] : [value, "px"];
                }
            }
            this.paint();
        },
        setSelection: function(e){
            var value, sum = 0, amount = 0, average = 0, equal = false;
            for(var i=0; i<4; i++){
                if(this.$fields.eq(i).hasClass("active")){ 
                    currentStyle[this.selector].isSelected[i] = true;
                    // count the sum of all radii
                    value = parseInt(currentStyle[this.selector].radii[i][0], 10);
                    sum+=value;
                    amount++;
                    if(sum/amount === value){
                        equal = true;
                    } else {
                        equal = false;
                    }
                } else {
                    currentStyle[this.selector].isSelected[i] = false;
                }
            }
            // set radius value (average) but don't set css
            average = amount === 0 ? 0 : Math.floor(sum/amount);
            value = equal ? average : 0;
            this.radiusSlider.set(value);
            this.radiusSlider.move(this.radiusSlider.toPos(value));
        },
        updateUnit: function(event){
            var $el = $(event.target), average, sum = 0, amount = 0;
            switch($el.attr('data-unit')){
                case "%":
                    for(var i=0; i<4; i++){
                        if(currentStyle[this.selector].isSelected[i]){
                            var radius = currentStyle[this.selector].radii[i][0];
                            // recalculate value from pixel to percent and limit to 50
                            var value = Math.floor(Math.min(50, radius*100/currentStyle.height)); // height or width?
                            currentStyle[this.selector].radii[i] = [value, "%"];
                            currentStyle[this.selector].hasPercentage[i] = true;
                            sum += value;
                            amount++;
                        }
                    }
                    // limit slider to 50
                    this.radiusSlider.max = 50;
                    // uncheck pixel button
                    this.$pixel.removeClass("active");
                    break;
                case "px":
                    for(var i=0; i<4; i++){
                        if(currentStyle[this.selector].isSelected[i]){
                            var radius = currentStyle[this.selector].radii[i][0];
                            // recalculate value from percent to pixel and limit to maxRadius
                            var value = Math.floor(Math.min(currentStyle[this.selector].maxRadius, radius*currentStyle.height/100)); // height or width?
                            currentStyle[this.selector].radii[i] = [value, "px"];
                            currentStyle[this.selector].hasPercentage[i] = false;
                            sum += value;
                            amount++;
                        }
                    }
                    // reset limit
                    this.radiusSlider.max = this.maxRadius;
                    // uncheck percent button
                    this.$percent.removeClass("active");
                    break;
            }
            average = Math.floor(sum/amount);
            // update input value to the average value and trigger change() to adjust the slider
            this.radiusSlider.set(average);
            this.radiusSlider.move(this.radiusSlider.toPos(average));
            $el.addClass("active");
            this.paint();
        },
        paint: function(){
            $(document).trigger('paint');
        }
    },
    init: function(){
        this.background.init("background");
        
        this.dropShadow = Object.create(style.shadow);
        this.dropShadow.init("dropShadow");
        
        this.innerShadow = Object.create(style.shadow);
        this.innerShadow.init("innerShadow");
        
        this.border.init("border");
        
        this.borderRadius.init("borderRadius");
    }
};

================================================
FILE: js/styleStore.js
================================================
var styleStore = {
    styles: [
        { 
            name: "Default Style", 
            style: { }
        },
        { 
            name: "Inset Box", 
            style: {
                dropShadow: { color: [255,255,255], opacity: 100, blur: 0 },
                innerShadow: { color: [0,0,0], opacity: 40, blur: 7 },
                background: { stops: [[191, 191, 191], 11, [[242, 242, 242], 88], 77, [252, 252, 252]], reverse: true }
            }
        },
        {
            name: "Vista Inset Box",
            style: {
                dropShadow: { color: [255,255,255], opacity: 50, blur: 0 },
                innerShadow: { color: [0,0,0], opacity: 40, blur: 7 },
                background: { stops: [[116,116,116], [[109,109,109], 50], [[126,126,126], 50], [133,133,133]] },
                border: { isActive: false },
                borderRadius: { radii: [[10, "px"],[10, "px"],[10, "px"],[10, "px"]] }
            }
        },
        {
            name: "Hello Red",
            style: {
                dropShadow: { color: [255,255,255], opacity: 14, blur: 0 },
                innerShadow: { color: [255,255,255], opacity: 21 },
                background: { stops: [[213,87,91], [196,48,51]] },
                border: { color: [168,0,2] },
                borderRadius: { radii: [[5, "px"],[5, "px"],[5, "px"],[5, "px"]] }
            }
        },
        { 
            name: "Orange Box", 
            style: {
                dropShadow: { isActive: false },
                innerShadow: { color: [249,169,88], distance: 0, size: 1 },
                background: { stops: [[255, 225, 173], 42, [[250, 169, 28], 12], 91, [217, 97, 4]] },
                border: { color: [153,102,52] },
                borderRadius: { radii: [[2, "px"],[2, "px"],[2, "px"],[2, "px"]] }
            }
        },
        {
            name: "Apple Promo Box",
            style: {
                dropShadow: { color: [0,0,0], opacity: 40, blur: 3 },
                innerShadow: { color: [255,255,255], opacity: 100, distance: 0, size: 3 },
                background: { stops: [[250,250,250], [238,238,238]] },
                border: { isActive: false },
                borderRadius: { radii: [[5, "px"],[5, "px"],[5, "px"],[5, "px"]] }
            }
        },
        {
            name: "iPhone Copy Button",
            style: {
                dropShadow: { color: [0,0,0], opacity: 55, distance: 3, blur: 4 },
                innerShadow: { color: [255,255,255], opacity: 50 },
                background: { stops: [[112, 134, 255], [[79, 105, 255], 37], [[53, 83, 255], 41], [49, 79, 254]] },
                border: { color: [50,50,50] },
                borderRadius: { radii: [[5, "px"],[5, "px"],[5, "px"],[5, "px"]] }
            }
        },
        {
            name: "Please don't sue me",
            style: {
                dropShadow: { distance: 0 },
                innerShadow: { opacity: 55 },
                background: { stops: [[22, 127, 232], [0, 60, 123]] }
            }
        }
    ],
    init: function(){
        this.$el = $('#stylePresets');
        if(localStorage["styles"]) this.styles = JSON.parse(localStorage["styles"]);
        this.renderStyles(this.styles);
        this.loadStyle(0);
    },
    renderStyles: function(styleObjects){
        var styleFragment = document.createDocumentFragment();
        for(var i = 0, length = styleObjects.length; i<length; i++){
            styleFragment.appendChild( this.addStyle(styleObjects[i].name, styleObjects[i].style, i) );
        }
        this.$el.append(styleFragment);
    },
    addStyle: function(name, packedStyle, pos){
        var expandedStyle = this.decompress(packedStyle);
        var cssObj = css.displayCss(expandedStyle);
        var swatch = $('<div class="swatch" />')
                .attr({ 'title': name, 'data-pos': pos })
                .bind('mousedown', { self : this }, styleStore.select )
                    .append( $('<div />').css(cssObj) );
        return swatch.get(0);
    },
    select: function(e){
        e.stopPropagation();
        var self = e.data.self;
        var $obj = $(this);
        var family = $obj.parent().children();
        var pos = family.index(this);
        // if alt is pressed while clicking: remove style
        if(e.altKey){
            // double check - styles are precious
            if(pos !== 0 && window.confirm( lang.DeleteStyle + ' "'+ self.styles[pos].name +'"?' )){
                // slice out the gradient from the gradient array (method by John Resig)
                var rest = self.styles.slice(pos + 1);
                self.styles.length = pos;
                self.styles.push.apply(self.styles, rest);
                localStorage["styles"] = JSON.stringify(self.styles);
                $obj.remove();
            }
        }
        else {
            // else set the style
            family.removeClass('active');
            self.loadStyle(pos);
           }
    },
    compress: function(style){
        var slimStyle = {};
        var fatStyle = $.extend(true, {}, style);
        for( key in fatStyle ){
            var value = fatStyle[key];
            if(typeof style === "object"){
                if(value.isActive){
                    slimStyle[key] = {};
                    for( prop in value ){
                        var propVal = value[prop];
                        if( defaults[key][prop] === undefined ) continue;
                        if( typeof propVal === "object" ){
                            if( !jQuery.compare(propVal, defaults[key][prop]) ){
                                slimStyle[key][prop] = propVal;
                            }
                        } 
                        else if( propVal != defaults[key][prop] && prop !== "isActive" ){
                            slimStyle[key][prop] = propVal;
                        }
                    }
                    if( jQuery.isEmptyObject(slimStyle[key]) ) delete slimStyle[key];
                } else {
                    if(defaults[key].isActive){
                        slimStyle[key] = { isActive: false };
                    }
                }
            }
            else if(key === "globalAngle" && value !== defaults.globalAngle){
                slimStyle["globalAngle"] = value;
            }
        }
        return slimStyle;
    },
    decompress: function(packedStyle){
        var expandedStyle = $.extend(true, {}, defaults);
        for(key in packedStyle){
            expandedStyle[key] = $.extend({}, defaults[key], packedStyle[key]);
            if(packedStyle[key].isActive !== undefined){
                expandedStyle[key].isActive = packedStyle[key].isActive;
            } else {
                expandedStyle[key].isActive = true;
            }
        }
        return expandedStyle;
    },
    loadStyle: function(pos){
        this.$el.children().eq(pos).addClass('active');
        currentStyle = this.decompress(this.styles[pos].style);
        $(document).trigger('styleChange').trigger('paint');
    },
    create: function(){
        var newStyle, name = prompt(lang.NewStyle,"Style "+this.styles.length);
        if(name){
            newStyle = {'name': name, 'style': this.compress(currentStyle)};
            this.styles.push(newStyle);
            this.renderStyles([newStyle]);
            localStorage["styles"] = JSON.stringify(this.styles);
        }
    }
}


================================================
FILE: js/tools.js
================================================
var tools = {
    options: {
        hex: true
    },
    /**
     * @method  averageGradientColor
     * @param   fullStops {stops-array}
     * @return  color {string}
     * @example averageGradientColor([[255,255,255], [0,0,0]]) returns gray
     */
    averageGradientColor: function(fullStops){
        var stops = gradienteditor.expand( $.extend(true, [], fullStops) ),
            reducedArray = [],
            l = stops.length;

        for(var i = 0; i < l; i++){
            var stop = stops[i];
            if(typeof stop === 'number'){
                stops[i] = this.getMiddlepoint(stops[i-1], stop, stops[i+1]);
            }
        }    

        for(var i = 0; i < l-1; i++){
            var stopA = stops[i],
                stopB = stops[i+1];

            reducedArray.push(this.averageStop(stopA, stopB));
        }        
        // reduce array to one rgb array
        reducedArray = reducedArray.reduce(this.averageColor, [0,0,0]);

        // round its values
        for(var i=0; i<3; i++){
            reducedArray[i] = Math.round(reducedArray[i]);
        }

        // return said array as color string
        return this.toColor(reducedArray);
    },
    /**
     * @method  averageStop
     * @param   stopA {stop-array}
     * @param   stopB {stop-array}
     * @return  color-stop {stop-array}
     * @example averageStop([[255,255,255], 0], [[0,0,0], 100]) returns [[128,128,128], 50]
     */
    averageStop: function(stopA, stopB){
        var colorA = stopA[0],
            posA = stopA[1],
            colorB = stopB[0],
            posB = stopB[1];

        return [
            [
                this.getCenter(colorA[0],colorB[0]),
                this.getCenter(colorA[1],colorB[1]),
                this.getCenter(colorA[2],colorB[2])
            ], 
            posB - posA
        ];
    },
    /**
     * @method  averageColor
     * @param   previousValue {color-array}
     * @param   currentValue {stop-array}
     * @return  color {color-array}
     */
    averageColor: function(previousValue, currentValue, index, array){
        var color = currentValue[0],
            weight = currentValue[1]/100;

        return [
            previousValue[0] + color[0] * weight, // r
            previousValue[1] + color[1] * weight, // g
            previousValue[2] + color[2] * weight  // b
        ];
    },
    /**
     * @method  roundToMultiple
     * @param   number {integer}
     * @param    multiple {integer}    multiple to round to
     * @return  rounded number {integer}
     * @example roundToMultiple(35, 15) returns 30
     * @usage    in ui.js -> pot; to round to 15° steps
     */
    roundToMultiple: function(number, multiple){
        var value = number/multiple,
            integer = Math.floor(value),
            rest = value - integer;
        return rest > 0.5 ? (integer+1)*multiple : integer*multiple;
    },
    /**
     * @method  toColor
     * @param   rgb {array}   RGB or RGBA Color Array
     * @return  CSS Color {string}
     * @example toColor([255,255,255]) returns 'rgb(255,255,255)'
     *          toColor([255,255,255,0.5]) returns 'rgba(255,255,255,0.5)'
     */
    toColor: function(rgb){
        var mode = rgb.length === 3 ? 'rgb' : 'rgba',
            string = mode+'('+rgb.join(',')+')';
                
        if (css.colors[string]) {
            return css.colors[string];
        }
        else if(this.options.hex && mode === 'rgb'){
            return "#"+color.hexFromRgb(rgb);
        }
        return string;
    },
    /**
     * @method  getCenter    returns the center between a starting and an ending point
     * @param   start {integer}    
     *             end {integer}
     *             offset {integer} [optional] if the center has an offset
     * @return  center {integer}
     * @example getCenter(0, 60) returns 30
     *             getCenter(0, 60, 75) returns 45
     */
    getCenter: function(start, end, offset){
        var o = offset || 50;
        return start + Math.round(o/100*(end-start));
    },
    /**
     * @method  getMiddlepoint    returns the color at a specific position on a color gradient defined through a start and end color
     * @param   start {array}    eiter a rgb color (like [255,255,255])or a rgb color and a positon (e.g. [[255,255,255], 10])
     *             pos {integer}    position
     *             end {array}        rgb color [r, g, b]
     * @return  {array} of the rgb color {array} and relative index {integer}
     * @example getCenter(0, 60) returns 30
     *             getCenter(0, 60, 75) returns 45
     */
    getMiddlepoint: function(start, pos, end){
        var startColor = start,
            endColor = end,    
            startIndex = 0,
            endIndex = 100,
            index = 0,
            color = [];
        if(start.length === 2){ startIndex = start[1]; startColor = start[0]; }
        if(end.length === 2){ endIndex = end[1]; endColor = end[0]; }
        index = this.getCenter(startIndex, endIndex, pos);
        for (var i=0, l = startColor.length; i<l; i++) {
            color[i] = startColor[i] + Math.round((endColor[i] - startColor[i])/2);
        }
        return [color, index];
    },
    /**
     * @method  decodeStops
     * @param   stops {array}    encoded color stops
     * @param    alpha {float} [optional]     opacity value between 0-1
     * @return  {array} decoded color stops: rgb strings
     * @example decodeStops([0,0,0], 10, [255,255,255]) returns ['rgb(0,0,0)', 'rgb(25,25,25) 10%', 'rgb(255,255,255)']
     */
    decodeStops: function(stops){
        var steps = [];
        for(var i=0, length=stops.length; i<length; i++){
            var stop = stops[i];
            switch(typeof stop){
            case 'object': // => [255,255,255] or [[255,255,255], 33]
                if(stop.length > 2){ // => [255,255,255]
                    steps[i] = this.toColor(stop);
                }
                else { // => [[255,255,255], 33]
                    steps[i] = this.toColor(stop[0])+" "+stop[1]+"%";
                }
                break;
            case 'number': // => 11
                var middlepoint = this.getMiddlepoint(stops[i-1], stop, stops[i+1]);
                steps[i] = this.toColor(middlepoint[0])+" "+middlepoint[1]+"%";
                break;
            }           
        }
        return steps;
    },
    /**
     * @method  decodeCanvasGradient
     * @param   stops {array} the color stops
     * @param    angle {integer} the gradients angle
     * @param   ctx {canvas 2d context}    the context the gradient is for
     * @param   x {integer}    the x coordinate where the gradient should start
     * @param   y {integer}    the y coordinate where the gradient should start
     * @param   width {integer}    the width of the gradients box
     * @param   height {integer} the height of the gradients box
     * @return  {canvas-gradient}
     */
    decodeCanvasGradient: function(stops, angle, style, ctx, x, y, width, height){
        var gradient,
            // looks like stops is still referenced to currentStyle.background.translucentStops at this point
            tempStops = $.extend(true, [], stops);
        
        switch(style){
            case "linear":
                /*     missing: angle support
                    
                    0°     ->     x+width,    y,             x,             y
                    45° ->    x+width,    y,            x,            y+height
                    90°    ->    x,            y,            x,            y+height
                    135°->    x,            y,            x+width,    y+height
                    180°->    x,            y,            x+width,    y
                    225°->    x,            y+height,    x+width,    y
                    270°->    x,            y+height,    x,            y
                    315°->    x+width,    y+height,    x,            y
                    
                    there is a pattern :) something with sin & cos
                    for now now default to 90
                */
                gradient = ctx.createLinearGradient(x, y, x, y+height);
                break;
            case "reflected":
                tempStops = this.reflectStops(tempStops);
                gradient = ctx.createLinearGradient(x, y, x, y+height);
                break;
            case "contain":
                var closestSide = width < height ? width/2 : height/2;
                gradient = ctx.createRadialGradient(x+width/2, y+height/2, 0, x+width/2, y+height/2, closestSide); // centered
                break;
            case "cover":
                // farest corner = half diagonal side >> pitagoras
                var farestCorner = Math.sqrt( width * width + height * height )/2;
                gradient = ctx.createRadialGradient(x+width/2, y+height/2, 0, x+width/2, y+height/2, farestCorner); // centered
                break;
        }
        // bring the stops in the right order for canvas gradient:
        for(var i=0, length=tempStops.length; i<length; i++){
            var stop = tempStops[i], color, pos;
            // if the first stop has an offset add a color stop to 0
            if(i === 0 && stop.length === 2){
                gradient.addColorStop(0, this.toColor(stop[0]));
            }
            switch(typeof stop){
            case 'object': // => [255,255,255] or [[255,255,255], 33]
                if(stop.length === 3){ // => [255,255,255]
                    pos = i === 0 ? 0 : 100; // can either be the start or the end
                    color = this.toColor(stop);
                }
                else { // => [[255,255,255], 33]
                    color = this.toColor(stop[0]);
                    pos = stop[1];
                }
                break;
            case 'number': // => 11
                var middlepoint = this.getMiddlepoint(tempStops[i-1], stop, tempStops[i+1]);
                color = this.toColor(middlepoint[0]);
                pos = middlepoint[1];
                break;
            }
            // pos is now between 0-100 - for canvas we need it between 0-1
            pos = pos/100;
            pos = pos+''; // <-- to change from number to string seems to fix a bug in firefox on ubuntu
             gradient.addColorStop(pos, color);
        }
        return gradient;
    },
    /**
     * @method  opposite    
     * @param   direction {String}
     * @return  {String} opposite direction
     * @example opposite('top') returns 'bottom'
     */
    opposite: function(direction) {
        switch(direction){
        case 'top':
            return 'bottom';
        case 'right':
            return 'left';
        case 'bottom':
            return 'top';
        case 'left':
            return 'right';
        }
    },
    reflectStops: function(stops){
        var first = [],
            second = [];
            // bug: turns everything around
        for(var i=0, l=stops.length; i<l; i++){
            var stop = stops.shift(),
                start, end;
            switch(typeof stop){
                case "number":
                    start = Math.round(stop/2);
                    end = 100-start;
                    break;
                case "object":
                    start = stop.slice(0);
                    end = stop.slice(0);
                    if(stop.length === 2){
                        start[1] = Math.round(stop[1]/2);
                        end[1] = 100-start[1];
                    }
                    break;
            }
            
            // add 50% to the last element
            if(i === l-1) start = [start, 50];
            
            first.push(start);
            
            // don't add the last stop cause we only need one center
            if(i != l-1) second.unshift(end);
        }
        return first.concat(second);
    },
    reverseStops: function(stops){
        var reversed = [],
            stops = stops.slice(0);
        while(stops.length){
            var stop = stops.pop(), rev;
            switch(typeof stop){
                case "number":
                    rev = 100-stop;
                    break;
                case "object":    
                    rev = stop.slice(0);
                    if(stop.length === 2){
                        rev[1] = 100-stop[1];
                    }
                    break;
            }
            reversed.push(rev);
        }
        return reversed;
    },
}

================================================
FILE: js/ui.js
================================================
var pot = {
    init: function(el){
        // el = background, dropShadow, innerShadow
        this.$el = $("#"+el+" .pot");
        this.height = this.$el.height();
        this.width = this.$el.width();
        this.$pointer = this.$el.find('> div');
        this.model = el;
        this.$el.bind("mousedown", $.proxy( this, "start" ) );
        this.$input = this.$el.next('div').children('input:first-child');
        this.$input.change( $.proxy( this, "get" ) );
    },
    start: function(event){
        var myOffset = this.$el.offset();
        this.offset = { x: myOffset.left+(this.width/2), y: myOffset.top+(this.height/2) };
        this.turn(event);
        $(document).bind('mousemove.global', $.proxy( this, "turn") );
    },
    get: function(){
        var value = parseInt(this.$input.val());
        this.update(value);
    },
    set: function(value){
        this.$input.val(value);
    },
    update: function(value){
        this.move(value);
        if(currentStyle[this.model].hasGlobalLight) currentStyle.globalAngle = value;
        currentStyle[this.model].angle = value;
        this.set(value);
        style[this.model].paint();
    },
    move: function(degrees){
        this.$pointer.css('transform', 'rotate('+-degrees+'deg)');
    },
    turn: function(event){
        event.preventDefault();
        var opposite = this.offset.y - event.pageY,
            adjacent = event.pageX - this.offset.x,
            radiants = Math.atan(opposite/adjacent),
            degrees = Math.round(radiants*(180/Math.PI), 10);
        
        if(event.shiftKey) degrees = tools.roundToMultiple(degrees, 15);
        
        if(adjacent < 0 && opposite >= 0){ degrees+= 180; }
        else if(opposite < 0 && adjacent < 0){ degrees-= 180; }
        if(degrees === -180) degrees = 180;
        
        this.update(degrees);
    }
};

var toggle = {
    _treshhold: 2,
    _moving: false,
    init: function(el, toggle, thisArg, callback){
        this.$el = $("#"+el);
        this.$slider = this.$el.find('.slidePanel');
        this.width = this.$el.width();
        this.toggle = toggle;
        this.model = thisArg;
        // render befor the callback gets asigned to not call the callback at init
        this.render();
        this.callback = callback;
        this.$el.bind('mousedown', $.proxy( this, "start" ) );
    },
    start: function(event){
        event.preventDefault();
        this._startPos = event.pageX - this.$el.offset().left;
        this.$el.addClass('down');
        $(document).bind('mousemove.global', $.proxy( this, "move") );
        $(document).one('mouseup', $.proxy( this, "stop") );
    },
    move: function(event){
        var distance = event.pageX - this._startPos;
        if(!this._moving && Math.abs(distance) > this._treshhold){
            this.$el.addClass('moving');
            this._moving = true;
        }
        if(this._moving){
            this._pos = Math.min(0, Math.max(-this.width/2, this._offset + distance));
            this.$slider.css('left', this._pos);
        }
    },
    render: function(){
        this._offset = this.model[this.toggle] ? -this.width/2 : 0;
        this.$slider.css('left', this._offset);
        if(this.callback) this.callback();
    },
    stop: function(event){
        this.$el.removeClass('down');
        if(this._moving){
            this._moving = false;
            this.$el.removeClass('moving');
            if(this._pos >= -this.width/4){
                this.model[this.toggle] = false;
            } else {
                this.model[this.toggle] = true;
            }
        } else {
            this.model[this.toggle] = !this.model[this.toggle];
        }    
        this.render();
    }
};

var slider = {
    init: function(el, model){
        this.$el = $("#"+el+" ."+model).prev("div.slider");
        this.$pointer = this.$el.find('> div:nth-child(2)');
        this.$input = this.$el.next('input');
        this.max = this.$input.data("max");
        this.length = this.$el.width();
        this.ease = this.$el.data("easing");
        this.style = el;
        this.model = model;
        this.$el.bind("mousedown", $.proxy( this, "start" ) );
        this.$input.change( $.proxy( this, "get" ) );
    },
    acc: function(x){
        return this.ease ? x*x : x;
    },
    invAcc: function(x){
        return this.ease ? Math.sqrt(x) : x;
    },
    get: function(){
        var value = parseInt(this.$input.val());
        this.update(value);
    },
    set: function(value){
        this.$input.val(value);
    },
    update: function(value, position){
        this.move(this.toPos(value));
        currentStyle[this.style][this.model] = value;
        this.move(position || this.toPos(value));
        this.set(value);
        style[this.style].paint();
    },
    move: function(x){
        this.$pointer.css({ left: x+'px' });
    },
    toPos: function(value){
        var percentage = this.invAcc(value/this.max);
        return Math.round(this.length*percentage);
    },
    toValue: function(position){
        var percentage = this.acc(position/this.length);
        return Math.round(percentage*this.max);
    },
    start: function(event){
        this.offset = { x: this.$el.offset().left };
        this.slide(event);
        $(document).bind('mousemove.global', $.proxy( this, "slide" ) );
    },
    slide: function(event){
        event.preventDefault();
        var value, position = Math.max(0, Math.min(this.length, event.pageX - this.offset.x));    
        
        value = this.toValue(position);
        this.update(value, position);
    }
};

================================================
FILE: js/universe.js
================================================
var parallelUniverse = {
    x: 0,
    y: 0,
    KAPPA: 4*(Math.SQRT2-1)/3,
    roundToHalf: function(value){
        // makes the borders crisp
        return (value - parseInt(value, 10)) === 0.5 ? value+1 : value + 1.5;
    },
    draw: function(){
        this.x = this.roundToHalf(dimensions.width/2 - currentStyle.width/2);
        this.y = this.roundToHalf(dimensions.height/2 - currentStyle.height/2);
        
        pu.clearRect(0,0,dimensions.width,dimensions.height);    
        
        this.background();
        this.drawCanvases();
        
        this.shadow();
        pu.beginPath();
        this.rect(pu);
        pu.closePath();
        this.layerBackground();
        this.innerShadow();
        this.border();
    },
    background: function(){
        pu.fillStyle = tools.decodeCanvasGradient(
            background.background[1].stops, background.background[1].angle, background.background[1].style, pu, 0, 0, dimensions.width, dimensions.height
        );
        pu.fillRect(0, 0, dimensions.width, dimensions.height);
    },
    rect: function(ctx){
        var br = currentStyle.borderRadius;
        if(br.isActive){
            for(var i=3; i>=0; i--){
                var radiusX, radiusY, unit, percentage;
                unit = br.radii[i][1];
                if(unit === "%"){
                    percentage = Math.min(0.5, br.radii[i][0]/100);
                    radiusY = percentage*currentStyle.height;
                    radiusX = percentage*currentStyle.width;
                } else {
                    radiusX = radiusY = Math.min(currentStyle.width/2, br.radii[i][0]);
                }
                switch(i){ // anti-clockwise because of the innerShadow-mask
                case 3: // start at left middle; then bottom left
                    ctx.moveTo(this.x, this.y+currentStyle.height/2);
                    ctx.lineTo(this.x, this.y+currentStyle.height-radiusY);
                    ctx.bezierCurveTo(this.x, this.y+currentStyle.height-radiusY+radiusY*this.KAPPA, this.x+(radiusX-radiusX*this.KAPPA), this.y+currentStyle.height, this.x+radiusX, this.y+currentStyle.height);
                    break;
                case 2: // upper right
                    ctx.lineTo(this.x+currentStyle.width-radiusX, this.y+currentStyle.height);
                    ctx.bezierCurveTo(this.x+currentStyle.width-radiusX+radiusX*this.KAPPA, this.y+currentStyle.height, this.x+currentStyle.width, this.y+currentStyle.height-radiusY+radiusY*this.KAPPA, this.x+currentStyle.width, this.y+currentStyle.height-radiusY);
                    break;
                case 1: // bottom right
                    ctx.lineTo(this.x+currentStyle.width, this.y+radiusY);
                    ctx.bezierCurveTo(this.x+currentStyle.width, this.y+(radiusY-radiusY*this.KAPPA), this.x+currentStyle.width-radiusX+radiusX*this.KAPPA, this.y, this.x+currentStyle.width-radiusX, this.y);
                    break;
                case 0: // upper left and then back to left middle;
                    ctx.lineTo(this.x+radiusX, this.y);
                    ctx.bezierCurveTo(this.x+(radiusX-radiusX*this.KAPPA), this.y, this.x, this.y+(radiusY-radiusY*this.KAPPA), this.x, this.y+radiusY);
                    ctx.lineTo(this.x, this.y+currentStyle.height/2);
                    break;
                }
            }
        } else {
            // outwritten rect anti-clockwise instead of the ctx.rect(x,y,width,height) because of the innerShadow mask
            ctx.moveTo(this.x, this.y);
            ctx.lineTo(this.x, this.y+currentStyle.height);
            ctx.lineTo(this.x+currentStyle.width, this.y+currentStyle.height);
            ctx.lineTo(this.x+currentStyle.width, this.y);
            ctx.lineTo(this.x, this.y);
        }
        
    },
    drawCanvases: function(){
        var $canvases = $workspace.find('canvas.moveable');
        $.each($canvases, function(i, canvas){
            var $canvas = $(canvas),
                offset = $canvas.offset();
            pu.drawImage(canvas, offset.left, offset.top);
        });
    },
    shadow: function(){
        var sd = currentStyle.dropShadow, dropColor;
        if(sd.isActive){
            pu.save();
            pu.beginPath();
            
            this.rect(pu);
            
            dropColor = sd.color.slice(0);
            dropColor.push(sd.opacity/100);
            dropColor = tools.toColor(dropColor);
            pu.fillStyle = dropColor;
            pu.shadowOffsetX = sd.dropX;
            pu.shadowOffsetY = sd.dropY;
            pu.shadowBlur = sd.blur;
            pu.shadowColor = dropColor;
            pu.fill();
            pu.closePath();
            pu.restore();
        }
    },
    innerShadow: function(){
        var is = currentStyle.innerShadow, dropColor;
        if(is.isActive){
            iu.save();
            iu.beginPath();
            
            // draw the layer box as negativ area and use normal dropShadow in another universe
            // idea by Alistair MacDonald https://gist.github.com/787544
            
            iu.rect(0,0,dimensions.width,dimensions.height);
            iu.moveTo(this.x, this.y);
            this.rect(iu);
            
            dropColor = is.color.slice(0);
            dropColor.push(is.opacity/100);
            dropColor = tools.toColor(dropColor);
            iu.shadowOffsetX = is.dropX;
            iu.shadowOffsetY = is.dropY;
            iu.shadowBlur = is.blur;
            iu.shadowColor = dropColor;
            iu.fill();
            iu.closePath();
            iu.restore();
            
            // clip the paralell universe temporarily to the layers size (border-radius!) 
            // and draw the inner shadow from the other universe to the main parallel Universe
            pu.save();
            pu.beginPath();
            this.rect(pu);
            pu.closePath();
            pu.clip();
            pu.drawImage($innerShadowUniverse.get(0), this.x, this.y, currentStyle.width, currentStyle.height, this.x, this.y, currentStyle.width, currentStyle.height);
            pu.restore();
            iu.clearRect(0,0,dimensions.width,dimensions.height);
        }
    },
    layerBackground: function(){
        var bg = currentStyle.background, 
            tempAngle, tempStops;
    
        if(bg.isActive) {
            tempAngle = bg.angle;
            
            tempStops = $.extend(true, [], bg.translucidStops); // no deep copy!
            if(bg.hasGlobalLight) bg.angle = currentStyle.globalAngle;
            if(bg.isReverse) tempStops = tools.reverseStops(tempStops);
            pu.fillStyle = tools.decodeCanvasGradient(
                tempStops, tempAngle, bg.style,
                pu, this.x, this.y, currentStyle.width, currentStyle.height
            );
            pu.fill();
        }
    },
    border: function(){
        var bd = currentStyle.border, borderColor;
        if(bd.isActive){
            borderColor = bd.color.slice(0);
            borderColor.push(bd.opacity/100);
            pu.strokeStyle = tools.toColor(borderColor);
            pu.lineWidth = bd.size;
            pu.stroke();
        }
    }
};

================================================
FILE: js/zeroclipboard/ZeroClipboard.as
================================================
package {
	// Simple Set Clipboard System
	// Author: Joseph Huckaby
	
	import flash.display.Stage;
	import flash.display.Sprite;
	import flash.display.LoaderInfo;
	import flash.display.StageScaleMode;
	import flash.events.*;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.external.ExternalInterface;
	import flash.system.Security;
	import flash.utils.*;
	import flash.system.System;
 
	public class ZeroClipboard extends Sprite {
		
		private var id:String = '';
		private var button:Sprite;
		private var clipText:String = '';
		
		public function ZeroClipboard() {
			// constructor, setup event listeners and external interfaces
			stage.scaleMode = StageScaleMode.EXACT_FIT;
			flash.system.Security.allowDomain("*");
			
			// import flashvars
			var flashvars:Object = LoaderInfo( this.root.loaderInfo ).parameters;
			id = flashvars.id;
			
			// invisible button covers entire stage
			button = new Sprite();
			button.buttonMode = true;
			button.useHandCursor = true;
			button.graphics.beginFill(0xCCFF00);
			button.graphics.drawRect(0, 0, Math.floor(flashvars.width), Math.floor(flashvars.height));
			button.alpha = 0.0;
			addChild(button);
			button.addEventListener(MouseEvent.CLICK, clickHandler);
			
			button.addEventListener(MouseEvent.MOUSE_OVER, function(event:Event) {
				ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOver', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_OUT, function(event:Event) {
				ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOut', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event) {
				ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseDown', null );
			} );
			button.addEventListener(MouseEvent.MOUSE_UP, function(event:Event) {
				ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseUp', null );
			} );
			
			// external functions
			ExternalInterface.addCallback("setHandCursor", setHandCursor);
			ExternalInterface.addCallback("setText", setText);
			
			// signal to the browser that we are ready
			ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'load', null );
		}
		
		public function setText(newText) {
			// set the maximum number of files allowed
			clipText = newText;
		}
		
		public function setHandCursor(enabled:Boolean) {
			// control whether the hand cursor is shown on rollover (true)
			// or the default arrow cursor (false)
			button.useHandCursor = enabled;
		}
		
		private function clickHandler(event:Event):void {
			// user click copies text to clipboard
			// as of flash player 10, this MUST happen from an in-movie flash click event
			System.setClipboard( clipText );
			ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'complete', clipText );
		}
	}
}


================================================
FILE: js/zeroclipboard/ZeroClipboard.js
================================================
// Simple Set Clipboard System
// Author: Joseph Huckaby

var ZeroClipboard = {
	
	version: "1.0.7",
	clients: {}, // registered upload clients on page, indexed by id
	moviePath: 'ZeroClipboard.swf', // URL to movie
	nextId: 1, // ID of next movie
	
	$: function(thingy) {
		// simple DOM lookup utility function
		if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
		if (!thingy.addClass) {
			// extend element with a few useful methods
			thingy.hide = function() { this.style.display = 'none'; };
			thingy.show = function() { this.style.display = ''; };
			thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
			thingy.removeClass = function(name) {
				var classes = this.className.split(/\s+/);
				var idx = -1;
				for (var k = 0; k < classes.length; k++) {
					if (classes[k] == name) { idx = k; k = classes.length; }
				}
				if (idx > -1) {
					classes.splice( idx, 1 );
					this.className = classes.join(' ');
				}
				return this;
			};
			thingy.hasClass = function(name) {
				return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
			};
		}
		return thingy;
	},
	
	setMoviePath: function(path) {
		// set path to ZeroClipboard.swf
		this.moviePath = path;
	},
	
	dispatch: function(id, eventName, args) {
		// receive event from flash movie, send to client		
		var client = this.clients[id];
		if (client) {
			client.receiveEvent(eventName, args);
		}
	},
	
	register: function(id, client) {
		// register new client to receive events
		this.clients[id] = client;
	},
	
	getDOMObjectPosition: function(obj, stopObj) {
		// get absolute coordinates for dom element
		var info = {
			left: 0, 
			top: 0, 
			width: obj.width ? obj.width : obj.offsetWidth, 
			height: obj.height ? obj.height : obj.offsetHeight
		};

		while (obj && (obj != stopObj)) {
			info.left += obj.offsetLeft;
			info.top += obj.offsetTop;
			obj = obj.offsetParent;
		}

		return info;
	},
	
	Client: function(elem) {
		// constructor for new simple upload client
		this.handlers = {};
		
		// unique ID
		this.id = ZeroClipboard.nextId++;
		this.movieId = 'ZeroClipboardMovie_' + this.id;
		
		// register client with singleton to receive flash events
		ZeroClipboard.register(this.id, this);
		
		// create movie
		if (elem) this.glue(elem);
	}
};

ZeroClipboard.Client.prototype = {
	
	id: 0, // unique ID for us
	ready: false, // whether movie is ready to receive events or not
	movie: null, // reference to movie object
	clipText: '', // text to copy to clipboard
	handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
	cssEffects: true, // enable CSS mouse effects on dom container
	handlers: null, // user event handlers
	
	glue: function(elem, appendElem, stylesToAdd) {
		// glue to DOM element
		// elem can be ID or actual DOM element object
		this.domElement = ZeroClipboard.$(elem);
		
		// float just above object, or zIndex 99 if dom element isn't set
		var zIndex = 99;
		if (this.domElement.style.zIndex) {
			zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
		}
		
		if (typeof(appendElem) == 'string') {
			appendElem = ZeroClipboard.$(appendElem);
		}
		else if (typeof(appendElem) == 'undefined') {
			appendElem = document.getElementsByTagName('body'
Download .txt
gitextract_kja_9fna/

├── .project
├── README.markdown
├── builder.html
├── css/
│   ├── index.css
│   └── style.css
├── index.html
└── js/
    ├── application.js
    ├── codebox.js
    ├── color.js
    ├── colorpicker.js
    ├── css.js
    ├── gradienteditor.js
    ├── localization.js
    ├── numbers.js
    ├── style.js
    ├── styleStore.js
    ├── tools.js
    ├── ui.js
    ├── universe.js
    └── zeroclipboard/
        ├── ZeroClipboard.as
        ├── ZeroClipboard.fla
        ├── ZeroClipboard.js
        └── ZeroClipboard.swf
Download .txt
SYMBOL INDEX (11 symbols across 1 files)

FILE: js/application.js
  function moveWindow (line 203) | function moveWindow(event){
  function resizeLayer (line 207) | function resizeLayer(event, x, y){
  function showSlide (line 225) | function showSlide(pos){
  function dragenter (line 231) | function dragenter(e) {
  function dragleave (line 237) | function dragleave(e) {
  function dragover (line 243) | function dragover(e) {
  function drop (line 248) | function drop(e) {
  function showPickArea (line 291) | function showPickArea(){
  function hidePickArea (line 300) | function hidePickArea(){
  function pick (line 306) | function pick(event){
  function initialise (line 312) | function initialise() {
Condensed preview — 23 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (214K chars).
[
  {
    "path": ".project",
    "chars": 204,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>LayerStyles</name>\n\t<comment></comment>\n\t<projects>\n\t"
  },
  {
    "path": "README.markdown",
    "chars": 311,
    "preview": "Layer Styles\n============\n\nA HTML5 app for creating CSS3 in a intuitive way.\n\nHighlights\n----------\n\n- Colorpicker can p"
  },
  {
    "path": "builder.html",
    "chars": 20308,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>Layer S"
  },
  {
    "path": "css/index.css",
    "chars": 4693,
    "preview": "* { margin: 0; padding: 0; }\nhtml { height: 100%; }\nbody {\n\tfont: 12px/1.4 \"Helvetica Neue\", Helvetica, Arial, sans-seri"
  },
  {
    "path": "css/style.css",
    "chars": 30440,
    "preview": "* { margin: 0; padding: 0; }\nbody, html { height: 100%; overflow: hidden; }\nbody {\n    width: 100%;\n    font: 12px/14px "
  },
  {
    "path": "index.html",
    "chars": 2850,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n\t<title>Layer Styles<"
  },
  {
    "path": "js/application.js",
    "chars": 13470,
    "preview": "/*!\n *     _                                       ________                  _\n *    | |                                "
  },
  {
    "path": "js/codebox.js",
    "chars": 4298,
    "preview": "var codeBox = {\n    options: {\n        visible: true,\n        height: 143\n    },\n    minHeight: 100,\n    init: function("
  },
  {
    "path": "js/color.js",
    "chars": 2405,
    "preview": "var color = {\n    hsbFromRgb: function(rgb) {\n        r = rgb[0]/255, g = rgb[1]/255, b = rgb[2]/255;\n        var max = "
  },
  {
    "path": "js/colorpicker.js",
    "chars": 21636,
    "preview": "/*\n *      LayerStyles\n *       http://www.layerstyles.org\n *    \n *    Copyright (c) 2011 Felix Niklas\n *    This scrip"
  },
  {
    "path": "js/css.js",
    "chars": 7840,
    "preview": "var css = {\n    colors: {\n        'rgb(0,0,0)': \"black\",\n        'rgb(255,255,255)': \"white\"\n    },\n    gradientDirectio"
  },
  {
    "path": "js/gradienteditor.js",
    "chars": 19333,
    "preview": "var gradienteditor = {\n    callback: null,\n    thisArg: null,\n    changed: false,\n    puff: null,\n    gradientDimensions"
  },
  {
    "path": "js/localization.js",
    "chars": 1901,
    "preview": "var localization = {\n        en: {\n            \"Color\": \"Color\",\n            \"Opacity\": \"Opacity\",\n            \"Angle\": "
  },
  {
    "path": "js/numbers.js",
    "chars": 6669,
    "preview": "var numbers = {\n    regex: new RegExp(''),\n    min: 0,\n    max: 0,\n    temporaryMode: \"\",\n    match: false,\n    pressed:"
  },
  {
    "path": "js/style.js",
    "chars": 22340,
    "preview": "var style = {\n    background: {\n        elements: {\n            \".opacity\": { name: \"opacity\", handle: \"slider\" },\n     "
  },
  {
    "path": "js/styleStore.js",
    "chars": 7416,
    "preview": "var styleStore = {\n    styles: [\n        { \n            name: \"Default Style\", \n            style: { }\n        },\n      "
  },
  {
    "path": "js/tools.js",
    "chars": 12477,
    "preview": "var tools = {\n    options: {\n        hex: true\n    },\n    /**\n     * @method  averageGradientColor\n     * @param   fullS"
  },
  {
    "path": "js/ui.js",
    "chars": 5606,
    "preview": "var pot = {\n    init: function(el){\n        // el = background, dropShadow, innerShadow\n        this.$el = $(\"#\"+el+\" .p"
  },
  {
    "path": "js/universe.js",
    "chars": 7166,
    "preview": "var parallelUniverse = {\n    x: 0,\n    y: 0,\n    KAPPA: 4*(Math.SQRT2-1)/3,\n    roundToHalf: function(value){\n        //"
  },
  {
    "path": "js/zeroclipboard/ZeroClipboard.as",
    "chars": 2793,
    "preview": "package {\n\t// Simple Set Clipboard System\n\t// Author: Joseph Huckaby\n\t\n\timport flash.display.Stage;\n\timport flash.displ"
  },
  {
    "path": "js/zeroclipboard/ZeroClipboard.js",
    "chars": 9784,
    "preview": "// Simple Set Clipboard System\n// Author: Joseph Huckaby\n\nvar ZeroClipboard = {\n\t\n\tversion: \"1.0.7\",\n\tclients: {}, // re"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the mrflix/LayerStyles GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 23 files (199.2 KB), approximately 51.9k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!