/* ═══════════════════════════════════════════════════════════════════════════
 * POINTER — home page only
 * ═══════════════════════════════════════════════════════════════════════════
 * Two layers:
 *   .cwp-cursor       a small ring that tracks the pointer exactly
 *   .cwp-cursor-glow  a soft light that trails behind it and lifts whatever
 *                     it passes over
 *
 * WHAT IS DELIBERATELY ABSENT, AND WHY
 *   No backdrop-filter and no mix-blend-mode on either layer. Both force the
 *   browser to re-sample everything underneath on every frame the layer
 *   moves — and these sit above the entire page, so "underneath" is the whole
 *   viewport. The home page already drives four parallax layers per frame;
 *   adding a full-viewport resample on top of that is what produced the
 *   flicker on scroll. The glow gets its lift from plain alpha on a
 *   GPU-promoted layer instead, which composites for free.
 *
 * ACCESSIBILITY GATE
 *   The native cursor is hidden only by a class JS adds after confirming a
 *   fine pointer, real hover and no reduced-motion preference. If the script
 *   never runs, the ordinary cursor stays.
 */

.cwp-cursor,
.cwp-cursor-glow{
    position:fixed;
    top:0;
    left:0;
    pointer-events:none;
    /* The blanket reset `*,::before,::after{border-radius:0 !important}` this
       site ships wins over a plain declaration, so both layers have to say it
       loudly or they render as squares. */
    border-radius:50% !important;
    will-change:transform;
    opacity:0;
    transition:opacity .3s ease;
}

/* ── the trailing light ───────────────────────────────────────────────────
   Larger, softer and a few frames behind the ring. Because it lags, it reads
   as something being carried rather than a decal stuck to the pointer. */
.cwp-cursor-glow{
    width:360px;
    height:360px;
    margin:-180px 0 0 -180px;
    z-index:2147482990;
    background:radial-gradient(circle closest-side,
        color-mix(in srgb, var(--sp-A,#8b5cf6) 30%, transparent) 0%,
        color-mix(in srgb, var(--sp-A,#8b5cf6) 11%, transparent) 42%,
        transparent 72%);
    transform:translate3d(-400px,-400px,0);
}

/* ── the orbiting wordmark ────────────────────────────────────────────────
   A ring of characters circling the pointer, in the manner of vercera.in:
   one span per character, each rotated around a fixed radius, with the whole
   wrapper turning slowly.

   THE SPIN IS A CSS ANIMATION, NOT A JS TICK
   The reference drives its rotation from JavaScript, a frame at a time. A
   keyframe animation on a transform runs on the compositor instead, so the
   spin costs the main thread nothing — which matters on a page already
   driving four parallax layers, and is the whole reason the flicker appeared
   the first time round.

   IT ALSO STOPS. The animation is paused until the pointer is actually in the
   window; an animation that never stops keeps the compositor awake for the
   life of the page even when nobody is looking at it. */
.cwp-cursor-word{
    position:fixed;
    top:0;
    left:0;
    width:2px;
    height:2px;
    z-index:2147482995;          /* under the ring, over the glow */
    pointer-events:none;
    opacity:0;
    transition:opacity .35s ease;
    will-change:transform;
    transform:translate3d(-400px,-400px,0);
}

/* THE DARK RING the characters ride on.
   ─────────────────────────────────────────────────────────────────────────
   A ring rather than a filled disc: a solid circle would sit under the arrow
   and hide whatever the visitor is pointing at, which is the one thing a
   cursor must never do. An annulus leaves the middle clear, so the arrow and
   the content beneath it stay readable while the text gets consistent dark
   backing on every surface.

   Drawn with a thick border rather than a background, so the hole is genuinely
   transparent — a radial-gradient disc with a "transparent" centre still
   paints the middle at whatever alpha the gradient ends on.

   It lives on the word layer instead of being its own element: the ring has to
   stay exactly concentric with the characters, and sharing a layer means one
   transform moves both rather than two that can drift apart. */
.cwp-cursor-word::before{
    content:'';
    position:absolute;
    left:50%;
    top:50%;
    /* SIZED TO THE TEXT, NOT GUESSED.
       Measured on a rendered page, the rotated glyph boxes span radius 36.4 to
       56.8. The first version ran 39 to 64 — seven pixels of dead ring outside
       the characters, and an inner edge that actually cut 2.6px under them.
       These numbers bracket the measured band with about 1.5px of breathing
       room either side: outer radius 58, inner radius 35, so the band is 23px
       thick for a 20.4px run of text.

       border-box matters here: without it the border would be added OUTSIDE
       the declared width and every number below would be wrong by 46px. */
    width:116px;
    height:116px;
    margin:-58px 0 0 -58px;
    box-sizing:border-box;
    /* The page's own band colour, not a neutral black — see the JS, which
       hands this layer the same --sp-bg every hero and dark section paints.
       The small transparency keeps a hint of the page readable through it. */
    border:23px solid color-mix(in srgb, var(--sp-bg,#0c0a12) 86%, transparent);
    border-radius:50% !important;
    pointer-events:none;
}

.cwp-cursor-word.is-link::before{
    border-color:color-mix(in srgb, var(--sp-A,#8b5cf6) 42%, rgba(12,11,18,.78));
}

.cwp-cursor-word__spin{
    position:absolute;
    inset:0;
    animation:cwp-cursor-spin 16s linear infinite;
    animation-play-state:paused;
    transform-origin:center center;
}

.cwp-cursor-word.is-awake{opacity:.85;}
.cwp-cursor-word.is-awake .cwp-cursor-word__spin{animation-play-state:running;}

/* Each character is placed by a rotation plus an outward offset, so the
   radius is set in one place rather than per character. */
.cwp-cursor-word__c{
    position:absolute;
    top:0;
    left:0;
    font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
    font-size:11px;
    font-weight:800;
    letter-spacing:.06em;
    line-height:1;
    text-transform:uppercase;
    color:#ffffff;
    /* WHITE ON WHITE. A soft shadow was not enough: measured against the white
       lead-form card the wordmark came out a faint grey ghost. It now gets the
       same treatment as the arrow — white fill, dark outline — which is what
       makes a single colour work on the dark bands, the cream surfaces and the
       white cards alike, instead of needing a rule per surface.

       paint-order puts the stroke BEHIND the fill; without it the outline is
       drawn over the glyph and eats into thin strokes at this size, which
       reads as smudged rather than outlined. */
    -webkit-text-stroke:0.7px rgba(0,0,0,.62);
    paint-order:stroke fill;
    text-shadow:0 1px 2px rgba(0,0,0,.45);
    transform-origin:0 0;
    /* --a is the character's angle, written once by JS at build time. */
    transform:rotate(var(--a,0deg)) translate(0,-52px);
}

/* Over something clickable the wordmark takes the page colour and tightens in,
   so the whole pointer reads as one reaction rather than three loose parts. */
.cwp-cursor-word.is-link{opacity:1;}
.cwp-cursor-word.is-link .cwp-cursor-word__c{
    color:#ffffff;
    text-shadow:0 1px 2px rgba(0,0,0,.5),
                0 0 12px color-mix(in srgb, var(--sp-A,#8b5cf6) 70%, transparent);
}

@keyframes cwp-cursor-spin{
    from{transform:rotate(0deg);}
    to{transform:rotate(360deg);}
}

/* ── the ring ─────────────────────────────────────────────────────────── */
.cwp-cursor{
    width:22px;
    height:28px;
    /* The hotspot is the arrow's TIP, not the middle of the box. The path is
       drawn with its tip at (3,2) in the viewBox, so the layer is pulled back
       by exactly that much — otherwise every click lands a few pixels down and
       right of where the arrow appears to point. */
    margin:-2px 0 0 -3px;
    z-index:2147483000;
    /* Not a circle any more, so the blanket border-radius reset this site
       ships is irrelevant here — the shape comes from the SVG path. */
    border-radius:0 !important;
    background:none;
    border:0;
    transform:translate3d(-100px,-100px,0);
    transition:opacity .25s ease, filter .25s ease;
    /* A soft drop shadow is what stops a white-filled arrow disappearing when
       it crosses a pale surface, and it is what makes it read as the macOS
       pointer rather than a flat sticker. */
    filter:drop-shadow(0 1px 2px rgba(0,0,0,.34));
}

.cwp-cursor svg{display:block;width:100%;height:100%;overflow:visible;}

/* White fill, dark outline — the macOS arrow. */
.cwp-cursor svg path{
    fill:#ffffff;
    stroke:#0d0d0c;
    stroke-width:1.6;
    stroke-linejoin:round;
    stroke-linecap:round;
    transition:fill .25s ease;
}

/* Over something clickable the arrow lifts slightly and picks up the page
   colour, so it reacts in the same beat as the wordmark and the light. */
.cwp-cursor.is-link svg path{
    fill:color-mix(in srgb, var(--sp-A,#8b5cf6) 30%, #ffffff);
}

.cwp-cursor.is-awake,
.cwp-cursor-glow.is-awake{opacity:1;}

/* Over anything clickable the ring fills with the page colour and the light
   swells — the cue that the thing under the pointer will respond. */
.cwp-cursor-glow.is-link{opacity:1;}

/* Dark theme: invert the ring's outline or it vanishes on the dark bands. */
/* No dark-theme override is needed any more: the arrow is white with a dark
   outline and the wordmark is white with a dark halo, so both already read on
   either surface. One rule set instead of two. */

/* Hidden only once JS has confirmed it is safe. */
html.cwp-cursor-active,
html.cwp-cursor-active a,
html.cwp-cursor-active button,
html.cwp-cursor-active input,
html.cwp-cursor-active select,
html.cwp-cursor-active textarea,
html.cwp-cursor-active [role="button"]{cursor:none;}

@media (prefers-reduced-motion:reduce),(hover:none),(pointer:coarse){
    .cwp-cursor,.cwp-cursor-glow,.cwp-cursor-word{display:none !important;}
    html.cwp-cursor-active,
    html.cwp-cursor-active a,
    html.cwp-cursor-active button,
    html.cwp-cursor-active input,
    html.cwp-cursor-active select,
    html.cwp-cursor-active textarea,
    html.cwp-cursor-active [role="button"]{cursor:auto;}
}


/* ── CLICK FEEDBACK ────────────────────────────────────────────────────────
   A ring that expands from the point of the click and fades out. The site
   hides the system cursor, and with it the small press animation an OS cursor
   gives you for free — so without this, a click on a control that takes a
   moment to respond gives no sign anything happened, and people click again.

   Each ripple is its own short-lived element, removed when its animation ends,
   so nothing accumulates over a long session and there is no timer to clear.
   It animates transform and opacity only — both compositor properties — so a
   burst of rapid clicks cannot start costing layout. */
.cwp-click{
    position:fixed;
    top:0;
    left:0;
    width:26px;
    height:26px;
    margin:-13px 0 0 -13px;
    border-radius:50% !important;
    border:2px solid color-mix(in srgb, var(--sp-A,#8b5cf6) 70%, #ffffff);
    box-shadow:0 0 0 1px rgba(12,11,18,.45);
    pointer-events:none;
    z-index:2147482998;
    will-change:transform,opacity;
    animation:cwp-click-ripple .52s cubic-bezier(.22,1,.36,1) forwards;
}

@keyframes cwp-click-ripple{
    from{transform:translate3d(var(--cx,0),var(--cy,0),0) scale(.35);opacity:.95;}
    to  {transform:translate3d(var(--cx,0),var(--cy,0),0) scale(2.9);opacity:0;}
}

@media (prefers-reduced-motion:reduce),(hover:none),(pointer:coarse){
    .cwp-click{display:none !important;}
}
