remote-calibrator 0.3.0-beta.0 → 0.3.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.eslintrc.js +1 -1
  2. package/.husky/pre-commit +1 -1
  3. package/.prettierignore +4 -0
  4. package/CHANGELOG.md +38 -1
  5. package/README.md +33 -13
  6. package/homepage/example.css +4 -0
  7. package/homepage/example.js +1 -0
  8. package/homepage/index.html +26 -0
  9. package/i18n/.eslintrc.js +12 -0
  10. package/i18n/fetch-languages-sheets.js +62 -0
  11. package/lib/RemoteCalibrator.min.js +1 -1
  12. package/lib/RemoteCalibrator.min.js.LICENSE.txt +1 -1
  13. package/lib/RemoteCalibrator.min.js.map +1 -1
  14. package/package.json +12 -8
  15. package/src/components/buttons.js +4 -3
  16. package/src/components/language.js +31 -0
  17. package/src/components/onCanvas.js +4 -8
  18. package/src/components/swalOptions.js +25 -23
  19. package/src/{helpers.js → components/utils.js} +8 -2
  20. package/src/{video.js → components/video.js} +23 -4
  21. package/src/const.js +23 -3
  22. package/src/core.js +106 -6
  23. package/src/css/distance.scss +12 -7
  24. package/src/css/main.css +65 -10
  25. package/src/css/panel.scss +1 -1
  26. package/src/css/screenSize.css +28 -14
  27. package/src/debug.js +2 -0
  28. package/src/displaySize.js +1 -1
  29. package/src/distance/distance.js +20 -13
  30. package/src/distance/distanceTrack.js +9 -8
  31. package/src/gaze/gaze.js +22 -20
  32. package/src/gaze/gazeAccuracy.js +3 -4
  33. package/src/gaze/gazeCalibration.js +30 -22
  34. package/src/gaze/gazeTracker.js +4 -2
  35. package/src/i18n.js +6 -0
  36. package/src/index.js +1 -1
  37. package/src/interpupillaryDistance.js +34 -18
  38. package/src/{panel/panel.js → panel.js} +57 -21
  39. package/src/screenSize.js +72 -35
  40. package/src/constants.js +0 -11
  41. package/src/text.json +0 -34
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remote-calibrator",
3
- "version": "0.3.0-beta.0",
3
+ "version": "0.3.0-beta.4",
4
4
  "description": "A toolbox for remote testing calibration and tracking.",
5
5
  "main": "lib/RemoteCalibrator.min.js",
6
6
  "directories": {
@@ -15,7 +15,8 @@
15
15
  "build": "webpack --env=production",
16
16
  "serve": "node server.js",
17
17
  "prepare": "husky install",
18
- "netlify": "cp -r ./lib ./homepage"
18
+ "netlify": "cp -r ./lib ./homepage",
19
+ "phrases": "node i18n/fetch-languages-sheets.js && git add src/i18n.js"
19
20
  },
20
21
  "repository": {
21
22
  "type": "git",
@@ -28,17 +29,19 @@
28
29
  },
29
30
  "homepage": "https://github.com/EasyEyes/remote-calibrator#readme",
30
31
  "devDependencies": {
31
- "@babel/core": "^7.15.5",
32
+ "@babel/core": "^7.15.8",
32
33
  "autoprefixer": "^10.3.7",
33
34
  "babel-loader": "^8.2.2",
34
35
  "clean-webpack-plugin": "^4.0.0",
35
- "css-loader": "^6.3.0",
36
+ "css-loader": "^6.4.0",
36
37
  "cssnano": "^5.0.8",
37
38
  "eslint": "^7.32.0",
38
39
  "eslint-webpack-plugin": "^3.0.1",
39
40
  "express": "^4.17.1",
41
+ "googleapis": "^88.2.0",
40
42
  "husky": "^7.0.2",
41
- "lint-staged": "^11.2.0",
43
+ "lint-staged": "^11.2.3",
44
+ "nodemon": "^2.0.13",
42
45
  "postcss-loader": "^6.1.1",
43
46
  "prettier": "^2.4.1",
44
47
  "sass": "^1.42.1",
@@ -47,9 +50,10 @@
47
50
  "svg-inline-loader": "^0.8.2",
48
51
  "terser-webpack-plugin": "^5.2.4",
49
52
  "url-loader": "^4.1.1",
50
- "webpack": "^5.56.1",
51
- "webpack-cli": "^4.8.0",
52
- "webpack-modules": "^1.0.0"
53
+ "webpack": "^5.58.1",
54
+ "webpack-cli": "^4.9.0",
55
+ "webpack-modules": "^1.0.0",
56
+ "xlsx": "^0.17.2"
53
57
  },
54
58
  "lint-staged": {
55
59
  "*.js": "eslint --cache --fix",
@@ -1,6 +1,7 @@
1
+ import { phrases } from '../i18n'
1
2
  import '../css/buttons.scss'
2
3
 
3
- export const addButtons = (parent, { go, cancel }, showCancelButton) => {
4
+ export const addButtons = (RCL, parent, { go, cancel }, showCancelButton) => {
4
5
  const buttons = document.createElement('div')
5
6
  buttons.className = 'rc-buttons'
6
7
  buttons.id = 'rc-buttons'
@@ -11,7 +12,7 @@ export const addButtons = (parent, { go, cancel }, showCancelButton) => {
11
12
  goButton = document.createElement('button')
12
13
  goButton.className = 'rc-button rc-go-button'
13
14
  goButton.onclick = go
14
- goButton.innerHTML = 'OK'
15
+ goButton.innerHTML = phrases.RC_ok[RCL]
15
16
  buttons.appendChild(goButton)
16
17
  }
17
18
 
@@ -19,7 +20,7 @@ export const addButtons = (parent, { go, cancel }, showCancelButton) => {
19
20
  cancelButton = document.createElement('button')
20
21
  cancelButton.className = 'rc-button rc-cancel-button'
21
22
  cancelButton.onclick = cancel
22
- cancelButton.innerHTML = 'Cancel'
23
+ cancelButton.innerHTML = phrases.RC_cancel[RCL]
23
24
  buttons.appendChild(cancelButton)
24
25
  }
25
26
 
@@ -0,0 +1,31 @@
1
+ import { phrases } from '../i18n'
2
+
3
+ export function looseSetLanguage(lang) {
4
+ const originalKeys = Object.keys(phrases.EE_languageNameNative)
5
+ if (originalKeys.includes(lang)) return constructLangData(lang)
6
+
7
+ const shortKeys = []
8
+ originalKeys.forEach(l => {
9
+ shortKeys.push(l.split('-')[0])
10
+ })
11
+
12
+ const shortLang = lang.split('-')[0].toLowerCase()
13
+
14
+ if (shortKeys.includes(shortLang))
15
+ return constructLangData(originalKeys[shortKeys.indexOf(shortLang)])
16
+
17
+ return constructLangData('en-US')
18
+ }
19
+
20
+ function constructLangData(lang) {
21
+ return {
22
+ value: {
23
+ language: lang,
24
+ languageNameEnglish: phrases.EE_languageNameEnglish[lang],
25
+ languageNameNative: phrases.EE_languageNameNative[lang],
26
+ languageDirection: phrases.EE_languageDirection[lang],
27
+ languagePhraseSource: phrases.EE_phraseSource[lang],
28
+ },
29
+ timestamp: new Date(),
30
+ }
31
+ }
@@ -1,8 +1,6 @@
1
1
  // Draw cross and circle on the canvas
2
2
  // For blind spot test and more
3
3
 
4
- import { colorDarkRed } from '../constants'
5
-
6
4
  // CROSS
7
5
  const crossLW = 32 // Width of a line of the middle cross
8
6
  const crossLH = 3
@@ -25,18 +23,16 @@ export function _getCircleBounds(side, crossX, cW) {
25
23
  : [circleR >> 1, crossX - (crossLW + circleR) / 2]
26
24
  }
27
25
 
28
- export function _circle(ctx, x, y, frameCount, sparkle = true) {
26
+ export function _circle(RC, ctx, x, y, frameCount, sparkle = true) {
29
27
  ctx.beginPath()
30
28
  ctx.arc(x, y, circleR >> 1, 0, Math.PI * 2)
31
29
  ctx.closePath()
32
30
 
33
- if (!sparkle) ctx.fillStyle = colorDarkRed
31
+ if (!sparkle) ctx.fillStyle = RC._CONST.COLOR.DARK_RED
34
32
  else {
35
- // 10 Hz
36
- if (frameCount % 6 < 3) ctx.fillStyle = colorDarkRed
37
- else if (frameCount % 6 >= 3) ctx.fillStyle = '#fff'
33
+ if (frameCount % 4 < 2) ctx.fillStyle = RC._CONST.COLOR.DARK_RED
34
+ else ctx.fillStyle = '#fff'
38
35
  }
39
36
 
40
- // ctx.fillStyle = colorDarkRed // Red fill
41
37
  ctx.fill()
42
38
  }
@@ -1,25 +1,27 @@
1
- import { colorIconOrange } from '../constants'
1
+ import { phrases } from '../i18n'
2
2
 
3
- export const swalInfoOptions = {
4
- icon: 'info',
5
- allowEscapeKey: false,
6
- allowEnterKey: false,
7
- allowOutsideClick: false,
8
- showConfirmButton: true,
9
- confirmButtonText: 'OK',
10
- showClass: {
11
- popup: 'animate__animated animate__fadeInUp',
12
- // backdrop: 'animate__animated animate__fadeIn',
13
- },
14
- hideClass: {
15
- popup: 'animate__animated animate__fadeOutDown',
16
- // backdrop: 'animate__animated animate__fadeOut',
17
- },
18
- iconColor: colorIconOrange,
19
- confirmButtonColor: '#aaa',
20
- customClass: {
21
- icon: 'my__swal2__icon',
22
- title: 'my__swal2__title',
23
- htmlContainer: 'my__swal2__html',
24
- },
3
+ export const swalInfoOptions = RC => {
4
+ return {
5
+ icon: 'info',
6
+ allowEscapeKey: false,
7
+ allowEnterKey: false,
8
+ allowOutsideClick: false,
9
+ showConfirmButton: true,
10
+ confirmButtonText: phrases.RC_ok[RC.L],
11
+ showClass: {
12
+ popup: 'animate__animated animate__fadeInUp',
13
+ // backdrop: 'animate__animated animate__fadeIn',
14
+ },
15
+ hideClass: {
16
+ popup: 'animate__animated animate__fadeOutDown',
17
+ // backdrop: 'animate__animated animate__fadeOut',
18
+ },
19
+ iconColor: RC._CONST.COLOR.ORANGE,
20
+ confirmButtonColor: '#aaa',
21
+ customClass: {
22
+ icon: 'my__swal2__icon',
23
+ title: 'my__swal2__title',
24
+ htmlContainer: 'my__swal2__html',
25
+ },
26
+ }
25
27
  }
@@ -98,9 +98,15 @@ export function getFullscreen() {
98
98
 
99
99
  /* -------------------------------------------------------------------------- */
100
100
 
101
- export function constructInstructions(headline, description = null) {
101
+ export function constructInstructions(
102
+ headline,
103
+ description = null,
104
+ scrollable = false
105
+ ) {
102
106
  return (
103
- `<div class="calibration-instruction"><h1>${headline}</h1>` +
107
+ `<div class="calibration-instruction${
108
+ scrollable ? ' calibration-instruction-scrollable' : ''
109
+ }"><h1>${headline}</h1>` +
104
110
  (description
105
111
  ? `<p class="calibration-description">${description}</p></div>`
106
112
  : '')
@@ -69,7 +69,7 @@ export function checkWebcamStatus() {
69
69
  * Check if WebGazer video is ready. If so, set the style for it.
70
70
  *
71
71
  */
72
- export function checkWebgazerReady(pipWidthPx, opacity, WG, callback) {
72
+ export function checkWebgazerReady(RC, pipWidthPx, opacity, WG, callback) {
73
73
  let c = setInterval(() => {
74
74
  let v = document.getElementById('webgazerVideoContainer')
75
75
  if (v) {
@@ -78,15 +78,34 @@ export function checkWebgazerReady(pipWidthPx, opacity, WG, callback) {
78
78
  v.style.width = pipWidthPx + 'px'
79
79
  v.style.opacity = opacity
80
80
  WG.setVideoViewerSize(parseInt(v.style.width), parseInt(v.style.height))
81
- v.style.left = '10px'
82
- v.style.bottom = '10px'
81
+
82
+ // Set position
83
+ setDefaultVideoPosition(RC, v)
83
84
 
84
85
  // Give callback after 2 sec
85
86
  setTimeout(() => {
86
- v.style.transition = `left 0.5s, bottom 0.5s, width 0.5s, height 0.5s, border-radius 0.5s`
87
+ if (RC.isMobile.value)
88
+ v.style.transition = `right 0.5s, top 0.5s, width 0.5s, height 0.5s, border-radius 0.5s`
89
+ else
90
+ v.style.transition = `left 0.5s, bottom 0.5s, width 0.5s, height 0.5s, border-radius 0.5s`
87
91
  callback()
88
92
  }, 1000)
89
93
  clearInterval(c)
90
94
  }
91
95
  }, 200)
92
96
  }
97
+
98
+ export function setDefaultVideoPosition(RC, v) {
99
+ if (RC.isMobile.value) {
100
+ // Mobile
101
+ v.style.left = 'unset'
102
+ v.style.right = RC._CONST.N.VIDEO_MARGIN
103
+ v.style.top = RC._CONST.N.VIDEO_MARGIN
104
+ v.style.bottom = 'unset'
105
+ } else {
106
+ v.style.left = RC._CONST.N.VIDEO_MARGIN
107
+ v.style.right = 'unset'
108
+ v.style.top = 'unset'
109
+ v.style.bottom = RC._CONST.N.VIDEO_MARGIN
110
+ }
111
+ }
package/src/const.js CHANGED
@@ -1,8 +1,28 @@
1
1
  import RemoteCalibrator from './core'
2
2
 
3
3
  RemoteCalibrator.prototype._CONST = Object.freeze({
4
- CREDIT_TEXT: {
5
- BLIND_SPOT_TEST: `As suggested by the Li et al. (2020) "Virtual Chinrest" paper.`,
6
- CREDIT_CARD: `Credit card suggested by the Li et al. (2020) "Virtual Chinrest" paper.`,
4
+ N: {
5
+ VIDEO_W: {
6
+ DESKTOP: 208,
7
+ MOBILE: 144,
8
+ },
9
+ VIDEO_MARGIN: '10px',
10
+ GAZE_CALIBRATION: {
11
+ R: 28,
12
+ MARGIN: 10,
13
+ BORDER: 8,
14
+ },
15
+ },
16
+ S: {
17
+ AUTO: 'AUTO',
18
+ CLICK_TYPE: {
19
+ MOUSE: 'mouse',
20
+ TOUCH: 'touch',
21
+ },
22
+ },
23
+ COLOR: {
24
+ LIGHT_GREY: '#cccccc',
25
+ ORANGE: '#ff9a00',
26
+ DARK_RED: '#ac0d0d',
7
27
  },
8
28
  })
package/src/core.js CHANGED
@@ -8,8 +8,14 @@ import platform from 'platform'
8
8
  import DeviceDetector from 'device-detector-js'
9
9
 
10
10
  import randomPhrases from './components/randomPhrases'
11
- import { debug } from './constants'
12
- import { getFullscreen, blurAll, constructInstructions } from './helpers'
11
+ import { debug } from './debug'
12
+ import {
13
+ getFullscreen,
14
+ blurAll,
15
+ constructInstructions,
16
+ } from './components/utils'
17
+ import { looseSetLanguage } from './components/language'
18
+ import { phrases } from './i18n'
13
19
 
14
20
  class RemoteCalibrator {
15
21
  constructor() {
@@ -29,6 +35,9 @@ class RemoteCalibrator {
29
35
 
30
36
  this._id = null
31
37
 
38
+ this._lang = null // A single string, e.g., 'en-US'
39
+ this._langData = []
40
+
32
41
  this._environmentData = []
33
42
 
34
43
  this._displayData = [] // Px
@@ -76,6 +85,7 @@ class RemoteCalibrator {
76
85
  ////
77
86
 
78
87
  get id() {
88
+ if (!this._id) return null
79
89
  return {
80
90
  value: this._id.value,
81
91
  timestamp: this._id.timestamp,
@@ -100,6 +110,43 @@ class RemoteCalibrator {
100
110
  }
101
111
  }
102
112
 
113
+ get supportedLanguages() {
114
+ const a = []
115
+ for (let l in phrases.EE_languageNameEnglish) {
116
+ a.push({
117
+ language: l,
118
+ languageNameEnglish: phrases.EE_languageNameEnglish[l],
119
+ languageNameNative: phrases.EE_languageNameNative[l],
120
+ })
121
+ }
122
+
123
+ return a
124
+ }
125
+
126
+ get L() {
127
+ return this._lang
128
+ }
129
+
130
+ get language() {
131
+ return this._helper_get(this._langData, 'language')
132
+ }
133
+
134
+ get languageNameEnglish() {
135
+ return this._helper_get(this._langData, 'languageNameEnglish')
136
+ }
137
+
138
+ get languageNameNative() {
139
+ return this._helper_get(this._langData, 'languageNameNative')
140
+ }
141
+
142
+ get languageDirection() {
143
+ return this._helper_get(this._langData, 'languageDirection')
144
+ }
145
+
146
+ get languagePhraseSource() {
147
+ return this._helper_get(this._langData, 'languagePhraseSource')
148
+ }
149
+
103
150
  // Status
104
151
 
105
152
  get isFullscreen() {
@@ -135,6 +182,15 @@ class RemoteCalibrator {
135
182
  return this._helper_get(this._environmentData, 'deviceType')
136
183
  }
137
184
 
185
+ get isMobile() {
186
+ if (!this._environmentData.length) this.environment()
187
+ const d = this._helper_get(this._environmentData, 'deviceType')
188
+ return {
189
+ value: d.value !== 'desktop',
190
+ timestamp: d.timestamp,
191
+ }
192
+ }
193
+
138
194
  get model() {
139
195
  if (!this._environmentData.length) this.environment()
140
196
  return this._helper_get(this._environmentData, 'model')
@@ -170,6 +226,11 @@ class RemoteCalibrator {
170
226
  return this._helper_get(this._environmentData, 'fullDescription')
171
227
  }
172
228
 
229
+ get userLanguage() {
230
+ if (!this._environmentData.length) this.environment()
231
+ return this._helper_get(this._environmentData, 'userLanguage')
232
+ }
233
+
173
234
  // Screen
174
235
 
175
236
  get displayWidthPx() {
@@ -274,6 +335,10 @@ class RemoteCalibrator {
274
335
  return this._environmentData
275
336
  }
276
337
 
338
+ get languageData() {
339
+ return this._langData
340
+ }
341
+
277
342
  /* --------------------------------- SETTERS -------------------------------- */
278
343
 
279
344
  /**
@@ -338,6 +403,13 @@ class RemoteCalibrator {
338
403
  set newFullscreenData(data) {
339
404
  this._fullscreenData.push(data)
340
405
  }
406
+
407
+ /**
408
+ * @param {{ value: { language: string; languageNameEnglish: string; languageNameNative: string; languageDirection: string; languagePhraseSource: string; }; timestamp: Date; }} data
409
+ */
410
+ set newLanguageData(data) {
411
+ this._langData.push(data)
412
+ }
341
413
  }
342
414
 
343
415
  /**
@@ -351,6 +423,7 @@ RemoteCalibrator.prototype.init = function (options = {}, callback) {
351
423
  options = Object.assign(
352
424
  {
353
425
  id: randomPhrases(),
426
+ language: 'AUTO',
354
427
  fullscreen: false,
355
428
  },
356
429
  options
@@ -363,7 +436,15 @@ RemoteCalibrator.prototype.init = function (options = {}, callback) {
363
436
  timestamp: new Date(),
364
437
  }
365
438
 
366
- if (callback) callback(this._id)
439
+ this.environment()
440
+
441
+ if (this._CONST.S.AUTO === options.language)
442
+ // AUTO
443
+ this.newLanguageData = looseSetLanguage(this.userLanguage.value)
444
+ else this.newLanguageData = looseSetLanguage(options.language)
445
+ this._lang = this.language.value
446
+
447
+ if (callback && typeof callback === 'function') callback(this._id)
367
448
  }
368
449
  }
369
450
 
@@ -381,7 +462,9 @@ RemoteCalibrator.prototype.environment = function (callback) {
381
462
 
382
463
  const data = {
383
464
  value: {
384
- bot: bot ? `${bot.name} (${bot.category}) by ${bot.producer.name}` : '',
465
+ bot: bot
466
+ ? `${bot.name} (${bot.category}) by ${bot.producer.name}`
467
+ : null,
385
468
  browser: platform.name,
386
469
  browserVersion: platform.version,
387
470
  deviceType: device.device.type,
@@ -392,6 +475,8 @@ RemoteCalibrator.prototype.environment = function (callback) {
392
475
  systemFamily: platform.os.family,
393
476
  description: platform.description,
394
477
  fullDescription: platform.ua,
478
+ userLanguage:
479
+ window.navigator.userLanguage || window.navigator.language,
395
480
  },
396
481
  timestamp: this.id.timestamp,
397
482
  }
@@ -435,6 +520,18 @@ RemoteCalibrator.prototype.getFullscreen = function (f = true) {
435
520
  return f && !debug
436
521
  }
437
522
 
523
+ /**
524
+ * Set a new language
525
+ */
526
+ RemoteCalibrator.prototype.newLanguage = function (lang) {
527
+ if (this.checkInitialized()) {
528
+ let data
529
+ this.newLanguageData = data = looseSetLanguage(lang)
530
+ this._lang = this.language.value
531
+ return data
532
+ }
533
+ }
534
+
438
535
  /**
439
536
  *
440
537
  * Add background
@@ -447,6 +544,8 @@ RemoteCalibrator.prototype._addBackground = function (inner) {
447
544
  if (!b) {
448
545
  b = document.createElement('div')
449
546
  b.id = 'calibration-background'
547
+
548
+ document.body.classList.add('lock-view')
450
549
  document.body.appendChild(b)
451
550
 
452
551
  b.style.background = this.params.backgroundColor
@@ -474,6 +573,7 @@ RemoteCalibrator.prototype._replaceBackground = function (inner) {
474
573
  RemoteCalibrator.prototype._removeBackground = function () {
475
574
  let b = document.getElementById('calibration-background')
476
575
  if (b) {
576
+ document.body.classList.remove('lock-view')
477
577
  document.body.removeChild(b)
478
578
 
479
579
  this._background = {
@@ -541,11 +641,11 @@ RemoteCalibrator.prototype._setFloatInstructionElementPos = function (
541
641
  const r = this.instructionElement.getBoundingClientRect()
542
642
  this.instructionElement.style.top = `calc(50% + ${yOffset + 10}px)`
543
643
  if (side === 'left') {
544
- this.instructionElement.style.left = '10%'
644
+ this.instructionElement.style.left = `max(10%, ${r.width / 2}px)`
545
645
  this.instructionElement.style.right = 'unset'
546
646
  this.instructionElement.style.transform = `translate(${-r.width / 2}px, 0)`
547
647
  } else if (side === 'right') {
548
- this.instructionElement.style.right = '10%'
648
+ this.instructionElement.style.right = `max(10%, ${r.width / 2}px)`
549
649
  this.instructionElement.style.left = 'unset'
550
650
  this.instructionElement.style.transform = `translate(${r.width / 2}px, 0)`
551
651
  } else {
@@ -3,17 +3,22 @@
3
3
  }
4
4
 
5
5
  #blind-spot-canvas {
6
- z-index: -1;
6
+ position: fixed;
7
7
  display: block;
8
- position: absolute;
8
+ z-index: -1;
9
9
  top: 0;
10
10
  left: 0;
11
+ bottom: 0;
12
+ right: 0;
13
+ padding: 0;
14
+ margin: 0;
11
15
  }
12
16
 
13
- #blind-spot-instruction {
14
- display: block !important;
15
- top: 65%;
16
- }
17
+ // #blind-spot-instruction {
18
+ // display: block !important;
19
+ // top: 65%;
20
+ // position: fixed;
21
+ // }
17
22
 
18
23
  #pip-video {
19
24
  display: none;
@@ -31,7 +36,7 @@
31
36
  /* ----------------------------------- PD ----------------------------------- */
32
37
 
33
38
  #rc-ruler {
34
- position: absolute;
39
+ position: fixed;
35
40
  max-height: 120px;
36
41
  overflow: hidden;
37
42
  }
package/src/css/main.css CHANGED
@@ -28,14 +28,15 @@
28
28
 
29
29
  .calibration-instruction {
30
30
  position: absolute;
31
- margin: 2rem;
32
31
  text-align: left;
33
32
  user-select: none;
34
33
  }
35
34
 
35
+ .calibration-instruction-scrollable {
36
+ height: 200%;
37
+ }
38
+
36
39
  .calibration-instruction h1 {
37
- font-size: 2.5rem !important;
38
- line-height: 100%;
39
40
  min-width: 360px;
40
41
  font-weight: 700;
41
42
  }
@@ -53,21 +54,66 @@
53
54
  }
54
55
 
55
56
  .calibration-description {
56
- width: calc(100% - 4rem);
57
- width: max(min(100% - 4rem, 960px), 300px);
57
+ line-height: 170%;
58
+ }
59
+
60
+ /* -------------------------------------------------------------------------- */
61
+ /* Screen size specific */
62
+
63
+ @media (min-width: 481px) {
64
+ .calibration-instruction {
65
+ margin: 2rem;
66
+ }
67
+
68
+ .calibration-instruction h1 {
69
+ line-height: 100%;
70
+ font-size: 2.5rem !important;
71
+ }
72
+
73
+ .calibration-description {
74
+ width: calc(100% - 4rem);
75
+ width: max(min(100% - 4rem, 960px), 300px);
76
+ }
77
+
78
+ .calibration-description,
79
+ .calibration-description * {
80
+ font-size: 1.2rem;
81
+ }
82
+
83
+ .calibration-credit-text {
84
+ font-size: 0.9rem !important;
85
+ }
58
86
  }
59
87
 
60
88
  @media (max-width: 480px) {
89
+ .calibration-instruction {
90
+ margin: 1rem;
91
+ }
92
+
93
+ .calibration-instruction h1 {
94
+ line-height: 120%;
95
+ font-size: 1.8rem !important;
96
+ }
97
+
61
98
  .calibration-description {
62
- font-size: 0.9rem;
99
+ width: calc(100% - 1rem);
100
+ }
101
+
102
+ .calibration-description,
103
+ .calibration-description * {
104
+ font-size: 1rem;
105
+ }
106
+
107
+ .calibration-credit-text {
108
+ font-size: 0.7rem !important;
63
109
  }
64
110
  }
65
111
 
66
112
  .float-instruction {
67
- position: absolute;
113
+ position: fixed;
68
114
  text-align: center;
69
115
  user-select: none;
70
- background: rgba(255, 255, 255, 0.7);
116
+ background: rgba(255, 255, 255, 0.9);
71
117
  padding: 10px 17px;
72
118
  margin: 0;
73
119
  left: 50%;
@@ -75,6 +121,7 @@
75
121
  border-radius: 10px;
76
122
  font-size: 1.2rem;
77
123
  font-weight: 500;
124
+ z-index: 9999;
78
125
  }
79
126
 
80
127
  /* -------------------------------------------------------------------------- */
@@ -87,10 +134,18 @@
87
134
 
88
135
  .calibration-credit-text {
89
136
  position: fixed !important;
90
- left: 50% !important;
137
+ width: 100% !important;
91
138
  bottom: 3px !important;
139
+ left: 50% !important;
92
140
  transform: translate(-50%, 0) !important;
93
- font-size: 0.9rem !important;
94
141
  color: #999 !important;
95
142
  margin: 0 !important;
143
+ padding: 0 !important;
144
+ line-height: 100% !important;
145
+ }
146
+
147
+ /* -------------------------------------------------------------------------- */
148
+
149
+ .lock-view {
150
+ overflow: hidden !important;
96
151
  }
@@ -34,7 +34,7 @@
34
34
 
35
35
  .rc-panel-title {
36
36
  color: #fff !important;
37
- margin: 1rem auto 0 1rem !important;
37
+ margin: 1rem 1rem 0 1rem !important;
38
38
  font-size: 2rem !important;
39
39
  font-weight: 600 !important;
40
40
  }