/* ── Animated logo badge (.eos-badge) ────────────────────────────────
   The Urban Smiles mark on a disc: the disc pops in, the smile paints
   itself, then the two dots pop. Geometry is Figma's Group 9 export —
   104x104 viewBox, disc r=52 at (52,52).

   Per instance, three custom properties:
     --badge-size   width; 100% fills the code module
     --badge-ink    mark colour   (default --primary-teal)
     --badge-disc   disc colour   (default --cream)

   Placement is NOT here — each badge's position and width are builder
   settings on its code module. The translate below makes those offsets
   read as the badge's centre rather than its top-left corner.

   Wiring: js/badge.js. */

.eos-badge {
  --badge-size : 100%;
  --badge-ink  : var(--primary-teal);
  --badge-disc : var(--cream);
  --badge-rot  : -30deg;

  /* Named so the un-mask below can start exactly when the wipe ends. */
  --badge-wipe-delay : 0.58s;
  --badge-wipe-dur   : 0.60s;

  position       : relative;
  width          : var(--badge-size);
  aspect-ratio   : 1;
  transform      : translate(-50%, -50%);   /* builder offset = centre */
  pointer-events : none;                    /* decorative; never eat clicks */
  line-height    : 0;
}

/* Colourways. Classes rather than inline custom properties: the markup lives
   in block-attribute JSON, where a `--` would terminate the HTML comment the
   block is written in. */
.eos-badge-invert {
  --badge-disc : var(--primary-teal);   /* Figma #4A6871 */
  --badge-ink  : var(--cream);          /* Figma #FBFAF6 */
}

/* In Her Words. Same ink as the default, named so the instance reads as a
   deliberate colourway. */
.eos-badge-light-blue {
  --badge-disc : var(--light-blue);     /* Figma #E7F3FF */
  --badge-ink  : var(--primary-teal);   /* Figma #4A6871 */
}

/* ── .eos-badge-lift — let a badge out of its column ─────────────────
   Divi gives every column `position: relative; z-index: 2`, so a badge can
   never paint above a sibling COLUMN however high its own z-index goes.
   Dropping the context lets it compete at row level instead.

   OPT IN ONLY. Add it when the badge's column belongs BEHIND a sibling that
   would otherwise cover the badge (In Her Words: badge in the photo column,
   grey panel beside it). Do NOT add it when the badge's column has to stay
   ABOVE a sibling — on Services the badge shares the panel column, and
   `auto` there drops the whole panel behind the photo. */
.et_pb_column:has(.eos-badge-lift) { z-index: auto; }

/* An HTML box, not the SVG <circle> it started as: scaling a shape whose
   radius fills the viewBox rasterises against its bounding box and the pop
   visibly squares off at the corners. */
.eos-badge__disc {
  position         : absolute;
  inset            : 0;
  border-radius    : 50%;
  background       : var(--badge-disc);
  transform-origin : 50% 50%;
}

.eos-badge__mark {
  position         : absolute;
  inset            : 0;
  width            : 100%;
  height           : 100%;
  transform-origin : 50% 50%;
  transform        : rotate(var(--badge-rot));
}

.eos-badge__smile path,
.eos-badge__dot { fill: var(--badge-ink); }

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

/* Each dot's own centre in user units, so they grow in place rather than
   sliding out from the mark's centre. */
.eos-badge__dot_l { transform-origin: 43.99px 32.34px; }
.eos-badge__dot_r { transform-origin: 60.01px 32.34px; }


/* ── Armed ──────────────────────────────────────────────────────────
   js/badge.js stamps `eos-badge-js` on <html> before first paint, and that
   class is the only thing that hides anything — no script means no
   animation, never a missing logo. */
html.eos-badge-js .eos-badge__disc { transform: scale(0); }
html.eos-badge-js .eos-badge__dot  { transform: scale(0); }

/* The smile is revealed through a mask stroke running along the band's
   centreline; `pathLength="1"` in the markup makes one dash cover it.

   Not `1 1` / offset `1`: Blink's dasher measures the mark's cubic Béziers
   ~0.25% longer than pathLength resolves, leaving a residue at the end of
   the path — which, closed with Z, is also its start, dead between the eyes.
   The 1% longer dash swallows that residue and the wider gap stops it
   wrapping into the next dash while armed. */
html.eos-badge-js .eos-badge__wipe {
  stroke-dasharray  : 1.01 2;
  stroke-dashoffset : 1.06;
}


/* ── Playing ────────────────────────────────────────────────────────
   Disc pops, the eyes land left-then-right while it settles, the smile
   paints last — one gesture rather than a queue, and never a lone mouth. */
html.eos-badge-js .eos-badge.is-in .eos-badge__disc {
  animation : eos-badge-pop 0.42s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

html.eos-badge-js .eos-badge.is-in .eos-badge__dot_l {
  animation : eos-badge-dot 0.30s cubic-bezier(0.34, 1.56, 0.64, 1) 0.26s forwards;
}
html.eos-badge-js .eos-badge.is-in .eos-badge__dot_r {
  animation : eos-badge-dot 0.30s cubic-bezier(0.34, 1.56, 0.64, 1) 0.34s forwards;
}

html.eos-badge-js .eos-badge.is-in .eos-badge__wipe {
  animation : eos-badge-wipe var(--badge-wipe-dur) ease-in-out var(--badge-wipe-delay) forwards;
}

/* Drop the mask once the wipe ends. Belt to the dash values above: the
   residue they work around is a renderer measurement quirk, so detaching the
   mask makes the resting state exact in any engine. */
html.eos-badge-js .eos-badge.is-in .eos-badge__smile {
  animation : eos-badge-unmask 0.01s linear
              calc(var(--badge-wipe-delay) + var(--badge-wipe-dur)) forwards;
}

/* No float here on purpose — the drifting rise-and-tilt loop belongs to the
   disc-less mark, as `.eos-mark-float` in css/global/brand-mark.css. */

@keyframes eos-badge-pop  { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes eos-badge-dot  { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes eos-badge-wipe { to { stroke-dashoffset: 0; } }

/* A `mask="url(#…)"` presentation attribute loses to any CSS rule. */
@keyframes eos-badge-unmask { to { mask: none; } }


/* Motion off: land on the finished badge. Overrides the armed state rather
   than the animations, so nothing is caught mid-paint. */
@media (prefers-reduced-motion: reduce) {
  html.eos-badge-js .eos-badge__disc,
  html.eos-badge-js .eos-badge__dot  { transform: scale(1); }
  html.eos-badge-js .eos-badge__wipe { stroke-dashoffset: 0; }
  /* Detached outright: a fully-open dashed mask still shows the notch, and
     there is no animation here to wait for. */
  html.eos-badge-js .eos-badge__smile { mask: none; }
  html.eos-badge-js .eos-badge.is-in .eos-badge__disc,
  html.eos-badge-js .eos-badge.is-in .eos-badge__dot,
  html.eos-badge-js .eos-badge.is-in .eos-badge__smile,
  html.eos-badge-js .eos-badge.is-in .eos-badge__wipe { animation: none; }
}
