/* Portafolio CaruDev — sitio público
   ---------------------------------------------------------------------------
   Misma familia tipográfica y el mismo criterio de contraste que el panel, con
   la identidad clara y verde del diseño aprobado.

   Sobre los dos verdes: #7ac142 es la marca, pero sobre blanco da 2.2:1 y no
   sirve para texto. Se usa como SUPERFICIE (botones, con texto oscuro encima);
   el texto verde usa --leaf (#2f6b1c, 6.5:1).
   --------------------------------------------------------------------------- */

@font-face {
  font-family: "Plex Sans";
  src: url("../fonts/plexsans-latin.woff2") format("woff2");
  font-weight: 400 600;
  font-display: swap;
}
@font-face {
  font-family: "Plex Mono";
  src: url("../fonts/plexmono-latin.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

:root {
  --lime:      #7ac142;   /* marca — solo como superficie */
  --lime-soft: #a8e06a;
  --leaf:      #2f6b1c;   /* verde para texto y enlaces */
  --leaf-deep: #235114;
  --tint:      #e7f0e0;

  --bg:        #eff1ef;
  --surface:   #ffffff;
  --sunk:      #f5f7f5;
  --ink:       #151a17;
  --ink-2:     #545e58;
  --ink-3:     #7c857f;
  --rule:      #dde2de;
  --rule-2:    #eaeeea;
  --gold:      #9a6f00;   /* estrellas — 3.6:1 sobre blanco */
  --alert:     #9e3418;
  --alerta:    #c62828;

  --r:      14px;
  --r-sm:   9px;
  --shadow: 0 1px 2px rgba(21, 26, 23, .04), 0 6px 20px rgba(21, 26, 23, .045);
  --tap:    44px;
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 16px/1.6 "Plex Sans", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.2; font-weight: 600; letter-spacing: -0.015em; }
h1 { font-size: clamp(2rem, 1.3rem + 3vw, 3.1rem); font-weight: 600; letter-spacing: -0.03em; }
h2 { font-size: clamp(1.2rem, 1.05rem + .5vw, 1.4rem); }
h3 { font-size: 1rem; }

.accent { color: var(--leaf); }
.muted { color: var(--ink-2); }
.small { font-size: .82rem; }
.block { display: block; }
.mt { margin-top: 2.25rem; }
code, .data { font-family: "Plex Mono", ui-monospace, SFMono-Regular, monospace; }

/* El contenedor ocupa el 96% del ancho, que es lo que marca la navegación.
   El tope en rem evita que en pantallas muy anchas las tarjetas se estiren
   hasta perder proporción. */
.container { width: 96%; max-width: 108rem; margin: 0 auto; }
section.container { margin-bottom: 1.15rem; }
/* Aire entre la cabecera pegajosa y la primera tarjeta, y antes del pie: sin
   esto la tarjeta queda pegada a ambos. */
main > section.container:first-child { padding-top: 1.75rem; }
main > section.container:last-child { margin-bottom: 3rem; }
main > .hero:first-child { padding-top: 3.5rem; }
ul.plain, ol.plain { list-style: none; padding: 0; margin: 0; }

:focus-visible { outline: 2px solid var(--leaf); outline-offset: 3px; border-radius: 4px; }

.skip {
  position: absolute; left: -9999px; top: .6rem;
  background: var(--surface); color: var(--ink);
  padding: .6rem 1rem; border-radius: var(--r-sm); z-index: 100;
  box-shadow: var(--shadow); font-size: .9rem; font-weight: 500;
}
.skip:focus { left: 1rem; }

.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  padding: 1.6rem;
}

/* ── iconos ───────────────────────────────────────────────────────────── */
.icon {
  width: 1.05em; height: 1.05em; flex: none;
  fill: none; stroke: currentColor;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
  vertical-align: -0.16em;
}

/* ── botones ──────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 2.7rem; padding: 0 1.25rem;
  border: 1px solid transparent; border-radius: var(--r-sm);
  font: 500 .92rem/1 "Plex Sans", sans-serif; cursor: pointer;
  transition: background .14s ease, border-color .14s ease, transform .14s ease;
}
/* El realce va solo en transform y box-shadow: ninguno de los dos ocupa
   espacio, así que la caja del botón no cambia de tamaño. Con scale o con
   margin el botón crecería, se saldría de debajo del cursor y entraría en un
   ciclo de entra-sale que hace parpadear el efecto. */
.btn { will-change: transform; transform: translateY(0); }
.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--ink) 16%, transparent);
}
.btn:active { transform: translateY(0); box-shadow: none; }
.btn-sm { min-height: 2.3rem; padding: 0 .9rem; font-size: .86rem; }
.btn-primary { background: var(--lime-soft); color: #12300a; box-shadow: 0 2px 0 var(--leaf); }
.btn-primary:hover { background: var(--lime); }
.btn-outline { background: var(--surface); border-color: var(--rule); color: var(--ink); }
.btn-outline:hover { border-color: var(--leaf); color: var(--leaf); }

/* El "Contactar" de cada tarjeta: verde claro, texto negro, borde interior. */
.btn-contact {
  display: flex; width: 100%; min-height: 2.6rem;
  align-items: center; justify-content: center;
  background: var(--lime-soft); color: #000;
  font-weight: 600; font-size: .9rem;
  border: 1px solid rgba(21, 26, 23, .14); border-radius: var(--r-sm);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65),
              inset 0 -2px 0 rgba(21, 26, 23, .12),
              0 2px 5px rgba(21, 26, 23, .14);
  transition: background .14s ease, box-shadow .14s ease, transform .1s ease;
}
.btn-contact:hover {
  background: var(--lime);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65),
              inset 0 -2px 0 rgba(21, 26, 23, .12),
              0 5px 14px rgba(21, 26, 23, .22);
}
.btn-contact:active {
  box-shadow: inset 0 2px 5px rgba(21, 26, 23, .28);
  transform: translateY(1px);
}

.link-accent {
  display: inline-flex; align-items: center; gap: .35rem;
  color: var(--leaf); font-weight: 500; font-size: .89rem;
}
.link-accent:hover { color: var(--leaf-deep); }
.link-btn {
  background: none; border: 0; padding: 0; font: inherit;
  color: var(--leaf); font-weight: 500; font-size: .84rem; cursor: pointer;
}

/* ── cabecera ─────────────────────────────────────────────────────────── */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}
.header-inner { display: flex; align-items: center; gap: 1rem; padding: .75rem 0; }
.logo { display: flex; align-items: center; gap: .45rem; font-weight: 600; font-size: 1.1rem; letter-spacing: -0.02em; }
.logo-mark { color: var(--leaf); width: 1.15rem; height: 1.15rem; }
/* La marca escrita: CARU con el verde del icono, Dev con el color del texto.
   Se usa el verde de texto (--leaf), no el lima de superficie: el lima sobre
   fondo claro no llega al contraste mínimo. */
.brand-caru { color: var(--leaf); }

.nav { margin-left: auto; display: flex; gap: 1.5rem; font-size: .92rem; color: var(--ink-2); }
.nav a { padding: .2rem 0; border-bottom: 2px solid transparent; }
.nav a:hover { color: var(--ink); }
.nav a.active { color: var(--leaf); border-bottom-color: var(--leaf); }
.nav-toggle {
  display: none; background: none; border: 0; cursor: pointer;
  color: var(--ink); padding: .4rem; margin-left: auto;
}
.nav-toggle .icon { width: 1.4rem; height: 1.4rem; }

/* ── portada ──────────────────────────────────────────────────────────── */
.hero { display: grid; grid-template-columns: 17rem 1fr; gap: 3rem; align-items: center; padding: 3.5rem 0; }
.hero-photo { text-align: center; }
.hero-photo img, .photo-placeholder {
  width: 15rem; height: 15rem; border-radius: 50%; object-fit: cover;
  margin: 0 auto; background: var(--tint);
  display: grid; place-items: center;
  font-size: 3rem; font-weight: 600; color: var(--leaf);
}
.socials { display: flex; gap: .55rem; justify-content: center; margin-top: 1.2rem; }
.socials a {
  width: 2.5rem; height: 2.5rem; display: grid; place-items: center;
  border: 1px solid var(--rule); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-2);
  transition: border-color .14s ease, color .14s ease;
}
.socials a:hover { border-color: var(--leaf); color: var(--leaf); }
.socials .icon { width: 1.15rem; height: 1.15rem; }

.kicker { color: var(--leaf); font-weight: 500; font-size: .89rem; margin: 0 0 .6rem; }
.headline { font-size: 1.1rem; color: var(--ink-2); margin: .3rem 0 1.1rem; }
.intro { max-width: 58ch; color: var(--ink-2); }
.hero-actions { display: flex; gap: .8rem; margin-top: 1.8rem; flex-wrap: wrap; }

/* ── tecnologías y resumen ────────────────────────────────────────────── */
.two-col { display: grid; grid-template-columns: 1.12fr 1fr; gap: 1.15rem; align-items: start; }
.tech-grid {
  list-style: none; padding: 0; margin: 1.2rem 0 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(4.6rem, 1fr)); gap: 1rem .8rem;
}
.tech-grid li {
  display: grid; justify-items: center; gap: .45rem;
  font-size: .74rem; color: var(--ink-2); text-align: center;
  padding: .6rem .3rem; border-radius: var(--r-sm);
  border: 1px solid transparent;
  transition: border-color .2s ease, background .2s ease, color .2s ease;
}
.tech-grid li:hover { border-color: var(--rule); background: var(--surface); color: var(--ink); }
.tech-grid img, .tech-mark {
  width: 2.5rem; height: 2.5rem; object-fit: contain;
  /* El rebote va en el icono, no en el <li>: así la celda no cambia de
     tamaño y la rejilla no se recoloca al pasar el ratón. */
  transition: transform .25s cubic-bezier(.34, 1.56, .64, 1), filter .2s ease;
}
.tech-grid li:hover img, .tech-grid li:hover .tech-mark {
  transform: translateY(-4px) scale(1.08);
  filter: drop-shadow(0 6px 10px color-mix(in srgb, var(--ink) 30%, transparent));
}

/* Rebote de entrada, una vez, escalonado por posición. Se dispara al verlas,
   desde el JS, para que no ocurra fuera de pantalla. */
.tech-grid.is-live img, .tech-grid.is-live .tech-mark { animation: pingpong .7s ease both; }
.tech-grid.is-live li:nth-child(1) img,  .tech-grid.is-live li:nth-child(1) .tech-mark  { animation-delay: .00s; }
.tech-grid.is-live li:nth-child(2) img,  .tech-grid.is-live li:nth-child(2) .tech-mark  { animation-delay: .06s; }
.tech-grid.is-live li:nth-child(3) img,  .tech-grid.is-live li:nth-child(3) .tech-mark  { animation-delay: .12s; }
.tech-grid.is-live li:nth-child(4) img,  .tech-grid.is-live li:nth-child(4) .tech-mark  { animation-delay: .18s; }
.tech-grid.is-live li:nth-child(5) img,  .tech-grid.is-live li:nth-child(5) .tech-mark  { animation-delay: .24s; }
.tech-grid.is-live li:nth-child(6) img,  .tech-grid.is-live li:nth-child(6) .tech-mark  { animation-delay: .30s; }
.tech-grid.is-live li:nth-child(7) img,  .tech-grid.is-live li:nth-child(7) .tech-mark  { animation-delay: .36s; }
.tech-grid.is-live li:nth-child(8) img,  .tech-grid.is-live li:nth-child(8) .tech-mark  { animation-delay: .42s; }

@keyframes pingpong {
  0%   { transform: translateY(-14px) scale(.85); opacity: 0; }
  55%  { transform: translateY(3px)   scale(1.04); opacity: 1; }
  78%  { transform: translateY(-2px)  scale(.99); }
  100% { transform: translateY(0)     scale(1); }
}
.tech-mark {
  display: grid; place-items: center;
  background: var(--sunk); border: 1px solid var(--rule); border-radius: var(--r-sm);
  font-family: "Plex Mono", monospace; font-size: .82rem; color: var(--ink-2);
}

.stats { display: grid; grid-template-columns: 1fr 1fr; gap: .8rem; margin-top: 1.2rem; }
.stat {
  position: relative; overflow: hidden;
  border: 1px solid var(--rule); border-radius: var(--r-sm);
  padding: .95rem 1.1rem;
  background: var(--surface);
  /* Cifra a la izquierda y textos a la derecha, centrados con ella. */
  display: flex; align-items: center; gap: .85rem;
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.stat::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--lime); transform: scaleY(0); transform-origin: bottom;
  transition: transform .22s ease;
}
.stat:hover { border-color: var(--leaf); transform: translateY(-2px); box-shadow: var(--shadow); }
.stat:hover::before { transform: scaleY(1); }

.stat strong {
  flex: none;
  font-family: "Plex Mono", monospace;
  font-size: clamp(1.8rem, 1.4rem + 1.2vw, 2.4rem);
  line-height: 1; letter-spacing: -0.03em;
  color: var(--leaf);
  /* La cifra cambia de ancho al contar: con esto no baila el resto. */
  font-variant-numeric: tabular-nums;
}
/* La fecha es larga y no compite en tamaño con un «+100». */
.stat--date strong { font-size: clamp(1.05rem, .9rem + .5vw, 1.3rem); color: var(--ink); }

/* Filete vertical entre la cifra y su explicación. */
.stat__info {
  display: grid; gap: .1rem; min-width: 0;
  padding-left: .85rem; border-left: 1px solid var(--rule-2);
}
.stat__info b { font-weight: 500; font-size: .82rem; color: var(--ink); }
.stat__info i { font-style: normal; font-size: .76rem; color: var(--ink-2); }


.timeline {
  list-style: none; padding: 1.4rem 0 0; margin: 1.4rem 0 0;
  border-top: 1px solid var(--rule-2);
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 1rem;
}
.timeline li { display: grid; gap: .25rem; font-size: .82rem; position: relative; padding-top: 1.1rem; color: var(--ink-2); }
.timeline li::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: .55rem; height: .55rem; border-radius: 50%; background: var(--lime);
  outline: 3px solid var(--tint);
  animation: latido 2.4s ease-in-out infinite;
}
/* Cada punto entra desfasado: latir todos a la vez parece un error. */
.timeline li:nth-child(2)::before { animation-delay: .3s; }
.timeline li:nth-child(3)::before { animation-delay: .6s; }
.timeline li:nth-child(4)::before { animation-delay: .9s; }
/* El último es «Actualidad»: late más fuerte porque es donde estás ahora. */
.timeline li:last-child::before { background: var(--leaf); animation-duration: 1.8s; }

@keyframes latido {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--lime) 55%, transparent); }
  70%      { box-shadow: 0 0 0 .5rem transparent; }
}

.timeline strong { color: var(--ink); font-size: .92rem; }
.t-label { color: var(--leaf); font-family: "Plex Mono", monospace; font-size: .78rem; }

/* ── sobre mí ─────────────────────────────────────────────────────────── */
.about { display: flex; gap: 1.4rem; align-items: flex-start; }
.about-icon {
  flex: 0 0 3.2rem; height: 3.2rem; display: grid; place-items: center;
  border-radius: 50%; background: var(--tint); color: var(--leaf);
}
.about-icon .icon { width: 1.5rem; height: 1.5rem; }
.about p { color: var(--ink-2); max-width: 78ch; margin: 0; }

/* ── carrusel ─────────────────────────────────────────────────────────── */
.section-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; }
.carousel { position: relative; margin-top: 1.4rem; }
.car-track {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(15rem, 1fr);
  gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-behavior: smooth; padding: .3rem; scrollbar-width: none;
}

/* En pantallas estrechas caben dos tarjetas a medias y ninguna se lee. Pasa a
   una entera con un asomo de la siguiente: el corte a la derecha es lo que
   dice que hay más, sin necesidad de leer nada.

   Si solo hay una, ese asomo sobraría y deja un hueco muerto, así que ocupa
   todo el ancho. */
@media (max-width: 620px) {
  .car-track { grid-auto-columns: calc(100% - 3.25rem); }
  .car-track:has(> :only-child) { grid-auto-columns: 100%; }

  /* Con la tarjeta ocupando casi todo, las flechas flotantes se comen el
     texto. Bajan debajo del carrusel, donde no tapan nada y siguen a mano
     para quien no arrastra con el dedo. */
  .carousel { display: flex; flex-direction: column; }
  .car-track { order: 1; }
  .car-btn {
    position: static; transform: none; order: 2;
    width: 2.6rem; height: 2.6rem; min-width: 2.6rem; min-height: 2.6rem;
  }
  .car-btn.prev { margin: .8rem .4rem 0 auto; }
  .car-btn.next { margin: .8rem 0 0 0; }
}
.car-track::-webkit-scrollbar { display: none; }
.car-track > * { scroll-snap-align: start; }
.car-btn {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
  width: 2.4rem; height: 2.4rem; display: grid; place-items: center;
  border-radius: 50%; border: 1px solid var(--rule);
  background: var(--surface); color: var(--ink-2);
  box-shadow: var(--shadow); cursor: pointer;
  transition: color .14s ease, border-color .14s ease, opacity .14s ease;
}
.car-btn:hover:not(:disabled) { color: var(--leaf); border-color: var(--leaf); }
.car-btn:disabled { opacity: .3; cursor: default; }
.car-btn.prev { left: -1.1rem; }
.car-btn.next { right: -1.1rem; }

/* ── tarjeta de proyecto ──────────────────────────────────────────────── */
.grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr)); gap: 1rem; margin-top: 1.2rem; }
.project-card { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.project-card .thumb { display: block; aspect-ratio: 16 / 10; background: #0f1417; overflow: hidden; }
.project-card .thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform .3s ease; }
.project-card:hover .thumb img { transform: scale(1.03); }
.thumb-placeholder {
  display: grid; place-items: center; height: 100%;
  color: #4a5a63; font-family: "Plex Mono", monospace; font-size: 2.4rem;
}
.card-body { padding: 1rem; display: flex; flex-direction: column; gap: .55rem; flex: 1; }
.card-body h3 { margin: 0; font-size: .98rem; }
.card-body h3 a:hover { color: var(--leaf); }
.badge {
  align-self: flex-start; background: var(--tint); color: var(--leaf);
  font-size: .72rem; font-weight: 500; padding: .18rem .55rem; border-radius: 999px;
}
.tags { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: .35rem; }
.tags li {
  font-size: .72rem; background: var(--sunk); border: 1px solid var(--rule);
  border-radius: 6px; padding: .12rem .45rem; color: var(--ink-2);
  font-family: "Plex Mono", monospace;
}
.project-card .btn-contact { margin-top: auto; }

/* ── reseñas ──────────────────────────────────────────────────────────── */
.testimonial-card { display: flex; flex-direction: column; gap: .7rem; padding: 1.25rem; }
.t-head { display: flex; align-items: flex-start; gap: .7rem; }
.avatar { width: 2.6rem; height: 2.6rem; border-radius: 50%; object-fit: cover; flex: none; }
.avatar-initial {
  display: grid; place-items: center;
  background: var(--tint); color: var(--leaf); font-weight: 600;
}
/* Nombre, empresa y estrellas apilados: al lado, las estrellas le quitaban
   el ancho al nombre y lo partían en tres líneas. */
.t-who { display: grid; gap: .12rem; min-width: 0; }
.t-who strong { font-size: .92rem; line-height: 1.25; }
.t-company { font-size: .76rem; color: var(--ink-2); }
.stars { color: var(--gold); display: inline-flex; gap: .05rem; margin-top: .1rem; }
.stars .icon { width: .85rem; height: .85rem; }
.t-text { font-size: .87rem; color: var(--ink-2); margin: 0; line-height: 1.6; }
.t-text[data-clamp] { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.t-text.expanded { display: block; }

/* ── contacto ─────────────────────────────────────────────────────────── */
.contact { display: grid; grid-template-columns: 15rem 1fr; gap: 2.5rem; }
.contact-aside { text-align: center; }
.plane {
  display: grid; place-items: center; width: 7rem; height: 7rem;
  margin: 0 auto 1.2rem; border-radius: 50%;
  background: var(--tint); color: var(--leaf);
}
.plane .icon { width: 2.6rem; height: 2.6rem; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem 1.3rem; }
.field { margin: 0; display: grid; gap: .4rem; }
.field-wide { grid-column: 1 / -1; }
.req { color: var(--alert); }
label { font-size: .84rem; font-weight: 500; }

input[type=text], input[type=email], select, textarea {
  width: 100%; min-height: 2.7rem; padding: .6rem .8rem;
  font: inherit; font-size: .92rem; color: var(--ink);
  background: var(--sunk); border: 1px solid var(--rule); border-radius: var(--r-sm);
  transition: border-color .14s ease, box-shadow .14s ease;
}
textarea { min-height: 150px; resize: vertical; line-height: 1.6; }
input:hover, select:hover, textarea:hover { border-color: var(--ink-3); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--leaf);
  box-shadow: 0 0 0 3px var(--tint); background: var(--surface);
}
::placeholder { color: var(--ink-3); }

.counter { justify-self: end; font-family: "Plex Mono", monospace; font-size: .75rem; color: var(--ink-2); }
.checks { display: flex; gap: 2rem; flex-wrap: wrap; margin: 1.2rem 0; }
.check { display: flex; align-items: center; gap: .5rem; font-weight: 400; font-size: .85rem; cursor: pointer; }
.check input { width: 1.05rem; height: 1.05rem; min-height: 0; accent-color: var(--leaf); }
.check a { color: var(--leaf); text-decoration: underline; }

.alert { padding: .75rem 1rem; border-radius: var(--r-sm); font-size: .88rem; margin-bottom: 1.1rem; }
.alert.success { background: var(--tint); color: var(--leaf-deep); }
.alert.error { background: #f8e9e4; color: var(--alert); }
ul.errorlist { list-style: none; padding: 0; margin: .25rem 0 0; color: var(--alert); font-size: .79rem; }

/* ── detalle de proyecto ──────────────────────────────────────────────── */
.detail-hero { border-radius: var(--r); margin: 1.2rem 0; border: 1px solid var(--rule); }
.prose { color: var(--ink-2); font-size: .95rem; max-width: 74ch; }
.detail-hero { max-width: 60rem; }
.detail-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: .75rem; margin: 0 0 1.6rem;
}
.detail-grid > div { border: 1px solid var(--rule); border-radius: var(--r-sm); padding: .85rem; }
.detail-grid dt { font-size: .74rem; color: var(--ink-2); }
.detail-grid dd { margin: .25rem 0 0; font-weight: 500; font-size: .9rem; }
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 1rem; }
.gallery figure { margin: 0; }
.gallery img { border-radius: var(--r-sm); border: 1px solid var(--rule); }
.gallery figcaption { font-size: .78rem; color: var(--ink-2); margin-top: .4rem; }
.detail-actions { display: flex; gap: .75rem; flex-wrap: wrap; margin-top: 1.6rem; }
.detail-actions .btn-contact { width: auto; padding-inline: 1.5rem; }

/* ── páginas editables ────────────────────────────────────────────────── */
.legal { max-width: none; }
.legal > * { max-width: 74ch; }
.legal h1 { max-width: 22ch; }
.legal h1 { font-size: clamp(1.7rem, 1.3rem + 1.6vw, 2.3rem); margin-top: 1rem; }
.page-content, .legal p, .legal li { color: var(--ink-2); font-size: .95rem; }
.page-content { max-width: 72ch; }
.page-content h2 { font-size: 1.1rem; margin-top: 2.2rem; color: var(--ink); }
.page-content h3 { font-size: .98rem; margin-top: 1.6rem; color: var(--ink); }
.page-content ul, .page-content ol { padding-left: 1.2rem; }
.page-content li { margin-bottom: .4rem; }
.page-content a { color: var(--leaf); text-decoration: underline; }
.page-content img { border-radius: var(--r-sm); margin: 1.2rem 0; }
.page-content table, .legal-table {
  width: 100%; border-collapse: collapse; margin: 1.2rem 0; font-size: .87rem;
}
.page-content th, .page-content td, .legal-table th, .legal-table td {
  border: 1px solid var(--rule); padding: .55rem .7rem; text-align: left;
}
.page-content th, .legal-table th { background: var(--tint); color: var(--leaf-deep); font-size: .8rem; font-weight: 500; }
.page-content code { background: var(--sunk); border: 1px solid var(--rule); border-radius: 5px; padding: .1rem .35rem; font-size: .85em; }
.page-content pre { background: #0f1417; color: #dbe4ea; border-radius: var(--r-sm); padding: 1.1rem; overflow-x: auto; }
.page-content pre code { background: none; border: 0; color: inherit; }
.page-content blockquote { border-left: 3px solid var(--lime); margin: 1.2rem 0; padding-left: 1.1rem; color: var(--ink-2); }

/* ── pie ──────────────────────────────────────────────────────────────── */
.site-footer { background: var(--surface); border-top: 1px solid var(--rule); margin-top: 0; padding: 3rem 0 2.5rem; }
.footer-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1.2fr; gap: 2.5rem; }
.footer-grid h4 { font-size: .87rem; margin-bottom: .7rem; }
.footer-grid li { font-size: .87rem; margin-bottom: .35rem; color: var(--ink-2); }
.footer-grid a:hover { color: var(--leaf); }
.footer-grid .socials { justify-content: flex-start; margin-top: 0; }
.footer-quote {
  /* align-self evita que la rejilla del pie la estire hasta la altura de la
     columna más alta, que es lo que dejaba la caja medio vacía. */
  align-self: start;
  display: flex; align-items: flex-start; gap: .9rem;
  margin: 0; padding: 1.15rem 1.3rem;
  background: var(--tint); border-radius: var(--r);
}
.footer-quote__mark {
  width: 1.9rem; height: 1.9rem; flex: none;
  color: var(--leaf); opacity: .5; margin-top: -.15rem;
}
.footer-quote p { margin: 0; font-size: .89rem; line-height: 1.55; color: var(--leaf-deep); }
.mt-legal { margin-top: 1.4rem; }


/* ── tema oscuro ──────────────────────────────────────────────────────────
   Los tokens se redefinen dos veces a propósito:
     1. @media prefers-color-scheme, para quien no ha elegido nada;
     2. .dark, para quien pulsó el botón.
   El `:not(.light)` del bloque de media evita que el sistema pise una
   elección explícita de tema claro.

   El verde cambia de papel: sobre fondo oscuro --leaf tiene que aclararse
   para leerse, mientras --lime sigue siendo la superficie de los botones,
   que llevan texto oscuro y no dependen del fondo de la página.
   ------------------------------------------------------------------------ */
@media (prefers-color-scheme: dark) {
  :root:not(.light) {
    --leaf:      #8cc45f;
    --leaf-deep: #a6d67d;
    --tint:      #1e2a17;

    --bg:        #111513;
    --surface:   #191e1b;
    --sunk:      #212724;
    --ink:       #e5eae6;
    --ink-2:     #9fa9a3;
    --ink-3:     #7b857f;
    --rule:      #2b322d;
    --rule-2:    #232a26;
    --gold:      #d9a832;
    --alert:     #e08d74;
    --alerta:    #d94b4b;

    --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 20px rgba(0, 0, 0, .28);
  }
}

:root.dark {
  --leaf:      #8cc45f;
  --leaf-deep: #a6d67d;
  --tint:      #1e2a17;

  --bg:        #111513;
  --surface:   #191e1b;
  --sunk:      #212724;
  --ink:       #e5eae6;
  --ink-2:     #9fa9a3;
  --ink-3:     #7b857f;
  --rule:      #2b322d;
  --rule-2:    #232a26;
  --gold:      #d9a832;
  --alert:     #e08d74;
  --alerta:    #d94b4b;

  --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 20px rgba(0, 0, 0, .28);
}

/* Ajustes que no son solo de color. */
@media (prefers-color-scheme: dark) {
  :root:not(.light) .alert.success { background: var(--tint); color: var(--leaf); }
  :root:not(.light) .alert.error { background: #34211b; }
  :root:not(.light) .footer-quote { color: var(--leaf); }
  :root:not(.light) .btn-contact { border-color: rgba(0, 0, 0, .35); }
  :root:not(.light) .page-content th, :root:not(.light) .legal-table th { color: var(--leaf); }
  :root:not(.light) .skip { border: 1px solid var(--rule); }
}
:root.dark .alert.success { background: var(--tint); color: var(--leaf); }
:root.dark .alert.error { background: #34211b; }
:root.dark .footer-quote { color: var(--leaf); }
:root.dark .btn-contact { border-color: rgba(0, 0, 0, .35); }
:root.dark .page-content th, :root.dark .legal-table th { color: var(--leaf); }
:root.dark .skip { border: 1px solid var(--rule); }

/* ── botón de tema ────────────────────────────────────────────────────── */
.theme-toggle {
  display: grid; place-items: center;
  width: 2.3rem; height: 2.3rem; flex: none;
  background: none; border: 1px solid transparent; border-radius: var(--r-sm);
  color: var(--ink-2); cursor: pointer;
  transition: border-color .14s ease, color .14s ease;
}
.theme-toggle:hover { border-color: var(--rule); color: var(--ink); }
.theme-toggle .icon { width: 1.15rem; height: 1.15rem; }
.theme-moon { display: none; }
:root.dark .theme-sun { display: none; }
:root.dark .theme-moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not(.light) .theme-sun { display: none; }
  :root:not(.light) .theme-moon { display: block; }
}

/* ── responsive ───────────────────────────────────────────────────────── */
@media (max-width: 960px) {
  .hero, .two-col, .contact, .footer-grid { grid-template-columns: 1fr; }
  .hero { gap: 2rem; padding-top: 2.5rem; text-align: center; }
  .hero-actions, .intro { margin-inline: auto; }
  .hero-actions { justify-content: center; }
  .timeline { grid-auto-flow: row; }
  .car-btn.prev { left: -.4rem; }
  .car-btn.next { right: -.4rem; }
}
@media (max-width: 760px) {
  .container { width: 92%; }
  .form-grid { grid-template-columns: 1fr; }
  .nav {
    display: none; position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; gap: 0; background: var(--surface);
    padding: .5rem 4% 1rem; border-bottom: 1px solid var(--rule);
  }
  .nav.open { display: flex; }
  .nav a { padding: .7rem 0; border-bottom: 1px solid var(--rule-2); }
  .nav-toggle { display: block; order: 4; }
  .theme-toggle { order: 3; margin-left: auto; }
  .header-inner .btn-primary { display: none; }
  .card { padding: 1.2rem; }
  .socials a, .car-btn, .nav-toggle, .theme-toggle { min-width: var(--tap); min-height: var(--tap); }
  .stats { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
}

.empty-note { padding: 2rem 0; font-size: .9rem; }

/* ── carrusel de miniaturas de la tarjeta ─────────────────────────────── */
.shots { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: #0f1417; container-type: inline-size; }
.shots__track { display: flex; height: 100%; transition: transform .28s ease; }
.shots__item { flex: 0 0 100%; height: 100%; display: block; }
.shots__item img { width: 100%; height: 100%; object-fit: cover; }
.shots:hover .shots__item img { object-fit: contain; }
.shots__item--none {
  display: grid; place-items: center; padding: .75rem;
  color: #4a5a63; font-family: "Plex Mono", monospace;
  font-size: clamp(.75rem, 4cqi, 1.4rem); line-height: 1.25;
  text-align: center; overflow-wrap: break-word;
}
.shots__btn {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 2rem; height: 2rem; display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(255, 255, 255, .92); color: #151a17;
  opacity: 0; transition: opacity .16s ease;
}
.shots__btn--prev { left: .5rem; }
.shots__btn--next { right: .5rem; }
.shots:hover .shots__btn, .shots__btn:focus-visible { opacity: 1; }
.shots__dots {
  position: absolute; left: 0; right: 0; bottom: .5rem;
  display: flex; justify-content: center; gap: .3rem;
}
.shots__dots span {
  width: .35rem; height: .35rem; border-radius: 50%;
  background: rgba(255, 255, 255, .45); transition: background .16s ease;
}
.shots__dots span.is-on { background: #fff; }
/* En táctil no hay hover: las flechas se quedan visibles. */
@media (hover: none) {
  .shots__btn { opacity: 1; }
}

/* ── página de proyecto ───────────────────────────────────────────────── */
.case { padding-top: 1.75rem; padding-bottom: 3rem; }

.case__head {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r) var(--r) 0 0; border-bottom: 0;
  padding: 1.6rem 1.8rem 1.4rem;
}
.case__head .link-accent { margin-bottom: 1rem; }
.case__head .badge { display: inline-block; margin-bottom: .6rem; }
.case__head h1 { font-size: clamp(1.6rem, 1.1rem + 2vw, 2.4rem); max-width: 22ch; }
.case__lead { color: var(--ink-2); font-size: 1.02rem; max-width: 62ch; margin: 0 0 1rem; }
.case__head .tags { margin-top: .2rem; }

/* Imágenes y ficha comparten la primera pantalla: así la imagen no ocupa
   todo el ancho y los datos se ven sin desplazarse. */
.case__top {
  display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: 1.6rem;
  align-items: start;
  background: var(--surface); border: 1px solid var(--rule); border-bottom: 0;
  padding: 0 1.8rem 1.6rem;
}
/* Con barra destacada son tres columnas, las dos laterales del mismo ancho
   para que la imagen quede centrada de verdad.

   La barra va al final del HTML y aquí se coloca a la izquierda con
   grid-column, no con `order`: así el orden de lectura y el de tabulación
   siguen siendo imágenes -> detalles -> promoción, que es lo que espera quien
   abrió un proyecto concreto. En pantallas estrechas no hace falta nada: al
   apilarse ya caen en ese mismo orden. */
.case__top--wide { grid-template-columns: 20rem minmax(0, 1fr) 20rem; }
.case__top--wide > .showcase { grid-column: 1; grid-row: 1; }
.case__top--wide > .case__shots { grid-column: 2; grid-row: 1; }
.case__top--wide > .case__aside { grid-column: 3; grid-row: 1; }

/* Se perdió en una edición anterior: sin esto el texto queda sin tarjeta y
   pegado al borde. */
.case__body {
  display: grid; gap: 2rem;
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: 0 0 var(--r) var(--r);
  padding: 1.8rem;
}
.case__body .page-content, .case__body .prose { max-width: 78ch; }
.case__shots { min-width: 0; }
.shots-empty {
  display: grid; place-items: center; aspect-ratio: 16 / 10;
  border: 1px dashed var(--rule); border-radius: var(--r-sm);
  background: var(--sunk); color: var(--ink-3);
  font-family: "Plex Mono", monospace; font-size: 3rem;
}
.case__section h2 {
  font-size: 1.05rem; padding-bottom: .5rem; margin-bottom: .9rem;
  border-bottom: 1px solid var(--rule-2);
}

/* Visor de imágenes */
.viewer { margin: 0; display: grid; gap: .6rem; }
.viewer__stage {
  position: relative; overflow: hidden;
  border: 1px solid var(--rule); border-radius: var(--r-sm);
  background: #0f1417; aspect-ratio: 16 / 10;
}
.viewer__track { display: flex; height: 100%; transition: transform .3s ease; }
.viewer__frame {
  flex: 0 0 100%; width: 100%; height: 100%; padding: 0; margin: 0;
  border: 0; background: none; cursor: zoom-in; display: block;
}
.viewer__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.viewer__hint {
  position: absolute; left: .7rem; bottom: .7rem;
  display: inline-flex; align-items: center; gap: .35rem;
  background: rgba(15, 20, 23, .8); color: #fff;
  font-size: .74rem; padding: .2rem .55rem; border-radius: 999px;
  opacity: 0; transition: opacity .16s ease; pointer-events: none;
}
.viewer__stage:hover .viewer__hint { opacity: 1; }
.viewer__btn {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 2.4rem; height: 2.4rem; display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(255, 255, 255, .92); color: #151a17;
  opacity: 0; transition: opacity .16s ease;
}
.viewer__btn--prev { left: .7rem; }
.viewer__btn--next { right: .7rem; }
.viewer__stage:hover .viewer__btn, .viewer__btn:focus-visible { opacity: 1; }
.viewer__counter {
  position: absolute; right: .7rem; bottom: .7rem;
  background: rgba(15, 20, 23, .8); color: #fff;
  font-family: "Plex Mono", monospace; font-size: .72rem;
  padding: .15rem .5rem; border-radius: 999px;
}
.viewer__strip { display: flex; gap: .5rem; overflow-x: auto; padding-bottom: .2rem; scrollbar-width: thin; }
.viewer__thumb {
  flex: 0 0 5rem; height: 3.2rem; padding: 0; cursor: pointer;
  border: 1px solid var(--rule); border-radius: 7px; overflow: hidden;
  background: none; opacity: .55; transition: opacity .16s ease, border-color .16s ease;
}
.viewer__thumb img { width: 100%; height: 100%; object-fit: cover; }
.viewer__thumb:hover { opacity: .85; }
.viewer__thumb.is-on { opacity: 1; border-color: var(--leaf); }
@media (hover: none) { .viewer__btn { opacity: 1; } }

/* Metodología como proceso numerado */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; counter-reset: step; }
.steps li { display: flex; gap: .8rem; align-items: baseline; color: var(--ink-2); font-size: .95rem; }
.steps__n {
  flex: none; width: 1.6rem; height: 1.6rem; display: grid; place-items: center;
  border-radius: 50%; background: var(--tint); color: var(--leaf);
  font-family: "Plex Mono", monospace; font-size: .78rem; font-weight: 500;
  align-self: flex-start;
}

/* Ficha de «cómo se hizo» */
.case__aside { min-width: 0; }
.factbox {
  border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--sunk); padding: 1.2rem;
}
.factbox__techs dd { margin-top: .35rem; }
.factbox__techs .tags { gap: .3rem; }
.factbox h2 { font-size: .95rem; margin-bottom: .9rem; }
.factbox__list { display: grid; gap: .8rem; margin: 0 0 1.2rem; }
.factbox__list dt { font-size: .74rem; color: var(--ink-2); }
.factbox__list dd { margin: .1rem 0 0; font-size: .92rem; font-weight: 500; }
.factbox__links { display: grid; gap: .5rem; margin-bottom: .6rem; }
.factbox__links .btn { width: 100%; }

@media (max-width: 900px) {
  .case__top { grid-template-columns: 1fr; padding: 0 1.2rem 1.2rem; }
  .case__top--wide { grid-template-columns: 1fr; }
  .case__top--wide > .showcase,
  .case__top--wide > .case__shots,
  .case__top--wide > .case__aside { grid-column: 1; grid-row: auto; }
  .case__body { padding: 1.2rem; }
  .case__head { padding: 1.2rem; }
}

/* ── imagen a pantalla completa ───────────────────────────────────────── */
.lightbox {
  border: 0; padding: 0; background: none;
  width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh;
  overflow: hidden;
}
.lightbox::backdrop { background: rgba(8, 11, 9, .92); }
.lightbox__figure {
  margin: 0; height: 100%;
  display: grid; place-content: center; gap: .8rem; padding: 3.5rem 4.5rem;
}
.lightbox__figure img {
  max-width: min(100%, 100rem); max-height: calc(100dvh - 7rem);
  object-fit: contain; border-radius: var(--r-sm);
}
.lightbox__figure figcaption {
  text-align: center; color: #cfd6d1; font-size: .82rem;
  font-family: "Plex Mono", monospace;
}
.lightbox__close, .lightbox__btn {
  position: fixed; z-index: 2;
  display: grid; place-items: center;
  border: 1px solid rgba(255, 255, 255, .18); border-radius: 50%;
  background: rgba(255, 255, 255, .1); color: #fff;
  cursor: pointer; backdrop-filter: blur(4px);
  transition: background .14s ease;
}
.lightbox__close:hover, .lightbox__btn:hover { background: rgba(255, 255, 255, .22); }
.lightbox__close { top: 1rem; right: 1rem; width: 2.6rem; height: 2.6rem; }
.lightbox__btn { top: 50%; transform: translateY(-50%); width: 3rem; height: 3rem; }
.lightbox__btn--prev { left: 1rem; }
.lightbox__btn--next { right: 1rem; }
.lightbox .icon { width: 1.3rem; height: 1.3rem; }

/* ── proyectos parecidos ──────────────────────────────────────────────── */
.case__related { margin-top: 2rem; }
.case__related .section-head { margin-bottom: .2rem; }
.case__related h2 { font-size: 1.15rem; }

@media (max-width: 900px) {
  .lightbox__figure { padding: 3.5rem 1rem; }
  .lightbox__btn { width: var(--tap); height: var(--tap); }
  .lightbox__btn--prev { left: .4rem; }
  .lightbox__btn--next { right: .4rem; }
}

/* ── filtros del listado ──────────────────────────────────────────────── */
.filters { display: flex; gap: .6rem; margin: 1.2rem 0 1rem; flex-wrap: wrap; }
.filters__search {
  display: flex; align-items: center; gap: .5rem;
  flex: 1; min-width: 15rem; margin: 0; font-weight: 400;
  background: var(--sunk); border: 1px solid var(--rule);
  border-radius: var(--r-sm); padding: 0 .8rem;
}
.filters__search:focus-within { border-color: var(--leaf); box-shadow: 0 0 0 3px var(--tint); }
.filters__search .icon { color: var(--ink-3); }
.filters__search input {
  flex: 1; min-width: 0; min-height: 2.6rem;
  border: 0; background: none; padding: 0; box-shadow: none;
  font: inherit; font-size: .92rem; color: var(--ink); outline: none;
}
.filters__search input:focus { box-shadow: none; border: 0; background: none; }

.chips { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem; padding: 0; margin: 0 0 1.4rem; }
.chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .3rem .7rem; border-radius: 999px;
  border: 1px solid var(--rule); background: var(--surface);
  font-size: .82rem; color: var(--ink-2);
  transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.chip:hover { border-color: var(--leaf); color: var(--leaf); }
.chip.is-on { background: var(--tint); border-color: var(--leaf); color: var(--leaf-deep); font-weight: 500; }
.chip__n { font-family: "Plex Mono", monospace; font-size: .72rem; opacity: .7; }

/* Etiquetas de tecnología: ahora llevan al filtro. */
.tags li a { display: block; }
.tags li:has(a):hover { border-color: var(--leaf); color: var(--leaf); }

.pages { display: flex; gap: .9rem; align-items: center; justify-content: center; margin-top: 1.6rem; }

/* ── barra de promoción ───────────────────────────────────────────────── */
.showcase {
  border: 1px solid var(--rule); border-radius: var(--r);
  background: var(--sunk); padding: .9rem; min-width: 0;
}
.showcase__head {
  display: flex; align-items: center; gap: .5rem; margin-bottom: .8rem;
}
.showcase__head h2 { font-size: .88rem; margin: 0; }
.showcase__count {
  margin-left: auto; font-family: "Plex Mono", monospace; font-size: .72rem;
  color: var(--leaf); background: var(--tint);
  padding: .1rem .45rem; border-radius: 999px;
}
.showcase__list { list-style: none; margin: 0 0 .9rem; padding: 0; display: grid; gap: .7rem; }

.promo {
  display: block; overflow: hidden;
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  transition: border-color .14s ease, transform .14s ease;
}
.promo:hover { border-color: var(--leaf); transform: translateY(-1px); }

/* Ancha y baja: identifica sin comerse la tarjeta. */
.promo__shot {
  position: relative; display: block; height: 4.2rem;
  background: #0f1417; overflow: hidden;
}
.promo__shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.promo__letter {
  display: grid; place-items: center; height: 100%;
  color: #46555e; font-family: "Plex Mono", monospace; font-size: 1.5rem;
}
.promo__tag { position: absolute; top: .35rem; right: .35rem; font-size: .66rem; padding: .1rem .45rem; }

.promo__body { display: grid; gap: .2rem; padding: .6rem .7rem .7rem; }
.promo__title {
  font-size: .86rem; font-weight: 500; line-height: 1.3; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.promo__desc {
  font-size: .76rem; line-height: 1.4; color: var(--ink-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.promo .price { margin-top: .15rem; }
.showcase__all { font-size: .82rem; }

/* ── precios ──────────────────────────────────────────────────────────── */
.price { display: flex; align-items: baseline; gap: .45rem; margin: 0; font-family: "Plex Mono", monospace; }
.price__now { font-weight: 500; color: var(--leaf); font-size: 1rem; }
.price__old { color: var(--ink-3); font-size: .82rem; }
.price--sm .price__now { font-size: .82rem; }
.price--lg { margin-bottom: 1rem; }
.price--lg .price__now { font-size: 1.6rem; }
.price--lg .price__old { font-size: .95rem; }

/* ── etiqueta del proyecto ────────────────────────────────────────────── */
.tagchip {
  display: inline-block; padding: .18rem .6rem; border-radius: 999px;
  font-size: .72rem; font-weight: 500; border: 1px solid transparent;
}
.tagchip--venta     { background: #e2f0dc; color: #2f6b1c; border-color: #bcdcaa; }
.tagchip--licencia  { background: #dfe9f6; color: #24507f; border-color: #b6ccea; }
.tagchip--cliente   { background: #f7ecd6; color: #7a5712; border-color: #e6d0a4; }
.tagchip--propiedad { background: #ebe3f5; color: #553a86; border-color: #cfc0e8; }
:root.dark .tagchip--venta     { background: #1e2c17; color: #8cc45f; border-color: #2f4a22; }
:root.dark .tagchip--licencia  { background: #16232f; color: #7fb2e0; border-color: #24405a; }
:root.dark .tagchip--cliente   { background: #2c2617; color: #d9b264; border-color: #4a3f22; }
:root.dark .tagchip--propiedad { background: #241d33; color: #b79ee4; border-color: #3b3054; }

.project-card { position: relative; }
.project-card__tag { position: absolute; top: .6rem; right: .6rem; z-index: 3; }

/* Sin sitio para la tercera columna, la barra baja debajo a todo el ancho.
   No hace falta reordenar nada: ya es la última del HTML.

   El rango lleva min-width a propósito. Con solo max-width, esta regla también
   se aplicaría por debajo de 900px y, al estar más abajo en el archivo, ganaba
   a la de una sola columna: en móvil seguían viéndose imágenes y detalles
   lado a lado, cada uno en media pantalla. */
@media (min-width: 901px) and (max-width: 1100px) {
  .case__top--wide { grid-template-columns: minmax(0, 1fr) 20rem; }
  .case__top--wide > .showcase { grid-column: 1 / -1; grid-row: auto; }
  .case__top--wide > .case__shots { grid-column: 1; grid-row: 1; }
  .case__top--wide > .case__aside { grid-column: 2; grid-row: 1; }
  .case__top--wide .showcase {
    margin-top: .4rem; padding-top: 1rem; border-top: 1px solid var(--rule);
  }
  .case__top--wide .showcase__list {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  }
}

.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.toolbar .chips { margin-bottom: 0; }
.sorter { display: flex; align-items: center; gap: .5rem; margin: 0; }
.sorter select { min-height: 2.3rem; width: auto; font-size: .85rem; padding: .3rem 2rem .3rem .7rem; }
.chip--venta.is-on     { background: #e2f0dc; border-color: #7fae63; color: #2f6b1c; }
.chip--licencia.is-on  { background: #dfe9f6; border-color: #6f9bcb; color: #24507f; }
.chip--cliente.is-on   { background: #f7ecd6; border-color: #c9a961; color: #7a5712; }
.chip--propiedad.is-on { background: #ebe3f5; border-color: #9d84cf; color: #553a86; }

.chips--tech { margin-top: .9rem; }
.chip[aria-pressed="true"]::after { content: "×"; margin-left: .35rem; opacity: .6; font-size: .9em; }

/* En móvil la lista de tecnologías puede ser larga: se colapsa y el
   usuario decide si quiere verla completa. En pantallas grandes no hace
   falta, ahí entra sin problema. */
.chips-collapse__input { position: absolute; opacity: 0; pointer-events: none; }
.chips-collapse__btn { display: none; }
.chips-collapse__less { display: none; }
@media (max-width: 1000px) {
  .chips-collapse .chips--tech { max-height: 6.6rem; overflow: hidden; }
  .chips-collapse__input:checked ~ .chips--tech { max-height: none; }
  .chips-collapse__btn {
    display: inline-block; margin-top: .5rem; cursor: pointer;
    font-size: .85rem; color: var(--leaf);
  }
  .chips-collapse__input:checked ~ .chips-collapse__btn .chips-collapse__more { display: none; }
  .chips-collapse__input:checked ~ .chips-collapse__btn .chips-collapse__less { display: inline; }
}


/* ── titular que se escribe solo ──────────────────────────────────────────
   El texto ya está en el HTML: el JS solo lo revela. Sin JS se ve entero,
   así que ni los buscadores ni un lector de pantalla se quedan sin él. */
.typed { min-height: 1.2em; }
.typed__caret {
  display: inline-block; width: .06em; height: .85em;
  margin-left: .06em; vertical-align: -0.08em;
  background: var(--leaf);
  animation: cursor 1s steps(1) infinite;
}
.typed--done .typed__caret { animation: cursor 1s steps(1) 3, desvanecer .4s ease 3s forwards; }

@keyframes cursor { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes desvanecer { to { opacity: 0; width: 0; margin: 0; } }

/* ── entrada de las cifras ────────────────────────────────────────────────
   Se marca al observarlas: hasta entonces quedan a media opacidad para que
   el conteo se note como algo que ocurre, no como un parpadeo. */
.stat[data-count] strong { opacity: .35; transition: opacity .3s ease; }
.stat[data-count].is-live strong { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .timeline li::before { animation: none; }
  .tech-grid.is-live img, .tech-grid.is-live .tech-mark { animation: none; }
  .tech-grid li:hover img, .tech-grid li:hover .tech-mark { transform: none; }
  .typed__caret { display: none; }
  .stat[data-count] strong { opacity: 1; }
  .btn:hover { transform: none; }
}


/* ── entrada de las tarjetas ──────────────────────────────────────────────
   Se marcan al verse: animar lo que está fuera de pantalla desperdicia el
   efecto, porque se pierde antes de llegar. */
[data-reveal] { opacity: 0; transform: translateY(14px); }
[data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity .25s ease, transform .25s cubic-bezier(.22, 1, .36, 1);
}
/* Escalonado por posición dentro de su grupo. */
[data-reveal].is-in:nth-child(1) { transition-delay: 0s; }
[data-reveal].is-in:nth-child(2) { transition-delay: .02s; }
[data-reveal].is-in:nth-child(3) { transition-delay: .04s; }
[data-reveal].is-in:nth-child(4) { transition-delay: .06s; }
[data-reveal].is-in:nth-child(5) { transition-delay: .08s; }
[data-reveal].is-in:nth-child(n+6) { transition-delay: .1s; }
/* Dentro de un carrusel el retardo se acorta: la del asomo tiene que estar
   ahí casi a la vez que la primera, o el hueco se ve vacío. */
.car-track > [data-reveal].is-in { transition-delay: 0s; }
.car-track > [data-reveal].is-in:nth-child(2) { transition-delay: .02s; }
.car-track > [data-reveal].is-in:nth-child(3) { transition-delay: .04s; }
.car-track > [data-reveal].is-in:nth-child(n+4) { transition-delay: .06s; }

.project-card, .testimonial-card {
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.project-card:hover, .testimonial-card:hover {
  border-color: var(--leaf);
  transform: translateY(-3px);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--ink) 14%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; }
  .project-card:hover, .testimonial-card:hover { transform: none; }
}


/* El carrusel de «Proyectos parecidos» va dentro de una tarjeta que ya tiene
   su propio relleno, así que las flechas caen justo sobre el borde. */
.case__related .carousel { margin-top: 1rem; }
.case__related .car-btn.prev { left: -.9rem; }
.case__related .car-btn.next { right: -.9rem; }

/* Contador junto a «ver todos». Igual que el resto de la línea, solo que la
   cifra va en rojo y más grande: es el único sitio del portafolio donde el
   color se usa para llamar la atención y no para identificar algo. */
.pill {
  display: inline-block; min-width: 1.5rem; text-align: center;
  margin: 0 .15rem 0 .4rem; padding: .05rem .4rem;
  border-radius: 999px; background: var(--tint);
  color: var(--alerta); font-family: "Plex Mono", monospace;
  font-size: 1.34rem; font-weight: 500; line-height: 1.2;
  vertical-align: -0.2em;
  /* Solo transform: crecer con font-size o padding movería el enlace entero
     y el texto de al lado daría un salto al pasar el ratón. */
  transition: transform .18s cubic-bezier(.34, 1.56, .64, 1);
}
.link-accent:hover .pill { transform: scale(1.1); }

@media (prefers-reduced-motion: reduce) {
  .link-accent:hover .pill { transform: none; }
}

/* Aviso tras enviar el formulario. <dialog> ya centra y atrapa el foco. */
.sent-dialog {
  border: 0; border-radius: var(--r); padding: 2rem;
  max-width: 24rem; text-align: center;
  background: var(--surface); color: var(--ink);
  box-shadow: 0 1.5rem 3rem rgba(8, 11, 9, .25);
}
.sent-dialog::backdrop { background: rgba(8, 11, 9, .55); }
.sent-dialog p { margin: 1rem 0 1.5rem; }
.sent-dialog .plane { color: var(--leaf); }
.sent-dialog.error .plane { color: var(--alert); }

/* Tarjeta final del carrusel: en vez de traer el resto por fetch, se va al
   listado completo, que ya pagina y filtra. */
.more-card {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: .4rem; text-align: center;
  text-decoration: none; color: inherit; padding: 2rem 1rem;
}
.more-card__plus { font-size: 2rem; font-weight: 700; color: var(--leaf); }
.more-card:hover { border-color: var(--leaf); }
