/* ============================================================
   PTG STUDIO — CINEMATIC LAYER (styles)
   Loaded after styles.css so it can lean on the existing tokens.

   Every rule here is scoped to a ptg-* class or an [data-*]
   attribute, so nothing can leak into the client sites that share
   this directory during a preview. All of it is additive: if the
   script fails to load, the page looks exactly as it did before.

   Motion is transform/opacity only. No animated width, height,
   top or left anywhere in this file — those are the properties
   that force layout on every frame and destroy the 60fps feel.
   ============================================================ */

/* ---------- design tokens (amber storm family) ---------- */
:root {
  --amber-soft: #3a2a14;
  --amber-glow: #f2d486;
  --amber: #c99a4a;
  --amber-deep: #a87a3a;
  --amber-dull: #8a6a2e;
}

/* ---------- custom cursor ---------- */
.ptg-cursor {
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
}
.ptg-cursor.is-live { opacity: 1; }

.ptg-cursor__ring,
.ptg-cursor__dot,
.ptg-cursor__label {
  position: absolute;
  top: 0; left: 0;
  will-change: transform;
}

.ptg-cursor__ring {
  width: 34px; height: 34px;
  border: 1px solid rgba(242, 212, 134, .55);
  border-radius: 999px;
  transition: width .32s cubic-bezier(.2, .8, .2, 1),
              height .32s cubic-bezier(.2, .8, .2, 1),
              background-color .32s ease,
              border-color .32s ease;
}
.ptg-cursor__dot {
  width: 5px; height: 5px;
  margin: 0;
  background: var(--amber-glow);
  border-radius: 999px;
}
.ptg-cursor.is-hot .ptg-cursor__ring {
  width: 62px; height: 62px;
  background: rgba(242, 212, 134, .10);
  border-color: rgba(242, 212, 134, .80);
}
.ptg-cursor__label {
  font-family: var(--font-display, inherit);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--amber-glow);
  opacity: 0;
  transition: opacity .25s ease;
}
.ptg-cursor.is-hot .ptg-cursor__label { opacity: 1; }

/* The native cursor would draw a second one on top of this. */
body:has(.ptg-cursor.is-live),
body:has(.ptg-cursor.is-live) a,
body:has(.ptg-cursor.is-live) button { cursor: none; }

/* ---------- magnetic ---------- */
.ptg-magnetic {
  transition: transform .5s cubic-bezier(.16, 1, .3, 1),
              box-shadow .4s ease;
}

/* ---------- scroll progress ---------- */
.ptg-progress {
  position: fixed;
  top: 0; left: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg,
              transparent 0%,
              var(--amber) 40%,
              var(--amber) 60%,
              transparent 100%);
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 9999;
  pointer-events: none;
  will-change: transform;
}

/* ---------- rise reveal ----------
   NOT hidden by default. The hiding is applied from JS at the moment
   the observer is wired up, so if the script never runs — or the
   observer never fires — the visitor sees the content rather than a
   blank section. Failing open is the only safe default here. */
/* No will-change here. A blanket rule promoted every revealed element to its
   own compositor layer — this page ended up with 132 of them — and the reveal
   is a one-shot transition that the browser composites on its own. */
[data-rise].ptg-armed { opacity: 0; }

/* ---------- tilt hosts ---------- */
.ptg-tilt {
  transform-style: preserve-3d;
  transition: transform .55s cubic-bezier(.16, 1, .3, 1);
  will-change: transform;
}

/* ---------- char scrub ---------- */
[data-scrub] { display: inline-block; }
.ptg-char { display: inline-block; }

/* ---------- glare ---------- */
.price-card, .flip-card, .svc-card, .proof-card, .plan-card {
  position: relative;
  isolation: isolate;
}
.price-card::after, .flip-card::after, .svc-card::after,
.proof-card::after, .plan-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  background: radial-gradient(
    380px circle at var(--gx, 50%) var(--gy, 50%),
    rgba(242, 212, 134, .13),
    transparent 62%
  );
  z-index: 2;
}
.price-card:hover::after, .flip-card:hover::after, .svc-card:hover::after,
.proof-card:hover::after, .plan-card:hover::after { opacity: 1; }

/* ---------- field focus ---------- */
.field { transition: transform .35s cubic-bezier(.16, 1, .3, 1); }
.field.is-focused { transform: translateY(-2px); }
.field.is-focused input,
.field.is-focused textarea,
.field.is-focused select {
  border-color: rgba(242, 212, 134, .55);
  box-shadow: 0 0 0 3px rgba(242, 212, 134, .09);
}

/* ============================================================
   REDUCED MOTION — resolve every effect to its resting state.
   The JS already skips building the cursor and the progress bar,
   but the CSS must be safe on its own too.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .ptg-cursor { display: none; }
  .ptg-progress { display: none; }
  [data-rise], [data-rise].ptg-armed { opacity: 1; transform: none; }
  .ptg-char { opacity: 1; transform: none; }
  .ptg-magnetic, .ptg-tilt { transform: none !important; transition: none; }
}

/* ---------- reduced-motion: darker amber glow ---------- */
@media (prefers-reduced-motion: reduce) and (hover: hover) {
  .ptg-cursor__dot { background: var(--amber-dull); }
  .ptg-cursor.is-hot .ptg-cursor__ring,
  .ptg-cursor.is-hot .ptg-cursor__label { color: var(--amber-dull); }
}

/* ---------- coarse pointers: no cursor, no magnet ---------- */
@media (hover: none) {
  .ptg-cursor { display: none; }
  body:has(.ptg-cursor) a,
  body:has(.ptg-cursor) button { cursor: auto; }
}