/* =========================================================================
   Contact visual (templates/partials/visual_mail.html), in place of the
   stock typing clip at the top of the contact aside. Loaded by
   contact/contact.html after style.css (block extra_head); builds on the
   .visual panel of style.css 29.
   - the panel: the light card of the hub visuals, 40 % white so the tint
     band's grid and node network show through, navy ink, green only on
     the live dot, the seal, the trail and the check (02-couleurs.md)
   - the story, one period --T: a white letter is written line by line,
     folded in three, lifted, dropped into the navy envelope; the flap
     closes, the green square seals it, the envelope flies off along the
     green dotted line of the ribbon's crest and a check takes its place.
     The chip in the head follows: Rédaction, Mise sous pli, Envoyé.
   - the stage is drawn in em on a 32 x 15 grid; the em is 1/32 of the
     panel's width (container query), so the drawing scales as a whole
   - every base style is the resting picture (sealed envelope, trail drawn,
     chip on « Envoyé »): that is what shows without motion. main.js runs
     the animation only while the panel is on screen (.is-inview).
   ========================================================================= */

.visual-mail {
  --T: 10s;
  container-type: inline-size;
  background: rgba(255, 255, 255, 0.4);
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 30px 60px -32px rgba(11, 29, 51, 0.38),
    0 12px 30px -18px rgba(11, 29, 51, 0.18);
}
.visual-mail::before {
  background-image:
    linear-gradient(rgba(11, 29, 51, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 29, 51, 0.05) 1px, transparent 1px);
}
.visual-mail::after { border-color: transparent; box-shadow: none; }
.visual-mail .visual-head { color: var(--muted); }
.visual-mail .visual-live { background: var(--teal); animation-name: visual-pulse-teal; }

/* ---- the state chip: three labels stacked in one cell ------------------- */
.vm-state {
  display: inline-grid;
  background: var(--teal-soft);
  border-color: rgba(15, 122, 82, 0.25);
  color: var(--teal-ink);
  animation: vm-chip var(--T) ease infinite;
}
.vm-state > span {
  grid-area: 1 / 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  white-space: nowrap;
}
.vm-state i { font-size: 0.7rem; line-height: 1; }
.vm-state-write { opacity: 0; animation: vm-state-write var(--T) ease infinite; }
.vm-state-fold { opacity: 0; animation: vm-state-fold var(--T) ease infinite; }
.vm-state-sent { animation: vm-state-sent var(--T) ease infinite; }

/* ---- the stage ---------------------------------------------------------- */
.vm-scene {
  width: 100%;
  aspect-ratio: 32 / 15;
  font-size: 10px; /* without container queries: drawn for a 320px wide panel */
  font-size: calc(100cqw / 32);
}
/* drawn left to right, then mirrored as a whole in Arabic */
.vm-stage { position: absolute; inset: 0; direction: ltr; }
body.is-rtl .vm-stage { transform: scaleX(-1); }

/* the green dotted line the envelope leaves behind */
.vm-trail {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: none;
  stroke: var(--teal);
  stroke-opacity: 0.55;
  stroke-width: 0.26;
  stroke-linecap: round;
  stroke-dasharray: 0 0.7;
  animation: vm-trail var(--T) linear infinite;
}

/* the mail: envelope parts and the letter, stacked back to front */
.vm-mail {
  position: absolute;
  left: 10em;
  top: 7.4em;
  width: 12em;
  height: 7em;
  perspective: 40em;
  animation: vm-fly var(--T) linear infinite;
}
.vm-face {
  position: absolute;
  inset: 0;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.vm-env-back {
  position: absolute;
  z-index: 0;
  inset: 0;
  border-radius: 0.7em;
  background: var(--dark-2);
  box-shadow: 0 1.4em 2.4em -1.3em rgba(11, 29, 51, 0.6);
  animation: vm-env var(--T) ease infinite;
}
/* the flap, hinged on the top edge: open it shows its inside and sits
   behind the letter, closed it lies over the pocket */
.vm-flap {
  position: absolute;
  z-index: 4;
  left: 0;
  top: 0;
  width: 100%;
  height: 4.3em;
  transform-origin: 50% 0;
  transform-style: preserve-3d;
  animation: vm-env-rise var(--T) ease infinite, vm-flap var(--T) ease infinite;
}
.vm-flap .vm-face { animation: vm-env-fade var(--T) ease infinite; }
.vm-flap-out {
  background: linear-gradient(180deg, var(--dark-3), #233a5a);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}
.vm-flap-in {
  background: #0f223c;
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
  transform: rotateX(180deg);
}
.vm-env-front {
  position: absolute;
  z-index: 3;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  animation: vm-env var(--T) ease infinite;
}
.vm-pocket { fill: var(--dark); }
.vm-seam,
.vm-rim { fill: none; stroke-width: 0.8; stroke-linejoin: round; }
.vm-seam { stroke: rgba(255, 255, 255, 0.07); }
.vm-rim { stroke: rgba(255, 255, 255, 0.16); }
/* the seal: the green square of the charte on the flap's tip */
.vm-seal {
  position: absolute;
  z-index: 5;
  left: 50%;
  top: 4.3em;
  width: 1.1em;
  height: 1.1em;
  margin: -0.55em 0 0 -0.55em;
  border-radius: 0.12em;
  background: var(--teal-2);
  box-shadow: 0 0 0 0.25em rgba(47, 176, 124, 0.18);
  animation: vm-seal var(--T) ease infinite;
}

/* the letter: three panels; the top one folds down over the middle, then
   the bottom one up over both. Each folding panel has a back face. */
.vm-sheet {
  position: absolute;
  z-index: 2;
  left: 1.5em;
  top: -6.2em;
  width: 9em;
  height: 12.6em;
  perspective: 36em;
  translate: 0 3.6em;
  animation: vm-sheet var(--T) ease infinite;
}
.vm-panel {
  position: absolute;
  left: 0;
  width: 100%;
  height: 4.2em;
  transform-style: preserve-3d;
}
.vm-panel-top { z-index: 2; top: 0; transform-origin: 50% 100%; transform: rotateX(-180deg); animation: vm-fold-top var(--T) ease infinite; }
.vm-panel-mid { z-index: 1; top: 4.2em; }
.vm-panel-bot { z-index: 3; top: 8.4em; transform-origin: 50% 0; transform: rotateX(180deg); animation: vm-fold-bot var(--T) ease infinite; }
.vm-front {
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  padding: 0.3em 1.1em;
  background: #fff;
  box-shadow: inset 0 0 0 1px rgba(11, 29, 51, 0.06);
}
.vm-panel-top .vm-front { border-radius: 0.35em 0.35em 0 0; }
.vm-panel-bot .vm-front { border-radius: 0 0 0.35em 0.35em; box-shadow: inset 0 0 0 1px rgba(11, 29, 51, 0.06), 0 1em 1.8em -0.9em rgba(11, 29, 51, 0.4); }
/* the backs: plain paper, a shade darker towards the crease */
.vm-back {
  border-radius: 0.2em;
  background: linear-gradient(180deg, #f6f8fa, #e4e9ef);
  box-shadow: inset 0 0 0 1px rgba(11, 29, 51, 0.07), 0 0.6em 1.2em -0.6em rgba(11, 29, 51, 0.35);
  transform: rotateX(180deg);
}
.vm-letterhead { display: flex; align-items: center; gap: 0.5em; }
.vm-letterhead b { flex: none; width: 0.75em; height: 0.75em; border-radius: 0.08em; background: var(--teal); }
.vm-line {
  display: block;
  flex: none;
  width: var(--w);
  height: 0.36em;
  border-radius: 0.2em;
  background: var(--line-2);
  transform-origin: 0 50%;
  animation: vm-type var(--T) var(--ease-soft) calc(var(--k) * 0.3s) infinite backwards;
}
.vm-line-ink { background: var(--ink); }
.vm-sign { height: 0.5em; }

/* the check left where the envelope took off (outside the mirrored stage,
   so it never turns round) */
.vm-done {
  position: absolute;
  left: 50%;
  top: 50%;
  display: grid;
  place-items: center;
  width: 3.2em;
  height: 3.2em;
  margin: -1.6em 0 0 -1.6em;
  border-radius: 50%;
  background: var(--teal);
  color: #fff;
  font-size: inherit;
  box-shadow: 0 0 0 0.5em var(--teal-soft), 0 1em 2em -1em rgba(15, 122, 82, 0.6);
  opacity: 0;
  animation: vm-done var(--T) ease infinite;
}
.vm-done i { font-size: 1.7em; line-height: 1; }

/* paused until the panel is on screen (main.js); without JS it simply runs */
.js .visual-mail:not(.is-inview) * { animation-play-state: paused !important; }

@media (prefers-reduced-motion: reduce) {
  .visual-mail .vm-state,
  .visual-mail .vm-state > span,
  .visual-mail .vm-scene * { animation: none !important; }
}

/* ---- the period: 0-30 % write, 30-44 % fold, 44-64 % into the envelope
   and seal, 67-80 % fly, 80-95 % check, then the next letter ------------ */
@keyframes vm-sheet {
  0% { opacity: 0; translate: 0 0.8em; }
  4% { opacity: 1; translate: 0 0; }
  44% { translate: 0 0; }
  50% { translate: 0 -3.9em; }
  52% { translate: 0 -3.9em; animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.5); }
  56.5% { translate: 0 3.9em; }
  58% { translate: 0 3.45em; }
  59.5%, 100% { opacity: 1; translate: 0 3.6em; }
}
@keyframes vm-type {
  0%, 5% { transform: scaleX(0); }
  9%, 58% { transform: scaleX(1); }
  62%, 100% { transform: scaleX(0); }
}
@keyframes vm-fold-top {
  0%, 30% { transform: rotateX(0deg); }
  37%, 100% { transform: rotateX(-180deg); }
}
@keyframes vm-fold-bot {
  0%, 37% { transform: rotateX(0deg); }
  44%, 100% { transform: rotateX(180deg); }
}
/* the envelope rises in open, gives a little as the letter lands */
@keyframes vm-env {
  0%, 45% { opacity: 0; translate: 0 2.4em; }
  51% { opacity: 1; translate: 0 0; }
  56.5% { translate: 0 0; }
  57.5% { translate: 0 0.18em; }
  59.5%, 100% { opacity: 1; translate: 0 0; }
}
@keyframes vm-env-rise {
  0%, 45% { translate: 0 2.4em; }
  51%, 56.5% { translate: 0 0; }
  57.5% { translate: 0 0.18em; }
  59.5%, 100% { translate: 0 0; }
}
@keyframes vm-env-fade {
  0%, 45% { opacity: 0; }
  51%, 100% { opacity: 1; }
}
/* the flap swings over at 61.5 %: edge-on, it changes layer unseen */
@keyframes vm-flap {
  0% { transform: rotateX(180deg); z-index: 1; }
  59% { transform: rotateX(180deg); animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
  61.49% { z-index: 1; }
  61.5% { z-index: 4; }
  64%, 100% { transform: rotateX(0deg); z-index: 4; }
}
@keyframes vm-seal {
  0%, 64.5% { opacity: 0; transform: scale(0); }
  66.5% { opacity: 1; transform: scale(1.35); }
  68%, 100% { opacity: 1; transform: scale(1); }
}
/* a squash before take-off, then away along the trail's curve: sampled
   from the same cubic as the trail's path, so the reveal keeps pace */
@keyframes vm-fly {
  0%, 67.5% { transform: translate(0em, 0em) rotate(0deg) scale(1); opacity: 1; animation-timing-function: ease; }
  69% { transform: translate(0em, 0.3em) rotate(0deg) scale(1.04, 0.94); animation-timing-function: ease-out; }
  70% { transform: translate(0em, 0em) rotate(-4.1deg) scale(1); opacity: 1; }
  71.25% { transform: translate(0.39em, -0.05em) rotate(-4.6deg) scale(0.98); opacity: 1; }
  72.5% { transform: translate(1.28em, -0.25em) rotate(-7.6deg) scale(0.95); opacity: 1; }
  73.75% { transform: translate(2.57em, -0.69em) rotate(-11.2deg) scale(0.89); opacity: 1; }
  75% { transform: translate(4.27em, -1.53em) rotate(-14.7deg) scale(0.82); opacity: 1; }
  76.25% { transform: translate(6.44em, -2.91em) rotate(-17.5deg) scale(0.74); opacity: 1; }
  77.5% { transform: translate(9.2em, -4.97em) rotate(-19.1deg) scale(0.64); opacity: 0.86; }
  78.75% { transform: translate(12.78em, -7.87em) rotate(-19.7deg) scale(0.54); opacity: 0.45; }
  80%, 100% { transform: translate(17.5em, -11.7em) rotate(-19.3deg) scale(0.42); opacity: 0; }
}
@keyframes vm-trail {
  0%, 69.9% { opacity: 0; clip-path: inset(-1em 50% -1em -1em); }
  70% { opacity: 1; clip-path: inset(-1em 50% -1em -1em); }
  71.25% { clip-path: inset(-1em 48.8% -1em -1em); }
  72.5% { clip-path: inset(-1em 46% -1em -1em); }
  73.75% { clip-path: inset(-1em 42% -1em -1em); }
  75% { clip-path: inset(-1em 36.7% -1em -1em); }
  76.25% { clip-path: inset(-1em 29.9% -1em -1em); }
  77.5% { clip-path: inset(-1em 21.2% -1em -1em); }
  78.75% { clip-path: inset(-1em 10.1% -1em -1em); }
  80% { clip-path: inset(-1em -4.7% -1em -1em); }
  87% { opacity: 1; }
  92%, 100% { opacity: 0; clip-path: inset(-1em -4.7% -1em -1em); }
}
@keyframes vm-done {
  0%, 80% { opacity: 0; transform: scale(0.4); }
  83% { opacity: 1; transform: scale(1.12); }
  85%, 91% { opacity: 1; transform: scale(1); }
  95%, 100% { opacity: 0; transform: scale(0.9); }
}
@keyframes vm-chip {
  0%, 69% { background: var(--bg); border-color: var(--line); color: var(--ink-2); }
  71%, 95% { background: var(--teal-soft); border-color: rgba(15, 122, 82, 0.25); color: var(--teal-ink); }
  98%, 100% { background: var(--bg); border-color: var(--line); color: var(--ink-2); }
}
@keyframes vm-state-write {
  0% { opacity: 0; }
  2%, 29% { opacity: 1; }
  31%, 100% { opacity: 0; }
}
@keyframes vm-state-fold {
  0%, 29% { opacity: 0; }
  31%, 69% { opacity: 1; }
  71%, 100% { opacity: 0; }
}
@keyframes vm-state-sent {
  0%, 69% { opacity: 0; }
  71%, 95% { opacity: 1; }
  98%, 100% { opacity: 0; }
}
