/* ─────────────────────────────────────────────────────────────
   Kutly — Visual Effects
   Reusable building blocks: grain layer, grainy-gradient hero,
   blueprint rails, buttons, cards, pricing-card glow. Import
   AFTER colors_and_type.css.
   ───────────────────────────────────────────────────────────── */

/* ─── GRAIN ─────────────────────────────────────────────────────
   Two-layer grain: high-freq dither + low-freq blotch. Always
   pair them. `.grain-page` is the global cream-page overlay.
   ──────────────────────────────────────────────────────────── */
.grain-page {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  opacity: 0.06;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* The two-layer "heavy" grain — used inside dark/colored panels */
.grain-heavy::before,
.grain-heavy::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}
.grain-heavy::before {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='320' height='320'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.6' numOctaves='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.92 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 320px 320px;
  mix-blend-mode: overlay;
  opacity: 0.85;
}
.grain-heavy::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='640' height='640'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.55' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 640px 640px;
  mix-blend-mode: overlay;
  opacity: 0.55;
}

/* Card-scale grey grain — softer, used on crew/feature cards */
.grain-soft::before,
.grain-soft::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.grain-soft::before {
  background:
    radial-gradient(ellipse 80% 90% at 110% 110%, rgba(120,113,108,0.08), transparent 65%),
    radial-gradient(ellipse 60% 60% at -10% -10%, rgba(120,113,108,0.06), transparent 65%);
}
.grain-soft::after {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='260' height='260'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 260px 260px;
  mix-blend-mode: multiply;
  opacity: 0.08;
}
.grain-soft > * { position: relative; z-index: 1; }

/* ─── GRAINY GRADIENT HERO ──────────────────────────────────────
   THE signature surface. A deep base + 3 colored radial blobs.
   Intentionally STATIC: animating the blob positions repaints the
   whole layer every frame (expensive) — keep it a frozen frame.
   Combine with `.grain-heavy` for the full look. Two palettes:
   warm (default) + purple.
   ──────────────────────────────────────────────────────────── */
.grainy-hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.grainy-hero > * { position: relative; z-index: 3; }
.grainy-hero .gh-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* Warm (default) */
.grainy-hero .gh-bg,
[data-theme="warm"] .grainy-hero .gh-bg {
  background:
    radial-gradient(ellipse 75% 75% at 8% 92% in oklab, rgba(60,110,210,0.90) 0%, rgba(60,110,210,0.55) 22%, rgba(60,110,210,0.25) 45%, transparent 72%),
    radial-gradient(ellipse 55% 50% at var(--bx1, 30%) var(--by1, 50%) in oklab,  rgba(255,120,40,0.95) 0%, rgba(255,120,40,0.60) 28%, transparent 65%),
    radial-gradient(ellipse 60% 50% at var(--bx2, 78%) var(--by2, 60%) in oklab,  rgba(255,160,60,1) 0%, rgba(255,160,60,0.65) 28%, transparent 65%),
    radial-gradient(ellipse 50% 45% at var(--bx3, 50%) var(--by3, 30%) in oklab,  rgba(230,80,30,0.85) 0%, transparent 65%),
    radial-gradient(ellipse 55% 55% at calc(var(--bx2, 78%) - 65%) calc(var(--by1, 50%) - 55%) in oklab, rgba(255,140,70,0.75) 0%, rgba(255,140,70,0.35) 30%, transparent 70%),
    radial-gradient(ellipse 90% 100% at 50% 0% in oklab, #3A0F08 0%, #5C1A0C 45%, #7A2A12 90%);
}
/* Purple */
[data-theme="purple"] .grainy-hero .gh-bg {
  background:
    radial-gradient(ellipse 60% 50% at var(--bx1, 50%) var(--by1, 105%) in oklab, rgba(232,152,122,0.95) 0%, rgba(232,152,122,0.55) 18%, rgba(195,140,160,0.30) 38%, transparent 65%),
    radial-gradient(ellipse 70% 45% at var(--bx2, 50%) var(--by2, 80%) in oklab,  rgba(195,154,187,0.80) 0%, rgba(168,138,180,0.50) 25%, transparent 65%),
    radial-gradient(ellipse 50% 40% at var(--bx3, 30%) var(--by3, 60%) in oklab,  rgba(139,123,216,0.55), transparent 70%),
    radial-gradient(ellipse 90% 100% at 50% 0% in oklab, #1B2447 0%, #2D2A5C 40%, #3D3B6E 85%);
}

/* Fine high-frequency dither on top of the colored gradient — kills banding */
.grainy-hero .gh-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='2.4' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 200px 200px;
  mix-blend-mode: soft-light;
  opacity: 0.9;
}

/* ─── BLUEPRINT RAILS ───────────────────────────────────────────
   Dashed vertical lines that frame the content column. Dot
   markers appear where section dividers cross them.
   ──────────────────────────────────────────────────────────── */
.page-rails {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.page-rails .rail {
  position: absolute;
  top: 0; bottom: 0;
  width: 1px;
  background: var(--border-dashed);
}
.page-rails .rail.left  { left: var(--rail-gutter); }
.page-rails .rail.right { right: var(--rail-gutter); }

.section-rule {
  position: relative;
  border-top: 1px solid var(--border);
}
.section-rule::before,
.section-rule::after {
  content: '';
  position: absolute;
  top: -3px;
  margin-left: -2px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  border: 1px solid var(--border-dot);
  background: transparent;
  pointer-events: none;
}
.section-rule::before { left: var(--rail-gutter); }
.section-rule::after  { left: calc(100% - var(--rail-gutter) - 1px); }

/* ─── BUTTONS ───────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--text-base);
  line-height: 1;
  padding: 9px 16px;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.2s;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }

.btn-dark {
  background: #0A0A0A;
  color: #FAFAF7;
  border-color: #0A0A0A;
}
.btn-dark:hover { background: #1F1F1F; border-color: #1F1F1F; }

.btn-light {
  background: #FFFFFF;
  color: #0A0A0A;
  font-weight: 600;
  padding: 14px 26px;
  box-shadow: var(--shadow-button);
}
.btn-light:hover { transform: translateY(-1px); box-shadow: var(--shadow-button-hover); }
.btn-light:active { transform: translateY(0); }

.btn-ghost {
  background: transparent;
  color: var(--fg-1);
  border-color: var(--border-strong);
  padding: 13px 24px;
}
.btn-ghost:hover { border-color: rgba(10,10,10,0.32); background: rgba(10,10,10,0.025); }

.btn-large { padding: 14px 26px; font-weight: 600; }

/* ─── BADGES ─────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-strong);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--fg-2);
  text-transform: uppercase;
}
.badge .live-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: livePulse 1.6s ease-in-out infinite;
}
@keyframes livePulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}

/* ─── CARDS ──────────────────────────────────────────────────── */
.card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  position: relative;
}
.card-hover {
  transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
.card-hover:hover {
  transform: translateY(-1px);
  border-color: rgba(0,0,0,0.18);
  box-shadow: var(--shadow-card-hover);
}

/* ─── HOVER LINKS ────────────────────────────────────────────── */
.hover-link {
  color: var(--fg-2);
  text-decoration: none;
  transition: color 0.2s ease;
}
.hover-link:hover { color: var(--fg-1); }

/* ─── REVEAL ─────────────────────────────────────────────────── */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
.reveal { animation: fadeUp 0.7s ease both; }

/* ─── SCROLLBAR ──────────────────────────────────────────────── */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: #D5D1C8; border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: #B8B3A8; }

/* ─── KEYBOARD FOCUS RING ─────────────────────────────────────
   One brand ring on every interactive primitive — premium apps never
   rely on the inconsistent UA outline (faint on a dark theme). */
.btn:focus-visible,
.btn-app:focus-visible,
.generate-btn:focus-visible,
.k2-btn:focus-visible,
.opt-card:focus-visible,
.picker-trigger:focus-visible,
.k2-acc-item:focus-visible,
.sb-item:focus-visible,
.dropzone:focus-visible,
.card-menu-btn:focus-visible,
.card-menu-item:focus-visible,
.overlay-close:focus-visible,
.hover-link:focus-visible,
/* Controls converted from <a onClick>/<div role=button> to real Link/button — they
   became keyboard-focusable, so they get the same brand ring as everything else. */
.project-card:focus-visible,
.qs-card:focus-visible,
.hero-render:focus-visible,
.pack-card:focus-visible,
.overlay-rail .rail-item:focus-visible,
.voice-row .vr-select:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
/* Inset/segmented controls: hug the edge so the ring isn't clipped. */
.mode-seg:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: -2px;
}

/* The "… is typing" caret pulse on the Generating screen — the keyframe
   was referenced by .gen-typing-dots (app.css) but never defined. */
@keyframes caretBlink {
  0%, 50%      { opacity: 1; }
  50.01%, 100% { opacity: 0.25; }
}

/* ─── REDUCED MOTION ──────────────────────────────────────────
   Honor the OS "reduce motion" setting — neutralize all non-essential
   animation/transition (incl. the infinite pulse/shimmer indicators). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ─── NATIVE FEEL: drag + selection ───────────────────────────
   Decorative imagery inside clickable surfaces must not ghost-drag on press,
   and UI chrome (nav, labels, badges, metrics, eyebrows) is not prose. */
.pt-img, .sb-wordmark, .qs-card img, .yt-thumb img, .fin-thumb-img img {
  -webkit-user-drag: none;
  user-select: none;
}
.sb-item, .sb-section-label, .badge, .pt-status, .pt-dur, .metric, .m-lbl,
.field-label, .pm-sub, .vr-name, .vr-meta, .opt-name, .hero-eyebrow, .app-title .sub {
  -webkit-user-select: none;
  user-select: none;
}
