/* =============================================================================
   myk-hover-cursor.css — THE HOVER-CURSOR SKIN
   Lane: final:cursor-singleton.  Contract: build/COMPONENT-hover-cursor.md
   Values: review/branding/cursors.md §2 (render-proven from scale-4 PNGs)
   -----------------------------------------------------------------------------
   SCOPE OF THIS FILE — read before adding anything to it.

   CSS CANNOT OWN THE PAINT. Salient's `$t.prototype.mouseBind` writes fill and
   ink INLINE on every `mouseenter`, and inline beats every stylesheet rule.
   `!important` was tried by an earlier lane and lost the moment a real pointer
   entered a region. Fill, blur, ink, size, offset and content are therefore
   written by js/myk-hover-cursor.js at the inline level and MUST NOT be declared
   here — a duplicate declaration here would be dead code that reads as the source
   of truth to the next person.

   What CSS legitimately owns is everything Salient never writes inline and the
   controller never needs to arbitrate:
     · the entrance/exit transition (scale-in from 0.2, the press scale)
     · the chevron geometry (∓18.12px from centre — a CONSTANT, not a scale)
     · the label type
     · suppression of Salient's `:before` ring and `difference` blend base
     · the reduced-motion posture

   This file is the REQ-ECO-1 hoist target named in sections/04-ecology.css and
   sections/14-amenities.css. Those two blocks (and 07-building.css's) are
   requested for deletion in founder-trace/SHARED-REQUESTS.md; until their owning
   lanes remove them this file is written to WIN on specificity so the behaviour is
   the same either way.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   §1. GEOMETRY CONSTANTS — RENDER-SOLVED, not derived.

   ⚠ These are the values from SHARED-REQUESTS.md REQ-FBVE-1, which solved them by
   sweeping font-size and MEASURING THE WHITE INK in a scale-4 screenshot masked to
   the inscribed circle. They are NOT box arithmetic, and box arithmetic gets them
   wrong: `cursors.md` §2.5 states the target in INK terms (ink 11.25 x 19.50,
   centres at -+18.12 from disc centre, identical at 96 and 110), and a chevron's
   ink is not centred in its line box, so half the em and half the ink are
   different numbers. REQ-FBVE-1 records the earlier lane that mistook a box figure
   (11.77 x 20) for an ink figure and settled a decision on it.

   Derivation of these three from the sweep (REQ-FBVE-1's table, winning row):
     font-size 35.5px -> left -18.12 / right +18.12 / ink 11.25 x 19.50 / dy 0.00
     with left/right inset 23.25px and top -18.75px

   `top` gets its own token rather than `calc(font-size / -2)`: half the em box is
   -17.75 and the ink needs -18.75. The two insets are the SAME number on both
   sides — the older 24.25 / 24.5 asymmetry was two independently-rounded ink
   measurements written into two box properties, not a design intent.

   `sections/14-amenities.css` already declares these three tokens with these exact
   values (its §GLYPH GEOMETRY block, corrected in place by REQ-FBVE-1). They are
   restated here so this file is self-sufficient once that block is deleted per
   REQ-CUR-3, and they are IDENTICAL — if you ever change one, change both in the
   same commit or delete the older block first.
   -------------------------------------------------------------------------- */
:root {
  --myk-cursor-gi-glyph:   35.5px;   /* font-size; yields ink 11.25 x 19.50   */
  --myk-cursor-gi-inset:   23.25px;  /* puts the INK at -+18.12 from centre   */
  --myk-cursor-gi-glyph-y: -18.75px; /* ink y-centred in the disc, not the em */
  --myk-cursor-label-size: 18px;     /* cursors.md §2.1: Poppins Regular 18   */
  --myk-cursor-label-lh: 180%;
  --myk-cursor-enter-dur: 0.45s;     /* Salient's own entrance, verbatim      */
  --myk-cursor-fade-dur: 0.3s;
}

/* -----------------------------------------------------------------------------
   §2. THE BOX. Both singletons, both variants of the general class.

   `position: fixed` + `pointer-events: none` + z 400 is Salient's own contract
   (`$t` engine, cursors.md §6A) and is kept verbatim. `mix-blend-mode` is forced
   to `normal` because Salient's base is `difference`, which turns a 50%-black
   disc into an inverted smear over photography.
   -------------------------------------------------------------------------- */
body .nectar-drag-indicator[data-myk-cursor-variant],
body .nectar-view-indicator[data-myk-cursor-variant] {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 400;
  pointer-events: none;
  mix-blend-mode: normal;
  will-change: transform;
}

/* Salient's `default` style draws a 2px ring with `mix-blend-mode: difference`.
   The Mykrobial cursor is a filled disc in BOTH classes (cursors.md §2.0: "No
   cursor in this system has a border. Do not add one."), so the ring never
   applies to any variant this system ships. */
body .nectar-drag-indicator[data-myk-cursor-variant]::before,
body .nectar-view-indicator[data-myk-cursor-variant]::before,
body .nectar-drag-indicator[data-myk-cursor-variant]::after,
body .nectar-view-indicator[data-myk-cursor-variant]::after {
  display: none !important;
  content: none !important;
}

/* -----------------------------------------------------------------------------
   §3. THE ENTRANCE. Salient's own contract, verbatim: hidden at scale(0.2)
   opacity 0, scaling in on `.visible`. `.pointer-down` is Flickity's press
   feedback (init.js `pointerDown`/`pointerUp` on the shared node) — preserved.

   fill / blur / border-radius are deliberately ABSENT here; the controller owns
   them inline. See the header.
   -------------------------------------------------------------------------- */
body .nectar-drag-indicator[data-myk-cursor-variant] .color-circle,
body .nectar-view-indicator[data-myk-cursor-variant] .color-circle {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  display: block;
  transform: scale(0.2);
  opacity: 0;
  transition: transform var(--myk-cursor-enter-dur) ease,
              opacity var(--myk-cursor-fade-dur) ease;
}
body .nectar-drag-indicator[data-myk-cursor-variant].visible .color-circle,
body .nectar-view-indicator[data-myk-cursor-variant].visible .color-circle {
  transform: scale(1);
  opacity: 1;
}
body .nectar-drag-indicator[data-myk-cursor-variant].visible.pointer-down .color-circle,
body .nectar-view-indicator[data-myk-cursor-variant].visible.pointer-down .color-circle {
  transform: scale(0.15);
}

/* -----------------------------------------------------------------------------
   §4. THE INNER LAYER — the parallax carrier, and the reason the chevron numbers
   only work in one particular box.

   Salient ships `.nectar-drag-indicator span { position:absolute; top:50%; left:0;
   display:block; width:100%; text-align:center; transform:translateY(-50%) }`
   (style-non-critical.q-40f8116f6d.css). Because the two chevrons inside it are
   themselves absolutely positioned, that span's height is **zero**, so its top edge
   sits exactly on the disc's vertical centre and `translateY(-50%)` resolves to 0px.

   THAT IS THE BOX REQ-FBVE-1 SOLVED AGAINST. `top: -18.75px` on the glyph means
   "18.75px above the DISC CENTRE". Giving the inner layer `inset: 0` instead — an
   obvious-looking simplification — moves the containing block's top edge to the top
   of the disc and throws the ink 48px high. Measured: the `<i>` rect landed at
   y 473.25 against a disc box starting at y 492, and the scale-4 crop contained
   zero white pixels. Recorded because it looks like a tidy-up and is a regression.

   The controller writes this element's `transform` every frame for icon parallax
   (clamped ±12, divisor 1.65 — `$t.prototype.parallaxIcon`), which is why no
   transform is declared here. That is also what Salient itself does, and it is
   only safe because the height is zero.

   The geometry is therefore VARIANT-DEPENDENT, and the variant says which it wants
   through `data-myk-content`, written by the controller:
     chevrons  -> the zero-height rail on the disc's centre line (Salient's box)
     label     -> a full-box flex centre, because a word needs a real height
   -------------------------------------------------------------------------- */
body .nectar-drag-indicator[data-myk-cursor-variant] .inner-layer,
body .nectar-view-indicator[data-myk-cursor-variant] .inner-layer {
  position: absolute;
  display: block;
  opacity: 0;
  transition: opacity var(--myk-cursor-fade-dur) ease;
  pointer-events: none;
}
body .nectar-drag-indicator[data-myk-cursor-variant].visible .inner-layer,
body .nectar-view-indicator[data-myk-cursor-variant].visible .inner-layer {
  opacity: 1;
}

/* chevrons — Salient's own zero-height rail, restated so it survives the hoist */
body [data-myk-cursor-variant] .inner-layer[data-myk-content="chevrons"] {
  top: 50%;
  left: 0;
  width: 100%;
  height: 0;
  text-align: center;
}

/* label — a real box to centre a word in */
body [data-myk-cursor-variant] .inner-layer[data-myk-content^="label"] {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* -----------------------------------------------------------------------------
   §5. VARIANT C — general/flip. Two chevrons, `#FFFFFF`, ink centres at ∓18.12px
   from the disc centre. The values come from §1 and are RENDER-SOLVED; see the
   warning there before changing any of them.
   -------------------------------------------------------------------------- */
body [data-myk-cursor-variant] .inner-layer[data-myk-content="chevrons"] i {
  position: absolute;
  top: var(--myk-cursor-gi-glyph-y);
  font-size: var(--myk-cursor-gi-glyph);
  /* NOT declared: width / height / margin-top / line-height. Pinning a box on a
     glyph whose position is solved from its INK re-introduces the exact error
     REQ-FBVE-1 corrected — the box and the ink are different rectangles. Let the
     font set the box; `top` and `font-size` place the ink. */
  /* colour is written inline by the controller — do not declare it here */
}
body [data-myk-cursor-variant] .inner-layer[data-myk-content="chevrons"] i.fa-angle-left {
  left: var(--myk-cursor-gi-inset);
}
body [data-myk-cursor-variant] .inner-layer[data-myk-content="chevrons"] i.fa-angle-right {
  right: var(--myk-cursor-gi-inset);
}

/* -----------------------------------------------------------------------------
   §6. VARIANTS B and D — the labelled discs. The single word `View`, Poppins
   Regular 18 / 180%, CENTRED.

   cursors.md §2.6 records that the Figma source lands variant D's label +2.38px
   right of centre because D uses `primaryAxisAlignItems: MIN` + `padding-left: 36`
   while B uses CENTER, and the 43-wide label overflows the 38-wide content box.
   That is a source-side accident, not an intent — the two labels are otherwise
   byte-identical renders. **Built centred**, and the deviation is recorded here
   rather than silently normalised.
   -------------------------------------------------------------------------- */
body [data-myk-cursor-variant] .inner-layer[data-myk-content^="label"] {
  font-family: var(--mk-font-sans, "Poppins", system-ui, sans-serif);
  font-weight: 400;
  font-size: var(--myk-cursor-label-size);
  line-height: var(--myk-cursor-label-lh);
  letter-spacing: 0;
  text-align: center;
  white-space: nowrap;
}

/* -----------------------------------------------------------------------------
   §7. THE DEV FAULT DISC. An unknown or missing declaration must be VISIBLE, not
   silently inherited — silent inheritance is the exact failure being engineered
   out. The controller paints `#FF00A0` with a `?`; this makes it unmistakable.
   -------------------------------------------------------------------------- */
body [data-myk-cursor-variant="!fault"] {
  outline: 3px dashed #FF00A0;
  outline-offset: 4px;
}
body [data-myk-cursor-variant="!fault"] .inner-layer {
  display: flex;
  align-items: center;
  justify-content: center;
  font: 700 32px/1 ui-monospace, Menlo, monospace;
}

/* -----------------------------------------------------------------------------
   §8. REDUCED MOTION. css/reduced-motion.css is the site-wide owner; this is the
   cursor's share of it. Salient has no `prefers-reduced-motion` handling at all,
   so everything here is ours.

   The disc still APPEARS — removing the cursor entirely would remove the only
   affordance telling a visitor the carousel is draggable. What goes is the
   easing: the controller sets damping to 1 (snap to the pointer) and suppresses
   parallax; these rules drop the scale-in and the fade to instant.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  /* NOT declared here: `transition: none`. css/reduced-motion.css §1 already pins
     `transition-duration: 0.01ms !important` on `*, *::before, *::after`, and it
     does so DELIBERATELY rather than using `none` — a zero-duration transition
     still fires `transitionend`, so a Salient handler waiting on that event is not
     stranded mid-state. A `transition: none` here would be beaten by that
     `!important` and would read to the next person as the owner of a behaviour it
     does not own. Measured live: 1e-05s. */
  body .nectar-drag-indicator[data-myk-cursor-variant].visible .color-circle,
  body .nectar-view-indicator[data-myk-cursor-variant].visible .color-circle {
    transform: scale(1);
  }
}

/* -----------------------------------------------------------------------------
   §8b. R11-03 SUPPRESSION COVER — reversible, presentation-only.

   `js/myk-hover-cursor.js` `standDown()` no longer removes `.visible` from a
   surface it has ADOPTED from Salient (owner:"salient") — that class belongs
   to Salient's own `$t.prototype.mouseBind`, which binds native mouseenter/
   mouseleave that do not refire on an internal move to one of our declared
   sub-regions and back (RCA in standDown()'s own comment). Instead the
   controller marks the node `[data-myk-suppressed]` and this rule forces its
   PAINTED CONTENT invisible without touching `.visible` at all, so removing
   the attribute later (paintTotal(), or standDownAll() handing the surface
   back to its native owner) reveals exactly the state Salient itself set,
   undisturbed.

   Targets `.color-circle`/`.inner-layer` opacity, not the outer node's
   `display` — the existing verifier convention (`_tools/cursor-state-probe.py`)
   already reads "shown" off `.color-circle`'s computed opacity plus the
   `.visible` class, and `display:none` on an ancestor would leave that
   opacity reading `1` in Chrome (computed style resolves independent of an
   ancestor's box generation), producing a false PASS. Forcing opacity here
   keeps every existing check honest and produces the exact same "hidden"
   result the box already renders in its un-hovered rest state (§3/§4).
   -------------------------------------------------------------------------- */
body .nectar-drag-indicator[data-myk-suppressed] .color-circle,
body .nectar-view-indicator[data-myk-suppressed] .color-circle {
  opacity: 0 !important;
  transform: scale(0.2) !important;
}
body .nectar-drag-indicator[data-myk-suppressed] .inner-layer,
body .nectar-view-indicator[data-myk-suppressed] .inner-layer {
  opacity: 0 !important;
}

/* -----------------------------------------------------------------------------
   §9. TOUCH / COARSE POINTERS. Salient gates the whole `$t` engine behind
   `bt.usingMobileBrowser`; the controller has no equivalent gate because it is
   driven by `mouseover`, which a touch device does not sustain. This rule is the
   belt-and-braces: on a device with no hover capability the disc cannot paint at
   all, so a tap can never leave one stranded on screen.
   -------------------------------------------------------------------------- */
@media (hover: none) {
  body .nectar-drag-indicator[data-myk-cursor-variant],
  body .nectar-view-indicator[data-myk-cursor-variant] {
    display: none !important;
  }
}

/* -----------------------------------------------------------------------------
   §10. NATIVE CURSOR SUPPRESSION — R10-02.

   Her words: "when you're either seeing the view or the left right icon, I
   need that to disappear the mouse tooltip [native OS cursor]." Confirmed live
   BEFORE this fix (real pointer, `Input.dispatchMouseEvent`, 1440x900):
   `getComputedStyle(el).cursor` was `"auto"` over the black-dress play button,
   `"grab"` over the ecology AND building slider bodies (and over `07-building`
   `.heading-wrap`, which inherits it from its `.flickity-viewport` ancestor),
   `"grab"` over `14-amenities`, and `"auto"` over `16-amenities-52`'s
   photo-follower. None of the four mechanisms below ever suppressed it.

   THE ROOT CAUSE IS TWO BUGS, NOT ONE:

   1. NOT CENTRALISED. Exactly one `cursor: none` rule existed anywhere in this
      build — `sections/04-ecology.css`'s `.mk-ecology .flickity-viewport`,
      written for that section alone. `07-building` and `14-amenities` never
      had an equivalent rule at all, despite using the identical Salient
      mechanism. The play button and the amenities-52 photo-follower use two
      further, completely different engines (see B/C/D below) that never had
      one either.

   2. WHERE IT EXISTED, IT LOST. `.mk-ecology .flickity-viewport{cursor:none}`
      is two classes, specificity (0,2,0). Flickity's own vendored rule —
      `vendor/…/plugins/flickity.q-458c954239.css`:
        `.flickity-enabled.is-draggable .flickity-viewport{cursor:move;
         cursor:-webkit-grab;cursor:grab}`
      — is THREE classes, (0,3,0), and wins regardless of file order. This is
      why ecology's own founder-flagged bug was already "fixed" in markup and
      still visibly broken: nobody had measured the COMPUTED value, only
      grepped for the rule's presence. `!important` is the correct tool this
      time — unlike disc PAINT (fill/blur/ink), which Salient's `mouseBind`
      writes INLINE and which no stylesheet `!important` can beat (§ file
      header), the opponent here is another STYLESHEET rule, and `!important`
      beats a non-important rule deterministically, independent of specificity
      ties or load order.

   FOUR SELECTORS, ONE PER ENGINE, EVERY ONE KEYED TO MARKUP THAT ALREADY
   EXISTS — no section HTML/CSS file is touched by this fix:

   A. Salient's native `$t` "horizontal-movement" drag-indicator (ecology,
      building, 14-amenities' slider bodies). `data-indicator-bg` is Salient's
      own attribute already present on every `.nectar-flickity` this project
      gives a drag disc to (grep-verified: exactly those three, plus the
      shell's own `index.html` composition — NOT `21-logos-footer`'s plain
      logo strip, which carries `.nectar-flickity` with no `data-indicator-bg`
      and is correctly excluded). `cursor:none` on `.flickity-viewport`
      inherits down to everything inside it (the slide cells, and — this is
      what silently fixes `07-building`'s heading-wrap "View" region for free —
      any descendant that does not declare its own `cursor`). Flickity's own
      prev/next buttons and page dots are appended as SIBLINGS of
      `.flickity-viewport`, never descendants (`init.js` `sharedEvents`/
      pagination code targets `.$el.find(...)` off the `.nectar-flickity`
      root), so their own `cursor: pointer` is untouched.

   B. The declarative `[data-myk-hover]` API (07-building's heading-wrap,
      09–13-recovery + 10-recovery-41's cards). Excludes `"none"` — OBS-BTN-02's
      deliberate stand-down, where the CTA needs its OWN `cursor: pointer` to
      show. That exclusion is safe by construction, not by luck: CSS
      inheritance never overrides a value an element declares on itself
      (`myk-btn.css`'s `.mk-btn{cursor:pointer}`), no matter how the ancestor
      is declared — verified live, `cursor: pointer` on the CTA, unchanged
      before and after this rule.

      INCLUDES every descendant (`… *`), not just the region root, because of
      a SECOND override this lane measured and did not expect: a real
      `<a href>` inside a suppressed region wins its OWN native pointer back
      from an inherited `cursor:none`, `!important` or not. This is not an
      author stylesheet fight — `CSS.getMatchedStylesForNode` on the live page
      shows ZERO author rule setting `cursor` on the anchor; a bare
      `<a href="#">` with no CSS anywhere computes `cursor: pointer` in this
      Chrome (confirmed in isolation on `data:text/html,<a href=#>`). Chrome's
      UA stylesheet declares `cursor` directly on `:any-link`, and inheritance
      only ever fills in a property with NO declared value on the element —
      once ANY origin (UA included) has one, inheritance is not in the
      contest, so an ancestor's `!important` cannot reach through a link to
      override it. Caught live on `10-recovery-41`: its `.nectar-post-grid`
      carries the region's `data-myk-hover`, but the actual pointer target is
      a child `a.nectar-post-grid-link` (Salient's own post-grid markup) —
      computed `cursor: pointer` survived rule B until `*` was added, even
      though the `View` disc was painting correctly the entire time. No
      `[data-myk-hover="none"]` marker is currently nested inside a `general/*`
      region (grep-verified — the only `"none"` instances are the three
      ecology CTAs, which sit under A's `.flickity-viewport`, never under a
      `[data-myk-hover]` root), so `*` here needed no stand-down exception.
      Rule A below does NOT need the same `*` treatment: its three CTAs
      already carry their OWN `cursor: pointer` declaration (`myk-btn.css`),
      so inheritance from the viewport never reaches them regardless of
      whether A is written with `*` — confirmed unchanged, `pointer`, before
      and after this file's edit. A's only href-bearing descendants are
      grep-verified to be exactly those three CTAs (ecology), zero anchors at
      all (building), and one `href`-less `<a>` that Chrome's `:any-link` UA
      rule does not match at all (14-amenities) — so A has no instance of B's
      failure mode to guard against today. If a future slide adds a real
      interactive `<a href>` inside A's scope that should NOT keep the native
      pointer, extend A the same way B is extended here, and give whichever
      element must keep it its own scoped stand-down.

   C. The play button (`Gi()`/`.play_button.follow_mouse` — cursors.md's
      "primary/play", surface `"inflow"`). A THIRD engine again: no shared
      singleton, no `data-myk-hover`, and grep-verified zero pre-existing
      `cursor` rule anywhere touches `.play_button` or
      `.nectar_video_player_self_hosted`, so there is no specificity fight to
      win here — `!important` is kept anyway so a future incidental
      `a{cursor:pointer}` cannot silently reopen this bug.

   D. `16-amenities-52`'s circular photo-follower (Salient's own
      `data-style="mouse_follow_image"` — the JS controller's "media/reveal"
      row, declared OUT OF TAXONOMY and explicitly paints nothing; see
      `js/myk-hover-cursor.js` §1). The photo itself is the replacement
      affordance; the native pointer must stand down the same as it does for
      a disc.

   `prefers-reduced-motion` gets NO override here (unlike §8): hiding a
   SECOND, redundant cursor is not a motion effect, and the replacement
   icon/photo still fully paints under reduced motion — restoring the native
   pointer there would reintroduce exactly this bug for that audience.
   `cursor` has no rendered effect on a touch surface at all, so no
   `@media (hover: none)` companion is needed either.
   -------------------------------------------------------------------------- */

/* A — Salient's native drag-indicator sliders. */
.nectar-flickity[data-indicator-bg] .flickity-viewport {
  cursor: none !important;
}

/* B — the declarative API, everything except the explicit stand-down. `*`
   is required, not decorative: see the header note above — a real `<a href>`
   descendant (10-recovery-41's `.nectar-post-grid-link`) wins its native
   pointer back from a merely-inherited `cursor:none` regardless of
   `!important` on the ancestor, because the UA stylesheet declares `cursor`
   directly on the link and inheritance never competes once any origin has. */
[data-myk-hover]:not([data-myk-hover="none"]),
[data-myk-hover]:not([data-myk-hover="none"]) * {
  cursor: none !important;
}

/* C — the play button (a third, unrelated engine). */
.play_button.follow_mouse {
  cursor: none !important;
}

/* D — the amenities-52 photo-follower ("media/reveal", out of taxonomy).

   R19-FIX — scoped to `[data-has-img="true"]`, was unconditional. This rule's
   own premise, stated above, is "the photo itself is the replacement
   affordance" — true for the row's own live pointer only while a follower
   photo actually exists to paint. R19-03 (sections/16-amenities-52.css §9c)
   deleted the `.nectar-post-grid-item-bg-wrap` outright, and flipped
   `data-has-img` to `"false"`, on the 41 Unsplash-sourced rows (plus the one
   original always-no-image row, 42 of 47 total) — this rule still matched
   all of them unconditionally, so a real pointer sweeping the grid went
   fully invisible over those 42 rows with no replacement affordance shown in
   its place: no OS cursor (this rule) and no photo (deleted by R19-03).
   CONFIRMED CRITICAL by r19:verify:amenities. `data-has-img` already lives on
   this exact element (`.nectar-post-grid-item`, not a descendant — verified
   in sections/16-amenities-52.html), the same attribute §9c already keys off
   for the same reason, so no markup change is needed here. The 5 rows that
   still carry a real photo (`data-has-img="true"`) are unaffected — native
   cursor still suppressed there, exactly as before. */
.nectar-post-grid-wrap[data-style="mouse_follow_image"] .nectar-post-grid-item[data-has-img="true"] {
  cursor: none !important;
}
