/* ── Brand mark (.eos-mark) — the bare ":D", drawn, then floating ─────
   The Urban Smiles mark on its own: two dots and the rounded D, NO disc.

   THIS IS NOT THE BADGE, and the separation is deliberate. css/global/badge.css
   owns .eos-badge, which is the mark ON a filled circle — it pops the disc in,
   lands the eyes, paints the smile, and reads as an object sitting on top of a
   photo. The instances this file serves have no circle: they are the mark
   alone, usually large and pale, sitting in the background behind copy. Same
   artwork, different object, so they do not share a class — putting a disc
   behind one of these, or a background treatment on a badge, should be
   impossible by construction rather than a settings mistake.

   What they share is the ARTWORK and the reveal technique: identical path data
   (the same Figma geometry) and the same mask wipe, including the two fixes
   that took a while to find — see the dash note below.

   Wiring: js/reveal.js, via `data-eos-reveal` on the wrapper. No new script.

   Per instance, only these change:
     --mark-ink     the mark's colour        (default --primary-teal)
     --mark-alpha   opacity                  (default 1; watermarks want ~0.06)
     --mark-rot     the tilt                 (default -30deg, per the logo)

   SIZE. The viewBox is the badge's 104x104 so the geometry stays byte-identical
   to a proven asset, which means the box is LARGER than the visible mark: after
   the -30deg tilt the artwork occupies about 55.6 x 60.5 of those 104 units,
   i.e. 53% wide and 58% tall. So a 200px module renders a mark about 116px
   tall. Size instances from that ratio rather than guessing. */

.eos-mark {
  --mark-ink   : var(--primary-teal);
  --mark-alpha : 1;
  /* NOT -30deg. The disc badges tilt 30 degrees; the disc-less marks are a
     different rotation family entirely — measured off the Figma at -21.36deg
     on Services and -18.57deg on the About Us / Home set. Use the tilt class
     below for the latter. */
  --mark-rot   : -21.36deg;

  display        : block;
  width          : 100%;
  /* The viewBox is CROPPED to the artwork (see the markup), so the box IS the
     un-rotated mark and `width` means what it looks like it means. That is
     what makes the design's own numbers usable directly: Figma reports the
     un-rotated art width, so a module width of 29.99% of its panel is
     literally the value the inventory gives. With the badge's square 104
     viewBox the same instance would have needed 87.4%, via a ratio nobody
     would remember. */
  aspect-ratio   : 35.75 / 49.19;
  opacity        : var(--mark-alpha);
  /* Builder offsets read as the mark's CENTRE, matching how the badges are
     placed and how the design reports positions. On the `translate` property,
     not in `transform`, so the float below composes with it instead of
     overwriting it — see the note there. */
  translate      : -50% -50%;
  pointer-events : none;   /* decorative in every instance so far */
  line-height    : 0;
}

/* The About Us / Home watermark family. 2.8 degrees off the default — barely
   visible on a faint background mark, but it is in the design, so it is here. */
.eos-mark-tilt-19 { --mark-rot: -18.57deg; }

/* ── Colourways ──────────────────────────────────────────────────────
   CLASSES, not inline custom properties, and not values inherited from a
   parent. Two reasons, both learned the hard way:

   1. The markup lives in a Divi code module, i.e. inside block-attribute JSON
      inside an HTML comment — and a literal `--` in there TERMINATES the
      comment. So `style="--mark-ink: #fff"` is not available to us at all.
   2. `.eos-mark` declares the defaults on itself, so a `--mark-ink` set on an
      ancestor would lose to it: a declaration on the element always beats an
      inherited value. Setting the colourway on the wrapper looked like it
      worked and rendered teal.

   These rules come after .eos-mark, so they win on order at equal specificity.
   Alpha is kept separate from colour because the two vary independently — the
   panel watermarks are the same white as the photo marks, just far fainter. */
.eos-mark-white { --mark-ink: var(--white); }
.eos-mark-cream { --mark-ink: var(--cream); }
.eos-mark-teal  { --mark-ink: var(--primary-teal); }

.eos-mark-faint  { --mark-alpha: 0.08; }
.eos-mark-fainter { --mark-alpha: 0.04; }

/* Figma #3D5A63 — the CTA watermark. Distinct from -teal, which is the
   lighter --primary-teal used on photos. */
.eos-mark-darker-teal { --mark-ink: var(--darker-teal); }

/* Alpha ladder, weakest last: soft 0.1 → faint 0.08 → fainter 0.04. */
.eos-mark-soft { --mark-alpha: 0.1; }


.eos-mark svg {
  display          : block;
  width            : 100%;
  height           : 100%;
  transform        : rotate(var(--mark-rot));
  transform-origin : 50% 50%;
  /* The tilt pushes the corners outside the cropped viewBox, and SVG clips at
     its own edge by default. Every instance in the design overhangs whatever
     it sits on, so visible is correct — the clipping, where the design has
     any, comes from the container. */
  overflow         : visible;
}

.eos-mark__smile path,
.eos-mark__dot { fill: var(--mark-ink); }

/* Butt caps, overriding the markup's round ones. A round cap paints a full
   round dot even at ZERO dash length, which would show a blob at the smile's
   start point before the eyes had landed. */
.eos-mark__wipe { stroke-linecap: butt; }

/* Each dot grows from its own centre in user units rather than sliding in from
   the artwork's middle. */
.eos-mark__dot_l { transform-origin: 43.99px 32.34px; }
.eos-mark__dot_r { transform-origin: 60.01px 32.34px; }


/* ── Behind the copy (.eos-mark-behind) ──────────────────────────────
   For the watermark instances. Fills its module and sits under the content,
   the same arrangement css/quote-marks.css uses: the module is taken out of
   flow so it consumes none of the group's row gaps, and Divi's own
   .et_pb_code_inner is stretched too — with the artwork inside it absolutely
   positioned, that wrapper measures ZERO high and any percentage inside it
   would collapse.

   z-index -1 needs the PARENT group to establish a stacking context (set its
   Z Index to 0 in the builder), or the mark sinks behind the panel's own
   background instead of sitting on it. */
.et_pb_module.eos-mark-host,
.et_pb_module.eos-mark-host > .et_pb_code_inner {
  position       : absolute;
  inset          : 0;
  pointer-events : none;
}

.eos-mark-behind {
  position  : absolute;
  inset     : 0;
  z-index   : -1;
  translate : none;   /* inset:0 does the placing here, not a centre offset */
}


/* ── Armed ──────────────────────────────────────────────────────────
   js/reveal.js stamps `eos-reveal-js` on <html> before first paint, and that
   class is the ONLY thing that hides anything. No script means no animation,
   never a missing mark. */
html.eos-reveal-js .eos-mark__dot { transform: scale(0); }

/* The dash numbers are 1.01 / 2 / 1.06 and not 1 / 1 / 1, for the reason
   documented at length in badge.css: pathLength="1" normalises the contour to
   1, but Blink's dasher walks a path about 0.25% LONGER than that, and with a
   dash of exactly 1 the leftover lands on the path's start point — which, on a
   closed contour, is the middle of the D's top bar. It shows as a painted
   hairline before the animation runs and as a missing hairline after it. A 1%
   longer dash swallows it; the doubled gap stops it wrapping into the next
   dash while armed; the 1.06 offset parks the whole path inside that gap. */
html.eos-reveal-js .eos-mark__wipe {
  stroke-dasharray  : 1.01 2;
  stroke-dashoffset : 1.06;
}


/* ── Playing ────────────────────────────────────────────────────────
   Eyes first, left then right, then the smile paints as the second eye
   lands — so the three read as one gesture and the shape is never briefly a
   lone mouth. */
html.eos-reveal-js .eos-mark.is-in .eos-mark__dot_l {
  animation : eos-mark-dot 0.30s cubic-bezier(0.34, 1.56, 0.64, 1) 0.06s forwards;
}
html.eos-reveal-js .eos-mark.is-in .eos-mark__dot_r {
  animation : eos-mark-dot 0.30s cubic-bezier(0.34, 1.56, 0.64, 1) 0.14s forwards;
}
html.eos-reveal-js .eos-mark.is-in .eos-mark__wipe {
  animation : eos-mark-wipe 0.60s ease-in-out 0.38s forwards;
}

/* Then the mask is detached, because at rest it contributes nothing to the
   picture and everything to the risk: the residue above is a Blink
   measurement quirk, and nothing says another engine's is the same size.
   Dropping it makes the resting state exact by construction everywhere. */
html.eos-reveal-js .eos-mark.is-in .eos-mark__smile {
  animation : eos-mark-unmask 0.01s linear 0.98s forwards;   /* 0.38 + 0.60 */
}

@keyframes eos-mark-dot    { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes eos-mark-wipe   { to { stroke-dashoffset: 0; } }
@keyframes eos-mark-unmask { to { mask: none; } }


/* ── The lingering float (.eos-mark-float) ───────────────────────────
   Opt in alongside. The tilt lives on the inner <svg> and the float on the
   wrapper, so the two compose instead of overwriting each other — the same
   reason badge.css moves its centring to the `translate` property. Nothing
   here touches layout, so it cannot move CLS.

   The rise is a percentage because these render anywhere from ~90px to well
   over 400px across the site; a fixed pixel rise is a twitch on the small
   ones and a lurch on the large. */
.eos-mark-float {
  --mark-float-rise : 4%;
  --mark-float-tilt : 2.5deg;
  --mark-float-dur  : 7.5s;
}

/* Delayed past the end of the draw (0.38 + 0.60), and the keyframes start and
   end at zero so the hand-off has nothing to snap to. */
html.eos-reveal-js .eos-mark-float.is-in {
  animation : eos-mark-float var(--mark-float-dur) ease-in-out 1.1s infinite;
}

@keyframes eos-mark-float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  25%      { transform: translateY(calc(-1 * var(--mark-float-rise))) rotate(calc(-1 * var(--mark-float-tilt))); }
  75%      { transform: translateY(var(--mark-float-rise)) rotate(var(--mark-float-tilt)); }
}


/* Motion off: land on the finished mark. Overrides the armed state rather than
   the animations, so nothing is caught mid-paint. */
@media (prefers-reduced-motion: reduce) {
  html.eos-reveal-js .eos-mark__dot   { transform: scale(1); }
  html.eos-reveal-js .eos-mark__smile { mask: none; }
  html.eos-reveal-js .eos-mark__wipe  { stroke-dashoffset: 0; }
  html.eos-reveal-js .eos-mark.is-in .eos-mark__dot,
  html.eos-reveal-js .eos-mark.is-in .eos-mark__smile,
  html.eos-reveal-js .eos-mark.is-in .eos-mark__wipe,
  html.eos-reveal-js .eos-mark-float.is-in { animation: none; }
}


/* ── Safari: keep the mark under the copy ───────────────────────────
   The float animates a transform, which makes Safari promote the mark to its
   own compositing layer — and it then paints that layer above later siblings
   that rely on DOM order alone (every Divi module here is z-index: auto). The
   mark starts behind the text and flips in front once the layer is promoted.
   Chromium does not do this, so it only shows up in Safari.

   Making the order explicit removes the engine's discretion. Scoped to columns
   that actually contain a mark, and the sibling combinator lifts only the
   modules that come AFTER it, so nothing else on the site is touched. */
.et_pb_module:has(.eos-mark) { z-index: 0; }

/* Skip modules that carry their own stacking intent: a .eos-badge sets z-index
   10 in the builder because it must sit above a photo, and lifting it to 1 here
   sank the Services wellness-scan badge behind its image. */
.et_pb_module:has(.eos-mark) ~ .et_pb_module:not(:has(.eos-badge)):not(:has(.eos-mark)) {
  position : relative;
  z-index  : 1;
}
