From 94a0b4d92f494825468fdcb6c936f9eb8dc97d60 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 21:43:15 +0300 Subject: [PATCH 1/9] security(core): scope auth tokens with explicit CRUD permissions and server-assigned login Token scope was expressed as an app list and an endpoint regex, which verify_token compared against the request path and, when present, the request's app_id. That is a data-scoping control: it does not describe what the resolved member may do, and rights.js did not carry it past token resolution, so a token authorized whatever its owner could. Login capability was likewise inferred from the token's purpose string, which is supplied by the caller at creation. Tokens now carry explicit permissions and an explicit login capability. - token_permission stores a member.permission-shaped grant on the token. rights.js intersects it with the owner's own permissions as soon as the member is loaded, before any validator authorizes anything, so every existing feature check becomes scope-aware without being touched. The intersected member does not carry global_admin. The intersection is recomputed per request, so it follows the owner's current permissions. - A grant is bounded by the credential that creates it, not by the owner. Because the intersection has already happened, params.member is that credential's authority, and isPermissionSubset refuses anything wider. An "all" grant may only be passed on by a holder of "all", since it covers features that do not exist yet. - can_login is a server-assigned property of the token. It is set where the server establishes or propagates a session (setLoggedInVariables, the renderer, the ban-warning mail), and by /i/token/create only when the creating credential holds it and the child is not narrowed. purpose returns to being a description. - Token creation, listing and deletion require a full-permission credential, since each of them hands out, exposes or revokes the owner's credentials. Tokens created before this change are unaffected: with no token_permission they are neither intersected nor re-scoped, the endpoint regex still applies to them, and /login/token still accepts the unrestricted login-purpose tokens it accepted previously. The token manager grants app, CRUD and feature permissions using the same permission grid and helpers as user management, instead of endpoint regexes. Covered by unit tests for the permission algebra and the token record, and by API tests for the create, login, list and delete boundaries. Reported through the security bug bounty program (received 2026-08-18). Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 1 + api/parts/mgmt/mail.js | 2 + api/utils/authorizer.js | 77 ++-- api/utils/requestProcessor.js | 100 ++++- api/utils/rights.js | 419 +++++++++++++++++- frontend/express/libs/members.js | 35 +- .../javascripts/countly.views.js | 169 +++++-- .../templates/token-manager-drawer.html | 78 ++-- .../templates/token-manager.html | 6 +- .../countly/countly.token.manager.js | 34 +- .../dashboard/dashboard.properties | 19 + plugins/dashboards/api/api.js | 2 + test/2.api/16.token.manager.js | 245 ++++++++++ .../api.utils.authorizer.tokenFields.js | 179 ++++++++ .../api.utils.rights.tokenPermissions.js | 159 +++++++ 15 files changed, 1401 insertions(+), 124 deletions(-) create mode 100644 test/unit-tests/api.utils.authorizer.tokenFields.js create mode 100644 test/unit-tests/api.utils.rights.tokenPermissions.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 37ace8a79ae..cb4b7543eaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Enterprise Fixes: - [data-manager] Fixed editing an event whose key contains `&` creating undeletable duplicate rows in the events table Security Fixes: +- [core] Auth tokens are now granted explicit create/read/update/delete permissions per app and feature, enforced on every request as the intersection of the token's permissions and its owner's. A token can only be granted permissions that the credential creating it already holds. Permission to sign in to the dashboard is a separate property of the token, assigned by the server, instead of being inferred from the token's purpose. Token creation, listing and deletion require a full-permission credential. Tokens created before this change keep working under the previous app and endpoint restrictions - [hooks] Internal event hooks are now scoped to the apps the hook belongs to: app creation is a global-admin-only event, and remote-config, cohort, alert and hook-chaining events are only delivered when the event's app is one the hook is scoped to - [compliance-hub] The consents table now returns a fixed set of fields; a projection supplied on the request is no longer used to widen the response beyond the consent columns - [dashboards] Widgets are no longer copied when the copying user has no access to the apps they reference, and widget app ids are validated on widget create and update diff --git a/api/parts/mgmt/mail.js b/api/parts/mgmt/mail.js index 8f262213183..7a16cf64acf 100644 --- a/api/parts/mgmt/mail.js +++ b/api/parts/mgmt/mail.js @@ -269,6 +269,8 @@ mail.sendTimeBanWarning = function(member, db) { multi: false, owner: member._id, app: "", + //the mailed link logs the member back in, so this token carries login permission + can_login: true, callback: function(err, token) { mail.lookup(function(err2, host) { localize.getProperties(member.lang, function(err3, properties) { diff --git a/api/utils/authorizer.js b/api/utils/authorizer.js index d19ff519a0d..f526459d245 100644 --- a/api/utils/authorizer.js +++ b/api/utils/authorizer.js @@ -19,7 +19,9 @@ const log = require('./log.js')('core:authorizer'); * @param {string} options.token - token to store, if not provided, will be generated * @param {string} options.owner - id of the user who created this token * @param {string} options.app - list of the apps for which token was created -* @param {string} options.endpoint - regexp of endpoint(any string - is used as substring,to mach exact ^{yourpath}$) +* @param {string} options.endpoint - regexp of endpoint(any string - is used as substring,to mach exact ^{yourpath}$). Deprecated as an authorization mechanism, kept for tokens created before the permission model. +* @param {object} [options.token_permission] - CRUD permissions granted to this token, in the same shape as member.permission ({_:{a,u}, c/r/u/d:{appId:{all, allowed}}}). When set, the token authorizes only the intersection of this object and its owner's own permissions. When omitted, the token inherits the owner's full permissions. +* @param {boolean} [options.can_login=false] - if true, the token may be redeemed for a dashboard session at /login/token. SERVER-ASSIGNED ONLY - see the note below. * @param {string} options.tryReuse - if true - tries to find not expired token with same parameters. If not founds cretes new token. If found - updates token expiration time to new one and returns token. * @param {boolean} [options.temporary=false] - If logged in with temporary token. Doesn't kill other sessions on logout. * @param {function} options.callback - function called when saving was completed or errored, providing error object as first param and token string as second @@ -34,6 +36,13 @@ authorizer.save = function(options) { options.purpose = options.purpose || ""; options.temporary = options.temporary || false; //If logged in with temporary token. Doesn't kill other sessions on logout + // Login capability is a property of the token, never of its purpose string. It is set only + // where the server itself establishes or propagates a session (setLoggedInVariables, the + // renderer, the ban-warning mail, OIDC login), and by /i/token/create only when the creating + // credential already holds it. Defaulting to false here means any caller that does not ask + // for it explicitly produces a token that cannot be redeemed at /login/token. + options.can_login = options.can_login === true; + if (options.endpoint !== "" && !Array.isArray(options.endpoint)) { options.endpoint = [options.endpoint]; } @@ -53,8 +62,40 @@ authorizer.save = function(options) { } else if (member) { authorizer.clearExpiredTokens(options); + /** + * Build the token document to store. token_permission is only written when the + * token is actually scoped, so an unscoped token stays absent-means-unrestricted. + * @returns {object} document to insert into auth_tokens + */ + var buildTokenDoc = function() { + var doc = { + _id: options.token, + ttl: options.ttl, + ends: options.ttl + Math.round(Date.now() / 1000), + multi: options.multi, + owner: options.owner, + app: options.app, + endpoint: options.endpoint, + purpose: options.purpose, + temporary: options.temporary, + can_login: options.can_login + }; + if (options.token_permission) { + doc.token_permission = options.token_permission; + } + return doc; + }; if (options.tryReuse === true) { - var rules = {"multi": options.multi, "endpoint": options.endpoint, "app": options.app, "owner": options.owner, "purpose": options.purpose}; + var rules = {"multi": options.multi, "endpoint": options.endpoint, "app": options.app, "owner": options.owner, "purpose": options.purpose, "can_login": options.can_login}; + // Never reuse a token that grants something different from what is being asked + // for: an identical-looking token with a wider (or narrower) permission set is a + // different credential. + if (options.token_permission) { + rules.token_permission = options.token_permission; + } + else { + rules.token_permission = {$exists: false}; + } if (options.purpose === "LoggedInAuth") { //Login token, allow switching from expiring to not expiring(and other way around) //If there is changes to session expiration - this will allow to treat those tokens as same token. @@ -78,17 +119,7 @@ authorizer.save = function(options) { options.callback(err_token, token.value._id); } else { - options.db.collection("auth_tokens").insert({ - _id: options.token, - ttl: options.ttl, - ends: options.ttl + Math.round(Date.now() / 1000), - multi: options.multi, - owner: options.owner, - app: options.app, - endpoint: options.endpoint, - purpose: options.purpose, - temporary: options.temporary - }, function(err1) { + options.db.collection("auth_tokens").insert(buildTokenDoc(), function(err1) { if (typeof options.callback === "function") { options.callback(err1, options.token); } @@ -97,17 +128,7 @@ authorizer.save = function(options) { }); } else { - options.db.collection("auth_tokens").insert({ - _id: options.token, - ttl: options.ttl, - ends: options.ttl + Math.round(Date.now() / 1000), - multi: options.multi, - owner: options.owner, - app: options.app, - endpoint: options.endpoint, - purpose: options.purpose, - temporary: options.temporary - }, function(err1) { + options.db.collection("auth_tokens").insert(buildTokenDoc(), function(err1) { if (typeof options.callback === "function") { options.callback(err1, options.token); } @@ -249,7 +270,13 @@ var verify_token = function(options, return_owner, return_data) { if (Array.isArray(res.endpoint) && res.endpoint.length === 0) { res.endpoint = ""; } - if (res.endpoint && res.endpoint !== "") { + // The endpoint regex is the pre-permission-model scoping mechanism. It only ever + // constrained which paths a token could call, never what the resolved member was + // allowed to do, so it is not an authorization boundary. Tokens issued under the + // permission model carry token_permission instead, which rights.js intersects with + // the owner's own permissions on every request. Legacy tokens (no token_permission) + // keep being matched exactly as before, so existing integrations are unaffected. + if (!res.token_permission && res.endpoint && res.endpoint !== "") { //keep backwards compability if (!Array.isArray(res.endpoint)) { res.endpoint = [res.endpoint]; diff --git a/api/utils/requestProcessor.js b/api/utils/requestProcessor.js index 3287fe1c7dc..4d24d76d6fc 100644 --- a/api/utils/requestProcessor.js +++ b/api/utils/requestProcessor.js @@ -12,7 +12,7 @@ const Promise = require('bluebird'); const url = require('url'); const common = require('./common.js'); const countlyCommon = require('../lib/countly.common.js'); -const { validateAppAdmin, validateUser, validateRead, validateUserForRead, validateUserForWrite, validateGlobalAdmin, dbUserHasAccessToCollection, validateUpdate, validateDelete, validateCreate, getBaseAppFilter, getAdminApps, getUserAppsForFeaturePermission } = require('./rights.js'); +const { validateAppAdmin, validateUser, validateRead, validateUserForRead, validateUserForWrite, validateGlobalAdmin, dbUserHasAccessToCollection, validateUpdate, validateDelete, validateCreate, getBaseAppFilter, getAdminApps, getUserAppsForFeaturePermission, isPermissionSubset, getPermissionApps, isScopedCredential } = require('./rights.js'); const authorize = require('./authorizer.js'); const taskmanager = require('./taskmanager.js'); const plugins = require('../../plugins/pluginManager.js'); @@ -393,6 +393,8 @@ const processRequest = (params) => { owner: params.member._id, ttl: 300, purpose: "LoginAuthToken", + //the headless renderer authenticates by redeeming this at /login/token + can_login: true, callback: function(err2, token) { if (err2) { common.returnMessage(params, 400, 'Error creating token: ' + err2); @@ -2518,6 +2520,12 @@ const processRequest = (params) => { */ case 'delete': validateUser(() => { + //revoking the owner's other credentials is credential management, not + //something a token narrowed to a subset of the owner's access may do + if (isScopedCredential(params)) { + common.returnMessage(params, 403, "A restricted token cannot delete tokens"); + return; + } if (params.qstring.tokenid) { common.db.collection("auth_tokens").remove({ "_id": params.qstring.tokenid, @@ -2564,7 +2572,80 @@ const processRequest = (params) => { */ case 'create': validateUser(params, () => { - let ttl, multi, endpoint, purpose, apps; + let ttl, multi, endpoint, purpose, apps, tokenPermission; + + // The credential doing the creating, not its owner, is the ceiling for what + // may be granted. params.member is already that ceiling: rights.js bounds the + // member by the authenticating token's permissions before any handler runs, so + // for an api_key it is the full member, and for a scoped token it is exactly + // that token's authority. A token therefore cannot mint a child that reaches + // an app or feature it cannot reach itself, even though their owner can. + const creatorToken = params.token_data; + /** + * Whether a legacy app/endpoint scope value actually restricts anything. + * @param {string|Array} scope - the app or endpoint field of a token + * @returns {boolean} true if the token is restricted by it + */ + const isScopeRestricted = function(scope) { + return !(scope === undefined || scope === null || scope === "" || (Array.isArray(scope) && scope.length === 0)); + }; + // Tokens created before the permission model carry an app/endpoint regex scope + // instead of permissions. That scope is not carried into params.member, so + // there is nothing to bound such a token's grants by - refuse rather than + // issue a child that could be wider than its parent. + const creatorIsLegacyRestricted = !!creatorToken && !creatorToken.token_permission && (isScopeRestricted(creatorToken.app) || isScopeRestricted(creatorToken.endpoint)); + if (creatorIsLegacyRestricted) { + common.returnMessage(params, 403, "A restricted token cannot create tokens"); + return; + } + + if (params.qstring.permission && params.qstring.permission !== "") { + if (typeof params.qstring.permission === "string") { + try { + tokenPermission = JSON.parse(params.qstring.permission); + } + catch (ex) { + common.returnMessage(params, 400, "Invalid permission object"); + return; + } + } + else { + tokenPermission = params.qstring.permission; + } + if (typeof tokenPermission !== "object" || Array.isArray(tokenPermission)) { + common.returnMessage(params, 400, "Invalid permission object"); + return; + } + // The endpoint regex is not an authorization boundary and is ignored for + // permission-scoped tokens. Reject rather than store an inert restriction + // that would read as if it were enforced. + if (params.qstring.endpoint || params.qstring.endpointquery) { + common.returnMessage(params, 400, "Endpoint restrictions cannot be combined with permissions"); + return; + } + if (!isPermissionSubset(tokenPermission, params.member)) { + common.returnMessage(params, 403, "Token permissions must be a subset of the creating credential's permissions"); + return; + } + } + + // Login is a capability of the token, never of its purpose string, and it is + // only ever passed on by a credential that holds it, to a child that is not + // narrowed. That makes a scoped token unable to produce a session, which is + // what the purpose allowlist used to (and could not) guarantee. + const requestedLogin = params.qstring.can_login === true || params.qstring.can_login === "true" || params.qstring.can_login === "1"; + let canLogin = false; + if (requestedLogin) { + //a token created before this model that carries no restriction at all is a + //full-permission credential, and keeps the login authority it has today + const creatorHasLogin = !creatorToken || creatorToken.can_login === true || (typeof creatorToken.can_login === "undefined" && !creatorToken.token_permission); + if (!creatorHasLogin || tokenPermission) { + common.returnMessage(params, 403, "The creating credential cannot grant login permission"); + return; + } + canLogin = true; + } + if (params.qstring.ttl) { ttl = parseInt(params.qstring.ttl); } @@ -2579,6 +2660,11 @@ const processRequest = (params) => { if (params.qstring.apps) { apps = params.qstring.apps.split(','); } + //keep the app list in step with the granted permissions, so the token list + //shows what the token reaches and the app check stays a useful early filter + if (tokenPermission && !params.qstring.apps) { + apps = getPermissionApps(tokenPermission); + } if (params.qstring.endpointquery && params.qstring.endpointquery !== "") { try { @@ -2608,6 +2694,8 @@ const processRequest = (params) => { app: apps, endpoint: endpoint, purpose: purpose, + token_permission: tokenPermission, + can_login: canLogin, callback: (err, token) => { if (err) { common.returnMessage(params, 404, err); @@ -2697,6 +2785,14 @@ const processRequest = (params) => { */ case 'list': validateUser(params, function() { + // Every document here includes its _id, which is the token itself. Listing + // them from a scoped token would hand it the owner's other credentials - + // including the unrestricted session token - and let it act as any of them, + // which is the escalation the permission model exists to prevent. + if (isScopedCredential(params)) { + common.returnMessage(params, 403, "A restricted token cannot list tokens"); + return; + } common.db.collection("auth_tokens").find({"owner": params.member._id + ""}).toArray(function(err, res) { if (err) { common.returnMessage(params, 404, err.message); diff --git a/api/utils/rights.js b/api/utils/rights.js index d1fe6e02896..d2251bf7b1a 100644 --- a/api/utils/rights.js +++ b/api/utils/rights.js @@ -31,10 +31,14 @@ function validate_token_if_exists(params) { qstring: params.qstring, token: token, req_path: params.fullPath, + //the whole token document is needed, not just the owner, so the token's own + //permissions can bound what the resolved member is allowed to do + return_data: true, callback: function(valid) { - //false or owner.id + //false or the token document if (valid) { - resolve(valid); + params.token_data = valid; + resolve(valid.owner); } else { resolve('token-invalid'); @@ -48,6 +52,28 @@ function validate_token_if_exists(params) { } }); } + +/** +* Bound a member by the permissions of the token used to authenticate as them. +* +* Authenticating with a token resolves to the token's owner, and every validator then decides +* what to allow from that member. Without this step the member is loaded at full strength, so a +* token deliberately scoped to one app authorizes everything its owner can do - the escalation +* this model exists to prevent. Applied as soon as the member is loaded, so that the validators' +* own permission checks already see the bounded member. +* +* A token with no token_permission (an api_key request, a dashboard session token, or a token +* created before this model) is returned unchanged, so existing integrations are unaffected. +* @param {params} params - {@link params} object, carrying token_data when a token was used +* @param {object} member - member document loaded for the token owner +* @returns {object} the member, bounded by the token's permissions when the token is scoped +*/ +function applyTokenScope(params, member) { + if (params.token_data && params.token_data.token_permission) { + return exports.intersectPermission(member, params.token_data.token_permission); + } + return member; +} /** * Validate user for read access by api_key for provided app_id (both required parameters for the request). * User must exist, must not be locked, must pass plugin validation (if any) and have at least user access to the provided app (which also must exist). @@ -87,6 +113,9 @@ exports.validateUserForRead = function(params, callback, callbackParam) { return false; } + //bound the member by the token used to authenticate, before anything is authorized + member = applyTokenScope(params, member); + if (typeof params.qstring.app_id === "undefined") { common.returnMessage(params, 401, 'No app_id provided'); reject('No app_id provided'); @@ -183,6 +212,9 @@ exports.validateUserForWrite = function(params, callback, callbackParam) { return false; } + //bound the member by the token used to authenticate, before anything is authorized + member = applyTokenScope(params, member); + if (!(module.exports.hasAdminAccess(member, params.qstring.app_id))) { common.returnMessage(params, 401, 'User does not have right'); reject('User does not have right'); @@ -272,6 +304,9 @@ exports.validateGlobalAdmin = function(params, callback, callbackParam) { return false; } + //bound the member by the token used to authenticate, before anything is authorized + member = applyTokenScope(params, member); + if (!member.global_admin) { common.returnMessage(params, 401, 'User does not have right'); reject('User does not have right'); @@ -343,6 +378,9 @@ exports.validateAppAdmin = function(params, callback, callbackParam) { return false; } + //bound the member by the token used to authenticate, before anything is authorized + member = applyTokenScope(params, member); + if (!params.qstring.app_id) { common.returnMessage(params, 400, 'No app id provided'); return false; @@ -428,6 +466,9 @@ exports.validateUser = function(params, callback, callbackParam) { return false; } + //bound the member by the token used to authenticate, before anything is authorized + member = applyTokenScope(params, member); + if (member && member.locked) { common.returnMessage(params, 401, 'User is locked'); reject('User is locked'); @@ -826,6 +867,9 @@ exports.validateRead = function(params, feature, callback, callbackParam) { return false; } + //bound the member by the token used to authenticate, before anything is authorized + member = applyTokenScope(params, member); + if (!member.global_admin && typeof params.qstring.app_id === "undefined") { common.returnMessage(params, 401, 'No app_id provided'); reject('No app_id provided'); @@ -980,6 +1024,9 @@ function validateWrite(params, feature, accessType, callback, callbackParam) { return false; } + //bound the member by the token used to authenticate, before anything is authorized + member = applyTokenScope(params, member); + if (!member.global_admin && /*appIdExceptions.indexOf(feature) === -1 && */ typeof params.qstring.app_id === "undefined") { common.returnMessage(params, 401, 'No app_id provided'); reject('No app_id provided'); @@ -1226,6 +1273,374 @@ exports.hasDeleteRight = function(feature, app_id, member) { return hasAppSpecificRight || hasGlobalAdminRight || hasAppAdminRight; }; +/** +* Access types in a permission object, in their canonical order. +*/ +var PERMISSION_TYPES = ["c", "r", "u", "d"]; + +/** +* Whether a principal grants a single feature on an app for one access type. +* +* A principal is anything holding authority: a member (with global_admin / permission, or the +* legacy admin_of / user_of arrays), or a bare token permission set wrapped as {permission: obj}. +* This is the same rule the hasCreateRight / hasReadRight / hasUpdateRight / hasDeleteRight +* helpers apply to a member, expressed once so it can also be applied to a token. +* @param {object} principal - object with permission (and optionally global_admin) +* @param {string} type - access type (c, r, u, d) +* @param {string} appId - id of the app +* @param {string} feature - feature name +* @returns {boolean} true if the principal allows that feature +*/ +function principalAllows(principal, type, appId, feature) { + if (!principal) { + return false; + } + if (principal.global_admin) { + return true; + } + var permission = principal.permission; + if (typeof permission === "undefined") { + //legacy member: admin_of grants everything on the app, user_of grants reads + if (Array.isArray(principal.admin_of) && principal.admin_of.indexOf(appId) !== -1) { + return true; + } + return type === "r" && Array.isArray(principal.user_of) && principal.user_of.indexOf(appId) !== -1; + } + if (permission._ && Array.isArray(permission._.a) && permission._.a.indexOf(appId) !== -1) { + return true; + } + var forType = permission[type]; + if (!forType || !forType[appId]) { + return false; + } + if (forType[appId].all === true) { + return true; + } + return !!(forType[appId].allowed && forType[appId].allowed[feature] === true); +} + +/** +* Whether a principal grants every feature on an app for one access type. +* +* Distinct from principalAllows because "all" also covers features that do not exist yet, so it +* may only be granted by a principal that itself holds "all". +* @param {object} principal - object with permission (and optionally global_admin) +* @param {string} type - access type (c, r, u, d) +* @param {string} appId - id of the app +* @returns {boolean} true if the principal allows everything for that app and type +*/ +function principalAllowsAll(principal, type, appId) { + if (!principal) { + return false; + } + if (principal.global_admin) { + return true; + } + var permission = principal.permission; + if (typeof permission === "undefined") { + if (Array.isArray(principal.admin_of) && principal.admin_of.indexOf(appId) !== -1) { + return true; + } + return type === "r" && Array.isArray(principal.user_of) && principal.user_of.indexOf(appId) !== -1; + } + if (permission._ && Array.isArray(permission._.a) && permission._.a.indexOf(appId) !== -1) { + return true; + } + var forType = permission[type]; + return !!(forType && forType[appId] && forType[appId].all === true); +} + +/** +* Every app id a principal refers to, whether through the _ grouping or a c/r/u/d entry. +* @param {object} principal - object with permission (and optionally the legacy arrays) +* @returns {string[]} list of app ids +*/ +function principalApps(principal) { + var apps = []; + /** + * Add an app id once. + * @param {string} appId - id of the app + * @returns {void} + */ + var push = function(appId) { + if (apps.indexOf(appId) === -1) { + apps.push(appId); + } + }; + if (!principal) { + return apps; + } + var permission = principal.permission; + if (typeof permission === "undefined") { + (principal.admin_of || []).forEach(push); + (principal.user_of || []).forEach(push); + return apps; + } + if (permission._) { + if (Array.isArray(permission._.a)) { + permission._.a.forEach(push); + } + if (Array.isArray(permission._.u)) { + for (var g = 0; g < permission._.u.length; g++) { + (permission._.u[g] || []).forEach(push); + } + } + } + for (var t = 0; t < PERMISSION_TYPES.length; t++) { + var forType = permission[PERMISSION_TYPES[t]]; + for (var appId in forType || {}) { + push(appId); + } + } + return apps; +} + +/** +* App ids a permission object actually grants something on. +* +* Distinct from principalApps: the permission editor emits an entry for every app the editing user +* can see, most of them granting nothing, and an empty entry is not a grant. Apps listed under _.u +* do count, because some validators authorize on app membership alone. +* @param {object} permission - permission object +* @returns {string[]} list of app ids the permission grants something on +*/ +function grantingApps(permission) { + var apps = []; + /** + * Add an app id once. + * @param {string} appId - id of the app + * @returns {void} + */ + var push = function(appId) { + if (apps.indexOf(appId) === -1) { + apps.push(appId); + } + }; + if (!permission) { + return apps; + } + if (permission._) { + if (Array.isArray(permission._.a)) { + permission._.a.forEach(push); + } + if (Array.isArray(permission._.u)) { + for (var g = 0; g < permission._.u.length; g++) { + (permission._.u[g] || []).forEach(push); + } + } + } + for (var t = 0; t < PERMISSION_TYPES.length; t++) { + var forType = permission[PERMISSION_TYPES[t]] || {}; + for (var appId in forType) { + var entry = forType[appId]; + if (!entry) { + continue; + } + if (entry.all === true) { + push(appId); + continue; + } + for (var feature in entry.allowed || {}) { + if (entry.allowed[feature] === true) { + push(appId); + break; + } + } + } + } + return apps; +} + +/** +* Feature names a principal explicitly allows for an app and access type. +* @param {object} principal - object with permission +* @param {string} type - access type (c, r, u, d) +* @param {string} appId - id of the app +* @returns {string[]} list of feature names +*/ +function principalFeatures(principal, type, appId) { + var features = []; + var permission = principal && principal.permission; + var entry = permission && permission[type] && permission[type][appId]; + if (entry && entry.allowed) { + for (var feature in entry.allowed) { + if (entry.allowed[feature] === true) { + features.push(feature); + } + } + } + return features; +} + +/** +* Whether one permission set grants nothing beyond what a ceiling principal already holds. +* +* This is what bounds a grant to the credential that creates it: a token may only pass on +* authority it holds itself. The ceiling is the member for an api_key or an unrestricted session, +* and the parent token's own permissions when a token creates a token - so a token scoped to app A +* cannot produce a child that reaches app B, even though their common owner can. +* @param {object} childPermission - permission object being granted +* @param {object} ceiling - principal that must already hold everything the child grants +* @returns {boolean} true if childPermission is a subset of the ceiling's authority +*/ +exports.isPermissionSubset = function(childPermission, ceiling) { + //a malformed permission grants nothing recognisable, and an empty-looking value must not be + //mistaken for "grants nothing, therefore a subset" + if (!childPermission || typeof childPermission !== "object" || Array.isArray(childPermission)) { + return false; + } + var t, appId, i; + //an app the child administers implies every feature of every type, present and future + var childAdminApps = (childPermission._ && Array.isArray(childPermission._.a)) ? childPermission._.a : []; + for (i = 0; i < childAdminApps.length; i++) { + for (t = 0; t < PERMISSION_TYPES.length; t++) { + if (!principalAllowsAll(ceiling, PERMISSION_TYPES[t], childAdminApps[i])) { + return false; + } + } + } + //an app the child can see at all must be an app the ceiling can see, since some validators + //authorize on app membership alone + var ceilingApps = principalApps(ceiling); + var childApps = grantingApps(childPermission); + for (i = 0; i < childApps.length; i++) { + if (!ceiling.global_admin && ceilingApps.indexOf(childApps[i]) === -1) { + return false; + } + } + for (t = 0; t < PERMISSION_TYPES.length; t++) { + var forType = childPermission[PERMISSION_TYPES[t]]; + for (appId in forType || {}) { + var entry = forType[appId]; + if (!entry) { + continue; + } + if (entry.all === true && !principalAllowsAll(ceiling, PERMISSION_TYPES[t], appId)) { + return false; + } + for (var feature in entry.allowed || {}) { + if (entry.allowed[feature] === true && !principalAllows(ceiling, PERMISSION_TYPES[t], appId, feature)) { + return false; + } + } + } + } + return true; +}; + +/** +* Whether the credential that authenticated this request is narrower than its owner. +* +* True for a token carrying token_permission, and for a token restricted by the legacy +* app/endpoint scope. False for an api_key (the member itself) and for an unrestricted token such +* as a dashboard session token. Used to keep credential management - which hands out and revokes +* the owner's other credentials - to credentials that are not themselves narrowed. +* @param {params} params - {@link params} object +* @returns {boolean} true if a scoped credential authenticated the request +*/ +exports.isScopedCredential = function(params) { + var token = params && params.token_data; + if (!token) { + return false; + } + if (token.token_permission) { + return true; + } + /** + * Whether a legacy scope value restricts anything. + * @param {string|Array} scope - the app or endpoint field of a token + * @returns {boolean} true if restricted + */ + var isScopeRestricted = function(scope) { + return !(scope === undefined || scope === null || scope === "" || (Array.isArray(scope) && scope.length === 0)); + }; + return isScopeRestricted(token.app) || isScopeRestricted(token.endpoint); +}; + +/** +* Every app id referenced by a permission object. +* @param {object} permission - permission object ({_:{a,u}, c/r/u/d:{appId:...}}) +* @returns {string[]} list of app ids +*/ +exports.getPermissionApps = function(permission) { + return principalApps({permission: permission}); +}; + +/** +* Bound a member by a token's permissions, returning a member that holds only what both allow. +* +* The subset check at creation time bounds a token to its creator, but the owner's own +* permissions can be reduced afterwards, so the intersection is recomputed on every request. +* The returned member never carries global_admin: that is precisely the authority a scoped token +* was narrowed away from, and leaving it set would let every global_admin check bypass the scope. +* @param {object} member - member document for the token owner +* @param {object} tokenPermission - permission object stored on the token +* @returns {object} a copy of the member holding only the intersection +*/ +exports.intersectPermission = function(member, tokenPermission) { + var scoped = Object.assign({}, member); + scoped.global_admin = false; + //the legacy arrays are an alternative expression of authority, so they cannot be carried over + delete scoped.admin_of; + delete scoped.user_of; + + var result = {_: {a: [], u: [[]]}, c: {}, r: {}, u: {}, d: {}}; + var tokenPrincipal = {permission: tokenPermission}; + var userApps = []; + var memberApps = principalApps(member); + var tokenAdminApps = (tokenPermission._ && Array.isArray(tokenPermission._.a)) ? tokenPermission._.a : []; + var tokenUserApps = []; + if (tokenPermission._ && Array.isArray(tokenPermission._.u)) { + for (var g = 0; g < tokenPermission._.u.length; g++) { + tokenUserApps = tokenUserApps.concat(tokenPermission._.u[g] || []); + } + } + + grantingApps(tokenPermission).forEach(function(appId) { + //an app the owner can no longer reach grants the token nothing, whatever the token says + if (!member.global_admin && memberApps.indexOf(appId) === -1) { + return; + } + var grantsAnything = false; + for (var t = 0; t < PERMISSION_TYPES.length; t++) { + var type = PERMISSION_TYPES[t]; + var tokenAll = principalAllowsAll(tokenPrincipal, type, appId); + if (tokenAll && principalAllowsAll(member, type, appId)) { + result[type][appId] = {all: true, allowed: {}}; + grantsAnything = true; + continue; + } + //whichever side is not "all" has a finite feature list, and that is what to walk + var candidates = tokenAll ? principalFeatures(member, type, appId) : principalFeatures(tokenPrincipal, type, appId); + var allowed = {}; + var any = false; + candidates.forEach(function(feature) { + if (principalAllows(tokenPrincipal, type, appId, feature) && principalAllows(member, type, appId, feature)) { + allowed[feature] = true; + any = true; + } + }); + if (any) { + result[type][appId] = {all: false, allowed: allowed}; + grantsAnything = true; + } + } + var isAdmin = tokenAdminApps.indexOf(appId) !== -1 && exports.hasAdminAccess(member, appId); + if (isAdmin) { + result._.a.push(appId); + } + else if (grantsAnything || tokenUserApps.indexOf(appId) !== -1) { + //app membership alone is what some validators check, so an app the token grants + //anything on - or names as a user app - stays visible + userApps.push(appId); + } + }); + + result._.u = [userApps]; + scoped.permission = result; + return scoped; +}; + exports.getUserApps = function(member) { let userApps = []; if (member.global_admin) { diff --git a/frontend/express/libs/members.js b/frontend/express/libs/members.js index 37cff1f3e4b..1cf92674191 100644 --- a/frontend/express/libs/members.js +++ b/frontend/express/libs/members.js @@ -225,6 +225,9 @@ function setLoggedInVariables(req, member, countlyDb, callback) { tryReuse: reuse, ttl: getSessionTimeoutInMs(req) / 1000, purpose: "LoggedInAuth", + //the server is establishing an interactive session here, which is the one place login + //permission originates; the token is unscoped, so it stays as capable as the session it is + can_login: true, callback: function(err2, token) { if (err2) { console.log(err2); @@ -487,17 +490,27 @@ membersUtility.loginWithToken = function(req, callback) { return callback(undefined); } - // Only allow tokens whose purpose is explicitly "log this member in". - // - "LoggedInAuth" — legitimate session tokens (set by setLoggedInVariables; - // mail.sendTimeBanWarning). - // - "LoginAuthToken" — short-lived (TTL=300, multi:false) tokens used by the - // server-side Puppeteer renderer to authenticate the - // headless Chrome session at /login/token/:token. - // Any other purpose — including arbitrary purposes settable via /i/token/create - // by a global admin — MUST NOT be redeemable here. - var allowedLoginPurposes = ["LoggedInAuth", "LoginAuthToken"]; - if (allowedLoginPurposes.indexOf(valid.purpose) === -1) { - plugins.callMethod("tokenLoginFailed", {req: req, data: {token: token, token_owner: valid.owner, reason: "wrong_purpose"}}); + // Redeeming a token here grants the owner's full dashboard session, so it is allowed + // only for a token that explicitly carries login permission. can_login is set by the + // server where a session is established or propagated (setLoggedInVariables, the + // renderer, the ban-warning mail, OIDC), and by /i/token/create only when the creating + // credential already holds it and the child is not narrowed. Purpose is a description, + // not a capability: it used to be the gate here while being freely settable at create + // time, which is what let a scoped token forge its way into a full session. + var canLogin = valid.can_login === true; + if (!canLogin && typeof valid.can_login === "undefined") { + // Tokens minted before this model have no can_login field. Honour the ones that + // were legitimately redeemable then - a login purpose and no restriction at all - + // so live sessions and existing login-token integrations keep working. Scoped + // legacy tokens stay locked out. + var isLoginScopeRestricted = function(scope) { + return !(scope === undefined || scope === null || scope === "" || (Array.isArray(scope) && scope.length === 0)); + }; + var legacyLoginPurposes = ["LoggedInAuth", "LoginAuthToken"]; + canLogin = legacyLoginPurposes.indexOf(valid.purpose) !== -1 && !isLoginScopeRestricted(valid.app) && !isLoginScopeRestricted(valid.endpoint) && !valid.token_permission; + } + if (!canLogin) { + plugins.callMethod("tokenLoginFailed", {req: req, data: {token: token, token_owner: valid.owner, reason: "no_login_permission"}}); return callback(undefined); } diff --git a/frontend/express/public/core/token-manager/javascripts/countly.views.js b/frontend/express/public/core/token-manager/javascripts/countly.views.js index 2b95a00fe13..56787c24266 100644 --- a/frontend/express/public/core/token-manager/javascripts/countly.views.js +++ b/frontend/express/public/core/token-manager/javascripts/countly.views.js @@ -1,5 +1,7 @@ -/*global app, countlyVue, countlyCommon, CV, $, countlyGlobal, countlyTokenManager, CountlyHelpers */ +/*global app, countlyVue, countlyCommon, CV, $, countlyGlobal, countlyTokenManager, countlyUserManagement, countlyAuth, CountlyHelpers */ (function() { + var PERMISSION_TYPES = ["c", "r", "u", "d"]; + var TokenDrawer = countlyVue.views.create({ template: CV.T('/core/token-manager/templates/token-manager-drawer.html'), data: function() { @@ -7,6 +9,11 @@ tokenUsage: '0', tokenExpiration: '0', title: '', + features: [], + filteredFeatures: [], + searchQuery: '', + allByType: {c: false, r: false, u: false, d: false}, + permissionSet: countlyAuth.permissionSetGenerator(1)[0], constants: { "availableProps": [ { label: CV.i18n('token_manager.limit.h'), value: "hours" }, @@ -17,6 +24,13 @@ } }; }, + mounted: function() { + var self = this; + $.when(countlyUserManagement.fetchFeatures()).then(function() { + self.features = countlyUserManagement.getFeatures() || []; + self.filteredFeatures = self.features; + }); + }, methods: { appsData: function() { var apps = []; @@ -25,51 +39,81 @@ } return apps; }, - addEndpoint: function(endpoints) { - endpoints.push({parameters: [{}]}); + featureBeautifier: function(feature) { + return countlyAuth.featureBeautifier(feature); }, - addParameter: function(parameters) { - parameters.push({}); + search: function() { + var self = this; + var query = (self.searchQuery || "").toLowerCase(); + if (query !== "") { + self.filteredFeatures = self.features.filter(function(feature) { + return self.featureBeautifier(feature).toLowerCase().indexOf(query) !== -1; + }); + } + else { + self.filteredFeatures = self.features; + } }, - removeEndpoint: function(endpoints, endpointIndex) { - if (endpoints.length > 1) { - endpoints.splice(endpointIndex, 1); + clearSearch: function() { + this.searchQuery = ''; + this.filteredFeatures = this.features; + }, + //granting anything on a feature implies being able to read it, mirroring how a user's + //own permissions are edited in user management + setPermissionByFeature: function(type, feature) { + if (type !== 'r' && this.permissionSet[type].allowed[feature] && !this.permissionSet.r.allowed[feature]) { + this.$set(this.permissionSet.r.allowed, feature, true); } + if (type === 'r' && !this.permissionSet.r.allowed[feature]) { + for (var i = 0; i < PERMISSION_TYPES.length; i++) { + this.$set(this.permissionSet[PERMISSION_TYPES[i]].allowed, feature, false); + } + } + this.syncAllFlags(); }, - removeParameter: function(parameters, parameterIndex) { - if (parameters.length > 1) { - parameters.splice(parameterIndex, 1); + setPermissionByType: function(type) { + var on = this.allByType[type]; + for (var i = 0; i < this.filteredFeatures.length; i++) { + var feature = this.filteredFeatures[i]; + this.$set(this.permissionSet[type].allowed, feature, on); + if (on && type !== 'r') { + this.$set(this.permissionSet.r.allowed, feature, true); + } + if (!on && type === 'r') { + for (var j = 0; j < PERMISSION_TYPES.length; j++) { + this.$set(this.permissionSet[PERMISSION_TYPES[j]].allowed, feature, false); + } + } } + this.syncAllFlags(); + }, + //"all" must mean every feature, including ones added later, so it is only set when the + //whole list is selected - the server refuses an "all" grant the creator does not hold + syncAllFlags: function() { + var self = this; + PERMISSION_TYPES.forEach(function(type) { + var every = self.features.length > 0 && self.features.every(function(feature) { + return self.permissionSet[type].allowed[feature] === true; + }); + self.permissionSet[type].all = every; + self.allByType[type] = every; + }); + }, + buildPermission: function(apps) { + var permission = {_: {a: [], u: [apps]}, c: {}, r: {}, u: {}, d: {}}; + return countlyAuth.combinePermissionObject([apps], [this.permissionSet], permission); }, onClose: function() { this.tokenUsage = '0'; this.tokenExpiration = '0'; + this.searchQuery = ''; + this.filteredFeatures = this.features; + this.permissionSet = countlyAuth.permissionSetGenerator(1)[0]; + this.allByType = {c: false, r: false, u: false, d: false}; }, onSubmit: function(doc) { var self = this; var ttl = 0; - var selectApps = doc.selectApps; - var endpoints = doc.endpoints; - var newEndpoints = []; - endpoints.forEach(function(element) { - if (element.endpointName !== "" && element.endpointName) { - var obj = {params: {}} ; - obj.endpoint = element.endpointName; - element.parameters.forEach(function(item) { - var key = item.queryParameters1; - var value = item.queryParameters2; - obj.params[key] = value; - }); - newEndpoints.push(obj); - } - }); - endpoints = JSON.stringify(newEndpoints); - - if (self.tokenUsage === "1") { - if (doc.selectApps.length > 0) { - selectApps = doc.selectApps.join(","); - } - } if (self.tokenExpiration === "1") { if (doc.selectTime === "hours") { ttl = doc.timeInput * 3600; @@ -81,7 +125,26 @@ ttl = doc.timeInput * 3600 * 24 * 30; } } - countlyTokenManager.createTokenWithQuery(doc.description, endpoints, doc.checkboxMultipleTimes, selectApps, ttl, function() { + + var options = { + purpose: doc.description, + multi: doc.checkboxMultipleTimes, + ttl: ttl + }; + if (self.tokenUsage === "1") { + options.permission = self.buildPermission(doc.selectApps || []); + } + else { + //an unlimited token carries the creator's own permissions, and only such a + //token may be granted permission to sign in + options.canLogin = doc.checkboxCanLogin === true; + } + + countlyTokenManager.createTokenWithPermissions(options, function(err) { + if (err) { + CountlyHelpers.alert(CV.i18n('token_manager.create-error'), "red"); + return; + } self.$emit("create"); }); } @@ -156,6 +219,8 @@ row.purpose = row.purpose + ""; row.purpose = row.purpose[0].toUpperCase() + row.purpose.substring(1); } + row.canLogin = row.can_login === true; + row.permissionSummary = this.describePermission(row); if (Array.isArray(row.endpoint)) { var lines = []; for (var p = 0; p < row.endpoint.length; p++) { @@ -187,6 +252,40 @@ } this.tableData = tableData; }, + //describe what a token may do, so the list distinguishes a limited token from one that + //carries the owner's own permissions + describePermission: function(row) { + if (!row.token_permission) { + return CV.i18n('token_manager.permission.full'); + } + var counts = {c: 0, r: 0, u: 0, d: 0}; + var labels = []; + PERMISSION_TYPES.forEach(function(type) { + var forType = row.token_permission[type] || {}; + for (var appId in forType) { + var entry = forType[appId]; + if (!entry) { + continue; + } + var grants = entry.all === true; + for (var feature in entry.allowed || {}) { + if (entry.allowed[feature] === true) { + grants = true; + break; + } + } + if (grants) { + counts[type]++; + } + } + }); + PERMISSION_TYPES.forEach(function(type) { + if (counts[type] > 0) { + labels.push(CV.i18n('token_manager.permission.' + type)); + } + }); + return labels.length ? labels.join(", ") : CV.i18n('token_manager.permission.none'); + }, getColor: function(status) { if (status === "active") { return "green"; @@ -197,7 +296,7 @@ }, onCreateClick: function() { this.openDrawer("main", { - description: "", checkboxMultipleTimes: false, endpoints: [{parameters: [{}]}], selectApps: [] + description: "", checkboxMultipleTimes: false, checkboxCanLogin: false, selectApps: [] }); }, onDelete: function(row) { diff --git a/frontend/express/public/core/token-manager/templates/token-manager-drawer.html b/frontend/express/public/core/token-manager/templates/token-manager-drawer.html index 0c1e1b3aba0..dffe9c3e385 100644 --- a/frontend/express/public/core/token-manager/templates/token-manager-drawer.html +++ b/frontend/express/public/core/token-manager/templates/token-manager-drawer.html @@ -10,53 +10,28 @@ - -
-

{{i18n('token_manager.table.endpoints')}}

-

{{i18n('common.optional')}}

-
-

{{i18n('token_manager.table.endpoints-description')}}

-
- -
-

{{i18n('token_manager.table.endpoint-detail')}}

- - Remove - -
- - - - -
- - - - - -
- + {{i18n('token_manager.add-param')}} -
-
- - - + {{i18n('token_manager.add-new-endpoint')}} - -
-

{{i18n('token_manager.table.apps-title')}}

+

{{i18n('token_manager.permission.title')}}

+

{{i18n('token_manager.permission.description')}}

- - {{i18n('token_manager.table.apps-allow')}} + + {{i18n('token_manager.permission.full-label')}} +

{{i18n('token_manager.permission.full-text')}}

- - {{i18n('token_manager.table.apps-limit')}} + + {{i18n('token_manager.permission.limited-label')}} +

{{i18n('token_manager.permission.limited-text')}}

+ + + {{i18n('token_manager.permission.can-login')}} + +

{{i18n('token_manager.permission.can-login-text')}}

+

{{i18n('token_manager.select-apps')}}

@@ -66,6 +41,31 @@ + +
+

{{i18n('token_manager.permission.features')}}

+
+

{{i18n('token_manager.permission.features-description')}}

+ + + + +
+ {{i18n('management-users.create').toUpperCase()}} + {{i18n('management-users.read').toUpperCase()}} + {{i18n('management-users.update').toUpperCase()}} + {{i18n('management-users.delete').toUpperCase()}} +
+
+
{{featureBeautifier(feature)}}
+
+ + + + +
+
+

{{i18n('token_manager.table.limit-title')}}

diff --git a/frontend/express/public/core/token-manager/templates/token-manager.html b/frontend/express/public/core/token-manager/templates/token-manager.html index d93a97adc2c..7c062f1c6b1 100644 --- a/frontend/express/public/core/token-manager/templates/token-manager.html +++ b/frontend/express/public/core/token-manager/templates/token-manager.html @@ -38,9 +38,11 @@ {{scope.row.app}} - + diff --git a/frontend/express/public/javascripts/countly/countly.token.manager.js b/frontend/express/public/javascripts/countly/countly.token.manager.js index ec2c44f79a6..bf5cb848ead 100644 --- a/frontend/express/public/javascripts/countly/countly.token.manager.js +++ b/frontend/express/public/javascripts/countly/countly.token.manager.js @@ -44,17 +44,35 @@ }); }; - countlyTokenManager.createTokenWithQuery = function(purpose, endpoint, multi, apps, ttl, callback) { + /** + * Create a token, optionally limited to a set of CRUD permissions. + * @param {object} options - token options + * @param {string} options.purpose - description of the token + * @param {boolean} options.multi - can the token be used more than once + * @param {number} options.ttl - seconds until the token expires, 0 never expires + * @param {object=} options.permission - permission object limiting the token, omitted for a + * token that carries the creator's own permissions + * @param {boolean=} options.canLogin - request permission to sign in to the dashboard. Granted + * only when the creating credential holds it and the token is not limited + * @param {function} callback - called with (error, response) + * @returns {object} jQuery ajax object + */ + countlyTokenManager.createTokenWithPermissions = function(options, callback) { + var data = { + "purpose": options.purpose, + "multi": options.multi, + "ttl": options.ttl + }; + if (options.permission) { + data.permission = JSON.stringify(options.permission); + } + if (options.canLogin) { + data.can_login = true; + } return $.ajax({ type: "GET", url: countlyCommon.API_URL + "/i/token/create", - data: { - "purpose": purpose, - "endpointquery": endpoint, - "multi": multi, - "apps": apps, - "ttl": ttl - }, + data: data, success: function(json) { //token created callback(null, json); diff --git a/frontend/express/public/localization/dashboard/dashboard.properties b/frontend/express/public/localization/dashboard/dashboard.properties index e6c14460408..98fb2624548 100644 --- a/frontend/express/public/localization/dashboard/dashboard.properties +++ b/frontend/express/public/localization/dashboard/dashboard.properties @@ -1155,6 +1155,25 @@ token_manager.select-time-unit = Select time unit token_manager.token-expiration-time = Expiration Time token_manager.LoginAuthToken-description = This token is created when creating dashboard screenshots. If you are not currently rendering dashboard images, you can delete this token. token_manager.LoggedInAuth-description = This token is used for keeping the user's session. Deleting it will log out the user currently using it to keep the session. +token_manager.create-error = Creating token failed +token_manager.table.permission = Permissions +token_manager.permission.title = Permissions +token_manager.permission.description = Choose what this token is allowed to do. A token can never be given more access than the credential creating it has. +token_manager.permission.full-label = Same access as my account +token_manager.permission.full-text = The token can do anything you can do, and its access shrinks if yours does. +token_manager.permission.limited-label = Limited access +token_manager.permission.limited-text = The token is restricted to the apps and permissions selected below. +token_manager.permission.features = Feature permissions +token_manager.permission.features-description = Select what the token may create, read, update and delete on the selected apps. +token_manager.permission.can-login = Allow this token to sign in to the dashboard +token_manager.permission.can-login-text = Available only for a token with the same access as your account, and only if the credential you are signed in with may sign in itself. +token_manager.permission.can-login-tag = Can sign in +token_manager.permission.full = Same access as owner +token_manager.permission.none = No access +token_manager.permission.c = Create +token_manager.permission.r = Read +token_manager.permission.u = Update +token_manager.permission.d = Delete version_history.page-title = Countly version history diff --git a/plugins/dashboards/api/api.js b/plugins/dashboards/api/api.js index 85585c4081f..e3bcc563450 100644 --- a/plugins/dashboards/api/api.js +++ b/plugins/dashboards/api/api.js @@ -1506,6 +1506,8 @@ plugins.setConfigs("dashboards", { purpose: "LoginAuthToken", temporary: true, ttl: 540, //9 minutes + //the headless renderer authenticates by redeeming this at /login/token + can_login: true, callback: function(er, token) { if (er) { return resolve(); diff --git a/test/2.api/16.token.manager.js b/test/2.api/16.token.manager.js index eceac22a375..29106c75aab 100644 --- a/test/2.api/16.token.manager.js +++ b/test/2.api/16.token.manager.js @@ -379,4 +379,249 @@ describe('Testing token manager', function() { }); }); }); + + describe('Token permissions bound every grant to the creating credential', function() { + var limitedToken = ""; + var fullToken = ""; + var legacyRestrictedToken = ""; + + //a token allowed only to read the "core" feature of APP_ID, and nothing else + var readCorePermission = function(appId) { + var permission = {_: {a: [], u: [[appId]]}, c: {}, r: {}, u: {}, d: {}}; + permission.r[appId] = {all: false, allowed: {core: true}}; + return encodeURIComponent(JSON.stringify(permission)); + }; + + //a token that additionally claims delete on everything, which its creator must not pass on + var deleteAllPermission = function(appId) { + var permission = {_: {a: [], u: [[appId]]}, c: {}, r: {}, u: {}, d: {}}; + permission.r[appId] = {all: false, allowed: {core: true}}; + permission.d[appId] = {all: true, allowed: {}}; + return encodeURIComponent(JSON.stringify(permission)); + }; + + var deleteToken = function(id, done) { + if (!id) { + return done(); + } + request + .get('/i/token/delete?api_key=' + API_KEY_ADMIN + '&tokenid=' + id) + .end(function() { + done(); + }); + }; + + it('setup: api_key creates a token limited to reading core on one app', function(done) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&purpose=integration&multi=true&ttl=3600&permission=' + readCorePermission(APP_ID)) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + var ob = JSON.parse(res.text); + ob.should.have.property('result'); + limitedToken = ob.result; + (limitedToken !== "").should.equal(true); + done(); + }); + }); + + it('the limited token can read the feature it was granted', function(done) { + request + .get('/o/users/permissions?app_id=' + APP_ID + '&auth_token=' + limitedToken) + .expect(200) + .end(function(err) { + if (err) { + return done(err); + } + done(); + }); + }); + + it('the limited token cannot act as a global admin, even though its owner is one', function(done) { + request + .get('/o/users/all?auth_token=' + limitedToken) + .expect(401) + .end(function(err) { + if (err) { + return done(err); + } + done(); + }); + }); + + it('the limited token cannot create an unrestricted child', function(done) { + request + .get('/i/token/create?auth_token=' + limitedToken + '&multi=true&ttl=300') + .expect(403) + .end(function(err, res) { + if (err) { + return done(err); + } + //an unrestricted child would carry the owner's full permissions + JSON.parse(res.text).should.have.property('result'); + done(); + }); + }); + + it('the limited token cannot grant a permission it does not hold', function(done) { + request + .get('/i/token/create?auth_token=' + limitedToken + '&multi=true&ttl=300&permission=' + deleteAllPermission(APP_ID)) + .expect(403) + .end(function(err, res) { + if (err) { + return done(err); + } + JSON.parse(res.text).should.have.property('result', "Token permissions must be a subset of the creating credential's permissions"); + done(); + }); + }); + + it('the limited token can create a child within its own permissions', function(done) { + request + .get('/i/token/create?auth_token=' + limitedToken + '&multi=true&ttl=300&permission=' + readCorePermission(APP_ID)) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + deleteToken(JSON.parse(res.text).result, done); + }); + }); + + it('the limited token cannot be granted login permission', function(done) { + request + .get('/i/token/create?auth_token=' + limitedToken + '&multi=true&ttl=300&can_login=true') + .expect(403) + .end(function(err, res) { + if (err) { + return done(err); + } + JSON.parse(res.text).should.have.property('result', 'The creating credential cannot grant login permission'); + done(); + }); + }); + + it('the limited token cannot list the owner tokens, which would hand it their secrets', function(done) { + request + .get('/o/token/list?auth_token=' + limitedToken) + .expect(403) + .end(function(err, res) { + if (err) { + return done(err); + } + JSON.parse(res.text).should.have.property('result', 'A restricted token cannot list tokens'); + done(); + }); + }); + + it('the limited token cannot delete the owner tokens', function(done) { + request + .get('/i/token/delete?auth_token=' + limitedToken + '&tokenid=' + limitedToken) + .expect(403) + .end(function(err) { + if (err) { + return done(err); + } + done(); + }); + }); + + it('a purpose string alone never grants login permission', function(done) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&purpose=LoggedInAuth&multi=true&ttl=300') + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + var forged = JSON.parse(res.text).result; + //the token exists, but carries no login permission, so it cannot open a session + request + .get('/login/token/' + forged) + .expect(302) + .end(function(err2, res2) { + if (err2) { + return done(err2); + } + //rejected logins are redirected back to the login page + res2.headers.location.should.not.containEql('/dashboard'); + deleteToken(forged, done); + }); + }); + }); + + it('api_key can still create a token, and grant it login permission', function(done) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&multi=true&ttl=300&can_login=true') + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + fullToken = JSON.parse(res.text).result; + (fullToken !== "").should.equal(true); + done(); + }); + }); + + it('a full-permission token can create a child, as the dashboard session does', function(done) { + request + .get('/i/token/create?auth_token=' + fullToken + '&purpose=child&multi=true&ttl=300') + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + deleteToken(JSON.parse(res.text).result, done); + }); + }); + + it('setup: a token restricted the legacy way, by app', function(done) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&purpose=legacy&multi=true&ttl=3600&apps=' + APP_ID) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + legacyRestrictedToken = JSON.parse(res.text).result; + done(); + }); + }); + + it('a legacy app-restricted token cannot create tokens', function(done) { + request + .get('/i/token/create?auth_token=' + legacyRestrictedToken + '&multi=true&ttl=300') + .expect(403) + .end(function(err, res) { + if (err) { + return done(err); + } + JSON.parse(res.text).should.have.property('result', 'A restricted token cannot create tokens'); + done(); + }); + }); + + it('an endpoint restriction cannot be combined with permissions', function(done) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&multi=true&ttl=300&endpoint=/o/users&permission=' + readCorePermission(APP_ID)) + .expect(400) + .end(function(err) { + if (err) { + return done(err); + } + done(); + }); + }); + + it('cleanup: remove the tokens created here', function(done) { + deleteToken(limitedToken, function() { + deleteToken(fullToken, function() { + deleteToken(legacyRestrictedToken, done); + }); + }); + }); + }); }); \ No newline at end of file diff --git a/test/unit-tests/api.utils.authorizer.tokenFields.js b/test/unit-tests/api.utils.authorizer.tokenFields.js new file mode 100644 index 00000000000..3e86a0af786 --- /dev/null +++ b/test/unit-tests/api.utils.authorizer.tokenFields.js @@ -0,0 +1,179 @@ +require("should"); +var authorizer = require("../../api/utils/authorizer.js"); + +var OWNER = "60e42efa5c23ee7ec6259af0"; + +/** +* Minimal in-memory stand-in for the countly db handle, so the token record can be exercised +* without a running MongoDB. +* @param {object[]} tokens - documents the auth_tokens collection starts with +* @returns {object} db stub, with the stored documents on .stored +*/ +function dbStub(tokens) { + var stored = tokens || []; + return { + stored: stored, + ObjectID: function(id) { + return id; + }, + collection: function(name) { + return { + findOne: function(query, callback) { + if (name === "members") { + return callback(null, {_id: OWNER}); + } + var found = stored.filter(function(doc) { + return doc._id === query._id; + })[0]; + callback(null, found || null); + }, + insert: function(doc, callback) { + stored.push(doc); + callback(null, doc); + }, + remove: function() { }, + update: function() { }, + findAndModify: function(rules, sort, update, callback) { + callback(null, null); + } + }; + } + }; +} + +describe("authorizer token record", function() { + it("stores can_login and token_permission when they are asked for", function(done) { + var db = dbStub([]); + var permission = {_: {a: [], u: [["app1"]]}, c: {}, r: {app1: {all: false, allowed: {core: true}}}, u: {}, d: {}}; + authorizer.save({ + db: db, + owner: OWNER, + ttl: 300, + token_permission: permission, + can_login: true, + callback: function(err) { + (!err).should.equal(true); + db.stored.length.should.equal(1); + db.stored[0].can_login.should.equal(true); + db.stored[0].token_permission.should.eql(permission); + done(); + } + }); + }); + + it("defaults to no login permission and no permission scope", function(done) { + var db = dbStub([]); + authorizer.save({ + db: db, + owner: OWNER, + ttl: 300, + callback: function() { + //login permission is never acquired by omission + db.stored[0].can_login.should.equal(false); + db.stored[0].should.not.have.property("token_permission"); + done(); + } + }); + }); + + it("never treats a truthy non-true value as login permission", function(done) { + var db = dbStub([]); + authorizer.save({ + db: db, + owner: OWNER, + ttl: 300, + can_login: "yes", + callback: function() { + db.stored[0].can_login.should.equal(false); + done(); + } + }); + }); + + describe("verify_token", function() { + var future = Math.round(Date.now() / 1000) + 3600; + + it("still applies the endpoint regex to a legacy token", function(done) { + var db = dbStub([{ + _id: "legacy", + ttl: 300, + ends: future, + multi: true, + owner: OWNER, + app: "", + endpoint: ["^/o/users"], + purpose: "legacy" + }]); + authorizer.verify_return({ + db: db, + token: "legacy", + req_path: "/o/apps/all", + return_data: true, + callback: function(valid) { + //path outside the allowed regex is refused, as before + (valid === false).should.equal(true); + authorizer.verify_return({ + db: db, + token: "legacy", + req_path: "/o/users/all", + return_data: true, + callback: function(valid2) { + valid2.should.have.property("_id", "legacy"); + done(); + } + }); + } + }); + }); + + it("ignores the endpoint regex once a token carries permissions", function(done) { + //the regex was never an authorization boundary; permissions are enforced in rights.js + var db = dbStub([{ + _id: "scoped", + ttl: 300, + ends: future, + multi: true, + owner: OWNER, + app: "", + endpoint: ["^/o/users"], + purpose: "integration", + token_permission: {_: {a: [], u: [[]]}, c: {}, r: {}, u: {}, d: {}} + }]); + authorizer.verify_return({ + db: db, + token: "scoped", + req_path: "/o/apps/all", + return_data: true, + callback: function(valid) { + valid.should.have.property("_id", "scoped"); + valid.should.have.property("token_permission"); + done(); + } + }); + }); + + it("still refuses a request for an app the token is not scoped to", function(done) { + var db = dbStub([{ + _id: "appscoped", + ttl: 300, + ends: future, + multi: true, + owner: OWNER, + app: ["app1"], + endpoint: "", + purpose: "integration" + }]); + authorizer.verify_return({ + db: db, + token: "appscoped", + req_path: "/o", + qstring: {app_id: "app2"}, + return_data: true, + callback: function(valid) { + (valid === false).should.equal(true); + done(); + } + }); + }); + }); +}); diff --git a/test/unit-tests/api.utils.rights.tokenPermissions.js b/test/unit-tests/api.utils.rights.tokenPermissions.js new file mode 100644 index 00000000000..df3671067ba --- /dev/null +++ b/test/unit-tests/api.utils.rights.tokenPermissions.js @@ -0,0 +1,159 @@ +require("should"); +var rights = require("../../api/utils/rights.js"); + +var APP_A = "aaaaaaaaaaaaaaaaaaaaaaaa"; +var APP_B = "bbbbbbbbbbbbbbbbbbbbbbbb"; + +/** +* Build a permission object of the shape the permission editor and the token manager produce. +* @param {object} spec - {adminApps, userApps, grants:[{type, app, all, allowed}]} +* @returns {object} permission object +*/ +function permission(spec) { + var perm = {_: {a: spec.adminApps || [], u: [spec.userApps || []]}, c: {}, r: {}, u: {}, d: {}}; + (spec.grants || []).forEach(function(grant) { + perm[grant.type][grant.app] = grant.all ? {all: true, allowed: {}} : {all: false, allowed: grant.allowed}; + }); + return perm; +} + +var globalAdmin = {global_admin: true}; + +//can create+read core on A, read core and events on A, read core on B +var member = { + global_admin: false, + permission: permission({ + userApps: [APP_A, APP_B], + grants: [ + {type: "c", app: APP_A, allowed: {core: true}}, + {type: "r", app: APP_A, allowed: {core: true, events: true}}, + {type: "r", app: APP_B, allowed: {core: true}} + ] + }) +}; + +var adminOfA = {global_admin: false, permission: permission({adminApps: [APP_A]})}; + +var readCoreOnA = permission({userApps: [APP_A], grants: [{type: "r", app: APP_A, allowed: {core: true}}]}); + +describe("token permissions", function() { + describe("isPermissionSubset", function() { + it("allows a grant the ceiling holds", function() { + rights.isPermissionSubset(readCoreOnA, member).should.equal(true); + }); + + it("refuses a grant on an app the ceiling cannot reach", function() { + //the escalation this model exists to prevent: the owner has A and B, but a token + //scoped to A must not be able to produce a child that reaches B + var childOnB = permission({userApps: [APP_B], grants: [{type: "r", app: APP_B, allowed: {core: true}}]}); + rights.isPermissionSubset(childOnB, {permission: readCoreOnA}).should.equal(false); + rights.isPermissionSubset(childOnB, member).should.equal(true); + }); + + it("refuses a feature the ceiling does not hold", function() { + var update = permission({userApps: [APP_A], grants: [{type: "u", app: APP_A, allowed: {core: true}}]}); + rights.isPermissionSubset(update, member).should.equal(false); + }); + + it("refuses an all grant from a ceiling that holds only named features", function() { + //"all" covers features that do not exist yet, so only an "all" holder may pass it on + var readAll = permission({userApps: [APP_A], grants: [{type: "r", app: APP_A, all: true}]}); + rights.isPermissionSubset(readAll, member).should.equal(false); + rights.isPermissionSubset(readAll, adminOfA).should.equal(true); + rights.isPermissionSubset(readAll, globalAdmin).should.equal(true); + }); + + it("refuses app administration unless the ceiling administers that app", function() { + var adminChild = permission({adminApps: [APP_A]}); + rights.isPermissionSubset(adminChild, member).should.equal(false); + rights.isPermissionSubset(adminChild, adminOfA).should.equal(true); + }); + + it("ignores entries that grant nothing", function() { + //the permission editor emits an entry for every visible app, most of them empty + var editorShaped = permission({userApps: [APP_A], grants: [{type: "r", app: APP_A, allowed: {core: true}}]}); + editorShaped.d[APP_B] = {all: false, allowed: {}}; + editorShaped.c[APP_B] = {all: false, allowed: {core: false}}; + rights.isPermissionSubset(editorShaped, {permission: readCoreOnA}).should.equal(true); + }); + + it("refuses anything that is not a permission object", function() { + rights.isPermissionSubset(undefined, member).should.equal(false); + rights.isPermissionSubset([], member).should.equal(false); + }); + }); + + describe("intersectPermission", function() { + it("strips global admin, so a scoped token cannot act as one", function() { + var scoped = rights.intersectPermission(globalAdmin, readCoreOnA); + scoped.global_admin.should.equal(false); + rights.hasReadRight("core", APP_A, scoped).should.equal(true); + rights.hasReadRight("core", APP_B, scoped).should.equal(false); + }); + + it("keeps only what the token and the owner both allow", function() { + //the token asks for everything; the owner has only named features + var wide = permission({ + userApps: [APP_A], + grants: [ + {type: "r", app: APP_A, all: true}, + {type: "d", app: APP_A, all: true} + ] + }); + var scoped = rights.intersectPermission(member, wide); + rights.hasReadRight("core", APP_A, scoped).should.equal(true); + rights.hasReadRight("events", APP_A, scoped).should.equal(true); + rights.hasDeleteRight("core", APP_A, scoped).should.equal(false); + }); + + it("drops access the owner lost after the token was created", function() { + var reduced = { + global_admin: false, + permission: permission({ + userApps: [APP_A], + grants: [{type: "r", app: APP_A, allowed: {core: true}}] + }) + }; + var tokenOnBoth = permission({ + userApps: [APP_A, APP_B], + grants: [ + {type: "r", app: APP_A, allowed: {core: true}}, + {type: "r", app: APP_B, allowed: {core: true}} + ] + }); + var scoped = rights.intersectPermission(reduced, tokenOnBoth); + rights.hasReadRight("core", APP_A, scoped).should.equal(true); + rights.hasReadRight("core", APP_B, scoped).should.equal(false); + rights.getUserApps(scoped).indexOf(APP_B).should.equal(-1); + }); + + it("does not leave an app administrator administering it through a narrower token", function() { + var scoped = rights.intersectPermission(adminOfA, readCoreOnA); + rights.hasAdminAccess(scoped, APP_A).should.equal(false); + rights.hasReadRight("core", APP_A, scoped).should.equal(true); + rights.hasDeleteRight("core", APP_A, scoped).should.equal(false); + }); + + it("reports only the apps the token reaches", function() { + var scoped = rights.intersectPermission(member, readCoreOnA); + rights.getUserApps(scoped).should.eql([APP_A]); + }); + }); + + describe("isScopedCredential", function() { + it("treats an api_key request as unscoped", function() { + rights.isScopedCredential({}).should.equal(false); + }); + + it("treats a session style token as unscoped", function() { + rights.isScopedCredential({token_data: {app: "", endpoint: ""}}).should.equal(false); + rights.isScopedCredential({token_data: {app: [], endpoint: []}}).should.equal(false); + }); + + it("treats a permission scoped or legacy restricted token as scoped", function() { + rights.isScopedCredential({token_data: {token_permission: readCoreOnA}}).should.equal(true); + rights.isScopedCredential({token_data: {app: [APP_A], endpoint: ""}}).should.equal(true); + rights.isScopedCredential({token_data: {app: "", endpoint: ["^/o/users"]}}).should.equal(true); + }); + }); +}); From 7d70a17559914ed47929c2deec490ac55e5dd0c6 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 10:24:05 +0300 Subject: [PATCH 2/9] security(core): require a scoped token to state the permissions it grants A token created without an explicit permission carries no token_permission, and a token with no token_permission is bounded only by its owner. A scoped credential could therefore create a child wider than itself by simply omitting the parameter: the subset check had no permission object to compare and so never ran, which meant the omission itself was the way around it. Refuse instead - a credential that is itself scoped has to say what it grants. Also brings the existing token-list test to the behaviour this model defines. /o/token/list returns whole token documents and a document's _id is the token itself, so listing is restricted to a full-permission credential; an endpoint-scoped token is refused there even when its endpoint matches. The login test now supplies the permission the token already holds, so what it asserts is the login grant being refused rather than the missing permission. Found by the regression tests added with the permission model. Co-Authored-By: Claude Opus 4.8 --- api/utils/requestProcessor.js | 10 ++++++++++ test/2.api/16.token.manager.js | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/api/utils/requestProcessor.js b/api/utils/requestProcessor.js index 4d24d76d6fc..da80dcbf212 100644 --- a/api/utils/requestProcessor.js +++ b/api/utils/requestProcessor.js @@ -2629,6 +2629,16 @@ const processRequest = (params) => { } } + // A scoped credential has to say what it is granting. A token with no + // token_permission is bounded only by its owner, so a child created without + // one would reach everything the owner can - wider than the parent that + // created it. The subset check above cannot catch this, because there is no + // permission object to compare; the omission itself is the escalation. + if (!tokenPermission && creatorToken && creatorToken.token_permission) { + common.returnMessage(params, 403, "A scoped token must state the permissions it grants"); + return; + } + // Login is a capability of the token, never of its purpose string, and it is // only ever passed on by a credential that holds it, to a child that is not // narrowed. That makes a scoped token unable to produce a session, which is diff --git a/test/2.api/16.token.manager.js b/test/2.api/16.token.manager.js index 29106c75aab..f5b2e6e6bcf 100644 --- a/test/2.api/16.token.manager.js +++ b/test/2.api/16.token.manager.js @@ -201,10 +201,14 @@ describe('Testing token manager', function() { validate_token(token1, {"app": [APP_ID], "multi": true, "ttl": 300, "endpoint": ["/o/token"], "purpose": "My test token"}, 1, done); }); + //Deliberate change of behaviour: /o/token/list returns whole token documents, and a + //document's _id is the token itself, so listing hands the caller credentials that may be + //wider than the one it used. Token listing is therefore restricted to a full-permission + //credential, and this endpoint-scoped token is refused even though its endpoint matches. it('using token' + token1, function(done) { request .get('/o/token/list?auth_token=' + token1) - .expect(200) + .expect(403) .end(function(err, res) { if (err) { return done(err); @@ -491,8 +495,10 @@ describe('Testing token manager', function() { }); it('the limited token cannot be granted login permission', function(done) { + //the permission the token already holds is supplied, so a narrowing child is the only + //thing being asked for beyond login - what is refused here is the login grant itself request - .get('/i/token/create?auth_token=' + limitedToken + '&multi=true&ttl=300&can_login=true') + .get('/i/token/create?auth_token=' + limitedToken + '&multi=true&ttl=300&can_login=true&permission=' + readCorePermission(APP_ID)) .expect(403) .end(function(err, res) { if (err) { From 3c81f389c5883470302929140dd71e67669569f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 17:37:56 +0300 Subject: [PATCH 3/9] fix(token-manager): lay out the create-token drawer correctly Three layout defects in the permission drawer. - The two permission cards overflowed the drawer. is-autosized gives each width:100%, and a flex item's default min-width:auto stops it shrinking below its own text, so the card with the longer description pushed the other one off screen. They now share the line evenly and are allowed to shrink. - The feature grid's column headers and its per-feature checkboxes were laid out independently, flex-end against space-between, so the checkboxes did not sit under the headers. Both now use one name column plus four equal cells, and in the header the column name sits above its checkbox rather than beside it, since inline the label widens the cell and pushes the checkbox off the centre the rows align to. - The app selector was a plain el-select and showed no app icon. It now uses cly-app-select, which is the component that renders them. That last one needs cly-checklistbox to accept an option-prefix slot. cly-select-x forwards the slot only to cly-listbox, which serves single-select, so no multi-select app dropdown in the dashboard can show icons today. The slot is additive and renders only when a caller passes one, so every existing checklistbox is unchanged. The token-manager stylesheet existed but was empty and was never imported by manifest.scss. Co-Authored-By: Claude Opus 4.8 --- .../javascripts/countly.views.js | 10 +-- .../core/token-manager/stylesheets/_main.scss | 80 +++++++++++++++++++ .../templates/token-manager-drawer.html | 57 +++++++++---- .../countly/vue/components/input.js | 7 +- .../countly/vue/templates/selectx.html | 3 + .../stylesheets/styles/blocks/_select.scss | 15 +++- .../public/stylesheets/styles/manifest.scss | 1 + .../public/stylesheets/styles/manifest2.css | 2 +- 8 files changed, 146 insertions(+), 29 deletions(-) diff --git a/frontend/express/public/core/token-manager/javascripts/countly.views.js b/frontend/express/public/core/token-manager/javascripts/countly.views.js index 56787c24266..be20d582dac 100644 --- a/frontend/express/public/core/token-manager/javascripts/countly.views.js +++ b/frontend/express/public/core/token-manager/javascripts/countly.views.js @@ -19,8 +19,7 @@ { label: CV.i18n('token_manager.limit.h'), value: "hours" }, { label: CV.i18n('token_manager.limit.d'), value: "days" }, { label: CV.i18n('token_manager.limit.m'), value: "months" } - ], - "apps": this.appsData(), + ] } }; }, @@ -32,13 +31,6 @@ }); }, methods: { - appsData: function() { - var apps = []; - for (var appId in countlyGlobal.apps) { - apps.push({ value: appId, name: countlyGlobal.apps[appId].name }); - } - return apps; - }, featureBeautifier: function(feature) { return countlyAuth.featureBeautifier(feature); }, diff --git a/frontend/express/public/core/token-manager/stylesheets/_main.scss b/frontend/express/public/core/token-manager/stylesheets/_main.scss index e69de29bb2d..5ea14cd43af 100644 --- a/frontend/express/public/core/token-manager/stylesheets/_main.scss +++ b/frontend/express/public/core/token-manager/stylesheets/_main.scss @@ -0,0 +1,80 @@ +.token-manager-drawer { + // Two bordered radio cards sharing one line. `is-autosized` sets width:100%, and a flex + // item's default min-width:auto stops it shrinking below its own text, so the card with the + // longer description pushes the other one out of the drawer. Let them split the line evenly + // and allow both to shrink. + &__choice { + .el-radio.is-autosized { + flex: 1 1 0; + min-width: 0; + } + + .el-radio__label { + white-space: normal; + } + } + + // Feature permission grid. The column headers and the per-feature checkboxes are separate + // rows, so they line up only when both use the same column widths: a fixed-width name + // column, then four equal cells. + &__permission-header, + &__permission-row { + display: flex; + flex-direction: row; + align-items: center; + } + + &__permission-header { + border-bottom: 1px solid #ebebeb; + padding-bottom: 10px; + margin-bottom: 10px; + } + + &__permission-row { + height: 30px; + } + + &__feature-name { + width: 35%; + display: flex; + align-items: center; + justify-content: flex-start; + } + + &__feature-permissions { + width: 65%; + display: flex; + } + + // Equal cells, and the checkbox centred in each, so a row checkbox sits under the header + // checkbox above it. + &__permission-box { + flex: 1 1 0; + min-width: 0; + display: flex; + align-items: center; + justify-content: center; + + .el-checkbox { + margin-right: 0; + } + } + + // In the header the column name sits above its checkbox rather than beside it. Inline, the + // label widens the cell and pushes the checkbox off the centre the rows are aligned to, so + // the header boxes would sit ~20px left of the column they head. + &__permission-header &__permission-box { + .el-checkbox { + display: flex; + flex-direction: column-reverse; + align-items: center; + } + + .el-checkbox__label { + font-size: 11px; + padding-left: 0; + margin-bottom: 4px; + line-height: 1; + } + } +} diff --git a/frontend/express/public/core/token-manager/templates/token-manager-drawer.html b/frontend/express/public/core/token-manager/templates/token-manager-drawer.html index dffe9c3e385..ac70f56e8d1 100644 --- a/frontend/express/public/core/token-manager/templates/token-manager-drawer.html +++ b/frontend/express/public/core/token-manager/templates/token-manager-drawer.html @@ -15,7 +15,7 @@

{{i18n('token_manager.permission.title')}}

{{i18n('token_manager.permission.description')}}

-
+
{{i18n('token_manager.permission.full-label')}}

{{i18n('token_manager.permission.full-text')}}

@@ -36,10 +36,14 @@

{{i18n('token_manager.select-apps')}}

- - - - + +
@@ -50,19 +54,38 @@ -
- {{i18n('management-users.create').toUpperCase()}} - {{i18n('management-users.read').toUpperCase()}} - {{i18n('management-users.update').toUpperCase()}} - {{i18n('management-users.delete').toUpperCase()}} +
+
+
+
+ {{i18n('management-users.create').toUpperCase()}} +
+
+ {{i18n('management-users.read').toUpperCase()}} +
+
+ {{i18n('management-users.update').toUpperCase()}} +
+
+ {{i18n('management-users.delete').toUpperCase()}} +
+
-
-
{{featureBeautifier(feature)}}
-
- - - - +
+
{{featureBeautifier(feature)}}
+
+
+ +
+
+ +
+
+ +
+
+ +
diff --git a/frontend/express/public/javascripts/countly/vue/components/input.js b/frontend/express/public/javascripts/countly/vue/components/input.js index 028b5718bef..cf4fbbf013a 100755 --- a/frontend/express/public/javascripts/countly/vue/components/input.js +++ b/frontend/express/public/javascripts/countly/vue/components/input.js @@ -698,7 +698,12 @@ :key="option.value + \'-\' + index"\ v-for="(option, index) in searchedOptions">\
\ - {{option.label}}\ + \ + \ + \ + {{option.label}}\ + \ + \
\ \ \ diff --git a/frontend/express/public/javascripts/countly/vue/templates/selectx.html b/frontend/express/public/javascripts/countly/vue/templates/selectx.html index 9234f892523..e2929f28604 100644 --- a/frontend/express/public/javascripts/countly/vue/templates/selectx.html +++ b/frontend/express/public/javascripts/countly/vue/templates/selectx.html @@ -113,6 +113,9 @@ :options="getMatching(tab.options)" @change="handleValueChange" v-model="innerValue"> + .el-button{display:flex;align-items:center}.el-button-group>.el-select:first-child .el-button{display:flex;align-items:center}.cly-countly-icon-solid{width:20px;height:20px;background-image:url("../images/icons/countly-icon-solid.svg")}.cly-countly-icon-outline{width:20px;height:20px;background-image:url("../images/icons/countly-icon-outline.svg")}.cly-countly-icon-outline-trash-16px{background-position:99px 962px}.cly-countly-icon-outline-code-16px{background-position:99px 674px}.cly-countly-icon-outline-external-link-16px{background-position:419px 674px}.cly-countly-icon-outline-download-16px{background-position:299px 819px}.cly-countly-icon-outline-x-16px{background-position:139px 1107px}.cly-countly-icon-outline-document-download-16px{background-position:179px 1058px}.cly-countly-icon-outline-exclamation-circle-16px{background-position:339px 868px}.cly-countly-icon-outline-plus-circle-16px{background-position:299px 867px}.cly-countly-icon-outline-globe-16px{background-position:219px 1010px}.cly-countly-icon-outline-user-group-16px{background-position:300px 1202px}*{outline:none}html{height:100%;width:100%}body{height:100%;width:100%;margin:0;padding:0;overflow:auto;background-color:#f9f9f9;user-select:text;font-family:Inter,Ubuntu,Helvetica,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1{font-size:32px;line-height:48px;font-weight:500;margin:0;padding:10;color:#333c48}h2{font-size:24px;line-height:32px;font-weight:500;margin:0;padding:0;color:#333c48}h3{font-size:20px;line-height:30px;font-weight:500;margin:0;padding:0;color:#333c48}h4{font-size:16px;line-height:24px;font-weight:500;margin:0;padding:0;color:#333c48}h5{font-size:14px;line-height:20px;font-weight:500;margin:0;padding:0;color:#333c48}h6{font-size:14px;line-height:18px;font-weight:500;margin:0;padding:0;color:#333c48}textarea,input,p,h1,h2,h3,h4,h5,h6,button{font-family:Inter !important}.el-table th{padding:9px 0px;box-sizing:border-box;text-transform:uppercase;font-size:12px;font-style:normal;font-weight:500;border-bottom-width:2px}.el-table th .cell{line-height:16px;letter-spacing:.5px}.el-table th:hover .sort-caret.ascending{border-bottom-color:#005def}.el-table th:hover .sort-caret.descending{border-top-color:#005def}.el-table th.is-leaf{border-bottom-width:2px;border-top:1px solid #eef2f5}.el-table td{padding:14px 0px;font-style:normal;font-weight:normal;font-size:14px;box-sizing:border-box}.el-table td .cell{line-height:20px}.el-table.el-table--has-options td .cell{line-height:23px}.el-table th:first-child .cell,.el-table td:first-child .cell{padding-left:16px}.el-table th:last-child .cell,.el-table td:last-child .cell{padding-right:16px}.el-table .caret-wrapper{height:15px}.el-table .sort-caret{border-width:4px}.el-table .sort-caret.ascending{top:-2px}.el-table .sort-caret.descending{bottom:-1px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#005def}.el-table .descending .sort-caret.descending{border-top-color:#005def}.el-table .cell{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.el-table .cell>.el-checkbox,.el-table .cell>.el-switch,.el-table .cell>.el-radio{overflow:unset}.el-table table{width:0px}.el-radio.is-autosized{padding:16px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized.is-bordered+.el-radio.is-autosized.is-bordered{margin-left:10px}.el-radio.is-autosized.is-bordered{border-color:#cfd6e4;display:flex;align-items:center}.el-radio.is-autosized.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized.is-bordered.is-checked{border-color:#0166d6}.el-radio.is-autosized-vstack{padding:12px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized-vstack .el-radio__label{justify-content:space-between;display:flex;width:100%;align-items:baseline}.el-radio.is-autosized-vstack.is-bordered{align-items:center}.el-radio.is-autosized-vstack.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized-vstack.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized-vstack.is-bordered.is-multiline .el-radio__label{padding-top:2px}.el-radio.is-autosized-vstack.is-bordered+.el-radio.is-autosized-vstack.is-bordered{margin-left:0;margin-top:7px}.el-radio.is-bordered{border:1px solid #cfd6e4}.el-radio:hover:not(.is-disabled) .el-radio__label{color:inherit}.el-radio.is-checked:not(.is-disabled):hover .el-radio__label{color:inherit}.el-radio__input.is-checked+.el-radio__label{color:inherit}.el-collapse.is-bordered-box{border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.el-collapse.is-bordered-box .el-collapse-item__header{border-radius:4px;padding:0rem 1.5rem 0rem 1.5rem}.el-collapse.is-bordered-box .el-collapse-item__header.is-active{border-bottom-color:#ececec}.el-collapse.is-bordered-box .el-collapse-item__wrap{background-color:rgba(0,0,0,0)}.el-collapse.is-bordered-box .el-collapse-item__content{margin:0rem 1.5rem 0rem 1.5rem}.el-switch__label *{font-weight:normal;color:#a7aeb8;font-size:12px}.el-input.is-adaptive .el-input__inner{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:10px;vertical-align:middle}.el-select .el-input.is-arrow .el-input__inner{padding-right:30px}.el-button.is-wireframe{background:rgba(0,0,0,0);border:1px dotted #0166d6;box-sizing:border-box;box-shadow:0px 2px 4px rgba(1,122,255,.07)}.el-button.el-button--text.is-danger{color:#d23f00}.el-button.el-button--text.is-danger:hover{background-color:#f6f6f6}.el-button.is-light-blue{box-shadow:none;-webkit-box-shadow:none;border:none;font-weight:500;height:32px}.el-button.is-light-blue:not(.is-disabled){color:#0166d6;background-color:#e1efff}.el-button.is-light-blue:not(.is-disabled):hover{background-color:#cce0f7}.el-button-group>.el-select{float:left}.el-button-group>.el-select:first-child .el-button{border-top-right-radius:0;border-bottom-right-radius:0;-webkit-box-shadow:none;box-shadow:none}.el-button-group>.el-select:not(:last-child){margin-right:-1px}.el-button-group>.el-select:active,.el-button-group>.el-select:focus,.el-button-group>.el-select:hover{z-index:1}.el-button-group>.el-select:active .el-button,.el-button-group>.el-select:focus .el-button,.el-button-group>.el-select:hover .el-button{z-index:1}.el-input-number.is-slim .el-input__inner{padding-left:5px;padding-right:26px}.el-input-number.is-slim.el-input-number--small .el-input-number__decrease,.el-input-number.is-slim.el-input-number--small .el-input-number__increase{width:22px;font-size:14px}.el-tabs--card>.el-tabs__header{margin:0}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap{margin-bottom:-2px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap.is-scrollable{border-bottom:none;border-top-right-radius:4px;border-top-left-radius:4px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next{background:linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{background:linear-gradient(270deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{opacity:.85}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next:hover,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev:hover{opacity:1}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-top-left-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{border-top-right-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item{background-color:#fcfcfc;padding:0;height:auto;text-align:left;line-height:32px;border-bottom:2px solid #ececec}.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#0166d6;background-color:#fff}.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0px}.el-radio-group.is-full{display:flex}.el-radio-group.is-full .el-radio-button{flex-grow:1}.el-radio-group.is-full .el-radio-button__inner{width:100%}.el-dropdown-menu__item{padding:7px 6px}.el-dropdown-menu__item>i.cly-icon-outline{padding:2px 7px}.el-select-dropdown .el-scrollbar__bar{opacity:1 !important;right:0}.el-select-dropdown__item{padding:7px 6px}.el-tiptap-editor{border-radius:4px}.el-tiptap-editor .el-tiptap-editor__menu-bar{border-color:#cfd6e4}.el-tiptap-editor .el-tiptap-editor__menu-bar::before{background-color:#cfd6e4}.el-tiptap-editor>.el-tiptap-editor__content{border:1px solid #cfd6e4 !important;border-top:0 !important;border-bottom:0 !important}.el-tiptap-editor>.el-tiptap-editor__content pre code{font-family:"Courier New"}.el-tiptap-editor .el-tiptap-editor__footer{border-color:#cfd6e4}.el-tiptap-editor .border-top-radius{border-top-left-radius:4px !important;border-top-right-radius:4px !important}.el-tiptap-editor .border-bottom-radius{border-bottom-left-radius:4px !important;border-bottom-right-radius:4px !important}.el-tiptap-editor .fa-icon{fill:#333c48}.el-tiptap-editor__content{overflow-x:unset !important}.el-tiptap-editor__content>pre>code{font-family:"Courier New" !important}.el-tiptap-editor__content span>span{background-color:inherit}.el-tiptap-editor__content hr{width:100%}.el-dialog.el-tiptap-edit-link-dialog .el-button.is-round{border-radius:4px}.el-dialog.el-tiptap-edit-link-dialog .el-button.el-button--primary{border-color:#12af51;background-color:#12af51}.el-checkbox__input .el-checkbox__inner{color:#fff;text-align:center}.el-checkbox__input.is-checked .el-checkbox__inner::before{content:"" !important;font-family:"countly-icons-outline" !important;border:none !important;position:absolute;top:0px;width:15px;left:0px}.el-checkbox__input.is-checked .el-checkbox__inner::after{border:none !important}.el-checkbox__input.is-checked.is-disabled .el-checkbox__inner{color:#d0d0d0}.el-checkbox__inner::after{display:none}.el-checkbox.is-checked .el-checkbox__inner::after{display:block}.el-upload__folder-preview-content{height:32px}.el-upload-dragger{background-color:#fcfcfc;display:flex;flex-direction:column;justify-content:center}.el-upload-dragger .fa-folder{line-height:0}.el-upload-list__item-name{background-color:#fff;width:100%;border:1px solid #ececec;border-radius:5px;height:68px;padding-left:unset;cursor:default !important}.el-upload-list__item-remove{margin-left:auto;margin-right:24px;cursor:pointer !important}.el-upload-list__item-preview .cly-io-document-text{font-size:20px;color:#000;margin-right:4px}.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#000}.bu-level:not(:last-child){margin-bottom:0px}.bu-tag.is-slim{padding:0 .5em;height:1.5em}.bu-tag.is-legend{padding:0;height:.5em;width:1em;border-radius:3px}.bu-tag.is-curved{border-radius:67px;height:16px;padding-left:4px;padding-right:4px;min-width:12px}.vjs-tree{padding:10px}.vjs-value-boolean,.vjs-value-number{color:#31acb4}.vjs-value-string{color:#6c47ff}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f0fb}.cly-vue-theme-clydef{background-color:#f8f9fa}#main-views-container{height:100%;width:100%;overflow:auto}#main-views-container .main-view{min-width:768px;min-height:400px;width:100%;padding:0px 0 35px 0 !important;transition:width .55s;will-change:width;overflow:auto}.cly-vue-main{padding:0px 24px;margin:0}.cly-vue-section--has-configurator-skin .cly-vue-section__content{background:#fff;border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.cly-vue-section--has-configurator-skin .cly-vue-section__content .cly-vue-section__sub{border-top:none !important;border-bottom:1px solid #ececec;align-items:center;display:flex}.cly-vue-section--has-default-skin .cly-vue-section__content{border-top:1px solid #ececec;border-bottom:1px solid #ececec}.cly-vue-section .cly-vue-section__content-config{border-bottom:1px solid #ececec}.cly-vue-section:not(:last-child){margin-bottom:32px}.cly-vue-header{padding:24px 24px;margin-bottom:32px;border-bottom:1px solid #ececec;position:relative}.cly-vue-header__level{padding-top:8px;padding-bottom:12px}.cly-vue-header__level--no-pt{padding-top:0px}.cly-vue-header__level--no-pb{padding-bottom:0px}.cly-vue-header--no-mb{margin-bottom:0px}.cly-vue-header--no-bb{border-bottom:none}.cly-vue-header+div>.cly-vue-tabs{background-color:#fff;border-bottom:1px solid #ececec;margin-bottom:32px;padding:0px 24px}.cly-vue-select-x__pop .cly-vue-listbox{background-color:rgba(0,0,0,0) !important}.cly-vue-select-x__pop .el-tabs__active-bar{background-color:#0166d6}.cly-vue-select-x__pop .el-tabs__nav-wrap::after{background-color:rgba(0,0,0,0)}.cly-vue-select-x__pop .el-tabs__nav-scroll{margin:0 14px}.cly-vue-select-x__pop .el-tabs__header{margin:0 0 1px 0;z-index:2000}.cly-vue-select-x__pop .el-tabs__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:40px;opacity:.12}.cly-vue-select-x__pop--hidden-tabs .el-tabs__header::after{top:0px}.cly-vue-select-x__pop--hidden-tabs .el-tabs__nav-scroll{display:none}.cly-vue-select-x__pop--hidden-header .cly-vue-select-x__header{padding:0}.cly-vue-select-x__pop--hidden-tabs.cly-vue-select-x__pop--hidden-header .el-tabs__header::after{background:none;height:0;width:0}.cly-vue-select-x__title{font-weight:500;font-size:16px;line-height:24px;color:#333c48;padding-bottom:16px}.cly-vue-select-x__header-slot{padding-bottom:16px}.cly-vue-select-x__header{padding:16px}.cly-vue-select-x__header input[type=text]{background-color:#f6f6f6}.cly-vue-select-x__footer{border-top:1px solid #ececec}.cly-vue-select-x__commit-section{float:right;margin:16px}.cly-vue-select-x__pop--has-single-option .cly-vue-select-x__header-slot,.cly-vue-select-x__pop--has-slim-header .cly-vue-select-x__header-slot{padding:0}.cly-vue-select-x__pop--has-single-option .el-tabs__header::after{content:none}.cly-vue-select-x .el-select-head{width:100%}.cly-vue-listbox{background-color:#fff}.cly-vue-listbox label.el-checkbox{width:100%;margin-left:8px}.cly-vue-listbox.is-expandable{transition:width 200ms;width:100%;z-index:100}.cly-vue-listbox.is-expanded{width:130%;position:relative;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.08);box-shadow:0 1px 4px rgba(0,0,0,.08)}.cly-vue-listbox.cly-vue-listbox--bordered{border-radius:4px;border:1px solid #ececec}.cly-vue-listbox .cly-vue-listbox__no-data{padding:8px;line-height:20px;font-weight:500;color:#333c48;font-size:14px}.cly-vue-listbox .el-checkbox-group{overflow:hidden}.cly-vue-listbox .el-checkbox__label{line-height:20px;font-weight:400;color:#333c48;max-width:330px !important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom}.cly-vue-listbox .el-checkbox__input.is-checked+.el-checkbox__label{color:#333c48}.cly-vue-listbox .drag-handler{visibility:hidden;margin-right:8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cly-vue-listbox__header{margin:0 0 1px 0;z-index:1997;border-bottom:1px solid #ececec;position:relative}.cly-vue-listbox__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:57px;left:0;opacity:.12}.cly-vue-listbox .cly-vue-listbox__group{font-size:12px;line-height:14px;background-color:#f6f6f6;border-bottom:solid 1px #ececec;max-height:32px;display:flex;align-items:center;padding:8px}.cly-vue-listbox .cly-vue-listbox__item{display:flex;cursor:pointer;align-items:center;justify-content:space-between}.cly-vue-listbox .cly-vue-listbox__item.selected{background-color:#0166d6}.cly-vue-listbox .cly-vue-listbox__item.selected *{color:#fff}.cly-vue-listbox .cly-vue-listbox__item .cly-vue-listbox__remove-option{display:none}.cly-vue-listbox .cly-vue-listbox__item.hover .cly-vue-listbox__remove-option{display:block}.cly-vue-listbox .cly-vue-listbox__item-content{width:100%}.cly-vue-listbox__item-label{max-width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-listbox--disabled .cly-vue-listbox__item{background-color:#f6f6f6}.cly-vue-listbox--disabled .cly-vue-listbox__item *{color:#a7aeb8}.cly-vue-listbox--disabled .cly-vue-listbox__item.selected{opacity:.5}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover{background-color:#f6f6f6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .drag-handler{visibility:visible}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix *{color:#0166d6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item .cly-vue-listbox__remove-option:hover{color:#0166d6}.cly-vue-listbox--has-default-skin .cly-vue-listbox__item{padding:8px;border-radius:4px;line-height:16px}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item{padding:8px;height:55px;box-sizing:border-box;border-bottom:1px solid #ececec}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected{border-left:2px solid #0166d6;background-color:#f6f6f6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected *{color:#0166d6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item:last-child{border-bottom:none}.cly-vue-listbox--has-margin .cly-vue-listbox__item{margin:8px}.cly-fields-select.default-skin{display:inline-block}.cly-fields-select.default-skin .el-input__inner::placeholder{color:#000}.cly-fields-select.default-skin .fields-select-body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:0px;z-index:100;border:1px solid #d0d0d0;border-radius:2px;padding:16px;width:max-content}.cly-fields-select.default-skin .fields-select-body .controls{float:right;margin-top:10px}.cly-fields-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-fields-select__reset{float:right;font-size:12px;padding-bottom:26px;padding-top:0px;color:#d23f00;cursor:pointer;line-height:20px}.cly-fields-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-fields-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-fields-select__confirm{background-color:#12af51;color:#fff}.cly-fields-select__cancel{background:#f6f6f6}.cly-fields-select__dropdown .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin{display:inline-block}.cly-multi-select.default-skin .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin .cly-multi-select__body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:-2px;left:-2px;z-index:100;border:1px solid #d0d0d0;border-radius:4px;padding:16px;width:max-content}.cly-multi-select.default-skin .cly-multi-select__controls{float:right;margin-top:10px}.cly-multi-select__title-wrapper{margin-bottom:30px}.cly-multi-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-multi-select__reset{float:right;font-size:12px;padding:4px 8px;color:#d23f00;cursor:pointer;line-height:20px}.cly-multi-select__reset span{height:20px;line-height:20px}.cly-multi-select__reset:hover{background:#f6f6f6}.cly-multi-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-multi-select .cly-multi-select__confirm-button{margin-left:4px}.cly-multi-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-multi-select__dropdown .el-input__inner::placeholder{color:#000}.cly-vue-dropdown__pop{padding:0px;width:fit-content}.cly-vue-dropdown__pop-container{word-break:initial}.cly-vue-dropdown__dropdown-icon{width:16px;line-height:16px;height:16px;background-size:16px 16px;border-radius:4px;background-position:center;background-color:#017aff;display:inline-block}.cly-vue-more-options .el-button{border:1px solid #cfd6e4}.cly-vue-more-options .el-button .is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.cly-vue-eldatatable.silent-loading .el-loading-spinner{visibility:hidden}.cly-vue-eldatatable.silent-loading .el-loading-mask{display:none !important}.cly-vue-eldatatable.display-mode--list .el-table{background-color:unset}.cly-vue-eldatatable.display-mode--list .el-table__body{border-collapse:separate;border-spacing:0 8px}.cly-vue-eldatatable.display-mode--list .el-table__row{cursor:pointer}.cly-vue-eldatatable.display-mode--list .el-table__row td{cursor:pointer;height:56px;border-top:1px solid #ececec !important;border-bottom:2px solid #ececec !important;background-color:#fff !important;padding:18px 0px}.cly-vue-eldatatable.display-mode--list .el-table__row td:first-child{border-left:1px solid #ececec !important;border-radius:4px 0 0 4px !important}.cly-vue-eldatatable.display-mode--list .el-table__row td:last-child{border-right:1px solid #ececec !important;border-radius:0 4px 4px 0 !important}.cly-vue-eldatatable.display-mode--list .el-table__row td .cell{line-height:20px}.cly-vue-eldatatable.display-mode--list .el-table__row td.drag-icon .cell{text-overflow:unset !important}.cly-vue-eldatatable.display-mode--list .el-table thead tr{background-color:unset !important}.cly-vue-eldatatable.display-mode--list .el-table th{background-color:unset !important;border:none !important;padding:0 !important;color:#81868d !important}.cly-vue-eldatatable.display-mode--list .el-table__fixed-right::before{height:0 !important}.cly-vue-eldatatable__header{height:56px;border-left:none;border-right:none;box-sizing:border-box;padding:12px;border-top:1px solid #ececec}.cly-vue-eldatatable__header--white{background-color:#fff;color:#333c48;font-size:13px}.cly-vue-eldatatable__export--extended::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:185px;left:0;opacity:.12}.cly-vue-eldatatable__export--fileExport{border-top:1px solid #e2e4e8}.cly-vue-eldatatable__export--radio-button .el-radio-button{width:99px;display:inline-grid}.cly-vue-eldatatable__export--search input[type=text]{background-color:#f6f6f6}.cly-vue-eldatatable__search--grey input{background-color:#fbfdfe}.cly-vue-eldatatable__footer{height:40px;box-shadow:0px 2px 0px #eef2f5;border-left:none;border-right:none;box-sizing:border-box;padding:0px 12px}.cly-vue-eldatatable__footer--white{background-color:#fff;color:#808a9d;font-size:13px}.cly-vue-eldatatable .undo-row{position:absolute;left:0;padding:9px 0px;background-color:#ffd7d6;color:#2b2b2b;width:100%;height:100%;top:0;z-index:999;vertical-align:middle;display:flex;align-items:center;justify-content:center}.cly-vue-eldatatable .undo-row a{color:#017aff;cursor:pointer}.cly-vue-eldatatable .el-table-column--options .cly-vue-more-options{position:absolute;top:calc(50% - 16px);right:calc(50% - 20px)}.cly-vue-eldatatable div.cell{padding-left:16px;padding-right:8px}.cly-vue-eldatatable__empty-slot{height:200px}.cly-vue-table{width:100%}.cly-vue-table thead{background-color:#f6f6f6;border-top:1px solid #ececec;border-bottom:2px solid #ececec}.cly-vue-table thead th{color:#333c48;font-weight:500;font-size:12px;padding:9px;text-align:left}.cly-vue-table tbody td{padding:0px 9px}.cly-vue-chart{position:relative}.cly-vue-chart .bu-level{padding:0 20px 0 33px}.cly-progress-bar-container{width:100%}.cly-progress-bar-container.has-min-bradius .first-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:4px;border-top-left-radius:4px}.cly-progress-bar-container.has-min-bradius .last-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:4px;border-top-right-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__outer{border-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__inner{border-radius:4px}.cly-progress-bar-stack-container{float:left}.progress-bar-stack .el-progress-bar__inner{border-radius:0px}.first-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:0px;border-top-right-radius:0px}.middle-progress-bar-stack .el-progress-bar__outer{border-radius:0px}.last-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:0px;border-top-left-radius:0px}.cly-vue-tabs__primary-tab-list{padding:24px;box-sizing:border-box}.cly-vue-tabs__tab{height:34px;padding:10px 12px;display:inline-block;box-sizing:border-box}.cly-vue-tabs__tab--default{color:#81868d;line-height:14px;font-weight:500;font-size:14px;cursor:pointer}.cly-vue-tabs__tab--primary{border-radius:6px}.cly-vue-tabs__tab--primary:hover{color:#0166d6}.cly-vue-tabs__tab--secondary:hover{color:#333c48}.cly-vue-tabs__tab--primary-active{color:#0166d6;background-color:#e1efff}.cly-vue-tabs__tab--secondary-active{color:#333c48;border-bottom:2px solid #0166d6}.cly-vue-chart{width:100%;height:100%}.cly-vue-chart__echart{box-sizing:border-box;display:inline-block;width:100%}.cly-vue-chart--padded .cly-vue-chart__echart{padding-top:20px}.cly-vue-chart--full .cly-vue-chart__echart{padding:0}.cly-vue-chart-legend{display:inline-block;width:100%}.cly-vue-chart-legend__primary,.cly-vue-chart-legend__secondary{white-space:nowrap;overflow:auto;box-sizing:border-box;height:100%}.cly-vue-chart-legend__secondary--text-center{text-align:center}.cly-vue-chart-legend__p-series{display:inline-block;margin-left:64px;cursor:pointer}.cly-vue-chart-legend__p-series:first-child{margin-left:36px}.cly-vue-chart-legend__s-series{display:inline-block;margin-left:48px;cursor:pointer}.cly-vue-chart-legend__s-series:first-child{margin-left:0px}.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-rectangle,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-percentage{color:#a7aeb8}.cly-vue-chart-legend__second-row{margin-top:3px}.cly-vue-chart-legend__p-checkbox{height:16px;width:16px;border:1px solid #a7aeb8;display:inline-block;box-shadow:inset 0 0 0px 1.5px #fff;border-radius:4px;vertical-align:middle;box-sizing:border-box}.cly-vue-chart-legend__p-title{display:inline-block;vertical-align:middle;font-size:14px;color:#333c48}.cly-vue-chart-legend__p-tooltip{display:inline-block}.cly-vue-chart-legend__p-tooltip i{font-size:15px}.cly-vue-chart-legend__p-number{display:inline-block;font-size:24px;font-weight:500;color:#333c48}.cly-vue-chart-legend__p-trend{display:inline-block;font-size:14px;font-weight:500}.cly-vue-chart-legend__p-trend--trend-up{color:#12af51}.cly-vue-chart-legend__p-trend--trend-down{color:#d23f00}.cly-vue-chart-legend__s-rectangle{width:12px;height:6px;border-radius:3px;display:inline-block;vertical-align:middle;margin:0px 5px}.cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-percentage{display:inline-block;vertical-align:middle;margin-left:3px;font-size:12px;font-weight:400;color:#333c48}.cly-vue-chart-legend__bottom .cly-vue-chart-legend__primary,.cly-vue-chart-legend__bottom .cly-vue-chart-legend__secondary{padding:0px 24px 20px}.cly-vue-chart-legend__right{border-left:1px solid #ececec;width:265px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{margin-left:0px;padding:3px 7px;box-sizing:border-box;width:100%;display:block;border-bottom:1px solid #ececec}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{background-color:#f6f6f6;border-radius:0px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-percentage{font-weight:500}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{font-size:14px;line-height:30px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 30px);text-align:left}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{min-width:50px;text-align:right}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:10px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__view::before{content:"";position:absolute;width:100%;height:8px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie{border-left:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary{padding-top:30px;padding-bottom:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{border:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{border-radius:8px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 86px)}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:3px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view{display:flex;flex-direction:column;justify-content:center;padding-right:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view::before{background:none;height:0}.chart-type-toggle-wrapper__select{width:126px}.chart-type-toggle-wrapper__title{margin-top:16px;margin-left:16px;letter-spacing:.5px}.chart-type-toggle-wrapper__type{font-family:Inter;font-style:normal;font-weight:500;font-size:13px;line-height:13px}.chart-type-annotation-wrapper__icon{margin-top:1px}.chart-type-annotation-wrapper__img{margin-bottom:-2px}.chart-zoom-button{margin-right:12px}.cly-vue-zoom__external .chart-zoom-button{margin:0}.chart-download-button{width:42px;height:32px}.shadow-container{position:relative}.shadow-container:after{display:block;content:"";position:absolute;width:100%;margin:0 auto;height:70px;border:0;bottom:0;background:linear-gradient(180deg, rgba(255, 255, 255, 0.7) 0%, #FFFFFF 100%)}.chart-tooltip{max-height:360px;overflow:auto;margin-bottom:2px;max-width:300px;white-space:nowrap}.chart-tooltip__header{letter-spacing:.5px;text-transform:uppercase}.chart-tooltip__body{background-color:#fff;margin-bottom:16px;margin-top:16px}.chart-tooltip__body:last-child{margin-bottom:0 !important}.chart-tooltip__body.chart-tooltip__single-row{display:flex;margin-bottom:14px;margin-top:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__bar{margin-top:6px;float:none}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__series{display:flex;flex-direction:column;justify-content:space-between;width:calc(100% - 24px);margin-left:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__value{margin-top:-3px;margin-left:30px;display:flex;flex-direction:column;justify-content:space-between}.chart-tooltip__has-scroll .chart-tooltip__value{margin-right:10px}.chart-tooltip__bar{float:left;width:12px;min-width:12px;height:6px;border-radius:3px;margin-top:5px}.chart-tooltip__series{margin-left:24px;overflow:hidden}.chart-tooltip__series span{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.chart-tooltip__value{margin-top:2px;margin-left:24px}.graph-notes-tooltip{width:286px;max-height:118px;overflow:auto}.graph-notes-tooltip__header{width:100%}.graph-notes-tooltip__header .input-owner{font-weight:500}.graph-notes-tooltip__header .name-wrapper{margin-top:10px}.graph-notes-tooltip__header .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-notes-tooltip__header .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5;background-color:#f6f6f6}.graph-notes-tooltip__header .note-type{margin-top:12px}.graph-notes-tooltip__body{margin-top:12px}.graph-notes-tooltip__body .input-notes{word-break:break-word;display:inline-block;white-space:normal}.graph-notes-tooltip.minimize{width:180px}.graph-notes-tooltip.minimize .input-owner{font-size:12px}.graph-notes-tooltip.minimize__header{margin-top:0px}.graph-notes-tooltip.minimize .input-notes{font-size:12px}.graph-notes-tooltip.minimize .input-minimizer{margin-bottom:10px}.graph-notes-tooltip.minimize .graph-notes-tooltip__body{margin-top:5px}.graph-notes-tooltip.minimize .name-wrapper{margin-top:0px}.graph-notes-tooltip.minimize .note-date{font-size:11px}.graph-notes-tooltip.minimize .note-type{margin-top:2px;font-size:11px;margin-right:4px}.graph-tooltip-wrapper{margin-right:2px;margin-bottom:4px}.graph-tooltip-wrapper .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-tooltip-wrapper .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5}.graph-tooltip-wrapper__container{max-height:180px;overflow:hidden;overflow:auto}.cly-vue-tooltip-icon{font-size:17px;color:#a7aeb8;vertical-align:middle;width:18px;height:18px}.cly-in-page-notification{border-radius:4px;text-align:center;margin-bottom:32px}.cly-in-page-notification--light-informational{background-color:#e1efff;color:#333c48}.cly-in-page-notification--light-successful{background-color:#ebfaee;color:#333c48}.cly-in-page-notification--light-destructive{background-color:#fbece5;color:#333c48}.cly-in-page-notification--light-warning{background-color:#fcf5e5;color:#333c48}.cly-in-page-notification--dark-successful{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-informational{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-warning{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-destructive{background-color:#24292e;color:#fff}.cly-in-page-notification a:hover{text-decoration:underline;cursor:hand}.cly-vue-back-link{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase;margin-bottom:24px}.cly-vue-back-link:visited{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase}.cly-vue-back-link:hover span{text-decoration:underline}.cly-divider{width:100%;border-top:1px solid #ececec}.cly-divider.is-2{border-top-width:2px}.cly-divider.is-dashed{border-top-style:dashed}.cly-divider.is-dotted{border-top-style:dotted}.cly-event-select .el-radio-group{display:flex}.cly-event-select .el-radio-button{flex-grow:1}.cly-event-select .el-radio-button__inner{width:100%}.cly-vue-color-tag__color-tag-wrapper{width:20%}.cly-vue-color-tag__color-tag{width:92%;height:37px;margin-bottom:5px;border-radius:4px}.cly-vue-color-tag__color-tag__selected{border:2px solid #0166d6}.cly-vue-color-tag__checkmark{color:#fff}.cly-vue-empty-view-framed{border:1px solid #e2e4e8;background-color:#f8fafd;border-radius:8px;background-image:url("../images/icons/empty-background.svg");background-position:100% 100%;background-repeat:no-repeat}.cly-vue-json-editor .el-dialog__header{text-align:left;padding:8px 16px 0 !important;color:#fff}.cly-vue-json-editor .el-dialog__body{padding:0 !important}.cly-vue-json-editor__textarea{width:100%;box-sizing:border-box;outline:none;border:none;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fcfcfc}.cly-breadcrumbs a:hover{text-decoration:underline}.cly-is-fullwidth{width:100%}.is-estimate:hover{color:#0166d6;text-decoration:underline;text-decoration-style:dotted}#cly-vue-sidebar{left:0;height:100%;z-index:2000;user-select:none;color:#d6d6d6}.cly-vue-sidebar{height:100%}.cly-vue-sidebar .tooltip{display:block !important;z-index:10000}.cly-vue-sidebar .tooltip .tooltip-inner{background:#fff;color:#000}.cly-vue-sidebar .tooltip .tooltip-arrow{display:none}.cly-vue-sidebar .tooltip[x-placement^=right]{margin-left:0px}.cly-vue-sidebar .cly-vue-listbox__item-label{width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-sidebar__slide-transition-enter-active{transition:all .3s ease}.cly-vue-sidebar__slide-transition-leave-active{transition:all .8s cubic-bezier(1, 0.5, 0.8, 1)}.cly-vue-sidebar__slide-transition-enter,.cly-vue-sidebar__slide-transition-leave-to{transform:translateX(-224px)}.cly-vue-sidebar ul{list-style:none;padding:0;margin:0}.cly-vue-sidebar ul li{padding:0px}.cly-vue-sidebar__app-selector__dialog_box .el-dialog__body{padding:0px !important}.cly-vue-sidebar .el-collapse{border:none}.cly-vue-sidebar__app-name{font-size:14px}.cly-vue-sidebar__app-name-type{width:120px}.cly-vue-sidebar__app-selector{border:1px solid #424243;box-sizing:border-box;box-shadow:0px 11px 14px rgba(0,0,0,.371635);border-radius:4px;height:50px}.cly-vue-sidebar__app-type{opacity:.57}.cly-vue-sidebar__menu-options{width:48px;height:100%;overflow:auto;color:#a7aeb8;z-index:2005;background-color:#191c20}.cly-vue-sidebar__menu-options ul:first-child li:first-child{margin-top:28px}.cly-vue-sidebar__menu-option{width:48px;margin-top:24px;font-size:20px;cursor:pointer}.cly-vue-sidebar__menu-option .el-popover__reference:hover{color:#fff !important}.cly-vue-sidebar__menu-option-toggle{height:48px;background-color:#24292e;border-top-left-radius:50%;border-bottom-left-radius:50%}.cly-vue-sidebar__menu-option-toggle--no-bg{background-color:rgba(0,0,0,0)}.cly-vue-sidebar__menu-option-toggle--rotate-right{transform:rotate(180deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu-option-toggle--rotate-left{transform:rotate(0deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu{width:224px;background-color:#24292e;color:#d6d6d6;box-sizing:border-box;height:100%;overflow:hidden;z-index:2004;position:relative}.cly-vue-sidebar__menu--with-banner .__view{padding-bottom:200px}.cly-vue-sidebar__menu-items,.cly-vue-sidebar__submenu-items,.cly-vue-sidebar .el-collapse-item__header{line-height:20px;height:20px;background-color:#24292e;color:#d6d6d6;border:none;font-size:14px;padding:0;font-weight:400;font-family:Inter;padding:6px 12px}.cly-vue-sidebar__menu-items .el-collapse-item__arrow,.cly-vue-sidebar__submenu-items .el-collapse-item__arrow,.cly-vue-sidebar .el-collapse-item__header .el-collapse-item__arrow{margin-right:0px}.cly-vue-sidebar__menu-items:hover,.cly-vue-sidebar__submenu-items:hover,.cly-vue-sidebar .el-collapse-item__header:hover{background-color:#383a3f;color:#fff;border-radius:4px}.cly-vue-sidebar__menu-items--selected,.cly-vue-sidebar__submenu-items--selected,.cly-vue-sidebar .el-collapse-item__header--selected{background-color:#12af51;border-radius:4px;color:#fff}.cly-vue-sidebar__menu-items--selected:hover,.cly-vue-sidebar__submenu-items--selected:hover,.cly-vue-sidebar .el-collapse-item__header--selected:hover{background-color:#12af51;border-radius:4px}.cly-vue-sidebar .el-collapse-item__header.focusing:focus:not(:hover){color:#d6d6d6}.cly-vue-sidebar .el-collapse-item .cly-vue-sidebar__submenu-items{padding-left:32px}.cly-vue-sidebar__el-collapse--selected .el-collapse-item__header{border-radius:4px;background-color:#383a3f;color:#fff}.cly-vue-sidebar .el-collapse-item__content{margin:0;padding:0}.cly-vue-sidebar .el-collapse-item__wrap{border-bottom:1px solid #424243;background-color:#24292e;box-shadow:0px 1px 0px rgba(0,0,0,.4)}.cly-vue-sidebar__header{padding:16px 12px;position:relative}.cly-vue-sidebar__header-search input{background-color:#383a3f;border:none;color:#d6d6d6}.cly-vue-sidebar__header-search input:focus{outline:none;box-shadow:none}.cly-vue-sidebar__header-title{font-size:16px;line-height:24px;font-weight:500;display:inline-block;margin-top:12px}.cly-vue-sidebar__header-button{float:right;top:5px;position:relative}.cly-vue-sidebar__main-menu{overflow:auto;height:calc(100% - 130px)}.cly-vue-sidebar__app-image{width:26px;height:26px;background-size:26px 26px;border-radius:4px;background-position:center;display:inline-block}.cly-vue-sidebar__user-popper{box-sizing:border-box;font-family:Inter;padding:14px 0px;box-shadow:0px 2px 7px rgba(0,0,0,.18815);color:#333c48}.cly-vue-sidebar__language-popper{font-family:Inter;padding:0px;min-width:130px;box-shadow:0px 2px 7px rgba(0,0,0,.18815)}.cly-vue-sidebar__user-details .bu-level{padding:6px 12px}.cly-vue-sidebar__user-links .bu-level{padding:6px;margin:0px 6px}.cly-vue-sidebar__user-links .bu-level:hover{background-color:#f1f3f4;color:#0166d6;border-radius:4px}.cly-vue-sidebar__user-links .bu-level:hover .bu-level-item i{color:#333c48}.cly-vue-sidebar__user-links .bu-level .bu-level-item:first-child{width:15px}.cly-vue-sidebar__user-links .bu-level .bu-level-item i{color:#a7aeb8}.cly-vue-sidebar__user-info{width:140px}.cly-vue-sidebar__user-info p{padding:0;margin:0}.cly-vue-sidebar__user-info p:first-child{font-size:16px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-info p:last-child{margin-top:7px;line-height:17px;font-size:14px;font-weight:400}.cly-vue-sidebar__user-api{width:192px}.cly-vue-sidebar__user-api p{padding:0;margin:0}.cly-vue-sidebar__user-api p:first-child{font-size:12px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-api p:last-child{margin-top:7px;line-height:17px;font-size:12px;font-weight:400}.cly-vue-sidebar__user-image{height:50px;width:50px;border-radius:25px;text-align:center}.cly-vue-sidebar__user-initials{text-transform:uppercase;color:#fff;font-size:16px}.cly-vue-sidebar__user-divider{border:1px solid #ececec;margin-top:5px;position:relative}.cly-vue-sidebar__version{position:absolute;bottom:0;height:48px;display:flex;align-items:center;justify-content:center;width:224px;font-size:10px;background-color:#24292e}.cly-vue-sidebar__version__banner{position:absolute;bottom:12px;left:12px;right:12px;z-index:2001;cursor:default;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:#191c20;border-radius:4px;padding:16px}.cly-vue-sidebar__version__banner .button{width:100%;margin-top:12px}.cly-vue-sidebar__version__banner .text{font-size:14px;color:#fff}.cly-vue-sidebar .cly-icon-sidebar-app{background-image:url("../images/sidebar/default/app.svg");height:24px;width:24px}.cly-vue-sidebar .cly-icon-sidebar-analytics{background-image:url("../images/sidebar/default/analytics-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-analytics:hover{background-image:url("../images/sidebar/hover/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-analytics.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards{background-image:url("../images/sidebar/default/dashboards-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-dashboards:hover{background-image:url("../images/sidebar/hover/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-divider{background-image:url("../images/sidebar/default/divider.svg");width:32px;height:1px}.cly-vue-sidebar .cly-icon-sidebar-management{background-image:url("../images/sidebar/default/management.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-management:hover{background-image:url("../images/sidebar/hover/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-management.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager{background-image:url("../images/sidebar/default/report-manager.svg");height:18px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-report-manager:hover{background-image:url("../images/sidebar/hover/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center{background-image:url("../images/sidebar/default/help-center.svg");height:25px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-help-center:hover{background-image:url("../images/sidebar/hover/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications{background-image:url("../images/sidebar/default/notifications.svg");height:23px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-notifications:hover{background-image:url("../images/sidebar/hover/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-toggle-left{background-image:url("../images/sidebar/default/toggle-left.svg");height:15px;width:11px}.cly-vue-sidebar--floating{position:absolute;left:48px}.notification-toasts{position:absolute;right:24px;bottom:24px;z-index:600000}.notification-toasts__item{margin-top:12px;min-width:288px;max-width:288px}.notification-toasts__item--small{max-width:288px}.notification-toasts__item--large{max-width:611px}.font-weight-bold{font-weight:600 !important}.font-weight-normal{font-weight:400 !important}.font-italic{font-style:italic !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-big{color:#333c48;font-size:16px;font-weight:400;line-height:22px}.text-big.font-weight-bold{font-weight:500 !important}.text-medium{color:#333c48;font-size:14px;font-weight:400;line-height:20px}.text-medium.font-weight-bold{font-weight:500 !important}.text-smallish{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-smallish.font-weight-bold{font-weight:500 !important}.text-small{color:#333c48;font-size:12px;font-weight:400;line-height:18px}.text-small.font-weight-bold{font-weight:500 !important}.text-heading.text-big{line-height:24px;font-weight:500 !important;margin-bottom:16px}.text-heading.text-medium{line-height:20px;font-weight:500 !important;margin-bottom:8px}.text-heading.text-small{line-height:18px;font-weight:500 !important;margin-bottom:4px}.text-smaller{color:#333c48;font-size:10px;font-weight:400;line-height:12px}.text-smaller.font-weight-bold{font-weight:500 !important}.text-smallest{color:#333c48;font-size:10px;font-weight:700;line-height:12px}.text-smallest.font-weight-bold{font-weight:500 !important}.text-button{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-button.font-weight-bold{font-weight:500 !important}.cly-trend-up,.cly-trend-down,.cly-trend-neutral{font-size:14px;font-weight:500}.cly-trend-up,.cly-trend-down.negated{color:#12af51}.cly-trend-down,.cly-trend-up.negated{color:#d23f00}.cly-trend-neutral{color:#81868d}.cly-trend-up-icon,.cly-trend-down-icon,.cly-trend-neutral-icon{border-radius:50%;margin-right:4px;display:inline-block;width:17px;height:17px;text-align:center;line-height:17px}.cly-trend-up-icon{background-color:#ebfaee}.cly-trend-down-icon{background-color:#fbece5}.cly-trend-neutral-icon{background-color:#e2e4e8}.cly-trend-up.negated .cly-trend-up-icon{background-color:#fbece5}.cly-trend-down.negated .cly-trend-down-icon{background-color:#ebfaee}.cursor-pointer{cursor:pointer}.icon-size-1{font-size:6px}.icon-size-2{font-size:8px}.icon-size-3{font-size:10px}.icon-size-4{font-size:12px}.icon-size-5{font-size:14px}.icon-size-6{font-size:16px}.text-clickable{cursor:pointer}.color-white{color:#fff !important}.bg-white{background-color:#fff !important}.color-black{color:#000 !important}.bg-black{background-color:#000 !important}.color-warm-gray-100{color:#24292e !important}.bg-warm-gray-100{background-color:#24292e !important}.color-warm-gray-90{color:#24292e !important}.bg-warm-gray-90{background-color:#24292e !important}.color-warm-gray-80{color:#383a3f !important}.bg-warm-gray-80{background-color:#383a3f !important}.color-warm-gray-70{color:#424243 !important}.bg-warm-gray-70{background-color:#424243 !important}.color-warm-gray-60{color:#616165 !important}.bg-warm-gray-60{background-color:#616165 !important}.color-warm-gray-40{color:#d6d6d6 !important}.bg-warm-gray-40{background-color:#d6d6d6 !important}.color-warm-gray-30{color:#ececec !important}.bg-warm-gray-30{background-color:#ececec !important}.color-warm-gray-20{color:#f6f6f6 !important}.bg-warm-gray-20{background-color:#f6f6f6 !important}.color-warm-gray-10{color:#fcfcfc !important}.bg-warm-gray-10{background-color:#fcfcfc !important}.color-cool-gray-100{color:#333c48 !important}.bg-cool-gray-100{background-color:#333c48 !important}.color-cool-gray-50{color:#81868d !important}.bg-cool-gray-50{background-color:#81868d !important}.color-cool-gray-40{color:#a7aeb8 !important}.bg-cool-gray-40{background-color:#a7aeb8 !important}.color-cool-gray-30{color:#cfd6e4 !important}.bg-cool-gray-30{background-color:#cfd6e4 !important}.color-cool-gray-20{color:#e2e4e8 !important}.bg-cool-gray-20{background-color:#e2e4e8 !important}.color-cool-gray-10{color:#f8fafd !important}.bg-cool-gray-10{background-color:#f8fafd !important}.color-cool-gray-05{color:#fbfdfe !important}.bg-cool-gray-05{background-color:#fbfdfe !important}.color-charts-blue{color:#017aff !important}.bg-charts-blue{background-color:#017aff !important}.color-charts-turquoise{color:#39c0c8 !important}.bg-charts-turquoise{background-color:#39c0c8 !important}.color-charts-light-turquoise{color:#ebf9f9 !important}.bg-charts-light-turquoise{background-color:#ebf9f9 !important}.color-charts-amber{color:#f5c900 !important}.bg-charts-amber{background-color:#f5c900 !important}.color-charts-orange{color:#f96300 !important}.bg-charts-orange{background-color:#f96300 !important}.color-charts-light-orange{color:#feefe5 !important}.bg-charts-light-orange{background-color:#feefe5 !important}.color-charts-magenta{color:#f34971 !important}.bg-charts-magenta{background-color:#f34971 !important}.color-charts-light-magenta{color:#feedf1 !important}.bg-charts-light-magenta{background-color:#feedf1 !important}.color-charts-coral{color:#ff9382 !important}.bg-charts-coral{background-color:#ff9382 !important}.color-charts-violet{color:#da6efc !important}.bg-charts-violet{background-color:#da6efc !important}.color-charts-purple{color:#6c47ff !important}.bg-charts-purple{background-color:#6c47ff !important}.color-charts-light-purple{color:#f0edff !important}.bg-charts-light-purple{background-color:#f0edff !important}.color-charts-tan{color:#cdad7a !important}.bg-charts-tan{background-color:#cdad7a !important}.color-charts-olive{color:#aabb5d !important}.bg-charts-olive{background-color:#aabb5d !important}.color-charts-scarlet{color:#f62404 !important}.bg-charts-scarlet{background-color:#f62404 !important}.color-charts-pink{color:#ffb6f5 !important}.bg-charts-pink{background-color:#ffb6f5 !important}.color-yellow-100{color:#e49700 !important}.bg-yellow-100{background-color:#e49700 !important}.color-yellow-70{color:#ffc760 !important}.bg-yellow-70{background-color:#ffc760 !important}.color-yellow-20{color:#fff4ce !important}.bg-yellow-20{background-color:#fff4ce !important}.color-yellow-10{color:#fcf5e5 !important}.bg-yellow-10{background-color:#fcf5e5 !important}.color-blue-100{color:#0166d6 !important}.bg-blue-100{background-color:#0166d6 !important}.color-blue-90{color:#1a75da !important}.bg-blue-90{background-color:#1a75da !important}.color-blue-80{color:#3485de !important}.bg-blue-80{background-color:#3485de !important}.color-blue-70{color:#4d94e2 !important}.bg-blue-70{background-color:#4d94e2 !important}.color-blue-60{color:#67a3e6 !important}.bg-blue-60{background-color:#67a3e6 !important}.color-blue-50{color:#80b3eb !important}.bg-blue-50{background-color:#80b3eb !important}.color-blue-40{color:#99c2ef !important}.bg-blue-40{background-color:#99c2ef !important}.color-blue-30{color:#b3d1f3 !important}.bg-blue-30{background-color:#b3d1f3 !important}.color-blue-20{color:#cce0f7 !important}.bg-blue-20{background-color:#cce0f7 !important}.color-blue-10{color:#e6f0fb !important}.bg-blue-10{background-color:#e6f0fb !important}.color-sky-blue-100{color:#3f9aff !important}.bg-sky-blue-100{background-color:#3f9aff !important}.color-shadow-blue-100{color:#9cbce0 !important}.bg-shadow-blue-100{background-color:#9cbce0 !important}.color-light-blue-100{color:#e1efff !important}.bg-light-blue-100{background-color:#e1efff !important}.color-dark-blue-100{color:#32659d !important}.bg-dark-blue-100{background-color:#32659d !important}.color-teal{color:#00c3ca !important}.bg-teal{background-color:#00c3ca !important}.color-red-100{color:#d23f00 !important}.bg-red-100{background-color:#d23f00 !important}.color-red-10{color:#fbece5 !important}.bg-red-10{background-color:#fbece5 !important}.color-green-100{color:#10a14a !important}.bg-green-100{background-color:#10a14a !important}.color-green-80{color:#12af51 !important}.bg-green-80{background-color:#12af51 !important}.color-green-10{color:#ebfaee !important}.bg-green-10{background-color:#ebfaee !important}.color-primary{color:#0166d6 !important}.bg-primary{background-color:#0166d6 !important}.color-primary-green{color:#12af51 !important}.bg-primary-green{background-color:#12af51 !important}.color-success{color:#67c23a !important}.bg-success{background-color:#67c23a !important}.color-warning{color:#e49700 !important}.bg-warning{background-color:#e49700 !important}.color-danger{color:#d23f00 !important}.bg-danger{background-color:#d23f00 !important}.color-info{color:#909399 !important}.bg-info{background-color:#909399 !important}.color-text-secondary{color:#81868d !important}.bg-text-secondary{background-color:#81868d !important}.color-text-custom-1-active{color:#333c48 !important}.bg-text-custom-1-active{background-color:#333c48 !important}.color-text-placeholder{color:#81868d !important}.bg-text-placeholder{background-color:#81868d !important}.color-text-primary{color:#303133 !important}.bg-text-primary{background-color:#303133 !important}.color-text-regular{color:#333c48 !important}.bg-text-regular{background-color:#333c48 !important}.color-text-custom-1-passive{color:#858a91 !important}.bg-text-custom-1-passive{background-color:#858a91 !important}.color-action-blue{color:#0166d6 !important}.bg-action-blue{background-color:#0166d6 !important}.white-bg{background-color:#fff}.no-bg{background-color:none}.blinker{position:relative;top:-1px;width:6px;height:6px;border-radius:8px;background-color:#2fa732;display:inline-block;vertical-align:middle;margin-right:5px;animation:blinker 1.5s cubic-bezier(0.5, 0, 1, 1) infinite alternate}.has-tooltip{cursor:pointer}.has-ellipsis{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.has-ellipsis::after{content:"";display:block}.user-activity-table__divider{width:16px;justify-content:space-evenly;color:#a7aeb8}.user-activity-table__data-item-container{flex-basis:75px;margin-right:14px}.user-activity-table-progress-bar-container{width:100%}.user-activity-table-progress-bar-container progress::-webkit-progress-value{background-color:#39c0c8}.session-overview-date-picker-container{margin-bottom:32px}.session-durations-date-picker-container{margin-bottom:32px}.session-frequency-date-picker-container{margin-bottom:32px}.cly-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-top:1px solid #eef2f5;box-shadow:0px 2px 0px #eaecef;padding:24px 24px 0px 24px}.cly-events-breakdown-horizontal-tile__titleoverview{color:#333c48;font-size:14px;font-weight:400;line-height:20px;font-family:Inter}.cly-events-breakdown-horizontal-tile:nth-of-type(3n) .cly-events-breakdown-horizontal-tile__wrapper{border-right:0}.cly-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 24px 0px}.cly-events-breakdown-horizontal-tile__item-title{padding:12px 0px 8px 0px}.cly-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px;font-family:Inter;color:#333c48;letter-spacing:.003em}.cly-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:400;line-height:20px;font-family:Inter;color:#333c48}.cly-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-vue-events-overview-top-events{padding-left:24px;padding-bottom:16.5px}.cly-vue-events-overview-top-events--tooltip{margin-left:5.5px}.cly-vue-events-overview-top-events__description{font-weight:500;line-height:14px}.cly-vue-events-overview-top-events__trend{padding-right:3px}.cly-vue-events-overview-monitor-events__charts .cly-vue-chart__echart{padding:0px}.cly-vue-events-overview-monitor-events__empty{min-height:100px}.cly-vue-events-overview-monitor-events__empty__block{margin:32px auto 32px auto;max-width:586px}.cly-vue-events-overview-monitor-events__empty--image{width:242px;height:242px;background-image:url("../images/dashboard/events-overview-noevents.svg")}.cly-vue-events-overview-monitor-events--text{font-weight:500;font-size:12px;color:#a7aeb8;letter-spacing:.5px;font-family:Inter;line-height:14.52px}.cly-vue-events-overview-monitor-events .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.cly-vue-events-overview-monitor-events--grey{color:#a7aeb8}.cly-vue-events-overview-monitor-events__heading{padding:8px 0px 16px 0px}.cly-vue-events-overview-monitor-events__configure--position{float:right;margin-left:auto}.cly-events-overview-drawer__subheading{font-size:16px;line-height:24px;font-weight:500;font-family:Inter;color:#333c48}.cly-events-overview-drawer--dragicon{margin-right:18px}.cly-events-overview-drawer__event-records{border-radius:6px;width:100%;padding:14px 16px;background-color:#f8fafd}.cly-events-overview-drawer__basis{flex-basis:0}.cly-events-overview-drawer__dropdown{min-width:230px;width:100%}.cly-events-overview-drawer__close-icon{line-height:1;font-size:24px}.cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-bottom:1px solid #ececec;padding:24px 24px 0 24px}.cly-monitor-events-breakdown-horizontal-tile__title{font-size:12px;font-weight:400;line-height:20px;padding-bottom:8px}.cly-monitor-events-breakdown-horizontal-tile__titleoverview{font-size:12px;font-weight:400;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__eventproperty{font-size:12px;font-weight:400;line-height:20px;color:#81868d}.cly-monitor-events-breakdown-horizontal-tile:nth-of-type(2n) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:none}.cly-monitor-events-breakdown-horizontal-tile:nth-child(1) .cly-monitor-events-breakdown-horizontal-tile__wrapper,.cly-monitor-events-breakdown-horizontal-tile:nth-child(2) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-top:1px solid #ececec}.cly-monitor-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-monitor-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 16px 0px}.cly-monitor-events-breakdown-horizontal-tile__item-title{padding-top:4px}.cly-monitor-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px}.cly-monitor-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-monitor-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:300;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-monitor-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-monitor-events-breakdown-horizontal-tile__overview-name{z-index:1}.cly-monitor-events-breakdown-horizontal-tile__width-50{width:50%}.cly-vue-events-all{font-size:24px;line-height:32px;font-weight:500;padding-top:6px;letter-spacing:.003em;font-family:Inter;color:#333c48}.cly-vue-events-all__alerts a{text-decoration:underline}.cly-vue-events-all__subheading{font-size:14px;line-height:20px;color:#333c48}.cly-vue-events-all--padding{padding-top:32px}.cly-vue-events-all--margin{margin-right:32px}.cly-vue-events-group{color:#fff;background-color:#a7aeb8;font-size:10px;line-height:10px;font-weight:500;letter-spacing:.0042em;vertical-align:middle;padding:3px 4px;border-radius:4px}.cly-vue-events-all-placeholder-text{color:#81868d;font-size:12px;line-height:14.52px;font-weight:500;letter-spacing:.005em;white-space:nowrap}.cly-vue-events-all-date-picker{margin-right:26px}.cly-vue-events-all-tooltip{margin-left:10px}.cly-vue-overview-events-header{padding-right:9.5px;letter-spacing:.003em}.cly-vue-events-header{padding:8px 24px 24px 24px;letter-spacing:.003em;font-family:Inter;line-height:32px;border-bottom:1px solid #ececec;background-color:#fff}.cly-vue-events-header__subheading--widget{padding-right:5.33px;color:#81868d}.cly-vue-events-header__subheading--text{font-family:Inter;line-height:20px;font-size:14px;color:#81868d}.cly-vue-events-header--tooltip{padding-left:9.5px}.cly-vue-events-overview-subheadings{padding-right:9.5px;letter-spacing:.003em;font-family:Inter}.cly-vue-events-overview-subheadings--tooltip{padding-top:3px}.cly-vue-events-overview-subheadings--font{font-family:Inter}.cly-vue-listbox.is-expandable{z-index:2001}.cly-vue-events-omitted-segments__item{color:#81868d;font-size:14px;font-weight:500;line-height:16px;padding:8px;margin:8px}.cly-vue-events-omitted-segments__title{color:#a7aeb8;font-size:13px;font-weight:500;letter-spacing:.5px;text-transform:uppercase;line-height:16px;padding:8px;margin:8px}.technology-analytics-wrapper .allPlatformVersions{border-left:1px solid #ececec;height:264px;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions{height:264px;position:relative;border-left:1px solid #ececec;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions div{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48;position:absolute;top:50%;text-align:center;width:100%;margin-top:-10px}.technology-analytics-wrapper .version-graph-title{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.technology-analytics-wrapper .version-graph-title .divider{color:#a7aeb8}.technology-analytics-wrapper .version-graph-title div:first-child{text-align:left}.technology-analytics-wrapper .version-graph-title div:nth-child(2){text-align:right}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper .version-graph-title .bu-column{padding:0px}.technology-analytics-wrapper .cly-vue-metric-card__wrapper .bu-is-flex-direction-column{margin-right:-1.5rem}.technology-analytics-wrapper .selector_wrapper{position:relative;top:-5px;margin-left:8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .metricCardsWrapper{height:115px}.technology-analytics-wrapper .metricCardsWrapper .emptyCard{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .emptyCard div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .platformVersionsWrapper .emptyCard{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .platformVersionsWrapper{height:309px;padding-bottom:20px}.technology-analytics-wrapper .metricCardsWrapper .bu-columns{flex-wrap:nowrap}.technology-analytics-wrapper .metricCardsWrapper .__view{width:auto !important}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-cards{border-bottom:none}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-card{background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__items{height:115px}.technology-analytics-wrapper__versions{height:291px;padding-bottom:20px}.technology-analytics-wrapper__empty-card{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;top:50%;text-align:center;border-bottom:1px solid #ececec}.technology-analytics-wrapper__empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper__versions-empty-card{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-right:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__versions-empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .app-version-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-version-date-picker-container+.cly-vue-notification__alert-box{margin-top:-8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-carrier-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .devices-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper__metric-cards .bu-column:last-child{margin-right:unset !important}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart__echart{padding-right:0px}.technology-analytics-wrapper .technology-pie-graphs .bu-level .bu-level-right{padding-right:5px}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .cly-vue-chart-legend__secondary{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .bu-level .bu-level-right{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__rail-is-vertical{right:5px !important}.version-graph-block:last-child{margin-bottom:12px}.technology-dashboard-widget>.bu-column:nth-child(odd)>.cly-vue-section{padding-left:4px}.technology-dashboard-widget>.bu-column:nth-child(even)>.cly-vue-section{padding-right:12px}.routename-analytics-geo .geo-date-picker-container{margin-bottom:32px}.routename-analytics-geo .radio-column{width:256px}.leaflet-noclick-map .leaflet-interactive{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.leaflet-control-zoom{user-select:none;border-color:#dcdcdc !important}.leaflet-control-zoom a{color:#333c48;border-bottom-color:#dcdcdc}.geo-analytics-data .cly-vue-button{padding:6px 10px;border-radius:4px}.user-management-drawer-content__pp-options{height:fit-content;align-self:center;margin-left:15px;box-shadow:none}.user-management-drawer-content__pp-options .el-button{box-shadow:none;border:none}.user-management-drawer-content__user-pp{width:100px;height:100px;border-radius:50%}.user-management-drawer-content #user-drawer-dropzone{background-color:#f8fafd;border-radius:6px}.user-management-drawer-content__custom-options{box-shadow:none}.user-management-drawer-content__custom-options div button{box-shadow:none;padding:0px;background:none;border:none}.user-management-drawer-content__under-input-text{text-decoration:underline;cursor:pointer}.user-management-drawer-content__top-section{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__bottom-section{display:flex;margin-top:28px;flex-direction:column;justify-content:space-between}.user-management-drawer-content__input-wrapper{margin-top:10px}.user-management-drawer-content__label{display:flex;justify-content:space-between;flex-direction:column}.user-management-drawer-content__label--text-secondary{color:#81868d}.user-management-drawer-content__label-text{font-style:normal;font-weight:normal;font-size:13px;line-height:16px;color:#333c48}.user-management-drawer-content__help-text{font-family:Inter;font-style:normal;font-weight:normal;font-size:12px;line-height:16px;color:#81868d}.user-management-drawer-content__help-menu-icon{font-family:Inter;font-style:normal;font-weight:normal;font-size:16px;line-height:16px;color:#81868d}.user-management-drawer-content__light-button{background-color:#ddedff;color:#0166d6;font-weight:bold;padding:10px 20px;width:fit-content;margin-top:10px;font-size:13px;border-radius:5px}.user-management-drawer-content__profile-picture-area{margin-top:9px;margin-left:10px}.user-management-drawer-content__profile-picture-area__upload-section{border:1px dashed #81868d;padding:30px;border-radius:8px;display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content__profile-picture-area__upload-section__img-box{background-color:#e2e4e8;height:100px;width:100px;border-radius:50%}.user-management-drawer-content__profile-picture-area__upload-section__description-box{font-size:12px;text-align:center;width:80%}.user-management-drawer-content__profile-picture-area__upload-section__description-box--bold{font-weight:500;color:#0166d6}.user-management-drawer-content__profile-picture-area__upload-section__description-box--gray{color:gray}.user-management-drawer-content__drawer-sub-section{border-radius:6px;background-color:#f8fafd;margin-top:10px;margin-bottom:24px}.user-management-drawer-content__drawer-sub-title{display:flex;flex-direction:row;justify-content:space-between;padding:5px 0px;font-weight:500;font-size:16px}.user-management-drawer-content__permission-table-header{display:flex;justify-content:space-between;margin-top:10px;font-size:12px;border-bottom:1px solid #ebebeb;padding-bottom:10px}.user-management-drawer-content__feature-search{width:calc(40% - 15px);margin-left:10px}.user-management-drawer-content__feature-search .el-input__inner{background-color:#fff !important}.user-management-drawer-content__permission-type-cols{width:75%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-type{text-align:center;font-size:11px;width:25%;margin:auto}.user-management-drawer-content__permission-type .check-label{font-size:15px}.user-management-drawer-content__permission-type .check-text{margin-top:2px}.user-management-drawer-content__permission-type .el-checkbox__label{font-weight:medium !important}.user-management-drawer-content__permission-table-content{height:300px;overflow-y:scroll;padding:10px 0px}.user-management-drawer-content__permission-row{display:flex;flex-direction:row;height:30px;justify-content:center;align-items:center}.user-management-drawer-content__feature-name{width:calc(35% - 15px);text-align:left;padding-left:15px;display:flex;justify-content:flex-start;align-items:center;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.user-management-drawer-content__feature-permissions{width:65%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-box{text-align:center;width:35%}.user-management-drawer-content__section-title{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__section-header{font-family:Inter;font-style:normal;font-weight:500;font-size:12px;line-height:15px;letter-spacing:.5px;text-transform:uppercase;color:#333c48}.user-management-drawer-content__role-section .check-text{margin-top:4px !important}.user-management-drawer-content__role-section .el-checkbox__label{font-weight:normal !important}.user-management-drawer-content__app-selector{width:100%}.user-management-drawer-content__add-permission-set{background-color:#e1efff;border-radius:4px;cursor:pointer;padding:9.5px 12px;font-weight:500;font-size:13px;line-height:13px;color:#0166d6;width:fit-content}.user-management-drawer-content__group-selector{width:100%}.user-management-drawer-content .check-label{color:#0166d6 !important}.user-management-drawer-content .el-tag--info{background-color:#81868d;color:#fff}.user-management-drawer-content .el-icon-close{background-color:#fff !important}.user-management-drawer-content .el-icon-close:hover{color:#81868d !important}.user-management-drawer-content .dropzone-custom-content{display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image>div{height:100px;width:100px;border-radius:50%}.user-management-drawer-content .dz-image-preview{display:flex !important;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image-preview .dz-remove{font-size:12px;font-weight:bold}.user-management-drawer-content .dz-image-preview .dz-image{display:block !important}.manage-users-table{margin:0px}.manage-users-table__groups{display:inline-flex;color:#32659d}.manage-users-table__groups a:hover{color:#1a75da;text-decoration:underline}.manage-users-table__groups-label{margin:0px 2px}.user-management-filter-form .select-full-width{width:100%}.user-management-view .el-tabs--button>.el-tabs__header{padding:24px 24px 0px 24px}.user-management-view .manage-users-action-btn{background-color:#12af51}#main_home_view .el-loading-parent--relative{min-height:100px}#main_home_view .bu-level-left:first-child>h2{font-size:20px !important}#main_home_view .cly-back-link i{color:#333c48}#main_home_view .componentBlock>div{padding-top:16px;padding-bottom:20px}.app-management-view h2{letter-spacing:.3px}.app-management-view h3{letter-spacing:.3px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container{margin-top:12px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container .cly-vue-form-step__section{padding-left:24px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.app-management-view .cly-vue-section__content .el-collapse{border:none}.app-management-view .cly-vue-section__content .app-section{margin-left:12px;margin-right:4px}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section{margin-bottom:24px !important;margin-left:0 !important;margin-right:0 !important;color:#333c48;display:flex;justify-content:space-between}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section .cly-vue-form-field__inner .el-form-item .el-form-item__content{line-height:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p{font-size:14px;line-height:14px;margin:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p+p{font-size:12px;line-height:16px;font-weight:400;margin-top:4px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns{padding:0 !important;margin:0}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-4{width:50%;margin-right:48px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-8{width:37.33%}.app-management-view .account-settings-avatar-box{padding:24px;overflow:auto;flex:auto}.app-management-view .account-settings-avatar-box .el-upload{display:block}.app-management-view .feedback-settings__upload .el-upload{display:block}.app-management-view .feedback-settings__upload img{width:165px;height:50px;margin-left:24px;cursor:default}.app-management-view .feedback-settings__colorpicker .cly-vue-color-picker__picker{overflow:auto}.app-management-view .feedback-settings__button:active,.app-management-view .feedback-settings__button:focus,.app-management-view .feedback-settings__button:hover{background-color:unset !important;border-color:unset !important}.app-management-view .app-management-list{max-height:681px;max-width:223px}.app-management-view .app-management-list .cly-vue-listbox__item span{margin-left:8px;position:relative;top:-8px}.app-management-view .app-management-details .bu-columns{margin:0 !important;padding:0 !important;border-bottom:1px solid #ececec}.app-management-view .app-management-details .bu-columns:last-child{border-bottom:none;margin-bottom:-20px}.app-management-view .app-management-details .el-collapse-item__header.is-active{border-bottom:1px solid #ececec}.app-management-view .app-management-details .el-collapse-item__content{padding-bottom:0}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section{padding-left:48px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content{display:flex !important;justify-content:right !important;float:right;line-height:inherit}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content>div{max-width:232px}.app-management-view .app-management-details .el-collapse-item__arrow{color:#81868d}.app-management-view .app-management-details .el-collapse-item__header{color:#333c48;padding-left:24px !important;text-transform:uppercase}.app-management-view .app-management-details .el-collapse-item__wrap{overflow:unset}.app-management-view .box-card{background-color:#e6f0fb;border:1px solid #0166d6;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.app-management-view .box-card .el-card__body{padding:24px}.app-management-view .box-card .el-card__body p a{color:#0166d6}.app-management-view .box-card .el-card__body p:nth-of-type(1){line-height:24px;font-weight:500;font-size:16px}.app-management-view .box-card .el-card__body p{font-size:14px}.el-dropdown-menu__item--divided__fix-broken{border:none}.el-dropdown-menu__item--divided__fix-broken::before{height:0px}.add-border{margin:0 8px;padding:0;border-top:1px solid #ececec}.add-border>a{display:none}@media(max-width: 2133px){.app-section span div div:nth-last-child(1) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(1) .cly-vue-form-step__section .el-input{width:268%}}@media(max-width: 1280px){.app-section span div div:nth-last-child(2) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(2) .cly-vue-form-step__section .el-input{width:177%}}.report-manager-filter-form .select-full-width{width:100%}.header{display:flex;flex-direction:column;gap:20px}.setup-logo{margin-top:38px;margin-left:72px;width:165px;height:50px;background-image:url("../images/pre-login/countly-logo-dark.svg");background-repeat:no-repeat;background-size:contain;position:fixed;left:0px;top:0px}.centered-content{min-height:100vh;display:flex;align-items:center;justify-content:center;margin-bottom:-35px}.setup-byline{color:#81868d;margin-top:12px;font-size:14px}.setup-form{width:520px}.setup-radio-grid{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:10px;row-gap:10px}.setup-radio .el-radio.is-checked{background-color:#e1efff}.setup-radio .el-radio{margin-left:0 !important}.setup-radio .is-autosized.is-bordered .el-radio__input{display:none !important}.setup-radio .el-radio__label{padding-left:0}.setup-radio-item{display:flex;align-items:center;font-size:24px}.setup-radio-icon-bg{width:40px;height:40px;display:flex;align-items:center;justify-content:center;background-color:#e1efff;border-radius:100%}.is-checked .setup-radio-icon-bg{background-color:#0166d6;color:#fff}.setup-radio-icon{background-image:url("../images/dashboard/onboarding/box.svg");background-position:center;background-repeat:no-repeat;width:100%;height:100%}.setup-radio-icon--app-type-mobile{background-image:url("../images/dashboard/onboarding/app-type-mobile.svg")}.setup-radio-icon--app-type-web{background-image:url("../images/dashboard/onboarding/app-type-web.svg")}.setup-radio-icon--app-type-desktop{background-image:url("../images/dashboard/onboarding/app-type-desktop.svg")}.is-checked .setup-radio-icon{filter:brightness(10)}.setup-video-container{max-width:800px}.consent-form{width:700px}.consent-blurb{color:#81868d;font-size:14px}.consent-question{font-size:14px}.initial-populator{width:800px}.quickstart-item{display:flex;align-items:flex-start}.quickstart-item-desc{color:#81868d;text-align:left;word-break:break-word}.quickstart-link,.quickstart-link:visited{color:#0166d6}.quickstart-link:hover{color:#333c48}.preset-list{display:inline-block;position:absolute;left:170px;border:1px solid #a7aeb8;border-radius:4px;background-color:#fff}.preset-list__header{z-index:1997;position:relative;padding:8px 16px}.preset-list__header::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12;top:100%}.preset-list__header .el-button--primary{border:unset;font-weight:500;box-shadow:none}.preset-list__header .el-button--primary:hover{background-color:#cce0f7;color:#0166d6}.preset-list__header .el-button--text{font-weight:500;font-size:14px}.preset-list__body{background-color:#f9f9f9;height:400px;border-radius:4px}.preset-list__body::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(0deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);opacity:.12;left:0;bottom:0}.preset-list__body .preset{display:flex;flex-direction:column;justify-content:center;width:300px;background-color:#fff;border:1px solid #ececec;border-radius:4px;padding:12px;margin-bottom:8px;cursor:pointer}.preset-list__body .preset:first-child{margin-top:16px}.preset-list__body .preset:last-child{margin-bottom:16px}.preset-list__body .preset:hover{border:1px solid #0166d6;background-color:#e1efff}.preset-list__body .preset--selected{border:1px solid #0166d6}.preset-list .sortable-chosen{background-color:#e1efff !important}#preset-drawer .el-radio__label{display:flex;align-items:center}#preset-drawer .el-radio__input{display:flex}#preset-drawer .el-checkbox{font-weight:400}#preset-drawer .el-checkbox__label{padding-left:8px;color:#333c48}#preset-drawer .el-checkbox:hover__label{color:#333c48}/*# sourceMappingURL=manifest.css.map */ +.cly-icon-btn{height:12px;width:12px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-prefix-icon{height:14px;width:12px;margin-left:7px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-input{height:20px;width:20px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-zoom{background-image:url("../images/icons/zoom-icon.svg")}.cly-icon-arrow-down{background-image:url("../images/icons/arrow_drop_down.svg")}.cly-icon-arrow-up{background-image:url("../images/icons/arrow_drop_up.svg")}.cly-icon-menu{background-image:url("../images/icons/menu.svg")}.cly-icon-date{background-image:url("../images/icons/date.svg")}.cly-icon-download{background-image:url("../images/icons/download-icon.svg")}.cly-icon-save{background-image:url("../images/icons/save.svg")}.cly-icon-load{background-image:url("../images/icons/load.svg")}.cly-icon-upload{background-image:url("../images/icons/upload.svg")}.cly-icon-arrow_forward-circled{background-image:url("../images/icons/arrow_forward-circled.svg")}.cly-icon-copy{background-image:url("../images/icons/copy.svg")}.cly-icon-copy_interactive{background-image:url("../images/icons/copy_inactive.svg")}.cly-icon-copy_interactive:hover{background-image:url("../images/icons/copy.svg")}.el-button [class*=ion-]+span,[class*=cly-icon-]+span{margin-left:6px}.el-button-group>.el-button{display:flex;align-items:center}.el-button-group>.el-select:first-child .el-button{display:flex;align-items:center}.cly-countly-icon-solid{width:20px;height:20px;background-image:url("../images/icons/countly-icon-solid.svg")}.cly-countly-icon-outline{width:20px;height:20px;background-image:url("../images/icons/countly-icon-outline.svg")}.cly-countly-icon-outline-trash-16px{background-position:99px 962px}.cly-countly-icon-outline-code-16px{background-position:99px 674px}.cly-countly-icon-outline-external-link-16px{background-position:419px 674px}.cly-countly-icon-outline-download-16px{background-position:299px 819px}.cly-countly-icon-outline-x-16px{background-position:139px 1107px}.cly-countly-icon-outline-document-download-16px{background-position:179px 1058px}.cly-countly-icon-outline-exclamation-circle-16px{background-position:339px 868px}.cly-countly-icon-outline-plus-circle-16px{background-position:299px 867px}.cly-countly-icon-outline-globe-16px{background-position:219px 1010px}.cly-countly-icon-outline-user-group-16px{background-position:300px 1202px}*{outline:none}html{height:100%;width:100%}body{height:100%;width:100%;margin:0;padding:0;overflow:auto;background-color:#f9f9f9;user-select:text;font-family:Inter,Ubuntu,Helvetica,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1{font-size:32px;line-height:48px;font-weight:500;margin:0;padding:10;color:#333c48}h2{font-size:24px;line-height:32px;font-weight:500;margin:0;padding:0;color:#333c48}h3{font-size:20px;line-height:30px;font-weight:500;margin:0;padding:0;color:#333c48}h4{font-size:16px;line-height:24px;font-weight:500;margin:0;padding:0;color:#333c48}h5{font-size:14px;line-height:20px;font-weight:500;margin:0;padding:0;color:#333c48}h6{font-size:14px;line-height:18px;font-weight:500;margin:0;padding:0;color:#333c48}textarea,input,p,h1,h2,h3,h4,h5,h6,button{font-family:Inter !important}.el-table th{padding:9px 0px;box-sizing:border-box;text-transform:uppercase;font-size:12px;font-style:normal;font-weight:500;border-bottom-width:2px}.el-table th .cell{line-height:16px;letter-spacing:.5px}.el-table th:hover .sort-caret.ascending{border-bottom-color:#005def}.el-table th:hover .sort-caret.descending{border-top-color:#005def}.el-table th.is-leaf{border-bottom-width:2px;border-top:1px solid #eef2f5}.el-table td{padding:14px 0px;font-style:normal;font-weight:normal;font-size:14px;box-sizing:border-box}.el-table td .cell{line-height:20px}.el-table.el-table--has-options td .cell{line-height:23px}.el-table th:first-child .cell,.el-table td:first-child .cell{padding-left:16px}.el-table th:last-child .cell,.el-table td:last-child .cell{padding-right:16px}.el-table .caret-wrapper{height:15px}.el-table .sort-caret{border-width:4px}.el-table .sort-caret.ascending{top:-2px}.el-table .sort-caret.descending{bottom:-1px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#005def}.el-table .descending .sort-caret.descending{border-top-color:#005def}.el-table .cell{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.el-table .cell>.el-checkbox,.el-table .cell>.el-switch,.el-table .cell>.el-radio{overflow:unset}.el-table table{width:0px}.el-radio.is-autosized{padding:16px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized.is-bordered+.el-radio.is-autosized.is-bordered{margin-left:10px}.el-radio.is-autosized.is-bordered{border-color:#cfd6e4;display:flex;align-items:center}.el-radio.is-autosized.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized.is-bordered.is-checked{border-color:#0166d6}.el-radio.is-autosized-vstack{padding:12px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized-vstack .el-radio__label{justify-content:space-between;display:flex;width:100%;align-items:baseline}.el-radio.is-autosized-vstack.is-bordered{align-items:center}.el-radio.is-autosized-vstack.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized-vstack.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized-vstack.is-bordered.is-multiline .el-radio__label{padding-top:2px}.el-radio.is-autosized-vstack.is-bordered+.el-radio.is-autosized-vstack.is-bordered{margin-left:0;margin-top:7px}.el-radio.is-bordered{border:1px solid #cfd6e4}.el-radio:hover:not(.is-disabled) .el-radio__label{color:inherit}.el-radio.is-checked:not(.is-disabled):hover .el-radio__label{color:inherit}.el-radio__input.is-checked+.el-radio__label{color:inherit}.el-collapse.is-bordered-box{border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.el-collapse.is-bordered-box .el-collapse-item__header{border-radius:4px;padding:0rem 1.5rem 0rem 1.5rem}.el-collapse.is-bordered-box .el-collapse-item__header.is-active{border-bottom-color:#ececec}.el-collapse.is-bordered-box .el-collapse-item__wrap{background-color:rgba(0,0,0,0)}.el-collapse.is-bordered-box .el-collapse-item__content{margin:0rem 1.5rem 0rem 1.5rem}.el-switch__label *{font-weight:normal;color:#a7aeb8;font-size:12px}.el-input.is-adaptive .el-input__inner{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:10px;vertical-align:middle}.el-select .el-input.is-arrow .el-input__inner{padding-right:30px}.el-button.is-wireframe{background:rgba(0,0,0,0);border:1px dotted #0166d6;box-sizing:border-box;box-shadow:0px 2px 4px rgba(1,122,255,.07)}.el-button.el-button--text.is-danger{color:#d23f00}.el-button.el-button--text.is-danger:hover{background-color:#f6f6f6}.el-button.is-light-blue{box-shadow:none;-webkit-box-shadow:none;border:none;font-weight:500;height:32px}.el-button.is-light-blue:not(.is-disabled){color:#0166d6;background-color:#e1efff}.el-button.is-light-blue:not(.is-disabled):hover{background-color:#cce0f7}.el-button-group>.el-select{float:left}.el-button-group>.el-select:first-child .el-button{border-top-right-radius:0;border-bottom-right-radius:0;-webkit-box-shadow:none;box-shadow:none}.el-button-group>.el-select:not(:last-child){margin-right:-1px}.el-button-group>.el-select:active,.el-button-group>.el-select:focus,.el-button-group>.el-select:hover{z-index:1}.el-button-group>.el-select:active .el-button,.el-button-group>.el-select:focus .el-button,.el-button-group>.el-select:hover .el-button{z-index:1}.el-input-number.is-slim .el-input__inner{padding-left:5px;padding-right:26px}.el-input-number.is-slim.el-input-number--small .el-input-number__decrease,.el-input-number.is-slim.el-input-number--small .el-input-number__increase{width:22px;font-size:14px}.el-tabs--card>.el-tabs__header{margin:0}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap{margin-bottom:-2px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap.is-scrollable{border-bottom:none;border-top-right-radius:4px;border-top-left-radius:4px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next{background:linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{background:linear-gradient(270deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{opacity:.85}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next:hover,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev:hover{opacity:1}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-top-left-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{border-top-right-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item{background-color:#fcfcfc;padding:0;height:auto;text-align:left;line-height:32px;border-bottom:2px solid #ececec}.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#0166d6;background-color:#fff}.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0px}.el-radio-group.is-full{display:flex}.el-radio-group.is-full .el-radio-button{flex-grow:1}.el-radio-group.is-full .el-radio-button__inner{width:100%}.el-dropdown-menu__item{padding:7px 6px}.el-dropdown-menu__item>i.cly-icon-outline{padding:2px 7px}.el-select-dropdown .el-scrollbar__bar{opacity:1 !important;right:0}.el-select-dropdown__item{padding:7px 6px}.el-tiptap-editor{border-radius:4px}.el-tiptap-editor .el-tiptap-editor__menu-bar{border-color:#cfd6e4}.el-tiptap-editor .el-tiptap-editor__menu-bar::before{background-color:#cfd6e4}.el-tiptap-editor>.el-tiptap-editor__content{border:1px solid #cfd6e4 !important;border-top:0 !important;border-bottom:0 !important}.el-tiptap-editor>.el-tiptap-editor__content pre code{font-family:"Courier New"}.el-tiptap-editor .el-tiptap-editor__footer{border-color:#cfd6e4}.el-tiptap-editor .border-top-radius{border-top-left-radius:4px !important;border-top-right-radius:4px !important}.el-tiptap-editor .border-bottom-radius{border-bottom-left-radius:4px !important;border-bottom-right-radius:4px !important}.el-tiptap-editor .fa-icon{fill:#333c48}.el-tiptap-editor__content{overflow-x:unset !important}.el-tiptap-editor__content>pre>code{font-family:"Courier New" !important}.el-tiptap-editor__content span>span{background-color:inherit}.el-tiptap-editor__content hr{width:100%}.el-dialog.el-tiptap-edit-link-dialog .el-button.is-round{border-radius:4px}.el-dialog.el-tiptap-edit-link-dialog .el-button.el-button--primary{border-color:#12af51;background-color:#12af51}.el-checkbox__input .el-checkbox__inner{color:#fff;text-align:center}.el-checkbox__input.is-checked .el-checkbox__inner::before{content:"" !important;font-family:"countly-icons-outline" !important;border:none !important;position:absolute;top:0px;width:15px;left:0px}.el-checkbox__input.is-checked .el-checkbox__inner::after{border:none !important}.el-checkbox__input.is-checked.is-disabled .el-checkbox__inner{color:#d0d0d0}.el-checkbox__inner::after{display:none}.el-checkbox.is-checked .el-checkbox__inner::after{display:block}.el-upload__folder-preview-content{height:32px}.el-upload-dragger{background-color:#fcfcfc;display:flex;flex-direction:column;justify-content:center}.el-upload-dragger .fa-folder{line-height:0}.el-upload-list__item-name{background-color:#fff;width:100%;border:1px solid #ececec;border-radius:5px;height:68px;padding-left:unset;cursor:default !important}.el-upload-list__item-remove{margin-left:auto;margin-right:24px;cursor:pointer !important}.el-upload-list__item-preview .cly-io-document-text{font-size:20px;color:#000;margin-right:4px}.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#000}.bu-level:not(:last-child){margin-bottom:0px}.bu-tag.is-slim{padding:0 .5em;height:1.5em}.bu-tag.is-legend{padding:0;height:.5em;width:1em;border-radius:3px}.bu-tag.is-curved{border-radius:67px;height:16px;padding-left:4px;padding-right:4px;min-width:12px}.vjs-tree{padding:10px}.vjs-value-boolean,.vjs-value-number{color:#31acb4}.vjs-value-string{color:#6c47ff}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f0fb}.cly-vue-theme-clydef{background-color:#f8f9fa}#main-views-container{height:100%;width:100%;overflow:auto}#main-views-container .main-view{min-width:768px;min-height:400px;width:100%;padding:0px 0 35px 0 !important;transition:width .55s;will-change:width;overflow:auto}.cly-vue-main{padding:0px 24px;margin:0}.cly-vue-section--has-configurator-skin .cly-vue-section__content{background:#fff;border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.cly-vue-section--has-configurator-skin .cly-vue-section__content .cly-vue-section__sub{border-top:none !important;border-bottom:1px solid #ececec;align-items:center;display:flex}.cly-vue-section--has-default-skin .cly-vue-section__content{border-top:1px solid #ececec;border-bottom:1px solid #ececec}.cly-vue-section .cly-vue-section__content-config{border-bottom:1px solid #ececec}.cly-vue-section:not(:last-child){margin-bottom:32px}.cly-vue-header{padding:24px 24px;margin-bottom:32px;border-bottom:1px solid #ececec;position:relative}.cly-vue-header__level{padding-top:8px;padding-bottom:12px}.cly-vue-header__level--no-pt{padding-top:0px}.cly-vue-header__level--no-pb{padding-bottom:0px}.cly-vue-header--no-mb{margin-bottom:0px}.cly-vue-header--no-bb{border-bottom:none}.cly-vue-header+div>.cly-vue-tabs{background-color:#fff;border-bottom:1px solid #ececec;margin-bottom:32px;padding:0px 24px}.cly-vue-select-x__pop .cly-vue-checklistbox__item-content{display:inline-flex;align-items:center}.cly-vue-select-x__pop .cly-vue-checklistbox__item-prefix{display:inline-flex;align-items:center;margin-right:6px}.cly-vue-select-x__pop .cly-vue-listbox{background-color:rgba(0,0,0,0) !important}.cly-vue-select-x__pop .el-tabs__active-bar{background-color:#0166d6}.cly-vue-select-x__pop .el-tabs__nav-wrap::after{background-color:rgba(0,0,0,0)}.cly-vue-select-x__pop .el-tabs__nav-scroll{margin:0 14px}.cly-vue-select-x__pop .el-tabs__header{margin:0 0 1px 0;z-index:2000}.cly-vue-select-x__pop .el-tabs__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:40px;opacity:.12}.cly-vue-select-x__pop--hidden-tabs .el-tabs__header::after{top:0px}.cly-vue-select-x__pop--hidden-tabs .el-tabs__nav-scroll{display:none}.cly-vue-select-x__pop--hidden-header .cly-vue-select-x__header{padding:0}.cly-vue-select-x__pop--hidden-tabs.cly-vue-select-x__pop--hidden-header .el-tabs__header::after{background:none;height:0;width:0}.cly-vue-select-x__title{font-weight:500;font-size:16px;line-height:24px;color:#333c48;padding-bottom:16px}.cly-vue-select-x__header-slot{padding-bottom:16px}.cly-vue-select-x__header{padding:16px}.cly-vue-select-x__header input[type=text]{background-color:#f6f6f6}.cly-vue-select-x__footer{border-top:1px solid #ececec}.cly-vue-select-x__commit-section{float:right;margin:16px}.cly-vue-select-x__pop--has-single-option .cly-vue-select-x__header-slot,.cly-vue-select-x__pop--has-slim-header .cly-vue-select-x__header-slot{padding:0}.cly-vue-select-x__pop--has-single-option .el-tabs__header::after{content:none}.cly-vue-select-x .el-select-head{width:100%}.cly-vue-listbox{background-color:#fff}.cly-vue-listbox label.el-checkbox{width:100%;margin-left:8px}.cly-vue-listbox.is-expandable{transition:width 200ms;width:100%;z-index:100}.cly-vue-listbox.is-expanded{width:130%;position:relative;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.08);box-shadow:0 1px 4px rgba(0,0,0,.08)}.cly-vue-listbox.cly-vue-listbox--bordered{border-radius:4px;border:1px solid #ececec}.cly-vue-listbox .cly-vue-listbox__no-data{padding:8px;line-height:20px;font-weight:500;color:#333c48;font-size:14px}.cly-vue-listbox .el-checkbox-group{overflow:hidden}.cly-vue-listbox .el-checkbox__label{line-height:20px;font-weight:400;color:#333c48;max-width:330px !important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom}.cly-vue-listbox .el-checkbox__input.is-checked+.el-checkbox__label{color:#333c48}.cly-vue-listbox .drag-handler{visibility:hidden;margin-right:8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cly-vue-listbox__header{margin:0 0 1px 0;z-index:1997;border-bottom:1px solid #ececec;position:relative}.cly-vue-listbox__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:57px;left:0;opacity:.12}.cly-vue-listbox .cly-vue-listbox__group{font-size:12px;line-height:14px;background-color:#f6f6f6;border-bottom:solid 1px #ececec;max-height:32px;display:flex;align-items:center;padding:8px}.cly-vue-listbox .cly-vue-listbox__item{display:flex;cursor:pointer;align-items:center;justify-content:space-between}.cly-vue-listbox .cly-vue-listbox__item.selected{background-color:#0166d6}.cly-vue-listbox .cly-vue-listbox__item.selected *{color:#fff}.cly-vue-listbox .cly-vue-listbox__item .cly-vue-listbox__remove-option{display:none}.cly-vue-listbox .cly-vue-listbox__item.hover .cly-vue-listbox__remove-option{display:block}.cly-vue-listbox .cly-vue-listbox__item-content{width:100%}.cly-vue-listbox__item-label{max-width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-listbox--disabled .cly-vue-listbox__item{background-color:#f6f6f6}.cly-vue-listbox--disabled .cly-vue-listbox__item *{color:#a7aeb8}.cly-vue-listbox--disabled .cly-vue-listbox__item.selected{opacity:.5}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover{background-color:#f6f6f6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .drag-handler{visibility:visible}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix *{color:#0166d6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item .cly-vue-listbox__remove-option:hover{color:#0166d6}.cly-vue-listbox--has-default-skin .cly-vue-listbox__item{padding:8px;border-radius:4px;line-height:16px}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item{padding:8px;height:55px;box-sizing:border-box;border-bottom:1px solid #ececec}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected{border-left:2px solid #0166d6;background-color:#f6f6f6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected *{color:#0166d6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item:last-child{border-bottom:none}.cly-vue-listbox--has-margin .cly-vue-listbox__item{margin:8px}.cly-fields-select.default-skin{display:inline-block}.cly-fields-select.default-skin .el-input__inner::placeholder{color:#000}.cly-fields-select.default-skin .fields-select-body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:0px;z-index:100;border:1px solid #d0d0d0;border-radius:2px;padding:16px;width:max-content}.cly-fields-select.default-skin .fields-select-body .controls{float:right;margin-top:10px}.cly-fields-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-fields-select__reset{float:right;font-size:12px;padding-bottom:26px;padding-top:0px;color:#d23f00;cursor:pointer;line-height:20px}.cly-fields-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-fields-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-fields-select__confirm{background-color:#12af51;color:#fff}.cly-fields-select__cancel{background:#f6f6f6}.cly-fields-select__dropdown .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin{display:inline-block}.cly-multi-select.default-skin .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin .cly-multi-select__body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:-2px;left:-2px;z-index:100;border:1px solid #d0d0d0;border-radius:4px;padding:16px;width:max-content}.cly-multi-select.default-skin .cly-multi-select__controls{float:right;margin-top:10px}.cly-multi-select__title-wrapper{margin-bottom:30px}.cly-multi-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-multi-select__reset{float:right;font-size:12px;padding:4px 8px;color:#d23f00;cursor:pointer;line-height:20px}.cly-multi-select__reset span{height:20px;line-height:20px}.cly-multi-select__reset:hover{background:#f6f6f6}.cly-multi-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-multi-select .cly-multi-select__confirm-button{margin-left:4px}.cly-multi-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-multi-select__dropdown .el-input__inner::placeholder{color:#000}.cly-vue-dropdown__pop{padding:0px;width:fit-content}.cly-vue-dropdown__pop-container{word-break:initial}.cly-vue-dropdown__dropdown-icon{width:16px;line-height:16px;height:16px;background-size:16px 16px;border-radius:4px;background-position:center;background-color:#017aff;display:inline-block}.cly-vue-more-options .el-button{border:1px solid #cfd6e4}.cly-vue-more-options .el-button .is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.cly-vue-eldatatable.silent-loading .el-loading-spinner{visibility:hidden}.cly-vue-eldatatable.silent-loading .el-loading-mask{display:none !important}.cly-vue-eldatatable.display-mode--list .el-table{background-color:unset}.cly-vue-eldatatable.display-mode--list .el-table__body{border-collapse:separate;border-spacing:0 8px}.cly-vue-eldatatable.display-mode--list .el-table__row{cursor:pointer}.cly-vue-eldatatable.display-mode--list .el-table__row td{cursor:pointer;height:56px;border-top:1px solid #ececec !important;border-bottom:2px solid #ececec !important;background-color:#fff !important;padding:18px 0px}.cly-vue-eldatatable.display-mode--list .el-table__row td:first-child{border-left:1px solid #ececec !important;border-radius:4px 0 0 4px !important}.cly-vue-eldatatable.display-mode--list .el-table__row td:last-child{border-right:1px solid #ececec !important;border-radius:0 4px 4px 0 !important}.cly-vue-eldatatable.display-mode--list .el-table__row td .cell{line-height:20px}.cly-vue-eldatatable.display-mode--list .el-table__row td.drag-icon .cell{text-overflow:unset !important}.cly-vue-eldatatable.display-mode--list .el-table thead tr{background-color:unset !important}.cly-vue-eldatatable.display-mode--list .el-table th{background-color:unset !important;border:none !important;padding:0 !important;color:#81868d !important}.cly-vue-eldatatable.display-mode--list .el-table__fixed-right::before{height:0 !important}.cly-vue-eldatatable__header{height:56px;border-left:none;border-right:none;box-sizing:border-box;padding:12px;border-top:1px solid #ececec}.cly-vue-eldatatable__header--white{background-color:#fff;color:#333c48;font-size:13px}.cly-vue-eldatatable__export--extended::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:185px;left:0;opacity:.12}.cly-vue-eldatatable__export--fileExport{border-top:1px solid #e2e4e8}.cly-vue-eldatatable__export--radio-button .el-radio-button{width:99px;display:inline-grid}.cly-vue-eldatatable__export--search input[type=text]{background-color:#f6f6f6}.cly-vue-eldatatable__search--grey input{background-color:#fbfdfe}.cly-vue-eldatatable__footer{height:40px;box-shadow:0px 2px 0px #eef2f5;border-left:none;border-right:none;box-sizing:border-box;padding:0px 12px}.cly-vue-eldatatable__footer--white{background-color:#fff;color:#808a9d;font-size:13px}.cly-vue-eldatatable .undo-row{position:absolute;left:0;padding:9px 0px;background-color:#ffd7d6;color:#2b2b2b;width:100%;height:100%;top:0;z-index:999;vertical-align:middle;display:flex;align-items:center;justify-content:center}.cly-vue-eldatatable .undo-row a{color:#017aff;cursor:pointer}.cly-vue-eldatatable .el-table-column--options .cly-vue-more-options{position:absolute;top:calc(50% - 16px);right:calc(50% - 20px)}.cly-vue-eldatatable div.cell{padding-left:16px;padding-right:8px}.cly-vue-eldatatable__empty-slot{height:200px}.cly-vue-table{width:100%}.cly-vue-table thead{background-color:#f6f6f6;border-top:1px solid #ececec;border-bottom:2px solid #ececec}.cly-vue-table thead th{color:#333c48;font-weight:500;font-size:12px;padding:9px;text-align:left}.cly-vue-table tbody td{padding:0px 9px}.cly-vue-chart{position:relative}.cly-vue-chart .bu-level{padding:0 20px 0 33px}.cly-progress-bar-container{width:100%}.cly-progress-bar-container.has-min-bradius .first-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:4px;border-top-left-radius:4px}.cly-progress-bar-container.has-min-bradius .last-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:4px;border-top-right-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__outer{border-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__inner{border-radius:4px}.cly-progress-bar-stack-container{float:left}.progress-bar-stack .el-progress-bar__inner{border-radius:0px}.first-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:0px;border-top-right-radius:0px}.middle-progress-bar-stack .el-progress-bar__outer{border-radius:0px}.last-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:0px;border-top-left-radius:0px}.cly-vue-tabs__primary-tab-list{padding:24px;box-sizing:border-box}.cly-vue-tabs__tab{height:34px;padding:10px 12px;display:inline-block;box-sizing:border-box}.cly-vue-tabs__tab--default{color:#81868d;line-height:14px;font-weight:500;font-size:14px;cursor:pointer}.cly-vue-tabs__tab--primary{border-radius:6px}.cly-vue-tabs__tab--primary:hover{color:#0166d6}.cly-vue-tabs__tab--secondary:hover{color:#333c48}.cly-vue-tabs__tab--primary-active{color:#0166d6;background-color:#e1efff}.cly-vue-tabs__tab--secondary-active{color:#333c48;border-bottom:2px solid #0166d6}.cly-vue-chart{width:100%;height:100%}.cly-vue-chart__echart{box-sizing:border-box;display:inline-block;width:100%}.cly-vue-chart--padded .cly-vue-chart__echart{padding-top:20px}.cly-vue-chart--full .cly-vue-chart__echart{padding:0}.cly-vue-chart-legend{display:inline-block;width:100%}.cly-vue-chart-legend__primary,.cly-vue-chart-legend__secondary{white-space:nowrap;overflow:auto;box-sizing:border-box;height:100%}.cly-vue-chart-legend__secondary--text-center{text-align:center}.cly-vue-chart-legend__p-series{display:inline-block;margin-left:64px;cursor:pointer}.cly-vue-chart-legend__p-series:first-child{margin-left:36px}.cly-vue-chart-legend__s-series{display:inline-block;margin-left:48px;cursor:pointer}.cly-vue-chart-legend__s-series:first-child{margin-left:0px}.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-rectangle,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-percentage{color:#a7aeb8}.cly-vue-chart-legend__second-row{margin-top:3px}.cly-vue-chart-legend__p-checkbox{height:16px;width:16px;border:1px solid #a7aeb8;display:inline-block;box-shadow:inset 0 0 0px 1.5px #fff;border-radius:4px;vertical-align:middle;box-sizing:border-box}.cly-vue-chart-legend__p-title{display:inline-block;vertical-align:middle;font-size:14px;color:#333c48}.cly-vue-chart-legend__p-tooltip{display:inline-block}.cly-vue-chart-legend__p-tooltip i{font-size:15px}.cly-vue-chart-legend__p-number{display:inline-block;font-size:24px;font-weight:500;color:#333c48}.cly-vue-chart-legend__p-trend{display:inline-block;font-size:14px;font-weight:500}.cly-vue-chart-legend__p-trend--trend-up{color:#12af51}.cly-vue-chart-legend__p-trend--trend-down{color:#d23f00}.cly-vue-chart-legend__s-rectangle{width:12px;height:6px;border-radius:3px;display:inline-block;vertical-align:middle;margin:0px 5px}.cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-percentage{display:inline-block;vertical-align:middle;margin-left:3px;font-size:12px;font-weight:400;color:#333c48}.cly-vue-chart-legend__bottom .cly-vue-chart-legend__primary,.cly-vue-chart-legend__bottom .cly-vue-chart-legend__secondary{padding:0px 24px 20px}.cly-vue-chart-legend__right{border-left:1px solid #ececec;width:265px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{margin-left:0px;padding:3px 7px;box-sizing:border-box;width:100%;display:block;border-bottom:1px solid #ececec}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{background-color:#f6f6f6;border-radius:0px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-percentage{font-weight:500}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{font-size:14px;line-height:30px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 30px);text-align:left}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{min-width:50px;text-align:right}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:10px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__view::before{content:"";position:absolute;width:100%;height:8px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie{border-left:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary{padding-top:30px;padding-bottom:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{border:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{border-radius:8px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 86px)}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:3px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view{display:flex;flex-direction:column;justify-content:center;padding-right:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view::before{background:none;height:0}.chart-type-toggle-wrapper__select{width:126px}.chart-type-toggle-wrapper__title{margin-top:16px;margin-left:16px;letter-spacing:.5px}.chart-type-toggle-wrapper__type{font-family:Inter;font-style:normal;font-weight:500;font-size:13px;line-height:13px}.chart-type-annotation-wrapper__icon{margin-top:1px}.chart-type-annotation-wrapper__img{margin-bottom:-2px}.chart-zoom-button{margin-right:12px}.cly-vue-zoom__external .chart-zoom-button{margin:0}.chart-download-button{width:42px;height:32px}.shadow-container{position:relative}.shadow-container:after{display:block;content:"";position:absolute;width:100%;margin:0 auto;height:70px;border:0;bottom:0;background:linear-gradient(180deg, rgba(255, 255, 255, 0.7) 0%, #FFFFFF 100%)}.chart-tooltip{max-height:360px;overflow:auto;margin-bottom:2px;max-width:300px;white-space:nowrap}.chart-tooltip__header{letter-spacing:.5px;text-transform:uppercase}.chart-tooltip__body{background-color:#fff;margin-bottom:16px;margin-top:16px}.chart-tooltip__body:last-child{margin-bottom:0 !important}.chart-tooltip__body.chart-tooltip__single-row{display:flex;margin-bottom:14px;margin-top:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__bar{margin-top:6px;float:none}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__series{display:flex;flex-direction:column;justify-content:space-between;width:calc(100% - 24px);margin-left:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__value{margin-top:-3px;margin-left:30px;display:flex;flex-direction:column;justify-content:space-between}.chart-tooltip__has-scroll .chart-tooltip__value{margin-right:10px}.chart-tooltip__bar{float:left;width:12px;min-width:12px;height:6px;border-radius:3px;margin-top:5px}.chart-tooltip__series{margin-left:24px;overflow:hidden}.chart-tooltip__series span{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.chart-tooltip__value{margin-top:2px;margin-left:24px}.graph-notes-tooltip{width:286px;max-height:118px;overflow:auto}.graph-notes-tooltip__header{width:100%}.graph-notes-tooltip__header .input-owner{font-weight:500}.graph-notes-tooltip__header .name-wrapper{margin-top:10px}.graph-notes-tooltip__header .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-notes-tooltip__header .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5;background-color:#f6f6f6}.graph-notes-tooltip__header .note-type{margin-top:12px}.graph-notes-tooltip__body{margin-top:12px}.graph-notes-tooltip__body .input-notes{word-break:break-word;display:inline-block;white-space:normal}.graph-notes-tooltip.minimize{width:180px}.graph-notes-tooltip.minimize .input-owner{font-size:12px}.graph-notes-tooltip.minimize__header{margin-top:0px}.graph-notes-tooltip.minimize .input-notes{font-size:12px}.graph-notes-tooltip.minimize .input-minimizer{margin-bottom:10px}.graph-notes-tooltip.minimize .graph-notes-tooltip__body{margin-top:5px}.graph-notes-tooltip.minimize .name-wrapper{margin-top:0px}.graph-notes-tooltip.minimize .note-date{font-size:11px}.graph-notes-tooltip.minimize .note-type{margin-top:2px;font-size:11px;margin-right:4px}.graph-tooltip-wrapper{margin-right:2px;margin-bottom:4px}.graph-tooltip-wrapper .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-tooltip-wrapper .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5}.graph-tooltip-wrapper__container{max-height:180px;overflow:hidden;overflow:auto}.cly-vue-tooltip-icon{font-size:17px;color:#a7aeb8;vertical-align:middle;width:18px;height:18px}.cly-in-page-notification{border-radius:4px;text-align:center;margin-bottom:32px}.cly-in-page-notification--light-informational{background-color:#e1efff;color:#333c48}.cly-in-page-notification--light-successful{background-color:#ebfaee;color:#333c48}.cly-in-page-notification--light-destructive{background-color:#fbece5;color:#333c48}.cly-in-page-notification--light-warning{background-color:#fcf5e5;color:#333c48}.cly-in-page-notification--dark-successful{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-informational{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-warning{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-destructive{background-color:#24292e;color:#fff}.cly-in-page-notification a:hover{text-decoration:underline;cursor:hand}.cly-vue-back-link{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase;margin-bottom:24px}.cly-vue-back-link:visited{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase}.cly-vue-back-link:hover span{text-decoration:underline}.cly-divider{width:100%;border-top:1px solid #ececec}.cly-divider.is-2{border-top-width:2px}.cly-divider.is-dashed{border-top-style:dashed}.cly-divider.is-dotted{border-top-style:dotted}.cly-event-select .el-radio-group{display:flex}.cly-event-select .el-radio-button{flex-grow:1}.cly-event-select .el-radio-button__inner{width:100%}.cly-vue-color-tag__color-tag-wrapper{width:20%}.cly-vue-color-tag__color-tag{width:92%;height:37px;margin-bottom:5px;border-radius:4px}.cly-vue-color-tag__color-tag__selected{border:2px solid #0166d6}.cly-vue-color-tag__checkmark{color:#fff}.cly-vue-empty-view-framed{border:1px solid #e2e4e8;background-color:#f8fafd;border-radius:8px;background-image:url("../images/icons/empty-background.svg");background-position:100% 100%;background-repeat:no-repeat}.cly-vue-json-editor .el-dialog__header{text-align:left;padding:8px 16px 0 !important;color:#fff}.cly-vue-json-editor .el-dialog__body{padding:0 !important}.cly-vue-json-editor__textarea{width:100%;box-sizing:border-box;outline:none;border:none;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fcfcfc}.cly-breadcrumbs a:hover{text-decoration:underline}.cly-is-fullwidth{width:100%}.is-estimate:hover{color:#0166d6;text-decoration:underline;text-decoration-style:dotted}#cly-vue-sidebar{left:0;height:100%;z-index:2000;user-select:none;color:#d6d6d6}.cly-vue-sidebar{height:100%}.cly-vue-sidebar .tooltip{display:block !important;z-index:10000}.cly-vue-sidebar .tooltip .tooltip-inner{background:#fff;color:#000}.cly-vue-sidebar .tooltip .tooltip-arrow{display:none}.cly-vue-sidebar .tooltip[x-placement^=right]{margin-left:0px}.cly-vue-sidebar .cly-vue-listbox__item-label{width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-sidebar__slide-transition-enter-active{transition:all .3s ease}.cly-vue-sidebar__slide-transition-leave-active{transition:all .8s cubic-bezier(1, 0.5, 0.8, 1)}.cly-vue-sidebar__slide-transition-enter,.cly-vue-sidebar__slide-transition-leave-to{transform:translateX(-224px)}.cly-vue-sidebar ul{list-style:none;padding:0;margin:0}.cly-vue-sidebar ul li{padding:0px}.cly-vue-sidebar__app-selector__dialog_box .el-dialog__body{padding:0px !important}.cly-vue-sidebar .el-collapse{border:none}.cly-vue-sidebar__app-name{font-size:14px}.cly-vue-sidebar__app-name-type{width:120px}.cly-vue-sidebar__app-selector{border:1px solid #424243;box-sizing:border-box;box-shadow:0px 11px 14px rgba(0,0,0,.371635);border-radius:4px;height:50px}.cly-vue-sidebar__app-type{opacity:.57}.cly-vue-sidebar__menu-options{width:48px;height:100%;overflow:auto;color:#a7aeb8;z-index:2005;background-color:#191c20}.cly-vue-sidebar__menu-options ul:first-child li:first-child{margin-top:28px}.cly-vue-sidebar__menu-option{width:48px;margin-top:24px;font-size:20px;cursor:pointer}.cly-vue-sidebar__menu-option .el-popover__reference:hover{color:#fff !important}.cly-vue-sidebar__menu-option-toggle{height:48px;background-color:#24292e;border-top-left-radius:50%;border-bottom-left-radius:50%}.cly-vue-sidebar__menu-option-toggle--no-bg{background-color:rgba(0,0,0,0)}.cly-vue-sidebar__menu-option-toggle--rotate-right{transform:rotate(180deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu-option-toggle--rotate-left{transform:rotate(0deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu{width:224px;background-color:#24292e;color:#d6d6d6;box-sizing:border-box;height:100%;overflow:hidden;z-index:2004;position:relative}.cly-vue-sidebar__menu--with-banner .__view{padding-bottom:200px}.cly-vue-sidebar__menu-items,.cly-vue-sidebar__submenu-items,.cly-vue-sidebar .el-collapse-item__header{line-height:20px;height:20px;background-color:#24292e;color:#d6d6d6;border:none;font-size:14px;padding:0;font-weight:400;font-family:Inter;padding:6px 12px}.cly-vue-sidebar__menu-items .el-collapse-item__arrow,.cly-vue-sidebar__submenu-items .el-collapse-item__arrow,.cly-vue-sidebar .el-collapse-item__header .el-collapse-item__arrow{margin-right:0px}.cly-vue-sidebar__menu-items:hover,.cly-vue-sidebar__submenu-items:hover,.cly-vue-sidebar .el-collapse-item__header:hover{background-color:#383a3f;color:#fff;border-radius:4px}.cly-vue-sidebar__menu-items--selected,.cly-vue-sidebar__submenu-items--selected,.cly-vue-sidebar .el-collapse-item__header--selected{background-color:#12af51;border-radius:4px;color:#fff}.cly-vue-sidebar__menu-items--selected:hover,.cly-vue-sidebar__submenu-items--selected:hover,.cly-vue-sidebar .el-collapse-item__header--selected:hover{background-color:#12af51;border-radius:4px}.cly-vue-sidebar .el-collapse-item__header.focusing:focus:not(:hover){color:#d6d6d6}.cly-vue-sidebar .el-collapse-item .cly-vue-sidebar__submenu-items{padding-left:32px}.cly-vue-sidebar__el-collapse--selected .el-collapse-item__header{border-radius:4px;background-color:#383a3f;color:#fff}.cly-vue-sidebar .el-collapse-item__content{margin:0;padding:0}.cly-vue-sidebar .el-collapse-item__wrap{border-bottom:1px solid #424243;background-color:#24292e;box-shadow:0px 1px 0px rgba(0,0,0,.4)}.cly-vue-sidebar__header{padding:16px 12px;position:relative}.cly-vue-sidebar__header-search input{background-color:#383a3f;border:none;color:#d6d6d6}.cly-vue-sidebar__header-search input:focus{outline:none;box-shadow:none}.cly-vue-sidebar__header-title{font-size:16px;line-height:24px;font-weight:500;display:inline-block;margin-top:12px}.cly-vue-sidebar__header-button{float:right;top:5px;position:relative}.cly-vue-sidebar__main-menu{overflow:auto;height:calc(100% - 130px)}.cly-vue-sidebar__app-image{width:26px;height:26px;background-size:26px 26px;border-radius:4px;background-position:center;display:inline-block}.cly-vue-sidebar__user-popper{box-sizing:border-box;font-family:Inter;padding:14px 0px;box-shadow:0px 2px 7px rgba(0,0,0,.18815);color:#333c48}.cly-vue-sidebar__language-popper{font-family:Inter;padding:0px;min-width:130px;box-shadow:0px 2px 7px rgba(0,0,0,.18815)}.cly-vue-sidebar__user-details .bu-level{padding:6px 12px}.cly-vue-sidebar__user-links .bu-level{padding:6px;margin:0px 6px}.cly-vue-sidebar__user-links .bu-level:hover{background-color:#f1f3f4;color:#0166d6;border-radius:4px}.cly-vue-sidebar__user-links .bu-level:hover .bu-level-item i{color:#333c48}.cly-vue-sidebar__user-links .bu-level .bu-level-item:first-child{width:15px}.cly-vue-sidebar__user-links .bu-level .bu-level-item i{color:#a7aeb8}.cly-vue-sidebar__user-info{width:140px}.cly-vue-sidebar__user-info p{padding:0;margin:0}.cly-vue-sidebar__user-info p:first-child{font-size:16px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-info p:last-child{margin-top:7px;line-height:17px;font-size:14px;font-weight:400}.cly-vue-sidebar__user-api{width:192px}.cly-vue-sidebar__user-api p{padding:0;margin:0}.cly-vue-sidebar__user-api p:first-child{font-size:12px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-api p:last-child{margin-top:7px;line-height:17px;font-size:12px;font-weight:400}.cly-vue-sidebar__user-image{height:50px;width:50px;border-radius:25px;text-align:center}.cly-vue-sidebar__user-initials{text-transform:uppercase;color:#fff;font-size:16px}.cly-vue-sidebar__user-divider{border:1px solid #ececec;margin-top:5px;position:relative}.cly-vue-sidebar__version{position:absolute;bottom:0;height:48px;display:flex;align-items:center;justify-content:center;width:224px;font-size:10px;background-color:#24292e}.cly-vue-sidebar__version__banner{position:absolute;bottom:12px;left:12px;right:12px;z-index:2001;cursor:default;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:#191c20;border-radius:4px;padding:16px}.cly-vue-sidebar__version__banner .button{width:100%;margin-top:12px}.cly-vue-sidebar__version__banner .text{font-size:14px;color:#fff}.cly-vue-sidebar .cly-icon-sidebar-app{background-image:url("../images/sidebar/default/app.svg");height:24px;width:24px}.cly-vue-sidebar .cly-icon-sidebar-analytics{background-image:url("../images/sidebar/default/analytics-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-analytics:hover{background-image:url("../images/sidebar/hover/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-analytics.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards{background-image:url("../images/sidebar/default/dashboards-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-dashboards:hover{background-image:url("../images/sidebar/hover/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-divider{background-image:url("../images/sidebar/default/divider.svg");width:32px;height:1px}.cly-vue-sidebar .cly-icon-sidebar-management{background-image:url("../images/sidebar/default/management.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-management:hover{background-image:url("../images/sidebar/hover/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-management.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager{background-image:url("../images/sidebar/default/report-manager.svg");height:18px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-report-manager:hover{background-image:url("../images/sidebar/hover/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center{background-image:url("../images/sidebar/default/help-center.svg");height:25px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-help-center:hover{background-image:url("../images/sidebar/hover/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications{background-image:url("../images/sidebar/default/notifications.svg");height:23px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-notifications:hover{background-image:url("../images/sidebar/hover/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-toggle-left{background-image:url("../images/sidebar/default/toggle-left.svg");height:15px;width:11px}.cly-vue-sidebar--floating{position:absolute;left:48px}.notification-toasts{position:absolute;right:24px;bottom:24px;z-index:600000}.notification-toasts__item{margin-top:12px;min-width:288px;max-width:288px}.notification-toasts__item--small{max-width:288px}.notification-toasts__item--large{max-width:611px}.font-weight-bold{font-weight:600 !important}.font-weight-normal{font-weight:400 !important}.font-italic{font-style:italic !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-big{color:#333c48;font-size:16px;font-weight:400;line-height:22px}.text-big.font-weight-bold{font-weight:500 !important}.text-medium{color:#333c48;font-size:14px;font-weight:400;line-height:20px}.text-medium.font-weight-bold{font-weight:500 !important}.text-smallish{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-smallish.font-weight-bold{font-weight:500 !important}.text-small{color:#333c48;font-size:12px;font-weight:400;line-height:18px}.text-small.font-weight-bold{font-weight:500 !important}.text-heading.text-big{line-height:24px;font-weight:500 !important;margin-bottom:16px}.text-heading.text-medium{line-height:20px;font-weight:500 !important;margin-bottom:8px}.text-heading.text-small{line-height:18px;font-weight:500 !important;margin-bottom:4px}.text-smaller{color:#333c48;font-size:10px;font-weight:400;line-height:12px}.text-smaller.font-weight-bold{font-weight:500 !important}.text-smallest{color:#333c48;font-size:10px;font-weight:700;line-height:12px}.text-smallest.font-weight-bold{font-weight:500 !important}.text-button{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-button.font-weight-bold{font-weight:500 !important}.cly-trend-up,.cly-trend-down,.cly-trend-neutral{font-size:14px;font-weight:500}.cly-trend-up,.cly-trend-down.negated{color:#12af51}.cly-trend-down,.cly-trend-up.negated{color:#d23f00}.cly-trend-neutral{color:#81868d}.cly-trend-up-icon,.cly-trend-down-icon,.cly-trend-neutral-icon{border-radius:50%;margin-right:4px;display:inline-block;width:17px;height:17px;text-align:center;line-height:17px}.cly-trend-up-icon{background-color:#ebfaee}.cly-trend-down-icon{background-color:#fbece5}.cly-trend-neutral-icon{background-color:#e2e4e8}.cly-trend-up.negated .cly-trend-up-icon{background-color:#fbece5}.cly-trend-down.negated .cly-trend-down-icon{background-color:#ebfaee}.cursor-pointer{cursor:pointer}.icon-size-1{font-size:6px}.icon-size-2{font-size:8px}.icon-size-3{font-size:10px}.icon-size-4{font-size:12px}.icon-size-5{font-size:14px}.icon-size-6{font-size:16px}.text-clickable{cursor:pointer}.color-white{color:#fff !important}.bg-white{background-color:#fff !important}.color-black{color:#000 !important}.bg-black{background-color:#000 !important}.color-warm-gray-100{color:#24292e !important}.bg-warm-gray-100{background-color:#24292e !important}.color-warm-gray-90{color:#24292e !important}.bg-warm-gray-90{background-color:#24292e !important}.color-warm-gray-80{color:#383a3f !important}.bg-warm-gray-80{background-color:#383a3f !important}.color-warm-gray-70{color:#424243 !important}.bg-warm-gray-70{background-color:#424243 !important}.color-warm-gray-60{color:#616165 !important}.bg-warm-gray-60{background-color:#616165 !important}.color-warm-gray-40{color:#d6d6d6 !important}.bg-warm-gray-40{background-color:#d6d6d6 !important}.color-warm-gray-30{color:#ececec !important}.bg-warm-gray-30{background-color:#ececec !important}.color-warm-gray-20{color:#f6f6f6 !important}.bg-warm-gray-20{background-color:#f6f6f6 !important}.color-warm-gray-10{color:#fcfcfc !important}.bg-warm-gray-10{background-color:#fcfcfc !important}.color-cool-gray-100{color:#333c48 !important}.bg-cool-gray-100{background-color:#333c48 !important}.color-cool-gray-50{color:#81868d !important}.bg-cool-gray-50{background-color:#81868d !important}.color-cool-gray-40{color:#a7aeb8 !important}.bg-cool-gray-40{background-color:#a7aeb8 !important}.color-cool-gray-30{color:#cfd6e4 !important}.bg-cool-gray-30{background-color:#cfd6e4 !important}.color-cool-gray-20{color:#e2e4e8 !important}.bg-cool-gray-20{background-color:#e2e4e8 !important}.color-cool-gray-10{color:#f8fafd !important}.bg-cool-gray-10{background-color:#f8fafd !important}.color-cool-gray-05{color:#fbfdfe !important}.bg-cool-gray-05{background-color:#fbfdfe !important}.color-charts-blue{color:#017aff !important}.bg-charts-blue{background-color:#017aff !important}.color-charts-turquoise{color:#39c0c8 !important}.bg-charts-turquoise{background-color:#39c0c8 !important}.color-charts-light-turquoise{color:#ebf9f9 !important}.bg-charts-light-turquoise{background-color:#ebf9f9 !important}.color-charts-amber{color:#f5c900 !important}.bg-charts-amber{background-color:#f5c900 !important}.color-charts-orange{color:#f96300 !important}.bg-charts-orange{background-color:#f96300 !important}.color-charts-light-orange{color:#feefe5 !important}.bg-charts-light-orange{background-color:#feefe5 !important}.color-charts-magenta{color:#f34971 !important}.bg-charts-magenta{background-color:#f34971 !important}.color-charts-light-magenta{color:#feedf1 !important}.bg-charts-light-magenta{background-color:#feedf1 !important}.color-charts-coral{color:#ff9382 !important}.bg-charts-coral{background-color:#ff9382 !important}.color-charts-violet{color:#da6efc !important}.bg-charts-violet{background-color:#da6efc !important}.color-charts-purple{color:#6c47ff !important}.bg-charts-purple{background-color:#6c47ff !important}.color-charts-light-purple{color:#f0edff !important}.bg-charts-light-purple{background-color:#f0edff !important}.color-charts-tan{color:#cdad7a !important}.bg-charts-tan{background-color:#cdad7a !important}.color-charts-olive{color:#aabb5d !important}.bg-charts-olive{background-color:#aabb5d !important}.color-charts-scarlet{color:#f62404 !important}.bg-charts-scarlet{background-color:#f62404 !important}.color-charts-pink{color:#ffb6f5 !important}.bg-charts-pink{background-color:#ffb6f5 !important}.color-yellow-100{color:#e49700 !important}.bg-yellow-100{background-color:#e49700 !important}.color-yellow-70{color:#ffc760 !important}.bg-yellow-70{background-color:#ffc760 !important}.color-yellow-20{color:#fff4ce !important}.bg-yellow-20{background-color:#fff4ce !important}.color-yellow-10{color:#fcf5e5 !important}.bg-yellow-10{background-color:#fcf5e5 !important}.color-blue-100{color:#0166d6 !important}.bg-blue-100{background-color:#0166d6 !important}.color-blue-90{color:#1a75da !important}.bg-blue-90{background-color:#1a75da !important}.color-blue-80{color:#3485de !important}.bg-blue-80{background-color:#3485de !important}.color-blue-70{color:#4d94e2 !important}.bg-blue-70{background-color:#4d94e2 !important}.color-blue-60{color:#67a3e6 !important}.bg-blue-60{background-color:#67a3e6 !important}.color-blue-50{color:#80b3eb !important}.bg-blue-50{background-color:#80b3eb !important}.color-blue-40{color:#99c2ef !important}.bg-blue-40{background-color:#99c2ef !important}.color-blue-30{color:#b3d1f3 !important}.bg-blue-30{background-color:#b3d1f3 !important}.color-blue-20{color:#cce0f7 !important}.bg-blue-20{background-color:#cce0f7 !important}.color-blue-10{color:#e6f0fb !important}.bg-blue-10{background-color:#e6f0fb !important}.color-sky-blue-100{color:#3f9aff !important}.bg-sky-blue-100{background-color:#3f9aff !important}.color-shadow-blue-100{color:#9cbce0 !important}.bg-shadow-blue-100{background-color:#9cbce0 !important}.color-light-blue-100{color:#e1efff !important}.bg-light-blue-100{background-color:#e1efff !important}.color-dark-blue-100{color:#32659d !important}.bg-dark-blue-100{background-color:#32659d !important}.color-teal{color:#00c3ca !important}.bg-teal{background-color:#00c3ca !important}.color-red-100{color:#d23f00 !important}.bg-red-100{background-color:#d23f00 !important}.color-red-10{color:#fbece5 !important}.bg-red-10{background-color:#fbece5 !important}.color-green-100{color:#10a14a !important}.bg-green-100{background-color:#10a14a !important}.color-green-80{color:#12af51 !important}.bg-green-80{background-color:#12af51 !important}.color-green-10{color:#ebfaee !important}.bg-green-10{background-color:#ebfaee !important}.color-primary{color:#0166d6 !important}.bg-primary{background-color:#0166d6 !important}.color-primary-green{color:#12af51 !important}.bg-primary-green{background-color:#12af51 !important}.color-success{color:#67c23a !important}.bg-success{background-color:#67c23a !important}.color-warning{color:#e49700 !important}.bg-warning{background-color:#e49700 !important}.color-danger{color:#d23f00 !important}.bg-danger{background-color:#d23f00 !important}.color-info{color:#909399 !important}.bg-info{background-color:#909399 !important}.color-text-secondary{color:#81868d !important}.bg-text-secondary{background-color:#81868d !important}.color-text-custom-1-active{color:#333c48 !important}.bg-text-custom-1-active{background-color:#333c48 !important}.color-text-placeholder{color:#81868d !important}.bg-text-placeholder{background-color:#81868d !important}.color-text-primary{color:#303133 !important}.bg-text-primary{background-color:#303133 !important}.color-text-regular{color:#333c48 !important}.bg-text-regular{background-color:#333c48 !important}.color-text-custom-1-passive{color:#858a91 !important}.bg-text-custom-1-passive{background-color:#858a91 !important}.color-action-blue{color:#0166d6 !important}.bg-action-blue{background-color:#0166d6 !important}.white-bg{background-color:#fff}.no-bg{background-color:none}.blinker{position:relative;top:-1px;width:6px;height:6px;border-radius:8px;background-color:#2fa732;display:inline-block;vertical-align:middle;margin-right:5px;animation:blinker 1.5s cubic-bezier(0.5, 0, 1, 1) infinite alternate}.has-tooltip{cursor:pointer}.has-ellipsis{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.has-ellipsis::after{content:"";display:block}.user-activity-table__divider{width:16px;justify-content:space-evenly;color:#a7aeb8}.user-activity-table__data-item-container{flex-basis:75px;margin-right:14px}.user-activity-table-progress-bar-container{width:100%}.user-activity-table-progress-bar-container progress::-webkit-progress-value{background-color:#39c0c8}.session-overview-date-picker-container{margin-bottom:32px}.session-durations-date-picker-container{margin-bottom:32px}.session-frequency-date-picker-container{margin-bottom:32px}.cly-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-top:1px solid #eef2f5;box-shadow:0px 2px 0px #eaecef;padding:24px 24px 0px 24px}.cly-events-breakdown-horizontal-tile__titleoverview{color:#333c48;font-size:14px;font-weight:400;line-height:20px;font-family:Inter}.cly-events-breakdown-horizontal-tile:nth-of-type(3n) .cly-events-breakdown-horizontal-tile__wrapper{border-right:0}.cly-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 24px 0px}.cly-events-breakdown-horizontal-tile__item-title{padding:12px 0px 8px 0px}.cly-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px;font-family:Inter;color:#333c48;letter-spacing:.003em}.cly-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:400;line-height:20px;font-family:Inter;color:#333c48}.cly-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-vue-events-overview-top-events{padding-left:24px;padding-bottom:16.5px}.cly-vue-events-overview-top-events--tooltip{margin-left:5.5px}.cly-vue-events-overview-top-events__description{font-weight:500;line-height:14px}.cly-vue-events-overview-top-events__trend{padding-right:3px}.cly-vue-events-overview-monitor-events__charts .cly-vue-chart__echart{padding:0px}.cly-vue-events-overview-monitor-events__empty{min-height:100px}.cly-vue-events-overview-monitor-events__empty__block{margin:32px auto 32px auto;max-width:586px}.cly-vue-events-overview-monitor-events__empty--image{width:242px;height:242px;background-image:url("../images/dashboard/events-overview-noevents.svg")}.cly-vue-events-overview-monitor-events--text{font-weight:500;font-size:12px;color:#a7aeb8;letter-spacing:.5px;font-family:Inter;line-height:14.52px}.cly-vue-events-overview-monitor-events .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.cly-vue-events-overview-monitor-events--grey{color:#a7aeb8}.cly-vue-events-overview-monitor-events__heading{padding:8px 0px 16px 0px}.cly-vue-events-overview-monitor-events__configure--position{float:right;margin-left:auto}.cly-events-overview-drawer__subheading{font-size:16px;line-height:24px;font-weight:500;font-family:Inter;color:#333c48}.cly-events-overview-drawer--dragicon{margin-right:18px}.cly-events-overview-drawer__event-records{border-radius:6px;width:100%;padding:14px 16px;background-color:#f8fafd}.cly-events-overview-drawer__basis{flex-basis:0}.cly-events-overview-drawer__dropdown{min-width:230px;width:100%}.cly-events-overview-drawer__close-icon{line-height:1;font-size:24px}.cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-bottom:1px solid #ececec;padding:24px 24px 0 24px}.cly-monitor-events-breakdown-horizontal-tile__title{font-size:12px;font-weight:400;line-height:20px;padding-bottom:8px}.cly-monitor-events-breakdown-horizontal-tile__titleoverview{font-size:12px;font-weight:400;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__eventproperty{font-size:12px;font-weight:400;line-height:20px;color:#81868d}.cly-monitor-events-breakdown-horizontal-tile:nth-of-type(2n) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:none}.cly-monitor-events-breakdown-horizontal-tile:nth-child(1) .cly-monitor-events-breakdown-horizontal-tile__wrapper,.cly-monitor-events-breakdown-horizontal-tile:nth-child(2) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-top:1px solid #ececec}.cly-monitor-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-monitor-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 16px 0px}.cly-monitor-events-breakdown-horizontal-tile__item-title{padding-top:4px}.cly-monitor-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px}.cly-monitor-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-monitor-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:300;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-monitor-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-monitor-events-breakdown-horizontal-tile__overview-name{z-index:1}.cly-monitor-events-breakdown-horizontal-tile__width-50{width:50%}.cly-vue-events-all__alerts a{text-decoration:underline}.cly-vue-events-all{font-size:24px;line-height:32px;font-weight:500;padding-top:6px;letter-spacing:.003em;font-family:Inter;color:#333c48}.cly-vue-events-all__subheading{font-size:14px;line-height:20px;color:#333c48}.cly-vue-events-all--padding{padding-top:32px}.cly-vue-events-all--margin{margin-right:32px}.cly-vue-events-group{color:#fff;background-color:#a7aeb8;font-size:10px;line-height:10px;font-weight:500;letter-spacing:.0042em;vertical-align:middle;padding:3px 4px;border-radius:4px}.cly-vue-events-all-placeholder-text{color:#81868d;font-size:12px;line-height:14.52px;font-weight:500;letter-spacing:.005em;white-space:nowrap}.cly-vue-events-all-date-picker{margin-right:26px}.cly-vue-events-all-tooltip{margin-left:10px}.cly-vue-overview-events-header{padding-right:9.5px;letter-spacing:.003em}.cly-vue-events-header{padding:8px 24px 24px 24px;letter-spacing:.003em;font-family:Inter;line-height:32px;border-bottom:1px solid #ececec;background-color:#fff}.cly-vue-events-header__subheading--widget{padding-right:5.33px;color:#81868d}.cly-vue-events-header__subheading--text{font-family:Inter;line-height:20px;font-size:14px;color:#81868d}.cly-vue-events-header--tooltip{padding-left:9.5px}.cly-vue-events-overview-subheadings{padding-right:9.5px;letter-spacing:.003em;font-family:Inter}.cly-vue-events-overview-subheadings--tooltip{padding-top:3px}.cly-vue-events-overview-subheadings--font{font-family:Inter}.cly-vue-listbox.is-expandable{z-index:2001}.cly-vue-events-omitted-segments__item{color:#81868d;font-size:14px;font-weight:500;line-height:16px;padding:8px;margin:8px}.cly-vue-events-omitted-segments__title{color:#a7aeb8;font-size:13px;font-weight:500;letter-spacing:.5px;text-transform:uppercase;line-height:16px;padding:8px;margin:8px}.technology-analytics-wrapper .allPlatformVersions{border-left:1px solid #ececec;height:264px;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions{height:264px;position:relative;border-left:1px solid #ececec;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions div{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48;position:absolute;top:50%;text-align:center;width:100%;margin-top:-10px}.technology-analytics-wrapper .version-graph-title{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.technology-analytics-wrapper .version-graph-title .divider{color:#a7aeb8}.technology-analytics-wrapper .version-graph-title div:first-child{text-align:left}.technology-analytics-wrapper .version-graph-title div:nth-child(2){text-align:right}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper .version-graph-title .bu-column{padding:0px}.technology-analytics-wrapper .cly-vue-metric-card__wrapper .bu-is-flex-direction-column{margin-right:-1.5rem}.technology-analytics-wrapper .selector_wrapper{position:relative;top:-5px;margin-left:8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .metricCardsWrapper{height:115px}.technology-analytics-wrapper .metricCardsWrapper .emptyCard{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .emptyCard div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .platformVersionsWrapper .emptyCard{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .platformVersionsWrapper{height:309px;padding-bottom:20px}.technology-analytics-wrapper .metricCardsWrapper .bu-columns{flex-wrap:nowrap}.technology-analytics-wrapper .metricCardsWrapper .__view{width:auto !important}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-cards{border-bottom:none}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-card{background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__items{height:115px}.technology-analytics-wrapper__versions{height:291px;padding-bottom:20px}.technology-analytics-wrapper__empty-card{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;top:50%;text-align:center;border-bottom:1px solid #ececec}.technology-analytics-wrapper__empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper__versions-empty-card{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-right:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__versions-empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .app-version-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-version-date-picker-container+.cly-vue-notification__alert-box{margin-top:-8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-carrier-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .devices-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper__metric-cards .bu-column:last-child{margin-right:unset !important}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart__echart{padding-right:0px}.technology-analytics-wrapper .technology-pie-graphs .bu-level .bu-level-right{padding-right:5px}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .cly-vue-chart-legend__secondary{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .bu-level .bu-level-right{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__rail-is-vertical{right:5px !important}.version-graph-block:last-child{margin-bottom:12px}.technology-dashboard-widget>.bu-column:nth-child(odd)>.cly-vue-section{padding-left:4px}.technology-dashboard-widget>.bu-column:nth-child(even)>.cly-vue-section{padding-right:12px}.routename-analytics-geo .geo-date-picker-container{margin-bottom:32px}.routename-analytics-geo .radio-column{width:256px}.leaflet-noclick-map .leaflet-interactive{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.leaflet-control-zoom{user-select:none;border-color:#dcdcdc !important}.leaflet-control-zoom a{color:#333c48;border-bottom-color:#dcdcdc}.geo-analytics-data .cly-vue-button{padding:6px 10px;border-radius:4px}.user-management-drawer-content__pp-options{height:fit-content;align-self:center;margin-left:15px;box-shadow:none}.user-management-drawer-content__pp-options .el-button{box-shadow:none;border:none}.user-management-drawer-content__user-pp{width:100px;height:100px;border-radius:50%}.user-management-drawer-content #user-drawer-dropzone{background-color:#f8fafd;border-radius:6px}.user-management-drawer-content__custom-options{box-shadow:none}.user-management-drawer-content__custom-options div button{box-shadow:none;padding:0px;background:none;border:none}.user-management-drawer-content__under-input-text{text-decoration:underline;cursor:pointer}.user-management-drawer-content__top-section{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__bottom-section{display:flex;margin-top:28px;flex-direction:column;justify-content:space-between}.user-management-drawer-content__input-wrapper{margin-top:10px}.user-management-drawer-content__label{display:flex;justify-content:space-between;flex-direction:column}.user-management-drawer-content__label--text-secondary{color:#81868d}.user-management-drawer-content__label-text{font-style:normal;font-weight:normal;font-size:13px;line-height:16px;color:#333c48}.user-management-drawer-content__help-text{font-family:Inter;font-style:normal;font-weight:normal;font-size:12px;line-height:16px;color:#81868d}.user-management-drawer-content__help-menu-icon{font-family:Inter;font-style:normal;font-weight:normal;font-size:16px;line-height:16px;color:#81868d}.user-management-drawer-content__light-button{background-color:#ddedff;color:#0166d6;font-weight:bold;padding:10px 20px;width:fit-content;margin-top:10px;font-size:13px;border-radius:5px}.user-management-drawer-content__profile-picture-area{margin-top:9px;margin-left:10px}.user-management-drawer-content__profile-picture-area__upload-section{border:1px dashed #81868d;padding:30px;border-radius:8px;display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content__profile-picture-area__upload-section__img-box{background-color:#e2e4e8;height:100px;width:100px;border-radius:50%}.user-management-drawer-content__profile-picture-area__upload-section__description-box{font-size:12px;text-align:center;width:80%}.user-management-drawer-content__profile-picture-area__upload-section__description-box--bold{font-weight:500;color:#0166d6}.user-management-drawer-content__profile-picture-area__upload-section__description-box--gray{color:gray}.user-management-drawer-content__drawer-sub-section{border-radius:6px;background-color:#f8fafd;margin-top:10px;margin-bottom:24px}.user-management-drawer-content__drawer-sub-title{display:flex;flex-direction:row;justify-content:space-between;padding:5px 0px;font-weight:500;font-size:16px}.user-management-drawer-content__permission-table-header{display:flex;justify-content:space-between;margin-top:10px;font-size:12px;border-bottom:1px solid #ebebeb;padding-bottom:10px}.user-management-drawer-content__feature-search{width:calc(40% - 15px);margin-left:10px}.user-management-drawer-content__feature-search .el-input__inner{background-color:#fff !important}.user-management-drawer-content__permission-type-cols{width:75%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-type{text-align:center;font-size:11px;width:25%;margin:auto}.user-management-drawer-content__permission-type .check-label{font-size:15px}.user-management-drawer-content__permission-type .check-text{margin-top:2px}.user-management-drawer-content__permission-type .el-checkbox__label{font-weight:medium !important}.user-management-drawer-content__permission-table-content{height:300px;overflow-y:scroll;padding:10px 0px}.user-management-drawer-content__permission-row{display:flex;flex-direction:row;height:30px;justify-content:center;align-items:center}.user-management-drawer-content__feature-name{width:calc(35% - 15px);text-align:left;padding-left:15px;display:flex;justify-content:flex-start;align-items:center;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.user-management-drawer-content__feature-permissions{width:65%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-box{text-align:center;width:35%}.user-management-drawer-content__section-title{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__section-header{font-family:Inter;font-style:normal;font-weight:500;font-size:12px;line-height:15px;letter-spacing:.5px;text-transform:uppercase;color:#333c48}.user-management-drawer-content__role-section .check-text{margin-top:4px !important}.user-management-drawer-content__role-section .el-checkbox__label{font-weight:normal !important}.user-management-drawer-content__app-selector{width:100%}.user-management-drawer-content__add-permission-set{background-color:#e1efff;border-radius:4px;cursor:pointer;padding:9.5px 12px;font-weight:500;font-size:13px;line-height:13px;color:#0166d6;width:fit-content}.user-management-drawer-content__group-selector{width:100%}.user-management-drawer-content .check-label{color:#0166d6 !important}.user-management-drawer-content .el-tag--info{background-color:#81868d;color:#fff}.user-management-drawer-content .el-icon-close{background-color:#fff !important}.user-management-drawer-content .el-icon-close:hover{color:#81868d !important}.user-management-drawer-content .dropzone-custom-content{display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image>div{height:100px;width:100px;border-radius:50%}.user-management-drawer-content .dz-image-preview{display:flex !important;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image-preview .dz-remove{font-size:12px;font-weight:bold}.user-management-drawer-content .dz-image-preview .dz-image{display:block !important}.manage-users-table{margin:0px}.manage-users-table__groups{display:inline-flex;color:#32659d}.manage-users-table__groups a:hover{color:#1a75da;text-decoration:underline}.manage-users-table__groups-label{margin:0px 2px}.user-management-filter-form .select-full-width{width:100%}.user-management-view .el-tabs--button>.el-tabs__header{padding:24px 24px 0px 24px}.user-management-view .manage-users-action-btn{background-color:#12af51}#main_home_view .el-loading-parent--relative{min-height:100px}#main_home_view .bu-level-left:first-child>h2{font-size:20px !important}#main_home_view .cly-back-link i{color:#333c48}#main_home_view .componentBlock>div{padding-top:16px;padding-bottom:20px}.app-management-view h2{letter-spacing:.3px}.app-management-view h3{letter-spacing:.3px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container{margin-top:12px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container .cly-vue-form-step__section{padding-left:24px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.app-management-view .cly-vue-section__content .el-collapse{border:none}.app-management-view .cly-vue-section__content .app-section{margin-left:12px;margin-right:4px}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section{margin-bottom:24px !important;margin-left:0 !important;margin-right:0 !important;color:#333c48;display:flex;justify-content:space-between}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section .cly-vue-form-field__inner .el-form-item .el-form-item__content{line-height:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p{font-size:14px;line-height:14px;margin:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p+p{font-size:12px;line-height:16px;font-weight:400;margin-top:4px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns{padding:0 !important;margin:0}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-4{width:50%;margin-right:48px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-8{width:37.33%}.app-management-view .account-settings-avatar-box{padding:24px;overflow:auto;flex:auto}.app-management-view .account-settings-avatar-box .el-upload{display:block}.app-management-view .feedback-settings__upload .el-upload{display:block}.app-management-view .feedback-settings__upload img{width:165px;height:50px;margin-left:24px;cursor:default}.app-management-view .feedback-settings__colorpicker .cly-vue-color-picker__picker{overflow:auto}.app-management-view .feedback-settings__button:active,.app-management-view .feedback-settings__button:focus,.app-management-view .feedback-settings__button:hover{background-color:unset !important;border-color:unset !important}.app-management-view .app-management-list{max-height:681px;max-width:223px}.app-management-view .app-management-list .cly-vue-listbox__item span{margin-left:8px;position:relative;top:-8px}.app-management-view .app-management-details .bu-columns{margin:0 !important;padding:0 !important;border-bottom:1px solid #ececec}.app-management-view .app-management-details .bu-columns:last-child{border-bottom:none;margin-bottom:-20px}.app-management-view .app-management-details .el-collapse-item__header.is-active{border-bottom:1px solid #ececec}.app-management-view .app-management-details .el-collapse-item__content{padding-bottom:0}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section{padding-left:48px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content{display:flex !important;justify-content:right !important;float:right;line-height:inherit}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content>div{max-width:232px}.app-management-view .app-management-details .el-collapse-item__arrow{color:#81868d}.app-management-view .app-management-details .el-collapse-item__header{color:#333c48;padding-left:24px !important;text-transform:uppercase}.app-management-view .app-management-details .el-collapse-item__wrap{overflow:unset}.app-management-view .box-card{background-color:#e6f0fb;border:1px solid #0166d6;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.app-management-view .box-card .el-card__body{padding:24px}.app-management-view .box-card .el-card__body p a{color:#0166d6}.app-management-view .box-card .el-card__body p:nth-of-type(1){line-height:24px;font-weight:500;font-size:16px}.app-management-view .box-card .el-card__body p{font-size:14px}.el-dropdown-menu__item--divided__fix-broken{border:none}.el-dropdown-menu__item--divided__fix-broken::before{height:0px}.add-border{margin:0 8px;padding:0;border-top:1px solid #ececec}.add-border>a{display:none}@media(max-width: 2133px){.app-section span div div:nth-last-child(1) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(1) .cly-vue-form-step__section .el-input{width:268%}}@media(max-width: 1280px){.app-section span div div:nth-last-child(2) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(2) .cly-vue-form-step__section .el-input{width:177%}}.report-manager-filter-form .select-full-width{width:100%}.token-manager-drawer__choice .el-radio.is-autosized{flex:1 1 0;min-width:0}.token-manager-drawer__choice .el-radio__label{white-space:normal}.token-manager-drawer__permission-header,.token-manager-drawer__permission-row{display:flex;flex-direction:row;align-items:center}.token-manager-drawer__permission-header{border-bottom:1px solid #ebebeb;padding-bottom:10px;margin-bottom:10px}.token-manager-drawer__permission-row{height:30px}.token-manager-drawer__feature-name{width:35%;display:flex;align-items:center;justify-content:flex-start}.token-manager-drawer__feature-permissions{width:65%;display:flex}.token-manager-drawer__permission-box{flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:center}.token-manager-drawer__permission-box .el-checkbox{margin-right:0}.token-manager-drawer__permission-header .token-manager-drawer__permission-box .el-checkbox{display:flex;flex-direction:column-reverse;align-items:center}.token-manager-drawer__permission-header .token-manager-drawer__permission-box .el-checkbox__label{font-size:11px;padding-left:0;margin-bottom:4px;line-height:1}.header{display:flex;flex-direction:column;gap:20px}.setup-logo{margin-top:38px;margin-left:72px;width:165px;height:50px;background-image:url("../images/pre-login/countly-logo-dark.svg");background-repeat:no-repeat;background-size:contain;position:fixed;left:0px;top:0px}.centered-content{min-height:100vh;display:flex;align-items:center;justify-content:center;margin-bottom:-35px}.setup-byline{color:#81868d;margin-top:12px;font-size:14px}.setup-form{width:520px}.setup-radio-grid{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:10px;row-gap:10px}.setup-radio .el-radio.is-checked{background-color:#e1efff}.setup-radio .el-radio{margin-left:0 !important}.setup-radio .is-autosized.is-bordered .el-radio__input{display:none !important}.setup-radio .el-radio__label{padding-left:0}.setup-radio-item{display:flex;align-items:center;font-size:24px}.setup-radio-icon-bg{width:40px;height:40px;display:flex;align-items:center;justify-content:center;background-color:#e1efff;border-radius:100%}.is-checked .setup-radio-icon-bg{background-color:#0166d6;color:#fff}.setup-radio-icon{background-image:url("../images/dashboard/onboarding/box.svg");background-position:center;background-repeat:no-repeat;width:100%;height:100%}.setup-radio-icon--app-type-mobile{background-image:url("../images/dashboard/onboarding/app-type-mobile.svg")}.setup-radio-icon--app-type-web{background-image:url("../images/dashboard/onboarding/app-type-web.svg")}.setup-radio-icon--app-type-desktop{background-image:url("../images/dashboard/onboarding/app-type-desktop.svg")}.is-checked .setup-radio-icon{filter:brightness(10)}.setup-video-container{max-width:800px}.consent-form{width:700px}.consent-blurb{color:#81868d;font-size:14px}.consent-question{font-size:14px}.initial-populator{width:800px}.quickstart-item{display:flex;align-items:flex-start}.quickstart-item-desc{color:#81868d;text-align:left;word-break:break-word}.quickstart-link,.quickstart-link:visited{color:#0166d6}.quickstart-link:hover{color:#333c48}.preset-list{display:inline-block;position:absolute;left:170px;border:1px solid #a7aeb8;border-radius:4px;background-color:#fff}.preset-list__header{z-index:1997;position:relative;padding:8px 16px}.preset-list__header::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12;top:100%}.preset-list__header .el-button--primary{border:unset;font-weight:500;box-shadow:none}.preset-list__header .el-button--primary:hover{background-color:#cce0f7;color:#0166d6}.preset-list__header .el-button--text{font-weight:500;font-size:14px}.preset-list__body{background-color:#f9f9f9;height:400px;border-radius:4px}.preset-list__body::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(0deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);opacity:.12;left:0;bottom:0}.preset-list__body .preset{display:flex;flex-direction:column;justify-content:center;width:300px;background-color:#fff;border:1px solid #ececec;border-radius:4px;padding:12px;margin-bottom:8px;cursor:pointer}.preset-list__body .preset:first-child{margin-top:16px}.preset-list__body .preset:last-child{margin-bottom:16px}.preset-list__body .preset:hover{border:1px solid #0166d6;background-color:#e1efff}.preset-list__body .preset--selected{border:1px solid #0166d6}.preset-list .sortable-chosen{background-color:#e1efff !important}#preset-drawer .el-radio__label{display:flex;align-items:center}#preset-drawer .el-radio__input{display:flex}#preset-drawer .el-checkbox{font-weight:400}#preset-drawer .el-checkbox__label{padding-left:8px;color:#333c48}#preset-drawer .el-checkbox:hover__label{color:#333c48}/*# sourceMappingURL=manifest.css.map */ From ce2fa9dbd8e2b4fe0680e4fd81e1547747ae522e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 20:29:26 +0300 Subject: [PATCH 4/9] test(core): cover token scoping on real data endpoints The existing cases cover the token manager itself - what a token may create, list, delete and sign in with. They say nothing about what a token can actually reach, which is the point of the model, so this adds the same checks against endpoints that go through the ordinary validators. A token is scoped along three axes, and each is now exercised on a real endpoint: - app: a token granted read on one app is refused on another app of the same owner - CRUD type: a read token is refused an update, and an update token is refused a delete - feature: a token granted core is refused an events endpoint, and vice versa with the granted combination allowed through in each case. Another app is refused by two independent layers, and both are covered. The token's app list is derived from its permission, so verify_token normally rejects the request before a member is loaded ("Token not valid"). Passing apps explicitly widens that list without widening the permission, which gets past the app check and leaves the permission intersection to refuse it ("User does not have right") - so the second layer is not merely shadowed by the first. Co-Authored-By: Claude Opus 4.8 --- test/2.api/16.token.manager.js | 192 +++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/test/2.api/16.token.manager.js b/test/2.api/16.token.manager.js index f5b2e6e6bcf..270029e0cdc 100644 --- a/test/2.api/16.token.manager.js +++ b/test/2.api/16.token.manager.js @@ -630,4 +630,196 @@ describe('Testing token manager', function() { }); }); }); + + // The checks above cover the token manager itself. These cover what the token can actually + // reach: the same validators every data endpoint in the product goes through. A token is + // scoped by app, by CRUD type and by feature, so each of those has to hold on a real + // endpoint, not just in the permission algebra. + describe('Scoped tokens are enforced on real data endpoints', function() { + var readCoreToken = ""; + var updateEventsToken = ""; + var OTHER_APP_ID = ""; + + //grant exactly one feature, for one app, under one CRUD type + var permissionFor = function(appId, type, feature) { + var permission = {_: {a: [], u: [[appId]]}, c: {}, r: {}, u: {}, d: {}}; + permission[type][appId] = {all: false, allowed: {}}; + permission[type][appId].allowed[feature] = true; + return encodeURIComponent(JSON.stringify(permission)); + }; + + var createToken = function(permission, cb) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&multi=true&ttl=3600&permission=' + permission) + .expect(200) + .end(function(err, res) { + if (err) { + return cb(err); + } + cb(null, JSON.parse(res.text).result); + }); + }; + + var removeToken = function(id, done) { + if (!id) { + return done(); + } + request + .get('/i/token/delete?api_key=' + API_KEY_ADMIN + '&tokenid=' + id) + .end(function() { + done(); + }); + }; + + it('setup: a second app the tokens are not scoped to', function(done) { + var params = {name: "Token scope other app"}; + request + .get('/i/apps/create?api_key=' + API_KEY_ADMIN + "&args=" + JSON.stringify(params)) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + OTHER_APP_ID = JSON.parse(res.text)._id; + (OTHER_APP_ID !== "").should.equal(true); + done(); + }); + }); + + it('setup: a token that may only read core on the first app', function(done) { + createToken(permissionFor(APP_ID, 'r', 'core'), function(err, token) { + if (err) { + return done(err); + } + readCoreToken = token; + done(); + }); + }); + + it('setup: a token that may only update events on the first app', function(done) { + createToken(permissionFor(APP_ID, 'u', 'events'), function(err, token) { + if (err) { + return done(err); + } + updateEventsToken = token; + done(); + }); + }); + + it('the read-core token reads core data on the app it was granted', function(done) { + request + .get('/o?app_id=' + APP_ID + '&method=get_events&auth_token=' + readCoreToken) + .expect(200) + .end(function(err) { + done(err); + }); + }); + + //Two layers refuse another app, and this one is caught by the first. The token's app list + //is derived from its permission, so verify_token rejects the token itself before a member + //is ever loaded - hence "Token not valid" rather than "User does not have right". + it('the read-core token cannot read that same data on another app of the same owner', function(done) { + request + .get('/o?app_id=' + OTHER_APP_ID + '&method=get_events&auth_token=' + readCoreToken) + .expect(400) + .end(function(err, res) { + if (err) { + return done(err); + } + JSON.parse(res.text).should.have.property('result', 'Token not valid'); + done(); + }); + }); + + //...and this one is caught by the second. Passing apps explicitly widens the token's app + //list to both apps without widening its permission, so the app check lets the request + //through and the permission intersection is what refuses it. Without that layer a token + //could reach any app its app list happens to name. + it('a token whose app list is wider than its permission is still refused by the permission', function(done) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&multi=true&ttl=3600&apps=' + APP_ID + ',' + OTHER_APP_ID + '&permission=' + permissionFor(APP_ID, 'r', 'core')) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + var widerToken = JSON.parse(res.text).result; + request + .get('/o?app_id=' + OTHER_APP_ID + '&method=get_events&auth_token=' + widerToken) + .expect(401) + .end(function(err2, res2) { + if (err2) { + return removeToken(widerToken, function() { + done(err2); + }); + } + JSON.parse(res2.text).should.have.property('result', 'User does not have right'); + //and the app it was actually granted still works + request + .get('/o?app_id=' + APP_ID + '&method=get_events&auth_token=' + widerToken) + .expect(200) + .end(function(err3) { + removeToken(widerToken, function() { + done(err3); + }); + }); + }); + }); + }); + + it('the read-core token cannot update, only read', function(done) { + request + .get('/i/events/edit_map?app_id=' + APP_ID + '&auth_token=' + readCoreToken + '&event_order=' + JSON.stringify([])) + .expect(401) + .end(function(err) { + done(err); + }); + }); + + it('the update-events token cannot read core data, only update events', function(done) { + request + .get('/o?app_id=' + APP_ID + '&method=get_events&auth_token=' + updateEventsToken) + .expect(401) + .end(function(err) { + done(err); + }); + }); + + it('the update-events token cannot delete events, only update them', function(done) { + request + .get('/i/events/delete_events?app_id=' + APP_ID + '&auth_token=' + updateEventsToken + '&events=' + JSON.stringify(["nonexistent"])) + .expect(401) + .end(function(err) { + done(err); + }); + }); + + //the granted combination has to get past authorization. Whether the handler then finds an + //events document for this app depends on fixtures, so what is asserted is that the + //permission gate let it through rather than a particular success body. + it('the update-events token passes authorization for the update it was granted', function(done) { + request + .get('/i/events/edit_map?app_id=' + APP_ID + '&auth_token=' + updateEventsToken + '&event_order=' + JSON.stringify([])) + .end(function(err, res) { + if (err) { + return done(err); + } + res.status.should.not.equal(401); + done(); + }); + }); + + it('cleanup: remove the tokens and the second app', function(done) { + removeToken(readCoreToken, function() { + removeToken(updateEventsToken, function() { + request + .get('/i/apps/delete?api_key=' + API_KEY_ADMIN + '&args=' + JSON.stringify({app_id: OTHER_APP_ID})) + .end(function() { + done(); + }); + }); + }); + }); + }); + }); \ No newline at end of file From 150563d36c80e62ee567494c584528164959642c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 20:53:58 +0300 Subject: [PATCH 5/9] test(core): cover every token shape, the login path and permissions changing under a token Three areas the earlier cases left open. Token shapes. A token is created in a number of shapes - one feature, several features, several apps, a whole CRUD type - and each is now minted and then exercised on a real endpoint of a real feature: alerts carries create, read and update, events carries update and delete, so every CRUD type is covered on a plugin and on core. Each token reaches the endpoint it was granted, is refused another access type of the same feature, and is refused another feature entirely. The "all" grant is checked to reach features that were never named, and a two-app token to reach both apps while still being held to its one feature. The login path. /login/token is the only way a token becomes a dashboard session and /session is what that session is then checked with, and neither is reached through the api_key. A token carrying login permission is redeemed and the session it opens is then confirmed live; a scoped token is refused at the same door. Permissions changing under a token. The intersection is recomputed per request rather than frozen at creation, so a member is created, mints a token with the permissions they hold, loses the app, and the token loses it with them without being touched. One note on the assertion used for the granted case. "Not 401" is too weak on its own: an endpoint whose plugin is not loaded answers 400 "Invalid path", which let an earlier draft of these tests pass without ever reaching a validator. The check now rejects that answer explicitly. Co-Authored-By: Claude Opus 4.8 --- test/2.api/16.token.manager.js | 350 +++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) diff --git a/test/2.api/16.token.manager.js b/test/2.api/16.token.manager.js index 270029e0cdc..b0a67d65b5e 100644 --- a/test/2.api/16.token.manager.js +++ b/test/2.api/16.token.manager.js @@ -822,4 +822,354 @@ describe('Testing token manager', function() { }); }); + + // A token is created in a number of shapes - one feature, several features, several apps, a + // whole CRUD type - and whatever shape it was created in has to be the shape it is enforced in, + // on the ordinary validators every plugin goes through. alerts is a plugin feature carrying + // create/read/update, and events is a core feature carrying update/delete, so between them each + // CRUD type is exercised on a real endpoint of a real feature. + describe('Every shape a token is created in is the shape it is enforced in', function() { + var endpoints = { + alerts: {c: '/i/alert/save', r: '/o/alert/list', u: '/i/alert/status'}, + events: {u: '/i/events/edit_map', d: '/i/events/delete_events'} + }; + var created = []; + + var grant = function(spec) { + var permission = {_: {a: [], u: [spec.apps]}, c: {}, r: {}, u: {}, d: {}}; + spec.apps.forEach(function(appId) { + spec.types.forEach(function(type) { + permission[type][appId] = {all: !!spec.all, allowed: {}}; + (spec.features || []).forEach(function(feature) { + permission[type][appId].allowed[feature] = true; + }); + }); + }); + return encodeURIComponent(JSON.stringify(permission)); + }; + + var mint = function(spec, cb) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&multi=true&ttl=3600&permission=' + grant(spec)) + .expect(200) + .end(function(err, res) { + if (err) { + return cb(err); + } + var token = JSON.parse(res.text).result; + created.push(token); + cb(null, token); + }); + }; + + // What is asserted is the authorization outcome, not the handler's own result: a granted + // call has to get past the permission gate, a refused one has to be stopped by it. "Not 401" + // alone is too weak - an endpoint whose plugin is not loaded answers 400 "Invalid path", + // which would let a test pass without ever reaching a validator. + var expectAllowed = function(path, appId, token, done, extraQuery) { + request + .get(path + '?app_id=' + appId + '&auth_token=' + token + (extraQuery || '')) + .end(function(err, res) { + if (err) { + return done(err); + } + var body = {}; + try { + body = JSON.parse(res.text); + } + catch (ignored) { + body = {}; + } + (body.result + "").should.not.equal('Invalid path'); + res.status.should.not.equal(401); + done(); + }); + }; + + var expectRefused = function(path, appId, token, done, extraQuery) { + request + .get(path + '?app_id=' + appId + '&auth_token=' + token + (extraQuery || '')) + .expect(401) + .end(function(err, res) { + if (err) { + return done(err); + } + JSON.parse(res.text).should.have.property('result', 'User does not have right'); + done(); + }); + }; + + //feature, the type it is granted, a type of the same feature it must not reach, and a + //different feature it must not reach at all + var cases = [ + {feature: 'alerts', type: 'c', deniedSame: endpoints.alerts.r, deniedOther: endpoints.events.u}, + {feature: 'alerts', type: 'r', deniedSame: endpoints.alerts.u, deniedOther: endpoints.events.u}, + {feature: 'alerts', type: 'u', deniedSame: endpoints.alerts.r, deniedOther: endpoints.events.d}, + {feature: 'events', type: 'u', deniedSame: endpoints.events.d, deniedOther: endpoints.alerts.r}, + {feature: 'events', type: 'd', deniedSame: endpoints.events.u, deniedOther: endpoints.alerts.r} + ]; + + cases.forEach(function(testCase) { + var token = ""; + var label = testCase.type + ' on ' + testCase.feature; + + it('a token granted only ' + label + ' is created', function(done) { + mint({apps: [APP_ID], types: [testCase.type], features: [testCase.feature]}, function(err, minted) { + token = minted; + done(err); + }); + }); + + it('...reaches the ' + label + ' endpoint', function(done) { + expectAllowed(endpoints[testCase.feature][testCase.type], APP_ID, token, done); + }); + + it('...but not another access type of ' + testCase.feature, function(done) { + expectRefused(testCase.deniedSame, APP_ID, token, done); + }); + + it('...and not another feature at all', function(done) { + expectRefused(testCase.deniedOther, APP_ID, token, done); + }); + }); + + it('a token granted two features reaches both of them', function(done) { + mint({apps: [APP_ID], types: ['r'], features: ['alerts', 'core']}, function(err, token) { + if (err) { + return done(err); + } + expectAllowed(endpoints.alerts.r, APP_ID, token, function(err2) { + if (err2) { + return done(err2); + } + expectAllowed('/o', APP_ID, token, done, '&method=get_events'); + }); + }); + }); + + it('a token granted a whole CRUD type reaches features that were never named', function(done) { + //all:true is the "everything of this type" grant, so it covers features not listed + mint({apps: [APP_ID], types: ['r'], all: true}, function(err, token) { + if (err) { + return done(err); + } + expectAllowed(endpoints.alerts.r, APP_ID, token, function(err2) { + if (err2) { + return done(err2); + } + expectAllowed('/o', APP_ID, token, done, '&method=get_events'); + }); + }); + }); + + it('a token granted two apps reaches both, and still only the feature it was given', function(done) { + var params = {name: "Token shapes second app"}; + request + .get('/i/apps/create?api_key=' + API_KEY_ADMIN + "&args=" + JSON.stringify(params)) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + var secondApp = JSON.parse(res.text)._id; + mint({apps: [APP_ID, secondApp], types: ['r'], features: ['alerts']}, function(err2, token) { + if (err2) { + return done(err2); + } + expectAllowed(endpoints.alerts.r, APP_ID, token, function(err3) { + if (err3) { + return done(err3); + } + expectAllowed(endpoints.alerts.r, secondApp, token, function(err4) { + if (err4) { + return done(err4); + } + expectRefused('/i/events/edit_map', secondApp, token, function(err5) { + request + .get('/i/apps/delete?api_key=' + API_KEY_ADMIN + '&args=' + JSON.stringify({app_id: secondApp})) + .end(function() { + done(err5); + }); + }); + }); + }); + }); + }); + }); + + it('cleanup: remove the tokens created here', function(done) { + testUtils.db.collection("auth_tokens").remove({_id: {$in: created}}, function() { + done(); + }); + }); + }); + + // /login/token is the only path that turns a token into a dashboard session, and /session is + // what that session is then checked with. Both are reached without the api_key, so both are + // covered here rather than left to the login-permission checks on the create side alone. + describe('Login permission decides what can open a session', function() { + var agent = require('supertest').agent(testUtils.url); + var loginToken = ""; + var scopedToken = ""; + + it('setup: api_key mints a token that carries login permission', function(done) { + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&multi=true&ttl=600&can_login=true') + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + loginToken = JSON.parse(res.text).result; + done(); + }); + }); + + it('setup: api_key mints a token scoped to one feature', function(done) { + var permission = {_: {a: [], u: [[APP_ID]]}, c: {}, r: {}, u: {}, d: {}}; + permission.r[APP_ID] = {all: false, allowed: {core: true}}; + request + .get('/i/token/create?api_key=' + API_KEY_ADMIN + '&multi=true&ttl=600&permission=' + encodeURIComponent(JSON.stringify(permission))) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + scopedToken = JSON.parse(res.text).result; + done(); + }); + }); + + it('a scoped token cannot be redeemed for a session', function(done) { + request + .get('/login/token/' + scopedToken) + .expect(302) + .end(function(err, res) { + if (err) { + return done(err); + } + res.headers.location.should.not.containEql('/dashboard'); + done(); + }); + }); + + it('a token with login permission opens a session', function(done) { + agent + .get('/login/token/' + loginToken) + .expect(302) + .end(function(err, res) { + if (err) { + return done(err); + } + res.headers.location.should.containEql('/dashboard'); + done(); + }); + }); + + it('and the session it opened is a live one', function(done) { + //the session, not the token, is what /session checks - it reads req.session.auth_token + agent + .get('/session?check_session=true') + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + res.text.should.equal('success'); + done(); + }); + }); + + it('cleanup: remove the tokens', function(done) { + testUtils.db.collection("auth_tokens").remove({_id: {$in: [loginToken, scopedToken]}}, function() { + done(); + }); + }); + }); + + // The intersection is recomputed on every request rather than frozen into the token, so a token + // cannot keep reaching what its owner has since lost. + describe('A token never outlives the permissions of its owner', function() { + var memberId = ""; + var memberKey = ""; + var memberToken = ""; + var username = "tokenowner" + Math.round(Math.random() * 100000); + + it('setup: a member who may read core on the app', function(done) { + var permission = {_: {a: [], u: [[APP_ID]]}, c: {}, r: {}, u: {}, d: {}}; + permission.r[APP_ID] = {all: false, allowed: {core: true}}; + var params = {full_name: "Token Owner", username: username, password: testUtils.password, email: username + "@domain.com", permission: permission}; + request + .get('/i/users/create?api_key=' + API_KEY_ADMIN + "&args=" + JSON.stringify(params)) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + var ob = JSON.parse(res.text); + ob.should.have.property('api_key'); + memberId = ob._id; + memberKey = ob.api_key; + done(); + }); + }); + + it('setup: that member mints a token with the permissions they hold', function(done) { + var permission = {_: {a: [], u: [[APP_ID]]}, c: {}, r: {}, u: {}, d: {}}; + permission.r[APP_ID] = {all: false, allowed: {core: true}}; + request + .get('/i/token/create?api_key=' + memberKey + '&multi=true&ttl=3600&permission=' + encodeURIComponent(JSON.stringify(permission))) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + memberToken = JSON.parse(res.text).result; + done(); + }); + }); + + it('the token reads what its owner may read', function(done) { + request + .get('/o?app_id=' + APP_ID + '&method=get_events&auth_token=' + memberToken) + .expect(200) + .end(function(err) { + done(err); + }); + }); + + it('the owner loses access to the app', function(done) { + var params = {user_id: memberId, permission: {_: {a: [], u: [[]]}, c: {}, r: {}, u: {}, d: {}}}; + request + .get('/i/users/update?api_key=' + API_KEY_ADMIN + "&args=" + JSON.stringify(params)) + .expect(200) + .end(function(err) { + done(err); + }); + }); + + it('and the token loses it with them, without being touched', function(done) { + request + .get('/o?app_id=' + APP_ID + '&method=get_events&auth_token=' + memberToken) + .expect(401) + .end(function(err, res) { + if (err) { + return done(err); + } + JSON.parse(res.text).should.have.property('result', 'User does not have right'); + done(); + }); + }); + + it('cleanup: remove the token and the member', function(done) { + testUtils.db.collection("auth_tokens").remove({_id: memberToken + ""}, function() { + request + .get('/i/users/delete?api_key=' + API_KEY_ADMIN + "&args=" + JSON.stringify({user_ids: [memberId]})) + .end(function() { + done(); + }); + }); + }); + }); + }); \ No newline at end of file From b467847d0452ced79a0cb95d58d02674a3247516 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 21:14:44 +0300 Subject: [PATCH 6/9] test(core): keep the token scope cases deterministic wherever they run Two things that made these cases depend on the environment rather than on the code. The plugin cases need that plugin installed. Where it is not, its endpoints answer 400 "Invalid path", so they are now skipped explicitly after a single probe rather than run against an endpoint that was never there. The core cases do not depend on any plugin and always run. The two core cases checked their "another feature" refusal against /o/app_users/download, which rejects the request on its own parameters before any validator sees it, so the refusal proved nothing. They now check it against a core read, which reaches the validator. Co-Authored-By: Claude Opus 4.8 --- test/2.api/16.token.manager.js | 48 +++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/test/2.api/16.token.manager.js b/test/2.api/16.token.manager.js index b0a67d65b5e..2f5800a85c5 100644 --- a/test/2.api/16.token.manager.js +++ b/test/2.api/16.token.manager.js @@ -899,14 +899,35 @@ describe('Testing token manager', function() { }); }; + // The alerts cases need that plugin installed. Where it is not, its endpoints answer + // "Invalid path" and those cases are skipped explicitly rather than passing against an + // endpoint that was never there. The core cases below do not depend on any plugin. + var alertsInstalled = false; + + before(function(done) { + request + .get(endpoints.alerts.r + '?app_id=' + APP_ID + '&api_key=' + API_KEY_ADMIN) + .end(function(err, res) { + var body = {}; + try { + body = JSON.parse(res.text); + } + catch (ignored) { + body = {}; + } + alertsInstalled = (body.result !== 'Invalid path'); + done(); + }); + }); + //feature, the type it is granted, a type of the same feature it must not reach, and a //different feature it must not reach at all var cases = [ {feature: 'alerts', type: 'c', deniedSame: endpoints.alerts.r, deniedOther: endpoints.events.u}, {feature: 'alerts', type: 'r', deniedSame: endpoints.alerts.u, deniedOther: endpoints.events.u}, {feature: 'alerts', type: 'u', deniedSame: endpoints.alerts.r, deniedOther: endpoints.events.d}, - {feature: 'events', type: 'u', deniedSame: endpoints.events.d, deniedOther: endpoints.alerts.r}, - {feature: 'events', type: 'd', deniedSame: endpoints.events.u, deniedOther: endpoints.alerts.r} + {feature: 'events', type: 'u', deniedSame: endpoints.events.d, deniedOther: '/o', deniedOtherQuery: '&method=get_events'}, + {feature: 'events', type: 'd', deniedSame: endpoints.events.u, deniedOther: '/o', deniedOtherQuery: '&method=get_events'} ]; cases.forEach(function(testCase) { @@ -914,6 +935,9 @@ describe('Testing token manager', function() { var label = testCase.type + ' on ' + testCase.feature; it('a token granted only ' + label + ' is created', function(done) { + if (testCase.feature === 'alerts' && !alertsInstalled) { + return this.skip(); + } mint({apps: [APP_ID], types: [testCase.type], features: [testCase.feature]}, function(err, minted) { token = minted; done(err); @@ -921,19 +945,31 @@ describe('Testing token manager', function() { }); it('...reaches the ' + label + ' endpoint', function(done) { + if (testCase.feature === 'alerts' && !alertsInstalled) { + return this.skip(); + } expectAllowed(endpoints[testCase.feature][testCase.type], APP_ID, token, done); }); it('...but not another access type of ' + testCase.feature, function(done) { + if (testCase.feature === 'alerts' && !alertsInstalled) { + return this.skip(); + } expectRefused(testCase.deniedSame, APP_ID, token, done); }); it('...and not another feature at all', function(done) { - expectRefused(testCase.deniedOther, APP_ID, token, done); + if (testCase.feature === 'alerts' && !alertsInstalled) { + return this.skip(); + } + expectRefused(testCase.deniedOther, APP_ID, token, done, testCase.deniedOtherQuery); }); }); it('a token granted two features reaches both of them', function(done) { + if (!alertsInstalled) { + return this.skip(); + } mint({apps: [APP_ID], types: ['r'], features: ['alerts', 'core']}, function(err, token) { if (err) { return done(err); @@ -948,6 +984,9 @@ describe('Testing token manager', function() { }); it('a token granted a whole CRUD type reaches features that were never named', function(done) { + if (!alertsInstalled) { + return this.skip(); + } //all:true is the "everything of this type" grant, so it covers features not listed mint({apps: [APP_ID], types: ['r'], all: true}, function(err, token) { if (err) { @@ -963,6 +1002,9 @@ describe('Testing token manager', function() { }); it('a token granted two apps reaches both, and still only the feature it was given', function(done) { + if (!alertsInstalled) { + return this.skip(); + } var params = {name: "Token shapes second app"}; request .get('/i/apps/create?api_key=' + API_KEY_ADMIN + "&args=" + JSON.stringify(params)) From 7543ce31d4d90e5fa52dad3c18564c01907955fd Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 21:38:00 +0300 Subject: [PATCH 7/9] fix(core): keep the checklistbox option label a single text node Adding the option-prefix slot wrapped the option label in two spans across several lines, so the rendered el-checkbox__label gained nested nodes and surrounding whitespace. Callers that assert on that label exactly stopped matching: the alerts UI test looks for /^8.0.9$/ inside el-checkbox__label and timed out. The slot is now emitted bare, with no wrapper and no v-if, immediately before the label expression. A slot nobody fills renders nothing at all - not even the placeholder a falsy v-if leaves behind - so for every existing checklistbox the label is byte-identical to before. The app icon supplied by cly-app-select brings its own spacing, so the stylesheet rule the wrapper needed is gone too. Caught by the dashboard UI tests in CI, which pass on the base branch and failed here. Co-Authored-By: Claude Opus 4.8 --- .../javascripts/countly/vue/components/input.js | 7 +------ .../public/stylesheets/styles/blocks/_select.scss | 15 +-------------- .../public/stylesheets/styles/manifest2.css | 2 +- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/frontend/express/public/javascripts/countly/vue/components/input.js b/frontend/express/public/javascripts/countly/vue/components/input.js index cf4fbbf013a..ac198bbb602 100755 --- a/frontend/express/public/javascripts/countly/vue/components/input.js +++ b/frontend/express/public/javascripts/countly/vue/components/input.js @@ -698,12 +698,7 @@ :key="option.value + \'-\' + index"\ v-for="(option, index) in searchedOptions">\
\ - \ - \ - \ - {{option.label}}\ - \ - \ + {{option.label}}\
\ \ \ diff --git a/frontend/express/public/stylesheets/styles/blocks/_select.scss b/frontend/express/public/stylesheets/styles/blocks/_select.scss index 6b98adc34c2..cc2e4954ce9 100644 --- a/frontend/express/public/stylesheets/styles/blocks/_select.scss +++ b/frontend/express/public/stylesheets/styles/blocks/_select.scss @@ -5,20 +5,7 @@ .cly-vue-select-x { &__pop { - // Optional prefix (an app icon, for example) in front of a multi-check option label. Rendered -// only when the caller passes an option-prefix slot, so existing checklistboxes are unchanged. -.cly-vue-checklistbox__item-content { - display: inline-flex; - align-items: center; -} - -.cly-vue-checklistbox__item-prefix { - display: inline-flex; - align-items: center; - margin-right: 6px; -} - -.cly-vue-listbox { + .cly-vue-listbox { background-color: transparent !important; } .el-tabs { diff --git a/frontend/express/public/stylesheets/styles/manifest2.css b/frontend/express/public/stylesheets/styles/manifest2.css index 314c2431d9d..48fcdf9025c 100644 --- a/frontend/express/public/stylesheets/styles/manifest2.css +++ b/frontend/express/public/stylesheets/styles/manifest2.css @@ -1 +1 @@ -.cly-icon-btn{height:12px;width:12px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-prefix-icon{height:14px;width:12px;margin-left:7px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-input{height:20px;width:20px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-zoom{background-image:url("../images/icons/zoom-icon.svg")}.cly-icon-arrow-down{background-image:url("../images/icons/arrow_drop_down.svg")}.cly-icon-arrow-up{background-image:url("../images/icons/arrow_drop_up.svg")}.cly-icon-menu{background-image:url("../images/icons/menu.svg")}.cly-icon-date{background-image:url("../images/icons/date.svg")}.cly-icon-download{background-image:url("../images/icons/download-icon.svg")}.cly-icon-save{background-image:url("../images/icons/save.svg")}.cly-icon-load{background-image:url("../images/icons/load.svg")}.cly-icon-upload{background-image:url("../images/icons/upload.svg")}.cly-icon-arrow_forward-circled{background-image:url("../images/icons/arrow_forward-circled.svg")}.cly-icon-copy{background-image:url("../images/icons/copy.svg")}.cly-icon-copy_interactive{background-image:url("../images/icons/copy_inactive.svg")}.cly-icon-copy_interactive:hover{background-image:url("../images/icons/copy.svg")}.el-button [class*=ion-]+span,[class*=cly-icon-]+span{margin-left:6px}.el-button-group>.el-button{display:flex;align-items:center}.el-button-group>.el-select:first-child .el-button{display:flex;align-items:center}.cly-countly-icon-solid{width:20px;height:20px;background-image:url("../images/icons/countly-icon-solid.svg")}.cly-countly-icon-outline{width:20px;height:20px;background-image:url("../images/icons/countly-icon-outline.svg")}.cly-countly-icon-outline-trash-16px{background-position:99px 962px}.cly-countly-icon-outline-code-16px{background-position:99px 674px}.cly-countly-icon-outline-external-link-16px{background-position:419px 674px}.cly-countly-icon-outline-download-16px{background-position:299px 819px}.cly-countly-icon-outline-x-16px{background-position:139px 1107px}.cly-countly-icon-outline-document-download-16px{background-position:179px 1058px}.cly-countly-icon-outline-exclamation-circle-16px{background-position:339px 868px}.cly-countly-icon-outline-plus-circle-16px{background-position:299px 867px}.cly-countly-icon-outline-globe-16px{background-position:219px 1010px}.cly-countly-icon-outline-user-group-16px{background-position:300px 1202px}*{outline:none}html{height:100%;width:100%}body{height:100%;width:100%;margin:0;padding:0;overflow:auto;background-color:#f9f9f9;user-select:text;font-family:Inter,Ubuntu,Helvetica,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1{font-size:32px;line-height:48px;font-weight:500;margin:0;padding:10;color:#333c48}h2{font-size:24px;line-height:32px;font-weight:500;margin:0;padding:0;color:#333c48}h3{font-size:20px;line-height:30px;font-weight:500;margin:0;padding:0;color:#333c48}h4{font-size:16px;line-height:24px;font-weight:500;margin:0;padding:0;color:#333c48}h5{font-size:14px;line-height:20px;font-weight:500;margin:0;padding:0;color:#333c48}h6{font-size:14px;line-height:18px;font-weight:500;margin:0;padding:0;color:#333c48}textarea,input,p,h1,h2,h3,h4,h5,h6,button{font-family:Inter !important}.el-table th{padding:9px 0px;box-sizing:border-box;text-transform:uppercase;font-size:12px;font-style:normal;font-weight:500;border-bottom-width:2px}.el-table th .cell{line-height:16px;letter-spacing:.5px}.el-table th:hover .sort-caret.ascending{border-bottom-color:#005def}.el-table th:hover .sort-caret.descending{border-top-color:#005def}.el-table th.is-leaf{border-bottom-width:2px;border-top:1px solid #eef2f5}.el-table td{padding:14px 0px;font-style:normal;font-weight:normal;font-size:14px;box-sizing:border-box}.el-table td .cell{line-height:20px}.el-table.el-table--has-options td .cell{line-height:23px}.el-table th:first-child .cell,.el-table td:first-child .cell{padding-left:16px}.el-table th:last-child .cell,.el-table td:last-child .cell{padding-right:16px}.el-table .caret-wrapper{height:15px}.el-table .sort-caret{border-width:4px}.el-table .sort-caret.ascending{top:-2px}.el-table .sort-caret.descending{bottom:-1px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#005def}.el-table .descending .sort-caret.descending{border-top-color:#005def}.el-table .cell{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.el-table .cell>.el-checkbox,.el-table .cell>.el-switch,.el-table .cell>.el-radio{overflow:unset}.el-table table{width:0px}.el-radio.is-autosized{padding:16px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized.is-bordered+.el-radio.is-autosized.is-bordered{margin-left:10px}.el-radio.is-autosized.is-bordered{border-color:#cfd6e4;display:flex;align-items:center}.el-radio.is-autosized.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized.is-bordered.is-checked{border-color:#0166d6}.el-radio.is-autosized-vstack{padding:12px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized-vstack .el-radio__label{justify-content:space-between;display:flex;width:100%;align-items:baseline}.el-radio.is-autosized-vstack.is-bordered{align-items:center}.el-radio.is-autosized-vstack.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized-vstack.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized-vstack.is-bordered.is-multiline .el-radio__label{padding-top:2px}.el-radio.is-autosized-vstack.is-bordered+.el-radio.is-autosized-vstack.is-bordered{margin-left:0;margin-top:7px}.el-radio.is-bordered{border:1px solid #cfd6e4}.el-radio:hover:not(.is-disabled) .el-radio__label{color:inherit}.el-radio.is-checked:not(.is-disabled):hover .el-radio__label{color:inherit}.el-radio__input.is-checked+.el-radio__label{color:inherit}.el-collapse.is-bordered-box{border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.el-collapse.is-bordered-box .el-collapse-item__header{border-radius:4px;padding:0rem 1.5rem 0rem 1.5rem}.el-collapse.is-bordered-box .el-collapse-item__header.is-active{border-bottom-color:#ececec}.el-collapse.is-bordered-box .el-collapse-item__wrap{background-color:rgba(0,0,0,0)}.el-collapse.is-bordered-box .el-collapse-item__content{margin:0rem 1.5rem 0rem 1.5rem}.el-switch__label *{font-weight:normal;color:#a7aeb8;font-size:12px}.el-input.is-adaptive .el-input__inner{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:10px;vertical-align:middle}.el-select .el-input.is-arrow .el-input__inner{padding-right:30px}.el-button.is-wireframe{background:rgba(0,0,0,0);border:1px dotted #0166d6;box-sizing:border-box;box-shadow:0px 2px 4px rgba(1,122,255,.07)}.el-button.el-button--text.is-danger{color:#d23f00}.el-button.el-button--text.is-danger:hover{background-color:#f6f6f6}.el-button.is-light-blue{box-shadow:none;-webkit-box-shadow:none;border:none;font-weight:500;height:32px}.el-button.is-light-blue:not(.is-disabled){color:#0166d6;background-color:#e1efff}.el-button.is-light-blue:not(.is-disabled):hover{background-color:#cce0f7}.el-button-group>.el-select{float:left}.el-button-group>.el-select:first-child .el-button{border-top-right-radius:0;border-bottom-right-radius:0;-webkit-box-shadow:none;box-shadow:none}.el-button-group>.el-select:not(:last-child){margin-right:-1px}.el-button-group>.el-select:active,.el-button-group>.el-select:focus,.el-button-group>.el-select:hover{z-index:1}.el-button-group>.el-select:active .el-button,.el-button-group>.el-select:focus .el-button,.el-button-group>.el-select:hover .el-button{z-index:1}.el-input-number.is-slim .el-input__inner{padding-left:5px;padding-right:26px}.el-input-number.is-slim.el-input-number--small .el-input-number__decrease,.el-input-number.is-slim.el-input-number--small .el-input-number__increase{width:22px;font-size:14px}.el-tabs--card>.el-tabs__header{margin:0}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap{margin-bottom:-2px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap.is-scrollable{border-bottom:none;border-top-right-radius:4px;border-top-left-radius:4px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next{background:linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{background:linear-gradient(270deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{opacity:.85}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next:hover,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev:hover{opacity:1}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-top-left-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{border-top-right-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item{background-color:#fcfcfc;padding:0;height:auto;text-align:left;line-height:32px;border-bottom:2px solid #ececec}.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#0166d6;background-color:#fff}.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0px}.el-radio-group.is-full{display:flex}.el-radio-group.is-full .el-radio-button{flex-grow:1}.el-radio-group.is-full .el-radio-button__inner{width:100%}.el-dropdown-menu__item{padding:7px 6px}.el-dropdown-menu__item>i.cly-icon-outline{padding:2px 7px}.el-select-dropdown .el-scrollbar__bar{opacity:1 !important;right:0}.el-select-dropdown__item{padding:7px 6px}.el-tiptap-editor{border-radius:4px}.el-tiptap-editor .el-tiptap-editor__menu-bar{border-color:#cfd6e4}.el-tiptap-editor .el-tiptap-editor__menu-bar::before{background-color:#cfd6e4}.el-tiptap-editor>.el-tiptap-editor__content{border:1px solid #cfd6e4 !important;border-top:0 !important;border-bottom:0 !important}.el-tiptap-editor>.el-tiptap-editor__content pre code{font-family:"Courier New"}.el-tiptap-editor .el-tiptap-editor__footer{border-color:#cfd6e4}.el-tiptap-editor .border-top-radius{border-top-left-radius:4px !important;border-top-right-radius:4px !important}.el-tiptap-editor .border-bottom-radius{border-bottom-left-radius:4px !important;border-bottom-right-radius:4px !important}.el-tiptap-editor .fa-icon{fill:#333c48}.el-tiptap-editor__content{overflow-x:unset !important}.el-tiptap-editor__content>pre>code{font-family:"Courier New" !important}.el-tiptap-editor__content span>span{background-color:inherit}.el-tiptap-editor__content hr{width:100%}.el-dialog.el-tiptap-edit-link-dialog .el-button.is-round{border-radius:4px}.el-dialog.el-tiptap-edit-link-dialog .el-button.el-button--primary{border-color:#12af51;background-color:#12af51}.el-checkbox__input .el-checkbox__inner{color:#fff;text-align:center}.el-checkbox__input.is-checked .el-checkbox__inner::before{content:"" !important;font-family:"countly-icons-outline" !important;border:none !important;position:absolute;top:0px;width:15px;left:0px}.el-checkbox__input.is-checked .el-checkbox__inner::after{border:none !important}.el-checkbox__input.is-checked.is-disabled .el-checkbox__inner{color:#d0d0d0}.el-checkbox__inner::after{display:none}.el-checkbox.is-checked .el-checkbox__inner::after{display:block}.el-upload__folder-preview-content{height:32px}.el-upload-dragger{background-color:#fcfcfc;display:flex;flex-direction:column;justify-content:center}.el-upload-dragger .fa-folder{line-height:0}.el-upload-list__item-name{background-color:#fff;width:100%;border:1px solid #ececec;border-radius:5px;height:68px;padding-left:unset;cursor:default !important}.el-upload-list__item-remove{margin-left:auto;margin-right:24px;cursor:pointer !important}.el-upload-list__item-preview .cly-io-document-text{font-size:20px;color:#000;margin-right:4px}.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#000}.bu-level:not(:last-child){margin-bottom:0px}.bu-tag.is-slim{padding:0 .5em;height:1.5em}.bu-tag.is-legend{padding:0;height:.5em;width:1em;border-radius:3px}.bu-tag.is-curved{border-radius:67px;height:16px;padding-left:4px;padding-right:4px;min-width:12px}.vjs-tree{padding:10px}.vjs-value-boolean,.vjs-value-number{color:#31acb4}.vjs-value-string{color:#6c47ff}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f0fb}.cly-vue-theme-clydef{background-color:#f8f9fa}#main-views-container{height:100%;width:100%;overflow:auto}#main-views-container .main-view{min-width:768px;min-height:400px;width:100%;padding:0px 0 35px 0 !important;transition:width .55s;will-change:width;overflow:auto}.cly-vue-main{padding:0px 24px;margin:0}.cly-vue-section--has-configurator-skin .cly-vue-section__content{background:#fff;border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.cly-vue-section--has-configurator-skin .cly-vue-section__content .cly-vue-section__sub{border-top:none !important;border-bottom:1px solid #ececec;align-items:center;display:flex}.cly-vue-section--has-default-skin .cly-vue-section__content{border-top:1px solid #ececec;border-bottom:1px solid #ececec}.cly-vue-section .cly-vue-section__content-config{border-bottom:1px solid #ececec}.cly-vue-section:not(:last-child){margin-bottom:32px}.cly-vue-header{padding:24px 24px;margin-bottom:32px;border-bottom:1px solid #ececec;position:relative}.cly-vue-header__level{padding-top:8px;padding-bottom:12px}.cly-vue-header__level--no-pt{padding-top:0px}.cly-vue-header__level--no-pb{padding-bottom:0px}.cly-vue-header--no-mb{margin-bottom:0px}.cly-vue-header--no-bb{border-bottom:none}.cly-vue-header+div>.cly-vue-tabs{background-color:#fff;border-bottom:1px solid #ececec;margin-bottom:32px;padding:0px 24px}.cly-vue-select-x__pop .cly-vue-checklistbox__item-content{display:inline-flex;align-items:center}.cly-vue-select-x__pop .cly-vue-checklistbox__item-prefix{display:inline-flex;align-items:center;margin-right:6px}.cly-vue-select-x__pop .cly-vue-listbox{background-color:rgba(0,0,0,0) !important}.cly-vue-select-x__pop .el-tabs__active-bar{background-color:#0166d6}.cly-vue-select-x__pop .el-tabs__nav-wrap::after{background-color:rgba(0,0,0,0)}.cly-vue-select-x__pop .el-tabs__nav-scroll{margin:0 14px}.cly-vue-select-x__pop .el-tabs__header{margin:0 0 1px 0;z-index:2000}.cly-vue-select-x__pop .el-tabs__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:40px;opacity:.12}.cly-vue-select-x__pop--hidden-tabs .el-tabs__header::after{top:0px}.cly-vue-select-x__pop--hidden-tabs .el-tabs__nav-scroll{display:none}.cly-vue-select-x__pop--hidden-header .cly-vue-select-x__header{padding:0}.cly-vue-select-x__pop--hidden-tabs.cly-vue-select-x__pop--hidden-header .el-tabs__header::after{background:none;height:0;width:0}.cly-vue-select-x__title{font-weight:500;font-size:16px;line-height:24px;color:#333c48;padding-bottom:16px}.cly-vue-select-x__header-slot{padding-bottom:16px}.cly-vue-select-x__header{padding:16px}.cly-vue-select-x__header input[type=text]{background-color:#f6f6f6}.cly-vue-select-x__footer{border-top:1px solid #ececec}.cly-vue-select-x__commit-section{float:right;margin:16px}.cly-vue-select-x__pop--has-single-option .cly-vue-select-x__header-slot,.cly-vue-select-x__pop--has-slim-header .cly-vue-select-x__header-slot{padding:0}.cly-vue-select-x__pop--has-single-option .el-tabs__header::after{content:none}.cly-vue-select-x .el-select-head{width:100%}.cly-vue-listbox{background-color:#fff}.cly-vue-listbox label.el-checkbox{width:100%;margin-left:8px}.cly-vue-listbox.is-expandable{transition:width 200ms;width:100%;z-index:100}.cly-vue-listbox.is-expanded{width:130%;position:relative;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.08);box-shadow:0 1px 4px rgba(0,0,0,.08)}.cly-vue-listbox.cly-vue-listbox--bordered{border-radius:4px;border:1px solid #ececec}.cly-vue-listbox .cly-vue-listbox__no-data{padding:8px;line-height:20px;font-weight:500;color:#333c48;font-size:14px}.cly-vue-listbox .el-checkbox-group{overflow:hidden}.cly-vue-listbox .el-checkbox__label{line-height:20px;font-weight:400;color:#333c48;max-width:330px !important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom}.cly-vue-listbox .el-checkbox__input.is-checked+.el-checkbox__label{color:#333c48}.cly-vue-listbox .drag-handler{visibility:hidden;margin-right:8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cly-vue-listbox__header{margin:0 0 1px 0;z-index:1997;border-bottom:1px solid #ececec;position:relative}.cly-vue-listbox__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:57px;left:0;opacity:.12}.cly-vue-listbox .cly-vue-listbox__group{font-size:12px;line-height:14px;background-color:#f6f6f6;border-bottom:solid 1px #ececec;max-height:32px;display:flex;align-items:center;padding:8px}.cly-vue-listbox .cly-vue-listbox__item{display:flex;cursor:pointer;align-items:center;justify-content:space-between}.cly-vue-listbox .cly-vue-listbox__item.selected{background-color:#0166d6}.cly-vue-listbox .cly-vue-listbox__item.selected *{color:#fff}.cly-vue-listbox .cly-vue-listbox__item .cly-vue-listbox__remove-option{display:none}.cly-vue-listbox .cly-vue-listbox__item.hover .cly-vue-listbox__remove-option{display:block}.cly-vue-listbox .cly-vue-listbox__item-content{width:100%}.cly-vue-listbox__item-label{max-width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-listbox--disabled .cly-vue-listbox__item{background-color:#f6f6f6}.cly-vue-listbox--disabled .cly-vue-listbox__item *{color:#a7aeb8}.cly-vue-listbox--disabled .cly-vue-listbox__item.selected{opacity:.5}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover{background-color:#f6f6f6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .drag-handler{visibility:visible}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix *{color:#0166d6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item .cly-vue-listbox__remove-option:hover{color:#0166d6}.cly-vue-listbox--has-default-skin .cly-vue-listbox__item{padding:8px;border-radius:4px;line-height:16px}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item{padding:8px;height:55px;box-sizing:border-box;border-bottom:1px solid #ececec}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected{border-left:2px solid #0166d6;background-color:#f6f6f6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected *{color:#0166d6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item:last-child{border-bottom:none}.cly-vue-listbox--has-margin .cly-vue-listbox__item{margin:8px}.cly-fields-select.default-skin{display:inline-block}.cly-fields-select.default-skin .el-input__inner::placeholder{color:#000}.cly-fields-select.default-skin .fields-select-body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:0px;z-index:100;border:1px solid #d0d0d0;border-radius:2px;padding:16px;width:max-content}.cly-fields-select.default-skin .fields-select-body .controls{float:right;margin-top:10px}.cly-fields-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-fields-select__reset{float:right;font-size:12px;padding-bottom:26px;padding-top:0px;color:#d23f00;cursor:pointer;line-height:20px}.cly-fields-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-fields-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-fields-select__confirm{background-color:#12af51;color:#fff}.cly-fields-select__cancel{background:#f6f6f6}.cly-fields-select__dropdown .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin{display:inline-block}.cly-multi-select.default-skin .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin .cly-multi-select__body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:-2px;left:-2px;z-index:100;border:1px solid #d0d0d0;border-radius:4px;padding:16px;width:max-content}.cly-multi-select.default-skin .cly-multi-select__controls{float:right;margin-top:10px}.cly-multi-select__title-wrapper{margin-bottom:30px}.cly-multi-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-multi-select__reset{float:right;font-size:12px;padding:4px 8px;color:#d23f00;cursor:pointer;line-height:20px}.cly-multi-select__reset span{height:20px;line-height:20px}.cly-multi-select__reset:hover{background:#f6f6f6}.cly-multi-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-multi-select .cly-multi-select__confirm-button{margin-left:4px}.cly-multi-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-multi-select__dropdown .el-input__inner::placeholder{color:#000}.cly-vue-dropdown__pop{padding:0px;width:fit-content}.cly-vue-dropdown__pop-container{word-break:initial}.cly-vue-dropdown__dropdown-icon{width:16px;line-height:16px;height:16px;background-size:16px 16px;border-radius:4px;background-position:center;background-color:#017aff;display:inline-block}.cly-vue-more-options .el-button{border:1px solid #cfd6e4}.cly-vue-more-options .el-button .is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.cly-vue-eldatatable.silent-loading .el-loading-spinner{visibility:hidden}.cly-vue-eldatatable.silent-loading .el-loading-mask{display:none !important}.cly-vue-eldatatable.display-mode--list .el-table{background-color:unset}.cly-vue-eldatatable.display-mode--list .el-table__body{border-collapse:separate;border-spacing:0 8px}.cly-vue-eldatatable.display-mode--list .el-table__row{cursor:pointer}.cly-vue-eldatatable.display-mode--list .el-table__row td{cursor:pointer;height:56px;border-top:1px solid #ececec !important;border-bottom:2px solid #ececec !important;background-color:#fff !important;padding:18px 0px}.cly-vue-eldatatable.display-mode--list .el-table__row td:first-child{border-left:1px solid #ececec !important;border-radius:4px 0 0 4px !important}.cly-vue-eldatatable.display-mode--list .el-table__row td:last-child{border-right:1px solid #ececec !important;border-radius:0 4px 4px 0 !important}.cly-vue-eldatatable.display-mode--list .el-table__row td .cell{line-height:20px}.cly-vue-eldatatable.display-mode--list .el-table__row td.drag-icon .cell{text-overflow:unset !important}.cly-vue-eldatatable.display-mode--list .el-table thead tr{background-color:unset !important}.cly-vue-eldatatable.display-mode--list .el-table th{background-color:unset !important;border:none !important;padding:0 !important;color:#81868d !important}.cly-vue-eldatatable.display-mode--list .el-table__fixed-right::before{height:0 !important}.cly-vue-eldatatable__header{height:56px;border-left:none;border-right:none;box-sizing:border-box;padding:12px;border-top:1px solid #ececec}.cly-vue-eldatatable__header--white{background-color:#fff;color:#333c48;font-size:13px}.cly-vue-eldatatable__export--extended::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:185px;left:0;opacity:.12}.cly-vue-eldatatable__export--fileExport{border-top:1px solid #e2e4e8}.cly-vue-eldatatable__export--radio-button .el-radio-button{width:99px;display:inline-grid}.cly-vue-eldatatable__export--search input[type=text]{background-color:#f6f6f6}.cly-vue-eldatatable__search--grey input{background-color:#fbfdfe}.cly-vue-eldatatable__footer{height:40px;box-shadow:0px 2px 0px #eef2f5;border-left:none;border-right:none;box-sizing:border-box;padding:0px 12px}.cly-vue-eldatatable__footer--white{background-color:#fff;color:#808a9d;font-size:13px}.cly-vue-eldatatable .undo-row{position:absolute;left:0;padding:9px 0px;background-color:#ffd7d6;color:#2b2b2b;width:100%;height:100%;top:0;z-index:999;vertical-align:middle;display:flex;align-items:center;justify-content:center}.cly-vue-eldatatable .undo-row a{color:#017aff;cursor:pointer}.cly-vue-eldatatable .el-table-column--options .cly-vue-more-options{position:absolute;top:calc(50% - 16px);right:calc(50% - 20px)}.cly-vue-eldatatable div.cell{padding-left:16px;padding-right:8px}.cly-vue-eldatatable__empty-slot{height:200px}.cly-vue-table{width:100%}.cly-vue-table thead{background-color:#f6f6f6;border-top:1px solid #ececec;border-bottom:2px solid #ececec}.cly-vue-table thead th{color:#333c48;font-weight:500;font-size:12px;padding:9px;text-align:left}.cly-vue-table tbody td{padding:0px 9px}.cly-vue-chart{position:relative}.cly-vue-chart .bu-level{padding:0 20px 0 33px}.cly-progress-bar-container{width:100%}.cly-progress-bar-container.has-min-bradius .first-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:4px;border-top-left-radius:4px}.cly-progress-bar-container.has-min-bradius .last-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:4px;border-top-right-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__outer{border-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__inner{border-radius:4px}.cly-progress-bar-stack-container{float:left}.progress-bar-stack .el-progress-bar__inner{border-radius:0px}.first-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:0px;border-top-right-radius:0px}.middle-progress-bar-stack .el-progress-bar__outer{border-radius:0px}.last-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:0px;border-top-left-radius:0px}.cly-vue-tabs__primary-tab-list{padding:24px;box-sizing:border-box}.cly-vue-tabs__tab{height:34px;padding:10px 12px;display:inline-block;box-sizing:border-box}.cly-vue-tabs__tab--default{color:#81868d;line-height:14px;font-weight:500;font-size:14px;cursor:pointer}.cly-vue-tabs__tab--primary{border-radius:6px}.cly-vue-tabs__tab--primary:hover{color:#0166d6}.cly-vue-tabs__tab--secondary:hover{color:#333c48}.cly-vue-tabs__tab--primary-active{color:#0166d6;background-color:#e1efff}.cly-vue-tabs__tab--secondary-active{color:#333c48;border-bottom:2px solid #0166d6}.cly-vue-chart{width:100%;height:100%}.cly-vue-chart__echart{box-sizing:border-box;display:inline-block;width:100%}.cly-vue-chart--padded .cly-vue-chart__echart{padding-top:20px}.cly-vue-chart--full .cly-vue-chart__echart{padding:0}.cly-vue-chart-legend{display:inline-block;width:100%}.cly-vue-chart-legend__primary,.cly-vue-chart-legend__secondary{white-space:nowrap;overflow:auto;box-sizing:border-box;height:100%}.cly-vue-chart-legend__secondary--text-center{text-align:center}.cly-vue-chart-legend__p-series{display:inline-block;margin-left:64px;cursor:pointer}.cly-vue-chart-legend__p-series:first-child{margin-left:36px}.cly-vue-chart-legend__s-series{display:inline-block;margin-left:48px;cursor:pointer}.cly-vue-chart-legend__s-series:first-child{margin-left:0px}.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-rectangle,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-percentage{color:#a7aeb8}.cly-vue-chart-legend__second-row{margin-top:3px}.cly-vue-chart-legend__p-checkbox{height:16px;width:16px;border:1px solid #a7aeb8;display:inline-block;box-shadow:inset 0 0 0px 1.5px #fff;border-radius:4px;vertical-align:middle;box-sizing:border-box}.cly-vue-chart-legend__p-title{display:inline-block;vertical-align:middle;font-size:14px;color:#333c48}.cly-vue-chart-legend__p-tooltip{display:inline-block}.cly-vue-chart-legend__p-tooltip i{font-size:15px}.cly-vue-chart-legend__p-number{display:inline-block;font-size:24px;font-weight:500;color:#333c48}.cly-vue-chart-legend__p-trend{display:inline-block;font-size:14px;font-weight:500}.cly-vue-chart-legend__p-trend--trend-up{color:#12af51}.cly-vue-chart-legend__p-trend--trend-down{color:#d23f00}.cly-vue-chart-legend__s-rectangle{width:12px;height:6px;border-radius:3px;display:inline-block;vertical-align:middle;margin:0px 5px}.cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-percentage{display:inline-block;vertical-align:middle;margin-left:3px;font-size:12px;font-weight:400;color:#333c48}.cly-vue-chart-legend__bottom .cly-vue-chart-legend__primary,.cly-vue-chart-legend__bottom .cly-vue-chart-legend__secondary{padding:0px 24px 20px}.cly-vue-chart-legend__right{border-left:1px solid #ececec;width:265px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{margin-left:0px;padding:3px 7px;box-sizing:border-box;width:100%;display:block;border-bottom:1px solid #ececec}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{background-color:#f6f6f6;border-radius:0px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-percentage{font-weight:500}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{font-size:14px;line-height:30px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 30px);text-align:left}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{min-width:50px;text-align:right}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:10px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__view::before{content:"";position:absolute;width:100%;height:8px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie{border-left:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary{padding-top:30px;padding-bottom:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{border:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{border-radius:8px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 86px)}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:3px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view{display:flex;flex-direction:column;justify-content:center;padding-right:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view::before{background:none;height:0}.chart-type-toggle-wrapper__select{width:126px}.chart-type-toggle-wrapper__title{margin-top:16px;margin-left:16px;letter-spacing:.5px}.chart-type-toggle-wrapper__type{font-family:Inter;font-style:normal;font-weight:500;font-size:13px;line-height:13px}.chart-type-annotation-wrapper__icon{margin-top:1px}.chart-type-annotation-wrapper__img{margin-bottom:-2px}.chart-zoom-button{margin-right:12px}.cly-vue-zoom__external .chart-zoom-button{margin:0}.chart-download-button{width:42px;height:32px}.shadow-container{position:relative}.shadow-container:after{display:block;content:"";position:absolute;width:100%;margin:0 auto;height:70px;border:0;bottom:0;background:linear-gradient(180deg, rgba(255, 255, 255, 0.7) 0%, #FFFFFF 100%)}.chart-tooltip{max-height:360px;overflow:auto;margin-bottom:2px;max-width:300px;white-space:nowrap}.chart-tooltip__header{letter-spacing:.5px;text-transform:uppercase}.chart-tooltip__body{background-color:#fff;margin-bottom:16px;margin-top:16px}.chart-tooltip__body:last-child{margin-bottom:0 !important}.chart-tooltip__body.chart-tooltip__single-row{display:flex;margin-bottom:14px;margin-top:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__bar{margin-top:6px;float:none}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__series{display:flex;flex-direction:column;justify-content:space-between;width:calc(100% - 24px);margin-left:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__value{margin-top:-3px;margin-left:30px;display:flex;flex-direction:column;justify-content:space-between}.chart-tooltip__has-scroll .chart-tooltip__value{margin-right:10px}.chart-tooltip__bar{float:left;width:12px;min-width:12px;height:6px;border-radius:3px;margin-top:5px}.chart-tooltip__series{margin-left:24px;overflow:hidden}.chart-tooltip__series span{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.chart-tooltip__value{margin-top:2px;margin-left:24px}.graph-notes-tooltip{width:286px;max-height:118px;overflow:auto}.graph-notes-tooltip__header{width:100%}.graph-notes-tooltip__header .input-owner{font-weight:500}.graph-notes-tooltip__header .name-wrapper{margin-top:10px}.graph-notes-tooltip__header .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-notes-tooltip__header .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5;background-color:#f6f6f6}.graph-notes-tooltip__header .note-type{margin-top:12px}.graph-notes-tooltip__body{margin-top:12px}.graph-notes-tooltip__body .input-notes{word-break:break-word;display:inline-block;white-space:normal}.graph-notes-tooltip.minimize{width:180px}.graph-notes-tooltip.minimize .input-owner{font-size:12px}.graph-notes-tooltip.minimize__header{margin-top:0px}.graph-notes-tooltip.minimize .input-notes{font-size:12px}.graph-notes-tooltip.minimize .input-minimizer{margin-bottom:10px}.graph-notes-tooltip.minimize .graph-notes-tooltip__body{margin-top:5px}.graph-notes-tooltip.minimize .name-wrapper{margin-top:0px}.graph-notes-tooltip.minimize .note-date{font-size:11px}.graph-notes-tooltip.minimize .note-type{margin-top:2px;font-size:11px;margin-right:4px}.graph-tooltip-wrapper{margin-right:2px;margin-bottom:4px}.graph-tooltip-wrapper .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-tooltip-wrapper .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5}.graph-tooltip-wrapper__container{max-height:180px;overflow:hidden;overflow:auto}.cly-vue-tooltip-icon{font-size:17px;color:#a7aeb8;vertical-align:middle;width:18px;height:18px}.cly-in-page-notification{border-radius:4px;text-align:center;margin-bottom:32px}.cly-in-page-notification--light-informational{background-color:#e1efff;color:#333c48}.cly-in-page-notification--light-successful{background-color:#ebfaee;color:#333c48}.cly-in-page-notification--light-destructive{background-color:#fbece5;color:#333c48}.cly-in-page-notification--light-warning{background-color:#fcf5e5;color:#333c48}.cly-in-page-notification--dark-successful{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-informational{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-warning{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-destructive{background-color:#24292e;color:#fff}.cly-in-page-notification a:hover{text-decoration:underline;cursor:hand}.cly-vue-back-link{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase;margin-bottom:24px}.cly-vue-back-link:visited{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase}.cly-vue-back-link:hover span{text-decoration:underline}.cly-divider{width:100%;border-top:1px solid #ececec}.cly-divider.is-2{border-top-width:2px}.cly-divider.is-dashed{border-top-style:dashed}.cly-divider.is-dotted{border-top-style:dotted}.cly-event-select .el-radio-group{display:flex}.cly-event-select .el-radio-button{flex-grow:1}.cly-event-select .el-radio-button__inner{width:100%}.cly-vue-color-tag__color-tag-wrapper{width:20%}.cly-vue-color-tag__color-tag{width:92%;height:37px;margin-bottom:5px;border-radius:4px}.cly-vue-color-tag__color-tag__selected{border:2px solid #0166d6}.cly-vue-color-tag__checkmark{color:#fff}.cly-vue-empty-view-framed{border:1px solid #e2e4e8;background-color:#f8fafd;border-radius:8px;background-image:url("../images/icons/empty-background.svg");background-position:100% 100%;background-repeat:no-repeat}.cly-vue-json-editor .el-dialog__header{text-align:left;padding:8px 16px 0 !important;color:#fff}.cly-vue-json-editor .el-dialog__body{padding:0 !important}.cly-vue-json-editor__textarea{width:100%;box-sizing:border-box;outline:none;border:none;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fcfcfc}.cly-breadcrumbs a:hover{text-decoration:underline}.cly-is-fullwidth{width:100%}.is-estimate:hover{color:#0166d6;text-decoration:underline;text-decoration-style:dotted}#cly-vue-sidebar{left:0;height:100%;z-index:2000;user-select:none;color:#d6d6d6}.cly-vue-sidebar{height:100%}.cly-vue-sidebar .tooltip{display:block !important;z-index:10000}.cly-vue-sidebar .tooltip .tooltip-inner{background:#fff;color:#000}.cly-vue-sidebar .tooltip .tooltip-arrow{display:none}.cly-vue-sidebar .tooltip[x-placement^=right]{margin-left:0px}.cly-vue-sidebar .cly-vue-listbox__item-label{width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-sidebar__slide-transition-enter-active{transition:all .3s ease}.cly-vue-sidebar__slide-transition-leave-active{transition:all .8s cubic-bezier(1, 0.5, 0.8, 1)}.cly-vue-sidebar__slide-transition-enter,.cly-vue-sidebar__slide-transition-leave-to{transform:translateX(-224px)}.cly-vue-sidebar ul{list-style:none;padding:0;margin:0}.cly-vue-sidebar ul li{padding:0px}.cly-vue-sidebar__app-selector__dialog_box .el-dialog__body{padding:0px !important}.cly-vue-sidebar .el-collapse{border:none}.cly-vue-sidebar__app-name{font-size:14px}.cly-vue-sidebar__app-name-type{width:120px}.cly-vue-sidebar__app-selector{border:1px solid #424243;box-sizing:border-box;box-shadow:0px 11px 14px rgba(0,0,0,.371635);border-radius:4px;height:50px}.cly-vue-sidebar__app-type{opacity:.57}.cly-vue-sidebar__menu-options{width:48px;height:100%;overflow:auto;color:#a7aeb8;z-index:2005;background-color:#191c20}.cly-vue-sidebar__menu-options ul:first-child li:first-child{margin-top:28px}.cly-vue-sidebar__menu-option{width:48px;margin-top:24px;font-size:20px;cursor:pointer}.cly-vue-sidebar__menu-option .el-popover__reference:hover{color:#fff !important}.cly-vue-sidebar__menu-option-toggle{height:48px;background-color:#24292e;border-top-left-radius:50%;border-bottom-left-radius:50%}.cly-vue-sidebar__menu-option-toggle--no-bg{background-color:rgba(0,0,0,0)}.cly-vue-sidebar__menu-option-toggle--rotate-right{transform:rotate(180deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu-option-toggle--rotate-left{transform:rotate(0deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu{width:224px;background-color:#24292e;color:#d6d6d6;box-sizing:border-box;height:100%;overflow:hidden;z-index:2004;position:relative}.cly-vue-sidebar__menu--with-banner .__view{padding-bottom:200px}.cly-vue-sidebar__menu-items,.cly-vue-sidebar__submenu-items,.cly-vue-sidebar .el-collapse-item__header{line-height:20px;height:20px;background-color:#24292e;color:#d6d6d6;border:none;font-size:14px;padding:0;font-weight:400;font-family:Inter;padding:6px 12px}.cly-vue-sidebar__menu-items .el-collapse-item__arrow,.cly-vue-sidebar__submenu-items .el-collapse-item__arrow,.cly-vue-sidebar .el-collapse-item__header .el-collapse-item__arrow{margin-right:0px}.cly-vue-sidebar__menu-items:hover,.cly-vue-sidebar__submenu-items:hover,.cly-vue-sidebar .el-collapse-item__header:hover{background-color:#383a3f;color:#fff;border-radius:4px}.cly-vue-sidebar__menu-items--selected,.cly-vue-sidebar__submenu-items--selected,.cly-vue-sidebar .el-collapse-item__header--selected{background-color:#12af51;border-radius:4px;color:#fff}.cly-vue-sidebar__menu-items--selected:hover,.cly-vue-sidebar__submenu-items--selected:hover,.cly-vue-sidebar .el-collapse-item__header--selected:hover{background-color:#12af51;border-radius:4px}.cly-vue-sidebar .el-collapse-item__header.focusing:focus:not(:hover){color:#d6d6d6}.cly-vue-sidebar .el-collapse-item .cly-vue-sidebar__submenu-items{padding-left:32px}.cly-vue-sidebar__el-collapse--selected .el-collapse-item__header{border-radius:4px;background-color:#383a3f;color:#fff}.cly-vue-sidebar .el-collapse-item__content{margin:0;padding:0}.cly-vue-sidebar .el-collapse-item__wrap{border-bottom:1px solid #424243;background-color:#24292e;box-shadow:0px 1px 0px rgba(0,0,0,.4)}.cly-vue-sidebar__header{padding:16px 12px;position:relative}.cly-vue-sidebar__header-search input{background-color:#383a3f;border:none;color:#d6d6d6}.cly-vue-sidebar__header-search input:focus{outline:none;box-shadow:none}.cly-vue-sidebar__header-title{font-size:16px;line-height:24px;font-weight:500;display:inline-block;margin-top:12px}.cly-vue-sidebar__header-button{float:right;top:5px;position:relative}.cly-vue-sidebar__main-menu{overflow:auto;height:calc(100% - 130px)}.cly-vue-sidebar__app-image{width:26px;height:26px;background-size:26px 26px;border-radius:4px;background-position:center;display:inline-block}.cly-vue-sidebar__user-popper{box-sizing:border-box;font-family:Inter;padding:14px 0px;box-shadow:0px 2px 7px rgba(0,0,0,.18815);color:#333c48}.cly-vue-sidebar__language-popper{font-family:Inter;padding:0px;min-width:130px;box-shadow:0px 2px 7px rgba(0,0,0,.18815)}.cly-vue-sidebar__user-details .bu-level{padding:6px 12px}.cly-vue-sidebar__user-links .bu-level{padding:6px;margin:0px 6px}.cly-vue-sidebar__user-links .bu-level:hover{background-color:#f1f3f4;color:#0166d6;border-radius:4px}.cly-vue-sidebar__user-links .bu-level:hover .bu-level-item i{color:#333c48}.cly-vue-sidebar__user-links .bu-level .bu-level-item:first-child{width:15px}.cly-vue-sidebar__user-links .bu-level .bu-level-item i{color:#a7aeb8}.cly-vue-sidebar__user-info{width:140px}.cly-vue-sidebar__user-info p{padding:0;margin:0}.cly-vue-sidebar__user-info p:first-child{font-size:16px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-info p:last-child{margin-top:7px;line-height:17px;font-size:14px;font-weight:400}.cly-vue-sidebar__user-api{width:192px}.cly-vue-sidebar__user-api p{padding:0;margin:0}.cly-vue-sidebar__user-api p:first-child{font-size:12px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-api p:last-child{margin-top:7px;line-height:17px;font-size:12px;font-weight:400}.cly-vue-sidebar__user-image{height:50px;width:50px;border-radius:25px;text-align:center}.cly-vue-sidebar__user-initials{text-transform:uppercase;color:#fff;font-size:16px}.cly-vue-sidebar__user-divider{border:1px solid #ececec;margin-top:5px;position:relative}.cly-vue-sidebar__version{position:absolute;bottom:0;height:48px;display:flex;align-items:center;justify-content:center;width:224px;font-size:10px;background-color:#24292e}.cly-vue-sidebar__version__banner{position:absolute;bottom:12px;left:12px;right:12px;z-index:2001;cursor:default;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:#191c20;border-radius:4px;padding:16px}.cly-vue-sidebar__version__banner .button{width:100%;margin-top:12px}.cly-vue-sidebar__version__banner .text{font-size:14px;color:#fff}.cly-vue-sidebar .cly-icon-sidebar-app{background-image:url("../images/sidebar/default/app.svg");height:24px;width:24px}.cly-vue-sidebar .cly-icon-sidebar-analytics{background-image:url("../images/sidebar/default/analytics-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-analytics:hover{background-image:url("../images/sidebar/hover/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-analytics.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards{background-image:url("../images/sidebar/default/dashboards-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-dashboards:hover{background-image:url("../images/sidebar/hover/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-divider{background-image:url("../images/sidebar/default/divider.svg");width:32px;height:1px}.cly-vue-sidebar .cly-icon-sidebar-management{background-image:url("../images/sidebar/default/management.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-management:hover{background-image:url("../images/sidebar/hover/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-management.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager{background-image:url("../images/sidebar/default/report-manager.svg");height:18px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-report-manager:hover{background-image:url("../images/sidebar/hover/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center{background-image:url("../images/sidebar/default/help-center.svg");height:25px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-help-center:hover{background-image:url("../images/sidebar/hover/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications{background-image:url("../images/sidebar/default/notifications.svg");height:23px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-notifications:hover{background-image:url("../images/sidebar/hover/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-toggle-left{background-image:url("../images/sidebar/default/toggle-left.svg");height:15px;width:11px}.cly-vue-sidebar--floating{position:absolute;left:48px}.notification-toasts{position:absolute;right:24px;bottom:24px;z-index:600000}.notification-toasts__item{margin-top:12px;min-width:288px;max-width:288px}.notification-toasts__item--small{max-width:288px}.notification-toasts__item--large{max-width:611px}.font-weight-bold{font-weight:600 !important}.font-weight-normal{font-weight:400 !important}.font-italic{font-style:italic !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-big{color:#333c48;font-size:16px;font-weight:400;line-height:22px}.text-big.font-weight-bold{font-weight:500 !important}.text-medium{color:#333c48;font-size:14px;font-weight:400;line-height:20px}.text-medium.font-weight-bold{font-weight:500 !important}.text-smallish{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-smallish.font-weight-bold{font-weight:500 !important}.text-small{color:#333c48;font-size:12px;font-weight:400;line-height:18px}.text-small.font-weight-bold{font-weight:500 !important}.text-heading.text-big{line-height:24px;font-weight:500 !important;margin-bottom:16px}.text-heading.text-medium{line-height:20px;font-weight:500 !important;margin-bottom:8px}.text-heading.text-small{line-height:18px;font-weight:500 !important;margin-bottom:4px}.text-smaller{color:#333c48;font-size:10px;font-weight:400;line-height:12px}.text-smaller.font-weight-bold{font-weight:500 !important}.text-smallest{color:#333c48;font-size:10px;font-weight:700;line-height:12px}.text-smallest.font-weight-bold{font-weight:500 !important}.text-button{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-button.font-weight-bold{font-weight:500 !important}.cly-trend-up,.cly-trend-down,.cly-trend-neutral{font-size:14px;font-weight:500}.cly-trend-up,.cly-trend-down.negated{color:#12af51}.cly-trend-down,.cly-trend-up.negated{color:#d23f00}.cly-trend-neutral{color:#81868d}.cly-trend-up-icon,.cly-trend-down-icon,.cly-trend-neutral-icon{border-radius:50%;margin-right:4px;display:inline-block;width:17px;height:17px;text-align:center;line-height:17px}.cly-trend-up-icon{background-color:#ebfaee}.cly-trend-down-icon{background-color:#fbece5}.cly-trend-neutral-icon{background-color:#e2e4e8}.cly-trend-up.negated .cly-trend-up-icon{background-color:#fbece5}.cly-trend-down.negated .cly-trend-down-icon{background-color:#ebfaee}.cursor-pointer{cursor:pointer}.icon-size-1{font-size:6px}.icon-size-2{font-size:8px}.icon-size-3{font-size:10px}.icon-size-4{font-size:12px}.icon-size-5{font-size:14px}.icon-size-6{font-size:16px}.text-clickable{cursor:pointer}.color-white{color:#fff !important}.bg-white{background-color:#fff !important}.color-black{color:#000 !important}.bg-black{background-color:#000 !important}.color-warm-gray-100{color:#24292e !important}.bg-warm-gray-100{background-color:#24292e !important}.color-warm-gray-90{color:#24292e !important}.bg-warm-gray-90{background-color:#24292e !important}.color-warm-gray-80{color:#383a3f !important}.bg-warm-gray-80{background-color:#383a3f !important}.color-warm-gray-70{color:#424243 !important}.bg-warm-gray-70{background-color:#424243 !important}.color-warm-gray-60{color:#616165 !important}.bg-warm-gray-60{background-color:#616165 !important}.color-warm-gray-40{color:#d6d6d6 !important}.bg-warm-gray-40{background-color:#d6d6d6 !important}.color-warm-gray-30{color:#ececec !important}.bg-warm-gray-30{background-color:#ececec !important}.color-warm-gray-20{color:#f6f6f6 !important}.bg-warm-gray-20{background-color:#f6f6f6 !important}.color-warm-gray-10{color:#fcfcfc !important}.bg-warm-gray-10{background-color:#fcfcfc !important}.color-cool-gray-100{color:#333c48 !important}.bg-cool-gray-100{background-color:#333c48 !important}.color-cool-gray-50{color:#81868d !important}.bg-cool-gray-50{background-color:#81868d !important}.color-cool-gray-40{color:#a7aeb8 !important}.bg-cool-gray-40{background-color:#a7aeb8 !important}.color-cool-gray-30{color:#cfd6e4 !important}.bg-cool-gray-30{background-color:#cfd6e4 !important}.color-cool-gray-20{color:#e2e4e8 !important}.bg-cool-gray-20{background-color:#e2e4e8 !important}.color-cool-gray-10{color:#f8fafd !important}.bg-cool-gray-10{background-color:#f8fafd !important}.color-cool-gray-05{color:#fbfdfe !important}.bg-cool-gray-05{background-color:#fbfdfe !important}.color-charts-blue{color:#017aff !important}.bg-charts-blue{background-color:#017aff !important}.color-charts-turquoise{color:#39c0c8 !important}.bg-charts-turquoise{background-color:#39c0c8 !important}.color-charts-light-turquoise{color:#ebf9f9 !important}.bg-charts-light-turquoise{background-color:#ebf9f9 !important}.color-charts-amber{color:#f5c900 !important}.bg-charts-amber{background-color:#f5c900 !important}.color-charts-orange{color:#f96300 !important}.bg-charts-orange{background-color:#f96300 !important}.color-charts-light-orange{color:#feefe5 !important}.bg-charts-light-orange{background-color:#feefe5 !important}.color-charts-magenta{color:#f34971 !important}.bg-charts-magenta{background-color:#f34971 !important}.color-charts-light-magenta{color:#feedf1 !important}.bg-charts-light-magenta{background-color:#feedf1 !important}.color-charts-coral{color:#ff9382 !important}.bg-charts-coral{background-color:#ff9382 !important}.color-charts-violet{color:#da6efc !important}.bg-charts-violet{background-color:#da6efc !important}.color-charts-purple{color:#6c47ff !important}.bg-charts-purple{background-color:#6c47ff !important}.color-charts-light-purple{color:#f0edff !important}.bg-charts-light-purple{background-color:#f0edff !important}.color-charts-tan{color:#cdad7a !important}.bg-charts-tan{background-color:#cdad7a !important}.color-charts-olive{color:#aabb5d !important}.bg-charts-olive{background-color:#aabb5d !important}.color-charts-scarlet{color:#f62404 !important}.bg-charts-scarlet{background-color:#f62404 !important}.color-charts-pink{color:#ffb6f5 !important}.bg-charts-pink{background-color:#ffb6f5 !important}.color-yellow-100{color:#e49700 !important}.bg-yellow-100{background-color:#e49700 !important}.color-yellow-70{color:#ffc760 !important}.bg-yellow-70{background-color:#ffc760 !important}.color-yellow-20{color:#fff4ce !important}.bg-yellow-20{background-color:#fff4ce !important}.color-yellow-10{color:#fcf5e5 !important}.bg-yellow-10{background-color:#fcf5e5 !important}.color-blue-100{color:#0166d6 !important}.bg-blue-100{background-color:#0166d6 !important}.color-blue-90{color:#1a75da !important}.bg-blue-90{background-color:#1a75da !important}.color-blue-80{color:#3485de !important}.bg-blue-80{background-color:#3485de !important}.color-blue-70{color:#4d94e2 !important}.bg-blue-70{background-color:#4d94e2 !important}.color-blue-60{color:#67a3e6 !important}.bg-blue-60{background-color:#67a3e6 !important}.color-blue-50{color:#80b3eb !important}.bg-blue-50{background-color:#80b3eb !important}.color-blue-40{color:#99c2ef !important}.bg-blue-40{background-color:#99c2ef !important}.color-blue-30{color:#b3d1f3 !important}.bg-blue-30{background-color:#b3d1f3 !important}.color-blue-20{color:#cce0f7 !important}.bg-blue-20{background-color:#cce0f7 !important}.color-blue-10{color:#e6f0fb !important}.bg-blue-10{background-color:#e6f0fb !important}.color-sky-blue-100{color:#3f9aff !important}.bg-sky-blue-100{background-color:#3f9aff !important}.color-shadow-blue-100{color:#9cbce0 !important}.bg-shadow-blue-100{background-color:#9cbce0 !important}.color-light-blue-100{color:#e1efff !important}.bg-light-blue-100{background-color:#e1efff !important}.color-dark-blue-100{color:#32659d !important}.bg-dark-blue-100{background-color:#32659d !important}.color-teal{color:#00c3ca !important}.bg-teal{background-color:#00c3ca !important}.color-red-100{color:#d23f00 !important}.bg-red-100{background-color:#d23f00 !important}.color-red-10{color:#fbece5 !important}.bg-red-10{background-color:#fbece5 !important}.color-green-100{color:#10a14a !important}.bg-green-100{background-color:#10a14a !important}.color-green-80{color:#12af51 !important}.bg-green-80{background-color:#12af51 !important}.color-green-10{color:#ebfaee !important}.bg-green-10{background-color:#ebfaee !important}.color-primary{color:#0166d6 !important}.bg-primary{background-color:#0166d6 !important}.color-primary-green{color:#12af51 !important}.bg-primary-green{background-color:#12af51 !important}.color-success{color:#67c23a !important}.bg-success{background-color:#67c23a !important}.color-warning{color:#e49700 !important}.bg-warning{background-color:#e49700 !important}.color-danger{color:#d23f00 !important}.bg-danger{background-color:#d23f00 !important}.color-info{color:#909399 !important}.bg-info{background-color:#909399 !important}.color-text-secondary{color:#81868d !important}.bg-text-secondary{background-color:#81868d !important}.color-text-custom-1-active{color:#333c48 !important}.bg-text-custom-1-active{background-color:#333c48 !important}.color-text-placeholder{color:#81868d !important}.bg-text-placeholder{background-color:#81868d !important}.color-text-primary{color:#303133 !important}.bg-text-primary{background-color:#303133 !important}.color-text-regular{color:#333c48 !important}.bg-text-regular{background-color:#333c48 !important}.color-text-custom-1-passive{color:#858a91 !important}.bg-text-custom-1-passive{background-color:#858a91 !important}.color-action-blue{color:#0166d6 !important}.bg-action-blue{background-color:#0166d6 !important}.white-bg{background-color:#fff}.no-bg{background-color:none}.blinker{position:relative;top:-1px;width:6px;height:6px;border-radius:8px;background-color:#2fa732;display:inline-block;vertical-align:middle;margin-right:5px;animation:blinker 1.5s cubic-bezier(0.5, 0, 1, 1) infinite alternate}.has-tooltip{cursor:pointer}.has-ellipsis{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.has-ellipsis::after{content:"";display:block}.user-activity-table__divider{width:16px;justify-content:space-evenly;color:#a7aeb8}.user-activity-table__data-item-container{flex-basis:75px;margin-right:14px}.user-activity-table-progress-bar-container{width:100%}.user-activity-table-progress-bar-container progress::-webkit-progress-value{background-color:#39c0c8}.session-overview-date-picker-container{margin-bottom:32px}.session-durations-date-picker-container{margin-bottom:32px}.session-frequency-date-picker-container{margin-bottom:32px}.cly-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-top:1px solid #eef2f5;box-shadow:0px 2px 0px #eaecef;padding:24px 24px 0px 24px}.cly-events-breakdown-horizontal-tile__titleoverview{color:#333c48;font-size:14px;font-weight:400;line-height:20px;font-family:Inter}.cly-events-breakdown-horizontal-tile:nth-of-type(3n) .cly-events-breakdown-horizontal-tile__wrapper{border-right:0}.cly-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 24px 0px}.cly-events-breakdown-horizontal-tile__item-title{padding:12px 0px 8px 0px}.cly-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px;font-family:Inter;color:#333c48;letter-spacing:.003em}.cly-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:400;line-height:20px;font-family:Inter;color:#333c48}.cly-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-vue-events-overview-top-events{padding-left:24px;padding-bottom:16.5px}.cly-vue-events-overview-top-events--tooltip{margin-left:5.5px}.cly-vue-events-overview-top-events__description{font-weight:500;line-height:14px}.cly-vue-events-overview-top-events__trend{padding-right:3px}.cly-vue-events-overview-monitor-events__charts .cly-vue-chart__echart{padding:0px}.cly-vue-events-overview-monitor-events__empty{min-height:100px}.cly-vue-events-overview-monitor-events__empty__block{margin:32px auto 32px auto;max-width:586px}.cly-vue-events-overview-monitor-events__empty--image{width:242px;height:242px;background-image:url("../images/dashboard/events-overview-noevents.svg")}.cly-vue-events-overview-monitor-events--text{font-weight:500;font-size:12px;color:#a7aeb8;letter-spacing:.5px;font-family:Inter;line-height:14.52px}.cly-vue-events-overview-monitor-events .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.cly-vue-events-overview-monitor-events--grey{color:#a7aeb8}.cly-vue-events-overview-monitor-events__heading{padding:8px 0px 16px 0px}.cly-vue-events-overview-monitor-events__configure--position{float:right;margin-left:auto}.cly-events-overview-drawer__subheading{font-size:16px;line-height:24px;font-weight:500;font-family:Inter;color:#333c48}.cly-events-overview-drawer--dragicon{margin-right:18px}.cly-events-overview-drawer__event-records{border-radius:6px;width:100%;padding:14px 16px;background-color:#f8fafd}.cly-events-overview-drawer__basis{flex-basis:0}.cly-events-overview-drawer__dropdown{min-width:230px;width:100%}.cly-events-overview-drawer__close-icon{line-height:1;font-size:24px}.cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-bottom:1px solid #ececec;padding:24px 24px 0 24px}.cly-monitor-events-breakdown-horizontal-tile__title{font-size:12px;font-weight:400;line-height:20px;padding-bottom:8px}.cly-monitor-events-breakdown-horizontal-tile__titleoverview{font-size:12px;font-weight:400;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__eventproperty{font-size:12px;font-weight:400;line-height:20px;color:#81868d}.cly-monitor-events-breakdown-horizontal-tile:nth-of-type(2n) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:none}.cly-monitor-events-breakdown-horizontal-tile:nth-child(1) .cly-monitor-events-breakdown-horizontal-tile__wrapper,.cly-monitor-events-breakdown-horizontal-tile:nth-child(2) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-top:1px solid #ececec}.cly-monitor-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-monitor-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 16px 0px}.cly-monitor-events-breakdown-horizontal-tile__item-title{padding-top:4px}.cly-monitor-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px}.cly-monitor-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-monitor-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:300;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-monitor-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-monitor-events-breakdown-horizontal-tile__overview-name{z-index:1}.cly-monitor-events-breakdown-horizontal-tile__width-50{width:50%}.cly-vue-events-all__alerts a{text-decoration:underline}.cly-vue-events-all{font-size:24px;line-height:32px;font-weight:500;padding-top:6px;letter-spacing:.003em;font-family:Inter;color:#333c48}.cly-vue-events-all__subheading{font-size:14px;line-height:20px;color:#333c48}.cly-vue-events-all--padding{padding-top:32px}.cly-vue-events-all--margin{margin-right:32px}.cly-vue-events-group{color:#fff;background-color:#a7aeb8;font-size:10px;line-height:10px;font-weight:500;letter-spacing:.0042em;vertical-align:middle;padding:3px 4px;border-radius:4px}.cly-vue-events-all-placeholder-text{color:#81868d;font-size:12px;line-height:14.52px;font-weight:500;letter-spacing:.005em;white-space:nowrap}.cly-vue-events-all-date-picker{margin-right:26px}.cly-vue-events-all-tooltip{margin-left:10px}.cly-vue-overview-events-header{padding-right:9.5px;letter-spacing:.003em}.cly-vue-events-header{padding:8px 24px 24px 24px;letter-spacing:.003em;font-family:Inter;line-height:32px;border-bottom:1px solid #ececec;background-color:#fff}.cly-vue-events-header__subheading--widget{padding-right:5.33px;color:#81868d}.cly-vue-events-header__subheading--text{font-family:Inter;line-height:20px;font-size:14px;color:#81868d}.cly-vue-events-header--tooltip{padding-left:9.5px}.cly-vue-events-overview-subheadings{padding-right:9.5px;letter-spacing:.003em;font-family:Inter}.cly-vue-events-overview-subheadings--tooltip{padding-top:3px}.cly-vue-events-overview-subheadings--font{font-family:Inter}.cly-vue-listbox.is-expandable{z-index:2001}.cly-vue-events-omitted-segments__item{color:#81868d;font-size:14px;font-weight:500;line-height:16px;padding:8px;margin:8px}.cly-vue-events-omitted-segments__title{color:#a7aeb8;font-size:13px;font-weight:500;letter-spacing:.5px;text-transform:uppercase;line-height:16px;padding:8px;margin:8px}.technology-analytics-wrapper .allPlatformVersions{border-left:1px solid #ececec;height:264px;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions{height:264px;position:relative;border-left:1px solid #ececec;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions div{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48;position:absolute;top:50%;text-align:center;width:100%;margin-top:-10px}.technology-analytics-wrapper .version-graph-title{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.technology-analytics-wrapper .version-graph-title .divider{color:#a7aeb8}.technology-analytics-wrapper .version-graph-title div:first-child{text-align:left}.technology-analytics-wrapper .version-graph-title div:nth-child(2){text-align:right}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper .version-graph-title .bu-column{padding:0px}.technology-analytics-wrapper .cly-vue-metric-card__wrapper .bu-is-flex-direction-column{margin-right:-1.5rem}.technology-analytics-wrapper .selector_wrapper{position:relative;top:-5px;margin-left:8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .metricCardsWrapper{height:115px}.technology-analytics-wrapper .metricCardsWrapper .emptyCard{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .emptyCard div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .platformVersionsWrapper .emptyCard{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .platformVersionsWrapper{height:309px;padding-bottom:20px}.technology-analytics-wrapper .metricCardsWrapper .bu-columns{flex-wrap:nowrap}.technology-analytics-wrapper .metricCardsWrapper .__view{width:auto !important}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-cards{border-bottom:none}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-card{background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__items{height:115px}.technology-analytics-wrapper__versions{height:291px;padding-bottom:20px}.technology-analytics-wrapper__empty-card{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;top:50%;text-align:center;border-bottom:1px solid #ececec}.technology-analytics-wrapper__empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper__versions-empty-card{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-right:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__versions-empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .app-version-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-version-date-picker-container+.cly-vue-notification__alert-box{margin-top:-8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-carrier-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .devices-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper__metric-cards .bu-column:last-child{margin-right:unset !important}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart__echart{padding-right:0px}.technology-analytics-wrapper .technology-pie-graphs .bu-level .bu-level-right{padding-right:5px}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .cly-vue-chart-legend__secondary{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .bu-level .bu-level-right{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__rail-is-vertical{right:5px !important}.version-graph-block:last-child{margin-bottom:12px}.technology-dashboard-widget>.bu-column:nth-child(odd)>.cly-vue-section{padding-left:4px}.technology-dashboard-widget>.bu-column:nth-child(even)>.cly-vue-section{padding-right:12px}.routename-analytics-geo .geo-date-picker-container{margin-bottom:32px}.routename-analytics-geo .radio-column{width:256px}.leaflet-noclick-map .leaflet-interactive{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.leaflet-control-zoom{user-select:none;border-color:#dcdcdc !important}.leaflet-control-zoom a{color:#333c48;border-bottom-color:#dcdcdc}.geo-analytics-data .cly-vue-button{padding:6px 10px;border-radius:4px}.user-management-drawer-content__pp-options{height:fit-content;align-self:center;margin-left:15px;box-shadow:none}.user-management-drawer-content__pp-options .el-button{box-shadow:none;border:none}.user-management-drawer-content__user-pp{width:100px;height:100px;border-radius:50%}.user-management-drawer-content #user-drawer-dropzone{background-color:#f8fafd;border-radius:6px}.user-management-drawer-content__custom-options{box-shadow:none}.user-management-drawer-content__custom-options div button{box-shadow:none;padding:0px;background:none;border:none}.user-management-drawer-content__under-input-text{text-decoration:underline;cursor:pointer}.user-management-drawer-content__top-section{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__bottom-section{display:flex;margin-top:28px;flex-direction:column;justify-content:space-between}.user-management-drawer-content__input-wrapper{margin-top:10px}.user-management-drawer-content__label{display:flex;justify-content:space-between;flex-direction:column}.user-management-drawer-content__label--text-secondary{color:#81868d}.user-management-drawer-content__label-text{font-style:normal;font-weight:normal;font-size:13px;line-height:16px;color:#333c48}.user-management-drawer-content__help-text{font-family:Inter;font-style:normal;font-weight:normal;font-size:12px;line-height:16px;color:#81868d}.user-management-drawer-content__help-menu-icon{font-family:Inter;font-style:normal;font-weight:normal;font-size:16px;line-height:16px;color:#81868d}.user-management-drawer-content__light-button{background-color:#ddedff;color:#0166d6;font-weight:bold;padding:10px 20px;width:fit-content;margin-top:10px;font-size:13px;border-radius:5px}.user-management-drawer-content__profile-picture-area{margin-top:9px;margin-left:10px}.user-management-drawer-content__profile-picture-area__upload-section{border:1px dashed #81868d;padding:30px;border-radius:8px;display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content__profile-picture-area__upload-section__img-box{background-color:#e2e4e8;height:100px;width:100px;border-radius:50%}.user-management-drawer-content__profile-picture-area__upload-section__description-box{font-size:12px;text-align:center;width:80%}.user-management-drawer-content__profile-picture-area__upload-section__description-box--bold{font-weight:500;color:#0166d6}.user-management-drawer-content__profile-picture-area__upload-section__description-box--gray{color:gray}.user-management-drawer-content__drawer-sub-section{border-radius:6px;background-color:#f8fafd;margin-top:10px;margin-bottom:24px}.user-management-drawer-content__drawer-sub-title{display:flex;flex-direction:row;justify-content:space-between;padding:5px 0px;font-weight:500;font-size:16px}.user-management-drawer-content__permission-table-header{display:flex;justify-content:space-between;margin-top:10px;font-size:12px;border-bottom:1px solid #ebebeb;padding-bottom:10px}.user-management-drawer-content__feature-search{width:calc(40% - 15px);margin-left:10px}.user-management-drawer-content__feature-search .el-input__inner{background-color:#fff !important}.user-management-drawer-content__permission-type-cols{width:75%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-type{text-align:center;font-size:11px;width:25%;margin:auto}.user-management-drawer-content__permission-type .check-label{font-size:15px}.user-management-drawer-content__permission-type .check-text{margin-top:2px}.user-management-drawer-content__permission-type .el-checkbox__label{font-weight:medium !important}.user-management-drawer-content__permission-table-content{height:300px;overflow-y:scroll;padding:10px 0px}.user-management-drawer-content__permission-row{display:flex;flex-direction:row;height:30px;justify-content:center;align-items:center}.user-management-drawer-content__feature-name{width:calc(35% - 15px);text-align:left;padding-left:15px;display:flex;justify-content:flex-start;align-items:center;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.user-management-drawer-content__feature-permissions{width:65%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-box{text-align:center;width:35%}.user-management-drawer-content__section-title{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__section-header{font-family:Inter;font-style:normal;font-weight:500;font-size:12px;line-height:15px;letter-spacing:.5px;text-transform:uppercase;color:#333c48}.user-management-drawer-content__role-section .check-text{margin-top:4px !important}.user-management-drawer-content__role-section .el-checkbox__label{font-weight:normal !important}.user-management-drawer-content__app-selector{width:100%}.user-management-drawer-content__add-permission-set{background-color:#e1efff;border-radius:4px;cursor:pointer;padding:9.5px 12px;font-weight:500;font-size:13px;line-height:13px;color:#0166d6;width:fit-content}.user-management-drawer-content__group-selector{width:100%}.user-management-drawer-content .check-label{color:#0166d6 !important}.user-management-drawer-content .el-tag--info{background-color:#81868d;color:#fff}.user-management-drawer-content .el-icon-close{background-color:#fff !important}.user-management-drawer-content .el-icon-close:hover{color:#81868d !important}.user-management-drawer-content .dropzone-custom-content{display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image>div{height:100px;width:100px;border-radius:50%}.user-management-drawer-content .dz-image-preview{display:flex !important;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image-preview .dz-remove{font-size:12px;font-weight:bold}.user-management-drawer-content .dz-image-preview .dz-image{display:block !important}.manage-users-table{margin:0px}.manage-users-table__groups{display:inline-flex;color:#32659d}.manage-users-table__groups a:hover{color:#1a75da;text-decoration:underline}.manage-users-table__groups-label{margin:0px 2px}.user-management-filter-form .select-full-width{width:100%}.user-management-view .el-tabs--button>.el-tabs__header{padding:24px 24px 0px 24px}.user-management-view .manage-users-action-btn{background-color:#12af51}#main_home_view .el-loading-parent--relative{min-height:100px}#main_home_view .bu-level-left:first-child>h2{font-size:20px !important}#main_home_view .cly-back-link i{color:#333c48}#main_home_view .componentBlock>div{padding-top:16px;padding-bottom:20px}.app-management-view h2{letter-spacing:.3px}.app-management-view h3{letter-spacing:.3px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container{margin-top:12px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container .cly-vue-form-step__section{padding-left:24px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.app-management-view .cly-vue-section__content .el-collapse{border:none}.app-management-view .cly-vue-section__content .app-section{margin-left:12px;margin-right:4px}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section{margin-bottom:24px !important;margin-left:0 !important;margin-right:0 !important;color:#333c48;display:flex;justify-content:space-between}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section .cly-vue-form-field__inner .el-form-item .el-form-item__content{line-height:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p{font-size:14px;line-height:14px;margin:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p+p{font-size:12px;line-height:16px;font-weight:400;margin-top:4px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns{padding:0 !important;margin:0}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-4{width:50%;margin-right:48px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-8{width:37.33%}.app-management-view .account-settings-avatar-box{padding:24px;overflow:auto;flex:auto}.app-management-view .account-settings-avatar-box .el-upload{display:block}.app-management-view .feedback-settings__upload .el-upload{display:block}.app-management-view .feedback-settings__upload img{width:165px;height:50px;margin-left:24px;cursor:default}.app-management-view .feedback-settings__colorpicker .cly-vue-color-picker__picker{overflow:auto}.app-management-view .feedback-settings__button:active,.app-management-view .feedback-settings__button:focus,.app-management-view .feedback-settings__button:hover{background-color:unset !important;border-color:unset !important}.app-management-view .app-management-list{max-height:681px;max-width:223px}.app-management-view .app-management-list .cly-vue-listbox__item span{margin-left:8px;position:relative;top:-8px}.app-management-view .app-management-details .bu-columns{margin:0 !important;padding:0 !important;border-bottom:1px solid #ececec}.app-management-view .app-management-details .bu-columns:last-child{border-bottom:none;margin-bottom:-20px}.app-management-view .app-management-details .el-collapse-item__header.is-active{border-bottom:1px solid #ececec}.app-management-view .app-management-details .el-collapse-item__content{padding-bottom:0}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section{padding-left:48px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content{display:flex !important;justify-content:right !important;float:right;line-height:inherit}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content>div{max-width:232px}.app-management-view .app-management-details .el-collapse-item__arrow{color:#81868d}.app-management-view .app-management-details .el-collapse-item__header{color:#333c48;padding-left:24px !important;text-transform:uppercase}.app-management-view .app-management-details .el-collapse-item__wrap{overflow:unset}.app-management-view .box-card{background-color:#e6f0fb;border:1px solid #0166d6;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.app-management-view .box-card .el-card__body{padding:24px}.app-management-view .box-card .el-card__body p a{color:#0166d6}.app-management-view .box-card .el-card__body p:nth-of-type(1){line-height:24px;font-weight:500;font-size:16px}.app-management-view .box-card .el-card__body p{font-size:14px}.el-dropdown-menu__item--divided__fix-broken{border:none}.el-dropdown-menu__item--divided__fix-broken::before{height:0px}.add-border{margin:0 8px;padding:0;border-top:1px solid #ececec}.add-border>a{display:none}@media(max-width: 2133px){.app-section span div div:nth-last-child(1) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(1) .cly-vue-form-step__section .el-input{width:268%}}@media(max-width: 1280px){.app-section span div div:nth-last-child(2) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(2) .cly-vue-form-step__section .el-input{width:177%}}.report-manager-filter-form .select-full-width{width:100%}.token-manager-drawer__choice .el-radio.is-autosized{flex:1 1 0;min-width:0}.token-manager-drawer__choice .el-radio__label{white-space:normal}.token-manager-drawer__permission-header,.token-manager-drawer__permission-row{display:flex;flex-direction:row;align-items:center}.token-manager-drawer__permission-header{border-bottom:1px solid #ebebeb;padding-bottom:10px;margin-bottom:10px}.token-manager-drawer__permission-row{height:30px}.token-manager-drawer__feature-name{width:35%;display:flex;align-items:center;justify-content:flex-start}.token-manager-drawer__feature-permissions{width:65%;display:flex}.token-manager-drawer__permission-box{flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:center}.token-manager-drawer__permission-box .el-checkbox{margin-right:0}.token-manager-drawer__permission-header .token-manager-drawer__permission-box .el-checkbox{display:flex;flex-direction:column-reverse;align-items:center}.token-manager-drawer__permission-header .token-manager-drawer__permission-box .el-checkbox__label{font-size:11px;padding-left:0;margin-bottom:4px;line-height:1}.header{display:flex;flex-direction:column;gap:20px}.setup-logo{margin-top:38px;margin-left:72px;width:165px;height:50px;background-image:url("../images/pre-login/countly-logo-dark.svg");background-repeat:no-repeat;background-size:contain;position:fixed;left:0px;top:0px}.centered-content{min-height:100vh;display:flex;align-items:center;justify-content:center;margin-bottom:-35px}.setup-byline{color:#81868d;margin-top:12px;font-size:14px}.setup-form{width:520px}.setup-radio-grid{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:10px;row-gap:10px}.setup-radio .el-radio.is-checked{background-color:#e1efff}.setup-radio .el-radio{margin-left:0 !important}.setup-radio .is-autosized.is-bordered .el-radio__input{display:none !important}.setup-radio .el-radio__label{padding-left:0}.setup-radio-item{display:flex;align-items:center;font-size:24px}.setup-radio-icon-bg{width:40px;height:40px;display:flex;align-items:center;justify-content:center;background-color:#e1efff;border-radius:100%}.is-checked .setup-radio-icon-bg{background-color:#0166d6;color:#fff}.setup-radio-icon{background-image:url("../images/dashboard/onboarding/box.svg");background-position:center;background-repeat:no-repeat;width:100%;height:100%}.setup-radio-icon--app-type-mobile{background-image:url("../images/dashboard/onboarding/app-type-mobile.svg")}.setup-radio-icon--app-type-web{background-image:url("../images/dashboard/onboarding/app-type-web.svg")}.setup-radio-icon--app-type-desktop{background-image:url("../images/dashboard/onboarding/app-type-desktop.svg")}.is-checked .setup-radio-icon{filter:brightness(10)}.setup-video-container{max-width:800px}.consent-form{width:700px}.consent-blurb{color:#81868d;font-size:14px}.consent-question{font-size:14px}.initial-populator{width:800px}.quickstart-item{display:flex;align-items:flex-start}.quickstart-item-desc{color:#81868d;text-align:left;word-break:break-word}.quickstart-link,.quickstart-link:visited{color:#0166d6}.quickstart-link:hover{color:#333c48}.preset-list{display:inline-block;position:absolute;left:170px;border:1px solid #a7aeb8;border-radius:4px;background-color:#fff}.preset-list__header{z-index:1997;position:relative;padding:8px 16px}.preset-list__header::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12;top:100%}.preset-list__header .el-button--primary{border:unset;font-weight:500;box-shadow:none}.preset-list__header .el-button--primary:hover{background-color:#cce0f7;color:#0166d6}.preset-list__header .el-button--text{font-weight:500;font-size:14px}.preset-list__body{background-color:#f9f9f9;height:400px;border-radius:4px}.preset-list__body::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(0deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);opacity:.12;left:0;bottom:0}.preset-list__body .preset{display:flex;flex-direction:column;justify-content:center;width:300px;background-color:#fff;border:1px solid #ececec;border-radius:4px;padding:12px;margin-bottom:8px;cursor:pointer}.preset-list__body .preset:first-child{margin-top:16px}.preset-list__body .preset:last-child{margin-bottom:16px}.preset-list__body .preset:hover{border:1px solid #0166d6;background-color:#e1efff}.preset-list__body .preset--selected{border:1px solid #0166d6}.preset-list .sortable-chosen{background-color:#e1efff !important}#preset-drawer .el-radio__label{display:flex;align-items:center}#preset-drawer .el-radio__input{display:flex}#preset-drawer .el-checkbox{font-weight:400}#preset-drawer .el-checkbox__label{padding-left:8px;color:#333c48}#preset-drawer .el-checkbox:hover__label{color:#333c48}/*# sourceMappingURL=manifest.css.map */ +.cly-icon-btn{height:12px;width:12px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-prefix-icon{height:14px;width:12px;margin-left:7px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-input{height:20px;width:20px;display:inline-block;background-position:center;background-repeat:no-repeat;background-size:100%}.cly-icon-zoom{background-image:url("../images/icons/zoom-icon.svg")}.cly-icon-arrow-down{background-image:url("../images/icons/arrow_drop_down.svg")}.cly-icon-arrow-up{background-image:url("../images/icons/arrow_drop_up.svg")}.cly-icon-menu{background-image:url("../images/icons/menu.svg")}.cly-icon-date{background-image:url("../images/icons/date.svg")}.cly-icon-download{background-image:url("../images/icons/download-icon.svg")}.cly-icon-save{background-image:url("../images/icons/save.svg")}.cly-icon-load{background-image:url("../images/icons/load.svg")}.cly-icon-upload{background-image:url("../images/icons/upload.svg")}.cly-icon-arrow_forward-circled{background-image:url("../images/icons/arrow_forward-circled.svg")}.cly-icon-copy{background-image:url("../images/icons/copy.svg")}.cly-icon-copy_interactive{background-image:url("../images/icons/copy_inactive.svg")}.cly-icon-copy_interactive:hover{background-image:url("../images/icons/copy.svg")}.el-button [class*=ion-]+span,[class*=cly-icon-]+span{margin-left:6px}.el-button-group>.el-button{display:flex;align-items:center}.el-button-group>.el-select:first-child .el-button{display:flex;align-items:center}.cly-countly-icon-solid{width:20px;height:20px;background-image:url("../images/icons/countly-icon-solid.svg")}.cly-countly-icon-outline{width:20px;height:20px;background-image:url("../images/icons/countly-icon-outline.svg")}.cly-countly-icon-outline-trash-16px{background-position:99px 962px}.cly-countly-icon-outline-code-16px{background-position:99px 674px}.cly-countly-icon-outline-external-link-16px{background-position:419px 674px}.cly-countly-icon-outline-download-16px{background-position:299px 819px}.cly-countly-icon-outline-x-16px{background-position:139px 1107px}.cly-countly-icon-outline-document-download-16px{background-position:179px 1058px}.cly-countly-icon-outline-exclamation-circle-16px{background-position:339px 868px}.cly-countly-icon-outline-plus-circle-16px{background-position:299px 867px}.cly-countly-icon-outline-globe-16px{background-position:219px 1010px}.cly-countly-icon-outline-user-group-16px{background-position:300px 1202px}*{outline:none}html{height:100%;width:100%}body{height:100%;width:100%;margin:0;padding:0;overflow:auto;background-color:#f9f9f9;user-select:text;font-family:Inter,Ubuntu,Helvetica,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1{font-size:32px;line-height:48px;font-weight:500;margin:0;padding:10;color:#333c48}h2{font-size:24px;line-height:32px;font-weight:500;margin:0;padding:0;color:#333c48}h3{font-size:20px;line-height:30px;font-weight:500;margin:0;padding:0;color:#333c48}h4{font-size:16px;line-height:24px;font-weight:500;margin:0;padding:0;color:#333c48}h5{font-size:14px;line-height:20px;font-weight:500;margin:0;padding:0;color:#333c48}h6{font-size:14px;line-height:18px;font-weight:500;margin:0;padding:0;color:#333c48}textarea,input,p,h1,h2,h3,h4,h5,h6,button{font-family:Inter !important}.el-table th{padding:9px 0px;box-sizing:border-box;text-transform:uppercase;font-size:12px;font-style:normal;font-weight:500;border-bottom-width:2px}.el-table th .cell{line-height:16px;letter-spacing:.5px}.el-table th:hover .sort-caret.ascending{border-bottom-color:#005def}.el-table th:hover .sort-caret.descending{border-top-color:#005def}.el-table th.is-leaf{border-bottom-width:2px;border-top:1px solid #eef2f5}.el-table td{padding:14px 0px;font-style:normal;font-weight:normal;font-size:14px;box-sizing:border-box}.el-table td .cell{line-height:20px}.el-table.el-table--has-options td .cell{line-height:23px}.el-table th:first-child .cell,.el-table td:first-child .cell{padding-left:16px}.el-table th:last-child .cell,.el-table td:last-child .cell{padding-right:16px}.el-table .caret-wrapper{height:15px}.el-table .sort-caret{border-width:4px}.el-table .sort-caret.ascending{top:-2px}.el-table .sort-caret.descending{bottom:-1px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#005def}.el-table .descending .sort-caret.descending{border-top-color:#005def}.el-table .cell{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.el-table .cell>.el-checkbox,.el-table .cell>.el-switch,.el-table .cell>.el-radio{overflow:unset}.el-table table{width:0px}.el-radio.is-autosized{padding:16px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized.is-bordered+.el-radio.is-autosized.is-bordered{margin-left:10px}.el-radio.is-autosized.is-bordered{border-color:#cfd6e4;display:flex;align-items:center}.el-radio.is-autosized.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized.is-bordered.is-checked{border-color:#0166d6}.el-radio.is-autosized-vstack{padding:12px;display:flex;width:100%;margin-right:0;height:unset;background-color:#fff}.el-radio.is-autosized-vstack .el-radio__label{justify-content:space-between;display:flex;width:100%;align-items:baseline}.el-radio.is-autosized-vstack.is-bordered{align-items:center}.el-radio.is-autosized-vstack.is-bordered .el-radio__input{display:flex}.el-radio.is-autosized-vstack.is-bordered.is-multiline{align-items:flex-start}.el-radio.is-autosized-vstack.is-bordered.is-multiline .el-radio__label{padding-top:2px}.el-radio.is-autosized-vstack.is-bordered+.el-radio.is-autosized-vstack.is-bordered{margin-left:0;margin-top:7px}.el-radio.is-bordered{border:1px solid #cfd6e4}.el-radio:hover:not(.is-disabled) .el-radio__label{color:inherit}.el-radio.is-checked:not(.is-disabled):hover .el-radio__label{color:inherit}.el-radio__input.is-checked+.el-radio__label{color:inherit}.el-collapse.is-bordered-box{border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.el-collapse.is-bordered-box .el-collapse-item__header{border-radius:4px;padding:0rem 1.5rem 0rem 1.5rem}.el-collapse.is-bordered-box .el-collapse-item__header.is-active{border-bottom-color:#ececec}.el-collapse.is-bordered-box .el-collapse-item__wrap{background-color:rgba(0,0,0,0)}.el-collapse.is-bordered-box .el-collapse-item__content{margin:0rem 1.5rem 0rem 1.5rem}.el-switch__label *{font-weight:normal;color:#a7aeb8;font-size:12px}.el-input.is-adaptive .el-input__inner{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:10px;vertical-align:middle}.el-select .el-input.is-arrow .el-input__inner{padding-right:30px}.el-button.is-wireframe{background:rgba(0,0,0,0);border:1px dotted #0166d6;box-sizing:border-box;box-shadow:0px 2px 4px rgba(1,122,255,.07)}.el-button.el-button--text.is-danger{color:#d23f00}.el-button.el-button--text.is-danger:hover{background-color:#f6f6f6}.el-button.is-light-blue{box-shadow:none;-webkit-box-shadow:none;border:none;font-weight:500;height:32px}.el-button.is-light-blue:not(.is-disabled){color:#0166d6;background-color:#e1efff}.el-button.is-light-blue:not(.is-disabled):hover{background-color:#cce0f7}.el-button-group>.el-select{float:left}.el-button-group>.el-select:first-child .el-button{border-top-right-radius:0;border-bottom-right-radius:0;-webkit-box-shadow:none;box-shadow:none}.el-button-group>.el-select:not(:last-child){margin-right:-1px}.el-button-group>.el-select:active,.el-button-group>.el-select:focus,.el-button-group>.el-select:hover{z-index:1}.el-button-group>.el-select:active .el-button,.el-button-group>.el-select:focus .el-button,.el-button-group>.el-select:hover .el-button{z-index:1}.el-input-number.is-slim .el-input__inner{padding-left:5px;padding-right:26px}.el-input-number.is-slim.el-input-number--small .el-input-number__decrease,.el-input-number.is-slim.el-input-number--small .el-input-number__increase{width:22px;font-size:14px}.el-tabs--card>.el-tabs__header{margin:0}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap{margin-bottom:-2px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap.is-scrollable{border-bottom:none;border-top-right-radius:4px;border-top-left-radius:4px}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next{background:linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{background:linear-gradient(270deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.85) 100%)}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev{opacity:.85}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-next:hover,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap .el-tabs__nav-prev:hover{opacity:1}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-top-left-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{border-top-right-radius:3px}.el-tabs--card>.el-tabs__header .el-tabs__item{background-color:#fcfcfc;padding:0;height:auto;text-align:left;line-height:32px;border-bottom:2px solid #ececec}.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#0166d6;background-color:#fff}.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding:0px}.el-radio-group.is-full{display:flex}.el-radio-group.is-full .el-radio-button{flex-grow:1}.el-radio-group.is-full .el-radio-button__inner{width:100%}.el-dropdown-menu__item{padding:7px 6px}.el-dropdown-menu__item>i.cly-icon-outline{padding:2px 7px}.el-select-dropdown .el-scrollbar__bar{opacity:1 !important;right:0}.el-select-dropdown__item{padding:7px 6px}.el-tiptap-editor{border-radius:4px}.el-tiptap-editor .el-tiptap-editor__menu-bar{border-color:#cfd6e4}.el-tiptap-editor .el-tiptap-editor__menu-bar::before{background-color:#cfd6e4}.el-tiptap-editor>.el-tiptap-editor__content{border:1px solid #cfd6e4 !important;border-top:0 !important;border-bottom:0 !important}.el-tiptap-editor>.el-tiptap-editor__content pre code{font-family:"Courier New"}.el-tiptap-editor .el-tiptap-editor__footer{border-color:#cfd6e4}.el-tiptap-editor .border-top-radius{border-top-left-radius:4px !important;border-top-right-radius:4px !important}.el-tiptap-editor .border-bottom-radius{border-bottom-left-radius:4px !important;border-bottom-right-radius:4px !important}.el-tiptap-editor .fa-icon{fill:#333c48}.el-tiptap-editor__content{overflow-x:unset !important}.el-tiptap-editor__content>pre>code{font-family:"Courier New" !important}.el-tiptap-editor__content span>span{background-color:inherit}.el-tiptap-editor__content hr{width:100%}.el-dialog.el-tiptap-edit-link-dialog .el-button.is-round{border-radius:4px}.el-dialog.el-tiptap-edit-link-dialog .el-button.el-button--primary{border-color:#12af51;background-color:#12af51}.el-checkbox__input .el-checkbox__inner{color:#fff;text-align:center}.el-checkbox__input.is-checked .el-checkbox__inner::before{content:"" !important;font-family:"countly-icons-outline" !important;border:none !important;position:absolute;top:0px;width:15px;left:0px}.el-checkbox__input.is-checked .el-checkbox__inner::after{border:none !important}.el-checkbox__input.is-checked.is-disabled .el-checkbox__inner{color:#d0d0d0}.el-checkbox__inner::after{display:none}.el-checkbox.is-checked .el-checkbox__inner::after{display:block}.el-upload__folder-preview-content{height:32px}.el-upload-dragger{background-color:#fcfcfc;display:flex;flex-direction:column;justify-content:center}.el-upload-dragger .fa-folder{line-height:0}.el-upload-list__item-name{background-color:#fff;width:100%;border:1px solid #ececec;border-radius:5px;height:68px;padding-left:unset;cursor:default !important}.el-upload-list__item-remove{margin-left:auto;margin-right:24px;cursor:pointer !important}.el-upload-list__item-preview .cly-io-document-text{font-size:20px;color:#000;margin-right:4px}.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#000}.bu-level:not(:last-child){margin-bottom:0px}.bu-tag.is-slim{padding:0 .5em;height:1.5em}.bu-tag.is-legend{padding:0;height:.5em;width:1em;border-radius:3px}.bu-tag.is-curved{border-radius:67px;height:16px;padding-left:4px;padding-right:4px;min-width:12px}.vjs-tree{padding:10px}.vjs-value-boolean,.vjs-value-number{color:#31acb4}.vjs-value-string{color:#6c47ff}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f0fb}.cly-vue-theme-clydef{background-color:#f8f9fa}#main-views-container{height:100%;width:100%;overflow:auto}#main-views-container .main-view{min-width:768px;min-height:400px;width:100%;padding:0px 0 35px 0 !important;transition:width .55s;will-change:width;overflow:auto}.cly-vue-main{padding:0px 24px;margin:0}.cly-vue-section--has-configurator-skin .cly-vue-section__content{background:#fff;border:1px solid #ececec;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.cly-vue-section--has-configurator-skin .cly-vue-section__content .cly-vue-section__sub{border-top:none !important;border-bottom:1px solid #ececec;align-items:center;display:flex}.cly-vue-section--has-default-skin .cly-vue-section__content{border-top:1px solid #ececec;border-bottom:1px solid #ececec}.cly-vue-section .cly-vue-section__content-config{border-bottom:1px solid #ececec}.cly-vue-section:not(:last-child){margin-bottom:32px}.cly-vue-header{padding:24px 24px;margin-bottom:32px;border-bottom:1px solid #ececec;position:relative}.cly-vue-header__level{padding-top:8px;padding-bottom:12px}.cly-vue-header__level--no-pt{padding-top:0px}.cly-vue-header__level--no-pb{padding-bottom:0px}.cly-vue-header--no-mb{margin-bottom:0px}.cly-vue-header--no-bb{border-bottom:none}.cly-vue-header+div>.cly-vue-tabs{background-color:#fff;border-bottom:1px solid #ececec;margin-bottom:32px;padding:0px 24px}.cly-vue-select-x__pop .cly-vue-listbox{background-color:rgba(0,0,0,0) !important}.cly-vue-select-x__pop .el-tabs__active-bar{background-color:#0166d6}.cly-vue-select-x__pop .el-tabs__nav-wrap::after{background-color:rgba(0,0,0,0)}.cly-vue-select-x__pop .el-tabs__nav-scroll{margin:0 14px}.cly-vue-select-x__pop .el-tabs__header{margin:0 0 1px 0;z-index:2000}.cly-vue-select-x__pop .el-tabs__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:40px;opacity:.12}.cly-vue-select-x__pop--hidden-tabs .el-tabs__header::after{top:0px}.cly-vue-select-x__pop--hidden-tabs .el-tabs__nav-scroll{display:none}.cly-vue-select-x__pop--hidden-header .cly-vue-select-x__header{padding:0}.cly-vue-select-x__pop--hidden-tabs.cly-vue-select-x__pop--hidden-header .el-tabs__header::after{background:none;height:0;width:0}.cly-vue-select-x__title{font-weight:500;font-size:16px;line-height:24px;color:#333c48;padding-bottom:16px}.cly-vue-select-x__header-slot{padding-bottom:16px}.cly-vue-select-x__header{padding:16px}.cly-vue-select-x__header input[type=text]{background-color:#f6f6f6}.cly-vue-select-x__footer{border-top:1px solid #ececec}.cly-vue-select-x__commit-section{float:right;margin:16px}.cly-vue-select-x__pop--has-single-option .cly-vue-select-x__header-slot,.cly-vue-select-x__pop--has-slim-header .cly-vue-select-x__header-slot{padding:0}.cly-vue-select-x__pop--has-single-option .el-tabs__header::after{content:none}.cly-vue-select-x .el-select-head{width:100%}.cly-vue-listbox{background-color:#fff}.cly-vue-listbox label.el-checkbox{width:100%;margin-left:8px}.cly-vue-listbox.is-expandable{transition:width 200ms;width:100%;z-index:100}.cly-vue-listbox.is-expanded{width:130%;position:relative;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.08);box-shadow:0 1px 4px rgba(0,0,0,.08)}.cly-vue-listbox.cly-vue-listbox--bordered{border-radius:4px;border:1px solid #ececec}.cly-vue-listbox .cly-vue-listbox__no-data{padding:8px;line-height:20px;font-weight:500;color:#333c48;font-size:14px}.cly-vue-listbox .el-checkbox-group{overflow:hidden}.cly-vue-listbox .el-checkbox__label{line-height:20px;font-weight:400;color:#333c48;max-width:330px !important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom}.cly-vue-listbox .el-checkbox__input.is-checked+.el-checkbox__label{color:#333c48}.cly-vue-listbox .drag-handler{visibility:hidden;margin-right:8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cly-vue-listbox__header{margin:0 0 1px 0;z-index:1997;border-bottom:1px solid #ececec;position:relative}.cly-vue-listbox__header::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:57px;left:0;opacity:.12}.cly-vue-listbox .cly-vue-listbox__group{font-size:12px;line-height:14px;background-color:#f6f6f6;border-bottom:solid 1px #ececec;max-height:32px;display:flex;align-items:center;padding:8px}.cly-vue-listbox .cly-vue-listbox__item{display:flex;cursor:pointer;align-items:center;justify-content:space-between}.cly-vue-listbox .cly-vue-listbox__item.selected{background-color:#0166d6}.cly-vue-listbox .cly-vue-listbox__item.selected *{color:#fff}.cly-vue-listbox .cly-vue-listbox__item .cly-vue-listbox__remove-option{display:none}.cly-vue-listbox .cly-vue-listbox__item.hover .cly-vue-listbox__remove-option{display:block}.cly-vue-listbox .cly-vue-listbox__item-content{width:100%}.cly-vue-listbox__item-label{max-width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-listbox--disabled .cly-vue-listbox__item{background-color:#f6f6f6}.cly-vue-listbox--disabled .cly-vue-listbox__item *{color:#a7aeb8}.cly-vue-listbox--disabled .cly-vue-listbox__item.selected{opacity:.5}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover{background-color:#f6f6f6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .drag-handler{visibility:visible}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-prefix *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-label *,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix,.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item:not(.selected):hover .cly-vue-listbox__item-suffix *{color:#0166d6}.cly-vue-listbox:not(.cly-vue-listbox--disabled) .cly-vue-listbox__item .cly-vue-listbox__remove-option:hover{color:#0166d6}.cly-vue-listbox--has-default-skin .cly-vue-listbox__item{padding:8px;border-radius:4px;line-height:16px}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item{padding:8px;height:55px;box-sizing:border-box;border-bottom:1px solid #ececec}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected{border-left:2px solid #0166d6;background-color:#f6f6f6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item.selected *{color:#0166d6}.cly-vue-listbox--has-jumbo-skin .cly-vue-listbox__item:last-child{border-bottom:none}.cly-vue-listbox--has-margin .cly-vue-listbox__item{margin:8px}.cly-fields-select.default-skin{display:inline-block}.cly-fields-select.default-skin .el-input__inner::placeholder{color:#000}.cly-fields-select.default-skin .fields-select-body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:0px;z-index:100;border:1px solid #d0d0d0;border-radius:2px;padding:16px;width:max-content}.cly-fields-select.default-skin .fields-select-body .controls{float:right;margin-top:10px}.cly-fields-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-fields-select__reset{float:right;font-size:12px;padding-bottom:26px;padding-top:0px;color:#d23f00;cursor:pointer;line-height:20px}.cly-fields-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-fields-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-fields-select__confirm{background-color:#12af51;color:#fff}.cly-fields-select__cancel{background:#f6f6f6}.cly-fields-select__dropdown .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin{display:inline-block}.cly-multi-select.default-skin .el-input__inner::placeholder{color:#000}.cly-multi-select.default-skin .cly-multi-select__body{box-shadow:0 3px 7px rgba(0,0,0,.08);background-color:#fff;position:absolute;top:-2px;left:-2px;z-index:100;border:1px solid #d0d0d0;border-radius:4px;padding:16px;width:max-content}.cly-multi-select.default-skin .cly-multi-select__controls{float:right;margin-top:10px}.cly-multi-select__title-wrapper{margin-bottom:30px}.cly-multi-select__title{color:#333c48;font-family:Inter;line-height:24px;font-weight:500;font-size:16px}.cly-multi-select__reset{float:right;font-size:12px;padding:4px 8px;color:#d23f00;cursor:pointer;line-height:20px}.cly-multi-select__reset span{height:20px;line-height:20px}.cly-multi-select__reset:hover{background:#f6f6f6}.cly-multi-select__field{color:#333c48;font-family:Inter;line-height:20px;font-weight:500;font-size:12px;padding-bottom:3px}.cly-multi-select .cly-multi-select__confirm-button{margin-left:4px}.cly-multi-select__field-dropdown{width:320px;height:32px;margin-bottom:16px}.cly-multi-select__dropdown .el-input__inner::placeholder{color:#000}.cly-vue-dropdown__pop{padding:0px;width:fit-content}.cly-vue-dropdown__pop-container{word-break:initial}.cly-vue-dropdown__dropdown-icon{width:16px;line-height:16px;height:16px;background-size:16px 16px;border-radius:4px;background-position:center;background-color:#017aff;display:inline-block}.cly-vue-more-options .el-button{border:1px solid #cfd6e4}.cly-vue-more-options .el-button .is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.cly-vue-eldatatable.silent-loading .el-loading-spinner{visibility:hidden}.cly-vue-eldatatable.silent-loading .el-loading-mask{display:none !important}.cly-vue-eldatatable.display-mode--list .el-table{background-color:unset}.cly-vue-eldatatable.display-mode--list .el-table__body{border-collapse:separate;border-spacing:0 8px}.cly-vue-eldatatable.display-mode--list .el-table__row{cursor:pointer}.cly-vue-eldatatable.display-mode--list .el-table__row td{cursor:pointer;height:56px;border-top:1px solid #ececec !important;border-bottom:2px solid #ececec !important;background-color:#fff !important;padding:18px 0px}.cly-vue-eldatatable.display-mode--list .el-table__row td:first-child{border-left:1px solid #ececec !important;border-radius:4px 0 0 4px !important}.cly-vue-eldatatable.display-mode--list .el-table__row td:last-child{border-right:1px solid #ececec !important;border-radius:0 4px 4px 0 !important}.cly-vue-eldatatable.display-mode--list .el-table__row td .cell{line-height:20px}.cly-vue-eldatatable.display-mode--list .el-table__row td.drag-icon .cell{text-overflow:unset !important}.cly-vue-eldatatable.display-mode--list .el-table thead tr{background-color:unset !important}.cly-vue-eldatatable.display-mode--list .el-table th{background-color:unset !important;border:none !important;padding:0 !important;color:#81868d !important}.cly-vue-eldatatable.display-mode--list .el-table__fixed-right::before{height:0 !important}.cly-vue-eldatatable__header{height:56px;border-left:none;border-right:none;box-sizing:border-box;padding:12px;border-top:1px solid #ececec}.cly-vue-eldatatable__header--white{background-color:#fff;color:#333c48;font-size:13px}.cly-vue-eldatatable__export--extended::after{content:"";position:absolute;width:100%;height:12px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);top:185px;left:0;opacity:.12}.cly-vue-eldatatable__export--fileExport{border-top:1px solid #e2e4e8}.cly-vue-eldatatable__export--radio-button .el-radio-button{width:99px;display:inline-grid}.cly-vue-eldatatable__export--search input[type=text]{background-color:#f6f6f6}.cly-vue-eldatatable__search--grey input{background-color:#fbfdfe}.cly-vue-eldatatable__footer{height:40px;box-shadow:0px 2px 0px #eef2f5;border-left:none;border-right:none;box-sizing:border-box;padding:0px 12px}.cly-vue-eldatatable__footer--white{background-color:#fff;color:#808a9d;font-size:13px}.cly-vue-eldatatable .undo-row{position:absolute;left:0;padding:9px 0px;background-color:#ffd7d6;color:#2b2b2b;width:100%;height:100%;top:0;z-index:999;vertical-align:middle;display:flex;align-items:center;justify-content:center}.cly-vue-eldatatable .undo-row a{color:#017aff;cursor:pointer}.cly-vue-eldatatable .el-table-column--options .cly-vue-more-options{position:absolute;top:calc(50% - 16px);right:calc(50% - 20px)}.cly-vue-eldatatable div.cell{padding-left:16px;padding-right:8px}.cly-vue-eldatatable__empty-slot{height:200px}.cly-vue-table{width:100%}.cly-vue-table thead{background-color:#f6f6f6;border-top:1px solid #ececec;border-bottom:2px solid #ececec}.cly-vue-table thead th{color:#333c48;font-weight:500;font-size:12px;padding:9px;text-align:left}.cly-vue-table tbody td{padding:0px 9px}.cly-vue-chart{position:relative}.cly-vue-chart .bu-level{padding:0 20px 0 33px}.cly-progress-bar-container{width:100%}.cly-progress-bar-container.has-min-bradius .first-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:4px;border-top-left-radius:4px}.cly-progress-bar-container.has-min-bradius .last-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:4px;border-top-right-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__outer{border-radius:4px}.cly-progress-bar-container.has-min-bradius .el-progress:not(.progress-bar-stack) .el-progress-bar__inner{border-radius:4px}.cly-progress-bar-stack-container{float:left}.progress-bar-stack .el-progress-bar__inner{border-radius:0px}.first-progress-bar-stack .el-progress-bar__outer{border-bottom-right-radius:0px;border-top-right-radius:0px}.middle-progress-bar-stack .el-progress-bar__outer{border-radius:0px}.last-progress-bar-stack .el-progress-bar__outer{border-bottom-left-radius:0px;border-top-left-radius:0px}.cly-vue-tabs__primary-tab-list{padding:24px;box-sizing:border-box}.cly-vue-tabs__tab{height:34px;padding:10px 12px;display:inline-block;box-sizing:border-box}.cly-vue-tabs__tab--default{color:#81868d;line-height:14px;font-weight:500;font-size:14px;cursor:pointer}.cly-vue-tabs__tab--primary{border-radius:6px}.cly-vue-tabs__tab--primary:hover{color:#0166d6}.cly-vue-tabs__tab--secondary:hover{color:#333c48}.cly-vue-tabs__tab--primary-active{color:#0166d6;background-color:#e1efff}.cly-vue-tabs__tab--secondary-active{color:#333c48;border-bottom:2px solid #0166d6}.cly-vue-chart{width:100%;height:100%}.cly-vue-chart__echart{box-sizing:border-box;display:inline-block;width:100%}.cly-vue-chart--padded .cly-vue-chart__echart{padding-top:20px}.cly-vue-chart--full .cly-vue-chart__echart{padding:0}.cly-vue-chart-legend{display:inline-block;width:100%}.cly-vue-chart-legend__primary,.cly-vue-chart-legend__secondary{white-space:nowrap;overflow:auto;box-sizing:border-box;height:100%}.cly-vue-chart-legend__secondary--text-center{text-align:center}.cly-vue-chart-legend__p-series{display:inline-block;margin-left:64px;cursor:pointer}.cly-vue-chart-legend__p-series:first-child{margin-left:36px}.cly-vue-chart-legend__s-series{display:inline-block;margin-left:48px;cursor:pointer}.cly-vue-chart-legend__s-series:first-child{margin-left:0px}.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-rectangle,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-series--deselected .cly-vue-chart-legend__s-percentage{color:#a7aeb8}.cly-vue-chart-legend__second-row{margin-top:3px}.cly-vue-chart-legend__p-checkbox{height:16px;width:16px;border:1px solid #a7aeb8;display:inline-block;box-shadow:inset 0 0 0px 1.5px #fff;border-radius:4px;vertical-align:middle;box-sizing:border-box}.cly-vue-chart-legend__p-title{display:inline-block;vertical-align:middle;font-size:14px;color:#333c48}.cly-vue-chart-legend__p-tooltip{display:inline-block}.cly-vue-chart-legend__p-tooltip i{font-size:15px}.cly-vue-chart-legend__p-number{display:inline-block;font-size:24px;font-weight:500;color:#333c48}.cly-vue-chart-legend__p-trend{display:inline-block;font-size:14px;font-weight:500}.cly-vue-chart-legend__p-trend--trend-up{color:#12af51}.cly-vue-chart-legend__p-trend--trend-down{color:#d23f00}.cly-vue-chart-legend__s-rectangle{width:12px;height:6px;border-radius:3px;display:inline-block;vertical-align:middle;margin:0px 5px}.cly-vue-chart-legend__s-title,.cly-vue-chart-legend__s-percentage{display:inline-block;vertical-align:middle;margin-left:3px;font-size:12px;font-weight:400;color:#333c48}.cly-vue-chart-legend__bottom .cly-vue-chart-legend__primary,.cly-vue-chart-legend__bottom .cly-vue-chart-legend__secondary{padding:0px 24px 20px}.cly-vue-chart-legend__right{border-left:1px solid #ececec;width:265px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{margin-left:0px;padding:3px 7px;box-sizing:border-box;width:100%;display:block;border-bottom:1px solid #ececec}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{background-color:#f6f6f6;border-radius:0px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover .cly-vue-chart-legend__s-percentage{font-weight:500}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title,.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{font-size:14px;line-height:30px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 30px);text-align:left}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-percentage{min-width:50px;text-align:right}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:10px}.cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__view::before{content:"";position:absolute;width:100%;height:8px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie{border-left:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary{padding-top:30px;padding-bottom:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series{border:none}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:hover{border-radius:8px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series .cly-vue-chart-legend__s-title{width:calc(100% - 86px)}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .cly-vue-chart-legend__secondary .cly-vue-chart-legend__s-series:first-child{padding-top:3px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view{display:flex;flex-direction:column;justify-content:center;padding-right:30px}.cly-vue-chart-legend__right.cly-vue-chart-legend__pie .__vuescroll .__view::before{background:none;height:0}.chart-type-toggle-wrapper__select{width:126px}.chart-type-toggle-wrapper__title{margin-top:16px;margin-left:16px;letter-spacing:.5px}.chart-type-toggle-wrapper__type{font-family:Inter;font-style:normal;font-weight:500;font-size:13px;line-height:13px}.chart-type-annotation-wrapper__icon{margin-top:1px}.chart-type-annotation-wrapper__img{margin-bottom:-2px}.chart-zoom-button{margin-right:12px}.cly-vue-zoom__external .chart-zoom-button{margin:0}.chart-download-button{width:42px;height:32px}.shadow-container{position:relative}.shadow-container:after{display:block;content:"";position:absolute;width:100%;margin:0 auto;height:70px;border:0;bottom:0;background:linear-gradient(180deg, rgba(255, 255, 255, 0.7) 0%, #FFFFFF 100%)}.chart-tooltip{max-height:360px;overflow:auto;margin-bottom:2px;max-width:300px;white-space:nowrap}.chart-tooltip__header{letter-spacing:.5px;text-transform:uppercase}.chart-tooltip__body{background-color:#fff;margin-bottom:16px;margin-top:16px}.chart-tooltip__body:last-child{margin-bottom:0 !important}.chart-tooltip__body.chart-tooltip__single-row{display:flex;margin-bottom:14px;margin-top:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__bar{margin-top:6px;float:none}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__series{display:flex;flex-direction:column;justify-content:space-between;width:calc(100% - 24px);margin-left:14px}.chart-tooltip__body.chart-tooltip__single-row .chart-tooltip__value{margin-top:-3px;margin-left:30px;display:flex;flex-direction:column;justify-content:space-between}.chart-tooltip__has-scroll .chart-tooltip__value{margin-right:10px}.chart-tooltip__bar{float:left;width:12px;min-width:12px;height:6px;border-radius:3px;margin-top:5px}.chart-tooltip__series{margin-left:24px;overflow:hidden}.chart-tooltip__series span{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.chart-tooltip__value{margin-top:2px;margin-left:24px}.graph-notes-tooltip{width:286px;max-height:118px;overflow:auto}.graph-notes-tooltip__header{width:100%}.graph-notes-tooltip__header .input-owner{font-weight:500}.graph-notes-tooltip__header .name-wrapper{margin-top:10px}.graph-notes-tooltip__header .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-notes-tooltip__header .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5;background-color:#f6f6f6}.graph-notes-tooltip__header .note-type{margin-top:12px}.graph-notes-tooltip__body{margin-top:12px}.graph-notes-tooltip__body .input-notes{word-break:break-word;display:inline-block;white-space:normal}.graph-notes-tooltip.minimize{width:180px}.graph-notes-tooltip.minimize .input-owner{font-size:12px}.graph-notes-tooltip.minimize__header{margin-top:0px}.graph-notes-tooltip.minimize .input-notes{font-size:12px}.graph-notes-tooltip.minimize .input-minimizer{margin-bottom:10px}.graph-notes-tooltip.minimize .graph-notes-tooltip__body{margin-top:5px}.graph-notes-tooltip.minimize .name-wrapper{margin-top:0px}.graph-notes-tooltip.minimize .note-date{font-size:11px}.graph-notes-tooltip.minimize .note-type{margin-top:2px;font-size:11px;margin-right:4px}.graph-tooltip-wrapper{margin-right:2px;margin-bottom:4px}.graph-tooltip-wrapper .el-icon-close{color:#898787;z-index:9999;cursor:pointer}.graph-tooltip-wrapper .el-icon-close:hover{font-size:14px;color:#898787;font-weight:600;opacity:.5}.graph-tooltip-wrapper__container{max-height:180px;overflow:hidden;overflow:auto}.cly-vue-tooltip-icon{font-size:17px;color:#a7aeb8;vertical-align:middle;width:18px;height:18px}.cly-in-page-notification{border-radius:4px;text-align:center;margin-bottom:32px}.cly-in-page-notification--light-informational{background-color:#e1efff;color:#333c48}.cly-in-page-notification--light-successful{background-color:#ebfaee;color:#333c48}.cly-in-page-notification--light-destructive{background-color:#fbece5;color:#333c48}.cly-in-page-notification--light-warning{background-color:#fcf5e5;color:#333c48}.cly-in-page-notification--dark-successful{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-informational{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-warning{background-color:#24292e;color:#fff}.cly-in-page-notification--dark-destructive{background-color:#24292e;color:#fff}.cly-in-page-notification a:hover{text-decoration:underline;cursor:hand}.cly-vue-back-link{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase;margin-bottom:24px}.cly-vue-back-link:visited{cursor:pointer;color:#616161;font-size:12px;display:inline-block;text-transform:uppercase}.cly-vue-back-link:hover span{text-decoration:underline}.cly-divider{width:100%;border-top:1px solid #ececec}.cly-divider.is-2{border-top-width:2px}.cly-divider.is-dashed{border-top-style:dashed}.cly-divider.is-dotted{border-top-style:dotted}.cly-event-select .el-radio-group{display:flex}.cly-event-select .el-radio-button{flex-grow:1}.cly-event-select .el-radio-button__inner{width:100%}.cly-vue-color-tag__color-tag-wrapper{width:20%}.cly-vue-color-tag__color-tag{width:92%;height:37px;margin-bottom:5px;border-radius:4px}.cly-vue-color-tag__color-tag__selected{border:2px solid #0166d6}.cly-vue-color-tag__checkmark{color:#fff}.cly-vue-empty-view-framed{border:1px solid #e2e4e8;background-color:#f8fafd;border-radius:8px;background-image:url("../images/icons/empty-background.svg");background-position:100% 100%;background-repeat:no-repeat}.cly-vue-json-editor .el-dialog__header{text-align:left;padding:8px 16px 0 !important;color:#fff}.cly-vue-json-editor .el-dialog__body{padding:0 !important}.cly-vue-json-editor__textarea{width:100%;box-sizing:border-box;outline:none;border:none;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fcfcfc}.cly-breadcrumbs a:hover{text-decoration:underline}.cly-is-fullwidth{width:100%}.is-estimate:hover{color:#0166d6;text-decoration:underline;text-decoration-style:dotted}#cly-vue-sidebar{left:0;height:100%;z-index:2000;user-select:none;color:#d6d6d6}.cly-vue-sidebar{height:100%}.cly-vue-sidebar .tooltip{display:block !important;z-index:10000}.cly-vue-sidebar .tooltip .tooltip-inner{background:#fff;color:#000}.cly-vue-sidebar .tooltip .tooltip-arrow{display:none}.cly-vue-sidebar .tooltip[x-placement^=right]{margin-left:0px}.cly-vue-sidebar .cly-vue-listbox__item-label{width:350px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cly-vue-sidebar__slide-transition-enter-active{transition:all .3s ease}.cly-vue-sidebar__slide-transition-leave-active{transition:all .8s cubic-bezier(1, 0.5, 0.8, 1)}.cly-vue-sidebar__slide-transition-enter,.cly-vue-sidebar__slide-transition-leave-to{transform:translateX(-224px)}.cly-vue-sidebar ul{list-style:none;padding:0;margin:0}.cly-vue-sidebar ul li{padding:0px}.cly-vue-sidebar__app-selector__dialog_box .el-dialog__body{padding:0px !important}.cly-vue-sidebar .el-collapse{border:none}.cly-vue-sidebar__app-name{font-size:14px}.cly-vue-sidebar__app-name-type{width:120px}.cly-vue-sidebar__app-selector{border:1px solid #424243;box-sizing:border-box;box-shadow:0px 11px 14px rgba(0,0,0,.371635);border-radius:4px;height:50px}.cly-vue-sidebar__app-type{opacity:.57}.cly-vue-sidebar__menu-options{width:48px;height:100%;overflow:auto;color:#a7aeb8;z-index:2005;background-color:#191c20}.cly-vue-sidebar__menu-options ul:first-child li:first-child{margin-top:28px}.cly-vue-sidebar__menu-option{width:48px;margin-top:24px;font-size:20px;cursor:pointer}.cly-vue-sidebar__menu-option .el-popover__reference:hover{color:#fff !important}.cly-vue-sidebar__menu-option-toggle{height:48px;background-color:#24292e;border-top-left-radius:50%;border-bottom-left-radius:50%}.cly-vue-sidebar__menu-option-toggle--no-bg{background-color:rgba(0,0,0,0)}.cly-vue-sidebar__menu-option-toggle--rotate-right{transform:rotate(180deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu-option-toggle--rotate-left{transform:rotate(0deg);transition:transform .7s ease-in-out}.cly-vue-sidebar__menu{width:224px;background-color:#24292e;color:#d6d6d6;box-sizing:border-box;height:100%;overflow:hidden;z-index:2004;position:relative}.cly-vue-sidebar__menu--with-banner .__view{padding-bottom:200px}.cly-vue-sidebar__menu-items,.cly-vue-sidebar__submenu-items,.cly-vue-sidebar .el-collapse-item__header{line-height:20px;height:20px;background-color:#24292e;color:#d6d6d6;border:none;font-size:14px;padding:0;font-weight:400;font-family:Inter;padding:6px 12px}.cly-vue-sidebar__menu-items .el-collapse-item__arrow,.cly-vue-sidebar__submenu-items .el-collapse-item__arrow,.cly-vue-sidebar .el-collapse-item__header .el-collapse-item__arrow{margin-right:0px}.cly-vue-sidebar__menu-items:hover,.cly-vue-sidebar__submenu-items:hover,.cly-vue-sidebar .el-collapse-item__header:hover{background-color:#383a3f;color:#fff;border-radius:4px}.cly-vue-sidebar__menu-items--selected,.cly-vue-sidebar__submenu-items--selected,.cly-vue-sidebar .el-collapse-item__header--selected{background-color:#12af51;border-radius:4px;color:#fff}.cly-vue-sidebar__menu-items--selected:hover,.cly-vue-sidebar__submenu-items--selected:hover,.cly-vue-sidebar .el-collapse-item__header--selected:hover{background-color:#12af51;border-radius:4px}.cly-vue-sidebar .el-collapse-item__header.focusing:focus:not(:hover){color:#d6d6d6}.cly-vue-sidebar .el-collapse-item .cly-vue-sidebar__submenu-items{padding-left:32px}.cly-vue-sidebar__el-collapse--selected .el-collapse-item__header{border-radius:4px;background-color:#383a3f;color:#fff}.cly-vue-sidebar .el-collapse-item__content{margin:0;padding:0}.cly-vue-sidebar .el-collapse-item__wrap{border-bottom:1px solid #424243;background-color:#24292e;box-shadow:0px 1px 0px rgba(0,0,0,.4)}.cly-vue-sidebar__header{padding:16px 12px;position:relative}.cly-vue-sidebar__header-search input{background-color:#383a3f;border:none;color:#d6d6d6}.cly-vue-sidebar__header-search input:focus{outline:none;box-shadow:none}.cly-vue-sidebar__header-title{font-size:16px;line-height:24px;font-weight:500;display:inline-block;margin-top:12px}.cly-vue-sidebar__header-button{float:right;top:5px;position:relative}.cly-vue-sidebar__main-menu{overflow:auto;height:calc(100% - 130px)}.cly-vue-sidebar__app-image{width:26px;height:26px;background-size:26px 26px;border-radius:4px;background-position:center;display:inline-block}.cly-vue-sidebar__user-popper{box-sizing:border-box;font-family:Inter;padding:14px 0px;box-shadow:0px 2px 7px rgba(0,0,0,.18815);color:#333c48}.cly-vue-sidebar__language-popper{font-family:Inter;padding:0px;min-width:130px;box-shadow:0px 2px 7px rgba(0,0,0,.18815)}.cly-vue-sidebar__user-details .bu-level{padding:6px 12px}.cly-vue-sidebar__user-links .bu-level{padding:6px;margin:0px 6px}.cly-vue-sidebar__user-links .bu-level:hover{background-color:#f1f3f4;color:#0166d6;border-radius:4px}.cly-vue-sidebar__user-links .bu-level:hover .bu-level-item i{color:#333c48}.cly-vue-sidebar__user-links .bu-level .bu-level-item:first-child{width:15px}.cly-vue-sidebar__user-links .bu-level .bu-level-item i{color:#a7aeb8}.cly-vue-sidebar__user-info{width:140px}.cly-vue-sidebar__user-info p{padding:0;margin:0}.cly-vue-sidebar__user-info p:first-child{font-size:16px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-info p:last-child{margin-top:7px;line-height:17px;font-size:14px;font-weight:400}.cly-vue-sidebar__user-api{width:192px}.cly-vue-sidebar__user-api p{padding:0;margin:0}.cly-vue-sidebar__user-api p:first-child{font-size:12px;line-height:14px;font-weight:500}.cly-vue-sidebar__user-api p:last-child{margin-top:7px;line-height:17px;font-size:12px;font-weight:400}.cly-vue-sidebar__user-image{height:50px;width:50px;border-radius:25px;text-align:center}.cly-vue-sidebar__user-initials{text-transform:uppercase;color:#fff;font-size:16px}.cly-vue-sidebar__user-divider{border:1px solid #ececec;margin-top:5px;position:relative}.cly-vue-sidebar__version{position:absolute;bottom:0;height:48px;display:flex;align-items:center;justify-content:center;width:224px;font-size:10px;background-color:#24292e}.cly-vue-sidebar__version__banner{position:absolute;bottom:12px;left:12px;right:12px;z-index:2001;cursor:default;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:#191c20;border-radius:4px;padding:16px}.cly-vue-sidebar__version__banner .button{width:100%;margin-top:12px}.cly-vue-sidebar__version__banner .text{font-size:14px;color:#fff}.cly-vue-sidebar .cly-icon-sidebar-app{background-image:url("../images/sidebar/default/app.svg");height:24px;width:24px}.cly-vue-sidebar .cly-icon-sidebar-analytics{background-image:url("../images/sidebar/default/analytics-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-analytics:hover{background-image:url("../images/sidebar/hover/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-analytics.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/analytics-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards{background-image:url("../images/sidebar/default/dashboards-icon.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-dashboards:hover{background-image:url("../images/sidebar/hover/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-dashboards.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/dashboards-icon.svg")}.cly-vue-sidebar .cly-icon-sidebar-divider{background-image:url("../images/sidebar/default/divider.svg");width:32px;height:1px}.cly-vue-sidebar .cly-icon-sidebar-management{background-image:url("../images/sidebar/default/management.svg");height:20px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-management:hover{background-image:url("../images/sidebar/hover/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-management.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/management.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager{background-image:url("../images/sidebar/default/report-manager.svg");height:18px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-report-manager:hover{background-image:url("../images/sidebar/hover/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-report-manager.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/report-manager.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center{background-image:url("../images/sidebar/default/help-center.svg");height:25px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-help-center:hover{background-image:url("../images/sidebar/hover/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-help-center.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/help-center.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications{background-image:url("../images/sidebar/default/notifications.svg");height:23px;width:20px}.cly-vue-sidebar .cly-icon-sidebar-notifications:hover{background-image:url("../images/sidebar/hover/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-notifications.cly-vue-sidebar__menu-option--selected{background-image:url("../images/sidebar/selected/notifications.svg")}.cly-vue-sidebar .cly-icon-sidebar-toggle-left{background-image:url("../images/sidebar/default/toggle-left.svg");height:15px;width:11px}.cly-vue-sidebar--floating{position:absolute;left:48px}.notification-toasts{position:absolute;right:24px;bottom:24px;z-index:600000}.notification-toasts__item{margin-top:12px;min-width:288px;max-width:288px}.notification-toasts__item--small{max-width:288px}.notification-toasts__item--large{max-width:611px}.font-weight-bold{font-weight:600 !important}.font-weight-normal{font-weight:400 !important}.font-italic{font-style:italic !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-big{color:#333c48;font-size:16px;font-weight:400;line-height:22px}.text-big.font-weight-bold{font-weight:500 !important}.text-medium{color:#333c48;font-size:14px;font-weight:400;line-height:20px}.text-medium.font-weight-bold{font-weight:500 !important}.text-smallish{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-smallish.font-weight-bold{font-weight:500 !important}.text-small{color:#333c48;font-size:12px;font-weight:400;line-height:18px}.text-small.font-weight-bold{font-weight:500 !important}.text-heading.text-big{line-height:24px;font-weight:500 !important;margin-bottom:16px}.text-heading.text-medium{line-height:20px;font-weight:500 !important;margin-bottom:8px}.text-heading.text-small{line-height:18px;font-weight:500 !important;margin-bottom:4px}.text-smaller{color:#333c48;font-size:10px;font-weight:400;line-height:12px}.text-smaller.font-weight-bold{font-weight:500 !important}.text-smallest{color:#333c48;font-size:10px;font-weight:700;line-height:12px}.text-smallest.font-weight-bold{font-weight:500 !important}.text-button{color:#333c48;font-size:13px;font-weight:400;line-height:16px}.text-button.font-weight-bold{font-weight:500 !important}.cly-trend-up,.cly-trend-down,.cly-trend-neutral{font-size:14px;font-weight:500}.cly-trend-up,.cly-trend-down.negated{color:#12af51}.cly-trend-down,.cly-trend-up.negated{color:#d23f00}.cly-trend-neutral{color:#81868d}.cly-trend-up-icon,.cly-trend-down-icon,.cly-trend-neutral-icon{border-radius:50%;margin-right:4px;display:inline-block;width:17px;height:17px;text-align:center;line-height:17px}.cly-trend-up-icon{background-color:#ebfaee}.cly-trend-down-icon{background-color:#fbece5}.cly-trend-neutral-icon{background-color:#e2e4e8}.cly-trend-up.negated .cly-trend-up-icon{background-color:#fbece5}.cly-trend-down.negated .cly-trend-down-icon{background-color:#ebfaee}.cursor-pointer{cursor:pointer}.icon-size-1{font-size:6px}.icon-size-2{font-size:8px}.icon-size-3{font-size:10px}.icon-size-4{font-size:12px}.icon-size-5{font-size:14px}.icon-size-6{font-size:16px}.text-clickable{cursor:pointer}.color-white{color:#fff !important}.bg-white{background-color:#fff !important}.color-black{color:#000 !important}.bg-black{background-color:#000 !important}.color-warm-gray-100{color:#24292e !important}.bg-warm-gray-100{background-color:#24292e !important}.color-warm-gray-90{color:#24292e !important}.bg-warm-gray-90{background-color:#24292e !important}.color-warm-gray-80{color:#383a3f !important}.bg-warm-gray-80{background-color:#383a3f !important}.color-warm-gray-70{color:#424243 !important}.bg-warm-gray-70{background-color:#424243 !important}.color-warm-gray-60{color:#616165 !important}.bg-warm-gray-60{background-color:#616165 !important}.color-warm-gray-40{color:#d6d6d6 !important}.bg-warm-gray-40{background-color:#d6d6d6 !important}.color-warm-gray-30{color:#ececec !important}.bg-warm-gray-30{background-color:#ececec !important}.color-warm-gray-20{color:#f6f6f6 !important}.bg-warm-gray-20{background-color:#f6f6f6 !important}.color-warm-gray-10{color:#fcfcfc !important}.bg-warm-gray-10{background-color:#fcfcfc !important}.color-cool-gray-100{color:#333c48 !important}.bg-cool-gray-100{background-color:#333c48 !important}.color-cool-gray-50{color:#81868d !important}.bg-cool-gray-50{background-color:#81868d !important}.color-cool-gray-40{color:#a7aeb8 !important}.bg-cool-gray-40{background-color:#a7aeb8 !important}.color-cool-gray-30{color:#cfd6e4 !important}.bg-cool-gray-30{background-color:#cfd6e4 !important}.color-cool-gray-20{color:#e2e4e8 !important}.bg-cool-gray-20{background-color:#e2e4e8 !important}.color-cool-gray-10{color:#f8fafd !important}.bg-cool-gray-10{background-color:#f8fafd !important}.color-cool-gray-05{color:#fbfdfe !important}.bg-cool-gray-05{background-color:#fbfdfe !important}.color-charts-blue{color:#017aff !important}.bg-charts-blue{background-color:#017aff !important}.color-charts-turquoise{color:#39c0c8 !important}.bg-charts-turquoise{background-color:#39c0c8 !important}.color-charts-light-turquoise{color:#ebf9f9 !important}.bg-charts-light-turquoise{background-color:#ebf9f9 !important}.color-charts-amber{color:#f5c900 !important}.bg-charts-amber{background-color:#f5c900 !important}.color-charts-orange{color:#f96300 !important}.bg-charts-orange{background-color:#f96300 !important}.color-charts-light-orange{color:#feefe5 !important}.bg-charts-light-orange{background-color:#feefe5 !important}.color-charts-magenta{color:#f34971 !important}.bg-charts-magenta{background-color:#f34971 !important}.color-charts-light-magenta{color:#feedf1 !important}.bg-charts-light-magenta{background-color:#feedf1 !important}.color-charts-coral{color:#ff9382 !important}.bg-charts-coral{background-color:#ff9382 !important}.color-charts-violet{color:#da6efc !important}.bg-charts-violet{background-color:#da6efc !important}.color-charts-purple{color:#6c47ff !important}.bg-charts-purple{background-color:#6c47ff !important}.color-charts-light-purple{color:#f0edff !important}.bg-charts-light-purple{background-color:#f0edff !important}.color-charts-tan{color:#cdad7a !important}.bg-charts-tan{background-color:#cdad7a !important}.color-charts-olive{color:#aabb5d !important}.bg-charts-olive{background-color:#aabb5d !important}.color-charts-scarlet{color:#f62404 !important}.bg-charts-scarlet{background-color:#f62404 !important}.color-charts-pink{color:#ffb6f5 !important}.bg-charts-pink{background-color:#ffb6f5 !important}.color-yellow-100{color:#e49700 !important}.bg-yellow-100{background-color:#e49700 !important}.color-yellow-70{color:#ffc760 !important}.bg-yellow-70{background-color:#ffc760 !important}.color-yellow-20{color:#fff4ce !important}.bg-yellow-20{background-color:#fff4ce !important}.color-yellow-10{color:#fcf5e5 !important}.bg-yellow-10{background-color:#fcf5e5 !important}.color-blue-100{color:#0166d6 !important}.bg-blue-100{background-color:#0166d6 !important}.color-blue-90{color:#1a75da !important}.bg-blue-90{background-color:#1a75da !important}.color-blue-80{color:#3485de !important}.bg-blue-80{background-color:#3485de !important}.color-blue-70{color:#4d94e2 !important}.bg-blue-70{background-color:#4d94e2 !important}.color-blue-60{color:#67a3e6 !important}.bg-blue-60{background-color:#67a3e6 !important}.color-blue-50{color:#80b3eb !important}.bg-blue-50{background-color:#80b3eb !important}.color-blue-40{color:#99c2ef !important}.bg-blue-40{background-color:#99c2ef !important}.color-blue-30{color:#b3d1f3 !important}.bg-blue-30{background-color:#b3d1f3 !important}.color-blue-20{color:#cce0f7 !important}.bg-blue-20{background-color:#cce0f7 !important}.color-blue-10{color:#e6f0fb !important}.bg-blue-10{background-color:#e6f0fb !important}.color-sky-blue-100{color:#3f9aff !important}.bg-sky-blue-100{background-color:#3f9aff !important}.color-shadow-blue-100{color:#9cbce0 !important}.bg-shadow-blue-100{background-color:#9cbce0 !important}.color-light-blue-100{color:#e1efff !important}.bg-light-blue-100{background-color:#e1efff !important}.color-dark-blue-100{color:#32659d !important}.bg-dark-blue-100{background-color:#32659d !important}.color-teal{color:#00c3ca !important}.bg-teal{background-color:#00c3ca !important}.color-red-100{color:#d23f00 !important}.bg-red-100{background-color:#d23f00 !important}.color-red-10{color:#fbece5 !important}.bg-red-10{background-color:#fbece5 !important}.color-green-100{color:#10a14a !important}.bg-green-100{background-color:#10a14a !important}.color-green-80{color:#12af51 !important}.bg-green-80{background-color:#12af51 !important}.color-green-10{color:#ebfaee !important}.bg-green-10{background-color:#ebfaee !important}.color-primary{color:#0166d6 !important}.bg-primary{background-color:#0166d6 !important}.color-primary-green{color:#12af51 !important}.bg-primary-green{background-color:#12af51 !important}.color-success{color:#67c23a !important}.bg-success{background-color:#67c23a !important}.color-warning{color:#e49700 !important}.bg-warning{background-color:#e49700 !important}.color-danger{color:#d23f00 !important}.bg-danger{background-color:#d23f00 !important}.color-info{color:#909399 !important}.bg-info{background-color:#909399 !important}.color-text-secondary{color:#81868d !important}.bg-text-secondary{background-color:#81868d !important}.color-text-custom-1-active{color:#333c48 !important}.bg-text-custom-1-active{background-color:#333c48 !important}.color-text-placeholder{color:#81868d !important}.bg-text-placeholder{background-color:#81868d !important}.color-text-primary{color:#303133 !important}.bg-text-primary{background-color:#303133 !important}.color-text-regular{color:#333c48 !important}.bg-text-regular{background-color:#333c48 !important}.color-text-custom-1-passive{color:#858a91 !important}.bg-text-custom-1-passive{background-color:#858a91 !important}.color-action-blue{color:#0166d6 !important}.bg-action-blue{background-color:#0166d6 !important}.white-bg{background-color:#fff}.no-bg{background-color:none}.blinker{position:relative;top:-1px;width:6px;height:6px;border-radius:8px;background-color:#2fa732;display:inline-block;vertical-align:middle;margin-right:5px;animation:blinker 1.5s cubic-bezier(0.5, 0, 1, 1) infinite alternate}.has-tooltip{cursor:pointer}.has-ellipsis{word-break:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.has-ellipsis::after{content:"";display:block}.user-activity-table__divider{width:16px;justify-content:space-evenly;color:#a7aeb8}.user-activity-table__data-item-container{flex-basis:75px;margin-right:14px}.user-activity-table-progress-bar-container{width:100%}.user-activity-table-progress-bar-container progress::-webkit-progress-value{background-color:#39c0c8}.session-overview-date-picker-container{margin-bottom:32px}.session-durations-date-picker-container{margin-bottom:32px}.session-frequency-date-picker-container{margin-bottom:32px}.cly-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-top:1px solid #eef2f5;box-shadow:0px 2px 0px #eaecef;padding:24px 24px 0px 24px}.cly-events-breakdown-horizontal-tile__titleoverview{color:#333c48;font-size:14px;font-weight:400;line-height:20px;font-family:Inter}.cly-events-breakdown-horizontal-tile:nth-of-type(3n) .cly-events-breakdown-horizontal-tile__wrapper{border-right:0}.cly-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 24px 0px}.cly-events-breakdown-horizontal-tile__item-title{padding:12px 0px 8px 0px}.cly-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px;font-family:Inter;color:#333c48;letter-spacing:.003em}.cly-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:400;line-height:20px;font-family:Inter;color:#333c48}.cly-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-vue-events-overview-top-events{padding-left:24px;padding-bottom:16.5px}.cly-vue-events-overview-top-events--tooltip{margin-left:5.5px}.cly-vue-events-overview-top-events__description{font-weight:500;line-height:14px}.cly-vue-events-overview-top-events__trend{padding-right:3px}.cly-vue-events-overview-monitor-events__charts .cly-vue-chart__echart{padding:0px}.cly-vue-events-overview-monitor-events__empty{min-height:100px}.cly-vue-events-overview-monitor-events__empty__block{margin:32px auto 32px auto;max-width:586px}.cly-vue-events-overview-monitor-events__empty--image{width:242px;height:242px;background-image:url("../images/dashboard/events-overview-noevents.svg")}.cly-vue-events-overview-monitor-events--text{font-weight:500;font-size:12px;color:#a7aeb8;letter-spacing:.5px;font-family:Inter;line-height:14.52px}.cly-vue-events-overview-monitor-events .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.cly-vue-events-overview-monitor-events--grey{color:#a7aeb8}.cly-vue-events-overview-monitor-events__heading{padding:8px 0px 16px 0px}.cly-vue-events-overview-monitor-events__configure--position{float:right;margin-left:auto}.cly-events-overview-drawer__subheading{font-size:16px;line-height:24px;font-weight:500;font-family:Inter;color:#333c48}.cly-events-overview-drawer--dragicon{margin-right:18px}.cly-events-overview-drawer__event-records{border-radius:6px;width:100%;padding:14px 16px;background-color:#f8fafd}.cly-events-overview-drawer__basis{flex-basis:0}.cly-events-overview-drawer__dropdown{min-width:230px;width:100%}.cly-events-overview-drawer__close-icon{line-height:1;font-size:24px}.cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:1px solid #ececec;border-bottom:1px solid #ececec;padding:24px 24px 0 24px}.cly-monitor-events-breakdown-horizontal-tile__title{font-size:12px;font-weight:400;line-height:20px;padding-bottom:8px}.cly-monitor-events-breakdown-horizontal-tile__titleoverview{font-size:12px;font-weight:400;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__eventproperty{font-size:12px;font-weight:400;line-height:20px;color:#81868d}.cly-monitor-events-breakdown-horizontal-tile:nth-of-type(2n) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-right:none}.cly-monitor-events-breakdown-horizontal-tile:nth-child(1) .cly-monitor-events-breakdown-horizontal-tile__wrapper,.cly-monitor-events-breakdown-horizontal-tile:nth-child(2) .cly-monitor-events-breakdown-horizontal-tile__wrapper{border-top:1px solid #ececec}.cly-monitor-events-breakdown-horizontal-tile__values-list{align-items:center}.cly-monitor-events-breakdown-horizontal-tile__item{height:33.3333333%;padding:0px 0px 16px 0px}.cly-monitor-events-breakdown-horizontal-tile__item-title{padding-top:4px}.cly-monitor-events-breakdown-horizontal-tile__value{font-weight:500;font-size:20px;line-height:30px}.cly-monitor-events-breakdown-horizontal-tile__overviewvalue{font-weight:500;font-size:24px;line-height:32px}.cly-monitor-events-breakdown-horizontal-tile__percentage{font-size:14px;font-weight:300;line-height:20px}.cly-monitor-events-breakdown-horizontal-tile__trend{font-weight:500;line-height:14px}.cly-monitor-events-breakdown-horizontal-tile__arrow{padding-right:3px}.cly-monitor-events-breakdown-horizontal-tile__overview-name{z-index:1}.cly-monitor-events-breakdown-horizontal-tile__width-50{width:50%}.cly-vue-events-all__alerts a{text-decoration:underline}.cly-vue-events-all{font-size:24px;line-height:32px;font-weight:500;padding-top:6px;letter-spacing:.003em;font-family:Inter;color:#333c48}.cly-vue-events-all__subheading{font-size:14px;line-height:20px;color:#333c48}.cly-vue-events-all--padding{padding-top:32px}.cly-vue-events-all--margin{margin-right:32px}.cly-vue-events-group{color:#fff;background-color:#a7aeb8;font-size:10px;line-height:10px;font-weight:500;letter-spacing:.0042em;vertical-align:middle;padding:3px 4px;border-radius:4px}.cly-vue-events-all-placeholder-text{color:#81868d;font-size:12px;line-height:14.52px;font-weight:500;letter-spacing:.005em;white-space:nowrap}.cly-vue-events-all-date-picker{margin-right:26px}.cly-vue-events-all-tooltip{margin-left:10px}.cly-vue-overview-events-header{padding-right:9.5px;letter-spacing:.003em}.cly-vue-events-header{padding:8px 24px 24px 24px;letter-spacing:.003em;font-family:Inter;line-height:32px;border-bottom:1px solid #ececec;background-color:#fff}.cly-vue-events-header__subheading--widget{padding-right:5.33px;color:#81868d}.cly-vue-events-header__subheading--text{font-family:Inter;line-height:20px;font-size:14px;color:#81868d}.cly-vue-events-header--tooltip{padding-left:9.5px}.cly-vue-events-overview-subheadings{padding-right:9.5px;letter-spacing:.003em;font-family:Inter}.cly-vue-events-overview-subheadings--tooltip{padding-top:3px}.cly-vue-events-overview-subheadings--font{font-family:Inter}.cly-vue-listbox.is-expandable{z-index:2001}.cly-vue-events-omitted-segments__item{color:#81868d;font-size:14px;font-weight:500;line-height:16px;padding:8px;margin:8px}.cly-vue-events-omitted-segments__title{color:#a7aeb8;font-size:13px;font-weight:500;letter-spacing:.5px;text-transform:uppercase;line-height:16px;padding:8px;margin:8px}.technology-analytics-wrapper .allPlatformVersions{border-left:1px solid #ececec;height:264px;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions{height:264px;position:relative;border-left:1px solid #ececec;border-top:1px solid #ececec;border-bottom:1px solid #ececec;background-color:#fff}.technology-analytics-wrapper .emptyVersions div{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48;position:absolute;top:50%;text-align:center;width:100%;margin-top:-10px}.technology-analytics-wrapper .version-graph-title{font-family:Inter;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.technology-analytics-wrapper .version-graph-title .divider{color:#a7aeb8}.technology-analytics-wrapper .version-graph-title div:first-child{text-align:left}.technology-analytics-wrapper .version-graph-title div:nth-child(2){text-align:right}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper .version-graph-title .bu-column{padding:0px}.technology-analytics-wrapper .cly-vue-metric-card__wrapper .bu-is-flex-direction-column{margin-right:-1.5rem}.technology-analytics-wrapper .selector_wrapper{position:relative;top:-5px;margin-left:8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .metricCardsWrapper{height:115px}.technology-analytics-wrapper .metricCardsWrapper .emptyCard{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .emptyCard div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .platformVersionsWrapper .emptyCard{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper .platformVersionsWrapper{height:309px;padding-bottom:20px}.technology-analytics-wrapper .metricCardsWrapper .bu-columns{flex-wrap:nowrap}.technology-analytics-wrapper .metricCardsWrapper .__view{width:auto !important}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-cards{border-bottom:none}.technology-analytics-wrapper .metricCardsWrapper .cly-vue-metric-card{background-color:#fff;border-top:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__items{height:115px}.technology-analytics-wrapper__versions{height:291px;padding-bottom:20px}.technology-analytics-wrapper__empty-card{min-height:107px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;top:50%;text-align:center;border-bottom:1px solid #ececec}.technology-analytics-wrapper__empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper__versions-empty-card{min-height:250px;border-left:1px solid #ececec;width:100%;position:relative;background-color:#fff;border-top:1px solid #ececec;border-right:1px solid #ececec;border-bottom:1px solid #ececec}.technology-analytics-wrapper__versions-empty-card div{position:absolute;top:50%;text-align:center;width:100%;line-height:20px;margin-top:-10px}.technology-analytics-wrapper .app-version-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-version-date-picker-container+.cly-vue-notification__alert-box{margin-top:-8px}.technology-analytics-wrapper .app-resolution-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .app-carrier-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .devices-date-picker-container{margin-bottom:32px}.technology-analytics-wrapper .version-graph-block .version-graph-title{margin:0px;padding-bottom:4px}.technology-analytics-wrapper__metric-cards .bu-column:last-child{margin-right:unset !important}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart__echart{padding-right:0px}.technology-analytics-wrapper .technology-pie-graphs .bu-level .bu-level-right{padding-right:5px}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .cly-vue-chart-legend__secondary{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .bu-column:first-child .cly-vue-chart__echart .bu-level .bu-level-right{border-right:1px solid #ececec}.technology-analytics-wrapper .technology-pie-graphs .cly-vue-chart-legend__right .cly-vue-chart-legend__secondary .__vuescroll .__rail-is-vertical{right:5px !important}.version-graph-block:last-child{margin-bottom:12px}.technology-dashboard-widget>.bu-column:nth-child(odd)>.cly-vue-section{padding-left:4px}.technology-dashboard-widget>.bu-column:nth-child(even)>.cly-vue-section{padding-right:12px}.routename-analytics-geo .geo-date-picker-container{margin-bottom:32px}.routename-analytics-geo .radio-column{width:256px}.leaflet-noclick-map .leaflet-interactive{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.leaflet-control-zoom{user-select:none;border-color:#dcdcdc !important}.leaflet-control-zoom a{color:#333c48;border-bottom-color:#dcdcdc}.geo-analytics-data .cly-vue-button{padding:6px 10px;border-radius:4px}.user-management-drawer-content__pp-options{height:fit-content;align-self:center;margin-left:15px;box-shadow:none}.user-management-drawer-content__pp-options .el-button{box-shadow:none;border:none}.user-management-drawer-content__user-pp{width:100px;height:100px;border-radius:50%}.user-management-drawer-content #user-drawer-dropzone{background-color:#f8fafd;border-radius:6px}.user-management-drawer-content__custom-options{box-shadow:none}.user-management-drawer-content__custom-options div button{box-shadow:none;padding:0px;background:none;border:none}.user-management-drawer-content__under-input-text{text-decoration:underline;cursor:pointer}.user-management-drawer-content__top-section{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__bottom-section{display:flex;margin-top:28px;flex-direction:column;justify-content:space-between}.user-management-drawer-content__input-wrapper{margin-top:10px}.user-management-drawer-content__label{display:flex;justify-content:space-between;flex-direction:column}.user-management-drawer-content__label--text-secondary{color:#81868d}.user-management-drawer-content__label-text{font-style:normal;font-weight:normal;font-size:13px;line-height:16px;color:#333c48}.user-management-drawer-content__help-text{font-family:Inter;font-style:normal;font-weight:normal;font-size:12px;line-height:16px;color:#81868d}.user-management-drawer-content__help-menu-icon{font-family:Inter;font-style:normal;font-weight:normal;font-size:16px;line-height:16px;color:#81868d}.user-management-drawer-content__light-button{background-color:#ddedff;color:#0166d6;font-weight:bold;padding:10px 20px;width:fit-content;margin-top:10px;font-size:13px;border-radius:5px}.user-management-drawer-content__profile-picture-area{margin-top:9px;margin-left:10px}.user-management-drawer-content__profile-picture-area__upload-section{border:1px dashed #81868d;padding:30px;border-radius:8px;display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content__profile-picture-area__upload-section__img-box{background-color:#e2e4e8;height:100px;width:100px;border-radius:50%}.user-management-drawer-content__profile-picture-area__upload-section__description-box{font-size:12px;text-align:center;width:80%}.user-management-drawer-content__profile-picture-area__upload-section__description-box--bold{font-weight:500;color:#0166d6}.user-management-drawer-content__profile-picture-area__upload-section__description-box--gray{color:gray}.user-management-drawer-content__drawer-sub-section{border-radius:6px;background-color:#f8fafd;margin-top:10px;margin-bottom:24px}.user-management-drawer-content__drawer-sub-title{display:flex;flex-direction:row;justify-content:space-between;padding:5px 0px;font-weight:500;font-size:16px}.user-management-drawer-content__permission-table-header{display:flex;justify-content:space-between;margin-top:10px;font-size:12px;border-bottom:1px solid #ebebeb;padding-bottom:10px}.user-management-drawer-content__feature-search{width:calc(40% - 15px);margin-left:10px}.user-management-drawer-content__feature-search .el-input__inner{background-color:#fff !important}.user-management-drawer-content__permission-type-cols{width:75%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-type{text-align:center;font-size:11px;width:25%;margin:auto}.user-management-drawer-content__permission-type .check-label{font-size:15px}.user-management-drawer-content__permission-type .check-text{margin-top:2px}.user-management-drawer-content__permission-type .el-checkbox__label{font-weight:medium !important}.user-management-drawer-content__permission-table-content{height:300px;overflow-y:scroll;padding:10px 0px}.user-management-drawer-content__permission-row{display:flex;flex-direction:row;height:30px;justify-content:center;align-items:center}.user-management-drawer-content__feature-name{width:calc(35% - 15px);text-align:left;padding-left:15px;display:flex;justify-content:flex-start;align-items:center;font-style:normal;font-weight:normal;font-size:14px;line-height:20px;color:#333c48}.user-management-drawer-content__feature-permissions{width:65%;display:flex;justify-content:space-evenly}.user-management-drawer-content__permission-box{text-align:center;width:35%}.user-management-drawer-content__section-title{display:flex;flex-direction:row;justify-content:space-between}.user-management-drawer-content__section-header{font-family:Inter;font-style:normal;font-weight:500;font-size:12px;line-height:15px;letter-spacing:.5px;text-transform:uppercase;color:#333c48}.user-management-drawer-content__role-section .check-text{margin-top:4px !important}.user-management-drawer-content__role-section .el-checkbox__label{font-weight:normal !important}.user-management-drawer-content__app-selector{width:100%}.user-management-drawer-content__add-permission-set{background-color:#e1efff;border-radius:4px;cursor:pointer;padding:9.5px 12px;font-weight:500;font-size:13px;line-height:13px;color:#0166d6;width:fit-content}.user-management-drawer-content__group-selector{width:100%}.user-management-drawer-content .check-label{color:#0166d6 !important}.user-management-drawer-content .el-tag--info{background-color:#81868d;color:#fff}.user-management-drawer-content .el-icon-close{background-color:#fff !important}.user-management-drawer-content .el-icon-close:hover{color:#81868d !important}.user-management-drawer-content .dropzone-custom-content{display:flex;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image>div{height:100px;width:100px;border-radius:50%}.user-management-drawer-content .dz-image-preview{display:flex !important;flex-direction:column;justify-content:center;align-items:center}.user-management-drawer-content .dz-image-preview .dz-remove{font-size:12px;font-weight:bold}.user-management-drawer-content .dz-image-preview .dz-image{display:block !important}.manage-users-table{margin:0px}.manage-users-table__groups{display:inline-flex;color:#32659d}.manage-users-table__groups a:hover{color:#1a75da;text-decoration:underline}.manage-users-table__groups-label{margin:0px 2px}.user-management-filter-form .select-full-width{width:100%}.user-management-view .el-tabs--button>.el-tabs__header{padding:24px 24px 0px 24px}.user-management-view .manage-users-action-btn{background-color:#12af51}#main_home_view .el-loading-parent--relative{min-height:100px}#main_home_view .bu-level-left:first-child>h2{font-size:20px !important}#main_home_view .cly-back-link i{color:#333c48}#main_home_view .componentBlock>div{padding-top:16px;padding-bottom:20px}.app-management-view h2{letter-spacing:.3px}.app-management-view h3{letter-spacing:.3px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container{margin-top:12px}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-drawer__steps-wrapper .cly-vue-drawer__steps-container .cly-vue-form-step__section{padding-left:24px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .cly-vue-section__content{border:1px solid #ececec;border-radius:4px}.app-management-view .cly-vue-section__content .el-collapse{border:none}.app-management-view .cly-vue-section__content .app-section{margin-left:12px;margin-right:4px}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section{margin-bottom:24px !important;margin-left:0 !important;margin-right:0 !important;color:#333c48;display:flex;justify-content:space-between}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section .cly-vue-form-field__inner .el-form-item .el-form-item__content{line-height:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p{font-size:14px;line-height:14px;margin:0}.app-management-view .cly-vue-section__content .app-section .cly-vue-form-step__section div p+p{font-size:12px;line-height:16px;font-weight:400;margin-top:4px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns{padding:0 !important;margin:0}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-4{width:50%;margin-right:48px}.app-management-view .cly-vue-section__content .app-section span div .bu-columns .bu-is-8{width:37.33%}.app-management-view .account-settings-avatar-box{padding:24px;overflow:auto;flex:auto}.app-management-view .account-settings-avatar-box .el-upload{display:block}.app-management-view .feedback-settings__upload .el-upload{display:block}.app-management-view .feedback-settings__upload img{width:165px;height:50px;margin-left:24px;cursor:default}.app-management-view .feedback-settings__colorpicker .cly-vue-color-picker__picker{overflow:auto}.app-management-view .feedback-settings__button:active,.app-management-view .feedback-settings__button:focus,.app-management-view .feedback-settings__button:hover{background-color:unset !important;border-color:unset !important}.app-management-view .app-management-list{max-height:681px;max-width:223px}.app-management-view .app-management-list .cly-vue-listbox__item span{margin-left:8px;position:relative;top:-8px}.app-management-view .app-management-details .bu-columns{margin:0 !important;padding:0 !important;border-bottom:1px solid #ececec}.app-management-view .app-management-details .bu-columns:last-child{border-bottom:none;margin-bottom:-20px}.app-management-view .app-management-details .el-collapse-item__header.is-active{border-bottom:1px solid #ececec}.app-management-view .app-management-details .el-collapse-item__content{padding-bottom:0}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section{padding-left:48px !important;padding-right:24px !important;padding-top:12px !important;padding-bottom:12px !important}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content{display:flex !important;justify-content:right !important;float:right;line-height:inherit}.app-management-view .app-management-details .el-collapse-item__content .cly-vue-form-step__section div:nth-child(2) .el-form-item__content>div{max-width:232px}.app-management-view .app-management-details .el-collapse-item__arrow{color:#81868d}.app-management-view .app-management-details .el-collapse-item__header{color:#333c48;padding-left:24px !important;text-transform:uppercase}.app-management-view .app-management-details .el-collapse-item__wrap{overflow:unset}.app-management-view .box-card{background-color:#e6f0fb;border:1px solid #0166d6;box-sizing:border-box;box-shadow:0px 1px 0px #ececec;border-radius:4px}.app-management-view .box-card .el-card__body{padding:24px}.app-management-view .box-card .el-card__body p a{color:#0166d6}.app-management-view .box-card .el-card__body p:nth-of-type(1){line-height:24px;font-weight:500;font-size:16px}.app-management-view .box-card .el-card__body p{font-size:14px}.el-dropdown-menu__item--divided__fix-broken{border:none}.el-dropdown-menu__item--divided__fix-broken::before{height:0px}.add-border{margin:0 8px;padding:0;border-top:1px solid #ececec}.add-border>a{display:none}@media(max-width: 2133px){.app-section span div div:nth-last-child(1) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(1) .cly-vue-form-step__section .el-input{width:268%}}@media(max-width: 1280px){.app-section span div div:nth-last-child(2) .cly-vue-form-step__section{display:block !important}.app-section span div div:nth-last-child(2) .cly-vue-form-step__section .el-input{width:177%}}.report-manager-filter-form .select-full-width{width:100%}.token-manager-drawer__choice .el-radio.is-autosized{flex:1 1 0;min-width:0}.token-manager-drawer__choice .el-radio__label{white-space:normal}.token-manager-drawer__permission-header,.token-manager-drawer__permission-row{display:flex;flex-direction:row;align-items:center}.token-manager-drawer__permission-header{border-bottom:1px solid #ebebeb;padding-bottom:10px;margin-bottom:10px}.token-manager-drawer__permission-row{height:30px}.token-manager-drawer__feature-name{width:35%;display:flex;align-items:center;justify-content:flex-start}.token-manager-drawer__feature-permissions{width:65%;display:flex}.token-manager-drawer__permission-box{flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:center}.token-manager-drawer__permission-box .el-checkbox{margin-right:0}.token-manager-drawer__permission-header .token-manager-drawer__permission-box .el-checkbox{display:flex;flex-direction:column-reverse;align-items:center}.token-manager-drawer__permission-header .token-manager-drawer__permission-box .el-checkbox__label{font-size:11px;padding-left:0;margin-bottom:4px;line-height:1}.header{display:flex;flex-direction:column;gap:20px}.setup-logo{margin-top:38px;margin-left:72px;width:165px;height:50px;background-image:url("../images/pre-login/countly-logo-dark.svg");background-repeat:no-repeat;background-size:contain;position:fixed;left:0px;top:0px}.centered-content{min-height:100vh;display:flex;align-items:center;justify-content:center;margin-bottom:-35px}.setup-byline{color:#81868d;margin-top:12px;font-size:14px}.setup-form{width:520px}.setup-radio-grid{display:grid;grid-template-columns:1fr 1fr 1fr;column-gap:10px;row-gap:10px}.setup-radio .el-radio.is-checked{background-color:#e1efff}.setup-radio .el-radio{margin-left:0 !important}.setup-radio .is-autosized.is-bordered .el-radio__input{display:none !important}.setup-radio .el-radio__label{padding-left:0}.setup-radio-item{display:flex;align-items:center;font-size:24px}.setup-radio-icon-bg{width:40px;height:40px;display:flex;align-items:center;justify-content:center;background-color:#e1efff;border-radius:100%}.is-checked .setup-radio-icon-bg{background-color:#0166d6;color:#fff}.setup-radio-icon{background-image:url("../images/dashboard/onboarding/box.svg");background-position:center;background-repeat:no-repeat;width:100%;height:100%}.setup-radio-icon--app-type-mobile{background-image:url("../images/dashboard/onboarding/app-type-mobile.svg")}.setup-radio-icon--app-type-web{background-image:url("../images/dashboard/onboarding/app-type-web.svg")}.setup-radio-icon--app-type-desktop{background-image:url("../images/dashboard/onboarding/app-type-desktop.svg")}.is-checked .setup-radio-icon{filter:brightness(10)}.setup-video-container{max-width:800px}.consent-form{width:700px}.consent-blurb{color:#81868d;font-size:14px}.consent-question{font-size:14px}.initial-populator{width:800px}.quickstart-item{display:flex;align-items:flex-start}.quickstart-item-desc{color:#81868d;text-align:left;word-break:break-word}.quickstart-link,.quickstart-link:visited{color:#0166d6}.quickstart-link:hover{color:#333c48}.preset-list{display:inline-block;position:absolute;left:170px;border:1px solid #a7aeb8;border-radius:4px;background-color:#fff}.preset-list__header{z-index:1997;position:relative;padding:8px 16px}.preset-list__header::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(180deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);left:0;opacity:.12;top:100%}.preset-list__header .el-button--primary{border:unset;font-weight:500;box-shadow:none}.preset-list__header .el-button--primary:hover{background-color:#cce0f7;color:#0166d6}.preset-list__header .el-button--text{font-weight:500;font-size:14px}.preset-list__body{background-color:#f9f9f9;height:400px;border-radius:4px}.preset-list__body::after{content:"";position:absolute;width:100%;height:16px;background:linear-gradient(0deg, #333c48 0%, rgba(51, 60, 72, 0.0001) 100%);opacity:.12;left:0;bottom:0}.preset-list__body .preset{display:flex;flex-direction:column;justify-content:center;width:300px;background-color:#fff;border:1px solid #ececec;border-radius:4px;padding:12px;margin-bottom:8px;cursor:pointer}.preset-list__body .preset:first-child{margin-top:16px}.preset-list__body .preset:last-child{margin-bottom:16px}.preset-list__body .preset:hover{border:1px solid #0166d6;background-color:#e1efff}.preset-list__body .preset--selected{border:1px solid #0166d6}.preset-list .sortable-chosen{background-color:#e1efff !important}#preset-drawer .el-radio__label{display:flex;align-items:center}#preset-drawer .el-radio__input{display:flex}#preset-drawer .el-checkbox{font-weight:400}#preset-drawer .el-checkbox__label{padding-left:8px;color:#333c48}#preset-drawer .el-checkbox:hover__label{color:#333c48}/*# sourceMappingURL=manifest.css.map */ From 9062ee6f80a1222e3a455406ce257376710f838f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 22:08:22 +0300 Subject: [PATCH 8/9] test(core): give the probed handlers the parameters they need to reply The granted case for update on alerts called /i/alert/status with no parameters of its own. The handler parses qstring.status, and where that parse is not guarded it throws inside the callback and never replies, so the request hung and the case timed out after 50s rather than failing on an authorization outcome. Each probed endpoint is now given whatever its handler needs to answer, which is what a real caller would send. The assertion is unchanged and still about authorization only. Found by CI on the 24.05 backport, where that parse is unguarded; master guards it with a try/catch and answered 500, so the same case passed there. Co-Authored-By: Claude Opus 4.8 --- test/2.api/16.token.manager.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/2.api/16.token.manager.js b/test/2.api/16.token.manager.js index 2f5800a85c5..949ecdf45d3 100644 --- a/test/2.api/16.token.manager.js +++ b/test/2.api/16.token.manager.js @@ -835,6 +835,14 @@ describe('Testing token manager', function() { }; var created = []; + // Some handlers only answer once their own parameters are present - /i/alert/status parses + // qstring.status and, on branches where that parse is not guarded, never replies without it. + // Authorization is what these cases are about, so each endpoint is given whatever it needs + // to reply, and the assertion is on the authorization outcome rather than the reply itself. + var handlerQuery = { + '/i/alert/status': '&status=' + encodeURIComponent('{}') + }; + var grant = function(spec) { var permission = {_: {a: [], u: [spec.apps]}, c: {}, r: {}, u: {}, d: {}}; spec.apps.forEach(function(appId) { @@ -868,7 +876,7 @@ describe('Testing token manager', function() { // which would let a test pass without ever reaching a validator. var expectAllowed = function(path, appId, token, done, extraQuery) { request - .get(path + '?app_id=' + appId + '&auth_token=' + token + (extraQuery || '')) + .get(path + '?app_id=' + appId + '&auth_token=' + token + (handlerQuery[path] || '') + (extraQuery || '')) .end(function(err, res) { if (err) { return done(err); @@ -888,7 +896,7 @@ describe('Testing token manager', function() { var expectRefused = function(path, appId, token, done, extraQuery) { request - .get(path + '?app_id=' + appId + '&auth_token=' + token + (extraQuery || '')) + .get(path + '?app_id=' + appId + '&auth_token=' + token + (handlerQuery[path] || '') + (extraQuery || '')) .expect(401) .end(function(err, res) { if (err) { From db4e2c021179d31c16bae6419c0afd25584ad170 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 22:26:51 +0300 Subject: [PATCH 9/9] test(core): remove the member created for the owner-permission case deterministically That case needs a member of its own, and the cleanup suite later asserts that exactly one user remains, so a member left behind fails a test in a different file. The cleanup went through /i/users/delete and ignored its result, which made the whole thing conditional on that call succeeding. The member and any tokens they own are now removed directly, which is what the rest of this file already does for tokens. Found by CI on master: "Verify user deletion should return one user" failed while the token cases themselves passed. Co-Authored-By: Claude Opus 4.8 --- test/2.api/16.token.manager.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/2.api/16.token.manager.js b/test/2.api/16.token.manager.js index 949ecdf45d3..e354d6fa54c 100644 --- a/test/2.api/16.token.manager.js +++ b/test/2.api/16.token.manager.js @@ -1211,13 +1211,14 @@ describe('Testing token manager', function() { }); }); + //removed directly rather than through /i/users/delete, whose result this block would have to + //ignore: a member left behind here is counted by the later cleanup suite, which asserts that + //exactly one user remains it('cleanup: remove the token and the member', function(done) { - testUtils.db.collection("auth_tokens").remove({_id: memberToken + ""}, function() { - request - .get('/i/users/delete?api_key=' + API_KEY_ADMIN + "&args=" + JSON.stringify({user_ids: [memberId]})) - .end(function() { - done(); - }); + testUtils.db.collection("auth_tokens").remove({owner: memberId + ""}, function() { + testUtils.db.collection("members").remove({username: username}, function() { + done(); + }); }); }); });