/* ==========================================================================
   DINKOMART — Custom cursor

   Ring + centre dot, native arrow hidden.

   ── THE ONE RULE ───────────────────────────────────────────────────────────

   `cursor: none` is applied ONLY under `html.ag-cursor-on`, and that class is
   set by req/js/cursor.js at runtime — never by this file, never in the
   markup. If the script does not run, the class never appears and the native
   arrow is simply still there.

   Do not "simplify" this by putting `cursor: none` on `body`. A page with no
   pointer at all is the one failure a visitor cannot work around, and it is
   why the previous two attempts were removed. Same fail-open contract as
   `html.m-ready` in the motion system.

   Loads after viewer.css, before mobile.css.
   ========================================================================== */

/* --- the handover -------------------------------------------------------- */
html.ag-cursor-on,
html.ag-cursor-on * { cursor: none; }

/* Text fields keep the native I-beam. It tells you a field is editable and
   shows where the caret will land, which a dot cannot do. cursor.js also
   drops the class entirely while the pointer is over one, so this is the
   belt to that braces. */
html.ag-cursor-on input:not([type=radio]):not([type=checkbox]):not([type=button]):not([type=submit]),
html.ag-cursor-on textarea,
html.ag-cursor-on [contenteditable],
html.ag-cursor-on [data-native-cursor],
html.ag-cursor-on [data-native-cursor] * { cursor: auto; }

/* ==========================================================================
   A MODAL DIALOG IS IN THE TOP LAYER. THE CUSTOM CURSOR IS NOT.

   `showModal()` promotes an element into the top layer, which paints above
   every normal stacking context whatever its z-index — so the ring and dot,
   which are `position: fixed` on the body, are UNDERNEATH the open lightbox
   and cannot be seen. Meanwhile `html.ag-cursor-on *` has already taken the
   native arrow away.

   The result was a full-screen image viewer with NO POINTER AT ALL, and a
   close button in the far corner that you had to find by feel. Reported in
   those words.

   Every open dialog gets its native cursor back. Written against `dialog`
   rather than `.ag-box` so the next one that gets built is covered without
   anyone having to remember this. The meaningful cursors inside it are
   restored below, because `auto` over a zoomable photograph is a worse
   answer than the arrow it replaced. */
html.ag-cursor-on dialog[open],
html.ag-cursor-on dialog[open] * { cursor: auto; }
html.ag-cursor-on dialog[open] a,
html.ag-cursor-on dialog[open] button,
html.ag-cursor-on dialog[open] [role='button'] { cursor: pointer; }
html.ag-cursor-on dialog[open] .ag-box-fig { cursor: zoom-in; }
html.ag-cursor-on dialog[open] .ag-box-fig.is-zoomed { cursor: zoom-out; }

/* the 3D viewer keeps its grab affordance — the gesture is the point there */
html.ag-cursor-on .pdp-frame.has-3d.is-3d canvas { cursor: grab; }
html.ag-cursor-on .pdp-frame.has-3d.is-dragging canvas { cursor: grabbing; }

/* ==================================================================== parts */

.ag-cur {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 99999;
  pointer-events: none;           /* must never intercept a click */
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease-out);
}
.ag-cur.is-on { opacity: 1; }
/* over a text field the companion stands down completely */
.ag-cur.is-text { opacity: 0; }

/* --- the dot -------------------------------------------------------------
   Written straight from the pointer event with no easing, so it is exactly
   where the mouse is. This is the part you aim with. */
.ag-cur-dot {
  position: fixed;
  left: 0;
  top: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--fg);
  will-change: transform;
  transition: width var(--dur-1) var(--ease-out),
              height var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out),
              opacity var(--dur-1) var(--ease-out);
}

/* --- the ring ------------------------------------------------------------
   Eased a few frames behind the dot. Decoration, deliberately, so the lag
   never costs precision. */
.ag-cur-ring {
  position: fixed;
  left: 0;
  top: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--fg) 42%, transparent);
  will-change: transform;
  transition: width var(--dur-2) var(--ease-spring),
              height var(--dur-2) var(--ease-spring),
              border-color var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out),
              opacity var(--dur-1) var(--ease-out);
}

/* --- hover ---------------------------------------------------------------
   Over anything actionable the ring opens and takes the brand colour, and the
   dot shrinks so the centre of the target stays readable through it.

   THE RING DOES NOT FILL OVER A PLAIN LINK, AND THAT IS DELIBERATE.

   The generic rule at the bottom of RULES in cursor.js catches every `a`,
   `button`, `select`, `label` and `summary` on the site, so most of what you
   hover is inline text. A 46px disc tinted 10% brand, parked on a 13px link,
   sits ON the words — it tinted the very text it was pointing at, and was
   reported as looking broken. An open ring leaves the target legible, which
   is the whole job of a cursor.

   The fill is kept for the labelled targets — cards, photographs, the rail,
   the 3D frame. Those are large, nothing fine sits under the centre, and the
   label pill is already up, so it reads as a spotlight rather than a smear.
   `has-label` is set by cursor.js for exactly that set, so the distinction
   costs no extra bookkeeping. */
.ag-cur.is-active .ag-cur-ring {
  width: 40px;
  height: 40px;
  border-color: var(--brand);
}
.ag-cur.is-active.has-label .ag-cur-ring {
  background: color-mix(in srgb, var(--brand) 10%, transparent);
}
.ag-cur.is-active .ag-cur-dot { width: 5px; height: 5px; background: var(--brand); }

/* --- press ---------------------------------------------------------------
   The ring closes onto the dot, so the click reads as the two meeting.

   The `.has-label` selector is restated here because the hover fill above is
   (0,3,0) and would otherwise out-rank a plain `.is-down` at (0,2,0), leaving
   a card stuck at the hover fill through the whole press. */
.ag-cur.is-down .ag-cur-ring,
.ag-cur.is-down.has-label .ag-cur-ring {
  width: 24px;
  height: 24px;
  background: color-mix(in srgb, var(--brand) 20%, transparent);
}
.ag-cur.is-down .ag-cur-dot  { width: 9px; height: 9px; }

/* --- the label -----------------------------------------------------------
   Rides with the ring, offset below so it never sits under the dot. */
.ag-cur-label {
  position: fixed;
  left: 0;
  top: 0;
  margin-top: 34px;               /* clear of the ring at its widest */
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  background: var(--fg);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  will-change: transform;
  transition: opacity var(--dur-1) var(--ease-out);
}
.ag-cur.has-label .ag-cur-label { opacity: 1; }

/* ============================================================== dark ground

   `is-on-dark` is set by cursor.js while the pointer is over `.on-band` or
   `.site-footer` — surfaces that are dark in BOTH themes and therefore carry
   their own ink in `--band-*` rather than following `--fg`.

   Without this the companion painted the page's ink on a band's ground. In
   the light theme that is #101A12 on #06150D: measured 1.05:1 on every band
   and 1.01:1 on the footer, i.e. gone — and with `cursor: none` live, gone
   means no pointer at all, on 2880px of the home page and the footer of all
   ten. Read the note in cursor.js for why this cannot be done in CSS alone.

   Measured on the band with these tokens: dot 16.28:1, ring 3.70:1 (the dark
   theme already ships 3.61:1, so the ring is no fainter than it is anywhere
   else), active 9.16:1. `--band-sprout` is the build's own green-for-a-dark-
   ground; plain `--brand` measures 2.98:1 there and would trade one invisible
   state for another. */
.ag-cur.is-on-dark .ag-cur-dot { background: var(--band-fg); }
.ag-cur.is-on-dark .ag-cur-ring {
  border-color: color-mix(in srgb, var(--band-fg) 42%, transparent);
}
.ag-cur.is-on-dark.is-active .ag-cur-ring { border-color: var(--band-sprout); }
.ag-cur.is-on-dark.is-active .ag-cur-dot  { background: var(--band-sprout); }
.ag-cur.is-on-dark.is-active.has-label .ag-cur-ring {
  background: color-mix(in srgb, var(--band-sprout) 10%, transparent);
}
/* restated for the same specificity reason the press state above is */
.ag-cur.is-on-dark.is-down .ag-cur-ring,
.ag-cur.is-on-dark.is-down.has-label .ag-cur-ring {
  background: color-mix(in srgb, var(--band-sprout) 20%, transparent);
}
/* the label is `--fg` on `--bg`; on a band that is the page's pairing, which
   still reads, but the band's own pairing is the one that belongs there */
.ag-cur.is-on-dark .ag-cur-label {
  background: var(--band-fg);
  color: var(--band-bg);
}

/* ==================================================================== off */

/* cursor.js returns before building anything in either of these cases; this
   is here for a preference that flips mid-session, and so a coarse pointer
   can never be left with a stranded ring and no arrow. */
@media (prefers-reduced-motion: reduce) {
  .ag-cur { display: none; }
  html.ag-cursor-on, html.ag-cursor-on * { cursor: auto; }
}
@media (hover: none), (pointer: coarse) {
  .ag-cur { display: none !important; }
  html.ag-cursor-on, html.ag-cursor-on * { cursor: auto !important; }
}
