/* Every size and rate the cursor uses is declared here and nowhere else. The
   script reads --sc-ring-size, --sc-pad and --sc-ease back out of this block,
   so retuning the cursor means editing these values only — there are no
   geometry constants left in the JavaScript to keep in sync. Override them
   from a stylesheet loaded after this one. */
:root {
  --sc-dot-size: 6px;
  --sc-dot-glow: 6px; /* inner glow radius; the outer layer is three times this */
  --sc-ring-size: 34px; /* idle ring diameter */
  --sc-ring-width: 2px;
  --sc-ring-opacity: 0.65;
  --sc-ring-opacity-morph: 0.9;
  --sc-pad: 5px; /* gap left between a hovered element and the ring */
  --sc-ease: 0.3; /* 0–1: how far the ring closes on its target each frame */
  --sc-caret-width: 2px;
  --sc-caret-scale: 1.2; /* caret height as a multiple of the text's font-size */

  /* Dot colour, named for the surface it is used on. Override both with your
     own brand; each must be readable against the surface it is named for. */
  --brand: #1a1a1a; /* on light surfaces */
  --brand-light: #f5f5f5; /* on dark surfaces */

  /* Ring colour, likewise, plus a halo in the opposite tone. The halo is what
     keeps the ring readable on images and gradients: neither paints a
     background colour, so the luminance probe walks past them to the surface
     behind, and a ring toned for that surface can vanish on top of them. */
  --sc-ring-on-light: rgba(40, 40, 40, 0.8);
  --sc-ring-on-dark: rgba(255, 255, 255, 0.85);
  --sc-halo-on-light: rgba(255, 255, 255, 0.55);
  --sc-halo-on-dark: rgba(0, 0, 0, 0.45);
  --sc-ring-halo: 1px; /* thickness on each side of the border; 0 removes it */

  /* A drawn ring instead of a bordered box. Set --sc-sketch to 1 to turn it
     on; the wiggle is how far the line strays and the rate how often it is
     redrawn, in seconds. The halo does not apply to a drawn ring. */
  --sc-sketch: 0;
  --sc-sketch-wiggle: 2px;
  --sc-sketch-rate: 0; /* seconds between redraws; 0 holds one drawing */
}

/* Custom cursor: active only while <html> carries .sc-on, so the drawer
   toggle can switch back to the native pointer at any time. */
html.sc-on,
html.sc-on * { cursor: none !important; }

.smart-cursor,
.smart-cursor-ring {
  position: fixed;
  left: 0;
  top: 0;
  pointer-events: none;
  /* Said here rather than inherited: a page with a border-box reset — which is
     most of them — would otherwise fold the border into the size the script
     sets, leaving the ring smaller than the geometry it was given. */
  box-sizing: border-box;
  /* Position comes from JS as a translate3d transform (compositor-only, no
     layout/paint) — never via left/top. */
  will-change: transform;
}

.smart-cursor {
  width: var(--sc-dot-size);
  height: var(--sc-dot-size);
  border-radius: 50%;
  z-index: 99999;
  /* Two glow layers, no filter: cheap to repaint. */
  box-shadow: 0 0 var(--sc-dot-glow) currentColor,
              0 0 calc(var(--sc-dot-glow) * 3) currentColor;
  transition: width 0.15s ease, height 0.15s ease, border-radius 0.15s ease,
              opacity 0.2s ease, background-color 0.2s ease;
}

/* The ring's geometry (position, size, corner radius) is lerped per frame by
   JS so it can morph onto whatever it hovers — CSS must NOT transition those,
   or the two animations fight. Only paint properties transition here. */
.smart-cursor-ring {
  /* The idle circle. JS overwrites these three from the first frame on, but it
     derives them from the same tokens, so this is the identical geometry and
     not a second declaration to keep in sync. */
  width: var(--sc-ring-size);
  height: var(--sc-ring-size);
  border-radius: calc(var(--sc-ring-size) / 2);
  border: var(--sc-ring-width) solid;
  z-index: 99998;
  opacity: var(--sc-ring-opacity);
  /* Dark surface is the default; JS adds .on-light when the probe measures a
     light one. The two shadows sandwich the border — halo, ring, halo — so it
     keeps an edge against whatever it is actually drawn on. Both follow the
     border-radius JS lerps per frame, and paint only: no layout, no reflow. */
  border-color: var(--sc-ring-on-dark);
  box-shadow: 0 0 0 var(--sc-ring-halo) var(--sc-halo-on-dark),
              inset 0 0 0 var(--sc-ring-halo) var(--sc-halo-on-dark);
  transition: opacity 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

.smart-cursor-ring.on-light {
  border-color: var(--sc-ring-on-light);
  box-shadow: 0 0 0 var(--sc-ring-halo) var(--sc-halo-on-light),
              inset 0 0 0 var(--sc-ring-halo) var(--sc-halo-on-light);
}

/* Morphed onto an interactive element: read as its outline. */
.smart-cursor-ring.morph { opacity: var(--sc-ring-opacity-morph); }

/* Text-entry surfaces (inputs, terminal): the dot becomes a caret, the ring
   disappears. */
.smart-cursor.text {
  width: var(--sc-caret-width);
  border-radius: calc(var(--sc-caret-width) / 2);
  /* Height is written inline by JS from the hovered text's own font-size. This
     stands in for the frame before that lands, and if the size can't be read —
     1rem is the same assumption `font-size: medium` makes. */
  height: calc(1rem * var(--sc-caret-scale));
}
.smart-cursor-ring.text { opacity: 0; }

/* Hidden until the first mouse move, and while the pointer is off-window. */
.smart-cursor.off,
.smart-cursor-ring.off { opacity: 0; }

/* Touch devices: no pointer to replace. */
@media (hover: none) {
  .smart-cursor,
  .smart-cursor-ring { display: none !important; }
  html.sc-on,
  html.sc-on * { cursor: auto !important; }
}

/* ---------------------------------------------------------------------------
   The drawn ring. The box keeps its position and size — everything the script
   lerps still applies — but its edge is a path rather than a border, so the
   stroke can wander off the box and must not be clipped to it.
   --------------------------------------------------------------------------- */

.smart-cursor-ring.sketch {
  /* No border at all rather than a transparent one, so the drawing covers the
     whole box instead of the space left inside the border. */
  border: 0;
  box-shadow: none;
  overflow: visible;
}

/* The drawing is only present while the ring is hugging something; idle, the
   bordered circle above is the whole cursor. The two cross-fade on the same
   curve the border does: hiding the drawing outright left a fifth of a second
   with neither of them painted, which reads as a blink every time the pointer
   leaves an element. */
.smart-cursor-ring svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.smart-cursor-ring.sketch svg {
  opacity: 1;
}

.smart-cursor-ring.sketch path {
  fill: none;
  stroke: var(--sc-ring-on-dark);
  stroke-width: var(--sc-ring-width);
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: stroke 0.2s ease;
}

.smart-cursor-ring.sketch.on-light path {
  stroke: var(--sc-ring-on-light);
}
