Commits

Mariano Falcón committed 94595ca

cuenta inicial

Comments (0)

Files changed (21)

cashflow/forms.py

 from django import forms
 from django.forms import ModelForm
 
-from cashflow.models import Transaccion
+from cashflow.models import Transaccion, Cuenta
 
 from datetime import date
 
 
         return cleaned_data
 
-
+class CuentaForm(ModelForm):
+    class Meta:
+        model = Cuenta
+        exclude = ('usuario',)

cashflow/urls (compaq's conflicted copy 2010-10-26).py

+from django.conf.urls.defaults import *
+from cashflow import views
+
+
+urlpatterns = patterns('',
+    url(r'^$', views.cashflow, name='cs_cashflow'),
+    url(r'^prueba/(?P<nombre_cuenta>\w+)/$', views.cashflow2, name='cs_cashflow2'),
+    url(r'^arrow/$', views.arrow, name='cs_arrow'),
+    url(r'^ingresos/(?P<nombre_cuenta>\w+)/$', views.ingreso, name='cs_ingreso'),
+    url(r'^gastos/(?P<nombre_cuenta>\w+)|/$', views.gasto, name='cs_gasto'),
+    url(r'^welcome/$', views.welcome, name='cs_welcome'), #externo a cs
+)
     url(r'^arrow/(?P<nombre_cuenta>\w+)/$', views.arrow, name='cs_arrow'),
     url(r'^ingresos/(?P<nombre_cuenta>\w+)/$', views.ingreso, name='cs_ingreso'),
     url(r'^gastos/(?P<nombre_cuenta>\w+)/$', views.gasto, name='cs_gasto'),
+    url(r'^nueva_cuenta/$', views.nueva_cuenta, name='cs_nueva_cuenta'),
     url(r'^reportes/$', views.reportes, name='cs_reportes'),
 )

cashflow/views (compaq's conflicted copy 2010-10-26).py

+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect, Http404, HttpResponse
+from django.contrib.auth.decorators import login_required
+from django.utils import simplejson
+
+from cashflow.models import Categoria, Transaccion, Cuenta
+from cashflow.forms import TransaccionForm
+
+from datetime import date
+from dateutil import relativedelta
+
+import pdb 
+
+@login_required
+def welcome(request):
+    cuenta = Cuenta.objects.filter(usuario=request.user)[0]
+  
+    context = {
+          'cuenta': cuenta,
+     }
+    return render_to_response(
+        'cashflow/welcome.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+
+
+
+def lista_mes_anio(meses_previos, meses_sgtes):
+    '''crea una lista de tuplas (mes, anio) con los meses a mostrar en la tabla
+    #max meses_previos/sgtes=8'''
+    #TODO: mejorar funcion
+    hoy = date.today()
+    lhoy = [hoy]
+    rango_meses_previos = range(1, meses_previos+1)
+    rango_meses_sgtes = range(1, meses_sgtes+1)
+    fechas_previas = []
+    for mes_previo in rango_meses_previos:
+        fechas_previas.append(hoy+relativedelta.relativedelta(months=-mes_previo))
+    fechas_sgtes = []
+    for mes_sgte in rango_meses_sgtes:
+        fechas_sgtes.append(hoy+relativedelta.relativedelta(months=+mes_sgte))
+    if meses_previos >= 7:
+        partir = meses_previos - 7
+        lista = fechas_previas[partir:]
+    elif meses_sgtes >= 7:
+        partir = meses_sgtes -7
+        lista = fechas_sgtes[partir:]
+    else:
+        lista = fechas_previas + lhoy + fechas_sgtes
+    return lista
+
+def mesAnterior(fecha):
+    #fecha es una tupla(mes, anio)
+    if fecha[0] == 1:
+        return (12, fecha[1]-1)
+    else:
+        return (fecha[0]-1, fecha[1])
+
+#info_mes = {(mes, anio) : [ing, eg, enmano]}
+
+@login_required
+def cashflow2(request, nombre_cuenta):
+    info_mes = {}
+    info_cat = {}
+    lista_m_a = []
+    transacs = []
+    #if cuenta == "principal" :
+    """
+    try:
+        cuenta = Cuenta.objects.filter(usuario=request.user)[0]
+    except:
+        return HttpResponse('cashflow/prueba.html')
+    """
+    cuenta = Cuenta.objects.get(nombre=nombre_cuenta, usuario=request.user)
+    categorias = cuenta.categorias.all() 
+    #categorias = Categoria.objects.all()
+    for anio in range(2006,2017):
+        for mes in range(1,13):
+            info_mes[(mes,anio)] = [0, 0, 0]
+            for cat in categorias:
+                info_cat[(cat,mes,anio)] = 0
+    meses_ant = 1
+    meses_desp = 5
+    lista_fechas = lista_mes_anio(meses_ant, meses_desp)
+    lista_m_a = [(date.month, date.year) for date in lista_mes_anio(1,5)]
+    min, max = [] , []
+    min, max = lista_fechas[0], lista_fechas[len(lista_fechas)-1]
+    INGRESO = 0
+    GASTO = 1
+    ENMANO = 2
+    transacs_en_fechas = []
+    txs = cuenta.transacciones.order_by('fecha')
+    #txs = Transaccion.objects.order_by('fecha')
+    for tx in txs:
+        mesanio = ()
+        mesanio = (tx.fecha.month, tx.fecha.year)
+        if tx.frecuencia == 0:
+            if tx.tipo == 0:
+                info_mes[mesanio][INGRESO] += tx.monto
+                if tx.categoria:
+                    info_cat[(tx.categoria, mesanio[0], mesanio[1])] += tx.monto
+            else:
+                info_mes[mesanio][GASTO] += tx.monto
+                if tx.categoria:
+                    info_cat[(tx.categoria, mesanio[0], mesanio[1])] += tx.monto
+            if mesanio in lista_m_a:
+                if tx not in transacs_en_fechas:
+                    transacs_en_fechas.append(tx)
+        elif tx.frecuencia == 4:
+            meses_dif = relativedelta.relativedelta(tx.termina, tx.fecha).months
+            if tx.termina.day < tx.fecha.day:
+                meses_dif += 1
+            anios_dif = relativedelta.relativedelta(tx.termina, tx.fecha).years
+            dif = meses_dif + (anios_dif*12)
+            rango = dif + 1
+            #rango = dif + 2
+            for i in range(rango):
+                fch = tx.fecha+relativedelta.relativedelta(months=+i)
+                if (fch.month, fch.year) in lista_m_a:
+                    if tx not in transacs_en_fechas:
+                        transacs_en_fechas.append(tx)
+                if tx.tipo == 0:
+                    info_mes[(fch.month,fch.year)][INGRESO] += tx.monto
+                    if tx.categoria:
+                        info_cat[(tx.categoria, fch.month, fch.year)] += tx.monto
+                else:
+                    info_mes[(fch.month,fch.year)][GASTO] += tx.monto
+                    if tx.categoria:
+                        info_cat[(tx.categoria, fch.month, fch.year)] += tx.monto
+     
+    import operator
+    thelist = []
+    thelist = sorted((my + tuple(v) for my, v in info_mes.iteritems()),
+                 key = operator.itemgetter(1, 0))
+    thelistlist = []
+    for tupla in thelist:
+        thelistlist.append(list(tupla))
+    for i in range(len(thelistlist)):
+        if i != 0:
+            thelistlist[i][4] = thelistlist[i-1][2] - thelistlist[i-1][3] + thelistlist[i-1][4]
+    lista = []
+    for el in thelistlist:
+        if (el[0],el[1]) in lista_m_a:
+            lista.append(el)
+    
+    #lista es la lista final
+    transacciones = cuenta.transacciones.all()
+    #transacciones = Transaccion.objects.all()
+    cats_en_fechas_ing = []
+    cats_en_fechas_eg = []
+    for t in transacs_en_fechas:
+        if t.categoria and t.tipo == 0:
+            if t.categoria not in cats_en_fechas_ing:
+                cats_en_fechas_ing.append(t.categoria)
+        elif t.categoria and t.tipo == 1:
+            if t.categoria not in cats_en_fechas_eg:
+                cats_en_fechas_eg.append(t.categoria)
+
+    info_cats = []
+    for k, v in info_cat.items():
+        info_cats.append((k[0], k[1], k[2], v))
+
+    cuentas = Cuenta.objects.filter(usuario=request.user)
+
+    context = {
+        'fechas': lista_fechas, # [datetime.date] fechas en el rango
+        'info_mes': lista, # [(mes,anio):[in,eg,enma]] todas las fechas ordenadas
+        'txs': transacciones,
+        'min': min, #datetime menor mes actual
+        'max': max,
+        'currentmonth': date.today(),
+        'tx_en_fecha': transacs_en_fechas,
+        'mesanio': lista_m_a,
+        'meses_ant': meses_ant,
+        'meses_desp': meses_desp,
+        'cats': categorias,
+        'info_cat': info_cats,
+        'cats_ing': cats_en_fechas_ing,
+        'cats_eg': cats_en_fechas_eg,
+        'cuentas': cuentas,
+        'cuenta': cuenta,
+    }
+    return render_to_response(
+        'cashflow/cashflow2.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+
+
+@login_required
+def arrow(request):
+    if request.method == u'GET':
+        GET = request.GET
+        if GET.has_key(u'meses_ant') and GET.has_key(u'meses_desp'):
+            meses_ant = int(GET[u'meses_ant'])
+            meses_desp = int(GET[u'meses_desp'])
+    
+    info_mes = {}
+    lista_m_a = []
+    transacs = []
+    for anio in range(2006,2017):
+        for mes in range(1,13):
+            info_mes[(mes,anio)] = [0, 0, 0]
+    lista_fechas = lista_mes_anio(meses_ant, meses_desp)
+    lista_m_a = [(date.month, date.year) for date in lista_mes_anio(1,5)]
+    min, max = [] , []
+    min, max = lista_fechas[0], lista_fechas[len(lista_fechas)-1]
+    INGRESO = 0
+    GASTO = 1
+    ENMANO = 2
+    transacs_en_fechas = []
+    txs = cuenta.transacciones.order_by('fecha')
+    #txs = Transaccion.objects.order_by('fecha')
+    for tx in txs:
+        mesanio = ()
+        mesanio = (tx.fecha.month, tx.fecha.year)
+        if tx.frecuencia == 0:
+            if tx.tipo == 0:
+                info_mes[mesanio][INGRESO] += tx.monto
+                if tx.categoria:
+                    info_cat[(tx.categoria, mesanio[0], mesanio[1])] += tx.monto
+            else:
+                info_mes[mesanio][GASTO] += tx.monto
+                if tx.categoria:
+                    info_cat[(tx.categoria, mesanio[0], mesanio[1])] += tx.monto
+            if mesanio in lista_m_a:
+                if tx not in transacs_en_fechas:
+                    transacs_en_fechas.append(tx)
+        elif tx.frecuencia == 4:
+            meses_dif = relativedelta.relativedelta(tx.termina, tx.fecha).months
+            if tx.termina.day < tx.fecha.day:
+                meses_dif += 1
+            anios_dif = relativedelta.relativedelta(tx.termina, tx.fecha).years
+            dif = meses_dif + (anios_dif*12)
+            rango = dif + 1
+            #rango = dif + 2
+            for i in range(rango):
+                fch = tx.fecha+relativedelta.relativedelta(months=+i)
+                if (fch.month, fch.year) in lista_m_a:
+                    if tx not in transacs_en_fechas:
+                        transacs_en_fechas.append(tx)
+                if tx.tipo == 0:
+                    info_mes[(fch.month,fch.year)][INGRESO] += tx.monto
+                    if tx.categoria:
+                        info_cat[(tx.categoria, fch.month, fch.year)] += tx.monto
+                else:
+                    info_mes[(fch.month,fch.year)][GASTO] += tx.monto
+                    if tx.categoria:
+                        info_cat[(tx.categoria, fch.month, fch.year)] += tx.monto
+     
+    import operator
+    thelist = []
+    thelist = sorted((my + tuple(v) for my, v in info_mes.iteritems()),
+                 key = operator.itemgetter(1, 0))
+    thelistlist = []
+    for tupla in thelist:
+        thelistlist.append(list(tupla))
+    for i in range(len(thelistlist)):
+        if i != 0:
+            thelistlist[i][4] = thelistlist[i-1][2] - thelistlist[i-1][3] + thelistlist[i-1][4]
+    lista = []
+    for el in thelistlist:
+        if (el[0],el[1]) in lista_m_a:
+            lista.append(el)
+    
+    #lista es la lista final
+    transacciones = cuenta.transacciones.all()
+    #transacciones = Transaccion.objects.all()
+    cats_en_fechas_ing = []
+    cats_en_fechas_eg = []
+    for t in transacs_en_fechas:
+        if t.categoria and t.tipo == 0:
+            if t.categoria not in cats_en_fechas_ing:
+                cats_en_fechas_ing.append(t.categoria)
+        elif t.categoria and t.tipo == 1:
+            if t.categoria not in cats_en_fechas_eg:
+                cats_en_fechas_eg.append(t.categoria)
+
+    info_cats = []
+    for k, v in info_cat.items():
+        info_cats.append((k[0], k[1], k[2], v))
+
+    cuentas = Cuenta.objects.filter(usuario=request.user)
+
+    context = {
+        'fechas': lista_fechas, # [datetime.date] fechas en el rango
+        'info_mes': lista, # [(mes,anio):[in,eg,enma]] todas las fechas ordenadas
+        'txs': transacciones,
+        'min': min, #datetime menor mes actual
+        'max': max,
+        'currentmonth': date.today(),
+        'tx_en_fecha': transacs_en_fechas,
+        'mesanio': lista_m_a,
+        'meses_ant': meses_ant,
+        'meses_desp': meses_desp,
+        'cats': categorias,
+        'info_cat': info_cats,
+        'cats_ing': cats_en_fechas_ing,
+        'cats_eg': cats_en_fechas_eg,
+        'cuentas': cuentas,
+    }
+    return render_to_response(
+        'cashflow/arrows.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+'''
+        return render_to_response(
+        'cashflow/arrows.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+'''
+
+@login_required
+def ingreso(request, nombre_cuenta):
+    if request.method == 'POST':
+        form = TransaccionForm(data=request.POST)
+        if form.is_valid():
+            ingreso = form.save(commit=False)
+            ingreso.tipo = 0
+            ingreso.cuenta = nombre_cuenta
+            ingreso.nombre = form.cleaned_data['nombre']
+            if form.cleaned_data['categoria']:
+                ingreso.categoria = form.cleaned_data['categoria']
+            if form.cleaned_data['descripcion']:
+                ingreso.termina = form.cleaned_data['descripcion']
+            ingreso.monto = form.cleaned_data['monto']
+            ingreso.fecha = form.cleaned_data['fecha']
+            ingreso.frecuencia = form.cleaned_data['frecuencia']
+            ingreso.termina = form.cleaned_data['termina']
+            ingreso.save()
+            return HttpResponseRedirect("/cashflow/prueba/")
+    else:
+        form = TransaccionForm()
+    
+    context = {
+          'TransaccionForm': form,
+     }
+    return render_to_response(
+        'cashflow/ingreso.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+
+@login_required
+def gasto(request, nombre_cuenta):
+    if request.method == 'POST':
+        form = TransaccionForm(data=request.POST)
+        if form.is_valid():
+            ingreso = form.save(commit=False)
+            ingreso.tipo = 1
+            ingreso.cuenta = nombre_cuenta
+            ingreso.nombre = form.cleaned_data['nombre']
+            if form.cleaned_data['categoria']:
+                ingreso.categoria = form.cleaned_data['categoria']
+            if form.cleaned_data['descripcion']:
+                ingreso.termina = form.cleaned_data['descripcion']
+            ingreso.monto = form.cleaned_data['monto']
+            ingreso.fecha = form.cleaned_data['fecha']
+            ingreso.frecuencia = form.cleaned_data['frecuencia']
+            ingreso.termina = form.cleaned_data['termina']
+            ingreso.save()
+            return HttpResponseRedirect("/cashflow/prueba/")
+    else:
+        form = TransaccionForm()
+    
+    context = {
+          'TransaccionForm': form,
+     }
+    return render_to_response(
+        'cashflow/gasto.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+
+def cashflow(request):
+    info_mes = {}
+    lista_m_a = []
+    for anio in range(2005,2017):
+        for mes in range(1,13):
+            info_mes[(mes,anio)] = [0, 0, 0]
+    meses_ant = 1
+    meses_desp = 5
+    lista_fechas = lista_mes_anio(meses_ant, meses_desp)
+    lista_m_a = [(date.month, date.year) for date in lista_mes_anio(1,5)]
+    min, max = [] , []
+    min, max = lista_fechas[0], lista_fechas[len(lista_fechas)-1]
+    for mesanio in lista_m_a:
+        ingresos = 0
+        gastos = 0
+        enmano = 0
+        q = Transaccion.objects.filter(fecha__year=mesanio[1])
+        txsmes = q.filter(fecha__month=mesanio[0])
+        for tx in txsmes:
+            if tx.tipo == 0:
+                ingresos += tx.monto
+            else:
+                gastos += tx.monto
+        #ant_mes =  info_mes[(mesanio[0]-1,mesanio[1]-1)]        
+        ant_mes = info_mes[mesAnterior(mesanio)]
+        enmano = ant_mes[0] - ant_mes[1] + ant_mes[2]
+        #hash = info_mes[(mesanio[0],mesanio[1])]
+        #hash[0] , hash[1], hash[2] = ingresos, gastos, enmano
+        info_mes[(mesanio[0],mesanio[1])][0] = ingresos
+        info_mes[(mesanio[0],mesanio[1])][1] = gastos
+        info_mes[(mesanio[0],mesanio[1])][2] = enmano
+    sub_info_mes = {}
+    for k, v in info_mes.items():
+        if k in lista_m_a:
+            sub_info_mes[k] = v
+    import operator
+    thelist = []
+    thelist = sorted((my + tuple(v) for my, v in sub_info_mes.iteritems()),
+                 key = operator.itemgetter(1, 0))
+    transacciones = Transaccion.objects.all()
+
+
+    '''ordenado = {}
+    dic_final = {}
+    ordenado = sorted(sub_info_mes) #lista de tuplas: [(7, 2010), (8, 2010)]
+    for k in ordenado:
+        dic_final[k] = [info_mes[k][0], info_mes[k][1], info_mes[k][2]]
+    print dic_final'''
+    #txs_sin_cats = Transaccion.filter.all(cat=none)
+
+
+    context = {
+        'fechas': lista_fechas,
+        'info_mes': thelist,
+        'txs' : transacciones,
+        'min': min,
+        'max': max,
+        'currentmonth': date.today(),
+    }
+    return render_to_response(
+        'cashflow/cashflow.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+

cashflow/views.py

 from django.utils import simplejson
 
 from cashflow.models import Categoria, Transaccion, Cuenta
-from cashflow.forms import TransaccionForm
+from cashflow.forms import TransaccionForm, CuentaForm
 
 from datetime import date
 from dateutil import relativedelta
 
 @login_required
 def welcome(request):
-    cuenta = Cuenta.objects.filter(usuario=request.user)[0]
+    try:
+        cuenta = Cuenta.objects.filter(usuario=request.user)[0]
+    except:
+        cuenta = "Inicial"
   
     context = {
           'cuenta': cuenta,
 #info_mes = {(mes, anio) : [ing, eg, enmano]}
 
 @login_required
-def cashflow2(request, nombre_cuenta):
+def cashflow2(request, nombre_cuenta="Inicial"):
+    if nombre_cuenta == "Inicial":
+        uri = "/cashflow/nueva_cuenta"
+        return HttpResponseRedirect(uri)     
     info_mes = {}
     info_cat = {}
     lista_m_a = []
         context_instance = RequestContext(request),
     )
 
+@login_required
+def nueva_cuenta(request):
+    if request.method == 'POST':
+        form = CuentaForm(data=request.POST)
+        if form.is_valid():
+            nueva_cuenta = form.save(commit=False)
+            nueva_cuenta.usuario = request.user
+            s = str(form.cleaned_data['nombre'])
+            s = s.replace(" ", "")
+            nueva_cuenta.nombre = s
+            nueva_cuenta.save()
+            uri = ("/cashflow/prueba/%s") % s
+            return HttpResponseRedirect(uri)
+    else:
+        form = CuentaForm()
+    
+    context = {
+          'CuentaForm': form,
+     }
+    return render_to_response(
+        'cashflow/nueva_cuenta.html',
+        context,
+        context_instance = RequestContext(request),
+    )
+
 def cashflow(request):
     info_mes = {}
     lista_m_a = []

media/css/forms.css

+/* --------------------------------------------------------------
+
+   forms.css
+   * Sets up some default styling for forms
+   * Gives you classes to enhance your forms
+
+   Usage:
+   * For text fields, use class .title or .text
+   * For inline forms, use .inline (even when using columns)
+
+-------------------------------------------------------------- */
+
+/* 
+	A special hack is included for IE8 since it does not apply padding 
+	correctly on fieldsets
+ */ 
+label       { font-weight: bold; }
+fieldset    { padding:0 1.4em 1.4em 1.4em; margin: 0 0 1.5em 0; border: 1px solid #ccc; }
+legend      { font-weight: bold; font-size:1.2em; margin-top:-0.2em; margin-bottom:1em; }
+
+fieldset, #IE8#HACK { padding-top:1.4em; } 
+legend, #IE8#HACK { margin-top:0; margin-bottom:0; }
+
+/* Form fields
+-------------------------------------------------------------- */
+
+/* 
+  Attribute selectors are used to differentiate the different types 
+  of input elements, but to support old browsers, you will have to 
+  add classes for each one. ".title" simply creates a large text  
+  field, this is purely for looks.
+ */
+input[type=text], input[type=password],
+input.text, input.title,
+textarea {
+  background-color:#fff;
+  border:1px solid #bbb;
+}
+input[type=text]:focus, input[type=password]:focus,
+input.text:focus, input.title:focus,
+textarea:focus {
+  border-color:#666;
+}
+select { background-color:#fff; border-width:1px; border-style:solid; }
+
+input[type=text], input[type=password],
+input.text, input.title,
+textarea, select {
+  margin:0.5em 0;
+}
+
+input.text,
+input.title   { width: 300px; padding:5px; }
+input.title   { font-size:1.5em; }
+textarea      { width: 390px; height: 250px; padding:5px; }
+
+/* 
+  This is to be used on forms where a variety of elements are 
+  placed side-by-side. Use the p tag to denote a line. 
+ */
+form.inline { line-height:3; }
+form.inline p { margin-bottom:0; }
+
+
+/* Success, info, notice and error/alert boxes
+-------------------------------------------------------------- */
+
+.error,
+.alert, 
+.notice,
+.success, 
+.info 			{ padding: 0.8em; margin-bottom: 1em; border: 2px solid #ddd; }
+
+.error, .alert { background: #fbe3e4; color: #8a1f11; border-color: #fbc2c4; }
+.notice     { background: #fff6bf; color: #514721; border-color: #ffd324; }
+.success    { background: #e6efc2; color: #264409; border-color: #c6d880; }
+.info 			{ background: #d5edf8; color: #205791; border-color: #92cae4; }
+.error a, .alert a { color: #8a1f11; }
+.notice a   { color: #514721; }
+.success a  { color: #264409; }
+.info a			{ color: #205791; }

media/css/grid.css

+/* --------------------------------------------------------------
+
+   grid.css
+   * Sets up an easy-to-use grid of 24 columns.
+
+   By default, the grid is 950px wide, with 24 columns
+   spanning 30px, and a 10px margin between columns.
+
+   If you need fewer or more columns, namespaces or semantic
+   element names, use the compressor script (lib/compress.rb)
+
+-------------------------------------------------------------- */
+
+/* A container should group all your columns. */
+.container {
+  width: 950px;
+  margin: 0 auto;
+}
+
+/* Use this class on any .span / container to see the grid. */
+.showgrid {
+  background: url(src/grid.png);
+}
+
+
+/* Columns
+-------------------------------------------------------------- */
+
+/* Sets up basic grid floating and margin. */
+.column, .span-1, .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8, .span-9, .span-10, .span-11, .span-12, .span-13, .span-14, .span-15, .span-16, .span-17, .span-18, .span-19, .span-20, .span-21, .span-22, .span-23, .span-24 {
+  float: left;
+  margin-right: 10px;
+}
+
+/* The last column in a row needs this class. */
+.last { margin-right: 0; }
+
+/* Use these classes to set the width of a column. */
+.span-1 {width: 30px;}
+
+.span-2 {width: 70px;}
+.span-3 {width: 110px;}
+.span-4 {width: 150px;}
+.span-5 {width: 190px;}
+.span-6 {width: 230px;}
+.span-7 {width: 270px;}
+.span-8 {width: 310px;}
+.span-9 {width: 350px;}
+.span-10 {width: 390px;}
+.span-11 {width: 430px;}
+.span-12 {width: 470px;}
+.span-13 {width: 510px;}
+.span-14 {width: 550px;}
+.span-15 {width: 590px;}
+.span-16 {width: 630px;}
+.span-17 {width: 670px;}
+.span-18 {width: 710px;}
+.span-19 {width: 750px;}
+.span-20 {width: 790px;}
+.span-21 {width: 830px;}
+.span-22 {width: 870px;}
+.span-23 {width: 910px;}
+.span-24 {width:950px; margin-right:0;}
+
+/* Use these classes to set the width of an input. */
+input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {
+  border-left-width: 1px;
+  border-right-width: 1px;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+
+input.span-1, textarea.span-1 { width: 18px; }
+input.span-2, textarea.span-2 { width: 58px; }
+input.span-3, textarea.span-3 { width: 98px; }
+input.span-4, textarea.span-4 { width: 138px; }
+input.span-5, textarea.span-5 { width: 178px; }
+input.span-6, textarea.span-6 { width: 218px; }
+input.span-7, textarea.span-7 { width: 258px; }
+input.span-8, textarea.span-8 { width: 298px; }
+input.span-9, textarea.span-9 { width: 338px; }
+input.span-10, textarea.span-10 { width: 378px; }
+input.span-11, textarea.span-11 { width: 418px; }
+input.span-12, textarea.span-12 { width: 458px; }
+input.span-13, textarea.span-13 { width: 498px; }
+input.span-14, textarea.span-14 { width: 538px; }
+input.span-15, textarea.span-15 { width: 578px; }
+input.span-16, textarea.span-16 { width: 618px; }
+input.span-17, textarea.span-17 { width: 658px; }
+input.span-18, textarea.span-18 { width: 698px; }
+input.span-19, textarea.span-19 { width: 738px; }
+input.span-20, textarea.span-20 { width: 778px; }
+input.span-21, textarea.span-21 { width: 818px; }
+input.span-22, textarea.span-22 { width: 858px; }
+input.span-23, textarea.span-23 { width: 898px; }
+input.span-24, textarea.span-24 { width: 938px; }
+
+/* Add these to a column to append empty cols. */
+
+.append-1 { padding-right: 40px;}
+.append-2 { padding-right: 80px;}
+.append-3 { padding-right: 120px;}
+.append-4 { padding-right: 160px;}
+.append-5 { padding-right: 200px;}
+.append-6 { padding-right: 240px;}
+.append-7 { padding-right: 280px;}
+.append-8 { padding-right: 320px;}
+.append-9 { padding-right: 360px;}
+.append-10 { padding-right: 400px;}
+.append-11 { padding-right: 440px;}
+.append-12 { padding-right: 480px;}
+.append-13 { padding-right: 520px;}
+.append-14 { padding-right: 560px;}
+.append-15 { padding-right: 600px;}
+.append-16 { padding-right: 640px;}
+.append-17 { padding-right: 680px;}
+.append-18 { padding-right: 720px;}
+.append-19 { padding-right: 760px;}
+.append-20 { padding-right: 800px;}
+.append-21 { padding-right: 840px;}
+.append-22 { padding-right: 880px;}
+.append-23 { padding-right: 920px;}
+
+/* Add these to a column to prepend empty cols. */
+
+.prepend-1 { padding-left: 40px;}
+.prepend-2 { padding-left: 80px;}
+.prepend-3 { padding-left: 120px;}
+.prepend-4 { padding-left: 160px;}
+.prepend-5 { padding-left: 200px;}
+.prepend-6 { padding-left: 240px;}
+.prepend-7 { padding-left: 280px;}
+.prepend-8 { padding-left: 320px;}
+.prepend-9 { padding-left: 360px;}
+.prepend-10 { padding-left: 400px;}
+.prepend-11 { padding-left: 440px;}
+.prepend-12 { padding-left: 480px;}
+.prepend-13 { padding-left: 520px;}
+.prepend-14 { padding-left: 560px;}
+.prepend-15 { padding-left: 600px;}
+.prepend-16 { padding-left: 640px;}
+.prepend-17 { padding-left: 680px;}
+.prepend-18 { padding-left: 720px;}
+.prepend-19 { padding-left: 760px;}
+.prepend-20 { padding-left: 800px;}
+.prepend-21 { padding-left: 840px;}
+.prepend-22 { padding-left: 880px;}
+.prepend-23 { padding-left: 920px;}
+
+
+/* Border on right hand side of a column. */
+.border {
+  padding-right: 4px;
+  margin-right: 5px;
+  border-right: 1px solid #ddd;
+}
+
+/* Border with more whitespace, spans one column. */
+.colborder {
+  padding-right: 24px;
+  margin-right: 25px;
+  border-right: 1px solid #ddd;
+}
+
+
+/* Use these classes on an element to push it into the
+next column, or to pull it into the previous column.  */
+
+
+.pull-1 { margin-left: -40px; }
+.pull-2 { margin-left: -80px; }
+.pull-3 { margin-left: -120px; }
+.pull-4 { margin-left: -160px; }
+.pull-5 { margin-left: -200px; }
+.pull-6 { margin-left: -240px; }
+.pull-7 { margin-left: -280px; }
+.pull-8 { margin-left: -320px; }
+.pull-9 { margin-left: -360px; }
+.pull-10 { margin-left: -400px; }
+.pull-11 { margin-left: -440px; }
+.pull-12 { margin-left: -480px; }
+.pull-13 { margin-left: -520px; }
+.pull-14 { margin-left: -560px; }
+.pull-15 { margin-left: -600px; }
+.pull-16 { margin-left: -640px; }
+.pull-17 { margin-left: -680px; }
+.pull-18 { margin-left: -720px; }
+.pull-19 { margin-left: -760px; }
+.pull-20 { margin-left: -800px; }
+.pull-21 { margin-left: -840px; }
+.pull-22 { margin-left: -880px; }
+.pull-23 { margin-left: -920px; }
+.pull-24 { margin-left: -960px; }
+
+.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float: left; position:relative;}
+
+
+.push-1 { margin: 0 -40px 1.5em 40px; }
+.push-2 { margin: 0 -80px 1.5em 80px; }
+.push-3 { margin: 0 -120px 1.5em 120px; }
+.push-4 { margin: 0 -160px 1.5em 160px; }
+.push-5 { margin: 0 -200px 1.5em 200px; }
+.push-6 { margin: 0 -240px 1.5em 240px; }
+.push-7 { margin: 0 -280px 1.5em 280px; }
+.push-8 { margin: 0 -320px 1.5em 320px; }
+.push-9 { margin: 0 -360px 1.5em 360px; }
+.push-10 { margin: 0 -400px 1.5em 400px; }
+.push-11 { margin: 0 -440px 1.5em 440px; }
+.push-12 { margin: 0 -480px 1.5em 480px; }
+.push-13 { margin: 0 -520px 1.5em 520px; }
+.push-14 { margin: 0 -560px 1.5em 560px; }
+.push-15 { margin: 0 -600px 1.5em 600px; }
+.push-16 { margin: 0 -640px 1.5em 640px; }
+.push-17 { margin: 0 -680px 1.5em 680px; }
+.push-18 { margin: 0 -720px 1.5em 720px; }
+.push-19 { margin: 0 -760px 1.5em 760px; }
+.push-20 { margin: 0 -800px 1.5em 800px; }
+.push-21 { margin: 0 -840px 1.5em 840px; }
+.push-22 { margin: 0 -880px 1.5em 880px; }
+.push-23 { margin: 0 -920px 1.5em 920px; }
+.push-24 { margin: 0 -960px 1.5em 960px; }
+
+.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float: left; position:relative;}
+
+
+/* Misc classes and elements
+-------------------------------------------------------------- */
+
+/* In case you need to add a gutter above/below an element */
+div.prepend-top, .prepend-top {
+  margin-top:1.5em;
+}
+div.append-bottom, .append-bottom {
+  margin-bottom:1.5em;
+}
+
+/* Use a .box to create a padded box inside a column.  */
+.box {
+  padding: 1.5em;
+  margin-bottom: 1.5em;
+  background: #e5eCf9;
+}
+
+/* Use this to create a horizontal ruler across a column. */
+hr {
+  background: #ddd;
+  color: #ddd;
+  clear: both;
+  float: none;
+  width: 100%;
+  height: 1px;
+  margin: 0 0 1.45em;
+  border: none;
+}
+
+hr.space {
+  background: #fff;
+  color: #fff;
+  visibility: hidden;
+}
+
+
+/* Clearing floats without extra markup
+   Based on How To Clear Floats Without Structural Markup by PiE
+   [http://www.positioniseverything.net/easyclearing.html] */
+
+.clearfix:after, .container:after {
+  content: "\0020";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+  overflow:hidden;
+}
+.clearfix, .container {display: block;}
+
+/* Regular clearing
+   apply to column that should drop below previous ones. */
+
+.clear { clear:both; }
+/* --------------------------------------------------------------
+
+   ie.css
+
+   Contains every hack for Internet Explorer,
+   so that our core files stay sweet and nimble.
+
+-------------------------------------------------------------- */
+
+/* Make sure the layout is centered in IE5 */
+body { text-align: center; }
+.container { text-align: left; }
+
+/* Fixes IE margin bugs */
+* html .column, * html .span-1, * html .span-2,
+* html .span-3, * html .span-4, * html .span-5,
+* html .span-6, * html .span-7, * html .span-8,
+* html .span-9, * html .span-10, * html .span-11,
+* html .span-12, * html .span-13, * html .span-14,
+* html .span-15, * html .span-16, * html .span-17,
+* html .span-18, * html .span-19, * html .span-20,
+* html .span-21, * html .span-22, * html .span-23,
+* html .span-24 { display:inline; overflow-x: hidden; }
+
+
+/* Elements
+-------------------------------------------------------------- */
+
+/* Fixes incorrect styling of legend in IE6. */
+* html legend { margin:0px -8px 16px 0; padding:0; }
+
+/* Fixes wrong line-height on sup/sub in IE. */
+sup { vertical-align:text-top; }
+sub { vertical-align:text-bottom; }
+
+/* Fixes IE7 missing wrapping of code elements. */
+html>body p code { *white-space: normal; }
+
+/* IE 6&7 has problems with setting proper <hr> margins. */
+hr  { margin:-8px auto 11px; }
+
+/* Explicitly set interpolation, allowing dynamically resized images to not look horrible */
+img { -ms-interpolation-mode:bicubic; }
+
+/* Clearing
+-------------------------------------------------------------- */
+
+/* Makes clearfix actually work in IE */
+.clearfix, .container { display:inline-block; }
+* html .clearfix,
+* html .container { height:1%; }
+
+
+/* Forms
+-------------------------------------------------------------- */
+
+/* Fixes padding on fieldset */
+fieldset { padding-top:0; }
+legend { margin-top:-0.2em; margin-bottom:1em; margin-left:-0.5em; }
+
+/* Makes classic textareas in IE 6 resemble other browsers */
+textarea { overflow:auto; }
+
+/* Makes labels behave correctly in IE 6 and 7 */
+label { vertical-align:middle; position:relative; top:-0.25em; }
+
+/* Fixes rule that IE 6 ignores */
+input.text, input.title, textarea { background-color:#fff; border:1px solid #bbb; }
+input.text:focus, input.title:focus { border-color:#666; }
+input.text, input.title, textarea, select { margin:0.5em 0; }
+input.checkbox, input.radio { position:relative; top:.25em; }
+
+/* Fixes alignment of inline form elements */
+form.inline div, form.inline p { vertical-align:middle; }
+form.inline input.checkbox, form.inline input.radio,
+form.inline input.button, form.inline button {
+  margin:0.5em 0;
+}
+button, input.button { position:relative;top:0.25em; }

media/css/print.css

-#hiderow,
-.delete {
-  display: none;
-}
+/* --------------------------------------------------------------
+
+   print.css
+   * Gives you some sensible styles for printing pages.
+   * See Readme file in this directory for further instructions.
+
+   Some additions you'll want to make, customized to your markup:
+   #header, #footer, #navigation { display:none; }
+
+-------------------------------------------------------------- */
+
+body {
+  line-height: 1.5;
+  font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
+  color:#000;
+  background: none;
+  font-size: 10pt;
+}
+
+
+/* Layout
+-------------------------------------------------------------- */
+
+.container {
+  background: none;
+}
+
+hr {
+  background:#ccc;
+  color:#ccc;
+  width:100%;
+  height:2px;
+  margin:2em 0;
+  padding:0;
+  border:none;
+}
+hr.space {
+  background: #fff;
+  color: #fff;
+  visibility: hidden;
+}
+
+
+/* Text
+-------------------------------------------------------------- */
+
+h1,h2,h3,h4,h5,h6 { font-family: "Helvetica Neue", Arial, "Lucida Grande", sans-serif; }
+code { font:.9em "Courier New", Monaco, Courier, monospace; }
+
+a img { border:none; }
+p img.top { margin-top: 0; }
+
+blockquote {
+  margin:1.5em;
+  padding:1em;
+  font-style:italic;
+  font-size:.9em;
+}
+
+.small  { font-size: .9em; }
+.large  { font-size: 1.1em; }
+.quiet  { color: #999; }
+.hide   { display:none; }
+
+
+/* Links
+-------------------------------------------------------------- */
+
+a:link, a:visited {
+  background: transparent;
+  font-weight:700;
+  text-decoration: underline;
+}
+
+/* 
+	This has been the source of many questions in the past. This 
+	snippet of CSS appends the URL of each link within the text. 
+	The idea is that users printing your webpage will want to know 
+	the URLs they go to. If you want to remove this functionality, 
+	comment out this snippet and make sure to re-compress your files.
+ */
+a:link:after, a:visited:after {
+  content: " (" attr(href) ")";
+  font-size: 90%;
+}
+
+/* If you're having trouble printing relative links, uncomment and customize this:
+   (note: This is valid CSS3, but it still won't go through the W3C CSS Validator) */
+
+/* a[href^="/"]:after {
+  content: " (http://www.yourdomain.com" attr(href) ") ";
+} */

media/css/reset.css

+/* --------------------------------------------------------------
+
+   reset.css
+   * Resets default browser CSS.
+
+-------------------------------------------------------------- */
+
+html { 
+	margin:0; 
+	padding:0; 
+	border:0; 
+}
+
+body, div, span, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, code,
+del, dfn, em, img, q, dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, dialog, figure, footer, header,
+hgroup, nav, section {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-weight: inherit;
+  font-style: inherit;
+  font-size: 100%;
+  font-family: inherit;
+  vertical-align: baseline;
+}
+
+/* This helps to make newer HTML5 elements behave like DIVs in older browers */ 
+article, aside, dialog, figure, footer, header,
+hgroup, nav, section {
+    display:block;
+}
+
+/* Line-height should always be unitless! */
+body {
+  line-height: 1.5;
+  background: white; 
+}
+
+/* Tables still need 'cellspacing="0"' in the markup. */
+table { 
+	border-collapse: separate; 
+	border-spacing: 0; 
+}
+/* float:none prevents the span-x classes from breaking table-cell display */
+caption, th, td { 
+	text-align: left; 
+	font-weight: normal; 
+	float:none !important; 
+}
+table, th, td { 
+	vertical-align: middle; 
+}
+
+/* Remove possible quote marks (") from <q>, <blockquote>. */
+blockquote:before, blockquote:after, q:before, q:after { content: ''; }
+blockquote, q { quotes: "" ""; }
+
+/* Remove annoying border on linked images. */
+a img { border: none; }
+
+/* Remember to define your own focus styles! */
+:focus { outline: 0; }

media/css/screen.css

+/* -----------------------------------------------------------------------
+
+
+ Blueprint CSS Framework 1.0
+ http://blueprintcss.org
+
+   * Copyright (c) 2007-Present. See LICENSE for more info.
+   * See README for instructions on how to use Blueprint.
+   * For credits and origins, see AUTHORS.
+   * This is a compressed file. See the sources in the 'src' directory.
+
+----------------------------------------------------------------------- */
+
+/* reset.css */
+html {margin:0;padding:0;border:0;}
+body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, nav, section {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
+article, aside, dialog, figure, footer, header, hgroup, nav, section {display:block;}
+body {line-height:1.5;background:white;}
+table {border-collapse:separate;border-spacing:0;}
+caption, th, td {text-align:left;font-weight:normal;float:none !important;}
+table, th, td {vertical-align:middle;}
+blockquote:before, blockquote:after, q:before, q:after {content:'';}
+blockquote, q {quotes:"" "";}
+a img {border:none;}
+:focus {outline:0;}
+
+/* typography.css */
+html {font-size:100.01%;}
+body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
+h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
+h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
+h2 {font-size:2em;margin-bottom:0.75em;}
+h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
+h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
+h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
+h6 {font-size:1em;font-weight:bold;}
+h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
+p {margin:0 0 1.5em;}
+.left {float:left !important;}
+p .left {margin:1.5em 1.5em 1.5em 0;padding:0;}
+.right {float:right !important;}
+p .right {margin:1.5em 0 1.5em 1.5em;padding:0;}
+a:focus, a:hover {color:#09f;}
+a {color:#06c;text-decoration:underline;}
+blockquote {margin:1.5em;color:#666;font-style:italic;}
+strong, dfn {font-weight:bold;}
+em, dfn {font-style:italic;}
+sup, sub {line-height:0;}
+abbr, acronym {border-bottom:1px dotted #666;}
+address {margin:0 0 1.5em;font-style:italic;}
+del {color:#666;}
+pre {margin:1.5em 0;white-space:pre;}
+pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
+li ul, li ol {margin:0;}
+ul, ol {margin:0 1.5em 1.5em 0;padding-left:1.5em;}
+ul {list-style-type:disc;}
+ol {list-style-type:decimal;}
+dl {margin:0 0 1.5em 0;}
+dl dt {font-weight:bold;}
+dd {margin-left:1.5em;}
+table {margin-bottom:1.4em;width:100%;}
+th {font-weight:bold;}
+thead th {background:#c3d9ff;}
+th, td, caption {padding:4px 10px 4px 5px;}
+tbody tr:nth-child(even) td, tbody tr.even td {background:#e5ecf9;}
+tfoot {font-style:italic;}
+caption {background:#eee;}
+.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
+.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
+.hide {display:none;}
+.quiet {color:#666;}
+.loud {color:#000;}
+.highlight {background:#ff0;}
+.added {background:#060;color:#fff;}
+.removed {background:#900;color:#fff;}
+.first {margin-left:0;padding-left:0;}
+.last {margin-right:0;padding-right:0;}
+.top {margin-top:0;padding-top:0;}
+.bottom {margin-bottom:0;padding-bottom:0;}
+
+/* forms.css */
+label {font-weight:bold;}
+fieldset {padding:0 1.4em 1.4em 1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
+legend {font-weight:bold;font-size:1.2em;margin-top:-0.2em;margin-bottom:1em;}
+fieldset, #IE8#HACK {padding-top:1.4em;}
+legend, #IE8#HACK {margin-top:0;margin-bottom:0;}
+input[type=text], input[type=password], input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;}
+input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus {border-color:#666;}
+select {background-color:#fff;border-width:1px;border-style:solid;}
+input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;}
+input.text, input.title {width:300px;padding:5px;}
+input.title {font-size:1.5em;}
+textarea {width:390px;height:250px;padding:5px;}
+form.inline {line-height:3;}
+form.inline p {margin-bottom:0;}
+.error, .alert, .notice, .success, .info {padding:0.8em;margin-bottom:1em;border:2px solid #ddd;}
+.error, .alert {background:#fbe3e4;color:#8a1f11;border-color:#fbc2c4;}
+.notice {background:#fff6bf;color:#514721;border-color:#ffd324;}
+.success {background:#e6efc2;color:#264409;border-color:#c6d880;}
+.info {background:#d5edf8;color:#205791;border-color:#92cae4;}
+.error a, .alert a {color:#8a1f11;}
+.notice a {color:#514721;}
+.success a {color:#264409;}
+.info a {color:#205791;}
+
+/* grid.css */
+.container {width:950px;margin:0 auto;}
+.showgrid {background:url(src/grid.png);}
+.column, .span-1, .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8, .span-9, .span-10, .span-11, .span-12, .span-13, .span-14, .span-15, .span-16, .span-17, .span-18, .span-19, .span-20, .span-21, .span-22, .span-23, .span-24 {float:left;margin-right:10px;}
+.last {margin-right:0;}
+.span-1 {width:30px;}
+.span-2 {width:70px;}
+.span-3 {width:110px;}
+.span-4 {width:150px;}
+.span-5 {width:190px;}
+.span-6 {width:230px;}
+.span-7 {width:270px;}
+.span-8 {width:310px;}
+.span-9 {width:350px;}
+.span-10 {width:390px;}
+.span-11 {width:430px;}
+.span-12 {width:470px;}
+.span-13 {width:510px;}
+.span-14 {width:550px;}
+.span-15 {width:590px;}
+.span-16 {width:630px;}
+.span-17 {width:670px;}
+.span-18 {width:710px;}
+.span-19 {width:750px;}
+.span-20 {width:790px;}
+.span-21 {width:830px;}
+.span-22 {width:870px;}
+.span-23 {width:910px;}
+.span-24 {width:950px;margin-right:0;}
+input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {border-left-width:1px;border-right-width:1px;padding-left:5px;padding-right:5px;}
+input.span-1, textarea.span-1 {width:18px;}
+input.span-2, textarea.span-2 {width:58px;}
+input.span-3, textarea.span-3 {width:98px;}
+input.span-4, textarea.span-4 {width:138px;}
+input.span-5, textarea.span-5 {width:178px;}
+input.span-6, textarea.span-6 {width:218px;}
+input.span-7, textarea.span-7 {width:258px;}
+input.span-8, textarea.span-8 {width:298px;}
+input.span-9, textarea.span-9 {width:338px;}
+input.span-10, textarea.span-10 {width:378px;}
+input.span-11, textarea.span-11 {width:418px;}
+input.span-12, textarea.span-12 {width:458px;}
+input.span-13, textarea.span-13 {width:498px;}
+input.span-14, textarea.span-14 {width:538px;}
+input.span-15, textarea.span-15 {width:578px;}
+input.span-16, textarea.span-16 {width:618px;}
+input.span-17, textarea.span-17 {width:658px;}
+input.span-18, textarea.span-18 {width:698px;}
+input.span-19, textarea.span-19 {width:738px;}
+input.span-20, textarea.span-20 {width:778px;}
+input.span-21, textarea.span-21 {width:818px;}
+input.span-22, textarea.span-22 {width:858px;}
+input.span-23, textarea.span-23 {width:898px;}
+input.span-24, textarea.span-24 {width:938px;}
+.append-1 {padding-right:40px;}
+.append-2 {padding-right:80px;}
+.append-3 {padding-right:120px;}
+.append-4 {padding-right:160px;}
+.append-5 {padding-right:200px;}
+.append-6 {padding-right:240px;}
+.append-7 {padding-right:280px;}
+.append-8 {padding-right:320px;}
+.append-9 {padding-right:360px;}
+.append-10 {padding-right:400px;}
+.append-11 {padding-right:440px;}
+.append-12 {padding-right:480px;}
+.append-13 {padding-right:520px;}
+.append-14 {padding-right:560px;}
+.append-15 {padding-right:600px;}
+.append-16 {padding-right:640px;}
+.append-17 {padding-right:680px;}
+.append-18 {padding-right:720px;}
+.append-19 {padding-right:760px;}
+.append-20 {padding-right:800px;}
+.append-21 {padding-right:840px;}
+.append-22 {padding-right:880px;}
+.append-23 {padding-right:920px;}
+.prepend-1 {padding-left:40px;}
+.prepend-2 {padding-left:80px;}
+.prepend-3 {padding-left:120px;}
+.prepend-4 {padding-left:160px;}
+.prepend-5 {padding-left:200px;}
+.prepend-6 {padding-left:240px;}
+.prepend-7 {padding-left:280px;}
+.prepend-8 {padding-left:320px;}
+.prepend-9 {padding-left:360px;}
+.prepend-10 {padding-left:400px;}
+.prepend-11 {padding-left:440px;}
+.prepend-12 {padding-left:480px;}
+.prepend-13 {padding-left:520px;}
+.prepend-14 {padding-left:560px;}
+.prepend-15 {padding-left:600px;}
+.prepend-16 {padding-left:640px;}
+.prepend-17 {padding-left:680px;}
+.prepend-18 {padding-left:720px;}
+.prepend-19 {padding-left:760px;}
+.prepend-20 {padding-left:800px;}
+.prepend-21 {padding-left:840px;}
+.prepend-22 {padding-left:880px;}
+.prepend-23 {padding-left:920px;}
+.border {padding-right:4px;margin-right:5px;border-right:1px solid #ddd;}
+.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #ddd;}
+.pull-1 {margin-left:-40px;}
+.pull-2 {margin-left:-80px;}
+.pull-3 {margin-left:-120px;}
+.pull-4 {margin-left:-160px;}
+.pull-5 {margin-left:-200px;}
+.pull-6 {margin-left:-240px;}
+.pull-7 {margin-left:-280px;}
+.pull-8 {margin-left:-320px;}
+.pull-9 {margin-left:-360px;}
+.pull-10 {margin-left:-400px;}
+.pull-11 {margin-left:-440px;}
+.pull-12 {margin-left:-480px;}
+.pull-13 {margin-left:-520px;}
+.pull-14 {margin-left:-560px;}
+.pull-15 {margin-left:-600px;}
+.pull-16 {margin-left:-640px;}
+.pull-17 {margin-left:-680px;}
+.pull-18 {margin-left:-720px;}
+.pull-19 {margin-left:-760px;}
+.pull-20 {margin-left:-800px;}
+.pull-21 {margin-left:-840px;}
+.pull-22 {margin-left:-880px;}
+.pull-23 {margin-left:-920px;}
+.pull-24 {margin-left:-960px;}
+.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;}
+.push-1 {margin:0 -40px 1.5em 40px;}
+.push-2 {margin:0 -80px 1.5em 80px;}
+.push-3 {margin:0 -120px 1.5em 120px;}
+.push-4 {margin:0 -160px 1.5em 160px;}
+.push-5 {margin:0 -200px 1.5em 200px;}
+.push-6 {margin:0 -240px 1.5em 240px;}
+.push-7 {margin:0 -280px 1.5em 280px;}
+.push-8 {margin:0 -320px 1.5em 320px;}
+.push-9 {margin:0 -360px 1.5em 360px;}
+.push-10 {margin:0 -400px 1.5em 400px;}
+.push-11 {margin:0 -440px 1.5em 440px;}
+.push-12 {margin:0 -480px 1.5em 480px;}
+.push-13 {margin:0 -520px 1.5em 520px;}
+.push-14 {margin:0 -560px 1.5em 560px;}
+.push-15 {margin:0 -600px 1.5em 600px;}
+.push-16 {margin:0 -640px 1.5em 640px;}
+.push-17 {margin:0 -680px 1.5em 680px;}
+.push-18 {margin:0 -720px 1.5em 720px;}
+.push-19 {margin:0 -760px 1.5em 760px;}
+.push-20 {margin:0 -800px 1.5em 800px;}
+.push-21 {margin:0 -840px 1.5em 840px;}
+.push-22 {margin:0 -880px 1.5em 880px;}
+.push-23 {margin:0 -920px 1.5em 920px;}
+.push-24 {margin:0 -960px 1.5em 960px;}
+.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:left;position:relative;}
+div.prepend-top, .prepend-top {margin-top:1.5em;}
+div.append-bottom, .append-bottom {margin-bottom:1.5em;}
+.box {padding:1.5em;margin-bottom:1.5em;background:#e5eCf9;}
+hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:1px;margin:0 0 1.45em;border:none;}
+hr.space {background:#fff;color:#fff;visibility:hidden;}
+.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
+.clearfix, .container {display:block;}
+.clear {clear:both;}

media/css/style.css

 }
 #footer{
 	position: absolute;
-	bottom: 0px;
-	width: 100%;
-	clear: both;
+	bottom: -1px;
+	width: 100%;	
 	text-align: center;
 }
 /*
 }
 #cuentas {
     float: left;
-    top : -10;
-    right: 10;
     width: 200px;
 }
 #main {
     background-image: url(../images/bg_main1.gif);
     background-position: center top;
     background-repeat: repeat-x;
-    position: relative;
 }
 /*Reportes*/
+#contenedor {
+    position: relative;
+    margin-left: 25px;
+}
+.graficos {   
+    width:450px;
+    height:400px;
+    margin-bottom: 40px;
+}
+.chart {
+    width:1000px;
+    height:400px;
+    clear: both;
+}
+#chart1 {
+    float: left;
+    margin-right: 100px;
+}
+#chart2 {
+    float: left;
+}
+/* Forms */
+#list {
+    list-style: none;
+}
+#list li {
+    margin-bottom: 10px; 
+}

media/css/typography.css

+/* --------------------------------------------------------------
+
+   typography.css
+   * Sets up some sensible default typography.
+
+-------------------------------------------------------------- */
+
+/* Default font settings.
+   The font-size percentage is of 16px. (0.75 * 16px = 12px) */
+html { font-size:100.01%; }
+body {
+  font-size: 75%;
+  color: #222;
+  background: #fff;
+  font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
+}
+
+
+/* Headings
+-------------------------------------------------------------- */
+
+h1,h2,h3,h4,h5,h6 { font-weight: normal; color: #111; }
+
+h1 { font-size: 3em; line-height: 1; margin-bottom: 0.5em; }
+h2 { font-size: 2em; margin-bottom: 0.75em; }
+h3 { font-size: 1.5em; line-height: 1; margin-bottom: 1em; }
+h4 { font-size: 1.2em; line-height: 1.25; margin-bottom: 1.25em; }
+h5 { font-size: 1em; font-weight: bold; margin-bottom: 1.5em; }
+h6 { font-size: 1em; font-weight: bold; }
+
+h1 img, h2 img, h3 img,
+h4 img, h5 img, h6 img {
+  margin: 0;
+}
+
+
+/* Text elements
+-------------------------------------------------------------- */
+
+p           { margin: 0 0 1.5em; }
+/* 
+	These can be used to pull an image at the start of a paragraph, so 
+	that the text flows around it (usage: <p><img class="left">Text</p>) 
+ */
+.left  			{ float: left !important; }
+p .left			{ margin: 1.5em 1.5em 1.5em 0; padding: 0; }
+.right 			{ float: right !important; }
+p .right 		{ margin: 1.5em 0 1.5em 1.5em; padding: 0; }
+
+a:focus,
+a:hover     { color: #09f; }
+a           { color: #06c; text-decoration: underline; }
+
+blockquote  { margin: 1.5em; color: #666; font-style: italic; }
+strong,dfn	{ font-weight: bold; }
+em,dfn      { font-style: italic; }
+sup, sub    { line-height: 0; }
+
+abbr,
+acronym     { border-bottom: 1px dotted #666; }
+address     { margin: 0 0 1.5em; font-style: italic; }
+del         { color:#666; }
+
+pre         { margin: 1.5em 0; white-space: pre; }
+pre,code,tt { font: 1em 'andale mono', 'lucida console', monospace; line-height: 1.5; }
+
+
+/* Lists
+-------------------------------------------------------------- */
+
+li ul,
+li ol       { margin: 0; }
+ul, ol      { margin: 0 1.5em 1.5em 0; padding-left: 1.5em; }
+
+ul          { list-style-type: disc; }
+ol          { list-style-type: decimal; }
+
+dl          { margin: 0 0 1.5em 0; }
+dl dt       { font-weight: bold; }
+dd          { margin-left: 1.5em;}
+
+
+/* Tables
+-------------------------------------------------------------- */
+
+/* 
+	Because of the need for padding on TH and TD, the vertical rhythm 
+	on table cells has to be 27px, instead of the standard 18px or 36px 
+	of other elements. 
+ */ 
+table       { margin-bottom: 1.4em; width:100%; }
+th          { font-weight: bold; }
+thead th    { background: #c3d9ff; }
+th,td,caption { padding: 4px 10px 4px 5px; }
+/*
+	You can zebra-stripe your tables in outdated browsers by adding 
+	the class "even" to every other table row. 
+ */
+tbody tr:nth-child(even) td, 
+tbody tr.even td  { 
+	background: #e5ecf9; 
+}
+tfoot       { font-style: italic; }
+caption     { background: #eee; }
+
+
+/* Misc classes
+-------------------------------------------------------------- */
+
+.small      { font-size: .8em; margin-bottom: 1.875em; line-height: 1.875em; }
+.large      { font-size: 1.2em; line-height: 2.5em; margin-bottom: 1.25em; }
+.hide       { display: none; }
+
+.quiet      { color: #666; }
+.loud       { color: #000; }
+.highlight  { background:#ff0; }
+.added      { background:#060; color: #fff; }
+.removed    { background:#900; color: #fff; }
+
+.first      { margin-left:0; padding-left:0; }
+.last       { margin-right:0; padding-right:0; }
+.top        { margin-top:0; padding-top:0; }
+.bottom     { margin-bottom:0; padding-bottom:0; }

media/js/excanvas.js

+// Copyright 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+// Known Issues:
+//
+// * Patterns only support repeat.
+// * Radial gradient are not implemented. The VML version of these look very
+//   different from the canvas one.
+// * Clipping paths are not implemented.
+// * Coordsize. The width and height attribute have higher priority than the
+//   width and height style values which isn't correct.
+// * Painting mode isn't implemented.
+// * Canvas width/height should is using content-box by default. IE in
+//   Quirks mode will draw the canvas using border-box. Either change your
+//   doctype to HTML5
+//   (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
+//   or use Box Sizing Behavior from WebFX
+//   (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
+// * Non uniform scaling does not correctly scale strokes.
+// * Optimize. There is always room for speed improvements.
+
+// Only add this code if we do not already have a canvas implementation
+if (!document.createElement('canvas').getContext) {
+
+(function() {
+
+  // alias some functions to make (compiled) code shorter
+  var m = Math;
+  var mr = m.round;
+  var ms = m.sin;
+  var mc = m.cos;
+  var abs = m.abs;
+  var sqrt = m.sqrt;
+
+  // this is used for sub pixel precision
+  var Z = 10;
+  var Z2 = Z / 2;
+
+  var IE_VERSION = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];
+
+  /**
+   * This funtion is assigned to the <canvas> elements as element.getContext().
+   * @this {HTMLElement}
+   * @return {CanvasRenderingContext2D_}
+   */
+  function getContext() {
+    return this.context_ ||
+        (this.context_ = new CanvasRenderingContext2D_(this));
+  }
+
+  var slice = Array.prototype.slice;
+
+  /**
+   * Binds a function to an object. The returned function will always use the
+   * passed in {@code obj} as {@code this}.
+   *
+   * Example:
+   *
+   *   g = bind(f, obj, a, b)
+   *   g(c, d) // will do f.call(obj, a, b, c, d)
+   *
+   * @param {Function} f The function to bind the object to
+   * @param {Object} obj The object that should act as this when the function
+   *     is called
+   * @param {*} var_args Rest arguments that will be used as the initial
+   *     arguments when the function is called
+   * @return {Function} A new function that has bound this
+   */
+  function bind(f, obj, var_args) {
+    var a = slice.call(arguments, 2);
+    return function() {
+      return f.apply(obj, a.concat(slice.call(arguments)));
+    };
+  }
+
+  function encodeHtmlAttribute(s) {
+    return String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
+  }
+
+  function addNamespace(doc, prefix, urn) {
+    if (!doc.namespaces[prefix]) {
+      doc.namespaces.add(prefix, urn, '#default#VML');
+    }
+  }
+
+  function addNamespacesAndStylesheet(doc) {
+    addNamespace(doc, 'g_vml_', 'urn:schemas-microsoft-com:vml');
+    addNamespace(doc, 'g_o_', 'urn:schemas-microsoft-com:office:office');
+
+    // Setup default CSS.  Only add one style sheet per document
+    if (!doc.styleSheets['ex_canvas_']) {
+      var ss = doc.createStyleSheet();
+      ss.owningElement.id = 'ex_canvas_';
+      ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
+          // default size is 300x150 in Gecko and Opera
+          'text-align:left;width:300px;height:150px}';
+    }
+  }
+
+  // Add namespaces and stylesheet at startup.
+  addNamespacesAndStylesheet(document);
+
+  var G_vmlCanvasManager_ = {
+    init: function(opt_doc) {
+      var doc = opt_doc || document;
+      // Create a dummy element so that IE will allow canvas elements to be
+      // recognized.
+      doc.createElement('canvas');
+      doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
+    },
+
+    init_: function(doc) {
+      // find all canvas elements
+      var els = doc.getElementsByTagName('canvas');
+      for (var i = 0; i < els.length; i++) {
+        this.initElement(els[i]);
+      }
+    },
+
+    /**
+     * Public initializes a canvas element so that it can be used as canvas
+     * element from now on. This is called automatically before the page is
+     * loaded but if you are creating elements using createElement you need to
+     * make sure this is called on the element.
+     * @param {HTMLElement} el The canvas element to initialize.
+     * @return {HTMLElement} the element that was created.
+     */
+    initElement: function(el) {
+      if (!el.getContext) {
+        el.getContext = getContext;
+
+        // Add namespaces and stylesheet to document of the element.
+        addNamespacesAndStylesheet(el.ownerDocument);
+
+        // Remove fallback content. There is no way to hide text nodes so we
+        // just remove all childNodes. We could hide all elements and remove
+        // text nodes but who really cares about the fallback content.
+        el.innerHTML = '';
+
+        // do not use inline function because that will leak memory
+        el.attachEvent('onpropertychange', onPropertyChange);
+        el.attachEvent('onresize', onResize);
+
+        var attrs = el.attributes;
+        if (attrs.width && attrs.width.specified) {
+          // TODO: use runtimeStyle and coordsize
+          // el.getContext().setWidth_(attrs.width.nodeValue);
+          el.style.width = attrs.width.nodeValue + 'px';
+        } else {
+          el.width = el.clientWidth;
+        }
+        if (attrs.height && attrs.height.specified) {
+          // TODO: use runtimeStyle and coordsize
+          // el.getContext().setHeight_(attrs.height.nodeValue);
+          el.style.height = attrs.height.nodeValue + 'px';
+        } else {
+          el.height = el.clientHeight;
+        }
+        //el.getContext().setCoordsize_()
+      }
+      return el;
+    }
+  };
+
+  function onPropertyChange(e) {
+    var el = e.srcElement;
+
+    switch (e.propertyName) {
+      case 'width':
+        el.getContext().clearRect();
+        el.style.width = el.attributes.width.nodeValue + 'px';
+        // In IE8 this does not trigger onresize.
+        el.firstChild.style.width =  el.clientWidth + 'px';
+        break;
+      case 'height':
+        el.getContext().clearRect();
+        el.style.height = el.attributes.height.nodeValue + 'px';
+        el.firstChild.style.height = el.clientHeight + 'px';
+        break;
+    }
+  }
+
+  function onResize(e) {
+    var el = e.srcElement;
+    if (el.firstChild) {
+      el.firstChild.style.width =  el.clientWidth + 'px';
+      el.firstChild.style.height = el.clientHeight + 'px';
+    }
+  }
+
+  G_vmlCanvasManager_.init();
+
+  // precompute "00" to "FF"
+  var decToHex = [];
+  for (var i = 0; i < 16; i++) {
+    for (var j = 0; j < 16; j++) {
+      decToHex[i * 16 + j] = i.toString(16) + j.toString(16);
+    }
+  }
+
+  function createMatrixIdentity() {
+    return [
+      [1, 0, 0],
+      [0, 1, 0],
+      [0, 0, 1]
+    ];
+  }
+
+  function matrixMultiply(m1, m2) {
+    var result = createMatrixIdentity();
+
+    for (var x = 0; x < 3; x++) {
+      for (var y = 0; y < 3; y++) {
+        var sum = 0;
+
+        for (var z = 0; z < 3; z++) {
+          sum += m1[x][z] * m2[z][y];
+        }
+
+        result[x][y] = sum;
+      }
+    }
+    return result;
+  }
+
+  function copyState(o1, o2) {
+    o2.fillStyle     = o1.fillStyle;
+    o2.lineCap       = o1.lineCap;
+    o2.lineJoin      = o1.lineJoin;
+    o2.lineWidth     = o1.lineWidth;
+    o2.miterLimit    = o1.miterLimit;
+    o2.shadowBlur    = o1.shadowBlur;
+    o2.shadowColor   = o1.shadowColor;
+    o2.shadowOffsetX = o1.shadowOffsetX;
+    o2.shadowOffsetY = o1.shadowOffsetY;
+    o2.strokeStyle   = o1.strokeStyle;
+    o2.globalAlpha   = o1.globalAlpha;
+    o2.font          = o1.font;
+    o2.textAlign     = o1.textAlign;
+    o2.textBaseline  = o1.textBaseline;
+    o2.arcScaleX_    = o1.arcScaleX_;
+    o2.arcScaleY_    = o1.arcScaleY_;
+    o2.lineScale_    = o1.lineScale_;
+  }
+
+  var colorData = {
+    aliceblue: '#F0F8FF',
+    antiquewhite: '#FAEBD7',
+    aquamarine: '#7FFFD4',
+    azure: '#F0FFFF',
+    beige: '#F5F5DC',
+    bisque: '#FFE4C4',
+    black: '#000000',
+    blanchedalmond: '#FFEBCD',
+    blueviolet: '#8A2BE2',
+    brown: '#A52A2A',
+    burlywood: '#DEB887',
+    cadetblue: '#5F9EA0',
+    chartreuse: '#7FFF00',
+    chocolate: '#D2691E',
+    coral: '#FF7F50',
+    cornflowerblue: '#6495ED',
+    cornsilk: '#FFF8DC',
+    crimson: '#DC143C',
+    cyan: '#00FFFF',
+    darkblue: '#00008B',
+    darkcyan: '#008B8B',
+    darkgoldenrod: '#B8860B',
+    darkgray: '#A9A9A9',
+    darkgreen: '#006400',
+    darkgrey: '#A9A9A9',
+    darkkhaki: '#BDB76B',
+    darkmagenta: '#8B008B',
+    darkolivegreen: '#556B2F',
+    darkorange: '#FF8C00',
+    darkorchid: '#9932CC',
+    darkred: '#8B0000',
+    darksalmon: '#E9967A',
+    darkseagreen: '#8FBC8F',
+    darkslateblue: '#483D8B',
+    darkslategray: '#2F4F4F',
+    darkslategrey: '#2F4F4F',
+    darkturquoise: '#00CED1',
+    darkviolet: '#9400D3',
+    deeppink: '#FF1493',
+    deepskyblue: '#00BFFF',
+    dimgray: '#696969',
+    dimgrey: '#696969',
+    dodgerblue: '#1E90FF',
+    firebrick: '#B22222',
+    floralwhite: '#FFFAF0',
+    forestgreen: '#228B22',
+    gainsboro: '#DCDCDC',
+    ghostwhite: '#F8F8FF',
+    gold: '#FFD700',
+    goldenrod: '#DAA520',
+    grey: '#808080',
+    greenyellow: '#ADFF2F',
+    honeydew: '#F0FFF0',
+    hotpink: '#FF69B4',
+    indianred: '#CD5C5C',
+    indigo: '#4B0082',
+    ivory: '#FFFFF0',
+    khaki: '#F0E68C',
+    lavender: '#E6E6FA',
+    lavenderblush: '#FFF0F5',
+    lawngreen: '#7CFC00',
+    lemonchiffon: '#FFFACD',
+    lightblue: '#ADD8E6',
+    lightcoral: '#F08080',
+    lightcyan: '#E0FFFF',
+    lightgoldenrodyellow: '#FAFAD2',
+    lightgreen: '#90EE90',
+    lightgrey: '#D3D3D3',
+    lightpink: '#FFB6C1',
+    lightsalmon: '#FFA07A',
+    lightseagreen: '#20B2AA',
+    lightskyblue: '#87CEFA',
+    lightslategray: '#778899',
+    lightslategrey: '#778899',
+    lightsteelblue: '#B0C4DE',
+    lightyellow: '#FFFFE0',
+    limegreen: '#32CD32',
+    linen: '#FAF0E6',
+    magenta: '#FF00FF',
+    mediumaquamarine: '#66CDAA',
+    mediumblue: '#0000CD',
+    mediumorchid: '#BA55D3',
+    mediumpurple: '#9370DB',
+    mediumseagreen: '#3CB371',
+    mediumslateblue: '#7B68EE',
+    mediumspringgreen: '#00FA9A',
+    mediumturquoise: '#48D1CC',
+    mediumvioletred: '#C71585',
+    midnightblue: '#191970',
+    mintcream: '#F5FFFA',
+    mistyrose: '#FFE4E1',
+    moccasin: '#FFE4B5',
+    navajowhite: '#FFDEAD',
+    oldlace: '#FDF5E6',
+    olivedrab: '#6B8E23',
+    orange: '#FFA500',
+    orangered: '#FF4500',
+    orchid: '#DA70D6',
+    palegoldenrod: '#EEE8AA',
+    palegreen: '#98FB98',
+    paleturquoise: '#AFEEEE',
+    palevioletred: '#DB7093',
+    papayawhip: '#FFEFD5',
+    peachpuff: '#FFDAB9',
+    peru: '#CD853F',
+    pink: '#FFC0CB',
+    plum: '#DDA0DD',
+    powderblue: '#B0E0E6',
+    rosybrown: '#BC8F8F',
+    royalblue: '#4169E1',
+    saddlebrown: '#8B4513',
+    salmon: '#FA8072',
+    sandybrown: '#F4A460',
+    seagreen: '#2E8B57',
+    seashell: '#FFF5EE',
+    sienna: '#A0522D',
+    skyblue: '#87CEEB',
+    slateblue: '#6A5ACD',
+    slategray: '#708090',
+    slategrey: '#708090',
+    snow: '#FFFAFA',
+    springgreen: '#00FF7F',
+    steelblue: '#4682B4',
+    tan: '#D2B48C',
+    thistle: '#D8BFD8',
+    tomato: '#FF6347',
+    turquoise: '#40E0D0',
+    violet: '#EE82EE',
+    wheat: '#F5DEB3',
+    whitesmoke: '#F5F5F5',
+    yellowgreen: '#9ACD32'
+  };
+
+
+  function getRgbHslContent(styleString) {
+    var start = styleString.indexOf('(', 3);
+    var end = styleString.indexOf(')', start + 1);
+    var parts = styleString.substring(start + 1, end).split(',');
+    // add alpha if needed
+    if (parts.length != 4 || styleString.charAt(3) != 'a') {
+      parts[3] = 1;
+    }
+    return parts;
+  }
+
+  function percent(s) {
+    return parseFloat(s) / 100;
+  }
+
+  function clamp(v, min, max) {
+    return Math.min(max, Math.max(min, v));
+  }
+
+  function hslToRgb(parts){
+    var r, g, b, h, s, l;
+    h = parseFloat(parts[0]) / 360 % 360;
+    if (h < 0)
+      h++;
+    s = clamp(percent(parts[1]), 0, 1);
+    l = clamp(percent(parts[2]), 0, 1);
+    if (s == 0) {
+      r = g = b = l; // achromatic
+    } else {
+      var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+      var p = 2 * l - q;
+      r = hueToRgb(p, q, h + 1 / 3);
+      g = hueToRgb(p, q, h);
+      b = hueToRgb(p, q, h - 1 / 3);
+    }
+
+    return '#' + decToHex[Math.floor(r * 255)] +
+        decToHex[Math.floor(g * 255)] +
+        decToHex[Math.floor(b * 255)];
+  }
+
+  function hueToRgb(m1, m2, h) {
+    if (h < 0)
+      h++;
+    if (h > 1)
+      h--;
+
+    if (6 * h < 1)
+      return m1 + (m2 - m1) * 6 * h;
+    else if (2 * h < 1)
+      return m2;
+    else if (3 * h < 2)
+      return m1 + (m2 - m1) * (2 / 3 - h) * 6;
+    else
+      return m1;
+  }
+
+  var processStyleCache = {};
+
+  function processStyle(styleString) {
+    if (styleString in processStyleCache) {
+      return processStyleCache[styleString];
+    }
+
+    var str, alpha = 1;
+
+    styleString = String(styleString);
+    if (styleString.charAt(0) == '#') {
+      str = styleString;
+    } else if (/^rgb/.test(styleString)) {
+      var parts = getRgbHslContent(styleString);
+      var str = '#', n;
+      for (var i = 0; i < 3; i++) {
+        if (parts[i].indexOf('%') != -1) {
+          n = Math.floor(percent(parts[i]) * 255);
+        } else {
+          n = +parts[i];
+        }
+        str += decToHex[clamp(n, 0, 255)];
+      }
+      alpha = +parts[3];
+    } else if (/^hsl/.test(styleString)) {
+      var parts = getRgbHslContent(styleString);
+      str = hslToRgb(parts);
+      alpha = parts[3];
+    } else {
+      str = colorData[styleString] || styleString;
+    }
+    return processStyleCache[styleString] = {color: str, alpha: alpha};
+  }
+
+  var DEFAULT_STYLE = {
+    style: 'normal',
+    variant: 'normal',
+    weight: 'normal',