From a0cc2f5c668a7a6ee7565b60c331edc79aca20fc Mon Sep 17 00:00:00 2001 From: Ben Visness Date: Sat, 13 Aug 2022 14:15:00 -0500 Subject: [PATCH] Update auth flows --- public/style.css | 1888 +++++++++-------- public/themes/dark/theme.css | 2 + public/themes/light/theme.css | 2 + src/admintools/admintools.go | 2 +- src/email/email.go | 11 +- src/hmndata/jams.go | 2 +- src/hmnurl/urls.go | 8 +- src/rawdata/scss/_forms.scss | 4 +- .../scss/tachyons/scss/_variables.scss | 2 + src/rawdata/scss/tachyons/scss/_widths.scss | 8 + src/rawdata/scss/themes/dark/_variables.scss | 3 + src/rawdata/scss/themes/light/_variables.scss | 3 + src/templates/src/auth_do_password_reset.html | 57 +- src/templates/src/auth_email_validation.html | 46 +- src/templates/src/auth_login.html | 52 +- src/templates/src/auth_password_reset.html | 44 +- .../src/auth_password_reset_sent.html | 14 +- src/templates/src/auth_register.html | 96 +- src/templates/src/auth_register_success.html | 17 +- src/templates/src/email_password_reset.html | 30 +- src/templates/src/email_registration.html | 17 +- src/templates/src/project.css | 14 +- src/templates/src/user_settings.html | 8 +- src/website/auth.go | 93 +- src/website/user.go | 12 +- 25 files changed, 1295 insertions(+), 1140 deletions(-) diff --git a/public/style.css b/public/style.css index 45c2094..da157f3 100644 --- a/public/style.css +++ b/public/style.css @@ -1,11 +1,11 @@ @charset "UTF-8"; /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ -/* Document +/* Document ========================================================================== */ -/** - * 1. Correct the line height in all browsers. - * 2. Prevent adjustments of font size after orientation changes in - * IE on Windows Phone and in iOS. +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. */ html { line-height: 1.15; @@ -15,16 +15,16 @@ html { -webkit-text-size-adjust: 100%; /* 2 */ } -/* Sections +/* Sections ========================================================================== */ -/** - * Remove the margin in all browsers (opinionated). +/** + * Remove the margin in all browsers (opinionated). */ body { margin: 0; } -/** - * Add the correct display in IE 9-. +/** + * Add the correct display in IE 9-. */ article, aside, @@ -34,19 +34,19 @@ nav, section { display: block; } -/** - * Correct the font size and margin on `h1` elements within `section` and - * `article` contexts in Chrome, Firefox, and Safari. +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. */ h1 { font-size: 2em; margin: 0.67em 0; } -/* Grouping content +/* Grouping content ========================================================================== */ -/** - * Add the correct display in IE 9-. - * 1. Add the correct display in IE. +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. */ figcaption, figure, @@ -54,15 +54,15 @@ main { /* 1 */ display: block; } -/** - * Add the correct margin in IE 8. +/** + * Add the correct margin in IE 8. */ figure { margin: 1em 40px; } -/** - * 1. Add the correct box sizing in Firefox. - * 2. Show the overflow in Edge and IE. +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. */ hr { box-sizing: content-box; @@ -72,9 +72,9 @@ hr { overflow: visible; /* 2 */ } -/** - * 1. Correct the inheritance and scaling of font size in all browsers. - * 2. Correct the odd `em` font sizing in all browsers. +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. */ pre { font-family: monospace, monospace; @@ -82,11 +82,11 @@ pre { font-size: 1em; /* 2 */ } -/* Text-level semantics +/* Text-level semantics ========================================================================== */ -/** - * 1. Remove the gray background on active links in IE 10. - * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. */ a { background-color: transparent; @@ -94,9 +94,9 @@ a { -webkit-text-decoration-skip: objects; /* 2 */ } -/** - * 1. Remove the bottom border in Chrome 57- and Firefox 39-. - * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. +/** + * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. */ abbr[title] { border-bottom: none; @@ -106,23 +106,23 @@ abbr[title] { text-decoration: underline dotted; /* 2 */ } -/** - * Prevent the duplicate application of `bolder` by the next rule in Safari 6. +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. */ b, strong { font-weight: inherit; } -/** - * Add the correct font weight in Chrome, Edge, and Safari. +/** + * Add the correct font weight in Chrome, Edge, and Safari. */ b, strong { font-weight: bolder; } -/** - * 1. Correct the inheritance and scaling of font size in all browsers. - * 2. Correct the odd `em` font sizing in all browsers. +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. */ code, kbd, @@ -132,28 +132,28 @@ samp { font-size: 1em; /* 2 */ } -/** - * Add the correct font style in Android 4.3-. +/** + * Add the correct font style in Android 4.3-. */ dfn { font-style: italic; } -/** - * Add the correct background and color in IE 9-. +/** + * Add the correct background and color in IE 9-. */ mark { background-color: #ff0; color: #000; } -/** - * Add the correct font size in all browsers. +/** + * Add the correct font size in all browsers. */ small { font-size: 80%; } -/** - * Prevent `sub` and `sup` elements from affecting the line height in - * all browsers. +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. */ sub, sup { @@ -168,39 +168,39 @@ sub { sup { top: -0.5em; } -/* Embedded content +/* Embedded content ========================================================================== */ -/** - * Add the correct display in IE 9-. +/** + * Add the correct display in IE 9-. */ audio, video { display: inline-block; } -/** - * Add the correct display in iOS 4-7. +/** + * Add the correct display in iOS 4-7. */ audio:not([controls]) { display: none; height: 0; } -/** - * Remove the border on images inside links in IE 10-. +/** + * Remove the border on images inside links in IE 10-. */ img { border-style: none; } -/** - * Hide the overflow in IE. +/** + * Hide the overflow in IE. */ svg:not(:root) { overflow: hidden; } -/* Forms +/* Forms ========================================================================== */ -/** - * 1. Change the font styles in all browsers (opinionated). - * 2. Remove the margin in Firefox and Safari. +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. */ button, input, @@ -216,28 +216,28 @@ textarea { margin: 0; /* 2 */ } -/** - * Show the overflow in IE. - * 1. Show the overflow in Edge. +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. */ button, input { /* 1 */ overflow: visible; } -/** - * Remove the inheritance of text transform in Edge, Firefox, and IE. - * 1. Remove the inheritance of text transform in Firefox. +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. */ button, select { /* 1 */ text-transform: none; } -/** - * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` - * controls in Android 4. - * 2. Correct the inability to style clickable types in iOS and Safari. +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. */ button, html [type="button"], @@ -246,8 +246,8 @@ html [type="button"], -webkit-appearance: button; /* 2 */ } -/** - * Remove the inner border and padding in Firefox. +/** + * Remove the inner border and padding in Firefox. */ button::-moz-focus-inner, [type="button"]::-moz-focus-inner, @@ -256,8 +256,8 @@ button::-moz-focus-inner, border-style: none; padding: 0; } -/** - * Restore the focus styles unset by the previous rule. +/** + * Restore the focus styles unset by the previous rule. */ button:-moz-focusring, [type="button"]:-moz-focusring, @@ -265,17 +265,17 @@ button:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; } -/** - * Correct the padding in Firefox. +/** + * Correct the padding in Firefox. */ fieldset { padding: 0.35em 0.75em 0.625em; } -/** - * 1. Correct the text wrapping in Edge and IE. - * 2. Correct the color inheritance from `fieldset` elements in IE. - * 3. Remove the padding so developers are not caught out when they zero out - * `fieldset` elements in all browsers. +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. */ legend { box-sizing: border-box; @@ -291,9 +291,9 @@ legend { white-space: normal; /* 1 */ } -/** - * 1. Add the correct display in IE 9-. - * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. */ progress { display: inline-block; @@ -301,15 +301,15 @@ progress { vertical-align: baseline; /* 2 */ } -/** - * Remove the default vertical scrollbar in IE. +/** + * Remove the default vertical scrollbar in IE. */ textarea { overflow: auto; } -/** - * 1. Add the correct box sizing in IE 10-. - * 2. Remove the padding in IE 10-. +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. */ [type="checkbox"], [type="radio"] { @@ -318,16 +318,16 @@ textarea { padding: 0; /* 2 */ } -/** - * Correct the cursor style of increment and decrement buttons in Chrome. +/** + * Correct the cursor style of increment and decrement buttons in Chrome. */ [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } -/** - * 1. Correct the odd appearance in Chrome and Safari. - * 2. Correct the outline style in Safari. +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. */ [type="search"] { -webkit-appearance: textfield; @@ -335,16 +335,16 @@ textarea { outline-offset: -2px; /* 2 */ } -/** - * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. */ [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } -/** - * 1. Correct the inability to style clickable types in iOS and Safari. - * 2. Change font properties to `inherit` in Safari. +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. */ ::-webkit-file-upload-button { -webkit-appearance: button; @@ -352,57 +352,57 @@ textarea { font: inherit; /* 2 */ } -/* Interactive +/* Interactive ========================================================================== */ -/* - * Add the correct display in IE 9-. - * 1. Add the correct display in Edge, IE, and Firefox. +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. */ details, menu { display: block; } -/* - * Add the correct display in all browsers. +/* + * Add the correct display in all browsers. */ summary { display: list-item; } -/* Scripting +/* Scripting ========================================================================== */ -/** - * Add the correct display in IE 9-. +/** + * Add the correct display in IE 9-. */ canvas { display: inline-block; } -/** - * Add the correct display in IE. +/** + * Add the correct display in IE. */ template { display: none; } -/* Hidden +/* Hidden ========================================================================== */ -/** - * Add the correct display in IE 10-. +/** + * Add the correct display in IE 10-. */ [hidden] { display: none; } -/* - - VARIABLES - +/* + + VARIABLES + */ -/* - - DEBUG CHILDREN - Docs: http://tachyons.io/docs/debug/ - - Just add the debug class to any element to see outlines on its - children. - +/* + + DEBUG CHILDREN + Docs: http://tachyons.io/docs/debug/ + + Just add the debug class to any element to see outlines on its + children. + */ .debug * { outline: 1px solid gold; } @@ -413,15 +413,15 @@ template { .debug-black * { outline: 1px solid black; } -/* - - DEBUG GRID - http://tachyons.io/docs/debug-grid/ - - Can be useful for debugging layout issues - or helping to make sure things line up perfectly. - Just tack one of these classes onto a parent element. - +/* + + DEBUG GRID + http://tachyons.io/docs/debug-grid/ + + Can be useful for debugging layout issues + or helping to make sure things line up perfectly. + Just tack one of these classes onto a parent element. + */ .debug-grid { background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTRDOTY4N0U2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTRDOTY4N0Q2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3NjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3NzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsBS+GMAAAAjSURBVHjaYvz//z8DLsD4gcGXiYEAGBIKGBne//fFpwAgwAB98AaF2pjlUQAAAABJRU5ErkJggg==) repeat top left; } @@ -435,10 +435,10 @@ template { .debug-grid-16-solid { background: white url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzY3MkJEN0U2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzY3MkJEN0Y2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3RDY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pve6J3kAAAAzSURBVHjaYvz//z8D0UDsMwMjSRoYP5Gq4SPNbRjVMEQ1fCRDg+in/6+J1AJUxsgAEGAA31BAJMS0GYEAAAAASUVORK5CYII=) repeat top left; } -/* - - BOX SIZING - +/* + + BOX SIZING + */ html, body, @@ -476,22 +476,22 @@ input[type="url"], .border-box { box-sizing: border-box; } -/* - - ASPECT RATIOS - +/* + + ASPECT RATIOS + */ -/* This is for fluid media that is embedded from third party sites like youtube, vimeo etc. - * Wrap the outer element in aspect-ratio and then extend it with the desired ratio i.e - * Make sure there are no height and width attributes on the embedded media. - * Adapted from: https://github.com/suitcss/components-flex-embed - * - * Example: - * - *
- * - *
- * +/* This is for fluid media that is embedded from third party sites like youtube, vimeo etc. + * Wrap the outer element in aspect-ratio and then extend it with the desired ratio i.e + * Make sure there are no height and width attributes on the embedded media. + * Adapted from: https://github.com/suitcss/components-flex-embed + * + * Example: + * + *
+ * + *
+ * * */ .aspect-ratio, .timeline-item .timeline-content-box.embed { height: 0; @@ -648,30 +648,30 @@ input[type="url"], height: 100%; z-index: 100; } } -/* - - IMAGES - Docs: http://tachyons.io/docs/elements/images/ - +/* + + IMAGES + Docs: http://tachyons.io/docs/elements/images/ + */ /* Responsive images! */ img, video { max-width: 100%; } -/* - - BACKGROUND SIZE - Docs: http://tachyons.io/docs/themes/background-size/ - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + BACKGROUND SIZE + Docs: http://tachyons.io/docs/themes/background-size/ + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ -/* - Often used in combination with background image set as an inline style - on an html element. +/* + Often used in combination with background image set as an inline style + on an html element. */ .cover { background-size: cover !important; } @@ -697,25 +697,25 @@ img, video { .contain-l { background-size: contain !important; } } -/* - - BACKGROUND POSITION - - Base: - bg = background - - Modifiers: - -center = center center - -top = top center - -right = center right - -bottom = bottom center - -left = center left - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + BACKGROUND POSITION + + Base: + bg = background + + Modifiers: + -center = center center + -top = top center + -right = center right + -bottom = bottom center + -left = center left + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .bg-center { background-repeat: no-repeat; @@ -788,15 +788,15 @@ img, video { background-repeat: no-repeat; background-position: center left; } } -/* - - OUTLINES - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + OUTLINES + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .outline { outline: 1px solid; } @@ -831,27 +831,27 @@ img, video { .outline-0-l { outline: 0; } } -/* - - BORDERS - Docs: http://tachyons.io/docs/themes/borders/ - - Base: - b = border - - Modifiers: - a = all - t = top - r = right - b = bottom - l = left - n = none - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + BORDERS + Docs: http://tachyons.io/docs/themes/borders/ + + Base: + b = border + + Modifiers: + a = all + t = top + r = right + b = bottom + l = left + n = none + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .ba, .post-content th, .post-content td { border-style: solid; @@ -937,24 +937,24 @@ img, video { border-style: none; border-width: 0; } } -/* - - BORDER COLORS - Docs: http://tachyons.io/docs/themes/borders/ - - Border colors can be used to extend the base - border classes ba,bt,bb,br,bl found in the _borders.css file. - - The base border class by default will set the color of the border - to that of the current text color. These classes are for the cases - where you desire for the text and border colors to be different. - - Base: - b = border - - Modifiers: - --color-name = each color variable name is also a border color name - +/* + + BORDER COLORS + Docs: http://tachyons.io/docs/themes/borders/ + + Border colors can be used to extend the base + border classes ba,bt,bb,br,bl found in the _borders.css file. + + The base border class by default will set the color of the border + to that of the current text color. These classes are for the cases + where you desire for the text and border colors to be different. + + Base: + b = border + + Modifiers: + --color-name = each color variable name is also a border color name + */ .b--black { border-color: #000; } @@ -1142,30 +1142,30 @@ img, video { .b--inherit { border-color: inherit; } -/* - - BORDER RADIUS - Docs: http://tachyons.io/docs/themes/border-radius/ - - Base: - br = border-radius - - Modifiers: - 0 = 0/none - 1 = 1st step in scale - 2 = 2nd step in scale - 3 = 3rd step in scale - 4 = 4th step in scale - - Literal values: - -100 = 100% - -pill = 9999px - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + BORDER RADIUS + Docs: http://tachyons.io/docs/themes/border-radius/ + + Base: + br = border-radius + + Modifiers: + 0 = 0/none + 1 = 1st step in scale + 2 = 2nd step in scale + 3 = 3rd step in scale + 4 = 4th step in scale + + Literal values: + -100 = 100% + -pill = 9999px + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .br0 { border-radius: 0; } @@ -1288,27 +1288,27 @@ img, video { border-top-right-radius: 0; border-bottom-right-radius: 0; } } -/* - - BORDER STYLES - Docs: http://tachyons.io/docs/themes/borders/ - - Depends on base border module in _borders.css - - Base: - b = border-style - - Modifiers: - --none = none - --dotted = dotted - --dashed = dashed - --solid = solid - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + BORDER STYLES + Docs: http://tachyons.io/docs/themes/borders/ + + Depends on base border module in _borders.css + + Base: + b = border-style + + Modifiers: + --none = none + --dotted = dotted + --dashed = dashed + --solid = solid + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .b--dotted { border-style: dotted; } @@ -1352,27 +1352,27 @@ img, video { .b--none-l { border-style: none; } } -/* - - BORDER WIDTHS - Docs: http://tachyons.io/docs/themes/borders/ - - Base: - bw = border-width - - Modifiers: - 0 = 0 width border - 1 = 1st step in border-width scale - 2 = 2nd step in border-width scale - 3 = 3rd step in border-width scale - 4 = 4th step in border-width scale - 5 = 5th step in border-width scale - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + BORDER WIDTHS + Docs: http://tachyons.io/docs/themes/borders/ + + Base: + bw = border-width + + Modifiers: + 0 = 0 width border + 1 = 1st step in border-width scale + 2 = 2nd step in border-width scale + 3 = 3rd step in border-width scale + 4 = 4th step in border-width scale + 5 = 5th step in border-width scale + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .bw0 { border-width: 0; } @@ -1471,16 +1471,16 @@ img, video { .bl-0-l { border-left-width: 0; } } -/* - - BOX-SHADOW - Docs: http://tachyons.io/docs/themes/box-shadow/ - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + BOX-SHADOW + Docs: http://tachyons.io/docs/themes/box-shadow/ + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .shadow-1 { box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.2); } @@ -1533,41 +1533,41 @@ img, video { .shadow-5-l { box-shadow: 4px 4px 8px 0px rgba(0, 0, 0, 0.2); } } -/* - - CODE - +/* + + CODE + */ .pre { overflow-x: auto; overflow-y: hidden; overflow: scroll; } -/* - - COORDINATES - Docs: http://tachyons.io/docs/layout/position/ - - Use in combination with the position module. - - Base: - top - bottom - right - left - - Modifiers: - -0 = literal value 0 - -1 = literal value 1 - -2 = literal value 2 - --1 = literal value -1 - --2 = literal value -2 - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + COORDINATES + Docs: http://tachyons.io/docs/layout/position/ + + Use in combination with the position module. + + Base: + top + bottom + right + left + + Modifiers: + -0 = literal value 0 + -1 = literal value 1 + -2 = literal value 2 + --1 = literal value -1 + --2 = literal value -2 + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .top-0 { top: 0; } @@ -1776,13 +1776,13 @@ img, video { bottom: 0; left: 0; } } -/* - - CLEARFIX - http://tachyons.io/docs/layout/clearfix/ - +/* + + CLEARFIX + http://tachyons.io/docs/layout/clearfix/ + */ -/* Nicolas Gallaghers Clearfix solution +/* Nicolas Gallaghers Clearfix solution Ref: http://nicolasgallagher.com/micro-clearfix-hack/ */ .cf:before, .cf:after { @@ -1837,30 +1837,30 @@ img, video { .cn-l { clear: none; } } -/* - - DISPLAY - Docs: http://tachyons.io/docs/layout/display - - Base: - d = display - - Modifiers: - n = none - b = block - ib = inline-block - it = inline-table - t = table - tc = table-cell - tr = table-row - tcol = table-column - tcolg = table-column-group - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + DISPLAY + Docs: http://tachyons.io/docs/layout/display + + Base: + d = display + + Modifiers: + n = none + b = block + ib = inline-block + it = inline-table + t = table + tc = table-cell + tr = table-row + tcol = table-column + tcolg = table-column-group + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .dn { display: none; } @@ -1895,9 +1895,9 @@ img, video { .dt-column-group { display: table-column-group; } -/* - This will set table to full width and then - all cells will be equal width +/* + This will set table to full width and then + all cells will be equal width */ .dt--fixed { table-layout: fixed; @@ -1984,15 +1984,15 @@ img, video { table-layout: fixed; width: 100%; } } -/* - - FLEXBOX - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + FLEXBOX + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .flex, .tab-bar, .edit-form .edit-form-row { display: flex; } @@ -2000,7 +2000,7 @@ img, video { .inline-flex { display: inline-flex; } -/* 1. Fix for Chrome 44 bug. +/* 1. Fix for Chrome 44 bug. * https://code.google.com/p/chromium/issues/detail?id=506893 */ .flex-auto { flex: 1 1 auto; @@ -2432,30 +2432,30 @@ img, video { .flex-shrink-1-l { flex-shrink: 1; } } -/* - - FLOATS - http://tachyons.io/docs/layout/floats/ - - 1. Floated elements are automatically rendered as block level elements. - Setting floats to display inline will fix the double margin bug in - ie6. You know... just in case. - - 2. Don't forget to clearfix your floats with .cf - - Base: - f = float - - Modifiers: - l = left - r = right - n = none - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + FLOATS + http://tachyons.io/docs/layout/floats/ + + 1. Floated elements are automatically rendered as block level elements. + Setting floats to display inline will fix the double margin bug in + ie6. You know... just in case. + + 2. Don't forget to clearfix your floats with .cf + + Base: + f = float + + Modifiers: + l = left + r = right + n = none + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .fl { float: left; @@ -2498,11 +2498,11 @@ img, video { .fn-l { float: none; } } -/* - - FONT FAMILY GROUPS - Docs: http://tachyons.io/docs/typography/font-family/ - +/* + + FONT FAMILY GROUPS + Docs: http://tachyons.io/docs/typography/font-family/ + */ .sans-serif { font-family: -apple-system, BlinkMacSystemFont, "avenir next", avenir, helvetica, "helvetica neue", ubuntu, roboto, noto, "segoe ui", arial, sans-serif; } @@ -2519,50 +2519,50 @@ img, video { /* Monospaced Typefaces (for code) */ /* From http://cssfontstack.com */ code, .code { - font-family: Consolas, monaco, monospace; } + font-family: Consolas, monaco, monospace; } .courier { - font-family: 'Courier Next', courier, monospace; } + font-family: 'Courier Next', courier, monospace; } /* Sans-Serif Typefaces */ .helvetica { - font-family: 'helvetica neue', helvetica, sans-serif; } + font-family: 'helvetica neue', helvetica, sans-serif; } .avenir { - font-family: 'avenir next', avenir, sans-serif; } + font-family: 'avenir next', avenir, sans-serif; } /* Serif Typefaces */ .athelas { - font-family: athelas, georgia, serif; } + font-family: athelas, georgia, serif; } .georgia { - font-family: georgia, serif; } + font-family: georgia, serif; } .times { - font-family: times, serif; } + font-family: times, serif; } .bodoni { - font-family: "Bodoni MT", serif; } + font-family: "Bodoni MT", serif; } .calisto { - font-family: "Calisto MT", serif; } + font-family: "Calisto MT", serif; } .garamond { - font-family: garamond, serif; } + font-family: garamond, serif; } .baskerville { - font-family: baskerville, serif; } + font-family: baskerville, serif; } + +/* + + FONT STYLE + Docs: http://tachyons.io/docs/typography/font-style/ + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large -/* - - FONT STYLE - Docs: http://tachyons.io/docs/typography/font-style/ - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - */ .i { font-style: italic; } @@ -2588,30 +2588,30 @@ code, .code { .fs-normal-l { font-style: normal; } } -/* - - FONT WEIGHT - Docs: http://tachyons.io/docs/typography/font-weight/ - - Base - fw = font-weight - - Modifiers: - 1 = literal value 100 - 2 = literal value 200 - 3 = literal value 300 - 4 = literal value 400 - 5 = literal value 500 - 6 = literal value 600 - 7 = literal value 700 - 8 = literal value 800 - 9 = literal value 900 - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + FONT WEIGHT + Docs: http://tachyons.io/docs/typography/font-weight/ + + Base + fw = font-weight + + Modifiers: + 1 = literal value 100 + 2 = literal value 200 + 3 = literal value 300 + 4 = literal value 400 + 5 = literal value 500 + 6 = literal value 600 + 7 = literal value 700 + 8 = literal value 800 + 9 = literal value 900 + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .normal { font-weight: normal; } @@ -2718,10 +2718,10 @@ code, .code { .fw9-l { font-weight: 900; } } -/* - - FORMS - +/* + + FORMS + */ .input-reset { -webkit-appearance: none; @@ -2732,37 +2732,37 @@ code, .code { border: 0; padding: 0; } -/* - - HEIGHTS - Docs: http://tachyons.io/docs/layout/heights/ - - Base: - h = height - min-h = min-height - min-vh = min-height vertical screen height - vh = vertical screen height - - Modifiers - 1 = 1st step in height scale - 2 = 2nd step in height scale - 3 = 3rd step in height scale - 4 = 4th step in height scale - 5 = 5th step in height scale - - -25 = literal value 25% - -50 = literal value 50% - -75 = literal value 75% - -100 = literal value 100% - - -auto = string value of auto - -inherit = string value of inherit - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + HEIGHTS + Docs: http://tachyons.io/docs/layout/heights/ + + Base: + h = height + min-h = min-height + min-vh = min-height vertical screen height + vh = vertical screen height + + Modifiers + 1 = 1st step in height scale + 2 = 2nd step in height scale + 3 = 3rd step in height scale + 4 = 4th step in height scale + 5 = 5th step in height scale + + -25 = literal value 25% + -50 = literal value 50% + -75 = literal value 75% + -100 = literal value 100% + + -auto = string value of auto + -inherit = string value of inherit + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ /* Height Scale */ .h1 { @@ -2927,16 +2927,16 @@ code, .code { .h-inherit-l { height: inherit; } } -/* - - LETTER SPACING - Docs: http://tachyons.io/docs/typography/tracking/ - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + LETTER SPACING + Docs: http://tachyons.io/docs/typography/tracking/ + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .tracked { letter-spacing: 0.1em; } @@ -2971,16 +2971,16 @@ code, .code { .tracked-mega-l { letter-spacing: 0.25em; } } -/* - - LINE HEIGHT / LEADING - Docs: http://tachyons.io/docs/typography/line-height - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + LINE HEIGHT / LEADING + Docs: http://tachyons.io/docs/typography/line-height + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .lh-solid { line-height: 1; } @@ -3015,11 +3015,11 @@ code, .code { .lh-copy-l { line-height: 1.5; } } -/* - - LINKS - Docs: http://tachyons.io/docs/elements/links/ - +/* + + LINKS + Docs: http://tachyons.io/docs/elements/links/ + */ .link { text-decoration: none; @@ -3039,44 +3039,44 @@ code, .code { transition: color .15s ease-in; outline: 1px dotted currentColor; } -/* - - LISTS - http://tachyons.io/docs/elements/lists/ - +/* + + LISTS + http://tachyons.io/docs/elements/lists/ + */ .list { list-style-type: none; } -/* - - MAX WIDTHS - Docs: http://tachyons.io/docs/layout/max-widths/ - - Base: - mw = max-width - - Modifiers - 1 = 1st step in width scale - 2 = 2nd step in width scale - 3 = 3rd step in width scale - 4 = 4th step in width scale - 5 = 5th step in width scale - 6 = 6st step in width scale - 7 = 7nd step in width scale - 8 = 8rd step in width scale - 9 = 9th step in width scale - - -100 = literal value 100% - - -none = string value none - - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + MAX WIDTHS + Docs: http://tachyons.io/docs/layout/max-widths/ + + Base: + mw = max-width + + Modifiers + 1 = 1st step in width scale + 2 = 2nd step in width scale + 3 = 3rd step in width scale + 4 = 4th step in width scale + 5 = 5th step in width scale + 6 = 6st step in width scale + 7 = 7nd step in width scale + 8 = 8rd step in width scale + 9 = 9th step in width scale + + -100 = literal value 100% + + -none = string value none + + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ /* Max Width Percentages */ .mw-100, .edit-form textarea { @@ -3186,46 +3186,46 @@ code, .code { .mw-none-l { max-width: none; } } -/* - - WIDTHS - Docs: http://tachyons.io/docs/layout/widths/ - - Base: - w = width - - Modifiers - 1 = 1st step in width scale - 2 = 2nd step in width scale - 3 = 3rd step in width scale - 4 = 4th step in width scale - 5 = 5th step in width scale - - -10 = literal value 10% - -20 = literal value 20% - -25 = literal value 25% - -30 = literal value 30% - -33 = literal value 33% - -34 = literal value 34% - -40 = literal value 40% - -50 = literal value 50% - -60 = literal value 60% - -70 = literal value 70% - -75 = literal value 75% - -80 = literal value 80% - -90 = literal value 90% - -100 = literal value 100% - - -third = 100% / 3 (Not supported in opera mini or IE8) - -two-thirds = 100% / 1.5 (Not supported in opera mini or IE8) - -auto = string value auto - - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + WIDTHS + Docs: http://tachyons.io/docs/layout/widths/ + + Base: + w = width + + Modifiers + 1 = 1st step in width scale + 2 = 2nd step in width scale + 3 = 3rd step in width scale + 4 = 4th step in width scale + 5 = 5th step in width scale + + -10 = literal value 10% + -20 = literal value 20% + -25 = literal value 25% + -30 = literal value 30% + -33 = literal value 33% + -34 = literal value 34% + -40 = literal value 40% + -50 = literal value 50% + -60 = literal value 60% + -70 = literal value 70% + -75 = literal value 75% + -80 = literal value 80% + -90 = literal value 90% + -100 = literal value 100% + + -third = 100% / 3 (Not supported in opera mini or IE8) + -two-thirds = 100% / 1.5 (Not supported in opera mini or IE8) + -auto = string value auto + + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ /* Width Scale */ .w1 { @@ -3246,6 +3246,12 @@ code, .code { .w6 { width: 32rem; } +.w7 { + width: 48rem; } + +.w8 { + width: 64rem; } + .w-10 { width: 10%; } @@ -3310,6 +3316,10 @@ code, .code { width: 16rem; } .w6-ns, .edit-form textarea { width: 32rem; } + .w7-ns { + width: 48rem; } + .w8-ns { + width: 64rem; } .w-10-ns { width: 10%; } .w-20-ns { @@ -3358,6 +3368,10 @@ code, .code { width: 16rem; } .w6-m { width: 32rem; } + .w7-m { + width: 48rem; } + .w8-m { + width: 64rem; } .w-10-m { width: 10%; } .w-20-m { @@ -3406,6 +3420,10 @@ code, .code { width: 16rem; } .w6-l { width: 32rem; } + .w7-l { + width: 48rem; } + .w8-l { + width: 64rem; } .w-10-l { width: 10%; } .w-20-l { @@ -3441,15 +3459,15 @@ code, .code { .w-auto-l { width: auto; } } -/* - - OVERFLOW - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + OVERFLOW + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .overflow-visible { overflow: visible; } @@ -3565,16 +3583,16 @@ code, .code { .overflow-y-auto-l { overflow-y: auto; } } -/* - - POSITIONING - Docs: http://tachyons.io/docs/layout/position/ - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + POSITIONING + Docs: http://tachyons.io/docs/layout/position/ + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .static { position: static; } @@ -3618,11 +3636,11 @@ code, .code { .fixed-l { position: fixed; } } -/* - - OPACITY - Docs: http://tachyons.io/docs/themes/opacity/ - +/* + + OPACITY + Docs: http://tachyons.io/docs/themes/opacity/ + */ .o-100 { opacity: 1; } @@ -3663,10 +3681,10 @@ code, .code { .o-0 { opacity: 0; } -/* - - ROTATIONS - +/* + + ROTATIONS + */ .rotate-45 { transform: rotate(45deg); } @@ -3737,15 +3755,15 @@ code, .code { .rotate-315-l { transform: rotate(315deg); } } -/* - - SKINS - Docs: http://tachyons.io/docs/themes/skins/ - - Classes for setting foreground and background colors on elements. - If you haven't declared a border color, but set border on an element, it will - be set to the current text color. - +/* + + SKINS + Docs: http://tachyons.io/docs/themes/skins/ + + Classes for setting foreground and background colors on elements. + If you haven't declared a border color, but set border on an element, it will + be set to the current text color. + */ /* Text colors */ .black-90 { @@ -4088,13 +4106,13 @@ code, .code { .bg-inherit { background-color: inherit; } -/* - - SKINS:PSEUDO - - Customize the color of an element when - it is focused or hovered over. - +/* + + SKINS:PSEUDO + + Customize the color of an element when + it is focused or hovered over. + */ .hover-black:hover, .hover-black:focus { @@ -4541,39 +4559,39 @@ code, .code { background-color: inherit; } /* Variables */ -/* - SPACING - Docs: http://tachyons.io/docs/layout/spacing/ - - An eight step powers of two scale ranging from 0 to 16rem. - - Base: - p = padding - m = margin - - Modifiers: - a = all - h = horizontal - v = vertical - t = top - r = right - b = bottom - l = left - - 0 = none - 1 = 1st step in spacing scale - 2 = 2nd step in spacing scale - 3 = 3rd step in spacing scale - 4 = 4th step in spacing scale - 5 = 5th step in spacing scale - 6 = 6th step in spacing scale - 7 = 7th step in spacing scale - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + SPACING + Docs: http://tachyons.io/docs/layout/spacing/ + + An eight step powers of two scale ranging from 0 to 16rem. + + Base: + p = padding + m = margin + + Modifiers: + a = all + h = horizontal + v = vertical + t = top + r = right + b = bottom + l = left + + 0 = none + 1 = 1st step in spacing scale + 2 = 2nd step in spacing scale + 3 = 3rd step in spacing scale + 4 = 4th step in spacing scale + 5 = 5th step in spacing scale + 6 = 6th step in spacing scale + 7 = 7th step in spacing scale + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .pa0 { padding: 0; } @@ -5745,32 +5763,32 @@ input[type=submit]:not(.button-small), .notice { margin-left: 16rem; margin-right: 16rem; } } -/* - NEGATIVE MARGINS - - Base: - n = negative - - Modifiers: - a = all - t = top - r = right - b = bottom - l = left - - 1 = 1st step in spacing scale - 2 = 2nd step in spacing scale - 3 = 3rd step in spacing scale - 4 = 4th step in spacing scale - 5 = 5th step in spacing scale - 6 = 6th step in spacing scale - 7 = 7th step in spacing scale - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + NEGATIVE MARGINS + + Base: + n = negative + + Modifiers: + a = all + t = top + r = right + b = bottom + l = left + + 1 = 1st step in spacing scale + 2 = 2nd step in spacing scale + 3 = 3rd step in spacing scale + 4 = 4th step in spacing scale + 5 = 5th step in spacing scale + 6 = 6th step in spacing scale + 7 = 7th step in spacing scale + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .na1 { margin: -0.25rem; } @@ -6093,11 +6111,11 @@ input[type=submit]:not(.button-small), .notice { .nt7-l { margin-top: -16rem; } } -/* - - TABLES - Docs: http://tachyons.io/docs/elements/tables/ - +/* + + TABLES + Docs: http://tachyons.io/docs/elements/tables/ + */ .collapse { border-collapse: collapse; @@ -6121,17 +6139,17 @@ input[type=submit]:not(.button-small), .notice { .stripe-dark:nth-child(odd) { background-color: rgba(0, 0, 0, 0.1); } -/* - - TEXT DECORATION - Docs: http://tachyons.io/docs/typography/text-decoration/ - - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + TEXT DECORATION + Docs: http://tachyons.io/docs/typography/text-decoration/ + + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .strike { text-decoration: line-through; } @@ -6166,25 +6184,25 @@ input[type=submit]:not(.button-small), .notice { .no-underline-l { text-decoration: none; } } -/* - - TEXT ALIGN - Docs: http://tachyons.io/docs/typography/text-align/ - - Base - t = text-align - - Modifiers - l = left - r = right - c = center - j = justify - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + TEXT ALIGN + Docs: http://tachyons.io/docs/typography/text-align/ + + Base + t = text-align + + Modifiers + l = left + r = right + c = center + j = justify + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .tl, .edit-form .edit-form-row > :first-child { text-align: left; } @@ -6228,25 +6246,25 @@ input[type=submit]:not(.button-small), .notice { .tj-l { text-align: justify; } } -/* - - TEXT TRANSFORM - Docs: http://tachyons.io/docs/typography/text-transform/ - - Base: - tt = text-transform - - Modifiers - c = capitalize - l = lowercase - u = uppercase - n = none - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + TEXT TRANSFORM + Docs: http://tachyons.io/docs/typography/text-transform/ + + Base: + tt = text-transform + + Modifiers + c = capitalize + l = lowercase + u = uppercase + n = none + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .ttc { text-transform: capitalize; } @@ -6290,32 +6308,32 @@ input[type=submit]:not(.button-small), .notice { .ttn-l { text-transform: none; } } -/* - - TYPE SCALE - Docs: http://tachyons.io/docs/typography/scale/ - - Base: - f = font-size - - Modifiers - 1 = 1st step in size scale - 2 = 2nd step in size scale - 3 = 3rd step in size scale - 4 = 4th step in size scale - 5 = 5th step in size scale - 6 = 6th step in size scale - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large +/* + + TYPE SCALE + Docs: http://tachyons.io/docs/typography/scale/ + + Base: + f = font-size + + Modifiers + 1 = 1st step in size scale + 2 = 2nd step in size scale + 3 = 3rd step in size scale + 4 = 4th step in size scale + 5 = 5th step in size scale + 6 = 6th step in size scale + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large */ -/* - * For Hero/Marketing Titles - * - * These generally are too large for mobile - * so be careful using them on smaller screens. +/* + * For Hero/Marketing Titles + * + * These generally are too large for mobile + * so be careful using them on smaller screens. * */ .f-6, .f-headline { @@ -6413,16 +6431,16 @@ input[type=submit]:not(.button-small), .notice { .f7-l { font-size: 0.75rem; } } -/* - - TYPOGRAPHY - http://tachyons.io/docs/typography/measure/ - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + TYPOGRAPHY + http://tachyons.io/docs/typography/measure/ + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ /* Measure is limited to ~66 characters */ .measure { @@ -6505,15 +6523,15 @@ input[type=submit]:not(.button-small), .notice { overflow: hidden; text-overflow: ellipsis; } } -/* - - UTILITIES - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + UTILITIES + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ /* Equivalent to .overflow-y-scroll */ .overflow-container { @@ -6556,19 +6574,19 @@ input[type=submit]:not(.button-small), .notice { .ml-auto-l { margin-left: auto; } } -/* - - VISIBILITY - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + VISIBILITY + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ -/* - Text that is hidden but accessible - Ref: http://snook.ca/archives/html_and_css/hiding-content-for-accessibility +/* + Text that is hidden but accessible + Ref: http://snook.ca/archives/html_and_css/hiding-content-for-accessibility */ .clip { position: fixed !important; @@ -6601,15 +6619,15 @@ input[type=submit]:not(.button-small), .notice { /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); } } -/* - - WHITE SPACE - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + WHITE SPACE + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .ws-normal { white-space: normal; } @@ -6644,15 +6662,15 @@ input[type=submit]:not(.button-small), .notice { .pre-l { white-space: pre; } } -/* - - VERTICAL ALIGN - - Media Query Extensions: - -ns = not-small - -m = medium - -l = large - +/* + + VERTICAL ALIGN + + Media Query Extensions: + -ns = not-small + -m = medium + -l = large + */ .v-base { vertical-align: baseline; } @@ -6696,24 +6714,24 @@ input[type=submit]:not(.button-small), .notice { .v-btm-l { vertical-align: bottom; } } -/* - - HOVER EFFECTS - Docs: http://tachyons.io/docs/themes/hovers/ - - - Dim - - Glow - - Hide Child - - Underline text - - Grow - - Pointer - - Shadow - +/* + + HOVER EFFECTS + Docs: http://tachyons.io/docs/themes/hovers/ + + - Dim + - Glow + - Hide Child + - Underline text + - Grow + - Pointer + - Shadow + */ -/* - - Dim element on hover by adding the dim class. - +/* + + Dim element on hover by adding the dim class. + */ .dim { opacity: 1; @@ -6728,10 +6746,10 @@ input[type=submit]:not(.button-small), .notice { opacity: .8; transition: opacity .15s ease-out; } -/* - - Animate opacity to 100% on hover by adding the glow class. - +/* + + Animate opacity to 100% on hover by adding the glow class. + */ .glow { transition: opacity .15s ease-in; } @@ -6741,19 +6759,19 @@ input[type=submit]:not(.button-small), .notice { opacity: 1; transition: opacity .15s ease-in; } -/* - - Hide child & reveal on hover: - - Put the hide-child class on a parent element and any nested element with the - child class will be hidden and displayed on hover or focus. - -
-
Hidden until hover or focus
-
Hidden until hover or focus
-
Hidden until hover or focus
-
Hidden until hover or focus
-
+/* + + Hide child & reveal on hover: + + Put the hide-child class on a parent element and any nested element with the + child class will be hidden and displayed on hover or focus. + +
+
Hidden until hover or focus
+
Hidden until hover or focus
+
Hidden until hover or focus
+
Hidden until hover or focus
+
*/ .hide-child .child { opacity: 0; @@ -6769,7 +6787,7 @@ input[type=submit]:not(.button-small), .notice { .underline-hover:focus { text-decoration: underline; } -/* Can combine this with overflow-hidden to make background images grow on hover +/* Can combine this with overflow-hidden to make background images grow on hover * even if you are using background-size: cover */ .grow { -moz-osx-font-smoothing: grayscale; @@ -6801,11 +6819,11 @@ input[type=submit]:not(.button-small), .notice { .pointer:hover { cursor: pointer; } -/* - Add shadow on hover. - - Performant box-shadow animation pattern from - http://tobiasahlin.com/blog/how-to-animate-box-shadow/ +/* + Add shadow on hover. + + Performant box-shadow animation pattern from + http://tobiasahlin.com/blog/how-to-animate-box-shadow/ */ .shadow-hover { cursor: pointer; @@ -6829,46 +6847,46 @@ input[type=submit]:not(.button-small), .notice { .shadow-hover:focus::after { opacity: 1; } -/* Combine with classes in skins and skins-pseudo for +/* Combine with classes in skins and skins-pseudo for * many different transition possibilities. */ .bg-animate, .bg-animate:hover, .bg-animate:focus { transition: background-color .15s ease-in-out; } -/* - - Z-INDEX - - Base - z = z-index - - Modifiers - -0 = literal value 0 - -1 = literal value 1 - -2 = literal value 2 - -3 = literal value 3 - -4 = literal value 4 - -5 = literal value 5 - -999 = literal value 999 - -9999 = literal value 9999 - - -max = largest accepted z-index value as integer - - -inherit = string value inherit - -initial = string value initial - -unset = string value unset - - MDN: https://developer.mozilla.org/en/docs/Web/CSS/z-index - Spec: http://www.w3.org/TR/CSS2/zindex.html - Articles: - https://philipwalton.com/articles/what-no-one-told-you-about-z-index/ - - Tips on extending: - There might be a time worth using negative z-index values. - Or if you are using tachyons with another project, you might need to - adjust these values to suit your needs. - +/* + + Z-INDEX + + Base + z = z-index + + Modifiers + -0 = literal value 0 + -1 = literal value 1 + -2 = literal value 2 + -3 = literal value 3 + -4 = literal value 4 + -5 = literal value 5 + -999 = literal value 999 + -9999 = literal value 9999 + + -max = largest accepted z-index value as integer + + -inherit = string value inherit + -initial = string value initial + -unset = string value unset + + MDN: https://developer.mozilla.org/en/docs/Web/CSS/z-index + Spec: http://www.w3.org/TR/CSS2/zindex.html + Articles: + https://philipwalton.com/articles/what-no-one-told-you-about-z-index/ + + Tips on extending: + There might be a time worth using negative z-index values. + Or if you are using tachyons with another project, you might need to + adjust these values to suit your needs. + */ .z-0 { z-index: 0; } @@ -6906,12 +6924,12 @@ input[type=submit]:not(.button-small), .notice { .z-unset { z-index: unset; } -/* - - NESTED - Tachyons module for styling nested elements - that are generated by a cms. - +/* + + NESTED + Tachyons module for styling nested elements + that are generated by a cms. + */ .nested-copy-line-height p, .nested-copy-line-height ul, @@ -6954,32 +6972,32 @@ input[type=submit]:not(.button-small), .notice { color: #96ccff; transition: color .15s ease-in; } -/* - - STYLES - - Add custom styles here. - +/* + + STYLES + + Add custom styles here. + */ -/* -Inserts a CSS expression with one or more custom variables. -You can provide an arbitrary number of strings in the second -argument, separated by spaces. Any strings corresponding to -variable names will be replaced by the correct values, while -other strings are left untouched. - -Example usage: - -@include usevar(border-color, dimmer-color); -@include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")"); - -For clarity and to avoid syntax issues, you are encouraged to -use unquoted strings for variables and quoted strings for -everything else. - -For convenience in common cases, if only a single argument -is provided and it does not match an existing variable, this -will throw an error. +/* +Inserts a CSS expression with one or more custom variables. +You can provide an arbitrary number of strings in the second +argument, separated by spaces. Any strings corresponding to +variable names will be replaced by the correct values, while +other strings are left untouched. + +Example usage: + +@include usevar(border-color, dimmer-color); +@include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")"); + +For clarity and to avoid syntax issues, you are encouraged to +use unquoted strings for variables and quoted strings for +everything else. + +For convenience in common cases, if only a single argument +is provided and it does not match an existing variable, this +will throw an error. */ pre, code, .codeblock { /* Comment */ @@ -8422,10 +8440,10 @@ input[type=submit] { input[type=submit]:hover { color: #4c9ed9; color: var(--form-button-color-active); - background-color: #aaa; - background-color: var(--theme-color-dim); - border-color: #aaa; - border-color: var(--theme-color-dim); } + background-color: #666; + background-color: var(--theme-color-light); + border-color: #666; + border-color: var(--theme-color-light); } button.lite, .button.lite, diff --git a/public/themes/dark/theme.css b/public/themes/dark/theme.css index d9a2d2e..bc33ccc 100644 --- a/public/themes/dark/theme.css +++ b/public/themes/dark/theme.css @@ -216,6 +216,8 @@ pre, code, .codeblock { --theme-color-dim: #444; --theme-color-dimmer: #383838; --theme-color-dimmest: #333; + --theme-color-dark: #666; + --theme-color-light: #666; --link-color: #aaa; --link-border-color: #aaa; --hr-color: #aaa; diff --git a/public/themes/light/theme.css b/public/themes/light/theme.css index 5ea692d..00ec130 100644 --- a/public/themes/light/theme.css +++ b/public/themes/light/theme.css @@ -234,6 +234,8 @@ pre, code, .codeblock { --theme-color-dim: #aaa; --theme-color-dimmer: #bbb; --theme-color-dimmest: #ccc; + --theme-color-dark: #666; + --theme-color-light: #666; --link-color: #666; --link-border-color: #666; --hr-color: #444; diff --git a/src/admintools/admintools.go b/src/admintools/admintools.go index 05354a6..21885f3 100644 --- a/src/admintools/admintools.go +++ b/src/admintools/admintools.go @@ -286,7 +286,7 @@ func init() { var err error switch emailType { case "registration": - err = email.SendRegistrationEmail(toAddress, toName, "test_user", "test_token", p) + err = email.SendRegistrationEmail(toAddress, toName, "test_user", "test_token", "", p) case "passwordreset": err = email.SendPasswordReset(toAddress, toName, "test_user", "test_token", time.Now().Add(time.Hour*24), p) default: diff --git a/src/email/email.go b/src/email/email.go index 8025b33..36d3c78 100644 --- a/src/email/email.go +++ b/src/email/email.go @@ -26,14 +26,21 @@ type RegistrationEmailData struct { CompleteRegistrationUrl string } -func SendRegistrationEmail(toAddress string, toName string, username string, completionToken string, perf *perf.RequestPerf) error { +func SendRegistrationEmail( + toAddress string, + toName string, + username string, + completionToken string, + destination string, + perf *perf.RequestPerf, +) error { perf.StartBlock("EMAIL", "Registration email") perf.StartBlock("EMAIL", "Rendering template") contents, err := renderTemplate("email_registration.html", RegistrationEmailData{ Name: toName, HomepageUrl: hmnurl.BuildHomepage(), - CompleteRegistrationUrl: hmnurl.BuildEmailConfirmation(username, completionToken), + CompleteRegistrationUrl: hmnurl.BuildEmailConfirmation(username, completionToken, destination), }) if err != nil { return err diff --git a/src/hmndata/jams.go b/src/hmndata/jams.go index 96a7f1b..db53eea 100644 --- a/src/hmndata/jams.go +++ b/src/hmndata/jams.go @@ -28,7 +28,7 @@ var WRJ2021 = Jam{ var WRJ2022 = Jam{ Name: "Wheel Reinvention Jam 2022", Slug: "WRJ2022", - StartTime: time.Date(2022, 8, 15, 8, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))), + StartTime: time.Date(2022, 8, 3, 8, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))), EndTime: time.Date(2022, 8, 22, 8, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))), } diff --git a/src/hmnurl/urls.go b/src/hmnurl/urls.go index c2d6138..fbe80b9 100644 --- a/src/hmnurl/urls.go +++ b/src/hmnurl/urls.go @@ -119,9 +119,13 @@ func BuildRegistrationSuccess() string { var RegexEmailConfirmation = regexp.MustCompile("^/email_confirmation/(?P[^/]+)/(?P[^/]+)$") -func BuildEmailConfirmation(username, token string) string { +func BuildEmailConfirmation(username, token string, destination string) string { defer CatchPanic() - return Url(fmt.Sprintf("/email_confirmation/%s/%s", url.PathEscape(username), token), nil) + var query []Q + if destination != "" { + query = append(query, Q{"destination", destination}) + } + return Url(fmt.Sprintf("/email_confirmation/%s/%s", url.PathEscape(username), token), query) } var RegexRequestPasswordReset = regexp.MustCompile("^/password_reset$") diff --git a/src/rawdata/scss/_forms.scss b/src/rawdata/scss/_forms.scss index b656b4b..b4db676 100644 --- a/src/rawdata/scss/_forms.scss +++ b/src/rawdata/scss/_forms.scss @@ -163,8 +163,8 @@ input, select, textarea { &:hover { @include usevar('color', 'form-button-color-active'); - @include usevar('background-color', 'theme-color-dim'); - @include usevar('border-color', 'theme-color-dim'); + @include usevar('background-color', 'theme-color-light'); + @include usevar('border-color', 'theme-color-light'); } &.lite { diff --git a/src/rawdata/scss/tachyons/scss/_variables.scss b/src/rawdata/scss/tachyons/scss/_variables.scss index 7ef94a1..339230a 100644 --- a/src/rawdata/scss/tachyons/scss/_variables.scss +++ b/src/rawdata/scss/tachyons/scss/_variables.scss @@ -43,6 +43,8 @@ $width-3: 4rem !default; $width-4: 8rem !default; $width-5: 16rem !default; $width-6: 32rem !default; +$width-7: 48rem !default; +$width-8: 64rem !default; $max-width-1: 1rem !default; $max-width-2: 2rem !default; $max-width-3: 4rem !default; diff --git a/src/rawdata/scss/tachyons/scss/_widths.scss b/src/rawdata/scss/tachyons/scss/_widths.scss index 2b24968..fb0f942 100644 --- a/src/rawdata/scss/tachyons/scss/_widths.scss +++ b/src/rawdata/scss/tachyons/scss/_widths.scss @@ -55,6 +55,8 @@ .w4 { width: $width-4; } .w5 { width: $width-5; } .w6 { width: $width-6; } +.w7 { width: $width-7; } +.w8 { width: $width-8; } .w-10 { width: 10%; } .w-20 { width: 20%; } @@ -82,6 +84,8 @@ .w4-ns { width: $width-4; } .w5-ns { width: $width-5; } .w6-ns { width: $width-6; } + .w7-ns { width: $width-7; } + .w8-ns { width: $width-8; } .w-10-ns { width: 10%; } .w-20-ns { width: 20%; } .w-25-ns { width: 25%; } @@ -108,6 +112,8 @@ .w4-m { width: $width-4; } .w5-m { width: $width-5; } .w6-m { width: $width-6; } + .w7-m { width: $width-7; } + .w8-m { width: $width-8; } .w-10-m { width: 10%; } .w-20-m { width: 20%; } .w-25-m { width: 25%; } @@ -134,6 +140,8 @@ .w4-l { width: $width-4; } .w5-l { width: $width-5; } .w6-l { width: $width-6; } + .w7-l { width: $width-7; } + .w8-l { width: $width-8; } .w-10-l { width: 10%; } .w-20-l { width: 20%; } .w-25-l { width: 25%; } diff --git a/src/rawdata/scss/themes/dark/_variables.scss b/src/rawdata/scss/themes/dark/_variables.scss index 72ec76a..faba642 100644 --- a/src/rawdata/scss/themes/dark/_variables.scss +++ b/src/rawdata/scss/themes/dark/_variables.scss @@ -9,6 +9,9 @@ $vars: ( theme-color-dimmer: #383838, theme-color-dimmest: #333, + theme-color-dark: #666, + theme-color-light: #666, + link-color: #aaa, link-border-color: #aaa, diff --git a/src/rawdata/scss/themes/light/_variables.scss b/src/rawdata/scss/themes/light/_variables.scss index 0f02537..4282dec 100644 --- a/src/rawdata/scss/themes/light/_variables.scss +++ b/src/rawdata/scss/themes/light/_variables.scss @@ -9,6 +9,9 @@ $vars: ( theme-color-dimmer: #bbb, theme-color-dimmest: #ccc, + theme-color-dark: #666, + theme-color-light: #666, + link-color: #666, link-border-color: #666, diff --git a/src/templates/src/auth_do_password_reset.html b/src/templates/src/auth_do_password_reset.html index 3bfa7ad..1e341d4 100644 --- a/src/templates/src/auth_do_password_reset.html +++ b/src/templates/src/auth_do_password_reset.html @@ -1,41 +1,38 @@ {{ template "base.html" . }} {{ define "content" }} -
-
+
+
+

Hi, {{ .Username }}!

+ + {{/*NOTE: The username field isn't `type="hidden"` because this way browser will offer to save the username along with the password */}} - + -

Hi, {{ .Username }}!

-

Please enter a new password

-

- - -

+
Please enter a new password.
-

- - - Enter the same password as before, for verification. -

+
+ + +
- +
- +
{{ end }} diff --git a/src/templates/src/auth_email_validation.html b/src/templates/src/auth_email_validation.html index 97e9b5a..c151684 100644 --- a/src/templates/src/auth_email_validation.html +++ b/src/templates/src/auth_email_validation.html @@ -1,19 +1,39 @@ {{ template "base.html" . }} {{ define "content" }} -
-
- - {{/*NOTE: The username field isn't `type="hidden"` because this way browser will offer to save the username along with the password */}} - +
+ + + -

Hi, {{ .Username }}!

-

You're almost done signing up.

-

To complete your registration and log in, please enter the password you used during the registration process.

- - + {{/*NOTE: The username field isn't `type="hidden"` because this way browser will offer to save the username along with the password */}} + - - -
+

Hi, {{ .Username }}!

+

+ You're almost done signing up. +

+

+ To complete your registration and log in, please enter the password you used during the registration process. +

+ + + + + +
{{ end }} diff --git a/src/templates/src/auth_login.html b/src/templates/src/auth_login.html index cf6b9be..666611f 100644 --- a/src/templates/src/auth_login.html +++ b/src/templates/src/auth_login.html @@ -1,25 +1,43 @@ {{ template "base.html" . }} {{ define "content" }} -
-

Please enter your username and password

-
+
+
+

Log in

+ -

- - -

- -

- - -

- - Forgot your password? -

- -

+
+ + +
+ +
+
+ + Forgot your password? +
+ +
+ +
+ +
+ +
+ Need an account? Sign up. +
+
{{ end }} diff --git a/src/templates/src/auth_password_reset.html b/src/templates/src/auth_password_reset.html index e332ec9..3fd1b4f 100644 --- a/src/templates/src/auth_password_reset.html +++ b/src/templates/src/auth_password_reset.html @@ -1,26 +1,40 @@ {{ template "base.html" . }} {{ define "content" }} -
-

Request a password reset link

-
-

+

+
+

Reset your password

+ +
- -

+ +
-

+

- -

+ +
-

- -

+
+ +
-

- Note: To avoid your being spammed with password reset links, we limit the number of requests per account every 24 hours. -

+
+ Note: To avoid spamming you with password reset links, we limit the number of requests per account every 24 hours. +
+
{{ end }} diff --git a/src/templates/src/auth_password_reset_sent.html b/src/templates/src/auth_password_reset_sent.html index 74e4269..9bb126f 100644 --- a/src/templates/src/auth_password_reset_sent.html +++ b/src/templates/src/auth_password_reset_sent.html @@ -1,9 +1,13 @@ {{ template "base.html" . }} {{ define "content" }} -
-

A password reset link was sent. It'll expire in 24 hours.

-

If for some reason the email shouldn't arrive in a timely fashion, and it also doesn't show up in your spam trap, please contact the staff.

-

* Security best practices prevent us from disclosing whether or not the username and email combination was actually valid. An email may or may not have been sent depending on whether it was or wasn't.

-
+
+

A password reset link was sent.

+

+ It will expire in 24 hours. +

+

+ If for some reason the email doesn't arrive in a timely fashion, and it also doesn't show up in your spam, please contact the staff. +

+
{{ end }} diff --git a/src/templates/src/auth_register.html b/src/templates/src/auth_register.html index 0cfe7ca..1201dfb 100644 --- a/src/templates/src/auth_register.html +++ b/src/templates/src/auth_register.html @@ -1,58 +1,58 @@ {{ template "base.html" . }} {{ define "content" }} -
-
- {{/* NOTE(asaf): No CSRF on register. We don't have a user session yet and I don't think we would gain anything from a pre-login session here */}} +
+
+

Sign up

+ + {{/* NOTE(asaf): No CSRF on register. We don't have a user session yet and I don't think we would gain anything from a pre-login session here */}} + + -

- - - Required. You may use up to 30 characters. Must start with a letter or number. Dashes and underscores are allowed. -

+
+ + +
-

- - - Optional. -

+
+ + +
-

- - -

+
+ + +
-

- - -

+
+ + +
+ + {{/* TODO(asaf): Consider adding some bot-mitigation thing here */}} -

- - - Enter the same password as before, for verification. -

- - {{/* TODO(asaf): Consider adding some bot-mitigation thing here */}} - -

- -

- - +
+ +
+ +
{{ end }} diff --git a/src/templates/src/auth_register_success.html b/src/templates/src/auth_register_success.html index a7d6dc8..d63fec7 100644 --- a/src/templates/src/auth_register_success.html +++ b/src/templates/src/auth_register_success.html @@ -1,11 +1,16 @@ {{ template "base.html" . }} {{ define "content" }} -
-

Hi! You're almost done signing up.

-

We've sent you an email with a confirmation link. Please follow it to complete the registration process.

-

If for some reason the email doesn't arrive in a timely fashion and you also can't find it in your spam trap,
- you should feel free to contact the staff and ask us to activate you manually.
- You'll want to tell us the username you chose and preferably email us from the same address you used to sign up.

+
+

Verify your email

+

+ We've sent you an email with a confirmation link. Please follow it to complete the registration process. +

+

+ If for some reason the email doesn't arrive in a timely fashion and you also can't find it in your spam trap, you should feel free to contact the staff and ask us to activate you manually. +

+

+ Please tell us your username, and ideally email us from the same address you used to sign up. +

{{ end }} diff --git a/src/templates/src/email_password_reset.html b/src/templates/src/email_password_reset.html index 6b25146..3b8cdf3 100644 --- a/src/templates/src/email_password_reset.html +++ b/src/templates/src/email_password_reset.html @@ -1,12 +1,24 @@ -

Hello, {{ .Name }}

-

Someone has requested a password reset for your account.
-We hope it was you. If you didn't request it, we apologise. Kindly ignore this message.

-

To finish the password reset, visit: {{ .DoPasswordResetUrl }}
-This link will be valid for 24 hours (until {{ absolutedate .Expiration }} UTC)

-

Thanks,
-The Handmade Network staff.

+

+ Hello {{ .Name }}, +

+

+ Someone has requested a password reset for your Handmade Network account. To finish the password reset, visit the following link: +

+

+ {{ .DoPasswordResetUrl }} +

+

+ This link will be valid for 24 hours (until {{ absolutedate .Expiration }} UTC). +

+

+ If you did not request this password reset, we apologize - please ignore this message. +

+

+ Thanks,
+ The Handmade Network staff. +


-

-You are receiving this email because someone requested a password reset for your account and supplied both your username and email address correctly. +

+ You are receiving this email because someone requested a password reset for your account and supplied both your username and email address correctly.

diff --git a/src/templates/src/email_registration.html b/src/templates/src/email_registration.html index 0b00ef3..7e82a96 100644 --- a/src/templates/src/email_registration.html +++ b/src/templates/src/email_registration.html @@ -1,11 +1,16 @@ -

Hello, {{ .Name }}

-

Welcome to Handmade Network.
-To complete the registration process, please use the following link: {{ .CompleteRegistrationUrl }}.

+

+ Hello {{ .Name }} - welcome to Handmade Network! +

+

+ To complete the registration process, please use the following link: +

+

+ {{ .CompleteRegistrationUrl }}. +

Thanks,
The Handmade Network staff.


-

-You are receiving this email because someone registered with your email address at Handmade.Network.
-If that wasn't you, kindly ignore this email. If you do not complete the registration, your information will be deleted from our servers after 7 days. +

+You are receiving this email because someone registered with your email address at handmade.network. If that wasn't you, kindly ignore this email. If you do not complete the registration, your information will be deleted from our servers after 7 days.

diff --git a/src/templates/src/project.css b/src/templates/src/project.css index 5ca4474..11c07b4 100644 --- a/src/templates/src/project.css +++ b/src/templates/src/project.css @@ -5,8 +5,9 @@ {{ $themeDimmer := eq .Theme "dark" | ternary (lightness 0.3 $c) (lightness 0.8 $c) | color2css }} {{ $themeDimmest := eq .Theme "dark" | ternary (lightness 0.2 $c) (lightness 0.85 $c) | color2css }} -{{/* Theme "dark" colors are always darker in value, regardless of light or dark theme. */}} +{{/* Theme "dark" and "light" colors are always darker or lighter in value, regardless of theme. */}} {{ $themeDark := eq .Theme "dark" | ternary (lightness 0.30 $c) (lightness 0.35 $c) | color2css }} +{{ $themeLight := eq .Theme "dark" | ternary (lightness 0.55 $c) (lightness 0.55 $c) | color2css }} {{ $linkColor := eq .Theme "dark" | ternary (lightness 0.55 $c) (lightness 0.35 $c) | color2css }} {{ $linkHoverColor := eq .Theme "dark" | ternary (lightness 0.65 $c) (lightness 0.45 $c) | color2css }} @@ -18,6 +19,7 @@ --theme-color-dimmest: {{ $themeDimmest }}; --theme-color-dark: {{ $themeDark }}; + --theme-color-light: {{ $themeLight }}; --link-color: {{ $linkColor }}; --link-hover-color: {{ $linkHoverColor }}; @@ -89,6 +91,11 @@ a:hover, button:hover, .button:hover, input[type=button]:hover { background-color: var(--theme-color-dark); } +.bg-theme-light { + background-color: {{ $themeLight }}; + background-color: var(--theme-color-light); +} + .b--theme { border-color: {{ $c | color2css }}; border-color: var(--theme-color); @@ -114,6 +121,11 @@ a:hover, button:hover, .button:hover, input[type=button]:hover { border-color: var(--theme-color-dark); } +.b--theme-light { + border-color: {{ $themeLight }}; + border-color: var(--theme-color-light); +} + :root { --background-even-background: {{ .PostBgColor }}; } diff --git a/src/templates/src/user_settings.html b/src/templates/src/user_settings.html index fa1bfe8..68ef0fc 100644 --- a/src/templates/src/user_settings.html +++ b/src/templates/src/user_settings.html @@ -90,19 +90,13 @@
New password:
- +
Your password must be 8 or more characters, and must differ from your username and current password. Other than that, please follow best practices.
-
-
New password confirmation:
-
- -
-
diff --git a/src/website/auth.go b/src/website/auth.go index acfd179..c926ea5 100644 --- a/src/website/auth.go +++ b/src/website/auth.go @@ -9,6 +9,7 @@ import ( "time" "git.handmade.network/hmn/hmn/src/auth" + "git.handmade.network/hmn/hmn/src/config" "git.handmade.network/hmn/hmn/src/db" "git.handmade.network/hmn/hmn/src/email" "git.handmade.network/hmn/hmn/src/hmnurl" @@ -23,6 +24,7 @@ var UsernameRegex = regexp.MustCompile(`^[0-9a-zA-Z][\w-]{2,29}$`) type LoginPageData struct { templates.BaseData RedirectUrl string + RegisterUrl string ForgotPasswordUrl string } @@ -33,8 +35,9 @@ func LoginPage(c *RequestContext) ResponseData { var res ResponseData res.MustWriteTemplate("auth_login.html", LoginPageData{ - BaseData: getBaseDataAutocrumb(c, "Log in"), + BaseData: getBaseData(c, "Log in", nil), RedirectUrl: c.Req.URL.Query().Get("redirect"), + RegisterUrl: hmnurl.BuildRegister(), ForgotPasswordUrl: hmnurl.BuildRequestPasswordReset(), }, c.Perf) return res @@ -47,12 +50,14 @@ func Login(c *RequestContext) ResponseData { } redirect := form.Get("redirect") - if redirect == "" { - redirect = "/" + + destination := hmnurl.BuildHomepage() + if redirect != "" && urlIsLocal(redirect) { + destination = redirect } if c.CurrentUser != nil { - res := c.Redirect(redirect, http.StatusSeeOther) + res := c.Redirect(destination, http.StatusSeeOther) res.AddFutureNotice("warn", fmt.Sprintf("You are already logged in as %s.", c.CurrentUser.Username)) return res } @@ -65,7 +70,7 @@ func Login(c *RequestContext) ResponseData { showLoginWithFailure := func(c *RequestContext, redirect string) ResponseData { var res ResponseData - baseData := getBaseDataAutocrumb(c, "Log in") + baseData := getBaseData(c, "Log in", nil) baseData.AddImmediateNotice("failure", "Incorrect username or password") res.MustWriteTemplate("auth_login.html", LoginPageData{ BaseData: baseData, @@ -105,7 +110,7 @@ func Login(c *RequestContext) ResponseData { return c.RejectRequest("You must validate your email address before logging in. You should've received an email shortly after registration. If you did not receive the email, please contact the staff.") } - res := c.Redirect(redirect, http.StatusSeeOther) + res := c.Redirect(destination, http.StatusSeeOther) err = loginUser(c, user, &res) if err != nil { return c.ErrorResponse(http.StatusInternalServerError, err) @@ -114,12 +119,14 @@ func Login(c *RequestContext) ResponseData { } func Logout(c *RequestContext) ResponseData { - redir := c.Req.URL.Query().Get("redirect") - if redir == "" { - redir = "/" + redirect := c.Req.URL.Query().Get("redirect") + + destination := hmnurl.BuildHomepage() + if redirect != "" && urlIsLocal(redirect) { + destination = redirect } - res := c.Redirect(redir, http.StatusSeeOther) + res := c.Redirect(destination, http.StatusSeeOther) logoutUser(c, &res) return res } @@ -128,9 +135,21 @@ func RegisterNewUser(c *RequestContext) ResponseData { if c.CurrentUser != nil { c.Redirect(hmnurl.BuildUserSettings(c.CurrentUser.Username), http.StatusSeeOther) } + // TODO(asaf): Do something to prevent bot registration + + type RegisterPageData struct { + templates.BaseData + DestinationURL string + } + + tmpl := RegisterPageData{ + BaseData: getBaseData(c, "Register", nil), + DestinationURL: c.Req.URL.Query().Get("destination"), + } + var res ResponseData - res.MustWriteTemplate("auth_register.html", getBaseDataAutocrumb(c, "Register"), c.Perf) + res.MustWriteTemplate("auth_register.html", tmpl, c.Perf) return res } @@ -144,7 +163,7 @@ func RegisterNewUserSubmit(c *RequestContext) ResponseData { displayName := strings.TrimSpace(c.Req.Form.Get("displayname")) emailAddress := strings.TrimSpace(c.Req.Form.Get("email")) password := c.Req.Form.Get("password") - password2 := c.Req.Form.Get("password2") + destination := strings.TrimSpace(c.Req.Form.Get("destination")) if !UsernameRegex.Match([]byte(username)) { return c.RejectRequest("Invalid username") } @@ -154,9 +173,6 @@ func RegisterNewUserSubmit(c *RequestContext) ResponseData { if len(password) < 8 { return c.RejectRequest("Password too short") } - if password != password2 { - return c.RejectRequest("Password confirmation doesn't match password") - } c.Perf.StartBlock("SQL", "Check blacklist") // TODO(asaf): Check email against blacklist @@ -257,7 +273,14 @@ func RegisterNewUserSubmit(c *RequestContext) ResponseData { if mailName == "" { mailName = username } - err = email.SendRegistrationEmail(emailAddress, mailName, username, ott, c.Perf) + err = email.SendRegistrationEmail( + emailAddress, + mailName, + username, + ott, + destination, + c.Perf, + ) if err != nil { return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to send registration email")) } @@ -283,7 +306,7 @@ func RegisterNewUserSuccess(c *RequestContext) ResponseData { var res ResponseData res.MustWriteTemplate("auth_register_success.html", RegisterNewUserSuccessData{ - BaseData: getBaseDataAutocrumb(c, "Register"), + BaseData: getBaseData(c, "Register", nil), ContactUsUrl: hmnurl.BuildContactPage(), }, c.Perf) return res @@ -291,8 +314,9 @@ func RegisterNewUserSuccess(c *RequestContext) ResponseData { type EmailValidationData struct { templates.BaseData - Token string - Username string + Token string + Username string + DestinationURL string } func EmailConfirmation(c *RequestContext) ResponseData { @@ -329,9 +353,10 @@ func EmailConfirmation(c *RequestContext) ResponseData { var res ResponseData res.MustWriteTemplate("auth_email_validation.html", EmailValidationData{ - BaseData: getBaseDataAutocrumb(c, "Register"), - Token: token, - Username: username, + BaseData: getBaseData(c, "Register", nil), + Token: token, + Username: username, + DestinationURL: c.Req.URL.Query().Get("destination"), }, c.Perf) return res } @@ -342,6 +367,7 @@ func EmailConfirmationSubmit(c *RequestContext) ResponseData { token := c.Req.Form.Get("token") username := c.Req.Form.Get("username") password := c.Req.Form.Get("password") + destination := c.Req.Form.Get("destination") validationResult := validateUsernameAndToken(c, username, token, models.TokenTypeRegistration) if !validationResult.Match { @@ -354,7 +380,7 @@ func EmailConfirmationSubmit(c *RequestContext) ResponseData { return c.ErrorResponse(http.StatusInternalServerError, err) } else if !success { var res ResponseData - baseData := getBaseDataAutocrumb(c, "Register") + baseData := getBaseData(c, "Register", nil) // NOTE(asaf): We can report that the password is incorrect, because an attacker wouldn't have a valid token to begin with. baseData.AddImmediateNotice("failure", "Incorrect password. Please try again.") res.MustWriteTemplate("auth_email_validation.html", EmailValidationData{ @@ -401,7 +427,12 @@ func EmailConfirmationSubmit(c *RequestContext) ResponseData { } c.Perf.EndBlock() - res := c.Redirect(hmnurl.BuildHomepage(), http.StatusSeeOther) + redirect := hmnurl.BuildHomepage() + if destination != "" && urlIsLocal(destination) { + redirect = destination + } + + res := c.Redirect(redirect, http.StatusSeeOther) res.AddFutureNotice("success", "You've completed your registration successfully!") err = loginUser(c, validationResult.User, &res) if err != nil { @@ -432,7 +463,7 @@ func RequestPasswordReset(c *RequestContext) ResponseData { return c.Redirect(hmnurl.BuildHomepage(), http.StatusSeeOther) } var res ResponseData - res.MustWriteTemplate("auth_password_reset.html", getBaseDataAutocrumb(c, "Password Reset"), c.Perf) + res.MustWriteTemplate("auth_password_reset.html", getBaseData(c, "Password Reset", nil), c.Perf) return res } @@ -550,7 +581,7 @@ func PasswordResetSent(c *RequestContext) ResponseData { } var res ResponseData res.MustWriteTemplate("auth_password_reset_sent.html", PasswordResetSentData{ - BaseData: getBaseDataAutocrumb(c, "Password Reset"), + BaseData: getBaseData(c, "Password Reset", nil), ContactUsUrl: hmnurl.BuildContactPage(), }, c.Perf) return res @@ -584,7 +615,7 @@ func DoPasswordReset(c *RequestContext) ResponseData { } res.MustWriteTemplate("auth_do_password_reset.html", DoPasswordResetData{ - BaseData: getBaseDataAutocrumb(c, "Password Reset"), + BaseData: getBaseData(c, "Password Reset", nil), Username: username, Token: token, }, c.Perf) @@ -597,7 +628,6 @@ func DoPasswordResetSubmit(c *RequestContext) ResponseData { token := c.Req.Form.Get("token") username := c.Req.Form.Get("username") password := c.Req.Form.Get("password") - password2 := c.Req.Form.Get("password2") validationResult := validateUsernameAndToken(c, username, token, models.TokenTypePasswordReset) if !validationResult.Match { @@ -611,9 +641,6 @@ func DoPasswordResetSubmit(c *RequestContext) ResponseData { if len(password) < 8 { return c.RejectRequest("Password too short") } - if password != password2 { - return c.RejectRequest("Password confirmation doesn't match password") - } hashed := auth.HashPassword(password) @@ -806,3 +833,7 @@ func validateUsernameAndToken(c *RequestContext, username string, token string, return result } + +func urlIsLocal(url string) bool { + return strings.HasPrefix(url, config.Config.BaseUrl) +} diff --git a/src/website/user.go b/src/website/user.go index 228bfb8..981662b 100644 --- a/src/website/user.go +++ b/src/website/user.go @@ -405,10 +405,9 @@ func UserSettingsSave(c *RequestContext) ResponseData { // Update password oldPassword := form.Get("old_password") - newPassword := form.Get("new_password1") - newPasswordConfirmation := form.Get("new_password2") + newPassword := form.Get("new_password") if oldPassword != "" && newPassword != "" { - errorRes := updatePassword(c, tx, oldPassword, newPassword, newPasswordConfirmation) + errorRes := updatePassword(c, tx, oldPassword, newPassword) if errorRes != nil { return *errorRes } @@ -526,12 +525,7 @@ func UserProfileAdminNuke(c *RequestContext) ResponseData { return res } -func updatePassword(c *RequestContext, tx pgx.Tx, old, new, confirm string) *ResponseData { - if new != confirm { - res := c.RejectRequest("Your password and password confirmation did not match.") - return &res - } - +func updatePassword(c *RequestContext, tx pgx.Tx, old, new string) *ResponseData { oldHashedPassword, err := auth.ParsePasswordString(c.CurrentUser.Password) if err != nil { c.Logger.Warn().Err(err).Msg("failed to parse user's password string")