From 3bbc0016d9a12ebaabd1a834ae0abaf3077a9dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Tue, 16 Jun 2026 16:52:03 +0200 Subject: [PATCH] fix(cycle): restore the wellness-tile entrance so the ring renders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wheel tile, phase-education card, and dashboard cycle tile each set both data-revealed and .wellness-tile-rise on the same node. The keyframe selector is [data-revealed="true"] .wellness-tile-rise (descendant combinator), so it never matched a same-node pair — the tiles stayed at the rise rule's opacity: 0, invisible but still boxed. Lift data-revealed onto a contents wrapper (the documented pattern from the cycle insight summary card) so the entrance plays and the signature ring paints. --- src/components/cycle/cycle-ring-tile.tsx | 42 +++++++++++-------- src/components/cycle/cycle-view.tsx | 32 +++++++++----- src/components/cycle/phase-education-card.tsx | 32 ++++++++------ 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/components/cycle/cycle-ring-tile.tsx b/src/components/cycle/cycle-ring-tile.tsx index 2e20b4761..b7363c57e 100644 --- a/src/components/cycle/cycle-ring-tile.tsx +++ b/src/components/cycle/cycle-ring-tile.tsx @@ -92,23 +92,28 @@ export function CycleRingTile({ className }: { className?: string }) { const hue = PHASE_HUE[wheel.phase]; return ( - + // `data-revealed` must sit on an ANCESTOR of `.wellness-tile-rise` — the + // keyframe selector is `[data-revealed="true"] .wellness-tile-rise` + // (descendant combinator). Both on the same node never matched, leaving the + // tile stuck at the rise rule's `opacity: 0`. The `contents` wrapper carries + // the flag without adding a layout box. +
+
- + +
); } diff --git a/src/components/cycle/cycle-view.tsx b/src/components/cycle/cycle-view.tsx index 7f3b9b103..9f3d155e3 100644 --- a/src/components/cycle/cycle-view.tsx +++ b/src/components/cycle/cycle-view.tsx @@ -159,20 +159,29 @@ export function CycleView() {
{/* Wheel + compact phase card — grouped so they stick together. */}
- {/* Wheel — the signature ring on the premium wellness-tile surface. */} + {/* Wheel — the signature ring on the premium wellness-tile surface. + `data-revealed` must sit on an ANCESTOR of `.wellness-tile-rise` + — the keyframe selector is `[data-revealed="true"] + .wellness-tile-rise` (descendant combinator). Both on the same + node never matched, leaving the tile stuck at the rise rule's + `opacity: 0` (invisible but still boxed). The `contents` wrapper + carries the flag without adding a layout box. */}
+
{loading ? (
@@ -216,6 +225,7 @@ export function CycleView() { {t("cycle.ring.firstPeriodCta")} ) : null} +
{/* Phase-education card beneath the wheel — the single instance, diff --git a/src/components/cycle/phase-education-card.tsx b/src/components/cycle/phase-education-card.tsx index 681e2d9ed..eb8e65bcd 100644 --- a/src/components/cycle/phase-education-card.tsx +++ b/src/components/cycle/phase-education-card.tsx @@ -107,18 +107,23 @@ export function PhaseEducationCard({ const phaseName = phase ? t(`cycle.phase.${phase}`) : null; return ( -
+ // `data-revealed` must sit on an ANCESTOR of `.wellness-tile-rise` — the + // keyframe selector is `[data-revealed="true"] .wellness-tile-rise` + // (descendant combinator). Both on the same node never matched, leaving the + // tile stuck at the rise rule's `opacity: 0`. The `contents` wrapper carries + // the flag without adding a layout box. +
+
{/* Zone 1 — eyebrow + phase name with a hue dot (never colour-only). */}
)} -
+
+
); }