liftie 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli/fetch.js CHANGED
@@ -3,22 +3,21 @@ import { program } from 'commander';
3
3
  import curl from './curl.js';
4
4
  import { descriptorPath } from './dirs.js';
5
5
 
6
- let done;
7
-
8
6
  async function fetchExample(resortId) {
9
7
  try {
10
8
  const resort = JSON.parse(readFileSync(descriptorPath(resortId), 'utf8'));
11
- done = true;
12
9
  await curl(resort.dataUrl || resort.api || resort.url, resortId);
13
- } catch (e) {
14
- console.error(resortId, 'is not a valid resort ID', e);
10
+ } catch {
11
+ console.error(`"${resortId}" is not a valid resort ID`);
15
12
  process.exit(1);
16
13
  }
17
14
  }
18
15
 
19
- program.arguments('<resort-id>').action(fetchExample).parse(process.argv);
20
-
21
- if (!done) {
22
- program.outputHelp();
23
- process.exit(1);
24
- }
16
+ program
17
+ .arguments('<resort-id>')
18
+ .action(fetchExample)
19
+ .parseAsync()
20
+ .catch(e => {
21
+ console.error(e);
22
+ process.exit(1);
23
+ });
@@ -1,14 +1,8 @@
1
- import { readdir } from 'node:fs';
1
+ import { readdirSync } from 'node:fs';
2
2
  import { lib } from './dirs.js';
3
3
  export default forEachResort;
4
4
 
5
5
  function forEachResort(fn) {
6
6
  console.log('Reading:', lib);
7
- readdir(lib, { withFileTypes: true }, (err, dirents) => {
8
- if (err) {
9
- console.error(err);
10
- process.exit(1);
11
- }
12
- dirents.filter(dirent => dirent.isDirectory()).forEach(({ name }) => fn(name));
13
- });
7
+ readdirSync(lib, { withFileTypes: true }).forEach(dirent => dirent.isDirectory() && fn(dirent.name));
14
8
  }
@@ -52,7 +52,7 @@ const schema = [
52
52
  }
53
53
  ];
54
54
 
55
- program.option('-j, --json <file>', 'JSON file with resort data', String).parse(process.argv);
55
+ program.option('-j, --json <file>', 'JSON file with resort data', String).parse();
56
56
 
57
57
  if (program.json) {
58
58
  fname = path.resolve(program.json);
package/lib/cli/noaa.js CHANGED
@@ -1,10 +1,8 @@
1
- import { readFileSync, writeFileSync } from 'node:fs';
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
2
  import { program } from 'commander';
3
3
  import { descriptorPath } from './dirs.js';
4
4
  import forEachResort from './for-each-resort.js';
5
5
 
6
- let done = false;
7
-
8
6
  const userAgent = 'Mozilla/5.0 (compatible; Liftie/1.0; +https://liftie.info)';
9
7
 
10
8
  function points([lon, lat]) {
@@ -16,49 +14,47 @@ function points([lon, lat]) {
16
14
  }
17
15
 
18
16
  function fetchNoaa(resortId, options) {
19
- done = true;
20
-
21
17
  if (resortId) {
22
18
  noaaForResort(resortId, options);
23
19
  } else {
24
- forEachResort(resortId => noaaForResort(resortId, options));
20
+ forEachResort(resortId => noaaForResort(resortId, options).catch(e => console.error(resortId, e)));
25
21
  }
26
22
  }
27
23
 
28
- function noaaForResort(resortId, { overwrite }) {
29
- const descriptor = readDescriptor(resortId);
24
+ async function noaaForResort(resortId, { overwrite }) {
25
+ const descriptor = await readDescriptor(resortId);
30
26
 
31
27
  const { ll } = descriptor;
32
- fetch(`https://api.weather.gov/points/${points(ll)}`, {
28
+ const res = await fetch(`https://api.weather.gov/points/${points(ll)}`, {
33
29
  headers: {
34
30
  'User-Agent': userAgent,
35
31
  Accept: 'application/geo+json'
36
32
  }
37
- })
38
- .then(res => res.json())
39
- .then(body => {
40
- const {
41
- properties: { gridId, gridX, gridY }
42
- } = body;
43
- const noaa = `${gridId}/${gridX},${gridY}`;
44
- if (overwrite) {
45
- descriptor.noaa = noaa;
46
- writeDescriptor(resortId, descriptor);
47
- }
48
- console.log(resortId, noaa);
49
- })
50
- .catch(e => console.error('Cannot find NOAA station for:', resortId, e));
33
+ });
34
+ if (res.status !== 200) {
35
+ console.error('Cannot find NOAA station for:', resortId);
36
+ return;
37
+ }
38
+ const {
39
+ properties: { gridId, gridX, gridY }
40
+ } = await res.json();
41
+ const noaa = `${gridId}/${gridX},${gridY}`;
42
+ if (overwrite) {
43
+ descriptor.noaa = noaa;
44
+ await writeDescriptor(resortId, descriptor);
45
+ }
46
+ console.log(resortId, noaa);
51
47
  }
52
48
 
53
49
  function writeDescriptor(resortId, descriptor) {
54
50
  const filename = descriptorPath(resortId);
55
- writeFileSync(filename, `${JSON.stringify(descriptor, null, 2)}\n`);
51
+ return writeFile(filename, `${JSON.stringify(descriptor, null, 2)}\n`);
56
52
  }
57
53
 
58
- function readDescriptor(resortId) {
54
+ async function readDescriptor(resortId) {
59
55
  try {
60
56
  const filename = descriptorPath(resortId);
61
- return JSON.parse(readFileSync(filename, 'utf8'));
57
+ return JSON.parse(await readFile(filename, 'utf8'));
62
58
  } catch {
63
59
  console.error(resortId, 'is not a valid resort ID');
64
60
  process.exit(1);
@@ -69,9 +65,4 @@ program
69
65
  .option('--overwrite', 'overwrite resort descriptor with new value')
70
66
  .arguments('[resort-id]')
71
67
  .action(fetchNoaa)
72
- .parse(process.argv);
73
-
74
- if (!done) {
75
- program.outputHelp();
76
- process.exit(1);
77
- }
68
+ .parse();
@@ -13,5 +13,5 @@
13
13
  ],
14
14
  "twitter": "resortalyeska",
15
15
  "opening": "2017-12-15",
16
- "noaa": "AER/139,227"
16
+ "noaa": "AER/157,227"
17
17
  }
@@ -15,5 +15,5 @@
15
15
  44.077778
16
16
  ],
17
17
  "opening": "2017-12-15",
18
- "noaa": "GYX/39,72"
18
+ "noaa": "GYX/35,71"
19
19
  }
@@ -14,5 +14,5 @@
14
14
  44.077122
15
15
  ],
16
16
  "twitter": "bretton_woods",
17
- "noaa": "GYX/37,71"
17
+ "noaa": "GYX/33,70"
18
18
  }
@@ -14,5 +14,5 @@
14
14
  44.156452
15
15
  ],
16
16
  "twitter": "cannonmountain",
17
- "noaa": "GYX/25,73"
17
+ "noaa": "GYX/21,72"
18
18
  }
@@ -14,5 +14,5 @@
14
14
  ],
15
15
  "twitter": "CranmoreMtn",
16
16
  "opening": "2017-12-02",
17
- "noaa": "GYX/45,72"
17
+ "noaa": "GYX/41,71"
18
18
  }
@@ -14,5 +14,5 @@
14
14
  ],
15
15
  "twitter": "Gunstockmtn",
16
16
  "opening": "2017-12-01",
17
- "noaa": "GYX/41,47"
17
+ "noaa": "GYX/37,46"
18
18
  }
@@ -18,5 +18,5 @@
18
18
  ],
19
19
  "twitter": "KingPineSkiarea",
20
20
  "opening": "2017-12-15",
21
- "noaa": "GYX/47,63"
21
+ "noaa": "GYX/43,62"
22
22
  }
@@ -18,5 +18,5 @@
18
18
  ],
19
19
  "twitter": "loonmtn",
20
20
  "opening": "2017-11-22",
21
- "noaa": "GYX/28,69"
21
+ "noaa": "GYX/24,68"
22
22
  }
@@ -14,5 +14,5 @@
14
14
  43.341194
15
15
  ],
16
16
  "opening": "2017-12-05",
17
- "noaa": "GYX/19,34"
17
+ "noaa": "GYX/15,33"
18
18
  }
@@ -18,5 +18,5 @@
18
18
  ],
19
19
  "twitter": "patspeak",
20
20
  "opening": "2017-12-09",
21
- "noaa": "GYX/28,28"
21
+ "noaa": "GYX/24,27"
22
22
  }
@@ -18,5 +18,5 @@
18
18
  ],
19
19
  "twitter": "pleasantmtnme",
20
20
  "opening": "2022-09-02",
21
- "noaa": "GYX/55,73"
21
+ "noaa": "GYX/51,72"
22
22
  }
@@ -14,5 +14,5 @@
14
14
  ],
15
15
  "twitter": "raggedmtnNH",
16
16
  "opening": "2017-12-07",
17
- "noaa": "GYX/25,42"
17
+ "noaa": "GYX/21,41"
18
18
  }
@@ -13,5 +13,5 @@
13
13
  44.983387
14
14
  ],
15
15
  "twitter": "SaddlebackMaine",
16
- "noaa": "GYX/53,117"
16
+ "noaa": "GYX/49,116"
17
17
  }
@@ -18,5 +18,5 @@
18
18
  ],
19
19
  "twitter": "SugarloafMaine",
20
20
  "opening": "2017-11-23",
21
- "noaa": "GYX/63,123"
21
+ "noaa": "GYX/59,122"
22
22
  }
@@ -18,5 +18,5 @@
18
18
  ],
19
19
  "twitter": "sundayriver",
20
20
  "opening": "2017-11-22",
21
- "noaa": "GYX/48,96"
21
+ "noaa": "GYX/44,95"
22
22
  }
@@ -18,5 +18,5 @@
18
18
  43.961613
19
19
  ],
20
20
  "twitter": "waterville",
21
- "noaa": "GYX/32,65"
21
+ "noaa": "GYX/28,64"
22
22
  }
@@ -15,5 +15,5 @@
15
15
  ],
16
16
  "twitter": "skiwildcat",
17
17
  "opening": "2017-11-25",
18
- "noaa": "GYX/39,81"
18
+ "noaa": "GYX/35,80"
19
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liftie",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "Clean, simple, easy to read, fast ski resort lift status",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -60,7 +60,7 @@
60
60
  "devDependencies": {
61
61
  "@biomejs/biome": "2.2.6",
62
62
  "@pirxpilot/stylus": "^1.2.0",
63
- "commander": "~13",
63
+ "commander": "~14",
64
64
  "postcss": "~8",
65
65
  "postcss-cachify": "^4.0.0",
66
66
  "postcss-cli-simple": "~4.0.0",
@@ -1 +0,0 @@
1
- @font-face{font-family:lift-status;src:url(/OEQfOpxZ4A/stylesheets/fonts/lift-status.woff2) format("woff2");font-weight:400;font-style:normal}[class^=ls-]:before,[class*=" ls-"]:before{font-family:lift-status;font-style:normal;speak:none;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased}.ls-scheduled:before{content:"\e004";color:#104aa8}.ls-hold:before{content:"\e005";color:#ffa200}.ls-closed:before{content:"\e006";color:#ff1e00}.ls-open:before{content:"\e007";color:#00b831}.ls-github:before{content:"\e010"}.ls-twitter:before{content:"\e011"}.ls-facebook:before{content:"\e012"}.ls-google-plus:before{content:"\e013"}.ls-furkot:before{content:"\e020"}.ls-plus:before{content:"\e031"}.ls-minus:before{content:"\e032"}.ls-external:before{content:"\e033"}.ls-deal:before{content:"\e034"}.ls-star-full:before{content:"\e035"}.ls-star-outline:before{content:"\e036"}.ls-pie:before{content:"\e000"}.ls-snowflake:before{content:"\e001"}.ls-html:before{content:"\f068"}.ls-liftie:before{content:"\e002"}.ls-email:before{content:"\f028"}@font-face{font-family:iconvault;src:url(/qGg5C7akoM/stylesheets/fonts/iconvault_forecastfont.woff2) format("woff2");font-weight:400;font-style:normal}div.weather-icon ul li{list-style:none}div.weather-icon ul [class^=icon-],div.weather-icon ul [class*=" icon-"]{font-family:iconvault;font-weight:400;font-style:normal;text-decoration:inherit;speak:none;-webkit-font-smoothing:antialiased;font-size:4em}div.weather-icon ul .basecloud:before{font-family:iconvault;font-size:4em;content:"\f105";position:absolute;color:#ccc}div.weather-icon ul .windyraincloud:before{font-family:iconvault;font-size:4em;content:"\f111";position:absolute;color:#ccc}div.weather-icon ul .windysnowcloud:before{font-family:iconvault;font-size:4em;content:"\f109";position:absolute;color:#ccc}div.weather-icon ul .icon-thunder:before{content:"\f114";position:absolute;color:orange}div.weather-icon ul .icon-sunny:after{content:"\f101";color:orange;position:absolute}div.weather-icon ul .icon-drizzle:before{content:"\f10a";color:#82b2e4;position:absolute}div.weather-icon ul .icon-hail:before{content:"\f10f";position:absolute;color:#ccc}div.weather-icon ul .icon-showers:before{content:"\f104";position:absolute;color:#82b2e4}div.weather-icon ul .icon-rainy:before{content:"\f107";position:absolute;color:#4681c3}div.weather-icon ul .icon-snowy:before{content:"\f10b";position:absolute;color:#acd3f3}div.weather-icon ul .icon-frosty:before{content:"\f102";position:absolute;color:#85d8f7}div.weather-icon ul .icon-windy:before{content:"\f115";position:absolute;color:#ccc}div.weather-icon ul .icon-windyrain:before{content:"\f10e";position:absolute;color:#acd3f3}div.weather-icon ul .icon-windysnow:before{content:"\f103";position:absolute;color:#acd3f3}div.weather-icon ul .icon-sleet:before{content:"\f10c";position:absolute;color:#acd3f3}div.weather-icon ul .icon-moon:after{content:"\f10d";color:orange;position:absolute}div.weather-icon ul .icon-night:after{content:"\f100";position:absolute;color:orange}div.weather-icon ul .icon-sun:after{content:"\f113";color:orange;position:absolute}div.weather-icon ul .icon-cloud:after{content:"\f106";color:#ccc;position:absolute}div.weather-icon ul .icon-sunrise:before{content:"\f112";color:orange;position:absolute}div.weather-icon ul .icon-sunset:before{content:"\f110";color:#f96f23;position:absolute}div.weather-icon ul .icon-mist:before{content:"\f108";color:#ccc;position:absolute}*{padding:0;margin:0}a,input,button{-ms-touch-action:none!important}.hidden{display:none!important;visibility:hidden}.visible:after{content:" ";display:block;clear:both}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.icon-alone{display:inline-block;cursor:pointer}.left{float:left}.right{float:right}body{font-size:1em;font-family:Ubuntu,Lucida Grande,Helvetica,Arial,sans-serif;color:#333}a{color:#009ddb;text-shadow:0 1px #fff;transition:color .3s ease;text-decoration:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-tap-highlight-color:transparent}a:hover,a:active{color:#00a7f1}.panel{box-sizing:border-box;margin:0 8px 16px;width:320px;padding:0 12px;float:left;background-color:#f5f8ff}.panel:after{content:" ";display:block;clear:both}.panel:last-child{margin-bottom:0}header .ls-furkot{font-size:.9em}.add-to-trip{cursor:pointer;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.add-to-trip span+span{margin-left:.2em}.resort footer .add-to-trip{margin-top:.3em}.panel header,.panel footer{transition:all .4s ease}.panel header:after,.panel footer:after{content:" ";display:block;clear:both}.panel header{padding:.7em 0 .5em}.panel footer{padding:0 0 .7em}.panel header{font-size:1.2em;border-bottom:solid 2px transparent;vertical-align:middle;display:flex;align-items:baseline;gap:.2em}.panel header a{outline:none}.panel.open header{border-color:#0000004d}.open .expandable{opacity:1;max-height:4500px;min-height:5em}.open .expandable .lifts-status{position:relative}.open .expandable .lifts-status .opening-date{position:absolute;width:100%;height:100%;z-index:1;background-color:#f5f8ffe6}.open .expandable .lifts-status .opening-date a{position:absolute;top:50%;margin-top:-.6em;font-size:1.2em;width:100%;text-align:center}.expandable{transition:all .4s ease;max-height:0;overflow-y:hidden;opacity:0}.lifts{list-style:none;margin:.2em 0}.lifts .lift{display:block;line-height:2}.lifts .lift:after{content:" ";display:block;clear:both}.lifts .lift .name{float:left;max-width:90%;cursor:default;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.lifts .lift .status{font-size:1.1em;float:right;text-shadow:1px 1px #fff;padding-right:2px}.auto-refresh-reminder{color:#707070;font-style:italic;text-align:right;font-size:.8em;padding-right:2px}.ls-minimax:before{content:"\e031"}.open .ls-minimax:before{content:"\e032"}.ls-star:before{content:"\e036"}.starred .ls-star:before{content:"\e035"}.resort-link{font-size:.9em}.resort-name{flex:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.summary{list-style:none;font-size:.8em}.summary:after{content:" ";display:block;clear:both}.summary li{float:left;margin-right:.5em}.summary li:last-child{margin-right:0}.summary li [class^=ls-],.summary li [class*=" ls-"],.summary li [class^=ls-]:before,.summary li [class*=" ls-"]:before{margin-right:2px}.summary li [class^=ls-]:before,.summary li [class*=" ls-"]:before{text-shadow:1px 1px #fff}.summary-color-bar{width:100%;margin-bottom:.5em}.summary-color-bar:after{content:" ";display:block;clear:both}.summary-color-bar .open,.summary-color-bar .hold,.summary-color-bar .scheduled,.summary-color-bar .closed{height:2px;float:left}.summary-color-bar .open{background-color:#00b831}.summary-color-bar .hold{background-color:#ffa200}.summary-color-bar .scheduled{background-color:#104aa8}.summary-color-bar .closed{background-color:#ff1e00}.extras{padding-bottom:.7em}.extras .tile{font-size:.9em;padding:.5em 0}.extras .tile{border-bottom:solid 2px rgba(0,0,0,.3)}.extras .tile:last-child{padding-bottom:0;border-bottom:none}.extras .notice{margin-top:.5em;font-size:.8em;font-style:italic;display:flex;align-items:center;justify-content:flex-end;gap:.5em}.extras .weather .weather-icon{float:left;height:70px;margin-top:-10px}.extras .weather .temperature{float:right;font-size:1.5em}.extras .weather .snow-conditions{clear:right;float:right;font-size:1.1em;margin-left:60px;text-align:right}.extras .weather .snowforecast{margin-left:.5em;font-weight:700}.extras .weather .text{clear:both}.extras .weather .notice img{float:none;width:126px;vertical-align:bottom}.extras .webcams .swipe{overflow:hidden}.extras .webcams .swipe *{touch-action:pan-y!important}.extras .webcams .pager{text-align:center;font-weight:700;line-height:1.3}.extras .webcams .pager a{margin:0 2px;padding:0 .3em}.extras .webcams .pager .active:before{content:"\25cf"}.extras .webcams .pager .inactive:before{content:"\25cb"}.extras .webcams li{list-style:none;display:inline-block;max-width:296px;vertical-align:top}.extras .webcams .webcam{max-width:100%;display:inline-block}.extras .webcams .webcam>a{display:block;position:relative;overflow-x:hidden}.extras .webcams .webcam>a img{margin:0 auto;-webkit-user-select:none;user-select:none;pointer-events:none}.extras .webcams .webcam>a img.active{display:block}.extras .webcams .webcam>a img.inactive{display:none}.extras .webcams .webcam>a .title{margin-bottom:.5em;text-align:center}.extras .snow .value{display:inline-block;min-width:2em;text-align:right}.extras .deals{padding-bottom:0}.extras .deals .deal{padding:.4em 0;line-height:1.5}.extras .deals .deal:after{content:" ";display:block;clear:both}.extras .deals .deal span{float:left}.extras .deals .deal a{float:right}.resort .deal{font-size:.9em;margin-bottom:.5em;padding:.5em 0;border-bottom:solid 2px rgba(0,0,0,.3)}.resort .deal a{float:right}.stats .pie{margin:1em 0;width:294px;height:294px;border-radius:50%;background-image:conic-gradient(#00b831 0 var(--open),#ffa200 0 var(--hold),#104aa8 0 var(--scheduled),#ff1e00 0)}.stats footer .summary li{float:none;clear:both;line-height:2;text-align:right;width:55%;margin:0 auto}.stats footer .summary li span:first-child{float:left}.stats footer .summary li span:first-child:before{margin-right:.5em}.stats footer .summary li span:last-child{float:right}body>footer{clear:both;margin-top:1em;padding:0 .2em;line-height:1;text-align:center}body>footer .text{display:inline;margin-left:.2em}body>footer a{margin:0 .2em}body>footer a span{color:#666;transition:color .3s ease}body>footer a:hover span{color:#000}body>footer a:hover .ls-twitter{color:$twitter-color}body>footer a:hover .ls-facebook{color:#3b5998}.about{background-color:#f5f8ff;background:linear-gradient(to bottom,#f6f9ff,#dde8fe);box-sizing:border-box;padding:1em}.about h1{font-size:1.2em}.about:after{content:" ";display:block;clear:both}.about p{margin:.5em 0;line-height:1.5em}.about p [class^=ls-]:before,.about p [class*=" ls-"]:before{color:#009ddb;text-shadow:1px 1px #fff;margin-right:.2em}.about footer a{font-size:.9em;color:#fff;text-shadow:0 -1px rgba(0,0,0,.3);display:block;float:right;padding:.3em .5em;background-color:#009ddb;background:linear-gradient(to bottom,#00a8ea,#0095d0)}.about footer a:hover{background-color:#00b2f8;background:linear-gradient(to bottom,#06b9ff,#00a9ec)}.tags{list-style:none;display:block;margin:0 8px}.tags li{display:block;float:left;position:relative;font-size:.9em;margin-right:1.2em;margin-bottom:.6em}.tags li:last-child{margin-right:0}.tags a,.tags .count{display:block;box-sizing:border-box}.tags a{color:#009ddb;text-shadow:0 1px #fff;padding:5px 6px 5px 7px;background-color:#f5f8ff;background:linear-gradient(to bottom,#f6f9ff,#dde8fe)}.tags a .count{position:absolute;top:0;left:100%;z-index:2;overflow:hidden;max-width:0;padding:5px 0 5px 2px;color:#fff;text-shadow:0 -1px rgba(0,0,0,.3);background-color:#009ddb;background:linear-gradient(to bottom,#00a8ea,#0095d0);opacity:.95;transition-duration:.3s;transition-timing-function:ease-out;transition-property:padding,max-width}.tags a:hover .count{padding:5px 7px 5px 6px;max-width:40px;box-shadow:1px 1px 2px #0003}.content{margin:16px auto;width:2352px}.content:after{content:" ";display:block;clear:both}.widget{font-size:.8em}.widget .panel{width:100%;margin:0;display:block;float:none}.widget.naked .panel{background-color:transparent;padding:0}.content-4{max-width:1344px}@media screen and (max-width: 1680px){.content{width:1344px}}.content-3{max-width:1008px}@media screen and (max-width: 1344px){.content{width:1008px}}.content-2{max-width:672px}@media screen and (max-width: 1008px){.content{width:672px}}.content-1{max-width:320px}@media screen and (max-width: 672px){.content{width:320px}.panel{margin-right:0;margin-left:0}.tags{margin:0}}@media screen and (max-width: 720px){body>footer{font-size:1.3em}body>footer .text{display:none}}@media screen and (max-width: 400px){.extras.desktop,.extras.desktop img{display:none}.extras.mobile,.extras.mobile img{display:block}}@media screen and (min-width: 500px){.widget .lift{float:left;margin-right:3%}}@media screen and (min-width: 500px) and (max-width: 749px){.widget .lift{width:48.5%}.widget .lift:nth-child(2n){margin-right:0}}@media screen and (min-width: 750px) and (max-width: 999px){.widget .lift{width:31.333%}.widget .lift:nth-child(3n){margin-right:0}}@media screen and (min-width: 1000px){.widget .lift{width:22.75%}.widget .lift:nth-child(4n){margin-right:0}}