/* curtain-tassel-r82.css  ·  2026-09-16  ·  preview copy only
   -------------------------------------------------------------------------
   R010 · two small moving parts on the home page, and nothing else.

   1. A gold curtain pull-cord hanging at the bottom-right of the hero
      painting. It is the same size, the same gold and the same place in all
      eight gardens, so every rule below is written against the painting's own
      box (.r30-cover-art) and never against a data-garden-theme value. The
      stage gardens (blue, pink) show .r58-stage-art inside that box, the
      other six plus classic show .r30-garden-art inside the very same box, so
      one mount point covers all of them.
   2. A soft white glint that crosses the pearl garland (.r67-pearl-hem) about
      every 15 seconds. The garland itself - its image, size, position - is
      not touched: the glint is a child element laid over it and clipped to
      its 34px height.

   Colour is fixed gold: cord #c9a24b, knot and fringe #e2c375, and the ring
   around the knot takes var(--garden-paper) so the knot reads against any of
   the eight paintings. The first-visit bubble is the garden's own paper / ink
   / primary. Nothing here reads or writes a theme-specific selector.

   Load order: linked last, after stage-parity-r79.css. It adds only the two
   new elements' own rules plus one `position:relative` on the painting box
   (already relative in the stage gardens; a no-op layout-wise elsewhere).
   ------------------------------------------------------------------------- */


/* == 1. The painting becomes the positioning parent ======================= */
/* curtain-stage-r58.css line 15 and stage-parity-r79.css line 66 already say
   position:relative for the two stage gardens; this repeats the same value
   for the six colour gardens and classic, where the box was static. No other
   sheet sets `position` on .r30-cover-art, so nothing is overridden. */
.r27-home .r30-cover-art{position:relative}


/* == 2. The pull-cord ===================================================== */
.r82-tassel{
  position:absolute;right:6%;bottom:3%;z-index:3;
  width:30px;height:126px;
  margin:0;padding:0;border:0;background:none;
  -webkit-appearance:none;appearance:none;
  line-height:0;cursor:pointer;touch-action:manipulation;
}
/* The span, not the <svg>, carries the rotation: an HTML element has the
   classList / style / offsetWidth the script needs to restart an animation. */
.r82-tassel-fig{
  display:block;width:100%;height:100%;
  transform-origin:top center;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,.30));
  transition:transform .25s ease;
}
.r82-tassel-fig>svg{display:block;width:100%;height:100%}
/* The paper ring is the one colour that follows the garden. */
.r82-tassel-ring{stroke:var(--garden-paper,#fffaf0)}
.r82-tassel:hover .r82-tassel-fig{filter:drop-shadow(0 1px 2px rgba(0,0,0,.22)) brightness(1.06)}
.r82-tassel:focus-visible{outline:none}
.r82-tassel:focus-visible .r82-tassel-fig{outline:2px solid var(--garden-ink,#28678d);outline-offset:3px;border-radius:9px}
@media(max-width:699px){
  .r82-tassel{width:26px}
}

/* One swing = 3.2s, +7deg then -7deg and settling, turning about the top
   where the cord disappears into the curtain. The iteration count is set by
   the script: 2 for the first sway, 1 for every sway after it. */
@keyframes r82-sway{
  0%{transform:rotate(0deg)}
  12%{transform:rotate(7deg)}
  37%{transform:rotate(-7deg)}
  62%{transform:rotate(4.2deg)}
  82%{transform:rotate(-2.1deg)}
  100%{transform:rotate(0deg)}
}
.r82-tassel-fig.is-swaying{
  animation-name:r82-sway;animation-duration:3.2s;animation-timing-function:ease-in-out;
}


/* == 3. First-visit bubble, to the left of the cord ======================= */
.r82-hint{
  position:absolute;right:calc(6% + 34px);bottom:calc(3% + 6px);z-index:4;
  box-sizing:border-box;width:max-content;max-width:calc(100% - 44px);
  padding:6px 10px;border:1px solid var(--garden-primary,#78b8e4);border-radius:12px;
  background:var(--garden-paper,#fffaf0);color:var(--garden-ink,#28678d);
  /* One line in English; the longer German and Arabic strings wrap instead of
     spilling out of the bubble on a 320px phone. */
  font:500 12.5px/1.3 'Playfair Display',Georgia,serif;text-align:center;
  box-shadow:0 3px 10px rgba(0,0,0,.12);
  opacity:0;transform:translateY(2px);
  transition:opacity .45s ease,transform .45s ease;
  pointer-events:none;
}
.r82-hint::after{
  content:'';position:absolute;top:11px;right:-5px;width:8px;height:8px;
  background:var(--garden-paper,#fffaf0);
  border-top:1px solid var(--garden-primary,#78b8e4);
  border-right:1px solid var(--garden-primary,#78b8e4);
  transform:rotate(45deg);
}
.r82-hint.is-on{opacity:1;transform:none}
@media(max-width:699px){
  .r82-hint{right:calc(6% + 30px);bottom:calc(3% + 6px);padding:5px 9px;font-size:12px}
}


/* == 4. Pearl-hem glint =================================================== */
/* A child of .r67-pearl-hem, so the garland's own background image, width
   formula and position stay exactly as pearl-hem-r67.css / stage-parity-r79
   section 7 wrote them. overflow:hidden keeps the light inside the garland's
   34px band; the hem is already pointer-events:none. */
.r82-glint{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.r82-glint-beam{
  position:absolute;top:0;bottom:0;left:0;width:100%;
  background-image:linear-gradient(90deg,rgba(255,255,255,0),rgba(255,255,255,.7) 50%,rgba(255,255,255,0));
  background-size:40px 100%;background-repeat:no-repeat;background-position:left center;
  opacity:0;
  animation:r82-hem-slide 15s ease-in-out infinite,r82-hem-fade 15s linear infinite;
}
/* 1.6s of the 15s cycle (10.67%) is the sweep; the rest is the beam parked
   off the right edge at opacity 0. Two animations so the travel keeps one
   unbroken ease-in-out while the fade in/out stays linear. */
@keyframes r82-hem-slide{
  0%{transform:translateX(-40px)}
  10.67%,100%{transform:translateX(100%)}
}
@keyframes r82-hem-fade{
  0%{opacity:0}
  1.1%{opacity:.7}
  9.6%{opacity:.7}
  10.67%,100%{opacity:0}
}


/* == 5. Reduced motion =================================================== */
/* Nothing moves: no sway, no glint, no fade on the bubble. The bubble itself
   still appears once on a first visit - it is information, not motion - but
   it is shown and removed with no transition. */
@media(prefers-reduced-motion:reduce){
  .r82-tassel-fig,.r82-tassel-fig.is-swaying{animation:none!important;transform:none!important}
  .r82-glint{display:none!important}
  .r82-hint{transition:none!important;transform:none!important}
}

/* r82b (2026-09-16 她要更显眼)：第一次晃得更大＋绳结闪光；手指按住/鼠标碰到时往下拉一截 */
@keyframes r82-sway-big{0%{transform:rotate(0)}12%{transform:rotate(10deg)}37%{transform:rotate(-10deg)}62%{transform:rotate(6deg)}82%{transform:rotate(-3deg)}100%{transform:rotate(0)}}
.r82-tassel-fig.is-swaying.is-first{animation-name:r82-sway-big}
@keyframes r82-spark{0%,100%{opacity:0;transform:translate(-50%,-50%) scale(.4)}50%{opacity:1;transform:translate(-50%,-50%) scale(1.3)}}
.r82-tassel.is-first::after{content:"";position:absolute;left:50%;top:64%;width:12px;height:12px;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,#fff 0,rgba(255,255,255,.95) 35%,rgba(255,255,255,0) 70%);
  transform:translate(-50%,-50%) scale(.4);opacity:0;animation:r82-spark 1.1s ease-in-out 3}
.r82-tassel:hover .r82-tassel-fig:not(.is-swaying),.r82-tassel:active .r82-tassel-fig:not(.is-swaying){transform:translateY(5px)}
@media (prefers-reduced-motion:reduce){.r82-tassel.is-first::after{display:none;animation:none}.r82-tassel-fig{transition:none}}
