/* Cursor follower, after the Breevast cursor, in plain shapes. One element
   that morphs between them (every shape is the same eight-point polygon,
   so the clip-path animates):
   - rest: a small square;
   - moving or scrolling up or down: a triangle pointing that way, back to
     the square once it stops;
   - over the gallery's edge zones: a triangle pointing left or right (the
     way the row moves); over its middle: a pause sign;
   - over the dark call-to-action buttons: a large circle, clipped to the
     button (main.js), so it only shows inside it;
   - over other links, buttons and the unit selector: a triangle pointing to
     the top left.
   Every shape shows what is under it in greyscale, inverted, so it reads
   on light and dark parts and on photos, a label under the circle stays
   legible, and no colors outside the palette appear. The click point
   is always exact: the square's top-left corner and each triangle's tip sit
   on the pointer (--theme-cursor-ox/-oy, the hotspot as a share of the
   shape); only the circle and the pause sign are centred. Mouse and trackpad
   only, and not with reduced motion: those visitors keep the browser's own
   cursor. The untold panel and form fields keep the native cursor too
   (.use-native-cursor). main.js builds the element and sets the state. */

.site-cursor {
  display: none;
}

@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .site-cursor {
    --theme-cursor-size: 10px;
    --theme-cursor-ox: 0;
    --theme-cursor-oy: 0;
    --theme-cursor-shape: polygon(0 0, 50% 0, 50% 0, 50% 0, 50% 0, 100% 0, 100% 100%, 0 100%);

    position: fixed;
    inset: 0 auto auto 0;
    z-index: 9999;
    display: block;
    width: 0;
    height: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s var(--theme-ease-signature);
  }

  .site-cursor.is-visible {
    opacity: 1;
    transition-duration: 0.1s;
  }

  .site-cursor.is-native {
    opacity: 0;
  }

  .has-cursor,
  .has-cursor * {
    cursor: none !important;
  }

  .site-cursor__shape {
    position: absolute;
    width: var(--theme-cursor-size);
    height: var(--theme-cursor-size);
    margin: calc(var(--theme-cursor-size) * var(--theme-cursor-oy) * -1) 0 0
      calc(var(--theme-cursor-size) * var(--theme-cursor-ox) * -1);
    border-radius: 0;

    /* Greyscale first, then inverted, with the contrast pushed so in-between
       greys split into black and white: the cursor never shows colors
       outside the palette, and a mid grey does not invert to itself. */
    backdrop-filter: grayscale(1) invert(1) contrast(10);
    clip-path: var(--theme-cursor-shape);
    transition:
      width 0.35s var(--theme-ease-signature),
      height 0.35s var(--theme-ease-signature),
      margin 0.35s var(--theme-ease-signature),
      clip-path 0.35s var(--theme-ease-signature),
      border-radius 0.35s var(--theme-ease-signature),
      background-color 0.3s var(--theme-ease-signature);
  }

  /* Moving up or down. */
  .site-cursor[data-shape='up'] {
    --theme-cursor-size: 14px;
    --theme-cursor-ox: 0.5;
    --theme-cursor-shape: polygon(50% 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0, 100% 100%, 0 100%);
  }

  .site-cursor[data-shape='down'] {
    --theme-cursor-size: 14px;
    --theme-cursor-ox: 0.5;
    --theme-cursor-oy: 1;
    --theme-cursor-shape: polygon(0 0, 50% 0, 50% 0, 50% 0, 50% 0, 100% 0, 50% 100%, 50% 100%);
  }

  /* The gallery: left and right in the edge zones, pause in the middle. */
  .site-cursor[data-shape='right'] {
    --theme-cursor-size: 24px;
    --theme-cursor-ox: 1;
    --theme-cursor-oy: 0.5;
    --theme-cursor-shape: polygon(
      0 0,
      50% 25%,
      50% 25%,
      50% 25%,
      50% 25%,
      100% 50%,
      100% 50%,
      0 100%
    );
  }

  .site-cursor[data-shape='left'] {
    --theme-cursor-size: 24px;
    --theme-cursor-oy: 0.5;
    --theme-cursor-shape: polygon(
      0 50%,
      50% 25%,
      50% 25%,
      50% 25%,
      50% 25%,
      100% 0,
      100% 100%,
      0 50%
    );
  }

  /* Two bars: the outline runs down one bar and up the other, the
     overlapping stretch along the bottom has no area. */
  .site-cursor[data-shape='pause'] {
    --theme-cursor-size: 22px;
    --theme-cursor-ox: 0.5;
    --theme-cursor-oy: 0.5;
    --theme-cursor-shape: polygon(0 0, 36% 0, 36% 100%, 64% 100%, 64% 0, 100% 0, 100% 100%, 0 100%);
  }

  /* Other links, buttons and the unit selector: a triangle pointing to
     the top left, its tip on the pointer. */
  .site-cursor[data-shape='tip'] {
    --theme-cursor-size: 16px;
    --theme-cursor-shape: polygon(
      0 0,
      50% 27.5%,
      50% 27.5%,
      50% 27.5%,
      50% 27.5%,
      100% 55%,
      55% 100%,
      0 0
    );
  }

  /* The dark call-to-action buttons: a large circle, centred, clipped to
     the button by main.js (an inline clip-path), so it lights up the part
     of the button around the pointer. */
  .site-cursor[data-shape='circle'] {
    --theme-cursor-size: 96px;
    --theme-cursor-ox: 0.5;
    --theme-cursor-oy: 0.5;
  }

  .site-cursor[data-shape='circle'] .site-cursor__shape {
    border-radius: 50%;
  }

  /* While the circle is held in a button the clip follows the pointer
     exactly: no transition on it (that made the circle trail outside the
     button while moving). */
  .site-cursor.is-held .site-cursor__shape {
    transition:
      width 0.35s var(--theme-ease-signature),
      height 0.35s var(--theme-ease-signature),
      margin 0.35s var(--theme-ease-signature),
      border-radius 0.35s var(--theme-ease-signature);
  }
}

/* Opt-out: the browser's own cursors inside these. */
.has-cursor .use-native-cursor,
.has-cursor .use-native-cursor * {
  cursor: auto !important;
}

.has-cursor
  .use-native-cursor
  :is(a[href], button:not(:disabled), summary, label, select, [role='slider'], [role='tab']) {
  cursor: pointer !important;
}

.has-cursor :is(input:not([type='submit'], [type='button'], [type='range']), textarea) {
  cursor: text !important;
}
