/* =====================================================================
   AFB — Sistema de diseño compartido (estilo Mood Board / letterhead)
   Se usa en todas las hojas del sitio. Requiere las fuentes Montserrat
   y Lora (cárgalas con <link> en el <head> de cada página).
   ===================================================================== */
:root{
  --teal:#229c9f;--teal-d:#1a7a7d;--blue:#d8e9f4;--white:#ffffff;
  --ink:#0e0e0f;--gray:#3a3b41;--gray-2:#6b6e77;
  --gold:#c9a227;--gold-2:#f0d98a;--gold-soft:rgba(201,162,39,.16);
  --line:#e5eaf0;--pad:clamp(26px,5vw,64px);
  --sans:'Montserrat',system-ui,'Segoe UI',sans-serif;
  --serif:'Lora',Georgia,serif;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;scroll-padding-top:104px}
body{font-family:var(--sans);background:var(--blue);color:var(--gray);
  -webkit-font-smoothing:antialiased;line-height:1.55}
img{display:block;max-width:100%}
a{text-decoration:none;color:inherit}
.serif{font-family:var(--serif)}
.kicker{font-size:.68rem;font-weight:700;letter-spacing:.3em;text-transform:uppercase;color:var(--teal)}

/* Barra superior */
.topbar{position:sticky;top:0;z-index:40;background:rgba(255,255,255,.86);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topbar .in{max-width:1200px;margin:0 auto;padding:0 26px;height:60px;display:flex;align-items:center;justify-content:space-between;gap:14px}
.brand{display:flex;align-items:center;gap:11px;font-weight:800;color:var(--ink)}
/* 48 px: los 32 de antes más un 50%. El logo nuevo (`logo-afb.png`) es la
   marca con fondo transparente y a resolución de verdad, así que ya no lleva
   `border-radius` ni `object-fit:cover` — eso venía de cuando la imagen era
   un cuadrito opaco de 13 KB, y sobre un PNG transparente `cover` recorta el
   dibujo por los lados. `contain` lo mete entero. La barra mide 60 px de
   alto, así que 48 es lo que cabe sin empujarla. */
.brand img{width:48px;height:48px;object-fit:contain}
.brand small{display:block;font-family:var(--serif);font-style:italic;font-weight:400;font-size:.7rem;color:var(--gray-2);letter-spacing:0;text-transform:none}
.back{font-size:.82rem;color:var(--gray-2);font-weight:600;white-space:nowrap}.back:hover{color:var(--teal)}

/* Menú de navegación (opcional) */
.navlinks{display:flex;gap:20px;flex-wrap:wrap}
.navlinks a{font-size:.84rem;font-weight:600;color:var(--gray-2);position:relative;padding-bottom:2px}
.navlinks a:hover{color:var(--teal)}
.navlinks a.active{color:var(--teal);font-weight:800}
.navlinks a.active::after{content:"";position:absolute;left:0;right:0;bottom:-4px;height:2px;border-radius:2px;
  background:linear-gradient(90deg,var(--teal),var(--gold))}
@media(max-width:720px){.navlinks{display:none}}

/* Toggle Ordenador / Móvil */
.view-toggle{display:inline-flex;align-items:center;gap:3px;background:#fff;border:1px solid var(--line);border-radius:100px;padding:3px}
.view-toggle button{border:0;background:transparent;font:inherit;font-size:.76rem;font-weight:700;color:var(--gray-2);
  padding:7px 13px;border-radius:100px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:.18s}
.view-toggle button svg{width:15px;height:15px}
.view-toggle button.active{background:linear-gradient(135deg,var(--teal),var(--teal-d));color:#fff;box-shadow:0 6px 16px -8px rgba(34,156,159,.6)}
.view-toggle .sl{color:#c7cfda;font-weight:400;font-size:1rem}
@media(max-width:560px){.view-toggle button span{display:none}.view-toggle button{padding:8px 11px}}

/* Hoja */
.sheet{max-width:1200px;margin:30px auto;background:var(--white);border:1px solid var(--line);border-radius:6px;
  box-shadow:0 40px 90px -50px rgba(14,14,15,.35);padding:var(--pad);overflow:hidden;overflow:clip;transition:max-width .4s ease}

/* Barra de secciones sticky (pills) — se pica y viaja entre secciones.
   Requiere ids en las secciones destino. El resalte activo lo pone afb.js. */
.secnav{position:sticky;top:60px;z-index:30;display:flex;gap:8px;flex-wrap:wrap;align-items:center;
  margin:8px 0 30px;padding:12px 2px;background:var(--white);border-bottom:1px solid var(--line)}
.secnav a,.secnav button{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;border:1px solid var(--line);border-radius:100px;
  font-family:inherit;font-size:.8rem;font-weight:700;color:var(--gray);background:var(--white);transition:.18s;white-space:nowrap;cursor:pointer}
.secnav a:hover,.secnav button:hover{border-color:var(--teal);color:var(--ink);box-shadow:0 6px 16px -10px rgba(34,156,159,.5)}
.secnav a.active,.secnav button.active{color:#fff;border-color:transparent;background:linear-gradient(135deg,var(--teal),var(--teal-d));
  box-shadow:0 8px 18px -8px rgba(34,156,159,.6)}
.secnav a .g,.secnav button .g{font-family:var(--serif);font-style:italic;font-size:1.02rem;line-height:1}
.secnav a.active .g{color:#fff}
@media(max-width:640px){.secnav{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;margin-bottom:22px}
  .secnav::-webkit-scrollbar{display:none}}

/* Banner de marca (estilo letterhead)
   Antes era `logo-lockup.png`: una sola imagen con el dibujo y las palabras.
   Ahora se arma con la marca (`logo-afb.png`, PNG transparente) más el nombre
   puesto en la tipografía del sitio. Tres razones:
     · El lockup traía el fondo opaco —blanco con un resplandor cian— y encima
       de la tarjeta blanca se veía como un rectángulo pegado.
     · Una imagen de texto no escala nítida y no sigue el modo oscuro; así el
       nombre usa var(--ink) y var(--teal) y cambia solo.
     · El nombre pasa a ser texto: lo lee un buscador y un lector de pantalla.
   El <img> va con alt="" a propósito: el <a> ya lleva aria-label con el
   nombre completo, y si además el logo se anunciara saldría dos veces. */
.brandbanner{display:flex;align-items:center;gap:14px;background:transparent}
.brandbanner img{display:block;width:auto;flex:0 0 auto}
.brandbanner .bb-txt{line-height:1.06}
.brandbanner .bb-txt b{display:block;font-family:var(--sans);font-weight:800;color:var(--ink);letter-spacing:-.025em}
.brandbanner .bb-txt small{display:block;font-family:var(--sans);font-weight:600;color:var(--teal)}
/* El membrete de arriba se quitó: iba entre la barra superior y el título de
   la página, repitiendo el logo y el nombre que la barra ya trae dos
   centímetros más arriba. Sólo queda el de cierre, al pie. */
.brandbanner.bottom{margin:34px 0 0;padding-top:16px;border-top:1px solid rgba(34,156,159,.32);opacity:.9}
.brandbanner.bottom img{height:48px}
.brandbanner.bottom .bb-txt b{font-size:1.55rem}
.brandbanner.bottom .bb-txt small{font-size:.73rem;margin-top:2px}
@media(max-width:640px){
  .brandbanner{gap:11px}
  .brandbanner.bottom img{height:38px}
  .brandbanner.bottom .bb-txt b{font-size:1.25rem}
  .brandbanner.bottom .bb-txt small{font-size:.66rem}
}

/* Masthead */
.mast{display:flex;justify-content:space-between;align-items:flex-end;gap:30px;flex-wrap:wrap}
.mast h1{font-family:var(--sans);font-weight:800;letter-spacing:-.025em;color:var(--ink);font-size:clamp(2.2rem,5.6vw,3.6rem);line-height:1;margin:12px 0 8px}
.mast .sub{font-family:var(--serif);font-style:italic;color:var(--gray);font-size:clamp(1.02rem,2.2vw,1.35rem);max-width:52ch}
.mast .count{font-family:var(--serif);font-size:clamp(2.4rem,7vw,4.4rem);color:var(--line);font-weight:600;line-height:.8}
.mast .count b{color:var(--teal)}

/* Barra decorativa con brillo */
.rulebar{height:5px;margin-top:26px;border-radius:4px;position:relative;overflow:hidden;
  background:linear-gradient(90deg,var(--teal) 0 30%,var(--gold) 30% 42%,var(--blue) 42% 100%)}
.rulebar::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.75),transparent);animation:afb-sweep 5.5s ease-in-out 1s infinite}
@keyframes afb-sweep{0%{transform:translateX(-100%)}55%,100%{transform:translateX(220%)}}

/* Letra griega decorativa (dorada con brillo) */
.glyph{position:relative;font-family:var(--serif);font-weight:600;line-height:.8;font-size:clamp(3rem,6vw,4.4rem);
  background:linear-gradient(115deg,#b8901f 0%,#f4e0a0 45%,#c9a227 60%,#f4e0a0 80%,#b8901f 100%);
  background-size:220% auto;-webkit-background-clip:text;background-clip:text;color:transparent;
  animation:afb-shimmer 5s linear infinite;filter:drop-shadow(0 2px 10px rgba(201,162,39,.28))}
@keyframes afb-shimmer{to{background-position:-220% center}}

/* Títulos de sección */
.h2{font-family:var(--sans);font-weight:800;color:var(--ink);letter-spacing:-.02em;
  font-size:clamp(1.5rem,3.4vw,2.2rem);line-height:1.12;position:relative;padding-bottom:14px;margin-bottom:14px}
.h2 span{font-family:var(--serif);font-weight:500;font-style:italic;color:var(--teal)}
.h2::after{content:"";position:absolute;left:0;bottom:0;width:56px;height:2px;background:linear-gradient(90deg,var(--teal),var(--gold))}
.h2.center{text-align:center}.h2.center::after{left:50%;transform:translateX(-50%)}

/* Botones */
.cta{display:inline-flex;align-items:center;gap:10px;font-weight:700;font-size:.95rem;color:#fff;
  padding:13px 26px;border-radius:100px;background:linear-gradient(135deg,var(--teal),var(--teal-d));
  box-shadow:0 12px 26px -12px rgba(34,156,159,.6);transition:transform .18s,box-shadow .25s;position:relative;overflow:hidden;cursor:pointer;border:0}
.cta::after{content:"";position:absolute;top:0;left:-120%;width:60%;height:100%;transform:skewX(-20deg);
  background:linear-gradient(90deg,transparent,rgba(255,240,200,.55),transparent)}
.cta:hover{transform:translateY(-2px);box-shadow:0 0 0 1px rgba(201,162,39,.55),0 16px 34px -12px rgba(201,162,39,.45)}
.cta:hover::after{animation:afb-glint .8s ease}
@keyframes afb-glint{to{left:150%}}
.btn-out{display:inline-flex;align-items:center;gap:9px;font-weight:700;font-size:.95rem;color:var(--ink);
  padding:13px 26px;border-radius:100px;border:1px solid var(--line);background:#fff;transition:.2s;cursor:pointer}
.btn-out:hover{border-color:var(--teal);color:var(--teal)}

/* Pie */
.foot{margin-top:20px;padding-top:20px;border-top:1px solid var(--line);
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:10px;
  font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;color:var(--gray-2)}
.foot a{color:var(--teal)}

/* =====================================================================
   Barra fija de acción — sólo en móvil.
   En escritorio hay rieles laterales y botones en la página; en el teléfono
   no hay dónde poner la mano. Va abajo, del ancho de la pantalla y con 52 px
   de alto, que es lo que necesita un pulgar para no fallar el toque, y
   respeta el área segura de los teléfonos con barra inferior.
   ===================================================================== */
.cta-fija{position:fixed;left:0;right:0;bottom:0;z-index:60;display:none;
  padding:10px 12px calc(10px + env(safe-area-inset-bottom,0px));
  background:linear-gradient(180deg,rgba(255,255,255,0),rgba(255,255,255,.92) 38%);
  transform:translateY(110%);transition:transform .28s ease;pointer-events:none}
.cta-fija.on{transform:none;pointer-events:auto}
.cta-fija-btn{display:flex;align-items:center;justify-content:center;gap:10px;
  min-height:52px;padding:12px 18px;border-radius:100px;font-weight:700;font-size:.95rem;
  color:#04250f;background:linear-gradient(135deg,#25d366,#1eb457);
  box-shadow:0 10px 26px -10px rgba(37,211,102,.75),0 0 0 1px rgba(0,0,0,.05)}
.cta-fija-btn svg{width:21px;height:21px;flex-shrink:0}
.cta-fija-btn:active{transform:scale(.985)}
@media(max-width:720px){
  .cta-fija{display:block}
  /* Con la barra abajo, el botón redondo sobra y se encima. Va con :has y no
     con el selector de hermano, porque el flotante se inyecta ANTES que la
     barra y `~` sólo mira hacia adelante. */
  body:has(.cta-fija.on) .wa-float{display:none}
}
:root[data-theme="dark"] .cta-fija{background:linear-gradient(180deg,rgba(14,18,22,0),rgba(14,18,22,.92) 38%)}
@media(prefers-reduced-motion:reduce){.cta-fija{transition:none}}

/* Reveal al hacer scroll */
.reveal{opacity:0;transform:translateY(26px);transition:opacity .7s ease,transform .7s ease}
.reveal.in{opacity:1;transform:none}

/* Lightbox */
.frame img,.thumbs img,.shots img,.zoomable{cursor:zoom-in}
.lb{position:fixed;inset:0;z-index:120;background:rgba(8,10,12,.92);backdrop-filter:blur(5px);
  display:none;align-items:center;justify-content:center;padding:28px;cursor:zoom-out}
.lb.open{display:flex;animation:afb-lbin .22s ease}
@keyframes afb-lbin{from{opacity:0}to{opacity:1}}
.lb figure{max-width:96%;max-height:94%;display:flex;flex-direction:column;align-items:center;gap:12px;cursor:default}
.lb img{max-width:100%;max-height:82vh;border-radius:10px;box-shadow:0 40px 90px -20px rgba(0,0,0,.85);border:1px solid rgba(255,255,255,.12)}
.lb figcaption{font-family:var(--serif);font-style:italic;color:#d8e9f4;font-size:.9rem}
.lb .x{position:absolute;top:18px;right:24px;color:#fff;font-size:2.2rem;line-height:1;cursor:pointer;opacity:.75;background:none;border:0}
.lb .x:hover{opacity:1}
.lb .hint{position:absolute;bottom:20px;left:0;right:0;text-align:center;color:rgba(255,255,255,.5);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase}

/* Vista MÓVIL simulada (genérico) */
body.view-mobile{background:#c3d3e0}
body.view-mobile .sheet{--pad:20px;max-width:430px;border-radius:34px;border:9px solid #0e0e0f;box-shadow:0 50px 90px -30px rgba(14,14,15,.6)}
body.view-mobile .mast{flex-direction:column;align-items:flex-start}
body.view-mobile .mast .count{display:none}
body.view-mobile .brandbanner{gap:11px}
body.view-mobilebody.view-mobilebody.view-mobilebody.view-mobile .brandbanner.bottom img{height:38px}
body.view-mobile .brandbanner.bottom .bb-txt b{font-size:1.25rem}
body.view-mobile .brandbanner.bottom .bb-txt small{font-size:.66rem}
body.view-mobile .two,body.view-mobile .three,body.view-mobile .four{grid-template-columns:1fr!important}

/* Rejillas utilitarias */
.two{display:grid;grid-template-columns:1fr 1fr;gap:24px}
.three{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.four{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
@media(max-width:820px){.two,.three,.four{grid-template-columns:1fr}}

@media(prefers-reduced-motion:reduce){
  .glyph,.rulebar::after,.cta::after{animation:none!important}
  .reveal{opacity:1;transform:none;transition:none}
}

/* =====================================================================
   Comparador Antes / Después (arrastrable). Markup:
   <div class="ba" data-ba>
     <img class="ba-after"  src="render.jpg"    alt="Después">
     <img class="ba-before" src="obra-gris.jpg" alt="Antes">
     <span class="ba-label before">Antes</span>
     <span class="ba-label after">Después</span>
     <div class="ba-handle" role="slider" tabindex="0"
          aria-label="Comparar antes y después"
          aria-valuemin="0" aria-valuemax="100" aria-valuenow="50"><span></span></div>
   </div>
   ===================================================================== */
.ba{--pos:50%;position:relative;width:100%;aspect-ratio:16/10;border-radius:16px;overflow:hidden;
  border:1px solid var(--line);box-shadow:0 34px 70px -38px rgba(14,14,15,.55);
  touch-action:none;user-select:none;cursor:ew-resize}
.ba img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;pointer-events:none;display:block}
.ba .ba-before{clip-path:inset(0 calc(100% - var(--pos)) 0 0)}
.ba-label{position:absolute;top:14px;z-index:3;font-size:.64rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:#fff;background:rgba(14,14,15,.55);backdrop-filter:blur(4px);padding:6px 12px;border-radius:100px;pointer-events:none}
.ba-label.before{left:14px}
.ba-label.after{right:14px}
.ba-handle{position:absolute;top:0;bottom:0;left:var(--pos);width:2px;background:rgba(255,255,255,.92);
  transform:translateX(-50%);z-index:4;box-shadow:0 0 0 1px rgba(14,14,15,.15)}
.ba-handle span{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:44px;height:44px;border-radius:50%;
  background:#fff;box-shadow:0 6px 20px -6px rgba(14,14,15,.65);display:grid;place-items:center;cursor:ew-resize}
.ba-handle span::before{content:"‹ ›";color:var(--teal);font-weight:800;font-size:1rem;letter-spacing:-1px}
.ba-handle:focus-visible{outline:none}
.ba-handle:focus-visible span{box-shadow:0 0 0 3px var(--teal),0 6px 20px -6px rgba(14,14,15,.65)}

/* =====================================================================
   TEMA OSCURO — se activa con data-theme="dark" en <html>.
   Solo aplica cuando el atributo está presente; el modo claro es el default.
   ===================================================================== */
:root[data-theme="dark"]{
  --teal:#2fb6b9;--teal-d:#229c9f;--blue:#0e1216;--white:#171b21;
  --ink:#eef3f6;--gray:#c3ccd6;--gray-2:#8a94a2;
  --gold:#d9b23a;--gold-2:#f0d98a;--gold-soft:rgba(217,178,58,.18);
  --line:#272d36;
}
:root[data-theme="dark"] .topbar{background:rgba(18,22,27,.82)}
:root[data-theme="dark"] .btn-out{background:var(--white)}
:root[data-theme="dark"] .view-toggle{background:var(--white)}

/* Botón de tema (claro / oscuro) */
.theme-toggle{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;
  border-radius:100px;border:1px solid var(--line);background:var(--white);color:var(--teal);cursor:pointer;transition:.18s}
.theme-toggle:hover{border-color:var(--teal);box-shadow:0 6px 16px -8px rgba(34,156,159,.5)}
.theme-toggle svg{width:19px;height:19px}
.theme-toggle .sun{display:none}
:root[data-theme="dark"] .theme-toggle .moon{display:none}
:root[data-theme="dark"] .theme-toggle .sun{display:block}

/* =====================================================================
   Rieles laterales — aprovechan el margen en escritorio amplio.
   Contacto (izquierda) y redes (derecha). Ocultos en móvil / hoja estrecha.
   ===================================================================== */
.side-rail{position:fixed;top:50%;transform:translateY(-50%);z-index:35;
  display:none;flex-direction:column;align-items:center;gap:14px}
.side-rail.left{left:calc((100vw - 1200px)/4 - 22px)}
.side-rail.right{right:calc((100vw - 1200px)/4 - 22px)}
@media(min-width:1380px){.side-rail{display:flex}}
body.view-mobile .side-rail{display:none!important}
.rail-label{writing-mode:vertical-rl;text-transform:uppercase;letter-spacing:.3em;
  font-size:.6rem;font-weight:700;color:var(--gray-2)}
.rail-ico{width:44px;height:44px;border-radius:50%;display:grid;place-items:center;
  background:var(--white);border:1px solid var(--line);color:var(--ink);transition:.2s}
.rail-ico:hover{transform:translateY(-3px);box-shadow:0 12px 24px -10px rgba(14,14,15,.4)}
.rail-ico svg{width:19px;height:19px}
.rail-ico.wa:hover{color:#fff;border-color:transparent;background:#25d366}
.rail-ico.mail:hover{color:#fff;border-color:transparent;background:linear-gradient(135deg,var(--teal),var(--teal-d))}
.rail-ico.ig:hover{color:#fff;border-color:transparent;background:linear-gradient(45deg,#f09433,#e6683c,#dc2743,#cc2366,#bc1888)}
.rail-ico.fb:hover{color:#fff;border-color:transparent;background:#1877f2}
.rail-ico.yt:hover{color:#fff;border-color:transparent;background:#ff0000}
.rail-line{width:1px;height:38px;background:linear-gradient(var(--line),transparent)}

/* WhatsApp flotante (inyectado por afb.js en todas las páginas) */
.wa-float{position:fixed;right:22px;bottom:22px;z-index:60;width:58px;height:58px;border-radius:50%;
  background:#25d366;display:grid;place-items:center;box-shadow:0 12px 30px -8px rgba(37,211,102,.6);transition:transform .2s}
.wa-float:hover{transform:scale(1.08)}
.wa-float svg{width:31px;height:31px;fill:#fff}

/* =====================================================================
   ÓRBITA — banda oscura con el anillo de las apps girando en 3D.
   ---------------------------------------------------------------------
   Es una sección que se queda OSCURA en los dos temas, a propósito: no
   es un descuido del modo claro, es un cielo. Por eso los colores viven
   en variables propias (--orb-*) y no en los tokens del sitio, que
   cambian con el tema. Los dos negros y el blanco son los mismos que ya
   usa nuestro modo oscuro.

   El fundido de arriba y abajo lo hace `mask-image`: sin él la banda se
   ve como una caja pegada encima de la hoja. Con él, la página se
   oscurece y vuelve.

   Se monta desde afb.js (función `orbita`). Si el JS no corre, la banda
   queda con el fondo y las figuras pero sin medallas: no rompe la página.
   ===================================================================== */
.orbita{
  --orb-teal:#2fb6b9; --orb-gold:#d9b23a; --orb-ink:#eef3f6; --orb-dim:#9aa6b3;
  --orb-w:clamp(140px,17vw,206px);
  position:relative; isolation:isolate;
  margin:34px calc(var(--pad) * -1) 30px;
  height:clamp(430px,64vh,620px);
  background:radial-gradient(115% 85% at 50% 42%, #101720 0%, #0a0f14 46%, #050809 100%);
  overflow:hidden;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,rgba(0,0,0,.42) 3.5%,#000 11%,#000 89%,rgba(0,0,0,.42) 96.5%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,rgba(0,0,0,.42) 3.5%,#000 11%,#000 89%,rgba(0,0,0,.42) 96.5%,transparent 100%);
}

/* Cuadrícula de plano. Se apaga en el centro para que el anillo respire. */
.orbita .malla{
  position:absolute; inset:0; z-index:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(47,182,185,.10) 1px, transparent 1px),
    linear-gradient(90deg, rgba(47,182,185,.10) 1px, transparent 1px);
  background-size:44px 44px;
  -webkit-mask-image:radial-gradient(72% 62% at 50% 50%, transparent 18%, #000 82%);
          mask-image:radial-gradient(72% 62% at 50% 50%, transparent 18%, #000 82%);
}
.orbita .halo{
  position:absolute; left:50%; top:50%; width:min(84%,780px); aspect-ratio:1;
  transform:translate(-50%,-50%); z-index:0; pointer-events:none;
  background:radial-gradient(circle, rgba(47,182,185,.20) 0%, rgba(47,182,185,.055) 38%, transparent 68%);
}
.orbita .barrido{
  position:absolute; left:0; width:100%; height:1px; z-index:0; pointer-events:none; opacity:0;
  background:linear-gradient(90deg,transparent,var(--orb-teal),transparent);
  animation:orb-barrido 9s ease-in-out infinite;
}
.orbita .barrido.b1{top:24%}
.orbita .barrido.b2{top:76%; animation-delay:4.5s}
@keyframes orb-barrido{
  0%{transform:translateX(-100%); opacity:0}
  50%{opacity:.5}
  100%{transform:translateX(100%); opacity:0}
}

/* Figuras de plano al fondo.
   La rotación va DENTRO de los keyframes: si se pone en la regla base, la
   animación —que también escribe `transform`— la borra y el rombo se
   endereza. */
.orbita .plano{position:absolute; z-index:0; pointer-events:none; border:1px solid rgba(195,204,214,.13)}
.orbita .plano.circ{width:180px; height:180px; border-radius:50%; top:-48px; right:7%;
  animation:orb-flota 11s ease-in-out infinite}
.orbita .plano.romb{width:120px; height:120px; bottom:-36px; left:6%;
  animation:orb-romb 13s ease-in-out infinite}
@keyframes orb-flota{0%,100%{transform:translateY(0) rotate(0deg)} 50%{transform:translateY(-12px) rotate(4deg)}}
@keyframes orb-romb {0%,100%{transform:rotate(45deg) translateY(0)}  50%{transform:rotate(50deg) translateY(-12px)}}

.orbita .anillo{
  position:absolute; inset:0; z-index:1; display:grid; place-items:center;
  perspective:2200px; touch-action:pan-y; cursor:grab; outline:none;
}
.orbita .anillo.arrastrando{cursor:grabbing}
.orbita .anillo:focus-visible{outline:2px solid var(--orb-teal); outline-offset:-4px; border-radius:12px}
.orbita .escena{position:relative; width:0; height:0; transform-style:preserve-3d; will-change:transform}

/* ── La medalla de cada app ──
   El dibujo viene de assets/medallas/, recortado con máscara circular de
   la lámina de 00 ICONOS AFB. No se le repinta nada: el color de cada app
   lo pone el resplandor de atrás, que sí es nuestro. Sin marco: una
   medalla redonda dentro de un rectángulo deja mucho vacío. */
.orbita .orb-carta{
  position:absolute; left:0; top:0;
  width:var(--orb-w); height:calc(var(--orb-w) * 1.22);
  margin-left:calc(var(--orb-w) / -2); margin-top:calc(var(--orb-w) * -.61);
  border-radius:50%; text-decoration:none; display:grid; place-items:center;
  padding:0; border:0; background:none;
  transition:opacity .25s linear;
}
.orbita .orb-carta::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(58% 58% at 50% 50%, var(--c), transparent 70%);
  opacity:.58;
}
.orbita .orb-carta .medalla{
  position:relative; z-index:1; width:100%; height:auto; display:block;
  filter:drop-shadow(0 10px 22px rgba(0,0,0,.55));
}

/* AFB Lista todavía no está en la lámina de medallas: se dibuja con CSS
   imitando el mismo objeto —aro de plata, cara teal, banda oscura— con
   los colores muestreados de las medallas de verdad. */
.orbita .orb-carta .medalla-css{
  position:relative; z-index:1; display:block;
  width:calc(var(--orb-w) * .97); height:calc(var(--orb-w) * .97);
  border-radius:50%; overflow:hidden;
  background:radial-gradient(72% 62% at 38% 26%, #37707a, #23545d 62%, #1b414a);
  border:calc(var(--orb-w) * .028) solid #b3b1ad;
  box-shadow:0 12px 26px rgba(0,0,0,.6), inset 0 0 0 2px rgba(0,0,0,.28);
}
.orbita .orb-carta .medalla-css .cara{
  position:absolute; left:0; right:0; top:0; height:60%; display:grid; place-items:center;
}
.orbita .orb-carta .medalla-css .cara svg{
  width:40%; height:auto; fill:none; stroke:#e6ecee; stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,.5));
}
.orbita .orb-carta .medalla-css .banda{
  position:absolute; left:0; right:0; bottom:0; height:40%;
  background:linear-gradient(180deg,#1e444d,#16333b);
  border-top:2px solid rgba(200,205,208,.5);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:2px; padding-bottom:5%;
}
.orbita .orb-carta .medalla-css .banda b{
  font-family:var(--sans); font-weight:800; color:#eef3f5; line-height:1;
  font-size:calc(var(--orb-w) * .105); letter-spacing:.6px; text-shadow:0 1px 1px rgba(0,0,0,.6);
}
.orbita .orb-carta .medalla-css .banda i{
  font-family:var(--sans); font-style:normal; font-weight:600; color:#cfd9dc;
  line-height:1; font-size:calc(var(--orb-w) * .074); text-shadow:0 1px 1px rgba(0,0,0,.6);
}
.orbita .orb-carta .pronto{
  position:absolute; top:6%; right:2%; z-index:2;
  font-family:var(--sans); font-size:.56rem; font-weight:700; letter-spacing:.13em;
  text-transform:uppercase; color:#fff; background:rgba(0,0,0,.5);
  border:1px solid rgba(255,255,255,.32); border-radius:100px; padding:3px 8px;
}
.orbita .orb-carta:hover .medalla,
.orbita .orb-carta:hover .medalla-css{filter:drop-shadow(0 0 14px rgba(255,255,255,.45))}
.orbita .orb-carta:focus-visible{outline:2px solid var(--orb-teal); outline-offset:4px; border-radius:50%}

/* De espaldas se apaga lo que lleva texto —saldría al revés— y queda sólo
   el resplandor cerrando el anillo. `backface-visibility` no sirve aquí:
   la medalla lleva `overflow:hidden` y eso aplana el contexto 3D. Se
   resuelve en el pintado, que ya sabe el ángulo de cada una. */
.orbita .orb-carta .medalla,
.orbita .orb-carta .medalla-css,
.orbita .orb-carta .pronto{transition:opacity .16s linear}
.orbita .orb-carta.de-espaldas .medalla,
.orbita .orb-carta.de-espaldas .medalla-css,
.orbita .orb-carta.de-espaldas .pronto{opacity:0}

.orbita .rotulo{position:absolute; left:0; right:0; bottom:min(7%,40px); z-index:2;
  text-align:center; pointer-events:none; padding:0 20px}
.orbita .rotulo b{display:block; font-family:var(--sans); font-weight:700; letter-spacing:.4px;
  font-size:clamp(1.05rem,2.7vw,1.5rem); color:var(--orb-gold); text-shadow:0 2px 18px rgba(0,0,0,.85)}
.orbita .rotulo span{display:block; margin:7px auto 0; font-family:var(--sans);
  font-size:.82rem; color:var(--orb-dim); max-width:46ch; line-height:1.4}

/* 44×44 es el mínimo táctil. */
.orbita .giro{
  position:absolute; top:50%; transform:translateY(-50%); z-index:3;
  width:44px; height:44px; border-radius:100px; display:grid; place-items:center;
  cursor:pointer; padding:0; color:var(--orb-ink);
  border:1px solid rgba(195,204,214,.22); background:rgba(10,15,20,.55);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px); transition:.2s;
}
.orbita .giro:hover{background:rgba(47,182,185,.3); border-color:var(--orb-teal)}
.orbita .giro:focus-visible{outline:2px solid var(--orb-teal); outline-offset:3px}
.orbita .giro svg{width:20px; height:20px}
.orbita .giro.izq{left:14px}
.orbita .giro.der{right:14px}

/* En el teléfono la banda no puede comerse la pantalla: con 64vh el rótulo
   caía bajo el pliegue y sólo se veía el anillo sin decir de qué app era. */
@media(max-width:720px){
  .orbita{height:clamp(356px,52vh,460px); margin-top:26px}
}
@media(max-width:560px){
  .orbita .giro.izq{left:8px} .orbita .giro.der{right:8px}
  .orbita .rotulo{bottom:min(6%,26px); padding:0 46px}
  .orbita .rotulo span{font-size:.76rem}
}

/* Quien pide menos movimiento: el anillo se queda quieto y se navega con
   los botones y las flechas. No se le quita nada, sólo el giro solo. */
@media(prefers-reduced-motion:reduce){
  .orbita .barrido{animation:none; opacity:.22; transform:none}
  .orbita .plano.circ{animation:none}
  .orbita .plano.romb{animation:none; transform:rotate(45deg)}
  .orbita .orb-carta{transition:none}
}

/* =====================================================================
   CAPA VISUAL — cuatro cosas, no ocho.
   ---------------------------------------------------------------------
   Un sitio de ingeniería se estropea rápido a base de fondos animados:
   acaba pareciendo plantilla. Estas cuatro extienden el lenguaje que ya
   existe (cuadrícula de plano, cota, teal y dorado) en vez de traer otro.

   Todas se apagan con `prefers-reduced-motion` y ninguna anima nada que
   no sea `transform`, `opacity` o `stroke-dashoffset`.
   ===================================================================== */

/* ── 1. Transición entre páginas ──────────────────────────────────────
   Dos líneas. Quita el parpadeo en blanco al cambiar de página y el
   sitio empieza a sentirse como una app. El navegador que no la soporta
   la ignora y todo sigue igual. */
@view-transition{ navigation:auto }
::view-transition-old(root),
::view-transition-new(root){ animation-duration:.22s }
@media(prefers-reduced-motion:reduce){
  ::view-transition-old(root),
  ::view-transition-new(root){ animation:none }
}

/* ── 2. Grano ─────────────────────────────────────────────────────────
   Ni animación ni canvas: una textura al 3% sobre la hoja. Le quita el
   plano digital perfecto y le da cuerpo de papel. Es lo más barato del
   lote y lo que más sube la percepción de acabado.
   `pointer-events:none` es obligatorio: si no, se traga los clics de
   toda la hoja. */
.sheet{position:relative}
.sheet::after{
  content:""; position:absolute; inset:0; z-index:4; pointer-events:none;
  border-radius:inherit; opacity:.035; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] .sheet::after{opacity:.06; mix-blend-mode:screen}

/* ── 3. La barra del masthead se dibuja ───────────────────────────────
   La `.rulebar` aparecía hecha. Ahora se traza de izquierda a derecha al
   cargar, como quien tira una línea. El ancho está en `transform`, no en
   `width`: animar `width` obliga a recalcular el diseño en cada cuadro. */
.rulebar{transform-origin:left center}
.rulebar.trazar{animation:afb-trazar .9s cubic-bezier(.16,1,.3,1) both}
@keyframes afb-trazar{from{transform:scaleX(0)} to{transform:scaleX(1)}}
@media(prefers-reduced-motion:reduce){
  .rulebar.trazar{animation:none}
}

/* ── 4. (retirado) ──────────────────────────────────────────────────
   La cuadrícula viva vivía sólo detrás del masthead de tecnología. Ahora
   el efecto del cursor es de todo el sitio (bloque 9), así que tenerlo
   además aquí era el mismo efecto dos veces en la misma pantalla. */

/* ── 5. La cota que se dibuja ─────────────────────────────────────────
   Línea de acotación de arquitecto: los dos remates, la línea entre
   ellos y la medida encima. Se traza cuando entra en pantalla y el
   número cuenta con el mismo contador que ya usa el sitio.

   Es el único efecto de la lista que nadie más puede copiar: es el
   oficio, no un adorno. */
.cota{
  display:flex; align-items:center; gap:12px;
  margin:22px 0 0; font-family:var(--sans);
}
.cota svg{flex:0 0 auto; height:20px; width:min(100%,320px); overflow:visible}
.cota .linea, .cota .remate{
  fill:none; stroke:var(--teal); stroke-width:1.6; stroke-linecap:round;
}
.cota .linea{
  stroke-dasharray:var(--largo,320); stroke-dashoffset:var(--largo,320);
}
.cota.trazada .linea{
  animation:afb-cota 1s cubic-bezier(.16,1,.3,1) forwards;
}
@keyframes afb-cota{ to{stroke-dashoffset:0} }
.cota .remate{opacity:0}
.cota.trazada .remate{animation:afb-remate .35s ease .75s forwards}
@keyframes afb-remate{ to{opacity:1} }
.cota .medida{
  font-size:.82rem; font-weight:700; color:var(--teal); white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.cota .medida small{
  display:block; font-size:.6rem; font-weight:600; letter-spacing:.14em;
  text-transform:uppercase; color:var(--gray-2); margin-top:2px;
}
@media(prefers-reduced-motion:reduce){
  .cota .linea{stroke-dashoffset:0; animation:none}
  .cota .remate{opacity:1; animation:none}
}

/* ── 6. Parallax de los renders ───────────────────────────────────────
   Las reglas viven en portafolio/index.html, no aquí: `.proj` sólo existe
   en esa página, y su <style> va DESPUÉS de este archivo — puesto aquí,
   su `height:100%` le ganaba al `116%` y la foto salía corta por abajo.
   El JS que las mueve (`parallax`) sí es compartido. */

/* ── 7. Hachura ───────────────────────────────────────────────────────
   El rayado de un corte de plano —concreto, acero— como separador entre
   secciones grandes, en vez de una línea de 1 px. Es del oficio y cuesta
   una regla.

   La franja se desvanece hacia los dos lados para que no corte la hoja
   de canto a canto. */
.hachura{
  height:24px; margin:52px 0; border:0; position:relative; overflow:hidden;
  background-image:repeating-linear-gradient(
    -45deg,
    var(--line) 0 1px,
    transparent 1px 9px
  );
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 22%,#000 78%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 22%,#000 78%,transparent);
  opacity:.9;
}
/* Una marca teal a la izquierda, como el número de una lámina. */
.hachura::after{
  content:""; position:absolute; left:0; top:50%; width:38px; height:2px;
  transform:translateY(-50%); background:var(--teal); border-radius:2px;
}
@media(max-width:640px){ .hachura{margin:36px 0} }

/* ── 8. Isométrico que se arma ────────────────────────────────────────
   Cuatro capas —terreno, losa, muros, cubierta— que entran de abajo
   hacia arriba, en el mismo orden en que ocurre una obra. Va encima de
   los cuatro pasos del flujo porque los ilustra; puesto en cualquier
   otro sitio sería un dibujo bonito y nada más.

   Proyección isométrica de 30°: (x,y,z) -> ((x-y)*0.866, (x+y)*0.5 - z).
   Los puntos están calculados, no tanteados. */
.iso{margin:34px 0 8px; display:flex; flex-direction:column; align-items:center; gap:12px}
.iso svg{width:min(100%,340px); height:auto; overflow:visible}
.iso figcaption{
  font-family:var(--serif); font-style:italic; font-size:.88rem;
  color:var(--gray-2); text-align:center; max-width:44ch;
}
.iso .capa{
  opacity:0; transform:translateY(-16px);
  transition:opacity .55s ease, transform .55s cubic-bezier(.16,1,.3,1);
}
.iso.armada .capa{opacity:1; transform:none}
.iso.armada .capa[data-capa="2"]{transition-delay:.14s}
.iso.armada .capa[data-capa="3"]{transition-delay:.28s}
.iso.armada .capa[data-capa="4"]{transition-delay:.42s}

.iso .terreno{fill:none; stroke:var(--line); stroke-width:1.4; stroke-dasharray:5 5}
.iso .cara-s{fill:rgba(34,156,159,.18); stroke:var(--teal); stroke-width:1.5}
.iso .cara-o{fill:rgba(34,156,159,.30); stroke:var(--teal); stroke-width:1.5}
.iso .cara-e{fill:rgba(34,156,159,.10); stroke:var(--teal); stroke-width:1.5}
.iso .junta{stroke:rgba(34,156,159,.45); stroke-width:1.1}
:root[data-theme="dark"] .iso .cara-s{fill:rgba(47,182,185,.20)}
:root[data-theme="dark"] .iso .cara-o{fill:rgba(47,182,185,.34)}
:root[data-theme="dark"] .iso .cara-e{fill:rgba(47,182,185,.12)}
@media(prefers-reduced-motion:reduce){
  .iso .capa{opacity:1; transform:none; transition:none}
}


/* ── 9. Cuadrícula de plano, en todo el sitio ─────────────────────────
   Rejilla de dos direcciones —no rayado diagonal— detrás de todo, y una
   segunda capa encendida que sigue al cursor por toda la página.

   Van en TRES sitios distintos, y cada uno resuelve algo:

   · `body::before`  fija, detrás de todo. Se ve en el margen alrededor
                     de la hoja.
   · `.sheet`        como fondo de la hoja. Sin esto, de 1200 px para
                     abajo —cualquier teléfono— no se veía rejilla en
                     ninguna parte, porque el margen desaparece.
   · `body::after`   la capa encendida del cursor. Va ENCIMA (z-index 25,
                     por debajo del índice y la barra) porque la hoja es
                     opaca: puesta detrás, el cursor no se vería al pasar
                     sobre el contenido, que es el 90% de la página.

   El paso es de 38 px, el mismo de la banda de órbita, para que sea la
   misma rejilla en todo el sitio y no dos tramas distintas. */
:root{
  --paso-rejilla:38px;
  --rejilla:rgba(34,156,159,.10);
  --rejilla-hoja:rgba(34,156,159,.055);
  --rejilla-viva:rgba(34,156,159,.42);
}
@media(prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --rejilla:rgba(47,182,185,.085);
    --rejilla-hoja:rgba(47,182,185,.05);
    --rejilla-viva:rgba(47,182,185,.5);
  }
}
:root[data-theme="dark"]{
  --rejilla:rgba(47,182,185,.085);
  --rejilla-hoja:rgba(47,182,185,.05);
  --rejilla-viva:rgba(47,182,185,.5);
}

/* Fuera de la hoja. `pointer-events:none` porque cubre la ventana entera:
   sin eso se traga todos los clics del sitio. */
body::before{
  content:""; position:fixed; inset:0; z-index:-1; pointer-events:none;
  background-image:
    linear-gradient(var(--rejilla) 1px, transparent 1px),
    linear-gradient(90deg, var(--rejilla) 1px, transparent 1px);
  background-size:var(--paso-rejilla) var(--paso-rejilla);
}

/* En la hoja: va como FONDO y no como capa encima, así queda detrás de
   las tarjetas en vez de cruzarlas. Y más floja que fuera, porque aquí
   sí cae texto encima. */
.sheet{
  background-image:
    linear-gradient(var(--rejilla-hoja) 1px, transparent 1px),
    linear-gradient(90deg, var(--rejilla-hoja) 1px, transparent 1px);
  background-size:var(--paso-rejilla) var(--paso-rejilla);
}

/* La linterna: la misma rejilla encendida, recortada a un círculo que
   sigue al puntero. El JS sólo escribe --mx y --my; no dibuja nada por
   cuadro y el recorte lo compone la GPU.

   Arranca en -999px para que antes del primer movimiento no haya un
   círculo encendido en la esquina. */
body::after{
  content:""; position:fixed; inset:0; z-index:25; pointer-events:none;
  opacity:0; transition:opacity .35s ease;
  background-image:
    linear-gradient(var(--rejilla-viva) 1px, transparent 1px),
    linear-gradient(90deg, var(--rejilla-viva) 1px, transparent 1px);
  background-size:var(--paso-rejilla) var(--paso-rejilla);
  -webkit-mask-image:radial-gradient(circle 170px at var(--mx,-999px) var(--my,-999px),
    #000 0%, rgba(0,0,0,.45) 48%, transparent 74%);
          mask-image:radial-gradient(circle 170px at var(--mx,-999px) var(--my,-999px),
    #000 0%, rgba(0,0,0,.45) 48%, transparent 74%);
}
:root.con-foco body::after{opacity:1}

/* Sin puntero fino —un teléfono— no hay cursor que seguir: la capa
   encendida no se monta siquiera. Y quien pide menos movimiento se queda
   con la rejilla quieta, que ya es la mitad del efecto. */
@media(prefers-reduced-motion:reduce){
  body::after{display:none}
}
