/* The reticle, the panels that lean toward it, and controls that take a press.
 *
 * Loaded by every page. Nothing here applies unless cursor.js has decided the device has a
 * real pointer and the viewer has not asked for reduced motion — it adds `.has-reticle` to the
 * root, and every rule that hides or replaces the system cursor is gated behind it. A page
 * that lost its cursor because a script failed would be worse than one that never had a
 * custom one.
 */

.has-reticle, .has-reticle * { cursor: none !important; }
/* Belt as well as braces. cursor.js refuses to mount under forced colours, but if it ever did,
   hiding the pointer for somebody running high contrast is the precise failure the published
   guidance warns about. */
@media (forced-colors: active) {
  .has-reticle, .has-reticle * { cursor: auto !important; }
  .reticle { display: none; }
}
/* Text selection is the exception. Hiding the caret while somebody drags across a paragraph
   makes copying an address — which is the one thing people do on this site — a guess. */
.has-reticle input, .has-reticle textarea { cursor: text !important; }

.reticle {
  position: fixed; top: 0; left: 0; z-index: 9999;
  width: 0; height: 0; pointer-events: none;
  opacity: 0; transition: opacity .18s ease;
  will-change: transform;
}
.reticle.on { opacity: 1; }

/* A crosshair: two hairlines and a ring. The lines are what make it a reticle rather than a
   dot, and they are what the site's whole visual language is built from.
 *
 * Solid at the centre, faint past the halfway mark, with a hard edge between the two.
 *
 * The reticle sits above everything at z-index 9999, so wherever it goes it is on top of the
 * text being read. At full strength across its whole width that meant a bright bar lying over a
 * word every time the pointer paused mid-sentence. Fading it evenly would have fixed the
 * covering and lost the cursor — a uniformly translucent crosshair is hard to find on a dark
 * page, which is the thing a cursor must never be.
 *
 * So the strength is not uniform. The middle few pixels — the part that says where the pointer
 * actually is — stay fully opaque, and everything beyond half the arm drops to a fifth. The
 * stops are doubled at the same percentage rather than blended, so it is a step and not a
 * gradient: a soft falloff reads as a glow and blurs exactly the letterforms underneath.
 *
 * Every rule below is written `.reticle i.ret-…` rather than `.ret-…`.
 *
 * `.reticle i` scores (0,1,1) and a bare `.ret-r` scores (0,1,0), so the shared fill won and
 * `background: none` on the ring never applied — the ring was not a ring at all. It was a solid
 * 26px green disc riding on top of the page at z-index 9999, which is the whole reason text kept
 * disappearing under the cursor. Nothing about it looked wrong in the source; the rule that
 * would have fixed it was sitting right there, outranked. */
.reticle i { position: absolute; display: block; background: var(--green); }
.reticle i.ret-h {
  left: -11px; top: -.5px; width: 22px; height: 1px;
  background: linear-gradient(to right,
    var(--lime) 0 18%, transparent 18% 34%,
    transparent 66% 82%, var(--lime) 82% 100%);
}
.reticle i.ret-v {
  top: -2.5px; left: -2.5px; width: 5px; height: 5px;
  border-radius: 50%; background: var(--lime);
}
.reticle i.ret-r {
  left: -15px; top: -15px; width: 30px; height: 30px;
  /* The ring is entirely outside the halfway mark, so it is all in the faint band. */
  background: none; border: 1px solid color-mix(in srgb, var(--lime) 30%, transparent);
  border-radius: 50%;
  transition: width .16s var(--e-out), height .16s var(--e-out),
              left .16s var(--e-out), top .16s var(--e-out),
              border-radius .16s var(--e-out), border-color .16s var(--e-out);
}

/* Over something pressable the ring squares off and closes in — the shape says "this is a
   target" before the label has been read. */
.reticle.is-press .ret-r {
  left: -11px; top: -11px; width: 22px; height: 22px;
  border-radius: 50%; border-width: 2px;
  border-color: var(--lime);
}
/* Over prose it becomes a tall bar, because that is what pressing would do there. This one sits
   directly on the line being read, so it is the faintest state of all. */
.reticle.is-text .ret-r {
  left: -1.5px; top: -12px; width: 3px; height: 24px;
  border-radius: 0; background: color-mix(in srgb, var(--green) 18%, transparent);
  border-color: transparent;
}
.reticle.is-text .ret-h, .reticle.is-text .ret-v { opacity: 0; }
/* Pressed: the ring snaps in. A cursor that does not acknowledge a click leaves people
   wondering whether the click landed. */
.reticle.is-down .ret-r { left: -9px; top: -9px; width: 18px; height: 18px; }

/* ── panels that lean toward the pointer ─────────────────────────────────── */
/* --tx and --ty are set by cursor.js as -0.5..0.5 offsets from the panel's centre. The tilt
   is deliberately under a degree: felt, not seen. A card that visibly rotates reads as a
   gimmick the second time somebody passes it. */
.is-near {
  transform: perspective(900px)
             rotateY(calc(var(--tx, 0) * 1.1deg))
             rotateX(calc(var(--ty, 0) * -1.1deg))
             translateZ(0);
  transition: transform .12s linear, box-shadow .2s var(--e-out), border-color .2s var(--e-out);
}
.card, .plan, .tile, .step {
  transition: transform .35s var(--e-out), box-shadow .35s var(--e-out), border-color .35s var(--e-out);
}
/* The edge nearest the pointer picks up light, so the panel reads as lit from where you are
   rather than uniformly glowing. */
.is-near {
  border-color: color-mix(in srgb, var(--green) 28%, var(--line2));
  box-shadow:
    calc(var(--tx, 0) * -14px) calc(var(--ty, 0) * -14px) 34px -22px var(--glow),
    0 0 0 1px color-mix(in srgb, var(--green) 10%, transparent);
}

/* ── controls that take a press ──────────────────────────────────────────── */
/* The complaint named this directly: buttons that change colour but never move. A press is a
   physical event and 1px of travel is what sells it. */
.btn, .rowbtn, .term, .sh-cta, button.more {
  transition: transform .12s var(--e-out), filter .16s var(--e-out),
              background .16s var(--e-out), border-color .16s var(--e-out);
}
.btn:active, .rowbtn:active, .term:active, .sh-cta:active, button.more:active {
  transform: translateY(1px) scale(.985);
}
.btn:hover, .sh-cta:hover { transform: translateY(-1px); }

@media (prefers-reduced-motion: reduce) {
  .is-near, .btn, .rowbtn, .term, .sh-cta, button.more { transition: none; transform: none; }
}
