/* =========================================
   ARC LP — Animations (pure CSS, no libraries)
   Every animation for the landing page lives in this file
   ========================================= */

/* -----------------------------------------
   1. SCROLL REVEAL UTILITIES
   Add .anim-* to an element; JS adds .in-view
   when it enters the viewport. --d = delay.
   ----------------------------------------- */
[class*="anim-"] {
  opacity: 0;
  animation-duration: .9s;
  animation-timing-function: cubic-bezier(.22,1,.36,1);
  animation-fill-mode: both;
  animation-delay: var(--d, 0s);
  animation-play-state: paused;
}
[class*="anim-"].in-view { animation-play-state: running; }

.anim-fade-up    { animation-name: fadeUp; }
.anim-fade-down  { animation-name: fadeDown; }
.anim-fade-left  { animation-name: fadeLeft; }
.anim-fade-right { animation-name: fadeRight; }
.anim-fade       { animation-name: fadeIn; }
.anim-zoom       { animation-name: zoomIn; }
.anim-reveal     { animation-name: clipReveal; }
.anim-line-up    { animation-name: lineUpIn; animation-duration: 1.1s; }
.anim-shape-in   { animation-name: shapeIn; animation-duration: 1.6s; }

/* image rises open from the bottom and settles at its exact size (full image, no crop) */
.anim-img-rise { animation-name: imgRise; animation-duration: 1.5s; animation-timing-function: cubic-bezier(.77,0,.18,1); }
.anim-img-rise img { transform: scale(1.2); transition: transform 2.2s cubic-bezier(.22,1,.36,1) .1s; }
.anim-img-rise.in-view img { transform: scale(1); }
@keyframes imgRise  { from { opacity:1; clip-path:inset(100% 0 0 0); } to { opacity:1; clip-path:inset(0 0 0 0); } }

/* image: curtain wipe from left + inner image settles from a slight zoom */
.anim-img-reveal { animation-name: imgWipe; animation-duration: 1.4s; animation-timing-function: cubic-bezier(.77,0,.18,1); }
.anim-img-reveal img { transform: scale(1.18); transition: transform 2.2s cubic-bezier(.22,1,.36,1) .1s; }
.anim-img-reveal.in-view img { transform: scale(1); }
.anim-img-reveal:hover img { transform: scale(1.04); transition-duration: 1.2s; transition-delay: 0s; }

/* decorative ARC shape keeps floating once in */
.anim-shape-in.in-view { animation: shapeIn 1.6s cubic-bezier(.22,1,.36,1) both, shapeFloat 7s 1.6s ease-in-out infinite alternate; }

@keyframes lineUpIn   { from { opacity:1; transform:translateY(110%); } to { opacity:1; transform:none; } }
@keyframes imgWipe    { from { opacity:1; clip-path:inset(0 100% 0 0); } to { opacity:1; clip-path:inset(0 0 0 0); } }
@keyframes shapeIn    { from { opacity:0; transform:translate(40px, 30px); } to { opacity:1; transform:none; } }
@keyframes shapeFloat { from { transform:translateY(0); } to { transform:translateY(-14px); } }

/* -----------------------------------------
   2. HEADER ENTRANCE (runs on page load)
   Everything in the header and hero waits for body.is-loaded.
   The bar drops in, the menu rules draw out from the centre,
   then the menu items follow one by one.
   ----------------------------------------- */
.site-header,
.wa-float {
  animation-fill-mode: both;
  animation-timing-function: cubic-bezier(.22,1,.36,1);
}
body:not(.is-loaded) .site-header,
body:not(.is-loaded) .site-header *,
body:not(.is-loaded) .site-header *::before,
body:not(.is-loaded) .site-header *::after,
body:not(.is-loaded) .hero *,
body:not(.is-loaded) .hero *::after,
body:not(.is-loaded) .wa-float { animation-play-state: paused; }

.site-header { animation: fadeDown 1s .2s both; }
.nav__menu::before,
.nav__menu::after { animation: drawLine 1.2s .45s cubic-bezier(.65,0,.35,1) both; transform-origin: 50% 50%; }
.nav__menu::after { animation-delay: .6s; }
.nav__list li     { animation: navItemIn .8s cubic-bezier(.22,1,.36,1) both; animation-delay: calc(.8s + var(--i, 0) * .1s); }
@keyframes navItemIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }

/* -----------------------------------------
   2b. HERO — the photo fades in from a soft zoom and keeps a very
   slow drift; sunlight breathes through the windows; the title
   lines rise one after another, then the text fades up.
   ----------------------------------------- */
.hero__bg img {
  transform-origin: 50% 100%;     /* zoom grows from the bottom edge, so the sofa is never cut */
  animation: heroSettle 2.8s .1s cubic-bezier(.22,1,.36,1) both,
             heroDrift 28s 2.9s ease-in-out infinite alternate;
}
.hero__glow { animation: glowIn 2s 1.2s ease both, glowBreathe 9s 3.2s ease-in-out infinite alternate; }
.hero__title .line > span { animation: lineUp 1.1s cubic-bezier(.22,1,.36,1) both; }
.hero__title .line:nth-child(1) > span { animation-delay: .5s; }
.hero__title .line:nth-child(2) > span { animation-delay: .65s; }
.hero__text { animation: fadeUp 1s .95s cubic-bezier(.22,1,.36,1) both; }
.hero__btn  { animation: fadeUp 1s 1.1s cubic-bezier(.22,1,.36,1) both; }

/* offer: the ticker rises from the bottom edge, the panel slides in from
   the left, its text fades up, PRE-LAUNCH rises out of its line;
   then the ticker message keeps scrolling right-to-left (pauses on hover) */
.hero__ticker   { animation: tickerUp .9s 1.1s cubic-bezier(.22,1,.36,1) both; }
.ticker__track  { animation: tickerMove 42s 1.4s linear infinite; }
.hero__ticker:hover .ticker__track { animation-play-state: paused; }
.hero__panel    { animation: panelIn 1.1s 1.3s cubic-bezier(.22,1,.36,1) both; }
.hero__bhk,
.hero__res      { animation: fadeUp .9s cubic-bezier(.22,1,.36,1) both; }
.hero__bhk      { animation-delay: 1.75s; }
.hero__res      { animation-delay: 1.9s; }
.hero__tag span { animation: lineUp 1s 1.7s cubic-bezier(.22,1,.36,1) both; }

@keyframes tickerUp   { from { transform: translateY(100%); } to { transform: none; } }
@keyframes tickerMove { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes panelIn    { from { transform: translateX(-101%); } to { transform: none; } }

@keyframes heroSettle  { from { opacity: 0; transform: scale(1.14); } to { opacity: 1; transform: scale(1.02); } }
@keyframes heroDrift   { from { transform: scale(1.02); } to { transform: scale(1.06) translateX(-.6%); } }
@keyframes glowIn      { from { opacity: 0; } to { opacity: .55; } }
@keyframes glowBreathe { from { opacity: .55; transform: none; } to { opacity: .95; transform: translate(-3%, 2%) scale(1.08); } }

/* -----------------------------------------
   3. WHATSAPP — pop in + pulse ring
   ----------------------------------------- */
.wa-float { animation: zoomIn .6s 1.6s both; }
.wa-float::before {
  content: '';
  position: absolute; inset: 0;
  border-radius: 50%;
  background: var(--c-wa);
  z-index: -1;
  animation: pulseRing 2s 2.2s ease-out infinite;
}

/* -----------------------------------------
   4. MODALS
   ----------------------------------------- */
.modal__overlay { opacity: 0; transition: opacity .4s ease; }
.modal__box {
  opacity: 0;
  transform: translateY(30px) scale(.97);
  transition: opacity .45s cubic-bezier(.22,1,.36,1), transform .45s cubic-bezier(.22,1,.36,1);
}
.modal.is-open .modal__overlay { opacity: 1; }
.modal.is-open .modal__box     { opacity: 1; transform: none; }
.modal.is-open .field,
.modal.is-open .arc-form .btn  { animation: fadeUp .6s cubic-bezier(.22,1,.36,1) both; }
.modal.is-open .arc-form > :nth-child(2) { animation-delay: .08s; }
.modal.is-open .arc-form > :nth-child(3) { animation-delay: .12s; }
.modal.is-open .arc-form > :nth-child(4) { animation-delay: .16s; }
.modal.is-open .arc-form > :nth-child(5) { animation-delay: .20s; }
.modal.is-open .arc-form > :nth-child(6) { animation-delay: .24s; }
.modal.is-open .arc-form > :nth-child(7) { animation-delay: .28s; }
.modal.is-open .arc-form > :nth-child(8) { animation-delay: .32s; }

.field.has-error { animation: shake .4s ease; }

/* -----------------------------------------
   KEYFRAMES
   ----------------------------------------- */
@keyframes fadeUp     { from { opacity:0; transform:translateY(40px); }  to { opacity:1; transform:none; } }
@keyframes fadeDown   { from { opacity:0; transform:translateY(-30px); } to { opacity:1; transform:none; } }
@keyframes fadeLeft   { from { opacity:0; transform:translateX(-50px); } to { opacity:1; transform:none; } }
@keyframes fadeRight  { from { opacity:0; transform:translateX(50px); }  to { opacity:1; transform:none; } }
@keyframes fadeIn     { from { opacity:0; } to { opacity:1; } }
@keyframes zoomIn     { from { opacity:0; transform:scale(.6); } to { opacity:1; transform:none; } }
@keyframes clipReveal { from { opacity:1; clip-path:inset(0 0 100% 0); } to { opacity:1; clip-path:inset(0 0 0 0); } }
@keyframes lineUp     { from { transform:translateY(110%); } to { transform:none; } }
@keyframes drawLine   { from { transform:scaleX(0); } to { transform:scaleX(1); } }
@keyframes circleRise { 0% { opacity:0; transform:translateY(60%); } 25% { opacity:1; } 100% { opacity:1; transform:none; } }
@keyframes heroUp     { from { opacity:0; transform:translateY(9vh); } to { opacity:1; transform:none; } }
@keyframes buildingUp { from { opacity:0; transform:translateY(7%); } to { opacity:1; transform:none; } }
@keyframes pulseRing  { 0% { transform:scale(1); opacity:.55; } 100% { transform:scale(1.9); opacity:0; } }
@keyframes shake      { 0%,100% { transform:none; } 25% { transform:translateX(-5px); } 75% { transform:translateX(5px); } }

/* -----------------------------------------
   REDUCED MOTION
   ----------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001s !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    transition-duration: .001s !important;
  }
  [class*="anim-"] { opacity: 1 !important; }
}

/* -----------------------------------------
   5. THANK YOU PAGE — plays on load
   ----------------------------------------- */
.ty__bg img            { animation: footZoom 2.4s cubic-bezier(.22,1,.36,1) both; }
.ty-header             { animation: fadeDown .9s .1s cubic-bezier(.22,1,.36,1) both; }
.ty__check circle      { stroke-dasharray: 151; stroke-dashoffset: 151; animation: tyDraw .9s .3s ease-out forwards; }
.ty__check path        { stroke-dasharray: 34;  stroke-dashoffset: 34;  animation: tyDraw .5s 1.05s ease-out forwards; }
.ty__title .line > span{ animation: lineUpIn 1.1s .5s cubic-bezier(.77,0,.18,1) both; }
.ty__lead              { animation: fadeUp 1s .9s cubic-bezier(.22,1,.36,1) both; }
.ty__dl                { animation: fadeUp 1s 1s cubic-bezier(.22,1,.36,1) both; }
.ty__btns              { animation: fadeUp 1s 1.1s cubic-bezier(.22,1,.36,1) both; }
.ty__call, .ty__foot   { animation: fadeIn 1s 1.4s ease both; }
@keyframes tyDraw { to { stroke-dashoffset: 0; } }
@keyframes footZoom { from { transform: scale(1.15); } to { transform: scale(1.02); } }
@media (prefers-reduced-motion: reduce) {
  .ty *, .ty-header { animation: none !important; stroke-dashoffset: 0 !important; }
}

/* =========================================
   SECTION ANIMATIONS
   Added one section at a time, same pattern as ARC:
   hold with  .<wrapper>:not(.in-view) ... { animation-play-state: paused; }
   ========================================= */

/* -----------------------------------------
   ABOUT THIRUVERKADU — title lines rise, text fades up, the map
   opens from the bottom and settles from a zoom (.anim-img-rise);
   each feature: number rises, title slides in, rule draws across,
   text follows — staggered with --d. Map zooms a touch on hover.
   ----------------------------------------- */
.feat__head  { overflow: hidden; }
.feat__num   { animation: lineUpIn .9s cubic-bezier(.22,1,.36,1) both; animation-delay: calc(var(--d) + 0s); }
.feat__title { animation: fadeLeft .9s cubic-bezier(.22,1,.36,1) both; animation-delay: calc(var(--d) + .15s); }
.feat__line  { animation: drawLine 1.1s cubic-bezier(.65,0,.35,1) both; animation-delay: calc(var(--d) + .25s); }
.feat__text  { animation: fadeUp .9s cubic-bezier(.22,1,.36,1) both; animation-delay: calc(var(--d) + .45s); }
:not(.in-view) > .feat .feat__num,
:not(.in-view) > .feat .feat__title,
:not(.in-view) > .feat .feat__line,
:not(.in-view) > .feat .feat__text { animation-play-state: paused; }

.about__map img { transition: transform 1.2s cubic-bezier(.22,1,.36,1); }
.about__media.in-view .about__map:hover img { transform: scale(1.04); }

/* -----------------------------------------
   CONNECTIVITY — title rises, text + buttons fade up; the map opens
   out from the centre while the image settles from a zoom; the
   categories slide in from the right one by one. Opening a category:
   header turns dark, plus turns to minus, the list unfolds and its
   rows fade up one after another.
   ----------------------------------------- */
.conn__map     { animation: mapOpen 1.6s cubic-bezier(.77,0,.18,1) both; }
.conn__map img { animation: mapSettle 2.4s cubic-bezier(.22,1,.36,1) both; }
.conn__map:not(.in-view),
.conn__map:not(.in-view) img { animation-play-state: paused; }
.conn__map-link { transition: transform 1.2s cubic-bezier(.22,1,.36,1); }
.conn__map.in-view .conn__map-link:hover { transform: scale(1.03); }

.cat { animation: fadeRight .9s cubic-bezier(.22,1,.36,1) both; animation-delay: calc(.35s + var(--i, 0) * .08s); }
.conn__list:not(.in-view) .cat { animation-play-state: paused; }

.cat__rows li { opacity: 0; transform: translateY(8px); transition: opacity .4s ease, transform .5s cubic-bezier(.22,1,.36,1); }
.cat.is-open .cat__rows li { opacity: 1; transform: none; }
.cat.is-open .cat__rows li:nth-child(1) { transition-delay: .15s; }
.cat.is-open .cat__rows li:nth-child(2) { transition-delay: .22s; }
.cat.is-open .cat__rows li:nth-child(3) { transition-delay: .29s; }
.cat.is-open .cat__rows li:nth-child(4) { transition-delay: .36s; }
.cat.is-open .cat__rows li:nth-child(5) { transition-delay: .43s; }
.cat.is-open .cat__rows li:nth-child(n+6) { transition-delay: .5s; }

@keyframes mapOpen   { from { clip-path: inset(10% 14% 10% 14%); } to { clip-path: inset(0 0 0 0); } }
@keyframes mapSettle { from { transform: scale(1.22); } to { transform: scale(1); } }

/* -----------------------------------------
   FLOOR PLANS — menu items slide in one by one, the plan card rises
   open, the info fades up. Switching plan crossfades the image (js)
   and the highlight glides to the chosen item. A soft ring keeps
   pulsing out of the Enquire button over the blurred plan.
   ----------------------------------------- */
.plans__item { animation: fadeLeft .8s cubic-bezier(.22,1,.36,1) both; animation-delay: calc(var(--i) * .08s + .1s); }
.plans__card { animation: imgRise 1.4s cubic-bezier(.77,0,.18,1) both; animation-delay: .15s; }
.plans__info { animation: fadeUp 1s cubic-bezier(.22,1,.36,1) both; animation-delay: .7s; }
.plans__enq  { animation: enqIn .8s 1.2s cubic-bezier(.22,1,.36,1) both; }
.plans__enq::after {
  content: '';
  position: absolute; inset: 0;
  border: 1px solid var(--c-brown);
  animation: tagPulse 2.4s 2s ease-out infinite both;
  pointer-events: none;
}
.plans__body:not(.in-view) .plans__item,
.plans__body:not(.in-view) .plans__card,
.plans__body:not(.in-view) .plans__info,
.plans__body:not(.in-view) .plans__enq,
.plans__body:not(.in-view) .plans__enq::after { animation-play-state: paused; }
@media (max-width: 991px) { .plans__enq { animation-delay: .6s; } }   /* the accordion re-runs it on every open */
@keyframes enqIn    { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes tagPulse { 0% { opacity: .9; transform: scale(1); } 70%, 100% { opacity: 0; transform: scale(1.12, 1.4); } }

/* -----------------------------------------
   FOOTER — disclaimers fade up, the rules draw across,
   then Phone / Email / Legal / Copyright rise in one after another.
   ----------------------------------------- */
.foot__disc { animation: fadeUp .9s cubic-bezier(.22,1,.36,1) both; }
.foot__brand .foot__disc { animation-delay: .25s; }
.foot__logo { animation: fadeUp .9s .15s cubic-bezier(.22,1,.36,1) both; }
.foot__rule { animation: drawLine 1.3s cubic-bezier(.65,0,.35,1) both; animation-delay: .1s; }
.foot__rule:nth-of-type(2) { animation-delay: .35s; }
.foot__col  { animation: fadeUp .9s cubic-bezier(.22,1,.36,1) both; animation-delay: calc(.45s + var(--i, 0) * .1s); }
.foot__inner:not(.in-view) .foot__disc,
.foot__inner:not(.in-view) .foot__logo,
.foot__inner:not(.in-view) .foot__rule,
.foot__inner:not(.in-view) .foot__col { animation-play-state: paused; }
