/*
  Jr. Food Mart: motion layer.
  Website developed by pressific.com Emily Park, Dileep C. Kaluaratchie and Tech Generation Ltd.

  Sits on top of the converted design without altering it. The layout, spacing
  and type are the client's and are not touched here: everything below either
  moves something that was already in place, or draws the brand mark that was
  already on the page.

  Three rules:

  1. FAIL-SAFE. Everything that starts hidden is scoped under .jfm-motion, a
     class JavaScript puts on <html>. No JS, or a JS error, means no class,
     which means nothing is ever hidden. The page is never at the mercy of a
     script.
  2. SCROLL-COUPLED, NOT ONE-SHOT. Reveals re-run whenever an element leaves and
     re-enters, and the circle's sweep reads a --p custom property that tracks
     its position in the viewport. Nothing fires once and dies.
  3. Anyone who asks their system for less motion gets none of it.

  Brand: red #c7262f, ink #1a1a1a, paper #ffffff.
*/

:root {
  --jfm-red:   #c7262f;
  --jfm-red-2: #a81d25;
  --jfm-ink:   #1a1a1a;
  --jfm-ease:  cubic-bezier(.22, .61, .36, 1);
}

/* the hidden geometry block is never laid out */
.jfm-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ---- 1. The opening: the mark, minted -------------------------------------
   The logo is a red disc inside a ring of arrows, so the site opens by making
   it a solid object: a coin out of the dark, tumbling, landing face-on. The
   last frame is the flat logo exactly, and the room goes white as it lands so
   the handover to the page is a light coming up rather than a cut.
   All of the drawing is in jfm-intro.js against a 2D canvas, including the
   background, so this is only the stage it plays on.                        */

.jfm-intro {
  position: fixed; inset: 0; z-index: 100000;
  background: #0d0d0f;
  pointer-events: none;
  opacity: 1;
  transition: opacity .55s ease;
}
.jfm-intro.is-done { opacity: 0; }
.jfm-intro__canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }

/* nothing scrolls while the sequence plays */
.jfm-intro-open, .jfm-intro-open body { overflow: hidden; }

/* ---- the circle itself, in either context --------------------------------- */

.jfm-circle { display: block; overflow: visible; }

/* the disc lands first, with a little weight to it */
.jfm-circle__body {
  transform-origin: 49.4% 51.2%;          /* the disc's own centre, not the box */
  transform: scale(.62);
  opacity: 0;
  transition: transform .85s cubic-bezier(.34, 1.32, .5, 1), opacity .5s ease;
}
.jfm-circle.is-in .jfm-circle__body { transform: scale(1); opacity: 1; }

/* the ring is revealed by its mask, so it needs no transition of its own */
.jfm-sweep__arc { transition: none; }

/* the red arc that runs the loop once the cycle is complete */
.jfm-chase {
  fill: none;
  stroke: var(--jfm-red);
  stroke-width: 7;
  stroke-linecap: round;
  opacity: 0;
  transform-origin: 49.4% 49.9%;
}
.jfm-circle.is-running .jfm-chase {
  opacity: .9;
  animation: jfm-chase 1.15s cubic-bezier(.5, 0, .3, 1) forwards;
}
@keyframes jfm-chase {
  0%   { stroke-dashoffset: var(--jfm-c); opacity: .95; }
  70%  { opacity: .95; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}

/* on the page, once the cycle has been drawn, it keeps turning: a short red
   arc travelling the ring, slowly, so the diagram reads as a live loop */
.jfm-circle.is-cycling .jfm-chase {
  opacity: .55;
  stroke-width: 5;
  animation: jfm-cycle 7.5s linear infinite;
}
@keyframes jfm-cycle {
  from { stroke-dashoffset: 0; }
  to   { stroke-dashoffset: calc(var(--jfm-c) * -1); }
}

/* ---- 2. Scroll-coupled page motion ---------------------------------------- */

/* sections and their contents rise as they enter, and again on re-entry */
.jfm-motion [data-jfm="rise"] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .75s ease, transform .75s var(--jfm-ease);
}
.jfm-motion [data-jfm="rise"].is-in { opacity: 1; transform: none; }
.jfm-motion [data-jfm="rise"][data-jfm-i="1"] { transition-delay: .08s; }
.jfm-motion [data-jfm="rise"][data-jfm-i="2"] { transition-delay: .16s; }
.jfm-motion [data-jfm="rise"][data-jfm-i="3"] { transition-delay: .24s; }

/* Headings draw a short red rule under themselves, matching the brand mark.
   It is positioned out of flow on purpose: a rule that took up height would
   push every following section down, and the client's layout is not ours to
   move. This way the page geometry is identical with the motion layer on. */
.jfm-motion [data-jfm="rule"] { position: relative; }
.jfm-motion [data-jfm="rule"]::after {
  content: ""; position: absolute; left: 0; bottom: -11px;
  height: 3px; width: 0;
  background: var(--jfm-red);
  transition: width .85s var(--jfm-ease) .12s;
}
.jfm-motion [data-jfm="rule"].is-in::after { width: 76px; }

/* photographs drift a little as they pass, tied to position not time */
.jfm-motion [data-jfm="drift"] {
  transform: translateY(calc((var(--p, .5) - .5) * -20px));
  transition: transform .12s linear;
  will-change: transform;
}

/* the banded background images get a slow parallax */
.jfm-motion [data-jfm="parallax"] {
  background-position-y: calc(50% + (var(--p, .5) - .5) * 64px) !important;
}

/* the state maps land one after another */
.jfm-motion [data-jfm="map"] {
  opacity: 0;
  transform: translateY(26px) scale(.96);
  transition: opacity .7s ease, transform .8s var(--jfm-ease);
}
.jfm-motion [data-jfm="map"].is-in { opacity: 1; transform: none; }
.jfm-motion [data-jfm="map"][data-jfm-i="1"] { transition-delay: .13s; }
.jfm-motion [data-jfm="map"][data-jfm-i="2"] { transition-delay: .26s; }

/* scroll progress, in the brand red, always live */
.jfm-progress {
  position: fixed; top: 0; left: 0; height: 3px; z-index: 9998;
  width: 100%;
  transform: scaleX(var(--jfm-scroll, 0)); transform-origin: 0 50%;
  background: var(--jfm-red);
  pointer-events: none;
}

/* ---- 3. Always-on life ----------------------------------------------------- */

/* the app store badges lift, because they are the one thing to click */
[data-jfm="badge"] {
  transition: transform .4s var(--jfm-ease), filter .4s ease;
  will-change: transform;
}
@media (hover: hover) {
  [data-jfm="badge"]:hover { transform: translateY(-3px) scale(1.02); filter: brightness(1.06); }
}

/* the red enquiry band gets a slow sheen so it never looks dead */
[data-jfm="band"] { position: relative; overflow: hidden; }
[data-jfm="band"]::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .10) 50%, transparent 62%);
  transform: translateX(-100%);
  animation: jfm-sheen 8s ease-in-out infinite;
  pointer-events: none;
}
@keyframes jfm-sheen {
  0%, 64% { transform: translateX(-100%); }
  100%    { transform: translateX(100%); }
}

/* ---- Respect the visitor --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .jfm-intro { display: none !important; }
  .jfm-motion [data-jfm="rise"],
  .jfm-motion [data-jfm="map"] { opacity: 1 !important; transform: none !important; transition: none; }
  .jfm-motion [data-jfm="drift"] { transform: none !important; }
  .jfm-motion [data-jfm="parallax"] { background-position-y: 50% !important; }
  .jfm-motion [data-jfm="rule"]::after { transition: none; width: 76px; }
  .jfm-circle__body { transform: none !important; opacity: 1 !important; transition: none; }
  .jfm-chase { display: none; }
  [data-jfm="band"]::after { animation: none; }
  [data-jfm="badge"] { transition: none; }
  .jfm-progress { display: none; }
}

/* The in-page instance sits exactly over the raster it replaces. The parent
   span is already position:relative and inline-block in the converted CSS, so
   this needs no restyling of the client's layout to hold it. */
.jfm-circle--inline {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ---- corrections to the conversion ----------------------------------------
   Website developed by pressific.com Emily Park, Dileep C. Kaluaratchie and Tech Generation Ltd.

   The app store badges were built with a Divi module that rendered its own
   anchor at run time, so the captured DOM kept the artwork and lost the link.
   The destinations came back out of the WordPress database dump. The anchor
   has to be display:block to sit exactly where the bare image sat, or the row
   shifts by the inline line-height.                                          */
a.jfm-badge-link {
  display: block;
  text-decoration: none;
  border: 0;
  line-height: 0;
  /* The tilt module stacks two invisible panels over its artwork: a .ss glare
     div at z-index 9, and a ::before on the wrapper at z-index 1. Both are
     empty, both are the full size of the badge, and with the module's own
     JavaScript gone they do nothing but swallow the click. Hit testing follows
     paint order, so the link has to sit above both of them. */
  position: relative;
  z-index: 10;
}
a.jfm-badge-link:focus-visible {
  outline: 2px solid var(--jfm-red);
  outline-offset: 3px;
}

/* and belt and braces: anything following the link inside the tilt wrapper is
   decoration, so it stops taking pointer events at all */
a.jfm-badge-link ~ * { pointer-events: none; }

/* ---- the opening lines, typed -----------------------------------------------
   Website developed by pressific.com Emily Park, Dileep C. Kaluaratchie and Tech Generation Ltd.

   Every character sits in its own span at full size before anything is shown,
   so the paragraph is laid out complete and typing is only opacity travelling
   along a fixed run. Line breaks, block height and everything below the hero
   are identical at the first frame and the last: nothing walks down the page
   while you read it.

   Scoped under .jfm-typing-ready, a class the script adds only once it has
   successfully wrapped the text. No script, or a script that threw, and the
   copy is simply there.                                                       */

.jfm-typing-ready .jfm-ch {
  opacity: 0;
  transition: opacity .12s linear;
}
.jfm-typing-ready .jfm-ch.is-on { opacity: 1; }

/* the caret rides the last visible character. The negative margin gives back
   the width the border takes, so the run never reflows as it moves. */
.jfm-typing-ready .jfm-ch.is-head {
  border-right: 2px solid var(--jfm-red);
  margin-right: -2px;
}

@media (prefers-reduced-motion: reduce) {
  .jfm-typing-ready .jfm-ch { opacity: 1 !important; transition: none; }
  .jfm-typing-ready .jfm-ch.is-head { border-right: 0; margin-right: 0; }
}
