Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div id="game" class="game">
</div>

<div class="title">DUCKY<br />FOG</div>

<div id="level-text" class="level-text">0</div>

<div id="water-level" class="water-level"></div>

<div id="controls" class="controls">
  <div id="top" class="controls__arrow controls__arrow--top"></div>
  <div id="left" class="controls__arrow controls__arrow--left"></div>
  <div id="right" class="controls__arrow controls__arrow--right"></div>
  <div id="bottom" class="controls__arrow controls__arrow--bottom"></div>
</div>

<div id="fullscreen" class="fullscreen"><svg fill="#FFF" width="1.3rem" height="1.3rem" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
    <path d="M14 3.414L9.414 8 14 12.586v-2.583h2V16h-6v-1.996h2.59L8 9.414l-4.59 4.59H6V16H0v-5.997h2v2.583L6.586 8 2 3.414v2.588H0V0h16v6.002h-2V3.414zm-1.415-1.413H10V0H6v2H3.415L8 6.586 12.585 2z" fill-rule="evenodd" />
  </svg></div>

<div id="refresh" class="refresh"><svg fill="#fff" width="2rem" height="2rem" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
    <path d="M27.1 14.313V5.396L24.158 8.34c-2.33-2.325-5.033-3.503-8.11-3.503C9.902 4.837 4.901 9.847 4.899 16c.001 6.152 5.003 11.158 11.15 11.16 4.276 0 9.369-2.227 10.836-8.478l.028-.122h-3.23l-.022.068c-1.078 3.242-4.138 5.421-7.613 5.421a8 8 0 0 1-5.691-2.359A7.993 7.993 0 0 1 8 16.001c0-4.438 3.611-8.049 8.05-8.049 2.069 0 3.638.58 5.924 2.573l-3.792 3.789H27.1z" />
  </svg></div>

<div id="over-text" class="over-text"></div>

<div id="level-selector" class="level-selector"></div>

<div id="intro" class="intro">
  <span class="intro__earth">DUCKY<br /></span>
  <span class="intro__title">DUCKY<br />FOG</span>
  <span class="intro__subtitle">around the world</span>
  <span class="intro__button">Play</span>
  <svg class="intro__player" height="800px" width="800px xmlns=" http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve">
    <g>
      <path style="fill:#ff7d66;" d="M90.465,186.912c0.086-7.581-5.26-27.49,2.771-43.781c8.025-16.291-42.226-20.546-67.682,0.367
		c-24.51,20.137,1.764,37.468,17.938,33.657C76.267,169.428,90.299,202.261,90.465,186.912z" />
      <path style="fill:#ff7d66;" d="M73.315,96.009c0.079,7.574-5.26,27.483,2.764,43.782c8.025,16.277-46.799,25.105-67.674-0.375
		c-20.878-25.48,1.76-37.461,17.941-33.65C59.102,113.485,73.137,80.654,73.315,96.009z" />
      <path class="game__player-body" style="fill:#fff07f;" d="M76.45,264.211c18.183-21.406,33.092-31.038,20.821-50.433
		c-23.402-23.408-34.309-48.743-34.309-84.458c0-35.709,14.476-68.035,37.876-91.436C124.243,14.483,156.563,0,192.278,0
		s68.035,14.483,91.443,37.884c23.401,23.402,37.87,55.728,37.87,91.436c0,52.789-42.222,95.011-42.222,121.4
		c-2.64,10.561,15.835,23.761,39.582,23.761c23.761,0,102.932,18.467,160.988-58.063c15.28-21.122,33.755-9.238,31.675,21.107
		C509.618,266.609,493.133,512,318.951,512c-50.135,0-43.788,0-139.874,0c-40.074,0-76.36-16.25-102.627-42.513
		c-26.273-26.27-42.52-62.554-42.52-102.649C33.93,326.765,50.176,290.474,76.45,264.211" />
      <path class="game__player-wing" style="fill:#dccc49;" d="M219.533,340.458h193.216c21.108,0,26.388,36.941-7.92,58.063c0,26.38-13.201,65.97-52.782,65.97
		c-39.596,0-87.092,0-121.4,0c-34.316,0-58.064-39.59-58.064-63.337C172.584,377.399,195.777,340.458,219.533,340.458z" />
      <path class="game__player-wing" style="fill:#F5FCCD;" d="M206.331,324.616h193.218c21.108,0,26.388,36.949-7.92,58.064c0,26.395-13.194,65.983-52.776,65.983
		c-39.589,0-87.097,0-121.406,0s-58.057-39.589-58.057-63.344C159.39,361.565,182.583,324.616,206.331,324.616z" />
      <path class="game__player-eye" style="fill:#FFFFFF;" d="M159.39,109.522c0,16.77-13.596,30.359-30.348,30.359c-16.763,0-30.355-13.589-30.355-30.359
		c0-16.748,13.592-30.344,30.355-30.344C145.794,79.177,159.39,92.773,159.39,109.522z" />
      <path class="game__player-eye" style="fill:#000038;" d="M143.556,109.522c0,8.025-6.503,14.525-14.514,14.525c-8.018,0-14.518-6.5-14.518-14.525
		c0-8.003,6.5-14.503,14.518-14.503C137.052,95.018,143.556,101.518,143.556,109.522z" />
    </g>
  </svg>
</div>

<div class="drawer" style="display:none;">
  <svg id="player" class="game__player" height="800px" width="800px xmlns=" http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve">
    <g>
      <path style="fill:#ff7d66;" d="M90.465,186.912c0.086-7.581-5.26-27.49,2.771-43.781c8.025-16.291-42.226-20.546-67.682,0.367
		c-24.51,20.137,1.764,37.468,17.938,33.657C76.267,169.428,90.299,202.261,90.465,186.912z" />
      <path style="fill:#ff7d66;" d="M73.315,96.009c0.079,7.574-5.26,27.483,2.764,43.782c8.025,16.277-46.799,25.105-67.674-0.375
		c-20.878-25.48,1.76-37.461,17.941-33.65C59.102,113.485,73.137,80.654,73.315,96.009z" />
      <path class="game__player-body" style="fill:#fff07f;" d="M76.45,264.211c18.183-21.406,33.092-31.038,20.821-50.433
		c-23.402-23.408-34.309-48.743-34.309-84.458c0-35.709,14.476-68.035,37.876-91.436C124.243,14.483,156.563,0,192.278,0
		s68.035,14.483,91.443,37.884c23.401,23.402,37.87,55.728,37.87,91.436c0,52.789-42.222,95.011-42.222,121.4
		c-2.64,10.561,15.835,23.761,39.582,23.761c23.761,0,102.932,18.467,160.988-58.063c15.28-21.122,33.755-9.238,31.675,21.107
		C509.618,266.609,493.133,512,318.951,512c-50.135,0-43.788,0-139.874,0c-40.074,0-76.36-16.25-102.627-42.513
		c-26.273-26.27-42.52-62.554-42.52-102.649C33.93,326.765,50.176,290.474,76.45,264.211" />
      <path class="game__player-wing" style="fill:#dccc49;" d="M219.533,340.458h193.216c21.108,0,26.388,36.941-7.92,58.063c0,26.38-13.201,65.97-52.782,65.97
		c-39.596,0-87.092,0-121.4,0c-34.316,0-58.064-39.59-58.064-63.337C172.584,377.399,195.777,340.458,219.533,340.458z" />
      <path class="game__player-wing" style="fill:#F5FCCD;" d="M206.331,324.616h193.218c21.108,0,26.388,36.949-7.92,58.064c0,26.395-13.194,65.983-52.776,65.983
		c-39.589,0-87.097,0-121.406,0s-58.057-39.589-58.057-63.344C159.39,361.565,182.583,324.616,206.331,324.616z" />
      <path class="game__player-eye" style="fill:#FFFFFF;" d="M159.39,109.522c0,16.77-13.596,30.359-30.348,30.359c-16.763,0-30.355-13.589-30.355-30.359
		c0-16.748,13.592-30.344,30.355-30.344C145.794,79.177,159.39,92.773,159.39,109.522z" />
      <path class="game__player-eye" style="fill:#000038;" d="M143.556,109.522c0,8.025-6.503,14.525-14.514,14.525c-8.018,0-14.518-6.5-14.518-14.525
		c0-8.003,6.5-14.503,14.518-14.503C137.052,95.018,143.556,101.518,143.556,109.522z" />
    </g>
  </svg>
  <div id="water" class="game__water game__water--0">
    <div class="game__water--bottom"></div>
    <div class="game__water--left"></div>
    <div class="game__water--right"></div>
    <div class="game__water--top"></div>
    <div class="game__water--front"></div>
  </div>
  <div id="rock" class="game__cell game__cell--rock">
    <div class="game__cell--rock-face game__cell--rock-left"></div>
    <div class="game__cell--rock-face game__cell--rock-right"></div>
    <div class="game__cell--rock-face game__cell--rock-top"></div>
    <div class="game__cell--rock-face game__cell--rock-bottom"></div>
    <div class="game__cell--rock-face game__cell--rock-front"></div>
  </div>
</div>
              
            
!

CSS

              
                @import url("https://fonts.googleapis.com/css2?family=Titan+One&display=swap");

$green: #80c0a1;
$yellow: #f5fccd;
$high-yellow: #fff07f;
$red: #ff7d66;
$black: #000038;
$white: #fff;
$pink: #eb80b1;
$light-blue: #78d6c6;
$blue: #419197;
$dark-blue: #12486b;
$orange: orange;
$grey: #919ea3;
$dark-grey: #66777f;

html {
  font-size: 3vh;
  @media (orientation: portrait) {
    font-size: 2.9vw;
  }
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  color: $white;
  background: radial-gradient($blue, $blue 60%, $white 300%);
  overflow: hidden;
  font-family: "Titan One", sans-serif;
  font-weight: 700;
  font-size: 1.5rem;
}

.game {
  $component-class: &;
  position: relative;
  display: flex;
  flex-wrap: wrap;
  width: 29.03rem; // .03 for errors when summing cells on Mozilla
  transition: transform 0.5s ease;
  border: 1px solid $blue;
  overflow: hidden;
  perspective: 20rem;
  transform-style: preserve-3d;
  transform-origin: center center 0;
  border-radius: 0.5rem;
  background-color: $light-blue;
  &:before,
  &:after {
    content: "";
    display: flex;
    position: absolute;
    z-index: -1;
    top: 0;
    width: var(--cell);
    height: 100%;
    background: red;
    transform-style: preserve-3d;
    transform-origin: center center 0;
    background-color: rgba($blue, 0.5);
    outline: 1px solid $white;
  }
  &:before {
    left: 0;
    transform: translateZ(calc(-0.5 * var(--cell)))
      translateX(calc(-0.5 * var(--cell))) rotate3d(0, 1, 0, 90deg);
  }
  &:after {
    right: 0;
    transform: translateZ(calc(-0.5 * var(--cell)))
      translateX(calc(0.5 * var(--cell))) rotate3d(0, 1, 0, 90deg);
  }
  &__player {
    position: absolute;
    z-index: 999;
    width: calc(var(--cell) * 0.8);
    height: calc(var(--cell) * 0.8);
    top: calc((var(--positionTop) + 0.1) * var(--cell));
    left: calc((var(--positionLeft) + 0.1) * var(--cell));
    transition-property: top, left, transform;
    transition-duration: 0.2s;
    transition-timing-function: ease;
    transform: var(--rotation) translateZ(0);
    &-eye {
      transform-origin: 50% 20%;
      @keyframes blink {
        0%,
        40%,
        60%,
        100% {
          transform: scaleY(1);
        }
        50% {
          transform: scaleY(0.2);
        }
      }
      animation: blink;
      animation-duration: 2s;
      animation-iteration-count: infinite;
    }
    @media (max-width: 767px) {
      transition-duration: 0.1s;
    }
  }
  &__cell {
    position: relative;
    z-index: -1;
    width: var(--cell);
    height: var(--cell);
    background: linear-gradient(135deg, $light-blue, $white 200%);
    outline: 1px solid $white;
    transform: translateZ(calc(-1 * var(--cell)));
    &--rock {
      $rock: &;
      position: relative;
      transform: translateZ(0);
      transform-style: preserve-3d;
      transform-origin: center center 0;
      background: none;
      outline: none;
      &-face {
        position: absolute;
        display: flex;
        background: linear-gradient(135deg, $grey, $white 200%);
        border-radius: 0.1rem;
        outline: 1px solid $grey;
      }
      &-lava #{$rock}-face {
        background: linear-gradient(45deg, $orange, $red 200%);
        background-size: 100% 200%;
        @keyframes lava {
          0%,
          100% {
            background-position: 0 0;
          }
          50% {
            background-position: 0 100%;
          }
        }
        animation: lava;
        animation-duration: 2s;
        animation-iteration-count: infinite;
        outline: 1px solid $red;
      }
      &-front {
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
      }
      &-top,
      &-bottom,
      &-left,
      &-right {
        width: 100%;
        height: var(--cell);
      }
      &-top {
        top: 0;
        left: 0;
        transform: translateZ(calc(-0.5 * var(--cell)))
          translateY(calc(-0.5 * var(--cell))) rotate3d(1, 0, 0, 90deg);
      }
      &-bottom {
        bottom: 0;
        left: 0;
        transform: translateZ(calc(-0.5 * var(--cell)))
          translateY(calc(0.5 * var(--cell))) rotate3d(1, 0, 0, 90deg);
      }
      &-left {
        top: 0;
        left: 0;
        transform: translateZ(calc(-0.5 * var(--cell)))
          translateY(calc(-0.5 * var(--cell)))
          translateX(calc(var(--cell) / -2)) rotate3d(1, 0, 0, 90deg)
          rotate3d(0, 1, 0, 90deg) translateX(calc(var(--cell) / 2));
      }
      &-right {
        top: 0;
        left: 0;
        transform: translateZ(calc(-0.5 * var(--cell)))
          translateY(calc(-0.5 * var(--cell)))
          translateX(calc(var(--cell) / -2)) rotate3d(1, 0, 0, 90deg)
          rotate3d(0, 1, 0, 90deg) translateX(calc(var(--cell) / 2))
          translateZ(var(--cell));
      }
    }
    &--horizontal {
      z-index: 0;
      transform: translateZ(calc(var(--cell) * -0.8));
      background: linear-gradient(135deg, $light-blue, $pink 200%);
      &:before,
      &:after {
        content: "";
        position: absolute;
        width: 0;
        height: 0;
        border-top: calc(var(--cell) / 4) solid transparent;
        border-bottom: calc(var(--cell) / 4) solid transparent;
      }
      &:before {
        bottom: calc(var(--cell) / 6);
        left: calc(var(--cell) / 6);
        border-left: calc(var(--cell) / 3) solid $white;
      }
      &:after {
        top: calc(var(--cell) / 6);
        right: calc(var(--cell) / 6);
        border-right: calc(var(--cell) / 3) solid $white;
      }
    }
    &--vertical {
      z-index: 0;
      transform: translateZ(calc(var(--cell) * -0.8));
      background: linear-gradient(135deg, $light-blue, $orange 200%);
      &:before,
      &:after {
        content: "";
        position: absolute;
        width: 0;
        height: 0;
        border-left: calc(var(--cell) / 4) solid transparent;
        border-right: calc(var(--cell) / 4) solid transparent;
      }
      &:before {
        bottom: calc(var(--cell) / 6);
        left: calc(var(--cell) / 6);
        border-bottom: calc(var(--cell) / 3) solid $white;
      }
      &:after {
        top: calc(var(--cell) / 6);
        right: calc(var(--cell) / 6);
        border-top: calc(var(--cell) / 3) solid $white;
      }
    }
    &--end {
      background-color: $white;
      background-image: linear-gradient(
          45deg,
          $black 25%,
          transparent 25%,
          transparent 74%,
          $black 75%,
          $black
        ),
        linear-gradient(
          45deg,
          $black 25%,
          transparent 25%,
          transparent 74%,
          $black 75%,
          $black
        );
      background-size: calc(var(--cell) / 2) calc(var(--cell) / 2);
      background-position: 0 0, calc(var(--cell) / 4) calc(var(--cell) / 4);
    }
  }
  &__wrapper {
    position: relative;
  }
  &__water {
    $water: &;
    position: absolute;
    transition-property: width, height;
    transition-duration: 0.2s;
    transition-timing-function: ease;
    transform-style: preserve-3d;
    &--0,
    &--2 {
      width: 100%;
      height: calc(var(--depth) * var(--cell));
    }
    &--1,
    &--3 {
      height: 100%;
      width: calc(var(--depth) * var(--cell));
    }
    &--0,
    &--3 {
      bottom: 0;
      left: 0;
    }
    &--1 {
      bottom: 0;
      right: 0;
    }
    &--2 {
      top: 0;
      left: 0;
    }
    &--front {
      position: relative;
      z-index: 2;
      width: 100%;
      height: 100%;
      background-color: rgba($blue, 0.6);
      transform: translateZ(0);
    }
    &--top,
    &--left,
    &--right,
    &--bottom {
      position: absolute;
      display: flex;
      background: linear-gradient(45deg, rgba($blue, 0.5), $white 200%);
    }
    &--top,
    &--bottom {
      width: 100%;
      height: var(--cell);
      transform-origin: center 0 0;
    }
    &--left,
    &--right {
      width: var(--cell);
      height: 100%;
      transform-origin: center center 0;
    }
    &--top {
      top: 0;
      left: 0;
      transform: translateZ(calc(-1 * var(--cell))) rotate3d(1, 0, 0, 90deg);
    }
    &--left {
      top: 0;
      left: 0;
      transform: translateZ(calc(-0.5 * var(--cell)))
        translateX(calc(-0.5 * var(--cell))) rotate3d(0, 1, 0, 90deg);
    }
    &--right {
      top: 0;
      right: 0;
      transform: translateZ(calc(-0.5 * var(--cell)))
        translateX(calc(0.5 * var(--cell))) rotate3d(0, 1, 0, 90deg);
    }
    &--bottom {
      bottom: 0;
      left: 0;
      transform: translateZ(calc(-1 * var(--cell)))
        translateY(calc(var(--cell))) rotate3d(1, 0, 0, 90deg);
    }
  }
}

.title {
  position: absolute;
  top: 1rem;
  left: 1rem;
  color: $high-yellow;
  //font-size: 1.2rem;
}

.level-text {
  position: absolute;
  top: 1rem;
  right: 1rem;
  &:before {
    content: "\0062\0079\ \0050\0045\0044\0052\004F\ \004F\004E\0044\0049\0056\0049\0045\004C\0041";
    position: absolute;
    right: 0;
    bottom: calc(4rem - 100vh);
    font-size: 0.5rem;
    text-align: right;
  }
}

.water-level {
  position: absolute;
  top: calc(50vh - var(--height) * var(--cell) * 0.5);
  right: calc(50vw - var(--width) * var(--cell) * 0.5 - 0.15rem);
  display: flex;
  width: 0.3rem;
  height: calc(var(--height) * var(--cell));
  background: linear-gradient($light-blue 50%, transparent 50%);
  background-size: 100% 200%;
  background-position: 0 calc(100% + (var(--depth) / var(--height) * 100%));
  transition: all 0.2s ease;
  &:before,
  &:after {
    content: "";
    position: absolute;
    left: -0.15rem;
    width: 5rem;
    color: $white;
    font-size: 1rem;
  }
  &:before {
    content: "min -";
    top: calc(100% - (var(--min-depth) / var(--height) * 100%) - 0.7rem);
    left: -2.35rem;
  }
  &:after {
    content: "- max";
    top: calc(100% - (var(--max-depth) / var(--height) * 100%) - 0.7rem);
  }
  &--hidden {
    display: none;
  }
}

.over-text {
  $overText: &;
  position: absolute;
  top: 0;
  left: 0;
  display: none;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 100vh;
  color: $white;
  background-color: rgba($blue, 0.5);
  text-align: center;
  text-transform: uppercase;
  &--display {
    display: flex;
  }
  &--lose {
    color: $black;
    background-color: rgba($red, 0.5);
  }
  &--win {
    display: flex;
    flex-direction: column;
    font-size: 10vw;
    color: $dark-blue;
    background-color: rgba($yellow, 0.5);
    #{$overText}__timer {
      font-size: 5vw;
    }
  }
  &--tutorial {
    color: $dark-blue;
    background: rgba(white, 0.3);
    top: unset;
    bottom: 0;
    height: 4rem;
    pointer-events: none;
  }
}

.controls {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  height: 100%;
  &__arrow {
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    &:after {
      content: "";
      width: 0;
      height: 0;
      margin: 1rem;
      opacity: 0.3;
    }
    &--top,
    &--bottom {
      width: 100%;
      height: 40vh;
    }
    &--left,
    &--right {
      flex-direction: column;
      width: 50%;
      height: 20vh;
    }
    &--top,
    &--left {
      align-items: flex-start;
    }
    &--bottom,
    &--right {
      align-items: flex-end;
    }
    &--top:after {
      border-left: 1rem solid transparent;
      border-right: 1rem solid transparent;
      border-bottom: 1rem solid $white;
    }
    &--left:after {
      border-left: 1rem solid transparent;
      border-right: 1rem solid transparent;
      border-top: 1rem solid $white;
      transform: rotate(45deg);
    }
    &--right:after {
      border-left: 1rem solid transparent;
      border-right: 1rem solid transparent;
      border-top: 1rem solid $white;
      transform: rotate(-45deg);
    }
    &--bottom:after {
      border-left: 1rem solid transparent;
      border-right: 1rem solid transparent;
      border-top: 1rem solid $white;
    }
  }
}

.intro {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
  padding: 1rem;
  color: $high-yellow;
  background-color: $blue;
  cursor: pointer;
  &__title {
    font-size: 4rem;
  }
  &__subtitle {
    color: $yellow;
  }
  &__explanation {
    position: absolute;
    bottom: 3rem;
    left: 1rem;
    width: calc(100vw - 2rem);
    font-size: 1.5rem;
    text-align: right;
    color: $white;
  }
  &__player {
    position: absolute;
    top: 10rem;
    right: 0;
    width: 40vw;
    height: 40vh;
    transform: rotate(10deg);
  }
  &__button {
    position: absolute;
    bottom: 30vh;
    left: 40vw;
    display: inline-flex;
    justify-content: center;
    width: 20vw;
    padding: 0.5rem 1rem;
    border-radius: 2rem;
    color: $dark-blue;
    background: $high-yellow;
    outline: 2px solid $dark-blue;
    transition: transform 0.2s ease;
    &:hover {
      transform: scale(1.2);
    }
  }
  &__earth {
    position: absolute;
    top: 30vh;
    left: 15vw;
    width: 70vw;
    height: 70vw;
    border-radius: 50%;
    background-color: $dark-blue;
    transform: rotate(10deg);
    overflow: hidden;
    @media (max-width: 767px) {
      width: 120vw;
      height: 120vw;
      left: -10vw;
    }
    &:before {
      content: "";
      display: block;
      width: 100%;
      height: 100%;
      background: url("https://www.pedro-ondiviela.com/assets/map.svg");
      background-size: cover;
      transition: background-position 0.5s ease;
      @keyframes globeSpinning {
        0% {
          background-position: 0 0;
        }

        100% {
          background-position: 288% 0;
        }
      }
      animation: globeSpinning;
      animation-duration: 300s;
      animation-iteration-count: infinite;
      animation-timing-function: linear;
    }
  }
  &--hidden {
    display: none;
  }
}

.fullscreen {
  position: absolute;
  top: 1.2rem;
  right: 7rem;
  cursor: pointer;
}

.refresh {
  position: absolute;
  top: 1rem;
  right: 4rem;
  cursor: pointer;
}

.level-selector {
  position: absolute;
  top: 0;
  left: 0;
  width: 80vw;
  height: 100vh;
  padding: 0 10vw;
  color: $white;
  background-color: rgba($blue, 0.5);
  font-size: 2rem;
  display: none;
  @media (min-height: 600px) {
    font-size: 1.5rem;
  }
  &--active {
    display: flex;
    justify-content: center;
    align-items: center;
    align-content: center;
    flex-wrap: wrap;
  }
  &__button {
    padding: 1rem;
    border-radius: 0.5rem;
    cursor: pointer;
    transition: background-color 0.2s ease;
    &:hover {
      background-color: rgba($black, 0.2);
    }
    &--current {
      background-color: $dark-blue;
    }
    &--disabled {
      opacity: 0.5;
      cursor: default;
      pointer-events: none;
    }
  }
}

              
            
!

JS

              
                const game = document.getElementById("game");
const player = document.getElementById("player");
const water = document.getElementById("water");
const rock = document.getElementById("rock");
const overText = document.getElementById("over-text");
const levelText = document.getElementById("level-text");
const waterLevel = document.getElementById("water-level");
const intro = document.getElementById("intro");
const topArrow = document.getElementById("top");
const leftArrow = document.getElementById("left");
const rightArrow = document.getElementById("right");
const bottomArrow = document.getElementById("bottom");
const refresh = document.getElementById("refresh");
const fullscreen = document.getElementById("fullscreen");
const levelSelector = document.getElementById("level-selector");

let level = 0;
let width = 29;
const puzzles = [
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["-----", "-----", "--e--", "-ox--", "--x--"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 3,
    level: ["------", "------", "---e--", "--xx--", "-o-x--", "---x--"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["-----", "-----", "-e---", "---xx", "---ox", "----x"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["--xxx-", "-----x", "-x-x--", "---xex", "---oxx", "----xx"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 4,
    level: [
      "----xxx-",
      "-------x",
      "---x-x--",
      "-xx--xex",
      "xx---oxx",
      "xx----xx"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 6,
    level: [
      "----xxe",
      "----xx-",
      "xx-----",
      "----xx-",
      "----xx-",
      "-o--xx-",
      "----xx-"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: [
      "x---xxx",
      "x-----x",
      "x-xxx-x",
      "xe--x-x",
      "x-x-x-x",
      "xox---x",
      "x-xxxxx"
    ]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 2,
    level: [
      "x--exxx",
      "x-xx--x",
      "x-x---x",
      "x---x-x",
      "xxxxx-x",
      "x-----x",
      "xoxxxxx"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["x--exxx", "xo----x", "x-xxxxx"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 1,
    level: ["-x-", "---", "oxe"]
  },
  {
    initialDepth: 1,
    minDepth: 0,
    maxDepth: 3,
    level: ["-x--x--", "-------", "-x--x--", "---ox--", "-x--xe-"]
  },
  {
    initialDepth: 3,
    minDepth: 0,
    maxDepth: 3,
    level: [
      "-x--x--",
      "-------",
      "-x--x--",
      "---ox--",
      "-x--xx-",
      "-x--x--",
      "-x--xe-"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 0,
    maxDepth: 1,
    level: [
      "-xxx--x--",
      "x-------x",
      "xx-xx-x--",
      "----xx---",
      "-x--x--xx",
      "-x-ox-x--",
      "-x--x--e-"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 6,
    level: [
      "xxx--x--xx",
      "--------xx",
      "x-xx-xx---",
      "---xx-xx--",
      "x--xxx---x",
      "x-oxex-xx-",
      "x--x----xx"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: [
      "x-----x",
      "-x---x-",
      "-------",
      "-------",
      "--x-x--",
      "oxe----",
      "x-----x"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: [
      "x--xx---x",
      "-x-xx--x-",
      "---------",
      "---xx----",
      "--xxx-x--",
      "oxe------",
      "x---xx--x"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 1,
    level: [
      "x-----x",
      "--x--x-",
      "-e-----",
      "----x--",
      "-x-x---",
      "ox----x",
      "----xxx"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 0,
    maxDepth: 1,
    level: ["-----", "---e-", "-xxx-", "--o--", "-----"]
  },
  {
    initialDepth: 3,
    minDepth: 3,
    maxDepth: 4,
    level: ["------", "----x-", "--o---", "---x--", "----e-", "-x----"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 0,
    level: ["xx---x", "----x-", "-xx---", "---xx-", "e-----", "ox-x--"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 0,
    level: ["xx---x", "------", "-xx---", "-e-x-x", "x-----", "-xox--"]
  },
  {
    initialDepth: 6,
    minDepth: 3,
    maxDepth: 6,
    level: [
      "-------x",
      "-x----xo",
      "--------",
      "---x----",
      "x---x---",
      "--x----x",
      "--e--xxx"
    ]
  },
  {
    initialDepth: 3,
    minDepth: 1,
    maxDepth: 3,
    level: [
      "x--x--x",
      "-x---x-",
      "---x---",
      "---x--o",
      "x------",
      "-xx--ex",
      "----x-x"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: [
      "x-x--x--x",
      "-x--x--x-",
      "-----x---",
      "--x--x---",
      "x--------",
      "-xx-x--ex",
      "----x-x-x",
      "xxo-x-x-x",
      "------x-x"
    ]
  },
  {
    initialDepth: 6,
    minDepth: 5,
    maxDepth: 6,
    level: [
      "x-x--x--x",
      "-x--x--x-",
      "---o-x---",
      "--x--x---",
      "x--------",
      "-xx-x---x",
      "----x-e-x",
      "xx--x-x-x",
      "------x-x"
    ]
  },
  {
    initialDepth: 2,
    minDepth: 2,
    maxDepth: 2,
    level: ["-------", "--x----", "--oe---", "-------"]
  },
  {
    initialDepth: 6,
    minDepth: 6,
    maxDepth: 6,
    level: [
      "---e----",
      "--------",
      "--x----x",
      "--x-x---",
      "----o---",
      "--x-----",
      "----x---"
    ]
  },
  {
    initialDepth: 5,
    minDepth: 5,
    maxDepth: 5,
    level: [
      "xxx--x",
      "xx---x",
      "x--x-x",
      "x---ex",
      "x-x--x",
      "xx---x",
      "xo-xxx"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 4,
    level: ["-----", "-----", "-l-e-", "-o---", "-----"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["-l---", "l--e-", "--l--", "--ol-", "---l-"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["xxxl-x", "xxxl-x", "xlll-x", "x---ex", "xo-lxx", "x--lxx"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["--l--", "--l--", "-l-e-", "-o-l-", "---l-"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 3,
    level: [
      "l---lll",
      "l-----l",
      "l-lll-l",
      "l-lel-l",
      "l-l-l-l",
      "l-l-l-l",
      "lol---l",
      "l-lllll"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 3,
    level: [
      "l---lll",
      "l-l---l",
      "l-lll-l",
      "l-e-l-l",
      "l-l-l-l",
      "lol---l",
      "l-lllll"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["l---lll", "l-l---l", "l----ll", "l-l---l", "lol-lel", "l-lllll"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 4,
    level: [
      "l-ll---ll",
      "l----l--l",
      "l-l----ll",
      "l-l--l--l",
      "l-l-ll--l",
      "lo--le--l",
      "l---lllll"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 2,
    level: ["l-l----ll", "lo--l--el", "l------ll"]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 4,
    level: [
      "l-l-lllll",
      "l-----lll",
      "l---l--ll",
      "l--lll-ll",
      "l-o--l-el",
      "l---ll-ll"
    ]
  },
  {
    initialDepth: 6,
    minDepth: 6,
    maxDepth: 6,
    level: [
      "xxxxxlll",
      "oxe---xl",
      "--lx---l",
      "x---ll--",
      "x-------",
      "xxxlllll"
    ]
  },
  {
    initialDepth: 3,
    minDepth: 2,
    maxDepth: 3,
    level: ["x---x-ol", "-x----xl", "--l--l--", "x-e-----", "xxxlllll"]
  },
  {
    initialDepth: 2,
    minDepth: 1,
    maxDepth: 2,
    level: ["llllll", "xe-xxx", "ll--ll", "xxx--x", "llll-o", "xxxxx-"]
  },
  {
    initialDepth: 2,
    minDepth: 1,
    maxDepth: 2,
    level: [
      "llllllll",
      "xx----xx",
      "ll-ll-ll",
      "xxexx-xx",
      "llll---o",
      "xxxxxxx-"
    ]
  },
  {
    initialDepth: 2,
    minDepth: 0,
    maxDepth: 4,
    level: [
      "le--------l",
      "x-llll---xx",
      "l--lll-l-ll",
      "xx-----x-xx",
      "llll-l-l--o",
      "xxxxxlllxx-"
    ]
  },
  {
    initialDepth: 8,
    minDepth: 8,
    maxDepth: 8,
    level: [
      "lx------elx",
      "ll--xxlllll",
      "ll----lllll",
      "llxxx-xxxxl",
      "xl-------xx",
      "l--ll-ll-ll",
      "xx-----x-xx",
      "ll----xl--o",
      "xxxxxlllxx-"
    ]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 2,
    level: ["-e-", "hhv", "-o-"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 2,
    level: ["hhv--", "-ev--", "hhv--", "-o---"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 2,
    level: ["hhvvv", "hevhh", "hhhvv", "-ohhv"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 2,
    level: ["hvhhvvv", "hevhhhh", "vvhhhvv", "-hhohhv"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 2,
    level: ["e-hh-", "vhvhv", "-l-hl", "hvhvh", "--o--"]
  },
  {
    initialDepth: 1,
    minDepth: 0,
    maxDepth: 1,
    level: ["hhvheh", "hvhvhv", "vvvvvv", "hhhohh", "------"]
  },
  {
    initialDepth: 1,
    minDepth: 0,
    maxDepth: 2,
    level: ["xxllhev", "xvx--lv", "xvh--lv", "xh-l-hh", "x--llo-", "xvhh--l"]
  },
  {
    initialDepth: 0,
    minDepth: 0,
    maxDepth: 2,
    level: ["hvhh", "vvvh", "vhvh", "-ove"]
  },
  {
    initialDepth: 1,
    minDepth: 0,
    maxDepth: 1,
    level: ["vhhvlh", "vv-hhh", "vhvllv", "-ohlev"]
  },
  {
    initialDepth: 2,
    minDepth: 0,
    maxDepth: 2,
    level: [
      "vh--hhxh",
      "vv-hl--h",
      "vlv--llv",
      "-oh--lev",
      "vv-hl--h",
      "vv-hh--h"
    ]
  },
  {
    initialDepth: 1,
    minDepth: 1,
    maxDepth: 1,
    level: ["xlohhev"]
  }
];

let rotation = 0;
let rotationPosition = 0;
let depth = 1;
let initialPosition = [];
let position = [];
let end = [];
let rocks = [];
let startTimer;

const getLevelInfo = () => {
  const currentLevel = puzzles[level];

  const rawWidth = puzzles[level].level[0].length;
  const rawHeight = puzzles[level].level.length;
  return {
    rawWidth,
    rawHeight,
    levelWidth: rawWidth - 1,
    levelHeight: rawHeight - 1,
    currentLevel
  };
};

const changeLevelStyle = () => {
  const { rawWidth, rawHeight, currentLevel } = getLevelInfo();
  game.style.transform = `rotate(${90 * rotation}deg)`;
  water.classList = `game__water game__water--${rotationPosition}`;
  water.style = `--depth: ${depth};`;
  waterLevel.style = `--depth: ${depth}; --width: ${
    rotationPosition % 2 === 0 ? rawWidth : rawHeight
  }; --height: ${
    rotationPosition % 2 === 0 ? rawHeight : rawWidth
  }; --min-depth: ${currentLevel.minDepth}; --max-depth: ${
    currentLevel.maxDepth
  };`;
};

const topFunction = () => changeWater(true);
const leftFunction = () => rotateLevel(false);
const rightFunction = () => rotateLevel(true);
const bottomFunction = () => changeWater(false);

const registerArrows = () => {
  topArrow.addEventListener("click", topFunction);
  leftArrow.addEventListener("click", leftFunction);
  rightArrow.addEventListener("click", rightFunction);
  bottomArrow.addEventListener("click", bottomFunction);
};

const removeArrowsEvents = () => {
  topArrow.removeEventListener("click", topFunction);
  leftArrow.removeEventListener("click", leftFunction);
  rightArrow.removeEventListener("click", rightFunction);
  bottomArrow.removeEventListener("click", bottomFunction);
};

const buildLevel = () => {
  if (level === 0) {
    startTimer = Date.now();
  }
  const {
    rawWidth,
    rawHeight,
    levelWidth,
    levelHeight,
    currentLevel
  } = getLevelInfo();
  // Adapt cell size to level
  document.body.style = `--cell: ${width / rawWidth}rem`;
  // Reset rocks
  rocks = [];
  currentLevel.level.forEach((row, rowIndex) => {
    const cells = row.split("");
    cells.forEach((cell, cellIndex) => {
      const newDiv = document.createElement("div");
      newDiv.classList.add("game__cell");
      if (cell === "o") {
        initialPosition = [cellIndex, rowIndex];
        position = [cellIndex, rowIndex];
        game.appendChild(newDiv);
      } else if (cell === "x" || cell === "l") {
        rocks.push([cellIndex, rowIndex, cell === "x" ? "rock" : "lava"]);
        const rockClone = rock.cloneNode(true);
        rockClone.id = "";
        if (cell === "l") {
          rockClone.classList.add("game__cell--rock-lava");
        }
        const xFactor =
          (cellIndex > levelWidth / 2 ? levelWidth - cellIndex : cellIndex) + 1;
        const yFactor =
          (rowIndex > levelHeight / 2 ? levelHeight - rowIndex : rowIndex) + 1;
        rockClone.style.zIndex = Math.round(xFactor * yFactor) + 3;
        game.appendChild(rockClone);
      } else if (cell === "h") {
        rocks.push([cellIndex, rowIndex, "horizontal"]);
        newDiv.classList.add("game__cell--horizontal");
        game.appendChild(newDiv);
      } else if (cell === "v") {
        rocks.push([cellIndex, rowIndex, "vertical"]);
        newDiv.classList.add("game__cell--vertical");
        game.appendChild(newDiv);
      } else if (cell === "e") {
        end = [cellIndex, rowIndex];
        newDiv.classList.add("game__cell--end");
        game.appendChild(newDiv);
      } else {
        game.appendChild(newDiv);
      }
    });
  });
  rotation = 0;
  rotationPosition = 0;
  levelText.innerHTML = level;
  depth = currentLevel.initialDepth;
  game.appendChild(water);
  changeLevelStyle();
  game.appendChild(player);
};

const positionPlayer = () => {
  player.style = `--positionLeft: ${position[0]}; --positionTop: ${
    position[1]
  }; --rotation: rotate(${-90 * rotation}deg)`;
};

const removeEvent = (e) => {
  e.preventDefault();
  e.stopPropagation();
};

const winLevel = () => {
  overText.classList.add("over-text--display");
  const winTexts = [
    "Well done! Next",
    "Ducktastic!",
    "You win!",
    "Amazing!",
    "Go go duck!",
    "You've got this!",
    "Keep going!",
    "Stay duck!",
    "Rotating to the next level...",
    "Best duck!",
    "You rock, duck!"
  ];
  overText.innerHTML = winTexts[Math.floor(Math.random() * winTexts.length)];
  document.addEventListener("keydown", removeEvent);
  removeArrowsEvents();
  setTimeout(() => {
    game.innerHTML = "";
    overText.classList.remove("over-text--display");
    level = level + 1;
    localStorage.setItem("ducky-fog", level);
    const maxLevel = localStorage.getItem("ducky-fog-max", level);
    localStorage.setItem("ducky-fog-max", maxLevel > level ? maxLevel : level);
    buildLevel();
    positionPlayer();
    document.removeEventListener("keydown", removeEvent);
    registerArrows();
  }, 500);
};

const loseLevel = () => {
  overText.classList.add("over-text--display");
  overText.classList.add("over-text--lose");
  const loseTexts = [
    "You lose! Repeat",
    "Oh no",
    "Uuuh",
    "Better duck next time",
    "You died",
    "Mamma mia",
    "Looosing",
    "That hurted",
    "Roasted duck!",
    "Burned",
    "Toasted"
  ];
  overText.innerHTML = loseTexts[Math.floor(Math.random() * loseTexts.length)];
  document.addEventListener("keydown", removeEvent);
  removeArrowsEvents();
  setTimeout(() => {
    game.innerHTML = "";
    overText.classList.remove("over-text--display");
    overText.classList.remove("over-text--lose");
    buildLevel();
    positionPlayer();
    document.removeEventListener("keydown", removeEvent);
    registerArrows();
  }, 500);
};

const nextLevel = () => {
  if (position[0] === end[0] && position[1] === end[1]) {
    if (level === puzzles.length - 1) {
      // If this was the last level: win the game
      overText.classList.add("over-text--display");
      overText.classList.add("over-text--win");
      if (startTimer) {
        const s = (Date.now() - startTimer) / 1000;
        overText.innerHTML = `The end!<br/><span class="over-text__timer">${parseInt(
          s / 60 / 60
        )}h ${parseInt((s / 60) % 60)}m ${parseInt(s % 60)}s</span>`;
      } else {
        overText.innerHTML = "The end!";
      }

      document.addEventListener("keydown", removeEvent);
      removeArrowsEvents();
    } else {
      winLevel();
    }
  }
};

const findRocks = (axis, perpendicularAxis, movingForward) => {
  const relevantRocks = rocks
    .filter((rock) => rock[axis] === position[axis]) // Filtering rocks in this axis
    .filter((rock) =>
      movingForward
        ? rock[perpendicularAxis] > position[perpendicularAxis]
        : rock[perpendicularAxis] < position[perpendicularAxis]
    ); // Filtering rocks that are in the desired direction

  const filteredRelevantRocks = relevantRocks.filter((rock) => {
    if (axis === 0 && rock[2] !== "vertical") {
      return rock;
    } else if (axis === 1 && rock[2] !== "horizontal") {
      return rock;
    }
  });

  if (filteredRelevantRocks.length) {
    // If there are rocks in this path
    const rockPosition = movingForward
      ? Math.min(
          ...filteredRelevantRocks.map((rock) => rock[perpendicularAxis])
        )
      : Math.max(
          ...filteredRelevantRocks.map((rock) => rock[perpendicularAxis])
        );
    const relevantRock = filteredRelevantRocks.filter(
      (rock) => rock[perpendicularAxis] === rockPosition
    )[0];

    const maxmin = movingForward ? rockPosition - 1 : rockPosition + 1;

    return { maxmin, rockPosition, relevantRock };
  }
  return { maxmin: undefined, rockPostion: undefined, relevantRock: undefined };
};

// true = right, false = left
const rotateLevel = (direction) => {
  const { levelWidth, levelHeight } = getLevelInfo();
  const y1 = position[1];
  const y2 = levelHeight - y1;
  const x1 = position[0];
  const x2 = levelWidth - x1;

  const next = [...position];

  const maxminCondition = (position, maxmin, next) => {
    return (
      maxmin !== undefined &&
      ((position >= maxmin && maxmin >= next) ||
        (position <= maxmin && maxmin <= next))
    );
  };

  if (rotationPosition === 0) {
    const next = direction ? levelWidth - depth : depth;
    const { maxmin, rockPosition, relevantRock } = findRocks(
      1,
      0,
      next - position[0] > 0
    );

    if (maxminCondition(position[0], maxmin, next)) {
      if (relevantRock[2] === "lava" && next !== maxmin) {
        position[0] = rockPosition;
        loseLevel();
      } else {
        position[0] = maxmin;
      }
    } else {
      position[0] = next;
    }
  } else if (rotationPosition === 1) {
    const next = direction ? depth : levelHeight - depth;
    const { maxmin, rockPosition, relevantRock } = findRocks(
      0,
      1,
      next - position[1] > 0
    );

    if (maxminCondition(position[1], maxmin, next)) {
      if (relevantRock[2] === "lava" && next !== maxmin) {
        position[1] = rockPosition;
        loseLevel();
      } else {
        position[1] = maxmin;
      }
    } else {
      position[1] = next;
    }
  } else if (rotationPosition === 2) {
    const next = direction ? depth : levelWidth - depth;
    const { maxmin, rockPosition, relevantRock } = findRocks(
      1,
      0,
      next - position[0] > 0
    );

    if (maxminCondition(position[0], maxmin, next)) {
      if (relevantRock[2] === "lava" && next !== maxmin) {
        position[0] = rockPosition;
        loseLevel();
      } else {
        position[0] = maxmin;
      }
    } else {
      position[0] = next;
    }
  } else {
    const next = direction ? levelHeight - depth : depth;
    const { maxmin, rockPosition, relevantRock } = findRocks(
      0,
      1,
      next - position[1] > 0
    );

    if (maxminCondition(position[1], maxmin, next)) {
      if (relevantRock[2] === "lava" && next !== maxmin) {
        position[1] = rockPosition;
        loseLevel();
      } else {
        position[1] = maxmin;
      }
    } else {
      position[1] = next;
    }
  }

  if (direction) {
    rotationPosition = (rotationPosition + 1) % 4;
  } else {
    rotationPosition = rotationPosition === 0 ? 3 : rotationPosition - 1;
  }

  waterLevel.classList.add("game__water-level--hidden");
  setTimeout(
    () => waterLevel.classList.remove("game__water-level--hidden"),
    300
  );

  rotation = direction ? rotation + 1 : rotation - 1;
  changeLevelStyle();
  positionPlayer();
  nextLevel();
};

// true = top, false = bottom
const changeWater = (direction) => {
  const { levelWidth, levelHeight, currentLevel } = getLevelInfo();
  // Avoid change if depth is max or min
  if (
    (direction && depth === currentLevel.maxDepth) ||
    (!direction && depth === currentLevel.minDepth)
  ) {
    return;
  }

  const y1 = position[1];
  const y2 = levelHeight - y1;
  const x1 = position[0];
  const x2 = levelWidth - x1;

  let playerOutWater = false;

  // Avoid change if depth doesnt match player
  playerOutWater =
    (rotationPosition === 0 && depth !== y2) ||
    (rotationPosition === 1 && depth !== x2) ||
    (rotationPosition === 2 && depth !== y1) ||
    (rotationPosition === 3 && depth !== x1);

  depth = direction ? depth + 1 : depth - 1;
  changeLevelStyle();

  if (playerOutWater) {
    return;
  }

  const next = [...position];

  if (rotationPosition === 0) {
    next[1] = direction ? position[1] - 1 : position[1] + 1;
  } else if (rotationPosition === 1) {
    next[0] = direction ? position[0] - 1 : position[0] + 1;
  } else if (rotationPosition === 2) {
    next[1] = direction ? position[1] + 1 : position[1] - 1;
  } else {
    next[0] = direction ? position[0] + 1 : position[0] - 1;
  }

  const relevantRock = rocks.find(
    (rock) => rock[0] === next[0] && rock[1] === next[1]
  );

  if (!relevantRock) {
    position = next;
  } else if (relevantRock[2] === "lava") {
    position = next;
    loseLevel();
  } else if (
    rotationPosition % 2 === 0
      ? relevantRock[2] === "vertical"
      : relevantRock[2] === "horizontal"
  ) {
    position = next;
  }
  positionPlayer();
  nextLevel();
};

const removeTutorial = () => {
  overText.classList.remove("over-text--display");
  overText.classList.remove("over-text--tutorial");
};

const buildLevelSelector = () => {
  const maxLevel = localStorage.getItem("ducky-fog-max", level) ?? level;
  puzzles.forEach((puzzle, index) => {
    const newButton = document.createElement("div");
    newButton.innerHTML = index;
    newButton.classList.add("level-selector__button");
    if (index === level) {
      newButton.classList.add("level-selector__button--current");
    }
    if (index <= maxLevel) {
      newButton.addEventListener("click", () => {
        level = index;
        localStorage.setItem("ducky-fog", level);
        levelSelector.classList.remove("level-selector--active");
        game.innerHTML = "";
        buildLevel();
        positionPlayer();
      });
    } else {
      newButton.classList.add("level-selector__button--disabled");
    }
    levelSelector.appendChild(newButton);
  });
  levelSelector.classList.add("level-selector--active");
};

document.addEventListener(
  "DOMContentLoaded",
  () => {
    const storedLevel = localStorage.getItem("ducky-fog");
    if (storedLevel) {
      level = Number(storedLevel);
      buildLevelSelector();
    } else {
      overText.classList.add("over-text--display");
      overText.classList.add("over-text--tutorial");
      overText.addEventListener("click", removeTutorial);
      overText.innerHTML =
        "Use arrow keys or buttons to rotate and control water";
    }
    // Init
    buildLevel();
    positionPlayer();
    registerArrows();
  },
  false
);

intro.addEventListener("click", () => {
  intro.classList.add("intro--hidden");
  setTimeout(() => {
    removeTutorial();
    overText.removeEventListener("click", removeTutorial);
  }, 4000);
});

refresh.addEventListener("click", () => {
  game.innerHTML = "";
  buildLevel();
  positionPlayer();
});

fullscreen.addEventListener("click", () => {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen();
  } else if (document.exitFullscreen) {
    document.exitFullscreen();
  }
});

window.addEventListener("keydown", (event) => {
  if (event.key === "ArrowRight") {
    rotateLevel(true);
  } else if (event.key === "ArrowLeft") {
    rotateLevel(false);
  } else if (event.key === "ArrowDown") {
    changeWater(false);
  } else if (event.key === "ArrowUp") {
    changeWater(true);
  }
});

              
            
!
999px

Console