/* Motion - preloader, scroll reveal, hero intro and hover micro-interactions, ported from the mock's
   feel (kit.js reveal, kit.css hovers) and made automatic (assets/js/motion.js tags the targets).
   Hidden states only exist under html.ddc-motion, which the script adds after it has checked it can
   reveal - so if the script fails, nothing is hidden. Transform + opacity only: no layout shift. */

/* Page transition (every page, Richard 30 Sept): the page stays visible through a light blur, with a
   purple + green spinner in the middle. No logo. Shown on arrival until load and when an internal link is
   followed (motion.js). Fails open: without JS it clears itself after 5s (ddc-preloader-out). */
.preloader {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  background: color-mix(in srgb, var(--ground) 25%, transparent); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  transition: opacity var(--dur-fast) var(--ease), visibility 0s linear var(--dur-fast);
  animation: ddc-preloader-out 0s linear 5s forwards;
}
/* Paced 1 Oct (Richard: "goes quite fast"): blur in over --page-in, hold (motion.js), reveal over --page-out. */
.preloader { --page-in: 300ms; --page-out: 450ms; }
.preloader.is-hidden { opacity: 0; visibility: hidden; pointer-events: none; transition-duration: var(--page-out), 0s; transition-delay: 0s, var(--page-out); }
.preloader.is-leaving { opacity: 1; visibility: visible; animation: none; transition-duration: var(--page-in), 0s; transition-delay: 0s; }
/* Two arcs, DDC green and DDC purple, on a faint track so the purple still reads over dark pages. */
.preloader__ring {
  width: var(--gap-60); height: var(--gap-60); border-radius: 50%;
  background: conic-gradient(var(--ddc-green) 0 30%, transparent 0 50%, var(--ddc-purple) 0 80%, transparent 0), var(--line);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--gap-4) - 1px), #000 calc(100% - var(--gap-4)));
  mask: radial-gradient(farthest-side, transparent calc(100% - var(--gap-4) - 1px), #000 calc(100% - var(--gap-4)));
  animation: ddc-preloader-spin calc(var(--dur-slow) * 2) linear infinite;
}
@keyframes ddc-preloader-spin { to { transform: rotate(360deg); } }
@keyframes ddc-preloader-out { to { opacity: 0; visibility: hidden; pointer-events: none; } }

/* Scroll reveal: fade up once, staggered in reading order (--r-i set by motion.js). */
.ddc-motion .ddc-r {
  transition: opacity var(--dur-reveal) var(--ease), transform var(--dur-reveal) var(--ease);
  transition-delay: calc(var(--r-i, 0) * var(--stagger));
}
.ddc-motion .ddc-r:not(.is-in) { opacity: 0; transform: translateY(var(--gap-20)); }

/* Hero intro: title rises, then the lead, then the buttons. */
.ddc-motion .ddc-hero-part {
  transition: opacity var(--dur-reveal) var(--ease), transform var(--dur-reveal) var(--ease);
  transition-delay: calc(var(--menu-delay) + var(--hero-i, 0) * var(--stagger) * 2);
}
.ddc-motion .hero:not(.ddc-hero-in) .ddc-hero-part { opacity: 0; transform: translateY(var(--gap-40)); }
.ddc-motion .hero:not(.ddc-hero-in) .ddc-hero-part:is(.display, .hero__title, .h-display, .h-1) { transform: translateY(calc(var(--gap-60) + var(--gap-20))); }

/* Stat figures keep their width while counting. */
.stat-figure { font-variant-numeric: tabular-nums; }

/* ---- Hover micro-interactions (subtle, never bouncy) ------------------------------------------ */

/* Photo tiles and the essence panel: the photo slowly zooms inside the card. The background is
   copied onto a clipped layer so only the image scales, never the text or the card edge. */
/* Only for tiles/panels painted with a background image; the mock's own .tile__img / .panel__img
   versions already zoom via mock.css. */
.elementor :is(.tile, .panel):not(:has(.tile__img, .panel__img)) { isolation: isolate; }
.elementor :is(.tile, .panel):not(:has(.tile__img, .panel__img))::before {
  content: ""; position: absolute; inset: 0; z-index: -1; background: inherit; border-radius: inherit;
  transition: transform var(--dur-slow) var(--ease);
}
.elementor :is(.tile, .panel):not(:has(.tile__img, .panel__img)):hover::before { transform: scale(1.04); }

/* Loop and card photos zoom within their frame (the frame itself never grows). */
/* Rest state is explicit (1 Oct, Richard: "hover effects need to be smooth"): object-view-box cannot
   interpolate from `none`, so the zoom used to SNAP in and out. inset(0) + brightness(1) = it eases. */
.elementor :is(img.media-43, img.media-45, .media-43 img, .media-45 img) {
  object-view-box: inset(0%); filter: brightness(1);
  transition: object-view-box var(--dur-slow) var(--ease), filter var(--dur-slow) var(--ease);
}
.elementor :is(.e-collection-loop-layout-base > *, .project):hover :is(img.media-43, img.media-45, .media-43 img, .media-45 img) { object-view-box: inset(2%); filter: brightness(1.06); }
.elementor .person__media img { transition: transform var(--dur-slow) var(--ease); }
.elementor .person:hover .person__media img { transform: scale(1.03); }

/* Buttons: colour swap on hover; any arrow icon turns (the mock's composite button). */
.elementor .btn { transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
.elementor .btn svg { transition: transform var(--dur) var(--ease); }
.elementor .btn:is(:hover, :focus-visible) svg { transform: var(--turn); }

/* Text links: the underline draws away and back, the text turns green. */
html body .elementor .link {
  border-bottom-color: transparent;
  background: linear-gradient(currentColor, currentColor) 0 100% / 100% var(--hair) no-repeat;
  transition: background-size var(--dur) var(--ease), color var(--dur-fast) var(--ease);
}
html body .elementor .link:hover { background-size: 0 var(--hair); background-position: 100% 100%; color: var(--ddc-green); }
.elementor .link a { color: inherit; text-decoration: none; }

/* Accreditation marks lift a touch. */
.elementor :is(.accred-logo, .strip__item) { transition: transform var(--dur) var(--ease); }
.elementor :is(.accred-logo, .strip__item):hover { transform: translateY(calc(var(--gap-4) * -1)); }

/* Need cards: the mock's tint, plus a small lift. */
.ddc-sc .need { transition: background-color var(--dur) var(--ease), transform var(--dur) var(--ease); }
.ddc-sc .need:hover { transform: translateY(calc(var(--gap-4) * -1)); }

/* Footer links brighten to white. */
:is(.foot, [data-elementor-type="footer"]) a { transition: color var(--dur-fast) var(--ease); }
:is(.foot, [data-elementor-type="footer"]) a:hover { color: var(--white); }

/* Never hide anything in the editor or on paper; no motion for reduced-motion. */
.elementor-editor-active :is(.ddc-r, .ddc-hero-part) { opacity: 1 !important; transform: none !important; }
@media print { .ddc-r, .ddc-hero-part { opacity: 1 !important; transform: none !important; } }
@media (prefers-reduced-motion: reduce) {
  .ddc-r, .ddc-hero-part { opacity: 1 !important; transform: none !important; transition: none !important; }
  .elementor :is(.tile, .panel):hover::before, .elementor .accred-logo:hover, .ddc-sc .need:hover { transform: none; }
}
