liftie
Version:
Clean, simple, easy to read, fast ski resort lift status
942 lines (810 loc) • 16.5 kB
CSS
/* biome-ignore-all lint/suspicious/noUselessEscapeInString: https://github.com/biomejs/biome/issues/7385 */
:root {
/* Lift Status Colors */
--color-scheduled: hsl(217, 76%, 35%);
--color-hold: hsl(36, 100%, 50%);
--color-closed: hsl(8, 100%, 50%);
--color-open: hsl(131, 100%, 36%);
/* Weather Icon Colors */
--color-cloud-light: hsl(0, 0%, 80%);
--color-orange: hsl(39, 100%, 50%);
--color-sunset: hsl(9, 100%, 50%);
--color-drizzle: hsl(218, 70%, 66%);
--color-rain: hsl(217, 57%, 54%);
--color-snow-light: hsl(210, 85%, 79%);
--color-frost: hsl(198, 90%, 79%);
/* Text & Body Colors */
--color-text-body: hsl(0, 0%, 20%);
--color-link: hsl(200, 100%, 43%);
--color-link-hover: hsl(from var(--color-link) h s calc(l + 5));
--color-white: hsl(0, 0%, 100%);
--color-gray-light: hsl(0, 0%, 44%);
--color-gray-medium: hsl(0, 0%, 40%);
--color-black: hsl(0, 0%, 0%);
/* Panel & Background Colors */
--color-panel-bg: hsl(220, 100%, 97%);
/* Button & Gradient Colors */
--color-button-primary: var(--color-link);
--color-button-hover: var(--color-link-hover);
/* Transparency Colors */
--color-overlay: hsla(0, 0%, 0%, 0.3);
/* Panel Opening Date Background */
--color-panel-opening-date: hsla(from var(--color-panel-bg) h s l 0.9);
--column-width: 320px;
--column-gutter: 16px;
/* allow animate height: auto */
interpolate-size: allow-keywords;
}
@font-face {
font-family: lift-status;
src: url("fonts/lift-status.woff2") format("woff2");
font-weight: normal;
font-style: normal;
}
[class^="ls-"]::before,
[class*=" ls-"]::before {
font-family: lift-status;
font-style: normal;
speak: none;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
}
.ls-scheduled::before {
content: "\e004";
color: var(--color-scheduled);
}
.ls-hold::before {
content: "\e005";
color: var(--color-hold);
}
.ls-closed::before {
content: "\e006";
color: var(--color-closed);
}
.ls-open::before {
content: "\e007";
color: var(--color-open);
}
.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("fonts/iconvault_forecastfont.woff2") format("woff2");
font-weight: normal;
font-style: normal;
}
div.weather-icon ul {
li {
list-style: none;
}
[class^="icon-"],
[class*=" icon-"] {
font-family: "iconvault";
font-weight: normal;
font-style: normal;
text-decoration: inherit;
speak: none;
-webkit-font-smoothing: antialiased;
font-size: 4em;
}
.basecloud::before,
.windyraincloud::before,
.windysnowcloud::before,
.icon-hail::before,
.icon-windy::before,
.icon-cloud::after {
font-family: "iconvault";
position: absolute;
}
.basecloud::before,
.windyraincloud::before,
.windysnowcloud::before {
font-size: 4em;
color: var(--color-cloud-light);
}
.basecloud::before {
content: "\f105";
}
.windyraincloud::before {
content: "\f111";
}
.windysnowcloud::before {
content: "\f109";
}
.icon-thunder::before {
content: "\f114";
position: absolute;
color: var(--color-orange);
}
.icon-sunny::after {
content: "\f101";
color: var(--color-orange);
position: absolute;
}
.icon-drizzle::before {
content: "\f10a";
color: var(--color-drizzle);
position: absolute;
}
.icon-hail::before {
content: "\f10f";
color: var(--color-cloud-light);
}
.icon-showers::before {
content: "\f104";
position: absolute;
color: var(--color-drizzle);
}
.icon-rainy::before {
content: "\f107";
position: absolute;
color: var(--color-rain);
}
.icon-snowy::before {
content: "\f10b";
position: absolute;
color: var(--color-snow-light);
}
.icon-frosty::before {
content: "\f102";
position: absolute;
color: var(--color-frost);
}
.icon-windy::before {
content: "\f115";
color: var(--color-cloud-light);
}
.icon-windyrain::before {
content: "\f10e";
position: absolute;
color: var(--color-snow-light);
}
.icon-windysnow::before {
content: "\f103";
position: absolute;
color: var(--color-snow-light);
}
.icon-sleet::before {
content: "\f10c";
position: absolute;
color: var(--color-snow-light);
}
.icon-moon::after {
content: "\f10d";
color: var(--color-orange);
position: absolute;
}
.icon-night::after {
content: "\f100";
position: absolute;
color: var(--color-orange);
}
.icon-sun::after {
content: "\f113";
color: var(--color-orange);
position: absolute;
}
.icon-cloud::after {
content: "\f106";
color: var(--color-cloud-light);
}
.icon-sunrise::before {
content: "\f112";
color: var(--color-orange);
position: absolute;
}
.icon-sunset::before {
content: "\f110";
color: var(--color-sunset);
position: absolute;
}
.icon-mist::before {
content: "\f108";
color: var(--color-cloud-light);
position: absolute;
}
}
* {
padding: 0;
margin: 0;
}
a,
input,
button {
-ms-touch-action: none ;
}
/* Hide from both screenreaders and browsers: h5bp.com/u */
.hidden {
display: none ;
visibility: hidden;
}
/* Hide only visually, but have it available for screenreaders: h5bp.com/v */
.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: system-ui, sans-serif;
color: var(--color-text-body);
display: flex;
flex-direction: column;
&:not(:has(.widget)) {
min-height: 100vh;
}
> main {
flex: 1;
}
> footer {
clear: both;
margin-top: 1em;
padding: 0.5em 0.2em;
line-height: 1;
text-align: center;
.text {
display: inline;
margin-left: 0.2em;
}
a {
margin: 0 0.2em;
span {
color: var(--color-gray-medium);
transition: color 0.3s ease;
}
&:hover span {
color: var(--color-black);
}
}
}
}
a {
color: var(--color-link);
text-shadow: 0 1px var(--color-white);
transition: color 0.3s ease;
text-decoration: none;
-webkit-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
&:hover,
&:active {
color: var(--color-link-hover);
}
}
header {
.ls-furkot {
font-size: 0.9em;
}
}
.panel {
box-sizing: border-box;
width: var(--column-width);
padding: 0 12px;
background-color: var(--color-panel-bg);
header {
padding: 0.7em 0 0.5em;
font-size: 1.2em;
--border-color: transparent;
border-bottom: solid 2px var(--border-color);
vertical-align: middle;
display: flex;
align-items: baseline;
gap: 0.2em;
transition: all 0.4s ease;
a {
outline: none;
}
}
footer {
padding: 0 0 0.7em;
transition: all 0.4s ease;
}
&.open header {
--border-color: var(--color-overlay);
}
}
.add-to-trip {
cursor: pointer;
display: block;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
span + span {
margin-left: 0.2em;
}
}
.resort footer .add-to-trip {
margin-top: 0.3em;
}
.open {
.expandable {
opacity: 1;
height: auto;
.lifts-status {
position: relative;
.opening-date {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
background-color: var(--color-panel-opening-date);
a {
position: absolute;
top: 50%;
margin-top: -0.6em;
font-size: 1.2em;
width: 100%;
text-align: center;
}
}
}
}
.ls-minimax::before {
content: "\e032";
}
}
.expandable {
transition: all 0.4s ease-in;
transition-behavior: allow-discrete;
height: 0;
overflow-y: hidden;
opacity: 0;
}
.lifts {
list-style: none;
margin: 0.2em 0;
.lift {
display: flex;
justify-content: space-between;
line-height: 2;
.name {
flex-grow: 1;
max-width: 90%;
cursor: default;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.status {
font-size: 1.1em;
text-shadow: 1px 1px var(--color-white);
padding-right: 2px;
}
}
}
.auto-refresh-reminder {
color: var(--color-gray-light);
font-style: italic;
text-align: right;
font-size: 0.8em;
padding-right: 2px;
}
.ls-minimax::before {
content: "\e031";
}
.ls-star::before {
content: "\e036";
}
.starred .ls-star::before {
content: "\e035";
}
.resort-link {
font-size: 0.9em;
}
.resort-name {
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.summary {
list-style: none;
font-size: 0.8em;
display: flex;
justify-content: space-between;
li {
[class^="ls-"],
[class*=" ls-"],
[class^="ls-"]::before,
[class*=" ls-"]::before {
margin-right: 2px;
}
[class^="ls-"]::before,
[class*=" ls-"]::before {
text-shadow: 1px 1px var(--color-white);
}
}
}
.summary-color-bar {
width: 100%;
margin-bottom: 0.5em;
display: flex;
.open,
.hold,
.scheduled,
.closed {
height: 2px;
}
.open {
background-color: var(--color-open);
}
.hold {
background-color: var(--color-hold);
}
.scheduled {
background-color: var(--color-scheduled);
}
.closed {
background-color: var(--color-closed);
}
}
.extras {
padding-bottom: 0.7em;
.tile {
font-size: 0.9em;
padding: 0.5em 0;
border-bottom: solid 2px var(--color-overlay);
&:last-child {
padding-bottom: 0;
border-bottom: none;
}
}
.notice {
margin-top: 0.5em;
font-size: 0.8em;
font-style: italic;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 0.5em;
}
.weather {
display: grid;
grid-template-rows: min-content min-content min-content min-content;
grid-template-areas:
"icon temperature"
"icon snow-conditions"
"text text"
"notice notice";
gap: 0.5em;
.weather-icon {
grid-area: icon;
}
.temperature {
font-size: 1.5em;
text-align: end;
grid-area: temperature;
}
.snow-conditions {
font-size: 1.1em;
text-align: end;
grid-area: snow-conditions;
}
.snowforecast {
margin-left: 0.5em;
font-weight: bold;
}
.text {
grid-area: text;
}
.notice {
grid-area: notice;
img {
width: 126px;
vertical-align: bottom;
}
}
}
.webcams {
.swipe {
overflow: hidden;
* {
touch-action: pan-y ;
}
}
.pager {
text-align: center;
font-weight: bold;
line-height: 1.3;
a {
margin: 0 2px;
padding: 0 0.3em;
}
.active::before {
content: "●";
}
.inactive::before {
content: "○";
}
}
li {
list-style: none;
display: inline-block;
max-width: 296px;
vertical-align: top;
}
.webcam {
max-width: 100%;
display: inline-block;
> a {
display: block;
position: relative;
overflow-x: hidden;
img {
margin: 0 auto;
-webkit-user-select: none;
user-select: none;
pointer-events: none;
&.active {
display: block;
}
&.inactive {
display: none;
}
}
.title {
margin-bottom: 0.5em;
text-align: center;
}
}
}
}
.snow .value {
display: inline-block;
min-width: 2em;
text-align: right;
}
.deals {
padding-bottom: 0;
.deal {
padding: 0.4em 0;
line-height: 1.5;
display: flex;
justify-content: space-between;
}
}
}
.resort .deal {
font-size: 0.9em;
margin-bottom: 0.5em;
padding: 0.5em 0;
border-bottom: solid 2px var(--color-overlay);
display: flex;
justify-content: space-between;
}
.stats {
.pie {
margin: 1em 0;
width: 294px;
height: 294px;
border-radius: 50%;
background-image: conic-gradient(
var(--color-open) 0 var(--open),
var(--color-hold) 0 var(--hold),
var(--color-scheduled) 0 var(--scheduled),
var(--color-closed) 0
);
}
footer .summary {
flex-direction: column;
li {
line-height: 2;
text-align: right;
width: 55%;
margin: 0 auto;
span:first-child {
float: left;
&::before {
margin-right: 0.5em;
}
}
span:last-child {
float: right;
}
}
}
}
.about {
--bg-color: var(--color-panel-bg);
background-color: var(--bg-color);
box-sizing: border-box;
padding: 1em;
max-width: 120ch;
h1 {
font-size: 1.2em;
}
p {
margin: 0.5em 0;
line-height: 1.5em;
[class^="ls-"]::before,
[class*=" ls-"]::before {
color: var(--color-link);
text-shadow: 1px 1px var(--color-white);
margin-right: 0.2em;
}
}
footer a {
font-size: 0.9em;
color: var(--color-white);
text-shadow: 0 -1px var(--color-overlay);
display: block;
float: right;
padding: 0.3em 0.5em;
--bg-color: var(--color-button-primary);
background-color: var(--bg-color);
&:hover {
--bg-color: var(--color-button-hover);
}
}
}
.tags {
list-style: none;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0 8px;
li {
display: block;
float: left;
position: relative;
font-size: 0.9em;
margin-right: 1.2em;
margin-bottom: 0.6em;
&:last-child {
margin-right: 0;
}
}
a,
.count {
display: block;
box-sizing: border-box;
}
a {
color: var(--color-link);
text-shadow: 0 1px var(--color-white);
padding: 5px 6px 5px 7px;
--bg-color: var(--color-panel-bg);
background-color: var(--bg-color);
.count {
position: absolute;
top: 0;
left: 100%;
z-index: 2;
overflow: hidden;
max-width: 0;
padding: 5px 0 5px 2px;
color: var(--color-white);
text-shadow: 0 -1px var(--color-overlay);
--bg-color: var(--color-button-primary);
background-color: var(--bg-color);
opacity: 0.95;
transition-duration: 0.3s;
transition-timing-function: ease-out;
transition-property: padding, max-width;
}
&:hover .count {
padding: 5px 7px 5px 6px;
max-width: 40px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
}
}
}
.content {
margin: var(--column-gutter) auto;
gap: var(--column-gutter);
display: grid;
grid-template-columns: repeat(auto-fit, var(--column-width));
justify-content: center;
justify-items: center;
align-items: start;
&.resorts {
display: grid-lanes;
}
&:has(> .tags),
&:has(> .about) {
grid-template-columns: 1fr;
}
}
.widget {
font-size: 0.8em;
.panel {
width: 100%;
margin: 0;
display: block;
.lifts {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(25ch, 1fr));
gap: 0 var(--column-gutter);
}
}
&.naked .panel {
background-color: transparent;
padding: 0;
}
}
@media screen and (max-width: 720px) {
body > footer {
font-size: 1.3em;
.text {
display: none;
}
}
}
@media screen and (max-width: 400px) {
.extras {
&.desktop {
display: none;
img {
display: none;
}
}
&.mobile {
display: block;
img {
display: block;
}
}
}
}