/* materialize.css
   Apple-style materialization placeholders for WMWH.

   These are NOT skeleton loaders. The metaphor is matte paper
   under a slowly drifting gallery spotlight — not iOS frosted glass.

   Sections:
   1. .mat-stack    — required grid-stacked wrapper (placeholder + content at 1/1)
   2. Primitives    — .mat-text / .mat-heading / .mat-block / .mat-pill / .mat-avatar
   3. Luminance     — ::before/::after pseudos drive 7s/11s coprime drift + 9s warmth pass
   4. Blur-to-focus — image filter transition for .mat-block--image
   5. Crossfade     — placeholder out + content in, simultaneous within a layer
   6. Layer cascade — data-layer="1..5" delays the reveal per layer
   7. Ambient       — half-alpha drift on settled .card / .tier / hero panel
   8. Reduced-motion overrides + high-contrast hardening
*/


/* ═══════════════════════════════════════════════════════════
   0. CUSTOM PROPERTIES — drift coordinates
   @property registers the typed custom props so they can be
   smoothly animated cross-browser. Safari old fallback: the
   @keyframes still animate the value, they just won't tween
   between keyframes — perceptually identical at this speed.
   ═══════════════════════════════════════════════════════════ */

@property --mat-drift-x {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 30%;
}
@property --mat-drift-y {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 40%;
}


/* ═══════════════════════════════════════════════════════════
   1. .mat-stack — grid-stacked wrapper
   Placeholder and content share grid-area: 1/1.
   Zero pixel shift on toggle. Required parent.
   ═══════════════════════════════════════════════════════════ */

.mat-stack {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto;
  position: relative;
}

.mat-stack > [data-mat-placeholder],
.mat-stack > [data-mat-content] {
  grid-area: 1 / 1;
  min-width: 0;
}

/* Content starts hidden. JS removes data-loading after layer fires. */
.mat-stack > [data-mat-content] {
  opacity: 0;
  transition: opacity var(--dur-materialize) var(--ease-spring);
  pointer-events: none;
}

.mat-stack[data-loading="false"] > [data-mat-content] {
  opacity: 1;
  pointer-events: auto;
}

.mat-stack > [data-mat-placeholder] {
  opacity: 1;
  transition: opacity var(--dur-materialize) var(--ease-settle);
  pointer-events: none;
}

.mat-stack[data-loading="false"] > [data-mat-placeholder] {
  opacity: 0;
  /* After fade-out completes, remove from a11y/layout tree. */
  visibility: hidden;
  transition:
    opacity var(--dur-materialize) var(--ease-settle),
    visibility 0s linear var(--dur-materialize);
}


/* ═══════════════════════════════════════════════════════════
   2. PRIMITIVES — base surfaces

   Base surface = rgba(5,5,5,0.035) — warm off-white, not gray.
   Overlay layers add the drift; the base itself never animates.
   ═══════════════════════════════════════════════════════════ */

.mat-text,
.mat-heading,
.mat-block,
.mat-pill,
.mat-avatar {
  position: relative;
  display: block;
  background-color: rgba(5, 5, 5, 0.035);
  overflow: hidden;
  isolation: isolate;
  /* Stable height so layout matches the final content footprint. */
  flex-shrink: 0;
}

/* ── Text rows — sans-serif body proportion ─────────────── */
.mat-text {
  height: 0.875em;
  margin: calc(1.65em * 0.225) 0;  /* mirrors --leading-body 1.65 */
  border-radius: 3px;
  width: var(--mat-w, 85%);
}
.mat-text[data-w="30"]   { --mat-w: 30%; }
.mat-text[data-w="45"]   { --mat-w: 45%; }
.mat-text[data-w="60"]   { --mat-w: 60%; }
.mat-text[data-w="75"]   { --mat-w: 75%; }
.mat-text[data-w="85"]   { --mat-w: 85%; }
.mat-text[data-w="100"]  { --mat-w: 100%; }

/* Display modifier — serif proportions (Cormorant), tighter leading. */
.mat-text--display {
  height: 1em;
  margin: calc(1.05em * 0.18) 0;
}

/* ── Headings — three sizes, tight leading ───────────────── */
.mat-heading {
  border-radius: 4px;
  width: var(--mat-w, 70%);
  height: 1em;
  margin: 0.15em 0 0.45em;
  /* Heading line-height matches --leading-tight (1.05). */
}
.mat-heading[data-size="h1"] { font-size: var(--size-h1); }
.mat-heading[data-size="h2"] { font-size: var(--size-h2); }
.mat-heading[data-size="h3"] { font-size: var(--size-h3); }
.mat-heading[data-size="hero"] { font-size: var(--size-hero); }

/* ── Blocks — surfaces / image placeholders ──────────────── */
.mat-block {
  border-radius: var(--radius-card);
  width: 100%;
  aspect-ratio: var(--mat-ratio, 16 / 9);
}
.mat-block[data-ratio="1-1"]   { --mat-ratio: 1 / 1; }
.mat-block[data-ratio="16-9"]  { --mat-ratio: 16 / 9; }
.mat-block[data-ratio="4-5"]   { --mat-ratio: 4 / 5; }
.mat-block[data-ratio="3-4"]   { --mat-ratio: 3 / 4; }
.mat-block[data-ratio="21-9"]  { --mat-ratio: 21 / 9; }

/* ── Pill / CTA stand-in ──────────────────────────────────── */
.mat-pill {
  border-radius: var(--radius-pill);
  height: 3rem;
  width: var(--mat-w, 14rem);
  max-width: 100%;
}
.mat-pill[data-size="sm"] { height: 2.25rem; }
.mat-pill[data-size="lg"] { height: 3.5rem;  width: var(--mat-w, 18rem); }

/* ── Avatar — circle ──────────────────────────────────────── */
.mat-avatar {
  border-radius: 50%;
  width: 3rem;
  height: 3rem;
}


/* ═══════════════════════════════════════════════════════════
   3. LUMINANCE DRIFT — ambient motion overlays

   Two overlays:
   ::after  — radial spotlight, X cycles 7s, Y cycles 11s (coprime).
   ::before — diagonal warmth pass at 9s. Imperceptibly soft.

   Peak alpha 0.18 (Facebook shimmer is 0.55+ — deliberately a third).
   Only the overlays animate. Base surface is static.
   ═══════════════════════════════════════════════════════════ */

.mat-text::after,
.mat-heading::after,
.mat-block::after,
.mat-pill::after,
.mat-avatar::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: radial-gradient(
    ellipse at var(--mat-drift-x, 30%) var(--mat-drift-y, 40%),
    rgba(245, 245, 240, 0.18) 0%,
    rgba(245, 245, 240, 0.05) 30%,
    rgba(245, 245, 240, 0) 55%
  );
  animation:
    mat-drift-x 7s ease-in-out infinite alternate,
    mat-drift-y 11s ease-in-out infinite alternate;
  will-change: --mat-drift-x, --mat-drift-y;
}

.mat-text::before,
.mat-heading::before,
.mat-block::before,
.mat-pill::before,
.mat-avatar::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(
    105deg,
    transparent 0%,
    rgba(255, 255, 255, 0.04) 50%,
    transparent 100%
  );
  transform: translateX(-30%);
  animation: mat-warmth 9s ease-in-out infinite alternate;
  will-change: transform;
}

@keyframes mat-drift-x {
  0%   { --mat-drift-x: 20%; }
  100% { --mat-drift-x: 78%; }
}
@keyframes mat-drift-y {
  0%   { --mat-drift-y: 30%; }
  100% { --mat-drift-y: 72%; }
}
@keyframes mat-warmth {
  0%   { transform: translateX(-30%); }
  100% { transform: translateX(30%); }
}


/* ═══════════════════════════════════════════════════════════
   4. BLUR-TO-FOCUS — image materialization

   Usage: <img class="mat-image" data-mat-src="/path/to/full.jpg"
                src="data:image/jpeg;base64,...24px LQIP..." alt="">
   On materialize:layer-3 the JS sets data-mat-loaded; CSS transitions
   filter from blur(20px) saturate(1.1) → blur(0) saturate(1).
   ═══════════════════════════════════════════════════════════ */

.mat-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Slight upscale hides LQIP block edges. */
  transform: scale(1.04);
  filter: blur(20px) saturate(1.1);
  transition:
    filter var(--dur-blur-focus) var(--ease-spring),
    transform var(--dur-blur-focus) var(--ease-spring);
  will-change: filter, transform;
}

.mat-image[data-mat-loaded="true"] {
  filter: blur(0) saturate(1);
  transform: scale(1);
}

/* When the .mat-block wraps an image, it inherits the final radius
   and clips the blur-to-focus image to its corners. */
.mat-block--image {
  background-color: rgba(5, 5, 5, 0.06);
  position: relative;
  aspect-ratio: var(--mat-ratio, 16 / 9);
  overflow: hidden;
}
.mat-block--image > .mat-image {
  position: absolute;
  inset: 0;
}


/* ═══════════════════════════════════════════════════════════
   5. LAYER CASCADE — data-layer="1..5"

   data-layer drives a transition-delay on .mat-stack so layers
   fire in sequence with --dur-layer-gap (90ms) spacing.

   Layer 1: headings        (delay 0)
   Layer 2: body text       (delay 90ms)
   Layer 3: images          (delay 180ms)
   Layer 4: CTAs / secondary (delay 270ms)
   Layer 5: scroll-triggered animations bind (no DOM delay — JS event)
   ═══════════════════════════════════════════════════════════ */

.mat-stack[data-layer="1"] > [data-mat-content],
.mat-stack[data-layer="1"] > [data-mat-placeholder] {
  transition-delay: 0ms;
}
.mat-stack[data-layer="2"] > [data-mat-content],
.mat-stack[data-layer="2"] > [data-mat-placeholder] {
  transition-delay: var(--dur-layer-gap);
}
.mat-stack[data-layer="3"] > [data-mat-content],
.mat-stack[data-layer="3"] > [data-mat-placeholder] {
  transition-delay: calc(var(--dur-layer-gap) * 2);
}
.mat-stack[data-layer="4"] > [data-mat-content],
.mat-stack[data-layer="4"] > [data-mat-placeholder] {
  transition-delay: calc(var(--dur-layer-gap) * 3);
}


/* ═══════════════════════════════════════════════════════════
   6. PATTERN UTILITIES — content-aware placeholder layouts

   Each .mat-pattern-* traces the shape of a real component.
   The shapes go in materialize.js; these classes give the
   placeholder its layout so it footprints the same as content.
   ═══════════════════════════════════════════════════════════ */

.mat-pattern {
  display: block;
  width: 100%;
}

/* Hero display pattern — eyebrow line, two heading rows, body, CTA. */
.mat-pattern--hero {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: flex-start;
}
.mat-pattern--hero .mat-text--eyebrow {
  height: 0.6875em;
  width: 12rem;
  margin: 0 0 0.5rem;
}

/* Card pattern — image area, heading, two body rows, CTA. */
.mat-pattern--card {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: var(--card-pad, 1.75rem);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  height: 100%;
  box-sizing: border-box;
}

/* Card grid pattern — wraps multiple card patterns. */
.mat-pattern--card-grid {
  display: grid;
  gap: 1.25rem;
}
.mat-pattern--card-grid[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
.mat-pattern--card-grid[data-cols="3"] { grid-template-columns: repeat(3, 1fr); }
.mat-pattern--card-grid[data-cols="4"] { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  .mat-pattern--card-grid[data-cols="3"],
  .mat-pattern--card-grid[data-cols="4"] {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 600px) {
  .mat-pattern--card-grid {
    grid-template-columns: 1fr !important;
  }
}

/* Pricing tiers — middle taller. */
.mat-pattern--tiers {
  display: grid;
  grid-template-columns: 1fr 1.05fr 1fr;
  gap: 1.25rem;
  align-items: stretch;
}
.mat-pattern--tiers > .mat-pattern--card:nth-child(2) {
  transform: scaleY(1.04);
  transform-origin: center;
}
@media (max-width: 900px) {
  .mat-pattern--tiers {
    grid-template-columns: 1fr;
  }
  .mat-pattern--tiers > .mat-pattern--card:nth-child(2) {
    transform: none;
  }
}

/* Accordion rows — FAQ list. */
.mat-pattern--accordion {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.mat-pattern--accordion .mat-accordion-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--color-border);
}
.mat-pattern--accordion .mat-accordion-row > .mat-text { flex: 1; margin: 0; }
.mat-pattern--accordion .mat-accordion-row > .mat-chevron {
  width: 12px; height: 12px;
  background-color: rgba(5, 5, 5, 0.035);
  border-radius: 2px;
  flex-shrink: 0;
  position: relative;
  overflow: hidden;
}

/* Diagnosis card pattern — heading + 4 answer pills. */
.mat-pattern--diagnosis {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  max-width: 720px;
}
.mat-pattern--diagnosis .mat-answer-stack {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}
.mat-pattern--diagnosis .mat-pill {
  width: 100%;
  height: 4.25rem;
  border-radius: var(--radius-card);
}

/* Contact form pattern — labels + inputs + submit. */
.mat-pattern--form {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  max-width: 560px;
}
.mat-pattern--form .mat-field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.mat-pattern--form .mat-field > .mat-text {
  height: 0.75em;
  width: 8rem;
  margin: 0;
}
.mat-pattern--form .mat-field > .mat-block {
  aspect-ratio: auto;
  height: 3rem;
  border-radius: var(--radius-md);
}
.mat-pattern--form .mat-field--textarea > .mat-block {
  height: 8rem;
}


/* ═══════════════════════════════════════════════════════════
   7. AMBIENT MOTION (post-materialization)

   After materialize:complete the body gets data-mat-settled="true"
   which enables a half-alpha drift on settled content surfaces.
   Card-like surfaces feel softly alive at all times.

   Pauses on:
     - prefers-reduced-motion
     - :hover of interactive elements
     - data-mat-no-ambient (text-heavy reading pages)
   ═══════════════════════════════════════════════════════════ */

body[data-mat-settled="true"] .card::after,
body[data-mat-settled="true"] .price-tier::after,
body[data-mat-settled="true"] .hero__content::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  border-radius: inherit;
  background: radial-gradient(
    ellipse at var(--mat-drift-x, 30%) var(--mat-drift-y, 40%),
    rgba(245, 245, 240, 0.09) 0%,
    rgba(245, 245, 240, 0.02) 35%,
    rgba(245, 245, 240, 0) 60%
  );
  animation:
    mat-drift-x 7s ease-in-out infinite alternate,
    mat-drift-y 11s ease-in-out infinite alternate;
}

/* Ambient drift surfaces need a positioning context. The .card class
   already gets position:relative via card.css; this is a guard. */
body[data-mat-settled="true"] .card,
body[data-mat-settled="true"] .price-tier {
  position: relative;
}

/* Pause ambient drift on hover so motion doesn't compete with the user. */
body[data-mat-settled="true"] .card:hover::after,
body[data-mat-settled="true"] .price-tier:hover::after,
body[data-mat-settled="true"] .hero__content:hover::after {
  animation-play-state: paused;
  opacity: 0;
  transition: opacity var(--dur-feedback) var(--ease-feedback);
}

/* Opt-out for text-heavy reading pages. */
body[data-mat-no-ambient="true"] .card::after,
body[data-mat-no-ambient="true"] .price-tier::after,
body[data-mat-no-ambient="true"] .hero__content::after {
  display: none;
}


/* ═══════════════════════════════════════════════════════════
   8. ACCESSIBILITY — visually hidden announcer
   ═══════════════════════════════════════════════════════════ */

.mat-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


/* ═══════════════════════════════════════════════════════════
   9. REDUCED MOTION + HIGH CONTRAST
   ═══════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .mat-text::after,
  .mat-heading::after,
  .mat-block::after,
  .mat-pill::after,
  .mat-avatar::after,
  .mat-text::before,
  .mat-heading::before,
  .mat-block::before,
  .mat-pill::before,
  .mat-avatar::before,
  body[data-mat-settled="true"] .card::after,
  body[data-mat-settled="true"] .price-tier::after,
  body[data-mat-settled="true"] .hero__content::after {
    animation: none;
  }

  .mat-stack > [data-mat-placeholder],
  .mat-stack > [data-mat-content] {
    transition-duration: 100ms;
    transition-timing-function: linear;
  }

  .mat-image {
    transition-duration: 120ms;
    transition-timing-function: linear;
  }
}

@media (prefers-contrast: more) {
  .mat-text::after,
  .mat-heading::after,
  .mat-block::after,
  .mat-pill::after,
  .mat-avatar::after,
  .mat-text::before,
  .mat-heading::before,
  .mat-block::before,
  .mat-pill::before,
  .mat-avatar::before {
    background: transparent;
    animation: none;
  }
  .mat-text,
  .mat-heading,
  .mat-block,
  .mat-pill,
  .mat-avatar {
    background-color: rgba(5, 5, 5, 0.10);
  }
}
