/* cp-components.css — Control-Plane component primitives.
 *
 * The .cp-* component classes (cp-hero, cp-status-strip, cp-section-title,
 * cp-caret, cp-scanline, cp-anim, cp-eyebrow, cp-mono, cp-cta, cp-signal,
 * cp-status-chip / cp-status-num / cp-status-static / cp-status-cap, etc.)
 * used to be duplicated across home.css, lab.css and sobre.css. This file
 * is the single global home for all of them — extracted from home.css in
 * Task 3.2 (Phase 3). The duplicates in lab.css / sobre.css were removed
 * in the same commit.
 *
 * Loaded globally between components.css and style.css, so every page that
 * uses any .cp-* class — homepage, /sobre/, /lab/, /proyectos/, single
 * posts — gets these primitives.
 *
 * Where lab.css and sobre.css disagreed on a rule body and home.css had
 * neither, sobre.css wins (it was the most-recently-touched of the two
 * per Phase 2's consolidation note in CLAUDE.md). The two cases were
 * .cp-eyebrow and .cp-section-title; either page can override locally.
 *
 * Depends on: jacar-components (so components.css and the underlying
 * tokens / base / layout chain is loaded before us).
 */

/* ============================================================
   CP-MOTION — RM gates and shared keyframes for the Control Plane
   redesign. Migrated here from the deleted assets/css/cp-motion.css.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  /* Hard reset: any element opted into a CP animation falls flat. */
  .cp-anim,
  .cp-anim * {
    animation: none !important;
    transition: none !important;
  }
}

@keyframes cp-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.cp-caret {
  display: inline-block;
  width: 0.6ch;
  margin-left: 0.05ch;
  background: currentColor;
  vertical-align: -0.1em;
  animation: cp-blink 1s steps(1) infinite;
}
@media (prefers-reduced-motion: reduce) {
  .cp-caret { animation: none; opacity: 0.6; }
}

@keyframes cp-scan {
  from { transform: translateX(-30%); opacity: 0; }
  20%  { opacity: 0.7; }
  to   { transform: translateX(130%); opacity: 0; }
}

.cp-scanline {
  position: absolute;
  inset: 0 auto 0 0;
  width: 30%;
  background: linear-gradient(90deg, transparent, var(--color-border-strong), transparent);
  pointer-events: none;
  animation: cp-scan 2.4s var(--ease-out) 1 forwards;
}
@media (prefers-reduced-motion: reduce) { .cp-scanline { display: none; } }

/* ============================================================
   Shared section utilities — used by /sobre, /lab and any future
   CP page. Both pages had divergent versions; sobre's wins.
   ============================================================ */
.cp-section-title {
  font-family: var(--font-sans);
  font-size: clamp(1.6rem, 3.2vw, 2.4rem);
  line-height: 1.2;
  margin: 0 0 1rem;
  letter-spacing: -0.01em;
}
.cp-eyebrow {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 0.5rem;
}

/* ============================================================
 * Hero — was assets/css/hero.css (merged into home.css 2026-04-28,
 * extracted here 2026-04-28 Task 3.2).
 * Layout + base hero rules. The .cp-hero shell is the homepage
 * hero on /, and is reused (with overrides) by .sobre-hero and
 * .lab-hero on /sobre/ and /lab/. Background visuals are owned
 * by the JCS hero recipe block at the bottom of home.css (kept
 * there because it is homepage-specific).
 * ============================================================ */

.cp-hero {
  /* Layout only — background is owned by the JCS hero recipe block in home.css. */
  min-height: clamp(260px, 44vh, 410px);
  color: #ffffff; /* dark hero, light text */
  padding: clamp(1.5rem, 4vw, 3rem) var(--rhythm-block) clamp(1rem, 3vw, 2rem);
  display: flex;
  align-items: center;
}

.cp-hero__grid {
  z-index: 1;
  opacity: 0.18;
}

.cp-hero__inner {
  position: relative;
  z-index: 2;
  width: min(100%, 64rem);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(0.75rem, 2vw, 1.25rem);
}

.cp-hero__eyebrow {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0;
}

.cp-hero__title {
  font-family: var(--font-sans);
  font-size: clamp(2.4rem, 6.5vw, 5rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  font-weight: 700;
  margin: 0;
  text-wrap: balance;
}
.cp-hero__title .cp-hero__prefix,
.cp-hero__title .cp-hero__tail {
  display: inline;
  white-space: pre-wrap;
}
.cp-hero__title .cp-hero__tail {
  background: linear-gradient(96deg, var(--glow-a), var(--glow-b));
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}

.cp-hero__sub {
  font-family: var(--font-sans);
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  line-height: 1.5;
  color: var(--color-text-muted);
  max-width: 48rem;
  margin: 0;
}

.cp-hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0.75rem 0 0;
}

.cp-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.85rem 1.25rem;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  border: 1px solid var(--color-border-strong);
  /* primary CTA copies the brand-pair gradient; we want the text always
     readable. On light theme the pair is teal→lime-dark (mid-tone), so
     ink-on-gradient (dark text) works. On dark theme the pair brightens
     to teal-bright→lime-bright; here a near-paper text reads better.
     Each theme block below sets the CTA foreground colour explicitly. */
  transition: transform var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
  will-change: transform;
}
.cp-cta--primary {
  background: linear-gradient(96deg, var(--glow-a), var(--glow-b));
  /* On light theme: the gradient is mid-tone teal→olive; white text fails
     contrast. Use ink (dark) text. On dark theme: bright teal→lime;
     paper (near-white) text wins. tokens.css flips --color-bg-page /
     --color-text-body per theme, so referencing them here would invert
     to white-on-dark and near-black-on-light, which is the OPPOSITE of
     what we want. Resolve explicitly below per theme. */
  color: #ffffff;
  border-color: transparent;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
}
:root .cp-cta--primary { color: #ffffff; }
[data-theme="dark"] .cp-cta--primary { color: #0d1117; text-shadow: none; }
@media (prefers-color-scheme: dark) {
  [data-theme="system"] .cp-cta--primary { color: #0d1117; text-shadow: none; }
}
.cp-cta--secondary {
  background: transparent;
  color: var(--color-text-body);
}
.cp-cta:focus-visible {
  outline: 2px solid var(--color-text-body);
  outline-offset: 3px;
}
.cp-cta:hover { border-color: var(--color-border-strong); }

/* Status strip */
.cp-status-strip {
  list-style: none;
  margin: clamp(1.25rem, 3vw, 2.5rem) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.75rem, 2vw, 1.5rem);
  border-top: 1px solid var(--color-border);
  padding-top: clamp(0.75rem, 2vw, 1.25rem);
}
.cp-status-strip--vertical { flex-direction: column; align-items: center; gap: 0.4rem; }
.cp-status-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  font-size: 0.86rem;
  color: var(--color-text-muted);
}
.cp-status-num,
.cp-status-static {
  color: var(--color-text-body);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cp-signal {
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  border-radius: 999px;
  margin-right: 0.15em;
  vertical-align: -0.05em;
}
.cp-signal--ok   { background: var(--color-signal-ok);   box-shadow: 0 0 8px var(--color-signal-ok); }
.cp-signal--warn { background: var(--color-signal-warn); box-shadow: 0 0 8px var(--color-signal-warn); }
.cp-signal--err  { background: var(--color-signal-err);  box-shadow: 0 0 8px var(--color-signal-err); }

/* Mobile */
@media (max-width: 720px) {
  .cp-hero { min-height: 50vh; padding-top: 2.25rem; }
  .cp-hero__title { font-size: clamp(2rem, 9vw, 3.4rem); }
  .cp-hero__ctas .cp-cta { width: 100%; justify-content: center; }
  .cp-status-strip { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
}

/* Reduced motion: paint the gradient straight, no caret blink, no scan. */
@media (prefers-reduced-motion: reduce) {
  .cp-hero__mesh { filter: none; }
  .cp-caret      { display: none; }
}
