/* ==========================================================================
   Jumaro AI — visual refinement layer
   --------------------------------------------------------------------------
   Additive only. Loaded AFTER the compiled Tailwind bundle so it can refine
   without touching the React source (which does not exist on this machine).
   Nothing here changes copy, structure, routing or behaviour.

   Design position: the site's own language — near-black / white / #f5f5f7
   alternation, single blue accent, Manrope + Plus Jakarta — is kept exactly.
   This layer fixes legibility, gives the light sections depth, tightens the
   vertical rhythm, and cleans the black<->light seams.
   ========================================================================== */

:root{
  --jm-blue:#1d4ed8;
  --jm-blue-lift:#3b82f6;
  --jm-ink:#0f172a;
  --jm-ease:cubic-bezier(.16,1,.3,1);      /* ease-out-expo, matches the site */
  --jm-ease-soft:cubic-bezier(.22,.61,.36,1);
  /* semantic z-scale, replaces ad-hoc values */
  --jm-z-sticky:40;
  --jm-z-header:50;
  --jm-z-overlay:60;
}

/* ==========================================================================
   1. LEGIBILITY
   Five distinct colour/size combinations failed WCAG AA on the live page.
   Each override below targets one of them, measured rather than guessed.
   ========================================================================== */

/* NOTE: the app root is <div class="min-h-screen bg-white">, so ANY selector of
   the form `.bg-white X` or `.bg-black X` matches essentially the whole site and
   cannot be used to infer a painted background. The site also nests white
   product panels inside black sections. Colour corrections therefore target the
   element's own class combination only, never an ancestor's background class.
   Each ratio below was measured on the live page. */

/* 1a. Decorative step numerals: slate-200 at 60px on white measured 1.23:1.
   Large text needs 3:1; this lands at 3.6:1 and stays visibly secondary. */
.text-slate-200.tabular-nums{ color:#7d8798; }

/* 1b. 11px slate-300 step numerals on the white section measured 1.48:1. */
section.bg-white .text-slate-300.tabular-nums{ color:#68758a; }

/* 1c/1d. Muted greys sitting on the genuinely dark surfaces measured 2.77:1
   (slate-600 arrows) and 4.41:1 (slate-500 labels). The :not() guards exclude
   the OPAQUE white product panels nested INSIDE the black hero (the
   exact class .bg-white only -- translucent bg-white/[0.04] chips are still
   dark surfaces and must NOT be excluded) — those keep
   their dark-on-light treatment. If a browser cannot parse the complex :not(),
   the whole rule is skipped and the colours simply stay as they are today. */

footer.bg-black :is(.text-slate-600,.text-slate-500),
footer :is(.text-slate-600,.text-slate-500){ color:#a3adbf; }
/* The dark surfaces use .text-xs; the white product panel nested in the hero
   uses .text-[11px]. That distinction separates them exactly, with no
   ancestor guessing -- the app root itself carries .bg-white, so ANY
   :not(.bg-white *) guard would exclude the whole document. */
section.bg-black .text-slate-600.text-xs{ color:#98a2b4; }
section.bg-black .text-xs.text-slate-500{ color:#a3adbf; }

/* Footer body text inherits slate-500 from its wrapper. */
footer.bg-black,footer.bg-black p,footer.bg-black li{ color:#a3adbf; }
footer .hover\:text-slate-300:hover{ color:#e2e8f0; }

/* 1e. slate-500 on the #f5f5f7 band measured 4.37:1 — just under AA. */
section.bg-\[\#f5f5f7\] .text-slate-500:not(.bg-black *){ color:#5b6879; }

/* 1f. Placeholders inherited the 400-level grey (2.8:1). */
.input-field::placeholder{ color:#6b7891; opacity:1; }

/* 1g. 50 elements rendered below 13px. Lift the floor without disturbing
   layout: 11px -> 12px, 12px -> 12.5px, and open the tracking slightly so
   the smallest labels stay comfortable. */
.text-\[11px\]{ font-size:12px; letter-spacing:.01em; }
.text-xs{ font-size:12.5px; }

/* ==========================================================================
   2. MEASURE
   Body paragraphs ran to ~90ch. Cap the reading measure; headings keep their
   own balance so they break evenly instead of leaving orphans.
   ========================================================================== */
section p:not([class*="max-w"]){ max-width:68ch; }
section h1,section h2,section h3{ text-wrap:balance; }
section p{ text-wrap:pretty; }

/* ==========================================================================
   3. SEAMS
   The black -> light transitions used a soft gradient that rendered as a grey
   smear across ~90px. Replace it with a clean edge plus a narrow, intentional
   falloff so the change of surface reads as deliberate.
   ========================================================================== */
section.bg-white + section.bg-black,
section.bg-\[\#f5f5f7\] + section.bg-black{
  box-shadow:inset 0 1px 0 rgba(255,255,255,.08);
}
section.bg-black + section.bg-white,
section.bg-black + section.bg-\[\#f5f5f7\]{
  box-shadow:inset 0 1px 0 rgba(15,23,42,.10);
}

/* ==========================================================================
   4. SURFACE DEPTH
   The light sections were flat white cards on flat white ground: correct, but
   inert. Give them a resting elevation and a real hover, without the
   border-plus-wide-shadow "ghost card" pairing.
   ========================================================================== */
section.bg-\[\#f5f5f7\] .rounded-xl.border,
section.bg-white .rounded-xl.border{
  box-shadow:0 1px 2px rgba(15,23,42,.04);
  transition:box-shadow .34s var(--jm-ease),
             transform .34s var(--jm-ease),
             border-color .34s ease;
}
section.bg-\[\#f5f5f7\] .rounded-xl.border:hover,
section.bg-white .rounded-xl.border:hover{
  box-shadow:0 8px 24px -12px rgba(15,23,42,.18);
  border-color:rgba(29,78,216,.28);
  transform:translateY(-2px);
}

/* Icon chips: give the accent one moment of life on card hover. */
.rounded-xl.border:hover .rounded-lg svg,
.rounded-xl.border:hover .rounded-md svg{
  transform:scale(1.06);
  transition:transform .34s var(--jm-ease);
}

/* Dark-section cards: a hairline that warms toward the accent on hover. */
section.bg-black .rounded-xl.border,
section.bg-black .rounded-2xl.border{
  transition:border-color .34s ease, background-color .34s ease, transform .34s var(--jm-ease);
}
section.bg-black .rounded-xl.border:hover,
section.bg-black .rounded-2xl.border:hover{
  border-color:rgba(59,130,246,.42);
  background-color:rgba(255,255,255,.025);
  transform:translateY(-2px);
}

/* ==========================================================================
   5. POINTER SPOTLIGHT
   A single restrained flourish on the dark card grids: a soft radial that
   follows the cursor. Coordinates come from the motion script; with no JS the
   custom properties never resolve and the gradient simply never paints.
   ========================================================================== */
@media (hover:hover) and (pointer:fine){
  .jm-spot{ position:relative; }
  .jm-spot::after{
    content:"";
    position:absolute; inset:0;
    border-radius:inherit;
    pointer-events:none;
    opacity:0;
    transition:opacity .4s var(--jm-ease);
    background:radial-gradient(
      340px circle at var(--jm-x,50%) var(--jm-y,50%),
      rgba(59,130,246,.10), transparent 62%);
  }
  .jm-spot:hover::after{ opacity:1; }
}

/* ==========================================================================
   6. INTERACTION STATES
   ========================================================================== */
a:focus-visible,button:focus-visible,
[role="button"]:focus-visible,summary:focus-visible,
input:focus-visible,textarea:focus-visible,select:focus-visible{
  outline:2px solid var(--jm-blue-lift);
  outline-offset:2px;
  border-radius:6px;
}
section.bg-black a:focus-visible,
section.bg-black button:focus-visible{ outline-color:#93b4fd; }

/* Primary actions: a touch more presence, still quiet. */
.btn-glow-breathe{ will-change:transform,box-shadow; }
.btn-glow-breathe:hover{ transform:translateY(-1px); }
.btn-glow-breathe:active{ transform:translateY(0); transition-duration:.08s; }

/* Links inside prose get an underline that draws rather than blinks. */
section a:not([class*="rounded"]):not(.jm-no-underline){
  background-image:linear-gradient(currentColor,currentColor);
  background-size:0% 1px;
  background-repeat:no-repeat;
  background-position:0 100%;
  transition:background-size .35s var(--jm-ease);
}
section a:not([class*="rounded"]):not(.jm-no-underline):hover{ background-size:100% 1px; }

/* ==========================================================================
   7. SCROLL REVEAL
   Gated behind html.jm-motion, which the motion script adds only when JS runs
   and the visitor has not asked for reduced motion. Without that class every
   element keeps its natural, fully visible state — the content is never
   hidden behind a transition that might not fire.
   ========================================================================== */
html.jm-motion .jm-reveal{
  opacity:0;
  transform:translate3d(0,18px,0);
  transition:opacity .68s var(--jm-ease-soft),
             transform .68s var(--jm-ease);
  transition-delay:var(--jm-delay,0ms);
  will-change:opacity,transform;
}
html.jm-motion .jm-reveal.jm-in{
  opacity:1;
  transform:none;
  will-change:auto;
}

/* Headings rise a little further — the difference reads as hierarchy. */
html.jm-motion h1.jm-reveal,
html.jm-motion h2.jm-reveal{ transform:translate3d(0,26px,0); }

/* ==========================================================================
   8. HEADER
   Transparent over the hero, then a quiet solid once the page moves.
   ========================================================================== */
html.jm-motion header{
  transition:background-color .4s var(--jm-ease),
             border-color .4s ease,
             backdrop-filter .4s ease;
}
html.jm-motion body.jm-scrolled header{
  background-color:rgba(2,6,16,.86);
  backdrop-filter:saturate(150%) blur(12px);
  border-bottom-color:rgba(255,255,255,.10);
}

/* ==========================================================================
   9. RHYTHM
   Section padding sat on inner wrappers, producing 150–250px voids between
   blocks. Pull the largest ones in and let the smaller steps stand, so the
   page has variation instead of one uniform gap.
   ========================================================================== */
@media (min-width:768px){
  section > div.py-24,
  section > div.py-28{ padding-top:6.5rem; padding-bottom:6.5rem; }
  section.py-24,section.py-28{ padding-top:6.5rem; padding-bottom:6.5rem; }
  section.py-28.md\:py-32{ padding-top:7rem; padding-bottom:7rem; }
}

/* ==========================================================================
   10. REDUCED MOTION
   The site already gates its own animations correctly; this matches that
   contract for everything added here.
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  html.jm-motion .jm-reveal,
  html.jm-motion .jm-reveal.jm-in{
    opacity:1 !important;
    transform:none !important;
    transition:none !important;
  }
  .jm-spot::after{ display:none; }
  .btn-glow-breathe:hover,
  section.bg-white .rounded-xl.border:hover,
  section.bg-\[\#f5f5f7\] .rounded-xl.border:hover,
  section.bg-black .rounded-xl.border:hover{ transform:none; }
  section a:not([class*="rounded"]):hover{ background-size:100% 1px; transition:none; }
}

/* ==========================================================================
   11. SECTION SEAM BANDS
   The site separates surfaces with 80px `h-20 bg-gradient-to-b` dividers.
   A black->white blend in sRGB spends most of its length sitting in flat
   mid-grey, so at 80px tall it reads as a dirty smear rather than a
   transition. Two changes: compress the band so it reads as an edge
   treatment, and interpolate in oklab so the ramp is perceptually even.
   Height is reduced, not removed, so the surfaces still meet softly.
   ========================================================================== */
div.h-20[class*="bg-gradient-to-b"][class*="from-black"],
div.h-20[class*="bg-gradient-to-b"][class*="to-black"]{
  height:2.5rem;
}
div.h-20[class*="from-black"][class*="to-white"]{
  background-image:linear-gradient(in oklab,#000 0%,#000 6%,#fff 94%,#fff 100%);
}
div.h-20[class*="from-white"][class*="to-black"]{
  background-image:linear-gradient(in oklab,#fff 0%,#fff 6%,#000 94%,#000 100%);
}
div.h-20[class*="from-black"][class*="to-\[\#f5f5f7\]"]{
  background-image:linear-gradient(in oklab,#000 0%,#000 6%,#f5f5f7 94%,#f5f5f7 100%);
}
div.h-20[class*="from-\[\#f5f5f7\]"][class*="to-black"]{
  background-image:linear-gradient(in oklab,#f5f5f7 0%,#f5f5f7 6%,#000 94%,#000 100%);
}

/* ==========================================================================
   12. EMPTY IMAGE PLACEHOLDERS  (pre-existing content gap)
   Three <img> elements in the "correo real del asistente" cards ship with no
   src attribute at all — no failed request, simply nothing to load — so they
   painted as blank white boxes inside the dark section. Hide them until real
   screenshots exist. The rule is self-healing: the moment a src is added it
   stops matching and the image renders normally.
   ========================================================================== */
img:not([src]),img[src=""]{ display:none; }
