From b3039768af062b4ba78e896011871d69b1bbf72c Mon Sep 17 00:00:00 2001 From: Tom Wiesing Date: Tue, 3 Jan 2023 13:02:42 +0100 Subject: [PATCH] Update URL routes --- internal/cli/cli_notices.go | 4 +-- internal/dis/component/auth/auth.go | 2 +- internal/dis/component/auth/protect.go | 2 +- internal/dis/component/auth/routes.go | 3 +- .../dis/component/auth/templates/home.html | 30 ++++++++-------- .../component/auth/templates/password.html | 14 +++++--- .../auth/templates/totp_disable.html | 15 +++++--- .../component/auth/templates/totp_enable.html | 13 ++++--- .../component/auth/templates/totp_enroll.html | 13 ++++--- internal/dis/component/auth/totp.go | 24 ++++++++----- internal/dis/component/auth/user.go | 17 ++++++++++ .../control/info/html/components.html | 6 ++-- .../component/control/info/html/index.html | 8 ++--- .../control/info/html/ingredients.html | 8 ++--- .../component/control/info/html/instance.html | 10 +++--- internal/dis/component/control/info/info.go | 2 +- .../component/control/static/assets_dist.go | 16 ++++----- ...ome.25c6db8a.css => HomeHome.4ec77c43.css} | 2 +- .../control/static/src/base/index.css | 9 ++++- .../control/static/templates/_form.html | 34 +++++++++---------- pkg/httpx/form.go | 16 +++++++-- 21 files changed, 152 insertions(+), 96 deletions(-) rename internal/dis/component/control/static/dist/{HomeHome.25c6db8a.css => HomeHome.4ec77c43.css} (99%) diff --git a/internal/cli/cli_notices.go b/internal/cli/cli_notices.go index 2e4c543..8b0fba2 100755 --- a/internal/cli/cli_notices.go +++ b/internal/cli/cli_notices.go @@ -1,7 +1,7 @@ package cli // =========================================================================================================== -// This file was generated automatically at 02-01-2023 12:34:04 using gogenlicense. +// This file was generated automatically at 03-01-2023 11:39:55 using gogenlicense. // Do not edit manually, as changes may be overwritten. // =========================================================================================================== @@ -2133,7 +2133,7 @@ package cli // # Generation // // This variable and the associated documentation have been automatically generated using the 'gogenlicense' tool. -// It was last updated at 02-01-2023 12:34:04. +// It was last updated at 03-01-2023 11:39:55. var LegalNotices string func init() { diff --git a/internal/dis/component/auth/auth.go b/internal/dis/component/auth/auth.go index 5f10383..0a7315c 100644 --- a/internal/dis/component/auth/auth.go +++ b/internal/dis/component/auth/auth.go @@ -27,7 +27,7 @@ var ( _ component.Routeable = (*Auth)(nil) ) -func (auth *Auth) Routes() []string { return []string{"/auth/"} } +func (auth *Auth) Routes() []string { return []string{"/user/"} } func (auth *Auth) HandleRoute(ctx context.Context, route string) (http.Handler, error) { router := httprouter.New() diff --git a/internal/dis/component/auth/protect.go b/internal/dis/component/auth/protect.go index 12d20f2..104ec44 100644 --- a/internal/dis/component/auth/protect.go +++ b/internal/dis/component/auth/protect.go @@ -33,7 +33,7 @@ func (auth *Auth) Protect(handler http.Handler, perm Permission) http.Handler { } // redirect the user to the login endpoint, with the original URI as a return - dest := "/auth/login?next=" + url.QueryEscape(r.URL.RequestURI()) + dest := "/user/login?next=" + url.QueryEscape(r.URL.RequestURI()) http.Redirect(w, r, dest, http.StatusSeeOther) return } diff --git a/internal/dis/component/auth/routes.go b/internal/dis/component/auth/routes.go index 1b7e286..3410e35 100644 --- a/internal/dis/component/auth/routes.go +++ b/internal/dis/component/auth/routes.go @@ -49,7 +49,8 @@ func (auth *Auth) authPassword(ctx context.Context) http.Handler { CSRF: auth.csrf.Get(nil), - RenderTemplate: passwordTemplate, + RenderTemplate: passwordTemplate, + RenderTemplateContext: auth.UserFormContext, Validate: func(r *http.Request, values map[string]string) (struct{}, error) { old, passcode, new, new2 := values["old"], values["passcode"], values["new"], values["new2"] diff --git a/internal/dis/component/auth/templates/home.html b/internal/dis/component/auth/templates/home.html index 4039a85..b85b662 100644 --- a/internal/dis/component/auth/templates/home.html +++ b/internal/dis/component/auth/templates/home.html @@ -1,20 +1,16 @@ {{ template "_base.html" . }} -{{ define "title" }}Distillery User{{ end }} +{{ define "title" }}User{{ end }} -{{ define "header/time" }} - -{{ end }} {{ define "header"}} - +

+ {{ .User.User }} +

+

+ Logout +

{{ end }} {{ define "content" }} -
- Welcome {{ .User.User }}! - Logout -
-
-

{{ if .User.Admin }} @@ -29,11 +25,11 @@ {{ end }}

- Change Password + Change Password {{ if .User.TOTPEnabled }} - Disable TOTP + Disable TOTP {{ else }} - Enable TOTP + Enable TOTP {{ end }}

@@ -43,11 +39,13 @@
{{ if (not .User.TOTPEnabled) }}
- TOTP is required to access these. +

+ TOTP is required to access these. +

{{ end }}
diff --git a/internal/dis/component/auth/templates/password.html b/internal/dis/component/auth/templates/password.html index 3d6342b..228e897 100644 --- a/internal/dis/component/auth/templates/password.html +++ b/internal/dis/component/auth/templates/password.html @@ -1,9 +1,13 @@ {{ template "_form.html" . }} {{ define "form/title" }}Change Password{{ end }} {{ define "form/button" }}Update{{ end }} -{{ define "form/extra" }} -
- Back -
-
+ +{{ define "header"}} +

+ {{ .User.User }} > + Change Password +

+

+ Logout +

{{ end }} diff --git a/internal/dis/component/auth/templates/totp_disable.html b/internal/dis/component/auth/templates/totp_disable.html index 080cac9..7fc4399 100644 --- a/internal/dis/component/auth/templates/totp_disable.html +++ b/internal/dis/component/auth/templates/totp_disable.html @@ -1,12 +1,17 @@ {{ template "_form.html" . }} {{ define "form/title" }}Disable TOTP{{ end }} {{ define "form/button" }}Disable{{ end }} -{{ define "form/extra" }} -
- Back -
-
+ +{{ define "header"}} +

+ {{ .User.User }} > + Disable TOTP +

+

+ Logout +

{{ end }} + {{ define "form/inside" }}
    diff --git a/internal/dis/component/auth/templates/totp_enable.html b/internal/dis/component/auth/templates/totp_enable.html index 6f301e4..bc8f881 100644 --- a/internal/dis/component/auth/templates/totp_enable.html +++ b/internal/dis/component/auth/templates/totp_enable.html @@ -1,11 +1,14 @@ {{ template "_form.html" . }} {{ define "form/title" }}Enable TOTP{{ end }} {{ define "form/button" }}Enable{{ end }} -{{ define "form/extra" }} -
    - Back -
    -
    +{{ define "header"}} +

    + {{ .User.User }} > + Enable TOTP +

    +

    + Logout +

    {{ end }} {{ define "form/inside" }}
    diff --git a/internal/dis/component/auth/templates/totp_enroll.html b/internal/dis/component/auth/templates/totp_enroll.html index 94f4ff3..9cd4723 100644 --- a/internal/dis/component/auth/templates/totp_enroll.html +++ b/internal/dis/component/auth/templates/totp_enroll.html @@ -1,11 +1,14 @@ {{ template "_form.html" . }} {{ define "form/title" }}Enable TOTP{{ end }} {{ define "form/button" }}Enable{{ end }} -{{ define "form/extra" }} -
    - Back -
    -
    +{{ define "header" }} +

    + {{ .User.User }} > + Enroll TOTP +

    +

    + Logout +

    {{ end }} {{ define "form/inside" }}
    diff --git a/internal/dis/component/auth/totp.go b/internal/dis/component/auth/totp.go index f45652e..dba34aa 100644 --- a/internal/dis/component/auth/totp.go +++ b/internal/dis/component/auth/totp.go @@ -28,7 +28,9 @@ func (auth *Auth) authTOTPEnable(ctx context.Context) http.Handler { user, err := auth.UserOf(r) return struct{}{}, err == nil && user != nil && user.TOTPEnabled }, - RenderTemplate: totpEnableTemplate, + + RenderTemplate: totpEnableTemplate, + RenderTemplateContext: auth.UserFormContext, Validate: func(r *http.Request, values map[string]string) (struct{}, error) { password := values["password"] @@ -55,7 +57,7 @@ func (auth *Auth) authTOTPEnable(ctx context.Context) http.Handler { }, RenderSuccess: func(_ struct{}, values map[string]string, w http.ResponseWriter, r *http.Request) error { - http.Redirect(w, r, "/auth/totp/enroll", http.StatusSeeOther) + http.Redirect(w, r, "/user/totp/enroll", http.StatusSeeOther) return nil }, } @@ -66,7 +68,7 @@ var totpEnrollStr string var totpEnrollTemplate = static.AssetsAuthLogin.MustParseShared("totp_enroll.html", totpEnrollStr) type totpEnrollContext struct { - httpx.FormContext + userFormContext TOTPImage template.URL TOTPURL template.URL } @@ -86,11 +88,16 @@ func (auth *Auth) authTOTPEnroll(ctx context.Context) http.Handler { return struct{}{}, user != nil && user.TOTPEnabled }, RenderForm: func(context httpx.FormContext, w http.ResponseWriter, r *http.Request) { + user, err := auth.UserOf(r) + ctx := totpEnrollContext{ - FormContext: context, + userFormContext: userFormContext{ + FormContext: context, + }, } - if user, err := auth.UserOf(r); err == nil && user != nil { + if err == nil && user != nil { + ctx.userFormContext.User = &user.User secret, err := user.TOTP() if err == nil { img, _ := TOTPLink(secret, 500, 500) @@ -127,7 +134,7 @@ func (auth *Auth) authTOTPEnroll(ctx context.Context) http.Handler { }, RenderSuccess: func(_ struct{}, values map[string]string, w http.ResponseWriter, r *http.Request) error { - http.Redirect(w, r, "/auth/", http.StatusSeeOther) + http.Redirect(w, r, "/user/", http.StatusSeeOther) return nil }, } @@ -151,7 +158,8 @@ func (auth *Auth) authTOTPDisable(ctx context.Context) http.Handler { user, _ := auth.UserOf(r) return struct{}{}, user != nil && !user.TOTPEnabled }, - RenderTemplate: totpDisableTemplate, + RenderTemplate: totpDisableTemplate, + RenderTemplateContext: auth.UserFormContext, Validate: func(r *http.Request, values map[string]string) (struct{}, error) { password, passcode := values["password"], values["passcode"] @@ -178,7 +186,7 @@ func (auth *Auth) authTOTPDisable(ctx context.Context) http.Handler { }, RenderSuccess: func(_ struct{}, values map[string]string, w http.ResponseWriter, r *http.Request) error { - http.Redirect(w, r, "/auth/", http.StatusSeeOther) + http.Redirect(w, r, "/user/", http.StatusSeeOther) return nil }, } diff --git a/internal/dis/component/auth/user.go b/internal/dis/component/auth/user.go index d6b5b6a..30db63f 100644 --- a/internal/dis/component/auth/user.go +++ b/internal/dis/component/auth/user.go @@ -7,8 +7,10 @@ import ( "errors" "fmt" "image/png" + "net/http" "github.com/FAU-CDI/wisski-distillery/internal/models" + "github.com/FAU-CDI/wisski-distillery/pkg/httpx" "github.com/pquerna/otp" "github.com/pquerna/otp/totp" "golang.org/x/crypto/bcrypt" @@ -288,3 +290,18 @@ func (au *AuthUser) Delete(ctx context.Context) error { return table.Delete(&au.User).Error } + +type userFormContext struct { + httpx.FormContext + User *models.User +} + +func (au *Auth) UserFormContext(ctx httpx.FormContext, r *http.Request) any { + user, err := au.UserOf(r) + + uctx := userFormContext{FormContext: ctx} + if err == nil { + uctx.User = &user.User + } + return uctx +} diff --git a/internal/dis/component/control/info/html/components.html b/internal/dis/component/control/info/html/components.html index bf916a7..eff5136 100644 --- a/internal/dis/component/control/info/html/components.html +++ b/internal/dis/component/control/info/html/components.html @@ -1,10 +1,10 @@ {{ template "_base.html" . }} -{{ define "title" }}Distillery Control Page - Components Page{{ end }} +{{ define "title" }}Distillery Admin - Components Page{{ end }} {{ define "header"}}

    - Control > - Components + Admin > + Components

    {{ end }} diff --git a/internal/dis/component/control/info/html/index.html b/internal/dis/component/control/info/html/index.html index cf1137b..4909062 100644 --- a/internal/dis/component/control/info/html/index.html +++ b/internal/dis/component/control/info/html/index.html @@ -1,12 +1,12 @@ {{ template "_base.html" . }} -{{ define "title" }}Distillery Control Page{{ end }} +{{ define "title" }}Distillery Admin{{ end }} {{ define "header"}}

    - Control + Admin

    - Components + Components

    {{ end }} @@ -269,7 +269,7 @@

    {{.URL}}
    - Details + Details

    diff --git a/internal/dis/component/control/info/html/ingredients.html b/internal/dis/component/control/info/html/ingredients.html index 6281cb8..6b2ad08 100644 --- a/internal/dis/component/control/info/html/ingredients.html +++ b/internal/dis/component/control/info/html/ingredients.html @@ -1,11 +1,11 @@ {{ template "_base.html" . }} -{{ define "title" }}Distillery Control Page - {{ .Instance.Slug }} - Ingredients{{ end }} +{{ define "title" }}Distillery Admin - {{ .Instance.Slug }} - Ingredients{{ end }} {{ define "header"}}

    - Control > - Instance > - Ingredients + Admin > + Instance > + Ingredients

    {{ end }} diff --git a/internal/dis/component/control/info/html/instance.html b/internal/dis/component/control/info/html/instance.html index 74862ab..4fed81f 100644 --- a/internal/dis/component/control/info/html/instance.html +++ b/internal/dis/component/control/info/html/instance.html @@ -1,13 +1,13 @@ {{ template "_base.html" . }} -{{ define "title" }}Distillery Control Page - {{ .Info.Slug }}{{ end }} +{{ define "title" }}Distillery Admin - {{ .Info.Slug }}{{ end }} {{ define "header"}}

    - Control > - Instance + Control > + Instance

    - Ingredients + Ingredients

    {{ end }} @@ -247,7 +247,7 @@ {{ $user.Login.Time.Format "2006-01-02T15:04:05Z07:00" }} -
    + diff --git a/internal/dis/component/control/info/info.go b/internal/dis/component/control/info/info.go index 66b931a..e7b51a6 100644 --- a/internal/dis/component/control/info/info.go +++ b/internal/dis/component/control/info/info.go @@ -35,7 +35,7 @@ var ( _ component.Routeable = (*Info)(nil) ) -func (*Info) Routes() []string { return []string{"/dis/"} } +func (*Info) Routes() []string { return []string{"/admin/"} } func (info *Info) HandleRoute(ctx context.Context, route string) (handler http.Handler, err error) { diff --git a/internal/dis/component/control/static/assets_dist.go b/internal/dis/component/control/static/assets_dist.go index 7de9ce5..73c814e 100644 --- a/internal/dis/component/control/static/assets_dist.go +++ b/internal/dis/component/control/static/assets_dist.go @@ -5,47 +5,47 @@ package static // AssetsHomeHome contains assets for the 'HomeHome' entrypoint. var AssetsHomeHome = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } // AssetsComponentsIndex contains assets for the 'ComponentsIndex' entrypoint. var AssetsComponentsIndex = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } // AssetsControlIndex contains assets for the 'ControlIndex' entrypoint. var AssetsControlIndex = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } // AssetsControlInstance contains assets for the 'ControlInstance' entrypoint. var AssetsControlInstance = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } // AssetsInstanceComponentsIndex contains assets for the 'InstanceComponentsIndex' entrypoint. var AssetsInstanceComponentsIndex = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } // AssetsAuthLogin contains assets for the 'AuthLogin' entrypoint. var AssetsAuthLogin = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } // AssetsAuthHome contains assets for the 'AuthHome' entrypoint. var AssetsAuthHome = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } // AssetsAuthTOTP contains assets for the 'AuthTOTP' entrypoint. var AssetsAuthTOTP = Assets{ Scripts: ``, - Styles: ``, + Styles: ``, } diff --git a/internal/dis/component/control/static/dist/HomeHome.25c6db8a.css b/internal/dis/component/control/static/dist/HomeHome.4ec77c43.css similarity index 99% rename from internal/dis/component/control/static/dist/HomeHome.25c6db8a.css rename to internal/dis/component/control/static/dist/HomeHome.4ec77c43.css index 31e30f0..38eb875 100644 --- a/internal/dis/component/control/static/dist/HomeHome.25c6db8a.css +++ b/internal/dis/component/control/static/dist/HomeHome.4ec77c43.css @@ -1 +1 @@ -html{-webkit-text-size-adjust:100%;line-height:1.15}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace;font-size:1em}a{background-color:#0000}abbr[title]{text-decoration:underline;border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;max-width:100%;white-space:normal;padding:0;display:table}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template,[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;flex-flow:wrap;align-content:flex-start;font-family:FreeSans,Arimo,Droid Sans,Helvetica,Arial,sans-serif;display:flex}@media (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-5-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-2-24,.pure-u-3-24,.pure-u-4-24,.pure-u-5-24,.pure-u-6-24,.pure-u-7-24,.pure-u-8-24,.pure-u-9-24,.pure-u-10-24,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-5-12,.pure-u-10-24{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-7-12,.pure-u-14-24{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-5-8,.pure-u-15-24{width:62.5%}.pure-u-2-3,.pure-u-16-24{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-3-4,.pure-u-18-24{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-5-6,.pure-u-20-24{width:83.3333%}.pure-u-7-8,.pure-u-21-24{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-5-5,.pure-u-24-24{width:100%}.pure-button{white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;user-select:none;box-sizing:border-box;line-height:normal;display:inline-block}.pure-button::-moz-focus-inner{border:0;padding:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{color:#000c;background-color:#e6e6e6;border:#0000;border-radius:2px;padding:.5em 1em;font-family:inherit;font-size:100%;text-decoration:none}.pure-button-hover,.pure-button:hover,.pure-button:focus{background-image:linear-gradient(#0000,#0000000d 40%,#0000001a)}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{border-color:#000;box-shadow:inset 0 0 0 1px #00000026,inset 0 0 6px #0003}.pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:focus,.pure-button-disabled:active{opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none;background-image:none;border:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{color:#fff;background-color:#0078e7}.pure-button-group .pure-button{border-right:1px solid #0003;border-radius:0;margin:0}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-right:none;border-top-right-radius:2px;border-bottom-right-radius:2px}.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form select,.pure-form textarea{vertical-align:middle;box-sizing:border-box;border:1px solid #ccc;border-radius:4px;padding:.5em .6em;display:inline-block;box-shadow:inset 0 1px 3px #ddd}.pure-form input:not([type]){box-sizing:border-box;border:1px solid #ccc;border-radius:4px;padding:.5em .6em;display:inline-block;box-shadow:inset 0 1px 3px #ddd}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=text]:focus,.pure-form input[type=password]:focus,.pure-form input[type=email]:focus,.pure-form input[type=url]:focus,.pure-form input[type=date]:focus,.pure-form input[type=month]:focus,.pure-form input[type=time]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=week]:focus,.pure-form input[type=number]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=color]:focus,.pure-form select:focus,.pure-form textarea:focus,.pure-form input:not([type]):focus{border-color:#129fea;outline:0}.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus,.pure-form input[type=checkbox]:focus{outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=text][disabled],.pure-form input[type=password][disabled],.pure-form input[type=email][disabled],.pure-form input[type=url][disabled],.pure-form input[type=date][disabled],.pure-form input[type=month][disabled],.pure-form input[type=time][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=week][disabled],.pure-form input[type=number][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=color][disabled],.pure-form select[disabled],.pure-form textarea[disabled],.pure-form input:not([type])[disabled]{cursor:not-allowed;color:#cad2d3;background-color:#eaeded}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{color:#777;background-color:#eee;border-color:#ccc}.pure-form input:focus:invalid,.pure-form textarea:focus:invalid,.pure-form select:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus,.pure-form input[type=checkbox]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;background-color:#fff;border:1px solid #ccc}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{border:0;margin:0;padding:.35em 0 .75em}.pure-form legend{width:100%;color:#333;border-bottom:1px solid #e5e5e5;margin-bottom:.3em;padding:.3em 0;display:block}.pure-form-stacked input[type=text],.pure-form-stacked input[type=password],.pure-form-stacked input[type=email],.pure-form-stacked input[type=url],.pure-form-stacked input[type=date],.pure-form-stacked input[type=month],.pure-form-stacked input[type=time],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=week],.pure-form-stacked input[type=number],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=color],.pure-form-stacked input[type=file],.pure-form-stacked select,.pure-form-stacked label,.pure-form-stacked textarea,.pure-form-stacked input:not([type]){margin:.25em 0;display:block}.pure-form-aligned input,.pure-form-aligned textarea,.pure-form-aligned select,.pure-form-message-inline{vertical-align:middle;display:inline-block}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;vertical-align:middle;width:10em;margin:0 1em 0 0;display:inline-block}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form input.pure-input-rounded,.pure-form .pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{border-radius:0;margin:0 0 -1px;padding:10px;display:block;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{border-radius:4px 4px 0 0;margin:0;top:1px}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{border-radius:4px;margin:0;top:1px}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{border-radius:0 0 4px 4px;margin:0;top:-2px}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{color:#666;vertical-align:middle;padding-left:.3em;font-size:.875em;display:inline-block}.pure-form-message{color:#666;font-size:.875em;display:block}@media only screen and (max-width:480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=text],.pure-group input[type=password],.pure-group input[type=email],.pure-group input[type=url],.pure-group input[type=date],.pure-group input[type=month],.pure-group input[type=time],.pure-group input[type=datetime],.pure-group input[type=datetime-local],.pure-group input[type=week],.pure-group input[type=number],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=color]{margin-bottom:0}.pure-form-aligned .pure-control-group label{text-align:left;width:100%;margin-bottom:.3em;display:block}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form-message-inline,.pure-form-message{padding:.2em 0 .8em;font-size:.75em;display:block}}.pure-menu{box-sizing:border-box}.pure-menu-fixed{z-index:3;position:fixed;top:0;left:0}.pure-menu-list,.pure-menu-item{position:relative}.pure-menu-list{margin:0;padding:0;list-style:none}.pure-menu-item{height:100%;margin:0;padding:0}.pure-menu-link,.pure-menu-heading{white-space:nowrap;text-decoration:none;display:block}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-separator{vertical-align:middle;display:inline-block}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{z-index:3;margin:0;padding:0;display:none;position:absolute;top:0;left:100%}.pure-menu-horizontal .pure-menu-children{width:inherit;top:auto;left:0}.pure-menu-allow-hover:hover>.pure-menu-children,.pure-menu-active>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{content:"▸";padding-left:.5em;font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"▾"}.pure-menu-scrollable{overflow-x:hidden;overflow-y:scroll}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;padding:.5em 0;overflow-x:auto;overflow-y:hidden}.pure-menu-separator,.pure-menu-horizontal .pure-menu-children .pure-menu-separator{height:1px;background-color:#ccc;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{width:auto;display:block}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-link,.pure-menu-heading{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{cursor:default;background-color:#0000}.pure-menu-active>.pure-menu-link,.pure-menu-link:hover,.pure-menu-link:focus{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;text-align:center;padding:1em 0;font:italic 85%/1 arial,sans-serif}.pure-table td,.pure-table th{font-size:inherit;border-width:0 0 0 1px;border-left-style:solid;border-left-color:#cbcbcb;margin:0;padding:.5em 1em;overflow:visible}.pure-table thead{color:#000;text-align:left;vertical-align:bottom;background-color:#e0e0e0}.pure-table td{background-color:#0000}.pure-table-odd td,.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px;border-bottom-style:solid;border-bottom-color:#cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@media screen and (min-width:35.5em){.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-1-2,.pure-u-sm-1-3,.pure-u-sm-2-3,.pure-u-sm-1-4,.pure-u-sm-3-4,.pure-u-sm-1-5,.pure-u-sm-2-5,.pure-u-sm-3-5,.pure-u-sm-4-5,.pure-u-sm-5-5,.pure-u-sm-1-6,.pure-u-sm-5-6,.pure-u-sm-1-8,.pure-u-sm-3-8,.pure-u-sm-5-8,.pure-u-sm-7-8,.pure-u-sm-1-12,.pure-u-sm-5-12,.pure-u-sm-7-12,.pure-u-sm-11-12,.pure-u-sm-1-24,.pure-u-sm-2-24,.pure-u-sm-3-24,.pure-u-sm-4-24,.pure-u-sm-5-24,.pure-u-sm-6-24,.pure-u-sm-7-24,.pure-u-sm-8-24,.pure-u-sm-9-24,.pure-u-sm-10-24,.pure-u-sm-11-24,.pure-u-sm-12-24,.pure-u-sm-13-24,.pure-u-sm-14-24,.pure-u-sm-15-24,.pure-u-sm-16-24,.pure-u-sm-17-24,.pure-u-sm-18-24,.pure-u-sm-19-24,.pure-u-sm-20-24,.pure-u-sm-21-24,.pure-u-sm-22-24,.pure-u-sm-23-24,.pure-u-sm-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-sm-1-24{width:4.1667%}.pure-u-sm-1-12,.pure-u-sm-2-24{width:8.3333%}.pure-u-sm-1-8,.pure-u-sm-3-24{width:12.5%}.pure-u-sm-1-6,.pure-u-sm-4-24{width:16.6667%}.pure-u-sm-1-5{width:20%}.pure-u-sm-5-24{width:20.8333%}.pure-u-sm-1-4,.pure-u-sm-6-24{width:25%}.pure-u-sm-7-24{width:29.1667%}.pure-u-sm-1-3,.pure-u-sm-8-24{width:33.3333%}.pure-u-sm-3-8,.pure-u-sm-9-24{width:37.5%}.pure-u-sm-2-5{width:40%}.pure-u-sm-5-12,.pure-u-sm-10-24{width:41.6667%}.pure-u-sm-11-24{width:45.8333%}.pure-u-sm-1-2,.pure-u-sm-12-24{width:50%}.pure-u-sm-13-24{width:54.1667%}.pure-u-sm-7-12,.pure-u-sm-14-24{width:58.3333%}.pure-u-sm-3-5{width:60%}.pure-u-sm-5-8,.pure-u-sm-15-24{width:62.5%}.pure-u-sm-2-3,.pure-u-sm-16-24{width:66.6667%}.pure-u-sm-17-24{width:70.8333%}.pure-u-sm-3-4,.pure-u-sm-18-24{width:75%}.pure-u-sm-19-24{width:79.1667%}.pure-u-sm-4-5{width:80%}.pure-u-sm-5-6,.pure-u-sm-20-24{width:83.3333%}.pure-u-sm-7-8,.pure-u-sm-21-24{width:87.5%}.pure-u-sm-11-12,.pure-u-sm-22-24{width:91.6667%}.pure-u-sm-23-24{width:95.8333%}.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-5-5,.pure-u-sm-24-24{width:100%}}@media screen and (min-width:48em){.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-1-2,.pure-u-md-1-3,.pure-u-md-2-3,.pure-u-md-1-4,.pure-u-md-3-4,.pure-u-md-1-5,.pure-u-md-2-5,.pure-u-md-3-5,.pure-u-md-4-5,.pure-u-md-5-5,.pure-u-md-1-6,.pure-u-md-5-6,.pure-u-md-1-8,.pure-u-md-3-8,.pure-u-md-5-8,.pure-u-md-7-8,.pure-u-md-1-12,.pure-u-md-5-12,.pure-u-md-7-12,.pure-u-md-11-12,.pure-u-md-1-24,.pure-u-md-2-24,.pure-u-md-3-24,.pure-u-md-4-24,.pure-u-md-5-24,.pure-u-md-6-24,.pure-u-md-7-24,.pure-u-md-8-24,.pure-u-md-9-24,.pure-u-md-10-24,.pure-u-md-11-24,.pure-u-md-12-24,.pure-u-md-13-24,.pure-u-md-14-24,.pure-u-md-15-24,.pure-u-md-16-24,.pure-u-md-17-24,.pure-u-md-18-24,.pure-u-md-19-24,.pure-u-md-20-24,.pure-u-md-21-24,.pure-u-md-22-24,.pure-u-md-23-24,.pure-u-md-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-md-1-24{width:4.1667%}.pure-u-md-1-12,.pure-u-md-2-24{width:8.3333%}.pure-u-md-1-8,.pure-u-md-3-24{width:12.5%}.pure-u-md-1-6,.pure-u-md-4-24{width:16.6667%}.pure-u-md-1-5{width:20%}.pure-u-md-5-24{width:20.8333%}.pure-u-md-1-4,.pure-u-md-6-24{width:25%}.pure-u-md-7-24{width:29.1667%}.pure-u-md-1-3,.pure-u-md-8-24{width:33.3333%}.pure-u-md-3-8,.pure-u-md-9-24{width:37.5%}.pure-u-md-2-5{width:40%}.pure-u-md-5-12,.pure-u-md-10-24{width:41.6667%}.pure-u-md-11-24{width:45.8333%}.pure-u-md-1-2,.pure-u-md-12-24{width:50%}.pure-u-md-13-24{width:54.1667%}.pure-u-md-7-12,.pure-u-md-14-24{width:58.3333%}.pure-u-md-3-5{width:60%}.pure-u-md-5-8,.pure-u-md-15-24{width:62.5%}.pure-u-md-2-3,.pure-u-md-16-24{width:66.6667%}.pure-u-md-17-24{width:70.8333%}.pure-u-md-3-4,.pure-u-md-18-24{width:75%}.pure-u-md-19-24{width:79.1667%}.pure-u-md-4-5{width:80%}.pure-u-md-5-6,.pure-u-md-20-24{width:83.3333%}.pure-u-md-7-8,.pure-u-md-21-24{width:87.5%}.pure-u-md-11-12,.pure-u-md-22-24{width:91.6667%}.pure-u-md-23-24{width:95.8333%}.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-5-5,.pure-u-md-24-24{width:100%}}@media screen and (min-width:64em){.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-1-2,.pure-u-lg-1-3,.pure-u-lg-2-3,.pure-u-lg-1-4,.pure-u-lg-3-4,.pure-u-lg-1-5,.pure-u-lg-2-5,.pure-u-lg-3-5,.pure-u-lg-4-5,.pure-u-lg-5-5,.pure-u-lg-1-6,.pure-u-lg-5-6,.pure-u-lg-1-8,.pure-u-lg-3-8,.pure-u-lg-5-8,.pure-u-lg-7-8,.pure-u-lg-1-12,.pure-u-lg-5-12,.pure-u-lg-7-12,.pure-u-lg-11-12,.pure-u-lg-1-24,.pure-u-lg-2-24,.pure-u-lg-3-24,.pure-u-lg-4-24,.pure-u-lg-5-24,.pure-u-lg-6-24,.pure-u-lg-7-24,.pure-u-lg-8-24,.pure-u-lg-9-24,.pure-u-lg-10-24,.pure-u-lg-11-24,.pure-u-lg-12-24,.pure-u-lg-13-24,.pure-u-lg-14-24,.pure-u-lg-15-24,.pure-u-lg-16-24,.pure-u-lg-17-24,.pure-u-lg-18-24,.pure-u-lg-19-24,.pure-u-lg-20-24,.pure-u-lg-21-24,.pure-u-lg-22-24,.pure-u-lg-23-24,.pure-u-lg-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-lg-1-24{width:4.1667%}.pure-u-lg-1-12,.pure-u-lg-2-24{width:8.3333%}.pure-u-lg-1-8,.pure-u-lg-3-24{width:12.5%}.pure-u-lg-1-6,.pure-u-lg-4-24{width:16.6667%}.pure-u-lg-1-5{width:20%}.pure-u-lg-5-24{width:20.8333%}.pure-u-lg-1-4,.pure-u-lg-6-24{width:25%}.pure-u-lg-7-24{width:29.1667%}.pure-u-lg-1-3,.pure-u-lg-8-24{width:33.3333%}.pure-u-lg-3-8,.pure-u-lg-9-24{width:37.5%}.pure-u-lg-2-5{width:40%}.pure-u-lg-5-12,.pure-u-lg-10-24{width:41.6667%}.pure-u-lg-11-24{width:45.8333%}.pure-u-lg-1-2,.pure-u-lg-12-24{width:50%}.pure-u-lg-13-24{width:54.1667%}.pure-u-lg-7-12,.pure-u-lg-14-24{width:58.3333%}.pure-u-lg-3-5{width:60%}.pure-u-lg-5-8,.pure-u-lg-15-24{width:62.5%}.pure-u-lg-2-3,.pure-u-lg-16-24{width:66.6667%}.pure-u-lg-17-24{width:70.8333%}.pure-u-lg-3-4,.pure-u-lg-18-24{width:75%}.pure-u-lg-19-24{width:79.1667%}.pure-u-lg-4-5{width:80%}.pure-u-lg-5-6,.pure-u-lg-20-24{width:83.3333%}.pure-u-lg-7-8,.pure-u-lg-21-24{width:87.5%}.pure-u-lg-11-12,.pure-u-lg-22-24{width:91.6667%}.pure-u-lg-23-24{width:95.8333%}.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-5-5,.pure-u-lg-24-24{width:100%}}@media screen and (min-width:80em){.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-1-2,.pure-u-xl-1-3,.pure-u-xl-2-3,.pure-u-xl-1-4,.pure-u-xl-3-4,.pure-u-xl-1-5,.pure-u-xl-2-5,.pure-u-xl-3-5,.pure-u-xl-4-5,.pure-u-xl-5-5,.pure-u-xl-1-6,.pure-u-xl-5-6,.pure-u-xl-1-8,.pure-u-xl-3-8,.pure-u-xl-5-8,.pure-u-xl-7-8,.pure-u-xl-1-12,.pure-u-xl-5-12,.pure-u-xl-7-12,.pure-u-xl-11-12,.pure-u-xl-1-24,.pure-u-xl-2-24,.pure-u-xl-3-24,.pure-u-xl-4-24,.pure-u-xl-5-24,.pure-u-xl-6-24,.pure-u-xl-7-24,.pure-u-xl-8-24,.pure-u-xl-9-24,.pure-u-xl-10-24,.pure-u-xl-11-24,.pure-u-xl-12-24,.pure-u-xl-13-24,.pure-u-xl-14-24,.pure-u-xl-15-24,.pure-u-xl-16-24,.pure-u-xl-17-24,.pure-u-xl-18-24,.pure-u-xl-19-24,.pure-u-xl-20-24,.pure-u-xl-21-24,.pure-u-xl-22-24,.pure-u-xl-23-24,.pure-u-xl-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-xl-1-24{width:4.1667%}.pure-u-xl-1-12,.pure-u-xl-2-24{width:8.3333%}.pure-u-xl-1-8,.pure-u-xl-3-24{width:12.5%}.pure-u-xl-1-6,.pure-u-xl-4-24{width:16.6667%}.pure-u-xl-1-5{width:20%}.pure-u-xl-5-24{width:20.8333%}.pure-u-xl-1-4,.pure-u-xl-6-24{width:25%}.pure-u-xl-7-24{width:29.1667%}.pure-u-xl-1-3,.pure-u-xl-8-24{width:33.3333%}.pure-u-xl-3-8,.pure-u-xl-9-24{width:37.5%}.pure-u-xl-2-5{width:40%}.pure-u-xl-5-12,.pure-u-xl-10-24{width:41.6667%}.pure-u-xl-11-24{width:45.8333%}.pure-u-xl-1-2,.pure-u-xl-12-24{width:50%}.pure-u-xl-13-24{width:54.1667%}.pure-u-xl-7-12,.pure-u-xl-14-24{width:58.3333%}.pure-u-xl-3-5{width:60%}.pure-u-xl-5-8,.pure-u-xl-15-24{width:62.5%}.pure-u-xl-2-3,.pure-u-xl-16-24{width:66.6667%}.pure-u-xl-17-24{width:70.8333%}.pure-u-xl-3-4,.pure-u-xl-18-24{width:75%}.pure-u-xl-19-24{width:79.1667%}.pure-u-xl-4-5{width:80%}.pure-u-xl-5-6,.pure-u-xl-20-24{width:83.3333%}.pure-u-xl-7-8,.pure-u-xl-21-24{width:87.5%}.pure-u-xl-11-12,.pure-u-xl-22-24{width:91.6667%}.pure-u-xl-23-24{width:95.8333%}.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-5-5,.pure-u-xl-24-24{width:100%}}@media screen and (min-width:120em){.pure-u-xxl-1,.pure-u-xxl-1-1,.pure-u-xxl-1-2,.pure-u-xxl-1-3,.pure-u-xxl-2-3,.pure-u-xxl-1-4,.pure-u-xxl-3-4,.pure-u-xxl-1-5,.pure-u-xxl-2-5,.pure-u-xxl-3-5,.pure-u-xxl-4-5,.pure-u-xxl-5-5,.pure-u-xxl-1-6,.pure-u-xxl-5-6,.pure-u-xxl-1-8,.pure-u-xxl-3-8,.pure-u-xxl-5-8,.pure-u-xxl-7-8,.pure-u-xxl-1-12,.pure-u-xxl-5-12,.pure-u-xxl-7-12,.pure-u-xxl-11-12,.pure-u-xxl-1-24,.pure-u-xxl-2-24,.pure-u-xxl-3-24,.pure-u-xxl-4-24,.pure-u-xxl-5-24,.pure-u-xxl-6-24,.pure-u-xxl-7-24,.pure-u-xxl-8-24,.pure-u-xxl-9-24,.pure-u-xxl-10-24,.pure-u-xxl-11-24,.pure-u-xxl-12-24,.pure-u-xxl-13-24,.pure-u-xxl-14-24,.pure-u-xxl-15-24,.pure-u-xxl-16-24,.pure-u-xxl-17-24,.pure-u-xxl-18-24,.pure-u-xxl-19-24,.pure-u-xxl-20-24,.pure-u-xxl-21-24,.pure-u-xxl-22-24,.pure-u-xxl-23-24,.pure-u-xxl-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-xxl-1-24{width:4.1667%}.pure-u-xxl-1-12,.pure-u-xxl-2-24{width:8.3333%}.pure-u-xxl-1-8,.pure-u-xxl-3-24{width:12.5%}.pure-u-xxl-1-6,.pure-u-xxl-4-24{width:16.6667%}.pure-u-xxl-1-5{width:20%}.pure-u-xxl-5-24{width:20.8333%}.pure-u-xxl-1-4,.pure-u-xxl-6-24{width:25%}.pure-u-xxl-7-24{width:29.1667%}.pure-u-xxl-1-3,.pure-u-xxl-8-24{width:33.3333%}.pure-u-xxl-3-8,.pure-u-xxl-9-24{width:37.5%}.pure-u-xxl-2-5{width:40%}.pure-u-xxl-5-12,.pure-u-xxl-10-24{width:41.6667%}.pure-u-xxl-11-24{width:45.8333%}.pure-u-xxl-1-2,.pure-u-xxl-12-24{width:50%}.pure-u-xxl-13-24{width:54.1667%}.pure-u-xxl-7-12,.pure-u-xxl-14-24{width:58.3333%}.pure-u-xxl-3-5{width:60%}.pure-u-xxl-5-8,.pure-u-xxl-15-24{width:62.5%}.pure-u-xxl-2-3,.pure-u-xxl-16-24{width:66.6667%}.pure-u-xxl-17-24{width:70.8333%}.pure-u-xxl-3-4,.pure-u-xxl-18-24{width:75%}.pure-u-xxl-19-24{width:79.1667%}.pure-u-xxl-4-5{width:80%}.pure-u-xxl-5-6,.pure-u-xxl-20-24{width:83.3333%}.pure-u-xxl-7-8,.pure-u-xxl-21-24{width:87.5%}.pure-u-xxl-11-12,.pure-u-xxl-22-24{width:91.6667%}.pure-u-xxl-23-24{width:95.8333%}.pure-u-xxl-1,.pure-u-xxl-1-1,.pure-u-xxl-5-5,.pure-u-xxl-24-24{width:100%}}body{font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}header,main,footer{margin:2em}.padding{padding:1em}.overflow{overflow-x:auto}.overflow table{width:100%}.overflow table td,.overflow table th{padding:.5em}.overflow table td:not(:last-child),.overflow table th:not(:last-child){width:1px;text-align:left;white-space:nowrap}.overflow table td:last-child,.overflow table th:last-child{white-space:nowrap}.hspace{height:1em;display:block}.pure-button-action{background-color:#42b8dd!important}.pure-button-success{background-color:#1cb841!important}.pure-button-xsmall{font-size:70%}.pure-button-small{font-size:85%}.pure-button-large{font-size:110%}.pure-button-xlarge{font-size:125%} \ No newline at end of file +html{-webkit-text-size-adjust:100%;line-height:1.15}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace;font-size:1em}a{background-color:#0000}abbr[title]{text-decoration:underline;border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;max-width:100%;white-space:normal;padding:0;display:table}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template,[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;flex-flow:wrap;align-content:flex-start;font-family:FreeSans,Arimo,Droid Sans,Helvetica,Arial,sans-serif;display:flex}@media (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-5-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-2-24,.pure-u-3-24,.pure-u-4-24,.pure-u-5-24,.pure-u-6-24,.pure-u-7-24,.pure-u-8-24,.pure-u-9-24,.pure-u-10-24,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-5-12,.pure-u-10-24{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-7-12,.pure-u-14-24{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-5-8,.pure-u-15-24{width:62.5%}.pure-u-2-3,.pure-u-16-24{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-3-4,.pure-u-18-24{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-5-6,.pure-u-20-24{width:83.3333%}.pure-u-7-8,.pure-u-21-24{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-5-5,.pure-u-24-24{width:100%}.pure-button{white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;user-select:none;box-sizing:border-box;line-height:normal;display:inline-block}.pure-button::-moz-focus-inner{border:0;padding:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{color:#000c;background-color:#e6e6e6;border:#0000;border-radius:2px;padding:.5em 1em;font-family:inherit;font-size:100%;text-decoration:none}.pure-button-hover,.pure-button:hover,.pure-button:focus{background-image:linear-gradient(#0000,#0000000d 40%,#0000001a)}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{border-color:#000;box-shadow:inset 0 0 0 1px #00000026,inset 0 0 6px #0003}.pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:focus,.pure-button-disabled:active{opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none;background-image:none;border:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{color:#fff;background-color:#0078e7}.pure-button-group .pure-button{border-right:1px solid #0003;border-radius:0;margin:0}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-right:none;border-top-right-radius:2px;border-bottom-right-radius:2px}.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form select,.pure-form textarea{vertical-align:middle;box-sizing:border-box;border:1px solid #ccc;border-radius:4px;padding:.5em .6em;display:inline-block;box-shadow:inset 0 1px 3px #ddd}.pure-form input:not([type]){box-sizing:border-box;border:1px solid #ccc;border-radius:4px;padding:.5em .6em;display:inline-block;box-shadow:inset 0 1px 3px #ddd}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=text]:focus,.pure-form input[type=password]:focus,.pure-form input[type=email]:focus,.pure-form input[type=url]:focus,.pure-form input[type=date]:focus,.pure-form input[type=month]:focus,.pure-form input[type=time]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=week]:focus,.pure-form input[type=number]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=color]:focus,.pure-form select:focus,.pure-form textarea:focus,.pure-form input:not([type]):focus{border-color:#129fea;outline:0}.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus,.pure-form input[type=checkbox]:focus{outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=text][disabled],.pure-form input[type=password][disabled],.pure-form input[type=email][disabled],.pure-form input[type=url][disabled],.pure-form input[type=date][disabled],.pure-form input[type=month][disabled],.pure-form input[type=time][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=week][disabled],.pure-form input[type=number][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=color][disabled],.pure-form select[disabled],.pure-form textarea[disabled],.pure-form input:not([type])[disabled]{cursor:not-allowed;color:#cad2d3;background-color:#eaeded}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{color:#777;background-color:#eee;border-color:#ccc}.pure-form input:focus:invalid,.pure-form textarea:focus:invalid,.pure-form select:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus,.pure-form input[type=checkbox]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;background-color:#fff;border:1px solid #ccc}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{border:0;margin:0;padding:.35em 0 .75em}.pure-form legend{width:100%;color:#333;border-bottom:1px solid #e5e5e5;margin-bottom:.3em;padding:.3em 0;display:block}.pure-form-stacked input[type=text],.pure-form-stacked input[type=password],.pure-form-stacked input[type=email],.pure-form-stacked input[type=url],.pure-form-stacked input[type=date],.pure-form-stacked input[type=month],.pure-form-stacked input[type=time],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=week],.pure-form-stacked input[type=number],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=color],.pure-form-stacked input[type=file],.pure-form-stacked select,.pure-form-stacked label,.pure-form-stacked textarea,.pure-form-stacked input:not([type]){margin:.25em 0;display:block}.pure-form-aligned input,.pure-form-aligned textarea,.pure-form-aligned select,.pure-form-message-inline{vertical-align:middle;display:inline-block}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;vertical-align:middle;width:10em;margin:0 1em 0 0;display:inline-block}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form input.pure-input-rounded,.pure-form .pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{border-radius:0;margin:0 0 -1px;padding:10px;display:block;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{border-radius:4px 4px 0 0;margin:0;top:1px}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{border-radius:4px;margin:0;top:1px}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{border-radius:0 0 4px 4px;margin:0;top:-2px}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{color:#666;vertical-align:middle;padding-left:.3em;font-size:.875em;display:inline-block}.pure-form-message{color:#666;font-size:.875em;display:block}@media only screen and (max-width:480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=text],.pure-group input[type=password],.pure-group input[type=email],.pure-group input[type=url],.pure-group input[type=date],.pure-group input[type=month],.pure-group input[type=time],.pure-group input[type=datetime],.pure-group input[type=datetime-local],.pure-group input[type=week],.pure-group input[type=number],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=color]{margin-bottom:0}.pure-form-aligned .pure-control-group label{text-align:left;width:100%;margin-bottom:.3em;display:block}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form-message-inline,.pure-form-message{padding:.2em 0 .8em;font-size:.75em;display:block}}.pure-menu{box-sizing:border-box}.pure-menu-fixed{z-index:3;position:fixed;top:0;left:0}.pure-menu-list,.pure-menu-item{position:relative}.pure-menu-list{margin:0;padding:0;list-style:none}.pure-menu-item{height:100%;margin:0;padding:0}.pure-menu-link,.pure-menu-heading{white-space:nowrap;text-decoration:none;display:block}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-separator{vertical-align:middle;display:inline-block}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{z-index:3;margin:0;padding:0;display:none;position:absolute;top:0;left:100%}.pure-menu-horizontal .pure-menu-children{width:inherit;top:auto;left:0}.pure-menu-allow-hover:hover>.pure-menu-children,.pure-menu-active>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{content:"▸";padding-left:.5em;font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"▾"}.pure-menu-scrollable{overflow-x:hidden;overflow-y:scroll}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;padding:.5em 0;overflow-x:auto;overflow-y:hidden}.pure-menu-separator,.pure-menu-horizontal .pure-menu-children .pure-menu-separator{height:1px;background-color:#ccc;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{width:auto;display:block}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-link,.pure-menu-heading{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{cursor:default;background-color:#0000}.pure-menu-active>.pure-menu-link,.pure-menu-link:hover,.pure-menu-link:focus{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;text-align:center;padding:1em 0;font:italic 85%/1 arial,sans-serif}.pure-table td,.pure-table th{font-size:inherit;border-width:0 0 0 1px;border-left-style:solid;border-left-color:#cbcbcb;margin:0;padding:.5em 1em;overflow:visible}.pure-table thead{color:#000;text-align:left;vertical-align:bottom;background-color:#e0e0e0}.pure-table td{background-color:#0000}.pure-table-odd td,.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px;border-bottom-style:solid;border-bottom-color:#cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@media screen and (min-width:35.5em){.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-1-2,.pure-u-sm-1-3,.pure-u-sm-2-3,.pure-u-sm-1-4,.pure-u-sm-3-4,.pure-u-sm-1-5,.pure-u-sm-2-5,.pure-u-sm-3-5,.pure-u-sm-4-5,.pure-u-sm-5-5,.pure-u-sm-1-6,.pure-u-sm-5-6,.pure-u-sm-1-8,.pure-u-sm-3-8,.pure-u-sm-5-8,.pure-u-sm-7-8,.pure-u-sm-1-12,.pure-u-sm-5-12,.pure-u-sm-7-12,.pure-u-sm-11-12,.pure-u-sm-1-24,.pure-u-sm-2-24,.pure-u-sm-3-24,.pure-u-sm-4-24,.pure-u-sm-5-24,.pure-u-sm-6-24,.pure-u-sm-7-24,.pure-u-sm-8-24,.pure-u-sm-9-24,.pure-u-sm-10-24,.pure-u-sm-11-24,.pure-u-sm-12-24,.pure-u-sm-13-24,.pure-u-sm-14-24,.pure-u-sm-15-24,.pure-u-sm-16-24,.pure-u-sm-17-24,.pure-u-sm-18-24,.pure-u-sm-19-24,.pure-u-sm-20-24,.pure-u-sm-21-24,.pure-u-sm-22-24,.pure-u-sm-23-24,.pure-u-sm-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-sm-1-24{width:4.1667%}.pure-u-sm-1-12,.pure-u-sm-2-24{width:8.3333%}.pure-u-sm-1-8,.pure-u-sm-3-24{width:12.5%}.pure-u-sm-1-6,.pure-u-sm-4-24{width:16.6667%}.pure-u-sm-1-5{width:20%}.pure-u-sm-5-24{width:20.8333%}.pure-u-sm-1-4,.pure-u-sm-6-24{width:25%}.pure-u-sm-7-24{width:29.1667%}.pure-u-sm-1-3,.pure-u-sm-8-24{width:33.3333%}.pure-u-sm-3-8,.pure-u-sm-9-24{width:37.5%}.pure-u-sm-2-5{width:40%}.pure-u-sm-5-12,.pure-u-sm-10-24{width:41.6667%}.pure-u-sm-11-24{width:45.8333%}.pure-u-sm-1-2,.pure-u-sm-12-24{width:50%}.pure-u-sm-13-24{width:54.1667%}.pure-u-sm-7-12,.pure-u-sm-14-24{width:58.3333%}.pure-u-sm-3-5{width:60%}.pure-u-sm-5-8,.pure-u-sm-15-24{width:62.5%}.pure-u-sm-2-3,.pure-u-sm-16-24{width:66.6667%}.pure-u-sm-17-24{width:70.8333%}.pure-u-sm-3-4,.pure-u-sm-18-24{width:75%}.pure-u-sm-19-24{width:79.1667%}.pure-u-sm-4-5{width:80%}.pure-u-sm-5-6,.pure-u-sm-20-24{width:83.3333%}.pure-u-sm-7-8,.pure-u-sm-21-24{width:87.5%}.pure-u-sm-11-12,.pure-u-sm-22-24{width:91.6667%}.pure-u-sm-23-24{width:95.8333%}.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-5-5,.pure-u-sm-24-24{width:100%}}@media screen and (min-width:48em){.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-1-2,.pure-u-md-1-3,.pure-u-md-2-3,.pure-u-md-1-4,.pure-u-md-3-4,.pure-u-md-1-5,.pure-u-md-2-5,.pure-u-md-3-5,.pure-u-md-4-5,.pure-u-md-5-5,.pure-u-md-1-6,.pure-u-md-5-6,.pure-u-md-1-8,.pure-u-md-3-8,.pure-u-md-5-8,.pure-u-md-7-8,.pure-u-md-1-12,.pure-u-md-5-12,.pure-u-md-7-12,.pure-u-md-11-12,.pure-u-md-1-24,.pure-u-md-2-24,.pure-u-md-3-24,.pure-u-md-4-24,.pure-u-md-5-24,.pure-u-md-6-24,.pure-u-md-7-24,.pure-u-md-8-24,.pure-u-md-9-24,.pure-u-md-10-24,.pure-u-md-11-24,.pure-u-md-12-24,.pure-u-md-13-24,.pure-u-md-14-24,.pure-u-md-15-24,.pure-u-md-16-24,.pure-u-md-17-24,.pure-u-md-18-24,.pure-u-md-19-24,.pure-u-md-20-24,.pure-u-md-21-24,.pure-u-md-22-24,.pure-u-md-23-24,.pure-u-md-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-md-1-24{width:4.1667%}.pure-u-md-1-12,.pure-u-md-2-24{width:8.3333%}.pure-u-md-1-8,.pure-u-md-3-24{width:12.5%}.pure-u-md-1-6,.pure-u-md-4-24{width:16.6667%}.pure-u-md-1-5{width:20%}.pure-u-md-5-24{width:20.8333%}.pure-u-md-1-4,.pure-u-md-6-24{width:25%}.pure-u-md-7-24{width:29.1667%}.pure-u-md-1-3,.pure-u-md-8-24{width:33.3333%}.pure-u-md-3-8,.pure-u-md-9-24{width:37.5%}.pure-u-md-2-5{width:40%}.pure-u-md-5-12,.pure-u-md-10-24{width:41.6667%}.pure-u-md-11-24{width:45.8333%}.pure-u-md-1-2,.pure-u-md-12-24{width:50%}.pure-u-md-13-24{width:54.1667%}.pure-u-md-7-12,.pure-u-md-14-24{width:58.3333%}.pure-u-md-3-5{width:60%}.pure-u-md-5-8,.pure-u-md-15-24{width:62.5%}.pure-u-md-2-3,.pure-u-md-16-24{width:66.6667%}.pure-u-md-17-24{width:70.8333%}.pure-u-md-3-4,.pure-u-md-18-24{width:75%}.pure-u-md-19-24{width:79.1667%}.pure-u-md-4-5{width:80%}.pure-u-md-5-6,.pure-u-md-20-24{width:83.3333%}.pure-u-md-7-8,.pure-u-md-21-24{width:87.5%}.pure-u-md-11-12,.pure-u-md-22-24{width:91.6667%}.pure-u-md-23-24{width:95.8333%}.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-5-5,.pure-u-md-24-24{width:100%}}@media screen and (min-width:64em){.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-1-2,.pure-u-lg-1-3,.pure-u-lg-2-3,.pure-u-lg-1-4,.pure-u-lg-3-4,.pure-u-lg-1-5,.pure-u-lg-2-5,.pure-u-lg-3-5,.pure-u-lg-4-5,.pure-u-lg-5-5,.pure-u-lg-1-6,.pure-u-lg-5-6,.pure-u-lg-1-8,.pure-u-lg-3-8,.pure-u-lg-5-8,.pure-u-lg-7-8,.pure-u-lg-1-12,.pure-u-lg-5-12,.pure-u-lg-7-12,.pure-u-lg-11-12,.pure-u-lg-1-24,.pure-u-lg-2-24,.pure-u-lg-3-24,.pure-u-lg-4-24,.pure-u-lg-5-24,.pure-u-lg-6-24,.pure-u-lg-7-24,.pure-u-lg-8-24,.pure-u-lg-9-24,.pure-u-lg-10-24,.pure-u-lg-11-24,.pure-u-lg-12-24,.pure-u-lg-13-24,.pure-u-lg-14-24,.pure-u-lg-15-24,.pure-u-lg-16-24,.pure-u-lg-17-24,.pure-u-lg-18-24,.pure-u-lg-19-24,.pure-u-lg-20-24,.pure-u-lg-21-24,.pure-u-lg-22-24,.pure-u-lg-23-24,.pure-u-lg-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-lg-1-24{width:4.1667%}.pure-u-lg-1-12,.pure-u-lg-2-24{width:8.3333%}.pure-u-lg-1-8,.pure-u-lg-3-24{width:12.5%}.pure-u-lg-1-6,.pure-u-lg-4-24{width:16.6667%}.pure-u-lg-1-5{width:20%}.pure-u-lg-5-24{width:20.8333%}.pure-u-lg-1-4,.pure-u-lg-6-24{width:25%}.pure-u-lg-7-24{width:29.1667%}.pure-u-lg-1-3,.pure-u-lg-8-24{width:33.3333%}.pure-u-lg-3-8,.pure-u-lg-9-24{width:37.5%}.pure-u-lg-2-5{width:40%}.pure-u-lg-5-12,.pure-u-lg-10-24{width:41.6667%}.pure-u-lg-11-24{width:45.8333%}.pure-u-lg-1-2,.pure-u-lg-12-24{width:50%}.pure-u-lg-13-24{width:54.1667%}.pure-u-lg-7-12,.pure-u-lg-14-24{width:58.3333%}.pure-u-lg-3-5{width:60%}.pure-u-lg-5-8,.pure-u-lg-15-24{width:62.5%}.pure-u-lg-2-3,.pure-u-lg-16-24{width:66.6667%}.pure-u-lg-17-24{width:70.8333%}.pure-u-lg-3-4,.pure-u-lg-18-24{width:75%}.pure-u-lg-19-24{width:79.1667%}.pure-u-lg-4-5{width:80%}.pure-u-lg-5-6,.pure-u-lg-20-24{width:83.3333%}.pure-u-lg-7-8,.pure-u-lg-21-24{width:87.5%}.pure-u-lg-11-12,.pure-u-lg-22-24{width:91.6667%}.pure-u-lg-23-24{width:95.8333%}.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-5-5,.pure-u-lg-24-24{width:100%}}@media screen and (min-width:80em){.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-1-2,.pure-u-xl-1-3,.pure-u-xl-2-3,.pure-u-xl-1-4,.pure-u-xl-3-4,.pure-u-xl-1-5,.pure-u-xl-2-5,.pure-u-xl-3-5,.pure-u-xl-4-5,.pure-u-xl-5-5,.pure-u-xl-1-6,.pure-u-xl-5-6,.pure-u-xl-1-8,.pure-u-xl-3-8,.pure-u-xl-5-8,.pure-u-xl-7-8,.pure-u-xl-1-12,.pure-u-xl-5-12,.pure-u-xl-7-12,.pure-u-xl-11-12,.pure-u-xl-1-24,.pure-u-xl-2-24,.pure-u-xl-3-24,.pure-u-xl-4-24,.pure-u-xl-5-24,.pure-u-xl-6-24,.pure-u-xl-7-24,.pure-u-xl-8-24,.pure-u-xl-9-24,.pure-u-xl-10-24,.pure-u-xl-11-24,.pure-u-xl-12-24,.pure-u-xl-13-24,.pure-u-xl-14-24,.pure-u-xl-15-24,.pure-u-xl-16-24,.pure-u-xl-17-24,.pure-u-xl-18-24,.pure-u-xl-19-24,.pure-u-xl-20-24,.pure-u-xl-21-24,.pure-u-xl-22-24,.pure-u-xl-23-24,.pure-u-xl-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-xl-1-24{width:4.1667%}.pure-u-xl-1-12,.pure-u-xl-2-24{width:8.3333%}.pure-u-xl-1-8,.pure-u-xl-3-24{width:12.5%}.pure-u-xl-1-6,.pure-u-xl-4-24{width:16.6667%}.pure-u-xl-1-5{width:20%}.pure-u-xl-5-24{width:20.8333%}.pure-u-xl-1-4,.pure-u-xl-6-24{width:25%}.pure-u-xl-7-24{width:29.1667%}.pure-u-xl-1-3,.pure-u-xl-8-24{width:33.3333%}.pure-u-xl-3-8,.pure-u-xl-9-24{width:37.5%}.pure-u-xl-2-5{width:40%}.pure-u-xl-5-12,.pure-u-xl-10-24{width:41.6667%}.pure-u-xl-11-24{width:45.8333%}.pure-u-xl-1-2,.pure-u-xl-12-24{width:50%}.pure-u-xl-13-24{width:54.1667%}.pure-u-xl-7-12,.pure-u-xl-14-24{width:58.3333%}.pure-u-xl-3-5{width:60%}.pure-u-xl-5-8,.pure-u-xl-15-24{width:62.5%}.pure-u-xl-2-3,.pure-u-xl-16-24{width:66.6667%}.pure-u-xl-17-24{width:70.8333%}.pure-u-xl-3-4,.pure-u-xl-18-24{width:75%}.pure-u-xl-19-24{width:79.1667%}.pure-u-xl-4-5{width:80%}.pure-u-xl-5-6,.pure-u-xl-20-24{width:83.3333%}.pure-u-xl-7-8,.pure-u-xl-21-24{width:87.5%}.pure-u-xl-11-12,.pure-u-xl-22-24{width:91.6667%}.pure-u-xl-23-24{width:95.8333%}.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-5-5,.pure-u-xl-24-24{width:100%}}@media screen and (min-width:120em){.pure-u-xxl-1,.pure-u-xxl-1-1,.pure-u-xxl-1-2,.pure-u-xxl-1-3,.pure-u-xxl-2-3,.pure-u-xxl-1-4,.pure-u-xxl-3-4,.pure-u-xxl-1-5,.pure-u-xxl-2-5,.pure-u-xxl-3-5,.pure-u-xxl-4-5,.pure-u-xxl-5-5,.pure-u-xxl-1-6,.pure-u-xxl-5-6,.pure-u-xxl-1-8,.pure-u-xxl-3-8,.pure-u-xxl-5-8,.pure-u-xxl-7-8,.pure-u-xxl-1-12,.pure-u-xxl-5-12,.pure-u-xxl-7-12,.pure-u-xxl-11-12,.pure-u-xxl-1-24,.pure-u-xxl-2-24,.pure-u-xxl-3-24,.pure-u-xxl-4-24,.pure-u-xxl-5-24,.pure-u-xxl-6-24,.pure-u-xxl-7-24,.pure-u-xxl-8-24,.pure-u-xxl-9-24,.pure-u-xxl-10-24,.pure-u-xxl-11-24,.pure-u-xxl-12-24,.pure-u-xxl-13-24,.pure-u-xxl-14-24,.pure-u-xxl-15-24,.pure-u-xxl-16-24,.pure-u-xxl-17-24,.pure-u-xxl-18-24,.pure-u-xxl-19-24,.pure-u-xxl-20-24,.pure-u-xxl-21-24,.pure-u-xxl-22-24,.pure-u-xxl-23-24,.pure-u-xxl-24-24{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;display:inline-block}.pure-u-xxl-1-24{width:4.1667%}.pure-u-xxl-1-12,.pure-u-xxl-2-24{width:8.3333%}.pure-u-xxl-1-8,.pure-u-xxl-3-24{width:12.5%}.pure-u-xxl-1-6,.pure-u-xxl-4-24{width:16.6667%}.pure-u-xxl-1-5{width:20%}.pure-u-xxl-5-24{width:20.8333%}.pure-u-xxl-1-4,.pure-u-xxl-6-24{width:25%}.pure-u-xxl-7-24{width:29.1667%}.pure-u-xxl-1-3,.pure-u-xxl-8-24{width:33.3333%}.pure-u-xxl-3-8,.pure-u-xxl-9-24{width:37.5%}.pure-u-xxl-2-5{width:40%}.pure-u-xxl-5-12,.pure-u-xxl-10-24{width:41.6667%}.pure-u-xxl-11-24{width:45.8333%}.pure-u-xxl-1-2,.pure-u-xxl-12-24{width:50%}.pure-u-xxl-13-24{width:54.1667%}.pure-u-xxl-7-12,.pure-u-xxl-14-24{width:58.3333%}.pure-u-xxl-3-5{width:60%}.pure-u-xxl-5-8,.pure-u-xxl-15-24{width:62.5%}.pure-u-xxl-2-3,.pure-u-xxl-16-24{width:66.6667%}.pure-u-xxl-17-24{width:70.8333%}.pure-u-xxl-3-4,.pure-u-xxl-18-24{width:75%}.pure-u-xxl-19-24{width:79.1667%}.pure-u-xxl-4-5{width:80%}.pure-u-xxl-5-6,.pure-u-xxl-20-24{width:83.3333%}.pure-u-xxl-7-8,.pure-u-xxl-21-24{width:87.5%}.pure-u-xxl-11-12,.pure-u-xxl-22-24{width:91.6667%}.pure-u-xxl-23-24{width:95.8333%}.pure-u-xxl-1,.pure-u-xxl-1-1,.pure-u-xxl-5-5,.pure-u-xxl-24-24{width:100%}}body{font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}header,main,footer{margin:2em}.padding{padding:1em}.overflow{overflow-x:auto}.overflow table{width:100%}.overflow table td,.overflow table th{padding:.5em}.overflow table td:not(:last-child),.overflow table th:not(:last-child){width:1px;text-align:left;white-space:nowrap}.overflow table td:last-child,.overflow table th:last-child{white-space:nowrap}.hspace{height:1em;display:block}.pure-button-action{background-color:#42b8dd!important}.pure-button-success{background-color:#1cb841!important}.pure-button-xsmall{font-size:70%}.pure-button-small{font-size:85%}.pure-button-large{font-size:110%}.pure-button-xlarge{font-size:125%}.error-message{color:red;background-color:pink;border:1px solid red;padding:2px} \ No newline at end of file diff --git a/internal/dis/component/control/static/src/base/index.css b/internal/dis/component/control/static/src/base/index.css index 16ff70a..f5660ce 100644 --- a/internal/dis/component/control/static/src/base/index.css +++ b/internal/dis/component/control/static/src/base/index.css @@ -63,4 +63,11 @@ footer { .pure-button-xlarge { font-size: 125%; -} \ No newline at end of file +} + +.error-message { + background-color: pink; + border: 1px solid red; + padding: 2px; + color: red; +} diff --git a/internal/dis/component/control/static/templates/_form.html b/internal/dis/component/control/static/templates/_form.html index a16dc75..e041b9e 100644 --- a/internal/dis/component/control/static/templates/_form.html +++ b/internal/dis/component/control/static/templates/_form.html @@ -1,34 +1,32 @@ {{ template "_base.html" . }} {{ define "title" }}{{ block "form/title" . }}Form{{ end }}{{ end }} -{{ define "header/time" }} - -{{ end }} -{{ define "header"}} - -{{ end }} - +{{ define "header" }}{{ end }} +{{ define "header/time" }}{{ end }} {{ define "content" }}
    - - {{ block "form/message" . }} - {{ $E := .Error }} - {{ if not (eq $E "") }} -
    - {{ $E }} -
    - {{ end }} - {{ end }} {{ block "form/extra" . }}{{ end }}
    {{ template "form/title" . }} + + {{ block "form/message" . }} + {{ $E := .Error }} + {{ if not (eq $E "") }} +
    +

    + {{ $E }} +

    +
    + {{ end }} + {{ end }} + {{ block "form/inside" . }}{{ end }} {{ .Form }} - +
    -{{ end }} +{{ end }} \ No newline at end of file diff --git a/pkg/httpx/form.go b/pkg/httpx/form.go index 200ef57..c6269b9 100644 --- a/pkg/httpx/form.go +++ b/pkg/httpx/form.go @@ -44,9 +44,13 @@ type Form[D any] struct { RenderForm func(context FormContext, w http.ResponseWriter, r *http.Request) // RenderTemplate represents an optional form to display to the user when RenderForm is nil - // It is passed a [FormContext] instance. + // It is passed the return value of [RenderTemplateContext], or a [FormContext] instance if this does not exist. RenderTemplate *template.Template + // RenderTemplateContext is the context to be used for RenderTemplate. + // When nil, assumed to be the identify function + RenderTemplateContext func(ctx FormContext, r *http.Request) any + // Validate, if non-nil, validates the given submitted values. // There is no guarantee that the values are set. Validate func(r *http.Request, values map[string]string) (D, error) @@ -151,8 +155,16 @@ func (form *Form[D]) renderForm(err error, values map[string]string, w http.Resp panic("form.RenderForm and form.Form are nil") } + // get the template context + var tplctx any + if form.RenderTemplateContext == nil { + tplctx = ctx + } else { + tplctx = form.RenderTemplateContext(ctx, r) + } + // render the form - WriteHTML(ctx, nil, form.RenderTemplate, "", w, r) + WriteHTML(tplctx, nil, form.RenderTemplate, "", w, r) } // FormContext is passed to Form.Form when used