/* Hallmark · macrostructure: bespoke vertical thread · tone: soft, personal · anchor hue: wine red
 * theme: custom · vibe: "blush paper, wine ink, handwritten" · paper oklch(95% 0.022 18) · accent oklch(50% 0.19 18)
 * fonts: Aref Ruqaa + IBM Plex Sans Arabic · axes: light / calligraphic-serif / warm
 */

:root {
  --color-paper: oklch(95.5% 0.02 18);
  --color-paper-2: oklch(98.5% 0.008 30);
  --color-ink: oklch(30% 0.09 16);
  --color-ink-soft: oklch(48% 0.06 16);
  --color-accent: oklch(50% 0.19 18);
  --color-blush: oklch(80% 0.09 8);
  --color-blush-soft: oklch(89% 0.05 10);
  --color-tape: oklch(88% 0.06 8 / 0.75);

  --font-display: "Aref Ruqaa", "Noto Naskh Arabic", serif;
  --font-body: "IBM Plex Sans Arabic", system-ui, sans-serif;

  --text-sm: 0.9375rem;
  --text-md: 1.0625rem;
  --text-lg: clamp(1.75rem, 1.4rem + 1.6vw, 2.5rem);
  --text-display: clamp(4rem, 2.6rem + 7vw, 8.5rem);

  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2.5rem;
  --space-2xl: 4rem;
  --space-3xl: 7rem;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-draw: 900ms;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { overflow-x: clip; }

body {
  margin: 0;
  background-color: var(--color-paper);
  /* soft blush fade; the doodles live on body::before */
  background-image: linear-gradient(180deg, var(--color-paper) 0%, var(--color-blush-soft) 100%);
  background-attachment: fixed;
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-md);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  /* normal arrow over text instead of the typing bar; links still get the hand */
  cursor: default;
}

/* top bar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background: oklch(95.5% 0.02 18 / 0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.375rem;
  color: var(--color-ink);
  text-decoration: none;
  white-space: nowrap;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0.4rem 1rem;
  border: 1.5px solid var(--color-accent);
  border-radius: 999px;
  color: var(--color-accent);
  font-weight: 600;
  font-size: var(--text-sm);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 160ms var(--ease-out), color 160ms var(--ease-out);
}

.pill:hover {
  background: var(--color-accent);
  color: var(--color-paper);
}

.pill:active { translate: 0 1px; }

.pill:focus-visible,
.brand:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 3px;
}

.ring {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linejoin: round;
}

.ring .stone { fill: currentColor; stroke-width: 1; }

@media (min-width: 900px) {
  .topbar { padding-inline: var(--space-xl); }
}

/* hero */

.hero {
  text-align: center;
  padding: var(--space-3xl) var(--space-md) var(--space-xl);
}

.hero-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-display);
  line-height: 1.1;
  color: var(--color-ink);
}

.hero-title {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 0.18em;
}

.person {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
}

/* المهندس / المهندسة above each name */
.eng {
  font-size: clamp(1.125rem, 0.9rem + 1vw, 1.625rem);
  font-weight: 400;
  line-height: 1.2;
  color: var(--color-ink-soft);
}

/* أنا and أمين share one spot; hover, focus, or a tap swaps them */
.me {
  display: inline-grid;
  justify-items: center;
  outline: none;
}

.me > span {
  grid-area: 1 / 1;
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out);
}

.me .real {
  opacity: 0;
  transform: translateY(0.25em);
  color: var(--color-accent);
}

.me:hover .alias,
.me:focus-visible .alias,
.me.flip .alias {
  opacity: 0;
  transform: translateY(-0.25em);
}

.me:hover .real,
.me:focus-visible .real,
.me.flip .real {
  opacity: 1;
  transform: none;
}

.me:focus-visible { text-decoration: underline 2px var(--color-blush); text-underline-offset: 0.15em; }

.her { white-space: nowrap; }

.name {
  position: relative;
  display: inline-block;
  color: var(--color-accent);
}

/* the big و sits in the middle, level with the names */
.and { align-self: flex-end; }

/* job titles under المهندس / المهندسة: red team and blue team */
:root {
  --color-red-team: oklch(52% 0.2 25);
  --color-blue-team: oklch(52% 0.16 255);
}

.role {
  margin-top: 0.15rem;
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}

.role.red { color: var(--color-red-team); }
.role.blue { color: var(--color-blue-team); }

.role .emo { font-weight: 400; }

.scribble {
  position: absolute;
  inset-inline: -4%;
  bottom: -0.08em;
  width: 108%;
  height: 0.22em;
  overflow: visible;
}

.scribble path {
  fill: none;
  stroke: var(--color-blush);
  stroke-width: 5;
  stroke-linecap: round;
}

.hero-sub {
  margin: var(--space-lg) auto 0;
  max-width: 34ch;
  color: var(--color-ink-soft);
  text-wrap: balance;
}

/* timeline */

.timeline {
  position: relative;
  max-width: 880px;
  margin: 0 auto;
  padding: var(--space-2xl) var(--space-md) var(--space-3xl);
}

.thread {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.thread path {
  fill: none;
  stroke-linecap: round;
}

.thread-done {
  stroke: var(--color-accent);
  stroke-width: 2.5;
}

.thread-next {
  stroke: var(--color-blush);
  stroke-width: 2;
  stroke-dasharray: 2 9;
}

.event {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 7rem minmax(0, 1fr);
  align-items: center;
  min-height: 9rem;
}

.event + .event { margin-top: var(--space-2xl); }

.dot {
  grid-column: 2;
  grid-row: 1;
  justify-self: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-accent);
  box-shadow: 0 0 0 6px var(--color-paper);
  z-index: 1;
}

.is-next .dot {
  background: var(--color-paper);
  border: 2px dashed var(--color-blush);
}

.card {
  grid-row: 1;
  grid-column: 1;
  width: fit-content;
  max-width: 100%;
  /* hug the thread: in RTL, "end" of column 1 is its left edge */
  justify-self: end;
  text-align: start;
}

/* alternate sides; column 1 is the right side in RTL */
.event:nth-of-type(even) .card {
  grid-column: 3;
  justify-self: start;
}

.date {
  display: block;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-accent);
  letter-spacing: 0;
}

.title {
  margin: var(--space-xs) 0 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-lg);
  line-height: 1.35;
  color: var(--color-ink);
  overflow-wrap: anywhere;
  min-width: 0;
}

/* game names inside a title: the handwriting font has no Latin letters */
.title .game {
  font-family: var(--font-body);
  font-size: 0.7em;
  font-weight: 600;
  color: var(--color-accent);
}

.note {
  margin: var(--space-sm) 0 0;
  color: var(--color-ink-soft);
}

.is-next .date { color: var(--color-ink-soft); font-weight: 500; }
.is-next .title { color: var(--color-ink-soft); }

/* photos: a print taped to the page, tilted a little */

.photo {
  position: relative;
  margin: 0 0 var(--space-lg);
  padding: 10px 10px 12px;
  width: 300px;
  max-width: 100%;
  background: var(--color-paper-2);
  box-shadow: 0 1px 2px oklch(30% 0.09 16 / 0.12), 0 8px 24px oklch(30% 0.09 16 / 0.08);
  rotate: -2deg;
}

.event:nth-of-type(even) .photo { rotate: 1.5deg; }

.photo::before {
  content: "";
  position: absolute;
  top: -12px;
  inset-inline-start: 50%;
  width: 84px;
  height: 24px;
  translate: 50% 0;
  background: var(--color-tape);
  rotate: 3deg;
}

.photo.wide { width: 400px; }

/* photo placed under the text instead of above it */
.photo:not(:first-child) { margin: var(--space-lg) 0 0; }

.photo.small { width: 200px; }

.photo a { display: block; }

.photo img {
  display: block;
  width: 100%;
  height: auto;
}

/* a little note written on the bottom of the print */
.photo figcaption {
  margin-top: var(--space-sm);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  line-height: 1.5;
  text-align: center;
  color: var(--color-ink-soft);
}

/* ending */

.end {
  text-align: center;
  padding: 0 var(--space-md) var(--space-3xl);
  color: var(--color-ink-soft);
}

.end p {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
}

.heart svg {
  width: 28px;
  height: 28px;
  margin-top: var(--space-md);
  fill: var(--color-accent);
}

/* phone: thread runs down the right edge, all cards to its left */

@media (max-width: 640px) {
  .hero { padding-top: var(--space-2xl); }

  /* zig-zag: odd memories sit on the right with their dot on the right edge,
     even ones on the left with the dot on the left edge, and the thread
     swings across between them */
  .event {
    grid-template-columns: 3rem minmax(0, 1fr);
    min-height: 0;
    align-items: start;
  }

  .event:nth-of-type(even) {
    grid-template-columns: minmax(0, 1fr) 3rem;
  }

  .dot {
    grid-column: 1;
    margin-top: 0.55rem;
  }

  .event:nth-of-type(even) .dot { grid-column: 2; }

  .card {
    grid-column: 2;
    justify-self: start;
  }

  .event:nth-of-type(even) .card {
    grid-column: 1;
    justify-self: end;
    text-align: end;
  }

  .event + .event { margin-top: 5rem; }

  .title { font-size: clamp(1.5rem, 1.2rem + 1.6vw, 1.875rem); }

  .photo { max-width: 100%; }

  /* left-side photos lean the other way so the page feels balanced */
  .event:nth-of-type(even) .photo { margin-inline-start: auto; }
}

/* decorations: hand-drawn hearts and sparkles around the title */

.hero { position: relative; }

.doodles {
  display: block;
  position: absolute;
  inset: 0;
  max-width: 760px;
  margin: 0 auto;
  pointer-events: none;
}

.d {
  position: absolute;
  fill: none;
  stroke: var(--color-blush);
  stroke-width: 1.6;
  stroke-linejoin: round;
  overflow: visible;
  animation: float 7s var(--ease-in-out) infinite;
}

.d.solid { fill: var(--color-blush-soft); stroke: var(--color-blush); }
.d.spark { fill: var(--color-blush); stroke: none; }

.d1 { width: 34px; height: 34px; top: 30%; inset-inline-start: 6%; rotate: -14deg; }
.d2 { width: 22px; height: 22px; top: 26%; inset-inline-end: 9%; animation-delay: -2s; }
.d3 { width: 18px; height: 18px; top: 74%; inset-inline-end: 16%; rotate: 12deg; animation-delay: -4s; }
.d4 { width: 14px; height: 14px; top: 80%; inset-inline-start: 18%; animation-delay: -1s; }
.d5 { width: 14px; height: 14px; top: 16%; inset-inline-end: 30%; rotate: 8deg; animation-delay: -5s; }

@keyframes float {
  50% { translate: 0 -7px; }
}

/* the heart that rides the tip of the thread */

.rider {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  fill: var(--color-accent);
  z-index: 2;
  pointer-events: none;
  filter: drop-shadow(0 2px 4px oklch(50% 0.19 18 / 0.35));
  opacity: 0;
  transition: opacity 250ms var(--ease-out);
  will-change: translate, scale;
}

.rider.show { opacity: 1; }

/* the heart beats while it rides; the svg itself is moved by JS, so beat the path */
.rider-heart .heart-shape {
  transform-box: fill-box;
  transform-origin: center;
  animation: beat var(--beat, 1.5s) var(--ease-in-out) infinite;
}

.rider-chat { width: 26px; height: 26px; margin: -13px 0 0 -13px; }

/* life before Sana: a little seedling, swaying and waiting to grow */
:root {
  --color-soil: oklch(50% 0.06 55);
  --color-stem: oklch(60% 0.11 140);
  --color-leaf: oklch(72% 0.14 138);
  --color-leaf-2: oklch(79% 0.15 135);
}

.rider-alone {
  width: 36px;
  height: 36px;
  margin: -20px 0 0 -18px;
  filter: drop-shadow(0 2px 3px oklch(40% 0.05 120 / 0.25));
}

.rider-alone .soil { fill: var(--color-soil); }
.rider-alone .stem { stroke: var(--color-stem); }
.rider-alone .leaf { fill: var(--color-leaf); }
.rider-alone .leaf:last-child { fill: var(--color-leaf-2); }

.rider-alone .sprout {
  transform-box: view-box;
  transform-origin: 16px 24px;
  animation: sprout 3s var(--ease-in-out) infinite;
}

@keyframes sprout {
  0%, 100% { transform: rotate(-5deg) scale(1); }
  50% { transform: rotate(5deg) scale(1.06); }
}


/* 🗣️ talking head (from صرت علّمها): the sound waves pulse out one by one */
.rider-talk {
  width: 30px;
  height: 30px;
  margin: -15px 0 0 -15px;
}

.rider-talk .head { fill: var(--color-accent); }
.rider-talk .waves { stroke: var(--color-accent); }
.rider-talk .waves path { animation: speak 1.1s var(--ease-out) infinite; }
.rider-talk .wave2 { animation-delay: 0.15s; }
.rider-talk .wave3 { animation-delay: 0.3s; }

@keyframes speak {
  0%, 100% { opacity: 0.15; }
  35% { opacity: 1; }
}

@media (max-width: 640px) {
  .rider-talk { width: 26px; height: 26px; margin: -13px 0 0 -13px; }
}

/* three dots, like the other person is typing */
.rider-chat .typing { animation: typing 1.2s var(--ease-in-out) infinite; }
.rider-chat .typing:nth-of-type(2) { animation-delay: 0.15s; }
.rider-chat .typing:nth-of-type(3) { animation-delay: 0.3s; }

@keyframes typing {
  0%, 60%, 100% { opacity: 0.35; }
  30% { opacity: 1; }
}

/* dots fill in when the thread reaches them */

.js .is-done .dot {
  background: var(--color-paper);
  border: 2px solid var(--color-accent);
  transition: background-color 300ms var(--ease-out);
}

.js .is-done .dot.lit {
  background: var(--color-accent);
  animation: pop 420ms var(--ease-out);
}

@keyframes pop {
  0% { scale: 1; }
  45% { scale: 1.6; }
  100% { scale: 1; }
}

/* entrance: title on load, memories as they scroll into view */

.js .hero-title,
.js .hero-sub {
  animation: rise 900ms var(--ease-out) both;
}

.js .hero-sub { animation-delay: 250ms; }

.js .scribble path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: draw 900ms var(--ease-out) 650ms forwards;
}

.js .card {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 700ms var(--ease-out), transform 700ms var(--ease-out);
}

.js .card.seen {
  opacity: 1;
  transform: none;
}

.js .card .photo {
  transform: scale(0.94);
  transition: transform 900ms var(--ease-out) 120ms;
}

.js .card.seen .photo { transform: none; }

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

@keyframes draw {
  to { stroke-dashoffset: 0; }
}

/* a slow heartbeat at the end */

.heart svg {
  animation: beat 2.4s var(--ease-in-out) infinite;
  transform-origin: center;
}

@keyframes beat {
  0%, 40%, 100% { transform: scale(1); }
  10% { transform: scale(1.18); }
  20% { transform: scale(1); }
  30% { transform: scale(1.12); }
}

@media (max-width: 640px) {
  .d1 { width: 24px; height: 24px; top: 22%; inset-inline-start: 4%; }
  .d2 { width: 16px; height: 16px; top: 20%; inset-inline-end: 6%; }
  .d3 { width: 14px; height: 14px; top: 86%; inset-inline-end: 8%; }
  .d4 { top: 88%; inset-inline-start: 10%; }
  .d5 { display: none; }
  .rider { width: 18px; height: 18px; margin: -9px 0 0 -9px; }
  .rider-chat { width: 22px; height: 22px; margin: -11px 0 0 -11px; }
  .rider-alone { width: 32px; height: 32px; margin: -18px 0 0 -16px; }
  .timeline { padding-top: 6rem; }
}

@media (prefers-reduced-motion: reduce) {
  .d, .heart svg { animation: none; }
  .js .hero-title, .js .hero-sub { animation: none; }
  .js .scribble path { animation: none; stroke-dashoffset: 0; }
  .js .card, .js .card .photo { transform: none; transition: opacity 150ms linear; }
  .js .is-done .dot { background: var(--color-accent); animation: none; }
  .rider { display: none; }
}

/* the doodle pattern sits on its own layer so it can drift slowly */
body::before {
  content: "";
  position: fixed;
  inset: -280px;
  z-index: -1;
  background: url("shared/pattern.svg") 0 0 / 280px 280px;
  animation: pan 60s linear infinite;
  will-change: transform;
  pointer-events: none;
}

@keyframes pan {
  to { transform: translate(-280px, -280px); }
}

@media (prefers-reduced-motion: reduce) {
  body::before { animation: none; }
}

/* hearts drifting up behind everything */

.drift {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.drift svg {
  position: absolute;
  bottom: -40px;
  width: 16px;
  height: 16px;
  fill: var(--color-blush);
  opacity: 0;
  animation: drift 18s linear infinite;
}

.drift svg:nth-child(1) { left: 6%;  animation-delay: 0s; }
.drift svg:nth-child(2) { left: 24%; animation-delay: -7s;  width: 11px; height: 11px; }
.drift svg:nth-child(3) { left: 47%; animation-delay: -13s; width: 13px; height: 13px; }
.drift svg:nth-child(4) { left: 68%; animation-delay: -4s;  width: 20px; height: 20px; }
.drift svg:nth-child(5) { left: 85%; animation-delay: -10s; width: 12px; height: 12px; }
.drift svg:nth-child(6) { left: 94%; animation-delay: -16s; }

@keyframes drift {
  0%   { opacity: 0;   transform: translate(0, 0) rotate(-10deg); }
  10%  { opacity: 0.55; }
  50%  { transform: translate(14px, -55vh) rotate(8deg); }
  90%  { opacity: 0.45; }
  100% { opacity: 0;   transform: translate(-6px, -110vh) rotate(-6deg); }
}

.hero, .timeline, .end { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .drift { display: none; }
}

/* the engagement ring that rides the dotted part of the thread */

:root {
  --color-gold: oklch(74% 0.11 82);
  --color-gem: oklch(98% 0.012 10);
}

.ring-rider {
  position: absolute;
  top: 0;
  left: 0;
  width: 30px;
  height: 30px;
  margin: -21px 0 0 -15px; /* sit the band, not the stone, on the line */
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms var(--ease-out);
  filter: drop-shadow(0 2px 4px oklch(30% 0.09 16 / 0.25));
  will-change: transform;
}

.ring-rider.show { opacity: 1; }

.ring-rider .band { stroke: var(--color-gold); }
.ring-rider .gem { fill: var(--color-gem); stroke: var(--color-accent); }
.ring-rider .facets { stroke: var(--color-accent); }

.ring-rider .gem,
.ring-rider .facets {
  transform-origin: 16px 10px;
  animation: sparkle 2.6s var(--ease-in-out) infinite;
}

@keyframes sparkle {
  0%, 70%, 100% { scale: 1; }
  80% { scale: 1.15; }
}

@media (max-width: 640px) {
  .ring-rider { width: 26px; height: 26px; margin: -18px 0 0 -13px; }
}

@media (prefers-reduced-motion: reduce) {
  .ring-rider { display: none; }
}

/* shy face, hand over the mouth (after الرؤية الشرعية) */

:root {
  --color-face: oklch(85% 0.14 88);
  --color-face-ink: oklch(42% 0.07 65);
  --color-hand: oklch(77% 0.13 72);
  --color-hand-line: oklch(60% 0.12 65);
  --color-cheek: oklch(74% 0.12 20);
}

.rider-shy,
.rider-dua {
  width: 32px;
  height: 32px;
  margin: -16px 0 0 -16px;
  filter: drop-shadow(0 2px 3px oklch(40% 0.05 60 / 0.25));
}

.rider-shy .face { fill: var(--color-face); }
.rider-shy .eyes { stroke: var(--color-face-ink); }
.rider-shy .blush { fill: var(--color-cheek); }
.rider-shy .hand { fill: var(--color-hand); }
.rider-shy .fingers { stroke: var(--color-hand-line); }

.rider-shy .face,
.rider-shy .eyes,
.rider-shy .blush,
.rider-shy .hand,
.rider-shy .fingers {
  transform-box: view-box;
  transform-origin: 16px 28px;
}

.rider-shy .face,
.rider-shy .eyes,
.rider-shy .hand,
.rider-shy .fingers { animation: giggle 1.6s var(--ease-in-out) infinite; }

.rider-shy .blush { animation: giggle 1.6s var(--ease-in-out) infinite, blush 2s var(--ease-in-out) infinite; }

@keyframes giggle {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-6deg); }
  75% { transform: rotate(6deg); }
}

@keyframes blush {
  50% { opacity: 0.45; }
}

/* hands open in dua (after الفاتحة) */

.rider-dua .hands {
  fill: var(--color-hand);
  animation: pray 2.4s var(--ease-in-out) infinite;
}

.rider-dua .light {
  fill: var(--color-face);
  transform-box: fill-box;
  transform-origin: center;
  animation: twinkle 2.4s var(--ease-in-out) infinite;
}

@keyframes pray {
  50% { transform: translateY(-1.5px); }
}

@keyframes twinkle {
  0%, 100% { opacity: 0.3; transform: scale(0.7); }
  50% { opacity: 1; transform: scale(1.15); }
}

/* the dotted dots turn pink once the ride reaches them */
.js .is-next .dot.lit {
  background: var(--color-blush);
  border-style: solid;
  transition: background-color 300ms var(--ease-out);
}

/* room below the last event so the ring has somewhere to ride */
.timeline { padding-bottom: 16rem; }
.end { padding-bottom: 45vh; }

/* heart monitor under والقصة لسا بأولها */

.monitor {
  direction: ltr;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  margin-top: var(--space-md);
}

.ecg {
  width: min(120px, 32vw);
  height: auto;
  overflow: visible;
}

.ecg path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ecg-base {
  stroke: var(--color-blush);
  stroke-width: 1.4;
}

.ecg-pulse {
  stroke: var(--color-accent);
  stroke-width: 2.2;
  stroke-dasharray: 0.28 1.5;
  stroke-dashoffset: 0.28;
  filter: drop-shadow(0 0 2px oklch(50% 0.19 18 / 0.6));
  animation: ecg-in 2.4s linear infinite;
}

.ecg-pulse.late { animation-name: ecg-out; }

@keyframes ecg-in {
  0% { stroke-dashoffset: 0.28; }
  45%, 100% { stroke-dashoffset: -1; }
}

@keyframes ecg-out {
  0%, 50% { stroke-dashoffset: 0.28; }
  95%, 100% { stroke-dashoffset: -1; }
}

.monitor .heart svg {
  display: block;
  margin-top: 0;
  /* beat right as the pulse arrives from the left */
  animation-delay: 1.05s;
}

@media (max-width: 640px) {
  .rider-shy, .rider-dua { width: 28px; height: 28px; margin: -14px 0 0 -14px; }
  .timeline { padding-bottom: 12rem; }
}

@media (prefers-reduced-motion: reduce) {
  .ecg-pulse { animation: none; stroke-dasharray: none; stroke-dashoffset: 0; }
}

/* the heart grows at each big moment and stays that size; the springy curve
   overshoots a touch so it feels like it's growing up, not just resizing */
:root { --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); }

.rider-heart { transition: opacity 250ms var(--ease-out), scale 900ms var(--ease-spring); }

/* 💘 cupid's arrow through the heart (at طلبت رقم أهلها) */

:root { --color-cap: oklch(32% 0.09 12); }

.rider-heart { overflow: visible; }

.rider-heart .arrow {
  opacity: 0;
  transform: translate(-26px, 15px);
}

.rider-heart .shaft { stroke: var(--color-gold); }
.rider-heart .tip { fill: var(--color-gold-deep); stroke: var(--color-gold-deep); }
.rider-heart .feather { fill: var(--color-cheek); }
.rider-heart .feather + .feather { fill: var(--color-blush); }

:root { --color-gold-deep: oklch(62% 0.11 80); }

/* flies in fast from the lower left, sticks, and the heart flinches */
.rider-heart.pierced .arrow {
  opacity: 1;
  transform: none;
  transition: transform 450ms var(--ease-out), opacity 150ms linear;
}

.rider-heart.pierced .heart-shape {
  animation: hit 500ms var(--ease-out) 380ms, beat var(--beat, 0.6s) var(--ease-in-out) 900ms infinite;
}

@keyframes hit {
  0% { transform: scale(1); }
  30% { transform: scale(0.82, 0.9) rotate(-6deg); }
  65% { transform: scale(1.12) rotate(3deg); }
  100% { transform: scale(1); }
}

/* 😁 beaming grin (after وافقت تعطيني رقم أهلها): a squash-and-stretch hop,
   with sparkles bursting out one after another */

.rider-giggle .face { fill: var(--color-face); }
.rider-giggle .eyes { stroke: var(--color-face-ink); }
.rider-giggle .mouth { fill: var(--color-face-ink); }
.rider-giggle .teeth { fill: var(--color-paper-2); }
.rider-giggle .gap { stroke: var(--color-tooth-line); }
.rider-giggle .cheek { fill: var(--color-cheek); }
.rider-giggle .beams { fill: var(--color-face); }

:root { --color-tooth-line: oklch(88% 0.02 70); }

.rider-giggle .grin {
  transform-box: view-box;
  transform-origin: 16px 29px;
  animation: hop 1.1s var(--ease-in-out) infinite;
}

.rider-giggle .beam {
  transform-box: fill-box;
  transform-origin: center;
  animation: burst 1.1s var(--ease-out) infinite;
}

.rider-giggle .beam:nth-child(2) { animation-delay: 0.27s; }
.rider-giggle .beam:nth-child(3) { animation-delay: 0.55s; }
.rider-giggle .beam:nth-child(4) { animation-delay: 0.82s; }

@keyframes hop {
  0%, 100% { transform: translateY(0) scale(1.06, 0.92); }
  30% { transform: translateY(-3px) scale(0.95, 1.06); }
  55% { transform: translateY(-3.5px) scale(1, 1) rotate(4deg); }
  80% { transform: translateY(0) scale(1.04, 0.96); }
}

/* the viewBox has room for the sparkles, so the box is a bit bigger */
.rider-giggle {
  width: 40px;
  height: 40px;
  margin: -20px 0 0 -20px;
  filter: drop-shadow(0 2px 3px oklch(40% 0.05 30 / 0.25));
}

@keyframes burst {
  0% { opacity: 0; transform: scale(0.2) rotate(0deg); }
  35% { opacity: 1; transform: scale(1.3) rotate(45deg); }
  70%, 100% { opacity: 0; transform: scale(0.4) rotate(90deg); }
}

@media (max-width: 640px) {
  .rider-giggle { width: 36px; height: 36px; margin: -18px 0 0 -18px; }
}
