/*
 * The views of the mountains, and the header whose lower edge is their
 * horizon. The drawings are made ahead of time (see Panorama.kt); each view's
 * own values are in panorama/<id>.css. Every colour is a LO-TEK token, mixed
 * in oklch where a shade between two is needed.
 */

@layer site {
  :root {
    /* Air makes distant mountains paler and bluer. Near is darkest; each
       layer is mixed between the two by its depth, 0 near and 1 far. */
    --ridge-near: color-mix(in oklch, var(--lt-color-accent-text) 62%, var(--lt-color-neutral-surface));
    --ridge-far: color-mix(in oklch, var(--lt-color-accent-border) 38%, var(--lt-color-neutral-canvas));
  }

  .panorama--misvaer { --sky-mask: var(--sky-mask-misvaer); }
  .panorama--vestvatn { --sky-mask: var(--sky-mask-vestvatn); }

  /* ---- The header: it stays, frosted, with the horizon as its lower edge ---- */

  .site-header {
    --frost: color-mix(in oklch, var(--lt-color-neutral-canvas) 72%, transparent);
    --edge: clamp(1.75rem, 5vw, 3.5rem);
    /* The horizon keeps its own proportions: as wide as the page at most
       heights, and on a narrow screen wider than the screen, with its middle
       shown, rather than pressed together into sharp spikes. */
    --edge-width: max(100%, calc(var(--edge) * 20.5));
    position: sticky;
    inset-block-start: 0;
    z-index: 10;
    border-block-end: 0;
    background: none;
  }

  /* The frost is a layer of its own behind the header, not the header: an
     element that blurs what is behind it would otherwise let the edge below
     blur only the header, not the page. */
  .site-header::before {
    content: "";
    position: absolute;
    inset: 0 0 var(--edge);
    z-index: -1;
    background: var(--frost);
    backdrop-filter: blur(14px) saturate(1.4);
  }

  /* The frosted band goes on below the header and stops at the horizon, so
     the header's lower edge is the mountains themselves. The mask cuts the
     blur too, so what lies below the ridge stays sharp. The frost is its own
     layer, so the red line along the horizon is not cut by the mask. */
  .site-header__edge {
    position: relative;
    block-size: var(--edge);
    overflow: clip;
    pointer-events: none;
  }

  .site-header__edge::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--frost);
    backdrop-filter: blur(14px) saturate(1.4);
    mask: var(--sky-mask) 50% 0 / var(--edge-width) 100% no-repeat;
  }

  /* The horizon as a line, drawn only while the next page is on its way. */
  .site-header__horizon {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 50%;
    inline-size: var(--edge-width);
    block-size: 100%;
    translate: -50% 0;
    overflow: visible;
  }

  .site-header__horizon path {
    fill: none;
    stroke: var(--lt-color-brand1-fill);
    stroke-width: 2px;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
    opacity: 0;
    transition: opacity 200ms ease;
  }

  .is-navigating .site-header__horizon path {
    opacity: 1;
  }

  /* When a page takes long: a short text under the header, at the right. */
  .site-header__status {
    position: absolute;
    inset: 100% var(--lt-spacing-4) auto auto;
    margin: var(--lt-spacing-1) 0 0;
    padding: var(--lt-spacing-1) var(--lt-spacing-3);
    border-radius: var(--lt-spacing-2);
    background: var(--lt-color-neutral-canvas);
    box-shadow: var(--lt-shadow-overlay);
    color: var(--lt-color-neutral-text-strong);
    font-size: var(--lt-font-size-s);
  }

  .site-header__status:empty {
    display: none;
  }

  /* ---- The view: one SVG per layer, stacked ---- */

  .ridge {
    position: relative;
    /* Clipped at the sides and the bottom, so a layer that rises never shows
       outside the band. Above it the names may go a little over the edge, as
       they rise with their layers when the page scrolls; the band keeps as
       much room clear above it. */
    --above: 0px;
    clip-path: inset(calc(var(--above) * -1) 0 0 0);
    margin-block: var(--above) var(--lt-spacing-8);
  }

  .ridge--tagged {
    --above: 1.75rem;
  }

  /* Under the slogan, the room above the names stands in for the space below it. */
  .welcome:has(+ .ridge) {
    margin-block-end: 0;
  }

  .ridge__layer,
  .ridge__layer svg {
    position: absolute;
    inset: 0;
  }

  .ridge__layer svg {
    inline-size: 100%;
    block-size: 100%;
  }

  .ridge__layer {
    --land: color-mix(in oklch, var(--ridge-far) calc(var(--depth) * 100%), var(--ridge-near));
    pointer-events: none;
  }

  .ridge .land {
    fill: var(--land);
  }

  /* The far mountains get a fine outline along the ridge, so white tops do
     not vanish against a light sky. */
  .ridge .ridge-line {
    fill: none;
    stroke: color-mix(in oklch, var(--lt-color-accent-border) 55%, transparent);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
  }

  /* The slope is lighter, as a cleared hillside looks from across the valley. */
  .ridge .slope {
    fill: color-mix(in oklch, var(--land) 58%, var(--lt-color-neutral-canvas));
  }

  .ridge .slope-mask polyline {
    fill: none;
    stroke: white;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  /* The fjord: the land's own colour, a little deeper. */
  .ridge .water {
    fill: color-mix(in oklch, var(--land) 86%, var(--lt-color-accent-text));
  }

  /* The roads, the houses and the pitch: lighter than the land, like the slope. */
  .ridge .road {
    fill: none;
    stroke: color-mix(in oklch, var(--land) 45%, var(--lt-color-neutral-canvas));
    stroke-width: 1.5px;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
  }

  .ridge .house {
    fill: color-mix(in oklch, var(--land) 40%, var(--lt-color-neutral-canvas));
  }

  .ridge .field {
    fill: color-mix(in oklch, var(--land) 58%, var(--lt-color-neutral-canvas));
  }

  /* The T-bar, dashed. */
  .ridge .lift {
    fill: none;
    stroke: color-mix(in oklch, var(--lt-color-neutral-text) 70%, transparent);
    stroke-width: 1.4;
    stroke-dasharray: 4 4;
    vector-effect: non-scaling-stroke;
  }

  .ridge .lift-reveal {
    fill: none;
    stroke: white;
    stroke-width: 12;
    stroke-linecap: round;
  }

  /* ---- The names: room above the mountains, a red line down to each place ---- */

  /* The names are placed twice when the view is made: for a wide band
     (--row-w and the tag--w-* classes) and for a phone (--row-n, tag--n-*). */
  .ridge--tagged {
    container-type: inline-size;
    --tag-rows: var(--tag-rows-w, 2);
    --tag-room: calc(var(--tag-rows) * 1.35rem + var(--lt-spacing-4));
    padding-block-start: var(--tag-room);
  }

  /* The view in its own proportions: a percentage padding is a share of the band's width. */
  .ridge--tagged::after {
    content: "";
    display: block;
    padding-block-end: calc(var(--ridge-ratio) * 100%);
  }

  .ridge--tagged .ridge__layer {
    inset-block-start: var(--tag-room);
  }

  .ridge--tagged:focus-visible {
    outline: var(--lt-focus-ring);
    outline-offset: 2px;
  }

  .tag {
    --row: var(--row-w);
    position: absolute;
    inset-inline-start: var(--x);
    inset-block-start: calc(var(--tag-room) * -1 + var(--lt-spacing-1) + var(--row) * 1.35rem);
    /* --yf is the place's height in the drawing, 0 at the top and 1 at the bottom. */
    inset-block-end: calc(100% * (1 - var(--yf)));
    inline-size: 0;
  }

  .tag__text {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    translate: -50% 0;
    white-space: nowrap;
    font-size: var(--lt-font-size-xs);
    font-weight: var(--lt-font-weight-semibold);
    line-height: 1.2;
    color: var(--lt-color-neutral-text-strong);
  }

  .tag__height {
    font-weight: var(--lt-font-weight-regular);
    color: var(--lt-color-neutral-text);
    font-variant-numeric: tabular-nums;
  }

  /* The name to the right of its line, or to the left, where it was placed so. */
  .tag--w-start .tag__text { translate: calc(var(--lt-spacing-2) * -1) 0; }
  .tag--w-end .tag__text { translate: calc(-100% + var(--lt-spacing-2)) 0; }
  .tag--w-hidden { display: none; }
  .tag__short { display: none; }

  @container (width < 48rem) {
    .tag {
      --row: var(--row-n);
    }

    .ridge--tagged {
      --tag-rows: var(--tag-rows-n, 2);
    }

    .tag--w-hidden { display: block; }
    .tag--n-hidden { display: none; }
    .tag__long { display: none; }
    .tag__short { display: inline; }
    .tag .tag__text { translate: -50% 0; }
    .tag--n-start .tag__text { translate: calc(var(--lt-spacing-2) * -1) 0; }
    .tag--n-end .tag__text { translate: calc(-100% + var(--lt-spacing-2)) 0; }
  }

  /* The line, from under the name down to the place. Thick enough to stay
     red against the dark layers in the valley. */
  .tag::after {
    content: "";
    position: absolute;
    inset-block: 1.15rem 0;
    inset-inline-start: -1px;
    inline-size: 2px;
    background: var(--lt-color-brand1-fill);
    transform-origin: top;
  }

  /* A small dot where the line meets the place. */
  .tag::before {
    content: "";
    position: absolute;
    inset-block-end: -2.5px;
    inset-inline-start: -2.5px;
    inline-size: 5px;
    block-size: 5px;
    border-radius: 50%;
    background: var(--lt-color-brand1-fill);
  }

  /* With a mouse, the names wait until the pointer is over the view, or the
     band has keyboard focus. On a phone there is no pointer to wait for, so
     they are always there. */
  @media (hover: hover) {
    .tag {
      opacity: 0;
      transition: opacity 200ms ease;
    }

    .tag::after {
      scale: 1 0;
      transition: scale 380ms cubic-bezier(0.2, 0.7, 0.2, 1);
    }

    .ridge--tagged:hover .tag,
    .ridge--tagged:focus-visible .tag {
      opacity: 1;
    }

    .ridge--tagged:hover .tag::after,
    .ridge--tagged:focus-visible .tag::after {
      scale: 1 1;
    }
  }

  /* ---- Motion, for those who have not asked for less ---- */

  @media (prefers-reduced-motion: no-preference) {
    @supports (animation-timeline: view()) {
      /* Parallax: as the band passes through the screen, the mountains
         rise a little, the near layers most. Each layer stretches up from
         its bottom edge, which stays put, so nothing below the drawing ever
         shows. The names follow their places in the stretched layer, so a
         marker never leaves the band. */
      .ridge--parallax {
        view-timeline: --band block;
      }

      .ridge--parallax .ridge__layer {
        --lift: calc(0.02 + (1 - var(--depth)) * 0.14);
      }

      .ridge--parallax .ridge__layer:not(.ridge__layer--tags) {
        transform-origin: bottom;
        animation: ridge-rise linear both;
        animation-timeline: --band;
        animation-range: cover 0% cover 100%;
      }

      /* The layer under the names is the drawing's height: the band's width
         times its proportions. */
      .ridge--parallax .tag {
        --rise: calc(var(--lift) * (1 - var(--yf)) * var(--ridge-ratio) * -100cqi);
        animation: tag-rise linear both;
        animation-timeline: --band;
        animation-range: cover 0% cover 100%;
      }

      /* The lift is drawn from the foot up as the band comes into view. */
      .ridge .lift-reveal {
        stroke-dasharray: 1 1;
        animation: lift-draw linear both;
        animation-timeline: --band;
        animation-range: entry 20% cover 50%;
      }
    }
  }

  @keyframes ridge-rise {
    from { scale: 1 calc(1 + var(--lift)); }
    to { scale: 1 1; }
  }

  @keyframes tag-rise {
    from { translate: 0 var(--rise); }
    to { translate: 0 0; }
  }

  @keyframes lift-draw {
    from { stroke-dashoffset: 1; }
    to { stroke-dashoffset: 0; }
  }
}
