/* ==========================================================================
   Radha Krishna wedding theme — Invitation section (section 2)
   --------------------------------------------------------------------------
   1. Tokens          <- the unit system, timings, easings, palette
   2. Shell           <- page-background layer + the composition's stage
   3. Composition     <- the static invitation (the reference screenshot)
   4. Responsive      <- nothing: section 1 already did it
   5. Entrance        <- the animation story, layered on top of 3
   6. Reduced motion

   THE UNIT SYSTEM
   ---------------
   Every length in section 3 is written in --u, so the whole invitation —
   artwork, type and spacing alike — is one piece that scales together, and
   the reference proportions hold at any size.

   --u itself is the only thing that has to think about the screen:

       --u = min(screen width / 100, screen height / 125)

   The design is two and a half times taller than it is wide. Sized from the
   width alone, a 1920 monitor would get a five-thousand-pixel poster; sized
   from the height alone, a phone would get a composition wider than the
   phone. The smaller of the two gives the reference design full-bleed on
   phones and portrait tablets, and about two screenfuls on any desktop.

   Because the composition can then be narrower than the screen, every side
   decoration is positioned from --out — the gap between the two — so the
   leaves, lotus, elephants and the garden sit against the EDGES OF THE
   SCREEN whatever size the invitation itself is.

   There are no breakpoints. Nothing below changes at any width.
   ========================================================================== */


/* 1. Tokens =============================================================== */

:root {
  /* The real screen, kept exact by invitation.js: 100vw includes the classic
     desktop scrollbar and 100vh lies on mobile while the browser chrome is
     sliding away. These two are the no-script fallbacks. */
  --vw: 100vw;
  --vh: 100vh;
}

.rk-invite {
  /* --- unit system ---
     --u is the size of everything: one unit of the composition. It is 1% of
     the screen's width, BUT never more than the screen's height will
     comfortably carry, because the reference design is two and a half times
     taller than it is wide. Tie it to width alone and a 1920 monitor gets a
     five-thousand-pixel poster; tie it to height alone and a phone gets a
     composition wider than the phone. min() of the two gives a composition
     that is the reference at phone and tablet sizes — full bleed, exactly as
     drawn — and settles to roughly two screenfuls on a desktop instead of
     five.

       --sw   the composition's own width, 100 units
       --out  how far the screen reaches past it on each side

     Every side decoration is positioned from --out, so the leaves, lotus,
     elephants and the whole garden sit against the EDGES OF THE SCREEN at
     any size, while the invitation itself keeps a size that suits the
     screen it is on. Full bleed and readable are not in conflict once the
     two are separated.                                                    */
  --u: min(calc(var(--vw) / 100), calc(var(--vh) / 100));
  --sw: calc(var(--u) * 100);
  --out: calc((var(--vw) - var(--sw)) / 2);

  /* --- and the artwork unit ---
     BOTH units measure the same thing: a percentage of the invitation. Every
     multiplier in section 3 — a 40-unit couple, a 15.5-unit lotus, a 55-unit
     message — is the proportion that element has in the reference, so the
     artwork and the words are drawn on one ruler and stay in step.
     --a is only slightly the larger of the two, which lets the illustrations
     reach the edges of a wide screen without growing out of scale with the
     text. Keep the two close: pull them apart and the leaves start to
     dwarf the words.
     The illustrations are not type. On a portrait screen they are the same
     size as everything else and the page is the reference exactly, because
     --a can never fall below --u. On a landscape screen, where --u has been
     held back by the height, the artwork keeps growing with the WIDTH, so
     the leaves, the morpankh, the elephants and the garden fill the screen
     instead of huddling round the words. This is how the opening section
     works too: its hands are sized in vw, its names in vh.               */
  --a: max(var(--u), calc(var(--vw) / 101));

  /* --- palette, sampled from the supplied artwork ---
     #404931 is the exact green of the date badge and the divider.           */
  --ink: #404931;
  /* headings, date, script     */
  --ink-soft: #55584a;
  /* invitation message         */
  --ink-teal: #1f4f57;
  /* "Daughter of ..."          */
  --ink-gold: #8a7a30;
  /* "Son of ..."               */
  --paper: #f4f2e4;
  /* matches page-background    */
  --badge: #404931;
  /* the date badge's flat fill */
  --badge-ink: #ffffff;
  /* the day number on it       */

  /* --- easings --- */
  --ease-reveal: cubic-bezier(0.22, 0.61, 0.36, 1);
  /* no overshoot        */
  --ease-glide: cubic-bezier(0.32, 0.02, 0.18, 1);
  /* long, soft landing  */
  --ease-drift: cubic-bezier(0.37, 0.00, 0.63, 1);
  /* sine in-out         */
  --ease-carry: cubic-bezier(0.25, 0.62, 0.30, 1);
  /* moves at once, then
                                                        settles: the feather
                                                        is carried, never
                                                        flung or dropped     */

  /* --- sequence timing (single source of truth) ---
     Read top to bottom, this is the animation story: leaves, feather,
     elephants, lotus, text, names, date, the couple, the garden.            */
  --t-leaf: 0s;
  --d-leaf: 1.5s;
  --t-plume: 1.10s;
  --d-plume: 3.2s;
  --t-eleph-l: 3.30s;
  --d-eleph: 1.8s;
  --t-eleph-r: 3.45s;
  --t-lotus: 3.55s;
  --d-lotus: 1.3s;

  --t-ganesh: 4.40s;
  --t-blessed: 4.75s;
  --t-title: 5.00s;
  --t-divider: 5.20s;
  --t-message: 5.35s;

  --t-riya: 5.60s;
  --t-riya-sub: 6.05s;
  --t-swastik: 6.30s;
  --t-kunal: 6.60s;
  --t-kunal-sub: 7.05s;

  --t-date: 7.45s;
  --t-time: 7.85s;
  --t-couple: 8.25s;
  --d-couple: 1.8s;
  --t-garden-c: 9.50s;
  /* centre group              */
  --t-garden-l: 9.65s;
  /* left group                */
  --t-garden-r: 9.80s;
  /* right group               */
  --d-garden: 1.5s;

  /* The banana clusters are pushed out into the corners so only leaves
     show. This must stay at HALF --leaf-w or more: at the crop line each
     cluster is a bare trunk between 19% and 48% in from its outer edge, and
     that trunk ends in a flat horizontal cut. Push past 50% and the trunk,
     the cut and all, sits off the screen — leaving nothing but foliage
     reaching in from the corner, which is what the reference shows.       */
  --leaf-w: 29;
  --leaf-out: 14.5;

  /* --- the morpankh, the one piece of composition that needs a knob:
     how wide it is, how far the box is lifted, and the room it is given.  */
  --plume-w: 94;
  --plume-lift: 54;
  --plume-band: 58;

  --d-text: 0.85s;
  /* every text reveal                             */
  --d-name: 1.05s;
  /* Riya / Kunal / Swastik, a touch longer        */
}


/* 2. Shell ================================================================ */

/* The section is full width, edge to edge, with no maximum and no centring
   container of its own — only the composition inside it has a measure.     */
.rk-invite {
  position: relative;
  width: 100%;
  max-width: none;
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  /* at least a full screen, free to grow */
  /* Decoration bleeds past the stage on every side — the leaves off the
     left and right, the garden off the bottom — so the section clips its
     own overflow and ends exactly at the edge of its paper. `clip` rather
     than `hidden` on purpose: it creates no scroll container (so it cannot
     add a scrollbar) and no stacking context (so the layering above still
     holds). */
  overflow: clip;
  background-color: var(--paper);
  /* shows through while the texture loads */
}

/* page-background is a layer of the section, not a wrapper round the
   content, so it always covers the section from left edge to right edge.
   The artwork is an even paper texture with soft floral watermarks, so
   `cover` can never distort or crop anything meaningful at any ratio.      */
.rk-invite__paper {
  position: absolute;
  z-index: 1;
  inset: 0;
  background-image: url("../../images/page-background.png");
  background-repeat: no-repeat;
  background-position: center top;
  background-size: cover;
  pointer-events: none;
}

/* The invitation is not part of the page until the visitor asks for it.
   The class is added by script, so with no script at all the invitation is
   simply there and nothing is unreachable. While it is closed the document
   is exactly one screen tall, which is what makes scrolling incapable of
   revealing the invitation — only the button can.                         */
.rk-invite.is-closed {
  display: none;
}

/* ...and once it is open, the opening — already faded to nothing by its own
   stylesheet — gives up its screenful of sky as well, so the invitation
   starts at the very top of the page. */
.rk-opening.is-dismissed {
  display: none;
}

/* Everything the visitor reads and every illustration lives in here.
   The stage has a measure; the section never does.                        */
.rk-invite__stage {
  position: relative;
  z-index: 10;
  width: var(--sw);
  margin: 0 auto;
  padding-bottom: calc(var(--u) * 2);
}

/* every band is its own positioning context, so decoration is anchored to
   the block it belongs with and never drifts when text rewraps */
.rk-inv__head,
.rk-inv__plume-band,
.rk-inv__names,
.rk-inv__when,
.rk-inv__finale {
  position: relative;
}

.rk-inv__art {
  position: absolute;
  pointer-events: none;
}

.rk-inv__art img,
.rk-inv__art>i {
  display: block;
  width: 100%;
  height: auto;
}

.rk-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* 3. Composition ========================================================== */

/* --- 3.1 head ----------------------------------------------------------- */

.rk-inv__head {
  z-index: 4;
  padding: calc(var(--u) * 7) 0 calc(var(--u) * 8);
  text-align: center;
}

.rk-inv__ganesh,
.rk-inv__blessed,
.rk-inv__message,
.rk-inv__time {
  margin: 0;
  font-family: Georgia, "Times New Roman", "Noto Serif", serif;
}

.rk-inv__ganesh {
  font-size: max(13px, calc(var(--u) * 3.7));
  letter-spacing: 0.02em;
  color: var(--ink);
}

.rk-inv__blessed {
  margin-top: calc(var(--u) * 4.4);
  font-size: max(14px, calc(var(--u) * 4.55));
  color: var(--ink);
}

.rk-inv__title {
  margin: calc(var(--u) * 0.6) 0 0;
  font-family: "Ananda", "Norican", "Segoe Script", cursive;
  font-weight: 400;
  font-size: max(28px, calc(var(--u) * 7.1));
  line-height: 1.25;
  color: var(--ink);
}

.rk-inv__divider {
  width: calc(var(--u) * 31);
  margin: calc(var(--u) * 1.2) auto 0;
}

.rk-inv__message {
  max-width: calc(var(--u) * 48);
  margin: calc(var(--u) * 4.2) auto 0;
  font-size: max(12px, calc(var(--u) * 3.35));
  line-height: 1.95;
  color: var(--ink-soft);
  text-wrap: balance;
  /* three even lines, as in the reference */
}

/* banana leaves ----------------------------------------------------------
   banana-leaf.png is one sheet holding both clusters with a wide empty gap
   between them. Each side below is a sprite window onto that sheet showing
   exactly one whole cluster — original pixels, nothing redrawn — so the two
   can enter from opposite edges independently.

   The window stops at the LEAVES. Below about three quarters of the way
   down, each cluster is nothing but a bare vertical trunk — that is what
   was making the corners read as two banana trees standing in a field
   rather than the leaf clusters in the reference. Window = 688 x 771 of
   the 3064 x 1101 sheet; all the percentages below follow from that and
   from nothing else.                                                       */
.rk-leaf {
  aspect-ratio: 688 / 771;
  background-image: url("../../images/banana-leaf.png");
  background-repeat: no-repeat;
  background-size: 445.35% 142.80%;
}

.rk-leaf--l {
  z-index: 2;
  width: calc(var(--a) * var(--leaf-w));
  top: 0;
  left: calc(var(--out) * -1 - var(--a) * var(--leaf-out));
  background-position: 0.04% 26.06%;
}

.rk-leaf--r {
  z-index: 2;
  width: calc(var(--a) * var(--leaf-w));
  top: 0;
  right: calc(var(--out) * -1 - var(--a) * var(--leaf-out));
  background-position: 99.96% 0.30%;
}

/* --- 3.2 the large morpankh --------------------------------------------
     The band is a fixed-ratio box so the feather always has exactly the
     room the reference gives it. The resting rotation lives on the image
     itself and is part of the composition, never part of the animation.    */
.rk-inv__plume-band {
  z-index: 5;
  height: calc(var(--a) * var(--plume-band));
}

/* The image box is nearly square and mostly transparent; what matters is
   where the feather itself lands, so the box is centred on the band and
   allowed to overhang it. --plume-x / --plume-y nudge the artwork inside
   the box so the plume sits centred, not the empty margins around it.     */
.rk-plume {
  position: absolute;
  z-index: 5;
  width: calc(var(--a) * var(--plume-w));
  left: 50%;
  top: 50%;
  margin-left: calc(var(--a) * var(--plume-w) * -0.5 - var(--a) * 3);
  margin-top: calc(var(--a) * var(--plume-lift) * -1);
  pointer-events: none;
}

.rk-plume__fly,
.rk-plume__arc,
.rk-plume__tilt {
  width: 100%;
}

/* the resting angle: the reference lays the feather almost along the page,
   quill low on the left and the eye high on the right */
.rk-plume img {
  width: 100%;
  height: auto;
  transform: rotate(56deg);
}

/* The feather turns about its quill, never about the middle of its box.
   This is the stem tip's position on screen once the image above has been
   rotated — measured from the artwork, so it stays true at every size. */
.rk-plume__tilt {
  transform-origin: 19.03% 77.02%;
}

/* --- 3.3 names ---------------------------------------------------------- */

.rk-inv__names {
  z-index: 4;
  padding: calc(var(--a) * 5) 0 calc(var(--u) * 2);
  text-align: center;
}

.rk-inv__name {
  margin: 0;
  font-family: "Ananda", "Norican", "Segoe Script", cursive;
  font-weight: 400;
  font-size: max(40px, calc(var(--u) * 11.9));
  line-height: 1.15;
  color: var(--ink);
}

.rk-inv__parents {
  margin: calc(var(--u) * 1.1) 0 0;
  font-family: "Poppins", system-ui, sans-serif;
  font-weight: 600;
  font-size: max(11px, calc(var(--u) * 2.88));
  letter-spacing: 0.015em;
  line-height: 1.5;
}

.rk-inv__parents--bride {
  color: var(--ink-teal);
}

.rk-inv__parents--groom {
  color: var(--ink-gold);
}

.rk-inv__swastik {
  width: calc(var(--u) * 6.8);
  margin: calc(var(--u) * 5) auto calc(var(--u) * 4.2);
}

.rk-inv__swastik img {
  display: block;
  width: 100%;
  height: auto;
}

/* the couple's block gets a little more air below it before the date */
.rk-inv__names>.rk-inv__pair--groom {
  margin-bottom: calc(var(--u) * 2);
}

/* lotus, either side of Riya ---------------------------------------------
   lotus-1 and lotus-2 are a mirrored pair; each is placed on the side that
   turns its blooms outward and sweeps its stems in, as in the reference.   */
.rk-lotus--l {
  z-index: 2;
  width: calc(var(--a) * 19);
  left: calc(var(--out) * -1 - var(--a) * 1);
  top: calc(var(--u) * 1);
}

.rk-lotus--r {
  z-index: 2;
  width: calc(var(--a) * 19);
  right: calc(var(--out) * -1 - var(--a) * 1);
  top: calc(var(--u) * 1);
}

/* elephants, either side of Kunal ---------------------------------------- */
.rk-eleph--l {
  z-index: 3;
  width: calc(var(--a) * 18.5);
  left: calc(var(--out) * -1);
  top: calc(var(--u) * 32);
}

.rk-eleph--r {
  z-index: 3;
  width: calc(var(--a) * 18.5);
  right: calc(var(--out) * -1);
  top: calc(var(--u) * 32);
}

/* --- 3.4 date and time -------------------------------------------------- */

.rk-inv__when {
  z-index: 4;
  padding: calc(var(--u) * 2) 0 calc(var(--u) * 4);
  text-align: center;
}

/* the pill and the "22" badge are the supplied artwork; only the two words
   are text, sitting in the empty halves the artwork leaves for them */
.rk-inv__date {
  position: relative;
  width: calc(var(--u) * 63);
  margin: 0 auto;
}

.rk-inv__date-art {
  display: block;
  width: 100%;
  height: auto;
}

.rk-inv__date-day,
.rk-inv__date-month {
  position: absolute;
  top: 50%;
  width: 33%;
  transform: translateY(-50%);
  font-family: Georgia, "Times New Roman", "Noto Serif", serif;
  font-size: max(15px, calc(var(--u) * 4.6));
  line-height: 1;
  color: var(--ink);
  text-align: center;
}

.rk-inv__date-day {
  left: 3%;
}

.rk-inv__date-month {
  right: 3%;
}

/* The day of the month --------------------------------------------------
   time.png has "22" printed into its badge, which would make the date
   permanent. The badge is a single flat colour — #404931, measured across
   the whole shape with a standard deviation under 2 — so a block of that
   same colour laid over the printed digits disappears into it completely
   and leaves a clean face to set live type on.

   23.21% x 82.05% is the largest centred block that stays inside the
   badge's quatrefoil, measured from the artwork; the printed digits are
   17.08% x 41.88%, so they are covered with room to spare. Change the
   number in the markup and it just works — no new artwork needed.        */
.rk-inv__date-num {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 23.2%;
  height: 82%;
  background: var(--badge);
  font-family: "Poppins", system-ui, sans-serif;
  font-weight: 600;
  font-size: max(18px, calc(var(--u) * 11));
  line-height: 1;
  color: var(--badge-ink);
  letter-spacing: -0.01em;
}

.rk-inv__time {
  margin-top: calc(var(--u) * 5);
  font-size: max(13px, calc(var(--u) * 3.85));
  color: var(--ink);
}

/* --- 3.5 the couple and the garden -------------------------------------- */

.rk-inv__finale {
  z-index: 6;
  padding-bottom: calc(var(--u) * 4);
}

.rk-inv__couple {
  position: relative;
  z-index: 6;
  display: block;
  width: calc(var(--a) * 45);
  height: auto;
  margin: 0 auto;
}

/* the garden sits behind the couple and is grouped left / centre / right so
   the reveal reads as three quiet movements, not thirty individual flowers */
.rk-inv__garden {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: calc(var(--a) * 56);
  z-index: 1;
  pointer-events: none;
}

/* a group is a transparent sheet the size of the garden, so its children
   keep their own placement while the group fades in as one movement */
.rk-garden-group {
  position: absolute;
  inset: 0;
}

.rk-tree--l {
  z-index: 1;
  width: calc(var(--a) * 20);
  left: calc(var(--out) * -1 - var(--a) * 4);
  bottom: calc(var(--a) * 9);
}

.rk-tree--r {
  z-index: 1;
  width: calc(var(--a) * 20);
  right: calc(var(--out) * -1 - var(--a) * 4);
  bottom: calc(var(--a) * 9);
}

.rk-minar--l {
  z-index: 2;
  width: calc(var(--a) * 14);
  left: calc(var(--out) * -1 + var(--a) * 2);
  bottom: calc(var(--a) * 12);
}

.rk-minar--r {
  z-index: 2;
  width: calc(var(--a) * 14);
  right: calc(var(--out) * -1 + var(--a) * 2);
  bottom: calc(var(--a) * 12);
}

.rk-mor--l {
  z-index: 3;
  width: calc(var(--a) * 9.5);
  left: calc(var(--out) * -1 + var(--a) * 5);
  bottom: calc(var(--a) * 12);
}

.rk-mor--r {
  z-index: 3;
  width: calc(var(--a) * 9.5);
  right: calc(var(--out) * -1 + var(--a) * 5);
  bottom: calc(var(--a) * 12);
}

/* the static peacock faces right in the artwork; the right-hand one is
   mirrored so both look inward, the same way the supplied elephants and
   lotus are mirrored pairs */
.rk-mor--r img {
  transform: scaleX(-1);
}

/* the ground band is the bottom edge of the page, so it is sized from the
   frame and the two halves always overlap in the middle, however wide the
   screen gets */
.rk-mix--l {
  z-index: 4;
  width: calc(var(--vw) * 0.56);
  left: calc(var(--out) * -1 - var(--a) * 4);
  bottom: calc(var(--a) * -1);
}

.rk-mix--r {
  z-index: 4;
  width: calc(var(--vw) * 0.56);
  right: calc(var(--out) * -1 - var(--a) * 4);
  bottom: calc(var(--a) * -1);
}

.rk-mix--l img {
  transform: scaleX(-1);
}

.rk-lily--l {
  z-index: 5;
  width: calc(var(--a) * 16);
  left: calc(var(--out) * -1 + var(--a) * 3);
  bottom: calc(var(--a) * -2);
}

.rk-lily--r {
  z-index: 5;
  width: calc(var(--a) * 16);
  right: calc(var(--out) * -1 + var(--a) * 3);
  bottom: calc(var(--a) * -2);
}

.rk-lily--r img {
  transform: scaleX(-1);
}


/* 4. Responsive ===========================================================
   There is nothing to switch. Section 3 is written entirely in --u, which
   is one per cent of the screen, so the invitation is the same composition
   at every width — it simply gets bigger or smaller with the browser. No
   breakpoint changes a position, a size or a proportion.

   The only concession is the max() floors on the type in section 3, which
   stop the smallest phones (under ~350px) from taking the supporting lines
   below legibility. Nothing else is capped, anywhere.                     */


/* 5. Entrance =============================================================
   .is-armed is added by script before the section is seen, and only puts
   things where the animation needs them to start. .is-revealed then runs
   the sequence with `both`, so it holds the finished composition. With no
   script, or with reduced motion, neither class is added and section 3 is
   simply the finished page.                                                */

/* --- phase 1: the paper itself -----------------------------------------
   The first thing that happens after the button is the page arriving.    */
@keyframes rk-paper-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.rk-invite.is-armed .rk-invite__paper {
  opacity: 0;
}

.rk-invite.is-revealed .rk-invite__paper {
  animation: rk-paper-in 0.9s var(--ease-reveal) both;
}

/* --- the shared text / artwork reveal ----------------------------------- */
@keyframes rk-inv-rise {
  from {
    opacity: 0;
    transform: translate3d(0, var(--rise, 1.4vh), 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* names carry a whisper of scale so they land with a little more weight */
@keyframes rk-inv-rise-name {
  from {
    opacity: 0;
    transform: translate3d(0, var(--rise, 1.4vh), 0) scale(0.97);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes rk-inv-sacred {
  from {
    opacity: 0;
    transform: translate3d(0, 0.8vh, 0) scale(0.92);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

.rk-invite.is-armed .rk-rise {
  opacity: 0;
}

.rk-invite.is-revealed .rk-rise {
  animation: rk-inv-rise var(--d-text) var(--ease-reveal) var(--d, 0s) both;
}

.rk-invite.is-revealed .rk-rise--name {
  animation-name: rk-inv-rise-name;
  animation-duration: var(--d-name);
}

.rk-invite.is-revealed .rk-rise--sacred {
  animation-name: rk-inv-sacred;
  animation-duration: var(--d-name);
}

/* text delays — the story, in order */
.rk-inv__ganesh {
  --d: var(--t-ganesh);
}

.rk-inv__blessed {
  --d: var(--t-blessed);
}

.rk-inv__title {
  --d: var(--t-title);
}

.rk-inv__divider {
  --d: var(--t-divider);
}

.rk-inv__message {
  --d: var(--t-message);
}

.rk-inv__name--bride {
  --d: var(--t-riya);
}

.rk-inv__parents--bride {
  --d: var(--t-riya-sub);
}

.rk-inv__swastik {
  --d: var(--t-swastik);
}

.rk-inv__name--groom {
  --d: var(--t-kunal);
}

.rk-inv__parents--groom {
  --d: var(--t-kunal-sub);
}

.rk-inv__date {
  --d: var(--t-date);
}

.rk-inv__time {
  --d: var(--t-time);
}

/* --- phase 1: the banana leaves ---------------------------------------- */
@keyframes rk-leaf-in-l {
  from {
    opacity: 0;
    transform: translate3d(-118%, 0, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes rk-leaf-in-r {
  from {
    opacity: 0;
    transform: translate3d(118%, 0, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

.rk-invite.is-armed .rk-leaf {
  opacity: 0;
}

.rk-invite.is-revealed .rk-leaf--l {
  animation: rk-leaf-in-l var(--d-leaf) var(--ease-glide) var(--t-leaf) both;
  will-change: transform;
}

.rk-invite.is-revealed .rk-leaf--r {
  animation: rk-leaf-in-r var(--d-leaf) var(--ease-glide) calc(var(--t-leaf) + 0.12s) both;
  will-change: transform;
}

/* --- phase 3: the large morpankh --------------------------------------
     One journey, one direction, once.

         off the left of the SCREEN
                 →  travels across the viewport
                 →  swinging up on its quill
                 →  one small settle
                 →  still, for good

     Three things make it read as a real feather rather than a sliding
     picture:

     1. THE PIVOT IS THE QUILL, NOT THE CENTRE. The stem tip sits at
        56.06% / 89.71% of the artwork; after the resting rotate(56deg)
        about the box centre it lands at 19.03% / 77.02%, which is where
        transform-origin below puts it. Everything therefore rotates about
        the end of the feather — the plume swings, the quill does not.

     2. THE CROSSING IS MEASURED FROM --vw, the real viewport width, not
        from the stage. On a wide monitor it crosses a wide monitor.

     3. IT NEVER COMES DOWN FROM ABOVE. The descent happens late and
        gently, so the path is a long shallow diagonal in from the left,
        not a drop.

     Every track ends at zero, so what is left standing is exactly the
     resting composition, and nothing here ever runs again.               */

@keyframes rk-plume-fly {
  from {
    transform: translate3d(calc(var(--vw) / -2 - 56%), 0, 0);
  }

  to {
    transform: translate3d(0, 0, 0);
  }
}

/* flat for the first half of the crossing, then easing down to rest —
   this is the shape of the arc, drawn in Y */
@keyframes rk-plume-arc {
  0% {
    transform: translate3d(0, calc(var(--a) * -13), 0);
  }

  45% {
    transform: translate3d(0, calc(var(--a) * -11), 0);
  }

  75% {
    transform: translate3d(0, calc(var(--a) * -5.5), 0);
  }

  100% {
    transform: translate3d(0, 0, 0);
  }
}

/* the swing, about the quill: carried in low, lifting as it arrives, one
   small settle past level and back. No spin, no full turn, no loop. */
@keyframes rk-plume-swing {
  0% {
    opacity: 0;
    transform: rotate(-19deg);
  }

  12% {
    opacity: 1;
    transform: rotate(-17deg);
  }

  62% {
    transform: rotate(-8deg);
  }

  88% {
    transform: rotate(2.2deg);
  }

  100% {
    opacity: 1;
    transform: rotate(0deg);
  }
}

.rk-invite.is-armed .rk-plume {
  opacity: 0;
}

.rk-invite.is-revealed .rk-plume {
  opacity: 1;
}

.rk-invite.is-revealed .rk-plume__fly {
  animation: rk-plume-fly var(--d-plume) var(--ease-carry) var(--t-plume) both;
  will-change: transform;
}

.rk-invite.is-revealed .rk-plume__arc {
  animation: rk-plume-arc var(--d-plume) var(--ease-drift) var(--t-plume) both;
  will-change: transform;
}

.rk-invite.is-revealed .rk-plume__tilt {
  animation: rk-plume-swing var(--d-plume) var(--ease-carry) var(--t-plume) both;
  will-change: transform, opacity;
}

/* --- phase 3: the elephants -------------------------------------------- */
@keyframes rk-eleph-in-l {
  from {
    opacity: 0;
    transform: translate3d(calc(var(--u) * -34), 0, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes rk-eleph-in-r {
  from {
    opacity: 0;
    transform: translate3d(calc(var(--u) * 34), 0, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

.rk-invite.is-armed .rk-eleph {
  opacity: 0;
}

.rk-invite.is-revealed .rk-eleph--l {
  animation: rk-eleph-in-l var(--d-eleph) var(--ease-glide) var(--t-eleph-l) both;
  will-change: transform;
}

.rk-invite.is-revealed .rk-eleph--r {
  animation: rk-eleph-in-r var(--d-eleph) var(--ease-glide) var(--t-eleph-r) both;
  will-change: transform;
}

/* --- phase 4: the lotus ------------------------------------------------- */
@keyframes rk-soft-in {
  from {
    opacity: 0;
    transform: translate3d(0, calc(var(--u) * 2.4), 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

.rk-invite.is-armed .rk-lotus,
.rk-invite.is-armed .rk-garden-group {
  opacity: 0;
}

.rk-invite.is-revealed .rk-lotus--l {
  animation: rk-soft-in var(--d-lotus) var(--ease-reveal) var(--t-lotus) both;
}

.rk-invite.is-revealed .rk-lotus--r {
  animation: rk-soft-in var(--d-lotus) var(--ease-reveal) calc(var(--t-lotus) + 0.15s) both;
}

/* --- phase 11: the couple ---------------------------------------------- */
@keyframes rk-couple-in {
  from {
    opacity: 0;
    transform: translate3d(0, calc(var(--u) * 3), 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

.rk-invite.is-armed .rk-inv__couple {
  opacity: 0;
}

.rk-invite.is-revealed .rk-inv__couple {
  animation: rk-couple-in var(--d-couple) var(--ease-glide) var(--t-couple) both;
  will-change: transform;
}

/* --- phase 12: the garden, in three groups ------------------------------ */
.rk-invite.is-revealed .rk-garden-group {
  animation: rk-soft-in var(--d-garden) var(--ease-reveal) var(--d, 0s) both;
}

.rk-garden-group--centre {
  --d: var(--t-garden-c);
}

.rk-garden-group--left {
  --d: var(--t-garden-l);
}

.rk-garden-group--right {
  --d: var(--t-garden-r);
}


/* 6. Reduced motion =======================================================
   Nothing moves. The invitation is simply there, already finished.        */

@media (prefers-reduced-motion: reduce) {
  .rk-invite [class] {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    will-change: auto !important;
  }

  /* mirrored artwork is composition, not animation — put it back */
  .rk-mor--r img,
  .rk-mix--l img,
  .rk-lily--r img {
    transform: scaleX(-1) !important;
  }

  .rk-plume img {
    transform: rotate(56deg) !important;
  }

  .rk-inv__date-day,
  .rk-inv__date-month {
    transform: translateY(-50%) !important;
  }
}