ghost 4.38.1 → 4.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.c8rc.json +1 -1
- package/Gruntfile.js +1 -1
- package/README.md +26 -18
- package/core/built/assets/{chunk.3.4906cf0b01d6d8e33374.js → chunk.3.6e2ed2d00856e12bd81a.js} +19 -19
- package/core/built/assets/ghost-dark-498ff8339a89bb68c3f78f59bee4146e.css +1 -0
- package/core/built/assets/ghost.min-77b93478f83b0def6ddc5a4f23ce963e.css +1 -0
- package/core/built/assets/{ghost.min-6386b02480494a69c3bfe66206754836.js → ghost.min-88c665c3ba304b4f220d08b8bcf9d246.js} +525 -538
- package/core/built/assets/icons/{event-changed-subscription.svg → event-subscriptions.svg} +0 -1
- package/core/built/assets/icons/member.svg +3 -0
- package/core/built/assets/{vendor.min-c814d3c4b3f543c4cd5ef3aacd0fc645.js → vendor.min-ed945ad80ea22f1d3ffeec6d5ae63aee.js} +2355 -1419
- package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
- package/core/frontend/apps/private-blogging/lib/views/private.hbs +9 -10
- package/core/frontend/public/ghost.css +205 -143
- package/core/frontend/public/ghost.min.css +1 -1
- package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +3 -1
- package/core/frontend/views/unsubscribe.hbs +28 -33
- package/core/frontend/web/middleware/error-handler.js +2 -2
- package/core/server/api/canary/authentication.js +7 -0
- package/core/server/api/canary/identities.js +0 -1
- package/core/server/api/canary/members.js +7 -1
- package/core/server/api/canary/tiers.js +3 -1
- package/core/server/api/canary/utils/serializers/input/pages.js +1 -1
- package/core/server/api/canary/utils/serializers/input/posts.js +1 -1
- package/core/server/api/canary/utils/serializers/input/tiers.js +17 -0
- package/core/server/api/canary/utils/serializers/output/actions.js +2 -2
- package/core/server/api/canary/utils/serializers/output/authentication.js +3 -3
- package/core/server/api/canary/utils/serializers/output/authors.js +3 -3
- package/core/server/api/canary/utils/serializers/output/email-posts.js +2 -2
- package/core/server/api/canary/utils/serializers/output/emails.js +3 -3
- package/core/server/api/canary/utils/serializers/output/images.js +2 -2
- package/core/server/api/canary/utils/serializers/output/integrations.js +5 -6
- package/core/server/api/canary/utils/serializers/output/labels.js +3 -3
- package/core/server/api/canary/utils/serializers/output/mappers/actions.js +7 -0
- package/core/server/api/canary/utils/serializers/output/mappers/emails.js +17 -0
- package/core/server/api/canary/utils/serializers/output/mappers/images.js +5 -0
- package/core/server/api/canary/utils/serializers/output/mappers/index.js +12 -0
- package/core/server/api/canary/utils/serializers/output/mappers/integrations.js +13 -0
- package/core/server/api/canary/utils/serializers/output/mappers/labels.js +4 -0
- package/core/server/api/canary/utils/serializers/output/mappers/pages.js +11 -0
- package/core/server/api/canary/utils/serializers/output/mappers/posts.js +101 -0
- package/core/server/api/canary/utils/serializers/output/mappers/settings.js +37 -0
- package/core/server/api/canary/utils/serializers/output/mappers/tags.js +11 -0
- package/core/server/api/canary/utils/serializers/output/mappers/users.js +12 -0
- package/core/server/api/canary/utils/serializers/output/members.js +2 -7
- package/core/server/api/canary/utils/serializers/output/pages.js +3 -3
- package/core/server/api/canary/utils/serializers/output/posts.js +3 -3
- package/core/server/api/canary/utils/serializers/output/preview.js +2 -2
- package/core/server/api/canary/utils/serializers/output/settings.js +2 -2
- package/core/server/api/canary/utils/serializers/output/tags.js +3 -3
- package/core/server/api/canary/utils/serializers/output/users.js +3 -3
- package/core/server/api/shared/serializers/handle.js +2 -2
- package/core/server/api/v2/utils/serializers/input/pages.js +1 -1
- package/core/server/api/v2/utils/serializers/input/posts.js +1 -1
- package/core/server/api/v3/utils/serializers/input/pages.js +1 -1
- package/core/server/api/v3/utils/serializers/input/posts.js +1 -1
- package/core/server/data/exporter/table-lists.js +1 -0
- package/core/server/data/importer/import-manager.js +152 -113
- package/core/server/data/migrations/versions/4.33/2022-01-14-11-51-add-default-free-tier.js +3 -0
- package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-free-products-visibility-column.js +66 -0
- package/core/server/data/migrations/versions/4.39/2022-03-07-10-57-update-products-visibility-column.js +36 -0
- package/core/server/data/migrations/versions/4.40/2022-03-07-14-37-add-members-cancel-events-table.js +8 -0
- package/core/server/data/migrations/versions/4.40/2022-03-15-06-40-add-offers-admin-integration-permission-roles.js +23 -0
- package/core/server/data/migrations/versions/4.40/2022-03-15-06-40-add-tiers-admin-integration-permission-roles.js +20 -0
- package/core/server/data/schema/default-settings/default-settings.json +2 -2
- package/core/server/data/schema/fixtures/fixtures.json +17 -160
- package/core/server/data/schema/schema.js +6 -0
- package/core/server/lib/image/image-size.js +12 -4
- package/core/server/models/base/plugins/generate-slug.js +13 -1
- package/core/server/models/base/plugins/raw-knex.js +1 -1
- package/core/server/models/member-cancel-event.js +28 -0
- package/core/server/models/post.js +16 -6
- package/core/server/models/user.js +1 -1
- package/core/server/services/auth/setup.js +29 -13
- package/core/server/services/mega/mega.js +4 -4
- package/core/server/services/mega/template.js +2 -1
- package/core/server/services/members/api.js +1 -0
- package/core/server/services/members/content-gating.js +1 -1
- package/core/server/services/members/middleware.js +1 -0
- package/core/server/services/posts/posts-service.js +1 -1
- package/core/server/services/themes/validate.js +3 -3
- package/core/server/services/url/UrlGenerator.js +1 -1
- package/core/server/services/webhooks/webhooks-service.js +2 -0
- package/core/server/views/maintenance.html +2 -2
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/api/app.js +0 -3
- package/core/server/web/api/canary/admin/middleware.js +2 -0
- package/core/server/web/parent/backend.js +2 -1
- package/core/server/web/shared/middleware/uncapitalise.js +2 -1
- package/core/shared/config/defaults.json +2 -2
- package/core/shared/config/overrides.json +7 -3
- package/core/shared/labs.js +8 -10
- package/core/shared/url-utils.js +4 -1
- package/package.json +37 -36
- package/yarn.lock +513 -329
- package/core/built/assets/ghost-dark-9f760f16230b8bc52e188d6ce28516b0.css +0 -1
- package/core/built/assets/ghost.min-f4c59dd57a2136df8b0a34f87c099034.css +0 -1
- package/core/built/assets/icons/event-started-subscription.svg +0 -6
- package/core/built/assets/icons/locked-email-back.svg +0 -1
- package/core/built/assets/icons/locked-email-front.svg +0 -1
- package/core/built/assets/icons/locked-email-lock.svg +0 -1
- package/core/built/assets/img/ghost-logo-de2acf283f53ba1fd1149928faeaaa74.png +0 -0
- package/core/server/api/canary/utils/serializers/output/utils/mapper.js +0 -213
- package/core/server/frontend/ghost.min.css +0 -1
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<path d="M9 6.12888V3.12891" stroke="#95A1AD" stroke-width="1.71429" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
|
-
<path d="M6 14.1288C6 15.6288 7.33999 16.1288 8.99997 16.1288C10.66 16.1288 11.9999 16.1288 11.9999 14.1288C11.9999 11.1289 6 11.1289 6 8.12889C6 6.12891 7.33999 6.12891 8.99997 6.12891C10.66 6.12891 11.9999 6.8889 11.9999 8.12889" stroke="#95A1AD" stroke-width="1.71429" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
-
<path d="M9 16.1289V19.1289" stroke="#95A1AD" stroke-width="1.71429" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
-
<path d="M14 18.1104L15.8232 19.9336C15.9209 20.0312 16.0791 20.0312 16.1768 19.9336L20.5 15.6104" stroke="#30CF43" stroke-width="1.44" stroke-linecap="round"/>
|
|
6
|
-
</svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg width="122" height="125" viewBox="0 0 122 125" xmlns="http://www.w3.org/2000/svg"><title>envelope-back</title><path d="M3.953 39.164L54.375 2.172c3.947-2.896 9.303-2.896 13.25 0l50.422 36.992c2.484 1.823 3.953 4.728 3.953 7.82v68.336c0 5.346-4.312 9.68-9.632 9.68H9.632C4.312 125 0 120.666 0 115.32V46.983c0-3.09 1.469-5.996 3.953-7.819z" fill="#C5D2D9" fill-rule="evenodd"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg width="122" height="77" viewBox="0 0 122 77" xmlns="http://www.w3.org/2000/svg"><title>envelope-front</title><g stroke="#C5D2D9" fill="none" fill-rule="evenodd"><path d="M.5 3.023v64.28c0 2.519 1.002 4.802 2.642 6.463 1.634 1.655 3.9 2.693 6.438 2.734h102.431c1.888-.005 3.641-.592 5.093-1.593l-5.64-3.368C44.768 31.699 9.41 10.472 5.388 7.859 3.085 6.365 1.463 4.75.5 3.024z" fill="#F2F4F7"/><path d="M121.491 3.111c-.97 1.746-2.609 3.38-4.94 4.89-3.73 2.418-34.423 20.824-92.079 55.216L4.895 74.89c1.428.99 3.162 1.578 5.127 1.61l102.41-.001c2.325-.006 4.447-.894 6.052-2.35 1.616-1.466 2.71-3.508 2.962-5.806l.045-65.233z" fill="#F8FAFC"/></g></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"><path d="M8.75 16.25h22.5c1.667 0 2.5.833 2.5 2.5v17.5c0 1.667-.833 2.5-2.5 2.5H8.75c-1.667 0-2.5-.833-2.5-2.5v-17.5c0-1.667.833-2.5 2.5-2.5zm2.5 0V10c0-3.368 1.458-5.894 4.375-7.578 2.917-1.684 5.833-1.684 8.75 0S28.75 6.632 28.75 10v6.25M20 25v5" stroke="#3EB0EF" stroke-width="1.5" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
Binary file
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
const _ = require('lodash');
|
|
2
|
-
const utils = require('../../../index');
|
|
3
|
-
const url = require('./url');
|
|
4
|
-
const date = require('./date');
|
|
5
|
-
const gating = require('./post-gating');
|
|
6
|
-
const clean = require('./clean');
|
|
7
|
-
const extraAttrs = require('./extra-attrs');
|
|
8
|
-
const postsMetaSchema = require('../../../../../../data/schema').tables.posts_meta;
|
|
9
|
-
const mega = require('../../../../../../services/mega');
|
|
10
|
-
const labsService = require('../../../../../../../shared/labs');
|
|
11
|
-
|
|
12
|
-
const getPostServiceInstance = require('../../../../../../services/posts/posts-service');
|
|
13
|
-
const postsService = getPostServiceInstance('canary');
|
|
14
|
-
|
|
15
|
-
const mapUser = (model, frame) => {
|
|
16
|
-
const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
|
|
17
|
-
|
|
18
|
-
url.forUser(model.id, jsonModel, frame.options);
|
|
19
|
-
|
|
20
|
-
clean.author(jsonModel, frame);
|
|
21
|
-
|
|
22
|
-
return jsonModel;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const mapTag = (model, frame) => {
|
|
26
|
-
const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
|
|
27
|
-
|
|
28
|
-
url.forTag(model.id, jsonModel, frame.options);
|
|
29
|
-
clean.tag(jsonModel, frame);
|
|
30
|
-
|
|
31
|
-
return jsonModel;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const mapPost = async (model, frame, options = {}) => {
|
|
35
|
-
const {tiers: tiersData} = options || {};
|
|
36
|
-
const extendedOptions = Object.assign(_.cloneDeep(frame.options), {
|
|
37
|
-
extraProperties: ['canonical_url']
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const jsonModel = model.toJSON(extendedOptions);
|
|
41
|
-
|
|
42
|
-
url.forPost(model.id, jsonModel, frame);
|
|
43
|
-
|
|
44
|
-
extraAttrs.forPost(frame, model, jsonModel);
|
|
45
|
-
|
|
46
|
-
// Attach tiers to custom nql visibility filter
|
|
47
|
-
if (labsService.isSet('multipleProducts')
|
|
48
|
-
&& jsonModel.visibility
|
|
49
|
-
) {
|
|
50
|
-
if (['members', 'public'].includes(jsonModel.visibility) && jsonModel.tiers) {
|
|
51
|
-
jsonModel.tiers = tiersData || [];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (jsonModel.visibility === 'paid' && jsonModel.tiers) {
|
|
55
|
-
jsonModel.tiers = tiersData ? tiersData.filter(t => t.type === 'paid') : [];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!['members', 'public', 'paid', 'tiers'].includes(jsonModel.visibility)) {
|
|
59
|
-
const tiers = await postsService.getProductsFromVisibilityFilter(jsonModel.visibility);
|
|
60
|
-
|
|
61
|
-
jsonModel.visibility = 'tiers';
|
|
62
|
-
jsonModel.tiers = tiers;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (utils.isContentAPI(frame)) {
|
|
67
|
-
// Content api v2 still expects page prop
|
|
68
|
-
if (jsonModel.type === 'page') {
|
|
69
|
-
jsonModel.page = true;
|
|
70
|
-
}
|
|
71
|
-
date.forPost(jsonModel);
|
|
72
|
-
gating.forPost(jsonModel, frame);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Transforms post/page metadata to flat structure
|
|
76
|
-
let metaAttrs = _.keys(_.omit(postsMetaSchema, ['id', 'post_id']));
|
|
77
|
-
_(metaAttrs).filter((k) => {
|
|
78
|
-
return (!frame.options.columns || (frame.options.columns && frame.options.columns.includes(k)));
|
|
79
|
-
}).each((attr) => {
|
|
80
|
-
// NOTE: the default of `email_only` is `false` which is why we default to `false` instead of `null`
|
|
81
|
-
// The undefined value is possible because `posts_meta` table is lazily created only one of the
|
|
82
|
-
// values is assigned.
|
|
83
|
-
const defaultValue = (attr === 'email_only') ? false : null;
|
|
84
|
-
jsonModel[attr] = _.get(jsonModel.posts_meta, attr) || defaultValue;
|
|
85
|
-
});
|
|
86
|
-
delete jsonModel.posts_meta;
|
|
87
|
-
|
|
88
|
-
clean.post(jsonModel, frame);
|
|
89
|
-
|
|
90
|
-
if (frame.options && frame.options.withRelated) {
|
|
91
|
-
frame.options.withRelated.forEach((relation) => {
|
|
92
|
-
// @NOTE: this block also decorates primary_tag/primary_author objects as they
|
|
93
|
-
// are being passed by reference in tags/authors. Might be refactored into more explicit call
|
|
94
|
-
// in the future, but is good enough for current use-case
|
|
95
|
-
if (relation === 'tags' && jsonModel.tags) {
|
|
96
|
-
jsonModel.tags = jsonModel.tags.map(tag => mapTag(tag, frame));
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (relation === 'authors' && jsonModel.authors) {
|
|
100
|
-
jsonModel.authors = jsonModel.authors.map(author => mapUser(author, frame));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (relation === 'email' && jsonModel.email) {
|
|
104
|
-
jsonModel.email = mapEmail(jsonModel.email, frame);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (relation === 'email' && _.isEmpty(jsonModel.email)) {
|
|
108
|
-
jsonModel.email = null;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return jsonModel;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const mapPage = async (model, frame, options) => {
|
|
117
|
-
const jsonModel = await mapPost(model, frame, options);
|
|
118
|
-
|
|
119
|
-
delete jsonModel.email_subject;
|
|
120
|
-
delete jsonModel.email_recipient_filter;
|
|
121
|
-
delete jsonModel.email_only;
|
|
122
|
-
|
|
123
|
-
return jsonModel;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const mapSettings = (attrs, frame) => {
|
|
127
|
-
url.forSettings(attrs);
|
|
128
|
-
extraAttrs.forSettings(attrs, frame);
|
|
129
|
-
|
|
130
|
-
// NOTE: The cleanup of deprecated ghost_head/ghost_foot has to happen here
|
|
131
|
-
// because codeinjection_head/codeinjection_foot are assigned on a previous
|
|
132
|
-
// `forSettings` step. This logic can be rewritten once we get rid of deprecated
|
|
133
|
-
// fields completely.
|
|
134
|
-
if (_.isArray(attrs)) {
|
|
135
|
-
const keysToFilter = ['ghost_head', 'ghost_foot'];
|
|
136
|
-
|
|
137
|
-
// NOTE: to support edits of deprecated 'slack' setting artificial 'slack_url' and 'slack_username'
|
|
138
|
-
// were added to the request body in the input serializer. These should not be returned in response
|
|
139
|
-
// body unless directly requested
|
|
140
|
-
if (frame.original.body && frame.original.body.settings) {
|
|
141
|
-
const requestedEditSlackUrl = frame.original.body.settings.find(s => s.key === 'slack_url');
|
|
142
|
-
const requestedEditSlackUsername = frame.original.body.settings.find(s => s.key === 'slack_username');
|
|
143
|
-
|
|
144
|
-
if (!requestedEditSlackUrl) {
|
|
145
|
-
keysToFilter.push('slack_url');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (!requestedEditSlackUsername) {
|
|
149
|
-
keysToFilter.push('slack_username');
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
attrs = _.filter(attrs, attr => !(keysToFilter.includes(attr.key)));
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return attrs;
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
const mapIntegration = (model, frame) => {
|
|
160
|
-
const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
|
|
161
|
-
|
|
162
|
-
if (jsonModel.api_keys) {
|
|
163
|
-
jsonModel.api_keys.forEach((key) => {
|
|
164
|
-
if (key.type === 'admin') {
|
|
165
|
-
key.secret = `${key.id}:${key.secret}`;
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return jsonModel;
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
const mapImage = (path) => {
|
|
174
|
-
return url.forImage(path);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const mapAction = (model, frame) => {
|
|
178
|
-
const attrs = model.toJSON(frame.options);
|
|
179
|
-
clean.action(attrs);
|
|
180
|
-
return attrs;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
const mapLabel = (model, frame) => {
|
|
184
|
-
const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
|
|
185
|
-
return jsonModel;
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
const mapEmail = (model, frame) => {
|
|
189
|
-
const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
|
|
190
|
-
|
|
191
|
-
// Ensure we're not outputting unwanted replacement strings when viewing email contents
|
|
192
|
-
// TODO: extract this to a utility, it's duplicated in the email-preview API controller
|
|
193
|
-
const replacements = mega.postEmailSerializer.parseReplacements(jsonModel);
|
|
194
|
-
replacements.forEach((replacement) => {
|
|
195
|
-
jsonModel[replacement.format] = jsonModel[replacement.format].replace(
|
|
196
|
-
replacement.match,
|
|
197
|
-
replacement.fallback || ''
|
|
198
|
-
);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
return jsonModel;
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
module.exports.mapPost = mapPost;
|
|
205
|
-
module.exports.mapPage = mapPage;
|
|
206
|
-
module.exports.mapUser = mapUser;
|
|
207
|
-
module.exports.mapTag = mapTag;
|
|
208
|
-
module.exports.mapLabel = mapLabel;
|
|
209
|
-
module.exports.mapIntegration = mapIntegration;
|
|
210
|
-
module.exports.mapSettings = mapSettings;
|
|
211
|
-
module.exports.mapImage = mapImage;
|
|
212
|
-
module.exports.mapAction = mapAction;
|
|
213
|
-
module.exports.mapEmail = mapEmail;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-family:sans-serif}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.darkgrey{color:#343f44}.midgrey{color:#738a94}.lightgrey{color:#e5eff5}.blue{color:#3eb0ef}.red{color:#f05230}.orange{color:#fecd35}.green{color:#a4d037}.darkgrey-hover:hover{color:#343f44}.midgrey-hover:hover{color:#738a94}.lightgrey-hover:hover{color:#e5eff5}.blue-hover:hover{color:#3eb0ef}.red-hover:hover{color:#f05230}.orange-hover:hover{color:#fecd35}.green-hover:hover{color:#a4d037}*,:after,:before{box-sizing:border-box}html{-webkit-tap-highlight-color:rgba(0,0,0,0);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:62.5%;letter-spacing:.2px;line-height:1.65;overflow:hidden}body,html{height:100%;width:100%}body{color:#343f44;font-size:1.4rem;overflow:auto;overflow-x:hidden}.gh-view{-ms-flex-positive:1;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;flex-grow:1}h1,h2{text-rendering:optimizeLegibility;color:#343f44;font-size:2.9rem;line-height:1.15em;margin:0 0 .3em;text-indent:-1px}@media (max-width:500px){h1{font-size:2.4rem}}.gh-input{-webkit-appearance:none;border:1px solid #d6e3eb;border-radius:4px;color:#4b5b62;display:block;font-size:1.6rem;font-weight:300;height:40px;line-height:1em;padding:10px 12px;transition:border-color .15s linear;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;width:100%}.gh-input:focus{border-color:#b4cbda;outline:0}.gh-btn{fill:#829aa8;-webkit-font-smoothing:subpixel-antialiased;border:1px solid #d6e3eb;border-radius:5px;color:#829aa8;display:inline-block;outline:none;text-decoration:none!important;text-shadow:0 1px 0 #fff;transition:all .2s ease;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.gh-btn span{border-radius:4px;display:block;font-size:1.3rem;font-weight:400;height:33px;letter-spacing:.2px;line-height:33px;padding:0 12px;text-align:center}.gh-btn:hover{border-color:#b4cbda}.gh-btn-hover-blue:hover{border-color:#3eb0ef;color:#3eb0ef}.gh-btn-blue{fill:#fff;background:linear-gradient(#3da1d6,#2288bf);border:0;box-shadow:0 1px 0 rgba(0,0,0,.12);color:#fff;padding:1px;text-shadow:0 -1px 0 rgba(0,0,0,.1);transition:none!important}.gh-btn-blue span{background:linear-gradient(#4ab6f0,#2fa5e4 60%,#2fa5e4 90%,#38a9e5);box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1)}.gh-btn-blue:active,.gh-btn-blue:focus{background:#1e78a9}.gh-btn-blue:active span,.gh-btn-blue:focus span{background:#29a0e0;box-shadow:none}.gh-btn-block{display:block;width:100%}.gh-input-icon{display:block;position:relative}.gh-input-icon svg{fill:color(var(--midgrey) l(15%));height:14px;left:10px;position:absolute;top:50%;transform:translateY(-7px);width:auto;z-index:2}.gh-input-icon input{padding-left:35px}.gh-app{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;height:100%;overflow:hidden}.gh-viewport{max-height:100%;overflow:hidden}.gh-main,.gh-viewport{-ms-flex-positive:1;display:-ms-flexbox;display:flex;flex-grow:1}.gh-main{background:#fff;overflow-y:auto;position:relative}.gh-flow{-ms-flex-positive:1;-ms-flex-direction:column;flex-direction:column;flex-grow:1;min-height:100%;overflow-y:auto}.gh-flow,.gh-flow-head{display:-ms-flexbox;display:flex}.gh-flow-head{-ms-flex-negative:0;-ms-flex-pack:justify;flex-shrink:0;justify-content:space-between;padding-bottom:20px;padding-top:4vh}.gh-flow-content-wrap{-ms-flex-positive:1;-ms-flex-negative:0;-ms-flex-pack:center;flex-grow:1;flex-shrink:0;justify-content:center;margin:0 5%;padding-bottom:8vh}.gh-flow-back,.gh-flow-content-wrap{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex}.gh-flow-back{border:1px solid transparent;border-radius:4px;color:#7d878a;font-weight:100;left:0;margin:0 0 0 3%;padding:2px 9px 2px 5px;position:absolute;top:0;transition:all .3s ease}.gh-flow-back svg{height:12px;line-height:14px;margin-right:4px}.gh-flow-back svg path{stroke:#7d878a;stroke-width:1.2px}.gh-flow-back:hover{border:1px solid #dae1e3}.gh-flow-back-plain{-ms-flex-align:center;align-items:center;color:#7d878a;display:-ms-flexbox;display:flex;font-weight:300;left:0;margin:0 0 0 3%;padding:2px 9px 2px 5px;position:absolute;text-decoration:none;top:0;transition:all .3s ease}.gh-flow-back-plain svg{height:12px;line-height:14px;margin-right:4px}.gh-flow-back-plain svg path{stroke:#7d878a;stroke-width:1.2px}.gh-flow-back-plain:hover{color:#15212a}.gh-flow-nav{-ms-flex:1;flex:1;position:relative}.gh-flow-content{color:#738a94;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;font-size:1.9rem;font-weight:100;line-height:1.5em;max-width:700px;text-align:center;width:100%}.gh-flow-content .gh-input-icon input{padding-left:35px}.gh-flow-content-unsubscribe{font-weight:300}@media (max-width:500px){.gh-flow-head-unsubscribe{padding-top:2.8vh}.gh-flow-content{font-size:4vw}.gh-flow-content-unsubscribe{font-size:1.8rem;line-height:1.6em}}.gh-flow-content header{margin:0 auto;max-width:520px}.gh-flow-content h1{font-size:4.2rem;font-weight:100}@media (max-width:600px){.gh-flow-content h1{font-size:7vw}}.gh-flow-content .gh-btn{display:block;margin:20px auto 0;max-width:400px}.gh-flow-content .form-group{margin-bottom:2.5rem}.gh-flow-content input{border:1px solid #dae1e3;font-size:1.6rem;font-weight:100;line-height:1.4em;padding:10px}.gh-flow-em{font-weight:500}.gh-signin{background:#f8fbfd;border:1px solid #dae1e3;border-radius:5px;margin:30px auto;max-width:400px;padding:40px;position:relative;text-align:left;width:100%}.gh-signin .form-group{margin-bottom:1.5rem}.gh-signin .gh-btn{margin:0}.error-content{flex-grow:1;justify-content:center;padding:8vw;user-select:text}.error-content,.error-details{align-items:center;display:flex}.error-details{margin-bottom:4rem}.error-ghost{height:115px;margin:15px}@media (max-width:630px){.error-ghost{display:none}}.error-code{color:#c5d2d9;font-size:10vw;font-weight:600;letter-spacing:-.4vw;line-height:.9em;margin:0}.error-description{border:none;color:#54666d;font-size:2.3rem;font-weight:300;line-height:1.3em;margin:0;padding:0}.error-message{align-items:center;display:flex;flex-direction:column;margin:15px}.error-message a{font-size:1.4rem;line-height:1;margin:8px 0}.error-link{background-color:transparent;color:#5ba4e5;text-decoration:none;transition:background .3s,color .3s}.error-stack{background-color:hsla(0,0%,100%,.3);margin:1rem auto;max-width:800px;padding:2rem}.error-stack-list{list-style-type:none;margin:0;padding:0}.error-stack-list li{display:block}.error-stack-list li:before{color:#bbb;content:"\21AA";display:inline-block;font-size:1.2rem;margin-right:.5rem}.error-stack-function{font-weight:700}
|