/* ==========================================================================
   Contact — LET'S START WITH UNDERSTANDING
   --------------------------------------------------------------------------
   Rebuilt from scratch 2026-10-01 on the site's own section grammar from
   home.css (.v2 sections, .v2-eyebrow, .v2-head, .v2-lead, .v2-btn,
   .v2-reveal, .v2--finale). Five sections:

     01 open    navy    the claim, and THE MEETING — two points finding each
                        other — as the hero's drawn object
     02 start   warm    the enquiry, set in the page rather than in a card
     03 reach   mist    email, telephone, WhatsApp and the city
     04 why     navy    THE BEAM — the hero's two points, resolved
     05 next    finale  the shared second bloom

   The page's idea is that understanding is something TWO parties arrive at.
   The hero draws it as two points reaching toward each other; section 4
   resolves it as one line joining inside a pool of light. Nothing on this
   page is a speech bubble, a chat or a network.

   AUTHORED STILL. Everything below is written in its finished state — both
   points met, the beam lit, the line joined. That is what a reader with
   reduced motion, or without JavaScript, gets. The head adds `.ct-motion`
   before first paint when motion is allowed; rules under it take a
   composition apart so it can arrive, and the section's own `.is-in` (from
   home-scenes.js) puts it back.

   Only transform, opacity, colour and stroke-dashoffset animate, each on
   its own element. Nothing is pinned, nothing hijacks the scroll, and this
   page has no JavaScript of its own beyond the site-wide form validation.
   Exactly one thing loops — the pulse at the meeting point — and
   `.ct-open.is-live` stops it the moment the hero leaves the screen.

   THE FORM CONTRACT IS SHARED, NOT LOCAL. `.field`, `.field__error`,
   `.field.is-invalid`, `.form-status` and `.checkbox` are styled in
   style.css and driven by js/form-validation.js. Everything here only
   places and sizes them; nothing overrides their error or focus states.

   Loaded by /contact alone.
   ========================================================================== */

:root {
  /* the MedhaSofts palette. home.css resolves the shared button and section
     rules against these, and each page's own stylesheet supplies them. */
  --bl-midnight: #0B1630;
  --bl-deep-navy: #10264A;
  --bl-royal: #2563EB;
  --bl-electric: #4DA8FF;
  --bl-soft: #93C5FD;
  --bl-teal: #14B8A6;
  --bl-violet: #8B5CF6;
  --bl-coral: #F28B82;
  --bl-off-white: #F8FAFC;
  --bl-dark: #0F172A;
  --bl-slate: #475569;

  --ct-ease: cubic-bezier(.22, .61, .36, 1);     /* the site ease */
  --ct-slow: cubic-bezier(.16, .84, .3, 1);
  /* An arrival is a deceleration, so these two carry every entrance here.
     `--ct-expo` is a true exponential-out: a fast attack and a long, quiet
     settle, which is what separates a considered entrance from a slide.
     `--ct-settle` overshoots by a hair and relaxes -- enough to feel weighted,
     far short of a bounce. */
  --ct-expo: cubic-bezier(.16, 1, .3, 1);
  --ct-settle: cubic-bezier(.34, 1.26, .64, 1);

  /* The travelling light. ONE period for the whole page: the spark crosses
     the rule in --ct-sweep, and each node works out its own flare delay from
     its position along that rule, so the two can never drift apart. */
  --ct-sweep: 7.2s;
  --ct-orbit: 11s;

  /* the page keeps two sizes of its own; everything else is .v2-head h2 and
     .v2-lead from home.css, so Contact never invents a scale */
  --ct-t-voice: var(--t-hero);   /* the H1 */
  --ct-t-claim: var(--t-display);     /* section 4 */

  --ct-measure: 60ch;
}

/* ================================================================ 01 open */
/* The tallest hero on the site at 1002px, against ~700px everywhere else.
   The object drove it: 560px of artwork plus a full hero padding above and
   below. A smaller object and the standard padding bring it into line. */
.ct-open { padding-block: var(--v2-pad); }
.ct-open__sky {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(1.5px 1.5px at 16% 26%, rgba(219, 234, 254, .5), transparent),
    radial-gradient(1px 1px at 72% 18%, rgba(219, 234, 254, .45), transparent),
    radial-gradient(1.5px 1.5px at 86% 64%, rgba(219, 234, 254, .4), transparent),
    radial-gradient(70% 90% at 50% 100%, rgba(37, 99, 235, .22), transparent 72%);
}
.ct-open__inner { position: relative; }
/* --v2-pad-hero, like every other content page: it puts the breadcrumb
   95px below the header. Contact was the last page still on --v2-pad
   and sat 9px high of the rest. */
.ct-open { padding-block: var(--v2-pad-hero) var(--v2-pad); }
.ct-open .crumbs { margin-bottom: clamp(22px, 3vw, 40px); }
/* the breadcrumb is a light-page component; on the dark open it takes the
   same pair every other dark hero on the site uses */
.ct-open .crumbs { color: #C4D4EC; }
.ct-open .crumbs a { color: #D6E3F6; }
.ct-open .crumbs a:hover { color: #FFFFFF; }
.ct-open__split { align-items: center; }
/* the H1 is long; two equal columns from 768px squeeze it onto four lines
   with a one-word orphan, so the hero stays one column until 1024 */
@media (max-width: 1023px) {
  .ct-open__split { grid-template-columns: minmax(0, 1fr); }
  .ct-con { max-width: 430px; margin-inline: 0; }
}
@media (min-width: 1024px) { .ct-open__split { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); } }

.ct-open .v2-head h1 {
  max-width: 14ch;
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--ct-t-voice);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -.035em;
  color: #FFFFFF;
  text-wrap: balance;
}
.ct-open .v2-head h1 em {
  font-style: normal;
  background: linear-gradient(100deg, var(--bl-soft), var(--bl-electric) 46%, var(--bl-violet));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.ct-open .v2-lead { max-width: 46ch; }

/* ------------------------------------------------------ THE CONVERGENCE -- */
/* The site draws with petals. Two groups of them, one from each side, turn
   and travel inward until they interlock as ONE bloom -- understanding is
   something two parties arrive at. Six petals, not the finale's eight, and it
   closes inward where every other bloom on the site opens outward. */
.ct-con { position: relative; width: 100%; max-width: 430px; margin-inline: auto; }
.ct-con__svg { display: block; width: 100%; height: auto; overflow: visible; }
.ct-con__ring circle {
  fill: none;
  stroke: rgba(147, 197, 253, .13);
  stroke-width: 1.5;
  /* 2*pi*172, so one dash covers the circle exactly and it can be drawn */
  stroke-dasharray: 1081;
  stroke-dashoffset: 0;
  transform-box: fill-box;
  transform-origin: 50% 50%;
  transform: rotate(-90deg);                  /* start the draw at the top */
}
.ct-con__petal {
  transform-box: fill-box;
  transform-origin: 50% 100%;                 /* the base, at the centre */
  transform: rotate(var(--a));
  opacity: var(--o, .9);                      /* one home, as above */
}
/* the two parties, in the two halves of the brand palette */
.ct-con__petal--a { color: var(--petal-electric); }
.ct-con__petal--b { color: var(--petal-violet); }
/* The pair that meets head-on is the palest, so the join reads as light.
   That is petals 3 and 4 (the two at 30 degrees, adjacent across the top) --
   the same pair the motion gives the last beat to, so colour and timing agree
   on which petals complete the bloom. */
.ct-con__petal:nth-child(3), .ct-con__petal:nth-child(4) { color: var(--petal-pale); --o: 1; }
.ct-con__core { fill: #DBEAFE; filter: drop-shadow(0 0 20px rgba(147, 197, 253, .95)); }
.ct-con__halo { transform-box: fill-box; transform-origin: 50% 50%; }

/* the ring of light that leaves the core when the pair meets -- once */
.ct-con__wave {
  fill: none;
  stroke: rgba(147, 197, 253, .55);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: 50% 50%;
  opacity: 0;                                 /* only the entrance shows it */
}
/* and the short arc of light that travels the ring afterwards */
.ct-con__trace {
  fill: none;
  stroke: url(#ctTrace);
  stroke-width: 2.5;
  stroke-linecap: round;
  /* 2*pi*172 = 1081; a 108-unit arc is a tenth of the circle */
  stroke-dasharray: 108 973;
  stroke-dashoffset: 0;
  opacity: 0;                                 /* the still page has no light */
  filter: drop-shadow(0 0 7px rgba(147, 197, 253, .85));
}

/* =============================================================== 02 start */
.ct-start__grid { display: grid; gap: clamp(32px, 4.5vw, 64px); }
@media (min-width: 1024px) {
  .ct-start__grid { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); align-items: start; }
  .ct-start__head { position: sticky; top: clamp(96px, 11vw, 128px); }
}
.ct-start__head .v2-head h2 { max-width: 16ch; }
.ct-start__note {
  margin: var(--space-5) 0 0;
  max-width: 34ch;
  font-size: clamp(1rem, .96rem + .2vw, 1.08rem);
  line-height: 1.65;
  color: var(--bl-slate);
}

/* the form is set in the page, not in a card: one rule down its left edge
   at wide widths is all it needs to read as a block */
.ct-form { max-width: 720px; }
.ct-fields {
  display: grid;
  gap: clamp(18px, 2.2vw, 26px);
}
@media (min-width: 680px) {
  .ct-fields { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ct-field--full, .ct-consent { grid-column: 1 / -1; }
}
.ct-field label {
  display: block;
  margin-bottom: 7px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: #14306A;                              /* 9.4:1 on the warm ground */
}
.ct-field .req { color: #B3261E; }
.ct-field input, .ct-field select, .ct-field textarea {
  width: 100%;
  padding: 13px 15px;
  font: inherit;
  font-size: 1rem;                             /* 16px: iOS must not zoom */
  color: var(--bl-dark);
  background: #FFFFFF;
  border: 1.5px solid rgba(37, 99, 235, .24);
  border-radius: 12px;
  transition: border-color .18s var(--ct-ease), box-shadow .18s var(--ct-ease);
}
.ct-field textarea { resize: vertical; min-height: 132px; }
.ct-field input::placeholder, .ct-field textarea::placeholder { color: #6B7A90; }
.ct-field input:hover, .ct-field select:hover, .ct-field textarea:hover {
  border-color: rgba(37, 99, 235, .45);
}
.ct-field input:focus, .ct-field select:focus, .ct-field textarea:focus {
  outline: none;
  border-color: var(--bl-royal);
  box-shadow: 0 0 0 4px rgba(37, 99, 235, .16);
}
/* the keyboard ring stays the site's, over the top of the focus styling */
.ct-field input:focus-visible, .ct-field select:focus-visible,
.ct-field textarea:focus-visible { outline: 3px solid var(--brand-accent); outline-offset: 2px; }

.ct-hint {
  display: block;
  margin-top: 6px;
  font-size: var(--text-sm);
  color: var(--bl-slate);
}
.ct-consent label {
  font-weight: 400;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--bl-slate);
}
.ct-form__end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(14px, 2vw, 28px);
  margin-top: clamp(24px, 3vw, 36px);
}
.ct-form__aside { margin: 0; font-size: var(--text-sm); color: var(--bl-slate); }
.ct-status:not(.is-visible) { display: none; }
.ct-status { margin-bottom: var(--space-5); }

/* =============================================================== 03 reach */
.ct-reach__head .v2-head h2 { max-width: 20ch; }
.ct-ways {
  display: grid;
  gap: clamp(2px, .4vw, 6px);
  margin: clamp(28px, 3.4vw, 46px) 0 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 768px) { .ct-ways { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 clamp(28px, 4vw, 64px); } }
.ct-way {
  display: grid;
  gap: 4px;
  padding: clamp(16px, 2vw, 22px) 0;
  border-top: 1px solid rgba(37, 99, 235, .16);
}
.ct-way__k {
  font-family: var(--font-label);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #1D4ED8;
}
.ct-way__v {
  font-family: var(--font-display);
  font-size: clamp(1.04rem, .98rem + .4vw, 1.3rem);
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--bl-midnight);
  word-break: break-word;
}
a.ct-way__v { color: #1A4FBF; }                /* 6.0:1 on the mist ground */
a.ct-way__v:hover { color: #0B2E68; }
.ct-way__note { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 400; color: var(--bl-slate); }
.ct-sep { padding-inline: 8px; color: rgba(71, 85, 105, .5); }

/* ================================================================= 04 why */
.ct-why { padding-block: var(--v2-pad-loose); }
.ct-why__copy { position: relative; max-width: var(--ct-measure); }

.ct-why__h {
  margin: 0;
  display: grid;
  font-family: var(--font-display);
  font-size: var(--ct-t-claim);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.028em;
  color: #FFFFFF;
}
.ct-why__h em {
  font-style: normal;
  background: linear-gradient(100deg, var(--bl-soft), var(--bl-electric) 50%, var(--bl-violet));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.ct-why__note {
  margin: clamp(32px, 4vw, 56px) 0 0;
  max-width: 52ch;
  font-size: clamp(1.02rem, .98rem + .25vw, 1.14rem);
  line-height: 1.7;
  color: #C9D8EE;                              /* 8.3:1 on #0B1630 */
}

@media (min-width: 1024px) {
  /* the progression runs the full container, so the head and the closing note
     centre over it. This block sits AFTER .ct-why__note: that rule's `margin`
     shorthand resets the inline margins, so centring declared before it loses. */
  .ct-why__copy, .ct-why__note { margin-inline: auto; text-align: center; }
  .ct-why__copy .v2-eyebrow { justify-content: center; }
}

/* --------------------------------------------------------- THE OPENING --- */
/* One question becomes many possibilities, read left to right like the
   sentence above it: one petal, then two, then three, then five. A
   progression, not a bloom -- which is what keeps it distinct from Careers'
   bud and from the shared finale. */
.ct-op {
  position: relative;
  margin: clamp(44px, 5.5vw, 78px) 0 0;
  height: clamp(190px, 22vw, 260px);
}
.ct-op__rule {
  position: absolute;
  left: 0; right: 0; bottom: 34px;
  height: 1px;
  background: rgba(147, 197, 253, .16);
}
/* the lit part of the rule: it travels with the progression */
.ct-op__line {
  position: absolute;
  left: 0; right: 0; bottom: 34px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    rgba(77, 168, 255, 0), var(--bl-electric) 18%, var(--bl-violet) 88%, rgba(139, 92, 246, 0));
  transform-origin: 0 50%;
}
/* the light that travels from the question to the possibility */
.ct-op__spark {
  display: none;                 /* the travelling line is gone; see the note above */
  position: absolute;
  left: 0;
  bottom: 30px;
  width: 128px;
  height: 10px;
  border-radius: 10px;
  opacity: 0;                                 /* the still page has no light */
  background: linear-gradient(90deg,
    rgba(147, 197, 253, 0), rgba(147, 197, 253, .5) 58%, #DBEAFE 92%, rgba(219, 234, 254, 0));
  filter: blur(1px);
  pointer-events: none;
}
.ct-op__stages { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; }
.ct-op__stage {
  position: absolute;
  left: var(--x);
  bottom: 34px;
  transform: translateX(-50%);
}
.ct-op__node {
  position: absolute;
  left: -5px; bottom: -5px;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--bl-electric);
  box-shadow: 0 0 0 4px rgba(77, 168, 255, .14), 0 0 16px rgba(77, 168, 255, .7);
}
/* the flare the travelling light leaves as it passes */
.ct-op__node::before {
  content: '';
  position: absolute;
  inset: -11px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(147, 197, 253, .75), transparent);
  opacity: 0;
  pointer-events: none;
}
/* one ring leaves the node as it lights -- a single pulse, not a loop */
.ct-op__node::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1.5px solid rgba(147, 197, 253, .55);
  opacity: 0;
}
.ct-op__stage:last-child .ct-op__node { background: #DBEAFE; box-shadow: 0 0 0 5px rgba(147, 197, 253, .18), 0 0 22px rgba(147, 197, 253, .95); }
.ct-op__cluster { position: absolute; left: 0; bottom: 0; }
.ct-op__petal {
  position: absolute;
  left: 0;
  bottom: 0;
  width: calc(var(--h) * .444);
  height: var(--h);
  margin-left: calc(var(--h) * -.222);
  transform-origin: 50% 100%;
  transform: rotate(var(--a));
  color: var(--petal-soft);
  /* resting opacity lives in ONE place, as a variable: a per-cluster rule that
     set `opacity` directly would out-specify the motion rule that hides the
     petal before its beat, and the cluster would sit visible at scale .2 */
  opacity: var(--o, .82);
}
.ct-op__petal svg { width: 100%; height: 100%; }
/* the progression warms from soft blue to the full palette as it opens */
.ct-op__stage:nth-child(2) .ct-op__petal { color: var(--petal-electric); }
.ct-op__stage:nth-child(3) .ct-op__petal { color: var(--petal-electric); }
.ct-op__stage:nth-child(3) .ct-op__petal:nth-child(2) { color: var(--petal-pale); }
.ct-op__stage:nth-child(4) .ct-op__petal { color: var(--petal-violet); --o: .9; }
.ct-op__stage:nth-child(4) .ct-op__petal:nth-child(2),
.ct-op__stage:nth-child(4) .ct-op__petal:nth-child(4) { color: var(--petal-electric); }
.ct-op__stage:nth-child(4) .ct-op__petal:nth-child(3) { color: var(--petal-pale); --o: 1; }

@media (max-width: 767px) {
  /* Four clusters will not fit across a phone, so the progression stands up
     and reads top to bottom, keeping the same one-two-three-five growth.
     It runs down the MIDDLE, not a left rail: the widest cluster spreads
     ~137px to each side, and off a left rail that put its outer petals past
     the screen edge, where the section clipped them. Centred and scaled to
     .74 it clears both edges at 360px. */
  .ct-op { height: auto; padding-left: 0; }
  .ct-op__rule, .ct-op__line {
    left: 50%; right: auto; top: 10px; bottom: 10px;
    width: 1px; height: auto; margin-left: -.5px;
  }
  .ct-op__line { width: 2px; margin-left: -1px; transform-origin: 50% 0; }
  .ct-op__stages { position: static; display: grid; gap: clamp(26px, 6vw, 42px); padding-block: 12px; }
  /* The stage is a GRID ITEM here, so it is already full width -- `left: 50%`
     plus `translateX(-50%)` cancel out on it and leave the cluster hard left.
     The cluster does the centring instead: it is a zero-width absolute box,
     so `left: 50%` puts its origin on the centre line and the petals spread
     either side of it. */
  .ct-op__stage {
    position: relative;
    left: auto; bottom: auto;
    transform: none;
    height: var(--row, 96px);
  }
  .ct-op__cluster { left: 50%; bottom: 0; scale: .74; transform-origin: 50% 100%; }
  .ct-op__node { left: calc(50% - 5px); }
  .ct-op__stage:nth-child(1) { --row: 62px; }
  .ct-op__stage:nth-child(2) { --row: 82px; }
  .ct-op__stage:nth-child(3) { --row: 102px; }
  .ct-op__stage:nth-child(4) { --row: 128px; }
}

/* ==========================================================================
   MOTION — only under .ct-motion, and only ever transform / opacity /
   stroke-dashoffset. Each rule takes one finished thing apart; .is-in puts
   it back. The page has no scroll engine: section reveals come from
   home-scenes.js, which this page already loads.
   ========================================================================== */

/* ----------------------------------------------- the convergence closes -- */
/* Each petal swings in along ITS OWN radius -- rotate first, then translate,
   so the travel follows the petal's axis rather than a flat slide across the
   box. It starts a third of the way round, pushed out and smaller, turns
   slightly past its angle and settles back.

   `--p` is the PAIR, so the left and the right petal of a ring share one
   beat and neither side leads. The pale pair that meets head-on is the last
   beat, which makes the join the end of the sentence rather than the middle
   of it. */
@keyframes ct-converge {
  0%   { transform: rotate(calc(var(--a) * .34)) translateY(132px) scale(.6); opacity: 0; }
  38%  { opacity: 1; }
  74%  { transform: rotate(calc(var(--a) * 1.05)) translateY(0) scale(1.015); }
  100% { transform: rotate(var(--a)) translateY(0) scale(1); opacity: var(--o, .9); }
}
.ct-motion .ct-con__petal {
  transform: rotate(calc(var(--a) * .34)) translateY(132px) scale(.6);
  opacity: 0;
}
.ct-motion .ct-open.is-in .ct-con__petal {
  animation: ct-converge 1.45s var(--ct-expo) forwards;
  animation-delay: calc(.3s + var(--p) * .14s);
}

/* the ring inscribes itself from the top while the petals are still coming in */
.ct-motion .ct-con__ring circle { stroke-dashoffset: 1081; }
.ct-motion .ct-open.is-in .ct-con__ring circle {
  transition: stroke-dashoffset 2.1s var(--ct-expo) .15s;
  stroke-dashoffset: 0;
}

/* the halo swells as the pair meets, not before: it is the payoff, so it
   must not be fully lit while the petals are still travelling */
.ct-motion .ct-con__halo { opacity: 0; transform: scale(.72); }
.ct-motion .ct-open.is-in .ct-con__halo {
  transition: opacity 1.5s ease .85s, transform 1.8s var(--ct-expo) .85s;
  opacity: 1;
  transform: none;
}

/* the core lights last, once there is a centre for it to light */
.ct-motion .ct-con__core {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 50% 50%;
  transform: scale(.25);
}
.ct-motion .ct-open.is-in .ct-con__core {
  transition: opacity .6s ease 1.5s, transform .95s var(--ct-settle) 1.5s;
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------------- the opening ----- */
/* A petal unfurls: it starts nearly upright and a fifth of its size -- not at
   nothing, which pops -- turns out past its angle and settles. Within a
   cluster `--d` is the distance from the middle, so the petals open OUTWARD
   from the centre the way a flower opens, instead of left to right. */
@keyframes ct-unfurl {
  0%   { transform: rotate(calc(var(--a) * .16)) scale(.2); opacity: 0; }
  42%  { opacity: var(--o, .82); }
  76%  { transform: rotate(calc(var(--a) * 1.07)) scale(1.035); }
  100% { transform: rotate(var(--a)) scale(1); opacity: var(--o, .82); }
}
.ct-motion .ct-op__petal { transform: rotate(calc(var(--a) * .16)) scale(.2); opacity: 0; }
.ct-motion .ct-why.is-in .ct-op__petal {
  animation: ct-unfurl 1.05s var(--ct-expo) forwards;
  animation-delay: calc(.52s + var(--i) * .34s + var(--d) * .07s);
}

/* the light travels the rule, and each node lights as it is reached */
.ct-motion .ct-op__line {
  transform: scaleX(0);
  transition: transform 1.75s var(--ct-expo) .15s;
}
.ct-motion .ct-why.is-in .ct-op__line { transform: scaleX(1); }

.ct-motion .ct-op__node {
  transform: scale(.25);
  opacity: 0;
  transition: transform .6s var(--ct-settle) calc(.38s + var(--i) * .34s),
              opacity .45s ease calc(.38s + var(--i) * .34s);
}
.ct-motion .ct-why.is-in .ct-op__node { transform: none; opacity: 1; }

@keyframes ct-node-ring {
  0%   { transform: scale(.5); opacity: .75; }
  100% { transform: scale(3.4); opacity: 0; }
}
.ct-motion .ct-why.is-in .ct-op__node::after {
  animation: ct-node-ring .95s var(--ct-expo) forwards;
  animation-delay: calc(.46s + var(--i) * .34s);
}

/* ====================================================== TRAVELLING LIGHT ==
   One looping light per composition, which is the whole budget: more than
   one or two moving things in a view reads as distraction rather than life.
   Both are gated on `.is-live` (from home-scenes.js), so neither ever runs
   off screen, and both are declared only under `.ct-motion`, so reduced
   motion and no-JS get a page with no light travelling at all.
   ======================================================================== */

/* the hero: a ring of light leaves the core at the moment the pair meets --
   once, as the last beat of the entrance, not a loop */
@keyframes ct-wave {
  0%   { transform: scale(.05); opacity: 0; }
  12%  { opacity: .55; }
  100% { transform: scale(1.32); opacity: 0; }
}
.ct-motion .ct-open.is-in .ct-con__wave {
  animation: ct-wave 1.9s var(--ct-expo) forwards;
  animation-delay: 1.5s;                      /* with the core, not before it */
}

/* and a short arc travels the ring from then on. Linear: it is constant-rate
   progress, and any easing would make it appear to hesitate each lap. */
/* The orbiting arc is GONE. A short line travelling a circle for ever is
   exactly the "a line is moving" reading we were trying to avoid, and it was
   the one element on this page that was not part of the bloom. What is left
   is the convergence itself, which is the index page's language: petals
   closing into one form. */

/* the opening: one spark runs the rule, and every node flares as it arrives.
   The flare delay is the stage's own position times the sweep, so the two
   cannot drift. */


@media (max-width: 767px) {
  .ct-motion .ct-op__line { transform: scaleY(0); }
  .ct-motion .ct-why.is-in .ct-op__line { transform: scaleY(1); }

  /* the rule stands up on a phone, so the light travels down it */
  .ct-op__spark {
    left: 50%;
    top: 0;
    bottom: auto;
    width: 10px;
    height: 128px;
    margin-left: -5px;
    background: linear-gradient(180deg,
      rgba(147, 197, 253, 0), rgba(147, 197, 253, .5) 58%, #DBEAFE 92%, rgba(219, 234, 254, 0));
  }
}

/* the claim arrives a line at a time, which is the only place on the page
   where a heading is broken on purpose */
.ct-motion .ct-wl {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  transition: opacity .8s var(--ct-ease) calc(.25s + var(--i) * .13s),
              transform .8s var(--ct-ease) calc(.25s + var(--i) * .13s);
}
.ct-motion .ct-why.is-in .ct-wl { opacity: 1; transform: none; }

/* the ways arrive down the list as it is read */
.ct-motion .ct-way {
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  transition: opacity .6s var(--ct-ease) calc(.15s + var(--i) * .09s),
              transform .6s var(--ct-ease) calc(.15s + var(--i) * .09s);
}
.ct-motion .ct-reach.is-in .ct-way { opacity: 1; transform: none; }

/* ==========================================================================
   TOUCH AND FOCUS
   ========================================================================== */
/* the form anchor is reached from three buttons; the header is sticky, so
   the section needs clearance or its heading lands underneath it */
.ct-start { scroll-margin-top: clamp(72px, 9vw, 104px); }

@media (max-width: 767px) {
  /* every control and every link in the ways list stays comfortably tappable */
  .ct-field input, .ct-field select { min-height: 48px; }
  .ct-way a { min-height: 44px; display: inline-flex; align-items: center; }
  .ct-form__end .btn { width: 100%; justify-content: center; }
}

/* ==========================================================================
   REDUCED MOTION — `.ct-motion` is never added, so every rule in the MOTION
   block above is inert and the authored page stands as written: both points
   met, both reaches arrived, the beam lit and the line joined. The pulse
   does not exist, because its animation is only declared under .ct-motion.
   The site-wide policy in style.css still lets colour and opacity settle.
   ========================================================================== */

/* ==================================================== FLOWING POINTS ====
   The Huenova hero's device, brought here: points of light travelling a path.
   On the hero they flow INWARD along each petal's bearing and arrive at the
   core; in section 4 they run the rule from the question toward the
   possibility. A POINT flowing — the line itself never moves, which is what
   separates this from the travelling line that was here before.
   ======================================================================== */
.ct-con__flow {
  fill: #DBEAFE;
  opacity: 0;
  filter: drop-shadow(0 0 6px rgba(147, 197, 253, .9));
}
.ct-motion .ct-open.is-in .ct-con__flow { opacity: .9; transition: opacity 1s ease 2.2s; }

.ct-op__flow { position: absolute; left: 0; right: 0; bottom: 30px; height: 10px; pointer-events: none; }
.ct-op__pt {
  position: absolute;
  left: 0;
  top: 3px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #DBEAFE;
  box-shadow: 0 0 10px rgba(147, 197, 253, .95);
  opacity: 0;
}
@keyframes ct-pt-run {
  0%   { transform: translateX(0); opacity: 0; }
  10%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translateX(calc(100cqw - 5px)); opacity: 0; }
}
.ct-op { container-type: inline-size; }
.ct-motion .ct-why.is-live .ct-op__pt {
  animation: ct-pt-run var(--d) linear infinite;
  animation-delay: var(--o);
}
@media (max-width: 767px) {
  /* the rule stands up on a phone, so the points fall down it */
  .ct-op__flow { left: 50%; right: auto; top: 0; bottom: 0; width: 10px; height: auto; margin-left: -5px; }
  .ct-op__pt { left: 3px; top: 0; }
  @keyframes ct-pt-fall {
    0%   { transform: translateY(0); opacity: 0; }
    10%  { opacity: 1; }
    88%  { opacity: 1; }
    100% { transform: translateY(calc(100cqh - 5px)); opacity: 0; }
  }
  .ct-op { container-type: size; }
  .ct-motion .ct-why.is-live .ct-op__pt { animation-name: ct-pt-fall; }
}
