diff --git a/.gitignore b/.gitignore index c2658d7d1b3..d35bbf75aa4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules/ +.idea/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..f0666e4f82c --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +Copyright (c) 2013, Stewart Lord +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 00000000000..93e77694f5e --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +identicon.js +============ + +GitHub-style identicons in JS with no server-side processing. + +This little library will produce the same shape and (roughly) the same color as GitHub when given the same hash value. Note that GitHub uses an internal database identifier for the hash, so you can't simply md5 the username and get the same result. The hard work is done by [Robert Eisele's](http://twitter.com/roberteisele) [PNGlib](http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/). The creative visual design is borrowed from [Jason Long](http://twitter.com/jasonlong) of Git and GitHub fame. + +Demo +---- +[View Demo](https://rawgithub.com/stewartlord/identicon.js/master/demo.html) + +Options +---- +* **hash** - [Optional] A unicode string that will be used to generate the image. Defaults to a random hash based on the current time. +* **options** - [Optional] An options object used to customize the generated image. + * **foreground** - The foreground color is automatically derived from the hash value. Use this option to override that behavior and provide a rgba value array instead (e.g. [255,0,0,255] for red). + * **background** - The background color expressed as an rgba value array to use for the image background. For example, use [255,0,0,255] for red. Defaults to an opaque light gray [240,240,240,255]. + * **margin** - The decimal fraction of the size to use for margin. For example, use 0.2 for a 20% margin. Defaults to 0.08 for an 8% margin. + * **size** - The size in pixels of the height and width of the generated (square) image. Defaults to 64 pixels. + +Usage +----- + +##### Simple +Generate the Identicon by supplying a hash string and size. +```js + +// create a base64 encoded PNG +var data = new Identicon('hash', 420).toString(); + +// write to a data URI +document.write(''); +``` + +##### Advanced +To customize additional properties, generate the Identicon by supplying a hash string and an options object. +```js +// set up options +var hash = "myUnicodeUsername!"; // Any unicode string +var options = { + foreground: [0, 0, 0, 255], // rgba black + background: [255, 255, 255, 255], // rgba white + margin: 0.2, // 20% margin + size: 420 // 420px square + }; + +// create a base64 encoded PNG +var data = new Identicon(hash, options).toString(); + +// write to a data URI +document.write(''); +``` + + +[Requires PNGLib](http://www.xarg.org/download/pnglib.js) + +Copyright 2013, [Stewart Lord](http://twitter.com/stewartlord) +Released under the [BSD license](http://www.opensource.org/licenses/bsd-license.php) diff --git a/bower.json b/bower.json new file mode 100644 index 00000000000..cdbd931fe07 --- /dev/null +++ b/bower.json @@ -0,0 +1,20 @@ +{ + "name": "identicon.js", + "main": [ + "pnglib.js", + "identicon.js" + ], + "version": "1.3.0", + "homepage": "https://github.com/stewartlord/identicon.js", + "authors": [ + "stewardlord" + ], + "description": "GitHub-style identicons in JS with no server-side processing.", + "moduleType": [ + "globals" + ], + "keywords": [ + "identicon" + ], + "license": "BSD" +} diff --git a/demo.html b/demo.html new file mode 100644 index 00000000000..2e5e9fa8162 --- /dev/null +++ b/demo.html @@ -0,0 +1,90 @@ + + + + + + + + +
+

Identicon.js

+
+
+

Basic Usage

+

Specify just a hash, use default background color, margins, and size.

+
+  var hash = 'd6fe8c82fb0abac17a702fd2a94eff37';
+  var data = new Identicon(hash).toString();
+  document.write('<img src="data:image/png;base64,' + data + '">');
+ +
+
+ +
+
+

Options Usage

+

Specify a hash and an options object to customize background color, margins, and size.

+
+  var hash = 'd6fe8c82fb0abac17a702fd2a94eff37';
+  var options = {
+    foreground: [255, 255, 255, 255],
+    background: [0, 0, 0, 255],
+    margin: 0.2,
+    size: 128
+  };
+  var data = new Identicon(hash, options).toString();
+  document.write('<img src="data:image/png;base64,' + data + '">');
+ +
+
+ +
+
+

Automatic Usage

+

Don't specify a hash to have one automatically generated based on the current time.

+
+  var data = new Identicon().toString();
+  document.write('<img src="data:image/png;base64,' + data + '">');
+ +
+
+
+ + diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 00000000000..0c97362d36e --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,46 @@ +//------------ user for publishing +gulp.task('bump-patch-version', function () { + return gulp.src(['./bower.json', './package.json']) + .pipe(bump({type: "patch"}).on('error', gutil.log)) + .pipe(gulp.dest('./')); +}); + +gulp.task('commit-changes', function () { + return gulp.src('.') + .pipe(git.commit('Bumped version number')); +}); + +gulp.task('push-changes', function (cb) { + git.push('origin', 'master', cb); +}); + +gulp.task('create-new-tag', function (cb) { + var version = getPackageJsonVersion(); + git.tag(version, 'Created Tag for version: ' + version, function (error) { + if (error) { + return cb(error); + } + git.push('origin', 'master', {args: '--tags'}, cb); + }); + + function getPackageJsonVersion () { + //We parse the json file instead of using require because require caches multiple calls so the version number won't be updated + return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; + } +}); + +gulp.task('release', function (callback) { + runSequence( + 'bump-patch-version', + 'commit-changes', + 'push-changes', + 'create-new-tag', + function (error) { + if (error) { + console.log(error.message); + } else { + console.log('RELEASE FINISHED SUCCESSFULLY'); + } + callback(error); + }); +}); \ No newline at end of file diff --git a/identicon.js b/identicon.js new file mode 100644 index 00000000000..9a7c2aafc1e --- /dev/null +++ b/identicon.js @@ -0,0 +1,144 @@ +/** + * Identicon.js v1.3.0 + * http://github.com/stewartlord/identicon.js + * + * Requires PNGLib + * http://www.xarg.org/download/pnglib.js + * + * Copyright 2013, Stewart Lord + * Released under the BSD license + * http://www.opensource.org/licenses/bsd-license.php + */ + +(function() { + var PNGlib; + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + PNGlib = require('./pnglib'); + } else { + PNGlib = window.PNGlib; + } + + var Identicon = function(hash, options){ + this.defaults = { + background: [240, 240, 240, 255], + hash: this.createHashFromString((new Date()).toISOString()), + margin: 0.08, + size: 64 + }; + + this.options = typeof(options) === 'object' ? options : this.defaults; + + // backward compatibility with old constructor (hash, size, margin) + if (arguments[1] && typeof(arguments[1]) === 'number') { this.options.size = arguments[1]; } + if (arguments[2]) { this.options.margin = arguments[2]; } + + this.hash = hash || this.defaults.hash; + this.background = this.options.background || this.defaults.background; + this.foreground = this.options.foreground; + this.margin = this.options.margin || this.defaults.margin; + this.size = this.options.size || this.defaults.size; + }; + + Identicon.prototype = { + background: null, + foreground: null, + hash: null, + margin: null, + size: null, + + render: function(){ + var hash = this.hash, + size = this.size, + baseMargin = Math.floor(size * this.margin), + cell = Math.floor((size - (baseMargin * 2)) / 5), + margin = Math.floor((size - cell * 5) / 2), + image = new PNGlib(size, size, 256); + + // light-grey background + var bg = image.color(this.background[0], this.background[1], this.background[2], this.background[3]), + fg; + + if (this.foreground) { + fg = image.color(this.foreground[0], this.foreground[1], this.foreground[2]); + } else { + // foreground is last 7 chars as hue at 50% saturation, 70% brightness + var rgb = this.hsl2rgb(parseInt(hash.substr(-7), 16) / 0xfffffff, 0.5, 0.7); + fg = image.color(rgb[0] * 255, rgb[1] * 255, rgb[2] * 255); + } + + // the first 15 characters of the hash control the pixels (even/odd) + // they are drawn down the middle first, then mirrored outwards + var i, color; + for (i = 0; i < 15; i++) { + color = parseInt(hash.charAt(i), 16) % 2 ? bg : fg; + if (i < 5) { + this.rectangle(2 * cell + margin, i * cell + margin, cell, cell, color, image); + } else if (i < 10) { + this.rectangle(1 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image); + this.rectangle(3 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image); + } else if (i < 15) { + this.rectangle(0 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image); + this.rectangle(4 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image); + } + } + + return image; + }, + + rectangle: function(x, y, w, h, color, image) { + var i, j; + for (i = x; i < x + w; i++) { + for (j = y; j < y + h; j++) { + image.buffer[image.index(i, j)] = color; + } + } + }, + + // adapted from: https://gist.github.com/aemkei/1325937 + hsl2rgb: function(h, s, b){ + h *= 6; + s = [ + b += s *= b < .5 ? b : 1 - b, + b - h % 1 * s * 2, + b -= s *= 2, + b, + b + h % 1 * s, + b + s + ]; + + return[ + s[ ~~h % 6 ], // red + s[ (h|16) % 6 ], // green + s[ (h|8) % 6 ] // blue + ]; + }, + + toString: function(){ + return this.render().getBase64(); + }, + + // Creates a consistent-length hash from a string + createHashFromString: function(str) { + var hash = '0', salt = 'identicon', i, chr, len; + + if (!str) { + return hash; + } + + str += salt + str; // Better randomization for short inputs. + + for (i = 0, len = str.length; i < len; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + return hash.toString(); + } + }; + + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = Identicon; + } else { + window.Identicon = Identicon; + } +})(); diff --git a/package.json b/package.json index f9c4b468108..9091433f638 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,22 @@ { - "name": "imad-2016-base", - "version": "0.1.0", - "description": "IMAD 2016 course app", - "main": "server.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "name": "identicon.js", + "version": "1.3.0", + "description": "GitHub-style identicons in JS with no server-side processing.", + "main": "identicon.js", + "repository": { + "type": "git", + "url": "https://github.com/stewartlord/identicon.js" }, - "author": "", - "license": "ISC", - "dependencies": { - "express": "^4.14.0", - "morgan": "^1.7.0" + "keywords": [ + "identicon" + ], + "author": "stewardlord", + "license": "BSD", + "bugs": { + "url": "https://github.com/stewartlord/identicon.js/issues" + }, + "homepage": "https://github.com/stewartlord/identicon.js", + "devDependencies": { + "gulp": "^3.9.0" } } diff --git a/pnglib.js b/pnglib.js new file mode 100644 index 00000000000..45a2c72c63e --- /dev/null +++ b/pnglib.js @@ -0,0 +1,214 @@ +/** +* A handy class to calculate color values. +* +* @version 1.0 +* @author Robert Eisele +* @copyright Copyright (c) 2010, Robert Eisele +* @link http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/ +* @license http://www.opensource.org/licenses/bsd-license.php BSD License +* +*/ + +(function() { + + // helper functions for that ctx + function write(buffer, offs) { + for (var i = 2; i < arguments.length; i++) { + for (var j = 0; j < arguments[i].length; j++) { + buffer[offs++] = arguments[i].charAt(j); + } + } + } + + function byte2(w) { + return String.fromCharCode((w >> 8) & 255, w & 255); + } + + function byte4(w) { + return String.fromCharCode((w >> 24) & 255, (w >> 16) & 255, (w >> 8) & 255, w & 255); + } + + function byte2lsb(w) { + return String.fromCharCode(w & 255, (w >> 8) & 255); + } + + // modified from original source to support NPM + var PNGlib = function(width,height,depth) { + + this.width = width; + this.height = height; + this.depth = depth; + + // pixel data and row filter identifier size + this.pix_size = height * (width + 1); + + // deflate header, pix_size, block headers, adler32 checksum + this.data_size = 2 + this.pix_size + 5 * Math.floor((0xfffe + this.pix_size) / 0xffff) + 4; + + // offsets and sizes of Png chunks + this.ihdr_offs = 0; // IHDR offset and size + this.ihdr_size = 4 + 4 + 13 + 4; + this.plte_offs = this.ihdr_offs + this.ihdr_size; // PLTE offset and size + this.plte_size = 4 + 4 + 3 * depth + 4; + this.trns_offs = this.plte_offs + this.plte_size; // tRNS offset and size + this.trns_size = 4 + 4 + depth + 4; + this.idat_offs = this.trns_offs + this.trns_size; // IDAT offset and size + this.idat_size = 4 + 4 + this.data_size + 4; + this.iend_offs = this.idat_offs + this.idat_size; // IEND offset and size + this.iend_size = 4 + 4 + 4; + this.buffer_size = this.iend_offs + this.iend_size; // total PNG size + + this.buffer = new Array(); + this.palette = new Object(); + this.pindex = 0; + + var _crc32 = new Array(); + + // initialize buffer with zero bytes + for (var i = 0; i < this.buffer_size; i++) { + this.buffer[i] = "\x00"; + } + + // initialize non-zero elements + write(this.buffer, this.ihdr_offs, byte4(this.ihdr_size - 12), 'IHDR', byte4(width), byte4(height), "\x08\x03"); + write(this.buffer, this.plte_offs, byte4(this.plte_size - 12), 'PLTE'); + write(this.buffer, this.trns_offs, byte4(this.trns_size - 12), 'tRNS'); + write(this.buffer, this.idat_offs, byte4(this.idat_size - 12), 'IDAT'); + write(this.buffer, this.iend_offs, byte4(this.iend_size - 12), 'IEND'); + + // initialize deflate header + var header = ((8 + (7 << 4)) << 8) | (3 << 6); + header+= 31 - (header % 31); + + write(this.buffer, this.idat_offs + 8, byte2(header)); + + // initialize deflate block headers + for (var i = 0; (i << 16) - 1 < this.pix_size; i++) { + var size, bits; + if (i + 0xffff < this.pix_size) { + size = 0xffff; + bits = "\x00"; + } else { + size = this.pix_size - (i << 16) - i; + bits = "\x01"; + } + write(this.buffer, this.idat_offs + 8 + 2 + (i << 16) + (i << 2), bits, byte2lsb(size), byte2lsb(~size)); + } + + /* Create crc32 lookup table */ + for (var i = 0; i < 256; i++) { + var c = i; + for (var j = 0; j < 8; j++) { + if (c & 1) { + c = -306674912 ^ ((c >> 1) & 0x7fffffff); + } else { + c = (c >> 1) & 0x7fffffff; + } + } + _crc32[i] = c; + } + + // compute the index into a png for a given pixel + this.index = function(x,y) { + var i = y * (this.width + 1) + x + 1; + var j = this.idat_offs + 8 + 2 + 5 * Math.floor((i / 0xffff) + 1) + i; + return j; + } + + // convert a color and build up the palette + this.color = function(red, green, blue, alpha) { + + alpha = alpha >= 0 ? alpha : 255; + var color = (((((alpha << 8) | red) << 8) | green) << 8) | blue; + + if (typeof this.palette[color] == "undefined") { + if (this.pindex == this.depth) return "\x00"; + + var ndx = this.plte_offs + 8 + 3 * this.pindex; + + this.buffer[ndx + 0] = String.fromCharCode(red); + this.buffer[ndx + 1] = String.fromCharCode(green); + this.buffer[ndx + 2] = String.fromCharCode(blue); + this.buffer[this.trns_offs+8+this.pindex] = String.fromCharCode(alpha); + + this.palette[color] = String.fromCharCode(this.pindex++); + } + return this.palette[color]; + } + + // output a PNG string, Base64 encoded + this.getBase64 = function() { + + var s = this.getDump(); + + var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var c1, c2, c3, e1, e2, e3, e4; + var l = s.length; + var i = 0; + var r = ""; + + do { + c1 = s.charCodeAt(i); + e1 = c1 >> 2; + c2 = s.charCodeAt(i+1); + e2 = ((c1 & 3) << 4) | (c2 >> 4); + c3 = s.charCodeAt(i+2); + if (l < i+2) { e3 = 64; } else { e3 = ((c2 & 0xf) << 2) | (c3 >> 6); } + if (l < i+3) { e4 = 64; } else { e4 = c3 & 0x3f; } + r+= ch.charAt(e1) + ch.charAt(e2) + ch.charAt(e3) + ch.charAt(e4); + } while ((i+= 3) < l); + return r; + } + + // output a PNG string + this.getDump = function() { + + // compute adler32 of output pixels + row filter bytes + var BASE = 65521; /* largest prime smaller than 65536 */ + var NMAX = 5552; /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + var s1 = 1; + var s2 = 0; + var n = NMAX; + + for (var y = 0; y < this.height; y++) { + for (var x = -1; x < this.width; x++) { + s1+= this.buffer[this.index(x, y)].charCodeAt(0); + s2+= s1; + if ((n-= 1) == 0) { + s1%= BASE; + s2%= BASE; + n = NMAX; + } + } + } + s1%= BASE; + s2%= BASE; + write(this.buffer, this.idat_offs + this.idat_size - 8, byte4((s2 << 16) | s1)); + + // compute crc32 of the PNG chunks + function crc32(png, offs, size) { + var crc = -1; + for (var i = 4; i < size-4; i += 1) { + crc = _crc32[(crc ^ png[offs+i].charCodeAt(0)) & 0xff] ^ ((crc >> 8) & 0x00ffffff); + } + write(png, offs+size-4, byte4(crc ^ -1)); + } + + crc32(this.buffer, this.ihdr_offs, this.ihdr_size); + crc32(this.buffer, this.plte_offs, this.plte_size); + crc32(this.buffer, this.trns_offs, this.trns_size); + crc32(this.buffer, this.idat_offs, this.idat_size); + crc32(this.buffer, this.iend_offs, this.iend_size); + + // convert PNG to string + return "\211PNG\r\n\032\n"+this.buffer.join(''); + } + } + + // modified from original source to support NPM + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = PNGlib; + } else { + window.PNGlib = PNGlib; + } +})(); diff --git a/server.js b/server.js index 3d5cece3abd..fd318e62cd9 100644 --- a/server.js +++ b/server.js @@ -9,6 +9,13 @@ app.get('/', function (req, res) { res.sendFile(path.join(__dirname, 'ui', 'index.html')); }); +app.get('/aro', function (req, res) { + res.sendFile(path.join(__dirname, 'ui', 'aro.html')); +}); + +app.get('/contact', function (req, res) { + res.sendFile(path.join(__dirname, 'ui', 'contact.html')); +}); app.get('/ui/style.css', function (req, res) { res.sendFile(path.join(__dirname, 'ui', 'style.css')); }); @@ -18,7 +25,7 @@ app.get('/ui/madi.png', function (req, res) { }); -var port = 8080; // Use 8080 for local development because you might already have apache running on 80 +var port = 8080; app.listen(8080, function () { console.log(`IMAD course app listening on port ${port}!`); }); diff --git a/ui/aro.html b/ui/aro.html new file mode 100644 index 00000000000..7de7a2cb408 --- /dev/null +++ b/ui/aro.html @@ -0,0 +1,64 @@ + + + + + My Personal Webpage + + + + +
+ + + +
+
+ +
+

What You'll Find Here

+

This is my space. Here are some of my interests:

+
    +
  • Saying "That's what she said"
  • +
  • Writing codes
  • +
  • Playing Cs:GO
  • +
  • Making Soundtracks
  • +
+
+

A Few of My Famous Quotes

+

+ + "That's what she said." - Me
+ "Would I rather be feared or loved? Easy, both. I want people to be afraid of how much they love me." - Me
+ "Wikipedia is the best thing ever. Anyone in the world can write anything they want about any subject, so you know you are getting the best possible information." - Me
+ "I am Aro, and I am An INDIAN." - Me
+

+
+
+
+ +
+
+ +
+ + + \ No newline at end of file diff --git a/ui/index.html b/ui/index.html index 5a28644db45..f62e4eebe6a 100644 --- a/ui/index.html +++ b/ui/index.html @@ -2,14 +2,16 @@ +
- +

- Hi! I am your webapp. +

Hi I am Aro , More About me Aro

+
diff --git a/ui/style.css b/ui/style.css index 71a5f6acc1e..8e7d3afe1fb 100644 --- a/ui/style.css +++ b/ui/style.css @@ -1,22 +1,162 @@ body { - font-family: sans-serif; - background-color: lightgrey; - margin-top: 75px; + font-family: sans-serif; + background-color: lightgrey; + margin-top: 75px; + } + + .center { + text-align: center; + } + + .text-big { + font-size: 300%; + } + + .bold { + font-weight: bold; + } + + .img-medium { + height: 200px; + } +/* Layout */ + +body { + font:normal 12px/1.6em Arial, Helvetica, sans-serif; + color:#2a3845; + margin:0; + padding:0; + background:#FFFFFF; } -.center { - text-align: center; +p { + margin:0; + padding:0; +} + +#wrapper { + margin:0 auto; + width:632px; + border-left:1px solid #f0e9eb; + border-right:1px solid #f0e9eb; +} + +#header { + margin:0 1px; +} + +#bg { + height:36px; + background:url('') repeat-x; +} + +#main-content { + margin:0 auto; +} + +#main-image { + text-align:center; +} + +#left-column { + width:300px; + padding:0 30px 30px; + float:left; +} + +#right-column { + width:270px; + float:right; +} + +.sidebar { + width:218px; + margin:0 auto; + padding:10px 25px; + background:url('') no-repeat top; +} + +#footer { + background:#f7f7f7; + border-top:1px solid #f0e9eb; + padding:10px 15px; + clear:both; +} + +/* Global Styling */ + +a:visited, a:link { + color:#a43b55; + text-decoration:underline; + background:none; +} + +a:hover { + color:#a43b55; + text-decoration:none; + background:none; +} + +h1 { + color:#7a2e40; + margin:0 0 10px; + padding-bottom:10px; + font:normal 17px Georgia, serif; + border-bottom:1px solid #efece7; +} + +h2 { + color:#7a2e40; + margin:20px 0 10px; + padding-bottom:10px; + font:normal 17px Georgia, serif; + border-bottom:1px solid #efece7; +} + +h3 { + color:#7a2e40; + margin:10px 0; + padding-bottom:10px; + font:bold 14px Arial, Helvetica, sans-serif; + border-bottom:1px solid #efece7; +} + +ul { + padding:0; + margin:0 0 0 17px; + list-style:square url(''); +} + +.box { + background:#f7f7f7; + border:1px solid #f0e9eb; + padding:15px; +} + +#nav { + background:#06a; + padding:10px 20px; + text-align:right; + color:#f6dde3; +} + +#nav a { + margin: 0 10px; } -.text-big { - font-size: 300%; +#nav a:visited, #nav a:link { + text-decoration:none; + color:#f6dde3; } -.bold { - font-weight: bold; +#nav a:hover { + text-decoration:underline; + color:#f6dde3; } -.img-medium { - height: 200px; +#logo { + margin-bottom:20px; + font:normal 18px Georgia, serif; + color:#fa7393; }