/*
  KÖNNEN Supply Chain Solutions — sitio web
  Concepto, diseño y desarrollo: Rodolfo Zavala · 2026
  Créditos completos: /humans.txt
*/
/* ===== NOSOTROS — "centro de control" ======================================
   Shares :root tokens, reset, header/nav, mobile menu and footer (already
   dark) from styles.css. Unlike the first pass, the whole page stays in one
   continuous dark register — hero, number strip, jump-nav and the three
   areas — so it reads as one operations deck instead of alternating
   marketing sections. The photo-less "console" panels (rings + glyph +
   scanline + readout) are unchanged from the previous version. */

.nos-page{background:var(--black);}

/* shared faint HUD grid — an actual element (not a pseudo) sat behind each
   dark section's content, so the same grain/grid/glow combo can be reused
   without redeclaring a giant background value per section */
.nos-hud-bg{
  position:absolute; inset:0; z-index:0; pointer-events:none;
  background:
    var(--grain),
    linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px),
    radial-gradient(ellipse 900px 600px at 85% 10%, rgba(232,119,34,.14), transparent 60%),
    linear-gradient(150deg, #141416 0%, #08080a 60%, #101012 100%);
  background-size:auto, 44px 44px, 44px 44px, auto, auto;
}

/* corner brackets — small HUD/viewfinder motif, purely decorative */
.nos-hud-corners span{
  position:absolute; width:22px; height:22px; z-index:2; pointer-events:none;
  border:1px solid rgba(232,119,34,.5);
}
.nos-hud-corners span:nth-child(1){top:24px; left:24px; border-width:1px 0 0 1px;}
.nos-hud-corners span:nth-child(2){top:24px; right:24px; border-width:1px 1px 0 0;}
.nos-hud-corners span:nth-child(3){bottom:24px; left:24px; border-width:0 0 1px 1px;}
.nos-hud-corners span:nth-child(4){bottom:24px; right:24px; border-width:0 1px 1px 0;}
@media (max-width:700px){ .nos-hud-corners span{width:16px; height:16px;} .nos-hud-corners span:nth-child(1),.nos-hud-corners span:nth-child(2){top:16px;} .nos-hud-corners span:nth-child(3),.nos-hud-corners span:nth-child(4){bottom:16px;} }

/* status pill — small blinking-dot readout used in the hero and the CTA */
.nos-status{
  display:inline-flex; align-items:center; gap:9px; position:relative; z-index:1;
  font-family:var(--ff-mono); font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--silver-2);
  border:1px solid rgba(255,255,255,.16); background:rgba(255,255,255,.03);
  padding:8px 14px; border-radius:999px; margin-bottom:22px;
}
.nos-status-dot{width:7px; height:7px; border-radius:50%; background:var(--orange); flex-shrink:0; animation:nosBlink 1.8s ease-in-out infinite;}
@keyframes nosBlink{0%,100%{opacity:1; box-shadow:0 0 0 0 rgba(232,119,34,.5);} 50%{opacity:.4; box-shadow:0 0 0 5px rgba(232,119,34,0);}}
@media (prefers-reduced-motion: reduce){ .nos-status-dot{animation:none;} }

/* ---- HERO ---- */
.nos-hero{position:relative; color:#fff; padding:170px 0 80px; overflow:hidden;}
.nos-hero .wrap{position:relative; z-index:1;}
.nos-hero-copy{max-width:760px;}
.nos-hero-copy .eyebrow{color:var(--orange);}
.nos-hero-copy h1{
  color:#fff; font-size:clamp(38px,5.6vw,66px); margin-top:10px; line-height:1.02;
  text-shadow:0 2px 10px rgba(0,0,0,.6);
}
.nos-hero-copy h1 .accent{color:var(--orange);}
.nos-hero-copy p{color:var(--silver-2); font-size:17px; line-height:1.7; max-width:600px; margin-top:26px;}

/* big ambient radar — the same "live system" motif as the console panels,
   scaled up into an atmospheric background element instead of a card, so
   the hero ties into the loved scan effect without repeating the module
   list that used to sit underneath it */
.nos-hero-radar{
  position:absolute; z-index:0; top:50%; right:-12%; transform:translateY(-50%);
  width:900px; height:900px; max-width:70vw; max-height:70vw; pointer-events:none;
}
.nos-hero-radar-rings{
  position:absolute; inset:0;
  background-image:
    radial-gradient(circle, transparent 0 24%, rgba(255,255,255,.05) 24.4% 24.8%, transparent 25.2%),
    radial-gradient(circle, transparent 0 44%, rgba(255,255,255,.045) 44.4% 44.8%, transparent 45.2%),
    radial-gradient(circle, transparent 0 64%, rgba(255,255,255,.035) 64.4% 64.8%, transparent 65.2%),
    radial-gradient(circle, transparent 0 84%, rgba(232,119,34,.06) 84.4% 84.8%, transparent 85.2%),
    radial-gradient(circle, rgba(232,119,34,.5) 0 3px, transparent 3px);
}
.nos-hero-radar-sweep{
  position:absolute; inset:0; border-radius:50%; overflow:hidden;
  -webkit-mask-image:radial-gradient(circle, #000 0 85%, transparent 85%);
  mask-image:radial-gradient(circle, #000 0 85%, transparent 85%);
}
.nos-hero-radar-sweep::before{
  content:''; position:absolute; inset:-10%;
  background:conic-gradient(from 0deg, rgba(232,119,34,.22), transparent 28%);
  animation:nosRadarSpin 6s linear infinite;
}
@keyframes nosRadarSpin{ to{transform:rotate(360deg);} }
@media (prefers-reduced-motion: reduce){ .nos-hero-radar-sweep::before{animation:none; display:none;} }
@media (max-width:900px){ .nos-hero-radar{right:-30%; opacity:.7;} }
@media (max-width:600px){ .nos-hero-radar{display:none;} }

/* ---- NUMBER STRIP — flows straight out of the hero, same background,
   no visual seam, like the next readout on the same console ---- */
.nos-stats{position:relative; border-top:1px solid rgba(255,255,255,.08);}
.nos-stats-grid{display:grid; grid-template-columns:repeat(4,1fr); border-left:1px solid rgba(255,255,255,.08);}
.nos-stat-cell{padding:30px 28px; border-right:1px solid rgba(255,255,255,.08); border-bottom:1px solid rgba(255,255,255,.08);}
.nos-stat-num{font-family:var(--ff-display); font-size:clamp(28px, 5vw + 12px, 40px); color:#fff; line-height:1; display:block; letter-spacing:-.01em;}
.nos-stat-cell--accent .nos-stat-num{color:var(--orange);}
.nos-stat-cell span{font-family:var(--ff-mono); font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color:var(--silver-2); display:block; margin-top:10px;}
@media (max-width:700px){ .nos-stats-grid{grid-template-columns:1fr 1fr;} }
@media (max-width:480px){ .nos-stat-cell{padding:22px 16px;} }

/* ---- NUESTRO ADN / MISIÓN / VISIÓN — closes out the identity block that
   opened with the hero, same black canvas, before the deck of operational
   rows below switches to alternating light/dark ---- */
.nos-dna{position:relative; background:var(--black); color:#fff; padding:100px 0 110px; overflow:hidden; border-top:1px solid rgba(255,255,255,.08);}
.nos-dna .wrap{position:relative; z-index:1;}
.nos-dna-head{text-align:center; max-width:640px; margin:0 auto 40px;}
.nos-dna-head .eyebrow{justify-content:center;}
.nos-dna-head h2{color:#fff;}
.nos-dna-statement{
  max-width:900px; margin:0 auto 64px; text-align:center;
  font-family:var(--ff-body); font-size:clamp(18px,2.1vw,24px); line-height:1.6; font-weight:400;
  color:var(--silver-1);
}
.nos-dna-statement b{color:var(--orange); font-weight:700;}
.nos-dna-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:32px;
  max-width:1160px; margin:0 auto;
}
.nos-dna-card{position:relative; background:#111113; border:1px solid rgba(255,255,255,.1); padding:64px 56px; transition:background .35s ease, box-shadow .45s ease, transform .35s ease, border-color .35s ease;}
.nos-dna-card:hover{
  background:#17171a; border-color:rgba(232,119,34,.4); transform:translateY(-4px); z-index:1;
  box-shadow:0 30px 70px -10px rgba(232,119,34,.35), 0 10px 30px -6px rgba(232,119,34,.2);
}
.nos-dna-card-icon{width:40px; height:40px; color:var(--orange); margin-bottom:26px;}
.nos-dna-card-icon svg{width:100%; height:100%;}
.nos-dna-card h3{font-family:var(--ff-display); font-size:clamp(36px,4vw,50px); text-transform:uppercase; color:#fff; margin-bottom:18px; line-height:1;}
.nos-dna-card p{font-size:clamp(18px,1.6vw,20px); line-height:1.65; color:var(--silver-1); margin:0;}
@media (max-width:800px){
  .nos-dna-grid{grid-template-columns:1fr; gap:20px;}
  .nos-dna-card{padding:48px 40px;}
}
@media (max-width:600px){
  .nos-dna{padding:70px 0 80px;}
  .nos-dna-statement{margin-bottom:44px;}
  .nos-dna-card{padding:34px 28px;}
}

/* ---- EQUIPO DIRECTIVO — closes out the identity block (hero / stats /
   ADN) with the people behind it, same black canvas as ADN right above it.
   Each card is a plain link out to that person's own bio page (Apple-style
   leadership grid — photo, name, role only; the write-up lives on its own
   page, see the PERFIL DIRECTIVO block further down). If a photo path ever
   404s, nosotros.js hides the broken <img> in place of an icon. */
.nos-team{position:relative; background:var(--black); color:#fff; padding:100px 0 110px; overflow:hidden; border-top:1px solid rgba(255,255,255,.08);}
.nos-team .section-head{align-items:flex-end;}
.nos-team .section-head h2{color:#fff;}
.nos-team .section-head p{color:var(--silver-2);}
.nos-team-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:1px;
  background:rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.1);
}
.nos-team-card{display:block; background:#111113; transition:background .35s ease;}
.nos-team-card:hover{background:#17171a;}
.nos-team-photo{
  position:relative; aspect-ratio:4/5; overflow:hidden; background:#1a1a1d;
  -webkit-mask-image:linear-gradient(to bottom, #000 58%, transparent 96%);
  mask-image:linear-gradient(to bottom, #000 58%, transparent 96%);
}
.nos-team-photo img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:50% 18%; filter:grayscale(1) contrast(1.05);}
.nos-team-photo img.is-broken{display:none;}
.nos-team-head{padding:0 40px 32px; margin-top:20px;}
.nos-team-name{font-family:var(--ff-display); font-size:clamp(24px,2.2vw,30px); text-transform:uppercase; color:#fff; line-height:1.05; margin-bottom:8px;}
.nos-team-role{display:block; font-family:var(--ff-mono); font-size:13px; letter-spacing:.06em; text-transform:uppercase; color:var(--orange);}
@media (max-width:980px){
  .nos-team-grid{grid-template-columns:1fr; }
}
@media (max-width:600px){
  .nos-team{padding:70px 0 80px;}
  .nos-team-head{padding-left:28px; padding-right:28px;}
}

/* ---- PERFIL DIRECTIVO — individual leadership bio pages (Apple Leadership
   style): a light hero with the name/role on the left and the photo on the
   right, shown in full (no crop — width-capped, height auto, bottom-aligned
   with the copy column) since the source portraits are the point here, not
   a graphic crop. Write-up below as two columns on white. Shares this
   stylesheet + nosotros.js (reveal/lenis/mobile-menu already wired there)
   since these pages are just an extension of Nosotros, not a separate
   template. */
.bio-hero{position:relative; background:var(--off-white); overflow:hidden;}
.bio-hero .wrap{
  padding-top:170px;
  display:grid; grid-template-columns:1.1fr 1fr; align-items:end; gap:40px;
}
.bio-back{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--ff-mono); font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--silver-3); margin-bottom:28px; transition:color .2s ease;
}
.bio-back:hover{color:var(--orange);}
.bio-back svg{width:12px; height:12px;}
.bio-hero-copy{padding-bottom:64px;}
.bio-hero-copy h1{font-size:clamp(34px,4.4vw,54px); color:var(--ink); line-height:1.05; margin-bottom:10px;}
.bio-role{display:block; font-family:var(--ff-body); font-size:19px; color:var(--silver-3);}
.bio-hero-photo{display:flex; justify-content:center;}
.bio-hero-photo img{
  display:block; width:auto; height:auto; max-width:100%; max-height:560px;
  filter:grayscale(1) contrast(1.05);
}
.bio-hero-photo img.is-broken{display:none;}

/* black vignette around a portrait — opt-in per photo (currently only
   Javier's) by adding .has-vignette to the photo's wrapper. On the bio
   page the img sits in a shrink-wrapped frame so the overlay hugs the
   photo itself, not the whole column. */
.bio-photo-frame{position:relative; display:inline-block; line-height:0; max-width:100%;}
.has-vignette::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:1;
  background:radial-gradient(ellipse at 50% 40%, transparent 32%, rgba(0,0,0,.5) 55%, rgba(0,0,0,.85) 75%, #000 92%);
}
.bio-body{background:var(--white); padding:80px 0 110px;}
.bio-body .wrap{display:grid; grid-template-columns:1fr 1fr; gap:60px;}
.bio-body p{font-size:16px; line-height:1.75; color:var(--silver-3); margin:0;}
@media (max-width:900px){
  .bio-hero .wrap{grid-template-columns:1fr; padding-top:150px;}
  .bio-hero-copy{padding-bottom:32px;}
  .bio-hero-photo img{max-height:400px;}
  .bio-body .wrap{grid-template-columns:1fr; gap:20px;}
  .bio-body{padding:56px 0 70px;}
}
@media (max-width:600px){
  .bio-hero .wrap{padding-top:130px;}
}

/* ---- DECK — the three areas, each its own full-width row so the
   alternating white/paper background can bleed edge to edge. Position
   never alternates (panel always left, copy always right on desktop) even
   though the background does — the dark "console" panel is the constant
   that ties the three together, not the page background around it. */
.nos-row{position:relative; background:var(--white); overflow:hidden;}

.nos-row-grid{
  position:relative; z-index:1;
  display:grid; grid-template-columns:.85fr 1.15fr; gap:70px; align-items:center;
  padding:90px 0;
}
/* Torre de Control — the one area singled out for a black background,
   same HUD grid/grain treatment as the hero and CTA so it reads as a live
   feed rather than just an inverted color scheme */
.nos-row--dark{background:var(--black);}
.nos-row--dark .nos-row-copy h2{color:#fff;}
.nos-row--dark .nos-row-dek{color:var(--silver-1);}
.nos-row--dark .nos-row-copy p{color:var(--silver-2);}

.nos-row-copy h2{margin-top:8px; max-width:520px; color:var(--ink);}
.nos-row-copy .eyebrow{color:var(--orange);}
.nos-row-dek{
  font-family:var(--ff-body); font-style:italic; font-weight:600; font-size:18px;
  color:var(--ink); line-height:1.4; margin:18px 0 22px;
}
.nos-row-copy p{font-size:15px; line-height:1.75; color:var(--silver-3); max-width:560px; margin-bottom:16px;}
.nos-row-copy p:last-of-type{margin-bottom:0;}

/* ---- CONSOLE PANEL — now a real photo underneath, with the same loved
   scanner HUD (rings, scanline sweep, live-readout strip) layered on top
   as a semi-transparent overlay instead of standing in for the image ---- */
.nos-panel{
  position:relative; aspect-ratio:4/5; border-radius:20px; overflow:hidden;
  background:#0a0a0b;
  box-shadow:0 40px 80px rgba(0,0,0,.4);
  border:1px solid rgba(255,255,255,.08);
  transition:transform .5s cubic-bezier(.16,1,.3,1), box-shadow .5s cubic-bezier(.16,1,.3,1);
}
.nos-panel:hover{
  transform:translateY(-8px);
  box-shadow:0 50px 90px rgba(0,0,0,.45);
}
@media (prefers-reduced-motion: reduce){
  .nos-panel{transition:none;}
  .nos-panel:hover{transform:none;}
}
.nos-panel-photo{position:absolute; inset:0; z-index:0; width:100%; height:100%; object-fit:cover; filter:brightness(1.2) saturate(1.05);}
.nos-panel-tint{
  position:absolute; inset:0; z-index:1;
  background:
    radial-gradient(ellipse 60% 55% at 75% 20%, rgba(232,119,34,.14), transparent 60%),
    linear-gradient(200deg, rgba(10,10,11,.05) 0%, rgba(6,6,7,.32) 100%);
}
.nos-panel-num{
  position:absolute; left:22px; top:20px; z-index:3;
  font-family:var(--ff-mono); font-size:12.5px; letter-spacing:.08em; color:var(--silver-1);
  text-shadow:0 1px 4px rgba(0,0,0,.6);
}
.nos-panel-scan{
  position:absolute; left:0; right:0; height:120px; z-index:2; pointer-events:none;
  background:linear-gradient(180deg, transparent, rgba(200,205,212,.28) 48%, rgba(228,229,231,.4) 50%, rgba(200,205,212,.28) 52%, transparent);
  animation:nosScan 5s ease-in-out infinite;
}
@keyframes nosScan{ 0%{top:-25%;} 50%{top:100%;} 100%{top:-25%;} }
@media (prefers-reduced-motion: reduce){ .nos-panel-scan{animation:none; display:none;} }
.nos-panel-readout{
  position:absolute; left:0; right:0; bottom:0; z-index:3;
  display:flex; flex-direction:column; gap:6px;
  padding:18px 22px; background:linear-gradient(0deg, rgba(0,0,0,.8) 0%, transparent 100%);
}
.nos-panel-readout span{
  font-family:var(--ff-mono); font-size:10.5px; letter-spacing:.05em; color:var(--silver-1);
  display:flex; align-items:center; gap:8px;
}
.nos-panel-readout span::before{content:''; width:5px; height:5px; border-radius:50%; background:var(--orange); flex-shrink:0;}

@media (max-width:980px){
  .nos-row-grid{grid-template-columns:1fr; gap:36px; padding:56px 0;}
  .nos-panel{aspect-ratio:16/9;}
  .nos-row-copy h2, .nos-row-copy p{max-width:none;}
}
@media (max-width:600px){
  .nos-hero{padding:140px 0 60px;}
}

/* ECOSISTEMA TECNOLÓGICO — estilos del diagrama orbital
   Concepto, diseño y desarrollo: Rodolfo Zavala
   Registro de autoría: by Rodolfo Zavala · 2026
   Al reutilizar o modificar estos estilos, conserve este aviso. */
/* ---- ECOSISTEMA TECNOLÓGICO — radial orbit diagram ----
   16 nodes placed on a circle around a central product shot, connected by
   thin radial "spoke" lines and enclosed by a dashed track — the whole
   thing is positioned with pure CSS (no JS trig): each .eco-node is
   rotated by its own share of 360°/var(--n), then .eco-node-content
   counter-rotates by the same amount so its badge + label always render
   upright regardless of where they sit on the ring. Dark register (this
   section breaks from the light .nos-row cadence around it) so the glow
   effects actually read. */
/* the base .section rule (styles.css) gives every section a flat 130px
   top/bottom — fine for a section that's mostly copy, but this one is
   almost entirely the ring diagram itself, so that padding plus the head's
   own 64px margin-bottom added up to a lot of dead black space above and
   below content that's already visually dense on its own. */
.section#ecosistema{background:var(--ink); color:#fff; padding:70px 0 60px;}
.section#ecosistema h2{color:#fff; font-size:clamp(36px, 5.2vw, 66px);}
.section#ecosistema .section-head{margin-bottom:10px;}
/* the section's own name now carries the big headline (h2, above); this
   is the descriptive line that used to be the headline itself — demoted
   to a smaller supporting dek and pulled in tight under the title so it
   reads as the lead-in to the ring diagram right below it, not a second
   competing heading. */
.eco-lede{
  color:var(--silver-2); font-size:18px; line-height:1.6;
  max-width:560px; margin:0 0 10px;
}

/* title + dek beside the ring instead of stacked above it. The ring's own
   overlap-safety math has a hard floor (--radius can't go below 342px
   without category 2's tightest-packed pair touching, and the badges
   themselves need real room past that radius too) — so the breakpoint
   and column width below are chosen as the narrowest combination where
   the right column still measures a safe ~800px+ even at its tightest
   (.wrap caps at var(--container), 1240px, so above ~1240px viewport the
   available width plateaus rather than keeps growing — that's why one
   rule comfortably covers everything from this breakpoint on up).
   Below this width the original stacked, centered layout stays exactly
   as it was, same as it already does below 1100px for the mobile grid —
   there just isn't a safe way to fit the ring's floor size next to a
   text column any narrower than this. */
@media (min-width:1200px){
  .eco-layout{display:grid; grid-template-columns:280px 1fr; align-items:center; gap:40px;}
  /* the section's own h2 size (bumped up to a 66px ceiling for the
     stacked layout, where it has the full wrap's width to spread across)
     is sized off vw, not this 280px column — left alone here it would
     wrap "ECOSISTEMA"/"TECNOLÓGICO" onto three cramped lines. Capped
     lower just in this column layout so it comfortably breaks into two. */
  .section#ecosistema h2{font-size:clamp(36px, 3.6vw, 56px); overflow-wrap:break-word;}
  .eco-lede{margin:0; max-width:none;}
  /* container query context: lets the ring below size itself off its OWN
     column's width (cqw) instead of the full viewport (vw) — needed now
     that the column is narrower than the viewport and, past ~1240px
     viewport, a fixed width rather than a fraction of it. */
  .eco-orbit-col{container-type:inline-size;}
  .eco-orbit{margin:0; --radius:clamp(342px, 45cqw, 387px);}
  .eco-orbit-core{width:clamp(99px, 18cqw, 153px); height:clamp(99px, 18cqw, 153px);}
  .eco-core-card{width:clamp(207px, 35cqw, 297px); height:clamp(207px, 35cqw, 297px);}
}

.eco-orbit{
  /* pie-chart layout: the circle is split into three EQUAL 120° wedges
     (see .eco-orbit-pie below), one per category, and every node's angle
     is now an explicit --angle set per node in the HTML (evenly spaced
     within its own category's wedge) instead of the old uniform
     360°/15 spacing. Category 2 has 7 items packed into a single 120°
     wedge — only ~17° between neighbors, the tightest spacing this
     diagram has needed yet — so the radius floor is bigger than any
     previous pass to keep even that tightest pair clear of each other. */
  --radius:clamp(342px, 21.6vw, 387px);
  position:relative; width:100%; max-width:990px; aspect-ratio:1/1;
  margin:40px auto 0;
}

/* the pie itself: a conic-gradient tinted wedge per category (very faint —
   just enough to read as "three sections"), plus three straight dividers
   from the center out to the ring's edge at each wedge seam. conic-gradient's
   own 0° is "up" while .eco-node's rotate()-based 0° is "right" (a 90°
   offset between the two angle systems) — the gradient's 0/120/240deg
   stops below line up with the actual node wedges (currently starting at
   node-angle 270°/30°/150° — category 2's wedge centered on the bottom —
   see the --angle values in the HTML) precisely because of that offset;
   if the wedge start angles in the HTML ever change, these three stops
   need to stay at (new node-start + 90°) each, not just copy the raw
   node angle. */
/* registered (not just declared) so the browser treats each as a real
   <color> it can interpolate frame-by-frame — a plain custom property
   swaps instantly with no way to transition, this is what makes the
   conic-gradient below actually fade smoothly instead of snapping. */
@property --cat1-tint{syntax:'<color>'; inherits:true; initial-value:rgba(140,142,148,.07);}
@property --cat2-tint{syntax:'<color>'; inherits:true; initial-value:rgba(230,232,236,.05);}
@property --cat3-tint{syntax:'<color>'; inherits:true; initial-value:rgba(90,92,97,.05);}

/* one tiny tiled SVG pattern per category, painted behind .eco-orbit-pie's
   tint and clipped to that same category's 120° wedge via a conic-gradient
   mask — data-URIs, not image requests, so this costs nothing to load.
   Wedge boundaries (0/120/240deg from 0deg) match .eco-orbit-pie exactly;
   if those ever move, these three masks need to move with them. */
.eco-orbit-texture{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:calc(var(--radius) * 2.1); height:calc(var(--radius) * 2.1);
  border-radius:50%; z-index:0; pointer-events:none;
  background-repeat:repeat;
}
/* Tecnología — fine dot grid */
.eco-orbit-texture--1{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16'><circle cx='2' cy='2' r='1' fill='rgba(140,142,148,0.28)'/></svg>");
  background-size:16px 16px;
  -webkit-mask-image:conic-gradient(from 0deg, #000 0deg 120deg, transparent 120deg 360deg);
  mask-image:conic-gradient(from 0deg, #000 0deg 120deg, transparent 120deg 360deg);
}
/* Blindaje — tiny hexagon outlines on a grid, same weight/scale as the
   Tecnología dots and Soporte crosshatch (a thin mark, not a filled cell) */
.eco-orbit-texture--2{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18'><polygon points='9,4 12.5,6 12.5,10 9,12 5.5,10 5.5,6' fill='none' stroke='rgba(230,232,236,0.14)' stroke-width='0.75'/></svg>");
  background-size:18px 18px;
  -webkit-mask-image:conic-gradient(from 0deg, transparent 0deg 120deg, #000 120deg 240deg, transparent 240deg 360deg);
  mask-image:conic-gradient(from 0deg, transparent 0deg 120deg, #000 120deg 240deg, transparent 240deg 360deg);
}
/* Soporte — subtle crosshatch grid */
.eco-orbit-texture--3{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18'><path d='M0 0H18M0 0V18' stroke='rgba(90,92,97,0.25)' stroke-width='1'/></svg>");
  background-size:18px 18px;
  -webkit-mask-image:conic-gradient(from 0deg, transparent 0deg 240deg, #000 240deg 360deg);
  mask-image:conic-gradient(from 0deg, transparent 0deg 240deg, #000 240deg 360deg);
}
.eco-orbit-pie{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:calc(var(--radius) * 2.1); height:calc(var(--radius) * 2.1);
  border-radius:50%; z-index:0; pointer-events:none;
  /* each third's tint is its own (registered, animatable) custom
     property rather than a literal color in the gradient stop — lets
     hovering that third — see initEcoWedgeHover in nosotros.js, which
     tracks the cursor's angle from center, not any one element — fade
     just that one wedge brighter without needing three separate stacked
     elements just to target a third of a conic-gradient. */
  background:conic-gradient(
    from 0deg,
    var(--cat1-tint) 0deg 120deg,
    var(--cat2-tint) 120deg 240deg,
    var(--cat3-tint) 240deg 360deg
  );
  transition:--cat1-tint .3s ease, --cat2-tint .3s ease, --cat3-tint .3s ease;
}
.eco-orbit-pie.is-hover-cat1{--cat1-tint:rgba(140,142,148,.2);}
.eco-orbit-pie.is-hover-cat2{--cat2-tint:rgba(230,232,236,.1);}
.eco-orbit-pie.is-hover-cat3{--cat3-tint:rgba(90,92,97,.2);}
@media (prefers-reduced-motion: reduce){
  .eco-orbit-pie{transition:none;}
}
.eco-orbit-pie-line{
  position:absolute; top:50%; left:50%; z-index:0; pointer-events:none;
  width:calc(var(--radius) * 1.05); height:1.5px;
  background:linear-gradient(90deg, rgba(255,255,255,.45), rgba(255,255,255,0) 92%);
  transform-origin:0 0;
  transform:rotate(var(--angle, 0deg));
}

/* "CAT 1/2/3" curving in a small ring tight around the center package —
   in the open gap between the core (which tops out around .2× radius)
   and category 1's own innermost nodes (at .5× radius) — centered on
   each wedge, curving outward like text on a badge. Each letter is its
   own tiny anchor placed at --char-angle (same rotate-then-translate
   placement trick used for the nodes) and then rotated again by
   (--char-tilt - --char-angle) so the glyph itself leans to match the
   circle's tangent at that point instead of staying flat — that's what
   makes the word read as curved text rather than straight text that
   merely sits on an arc. Category 2 sits at the BOTTOM of the ring,
   where a top-arc tilt formula would render upside down, so its tilt
   values are computed the opposite way (see the inline --char-tilt
   values in the HTML) — this file doesn't need to know which formula
   was used per label, it just applies whatever tilt it's given. */
.eco-cat-label{position:absolute; inset:0; z-index:1; pointer-events:none;}
.eco-cat-label span{
  position:absolute; top:50%; left:50%;
  /* JetBrains Mono is only loaded at 400/500/600 by default (see the
     Google Fonts <link> in <head>) — this was declared 800 the whole
     time but silently fell back to whatever weight the browser actually
     had, never rendering truly bold. 700/800 are now loaded too, so this
     finally renders as real bold instead of a fake one. */
  font-family:var(--ff-mono); font-size:19px; font-weight:800; letter-spacing:0;
  text-shadow:0 1px 3px rgba(0,0,0,.85), 0 0 10px rgba(0,0,0,.6);
  /* pushed out from .32 (a tight ring hugging the center package) to
     1.06 — snug against the outermost badges' own reach (their
     tier-radius plus their own visual radius already lands right around
     1.0× on its own, by design) instead of the wider gap a bigger
     multiplier leaves, so the words sit right at the rim, not floating
     well past it */
  transform:
    rotate(var(--char-angle))
    translateX(calc(var(--radius) * var(--label-radius-mult, 1.06)))
    rotate(calc(var(--char-tilt) - var(--char-angle)))
    translate(-50%, -50%);
}
.eco-cat-label--1 span{color:rgba(140,142,148,.95);}
.eco-cat-label--2 span{color:rgba(255,255,255,.97);}
.eco-cat-label--3 span{color:rgba(90,92,97,.92);}

/* center piece — product shot with breathing glow rings behind it, same
   slow ease-in-out "breathing" language used elsewhere on the site (never
   a hard on/off flicker) */
.eco-orbit-core{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:clamp(99px, 11.7vw, 153px); height:clamp(99px, 11.7vw, 153px);
  display:flex; align-items:center; justify-content:center; z-index:2;
  /* purely decorative (nothing inside it — the box photo, the breathing
     rings, the info card — is ever itself clickable), but it sat above
     the nodes in stacking order. The inner tier's badges now reach in
     close enough to the core that their (bigger, 150px) invisible hit
     area geometrically overlapped this box — with pointer-events left on,
     the core "stole" those clicks/hovers before they ever reached the
     badge underneath. This lets everything pass straight through it. */
  pointer-events:none;
}
/* the wrap exists only to clip the light-sweep glint below to the logo's
   own footprint — .eco-orbit-core itself stays overflow:visible (the
   breathing rings and open-state card both reach past this box) */
.eco-core-logo-wrap{
  position:relative; z-index:1; width:78%; height:78%; overflow:hidden;
  margin-left:12px;
  opacity:1; transform:scale(1);
  transition:opacity .5s cubic-bezier(.16,1,.3,1), transform .5s cubic-bezier(.16,1,.3,1);
}
.eco-orbit-core.is-open .eco-core-logo-wrap{opacity:0; transform:scale(.85);}
.eco-core-img{
  position:relative; z-index:1; width:100%; height:100%; object-fit:contain;
  display:block;
}
/* a soft diagonal glint sweeps across the mark every few seconds — same
   "never a hard flicker, always ease" language as the breathing rings
   next to it, just as a one-shot pass instead of a loop-in-place pulse.
   Sits above the logo (z-index:2) but below the info card (z-index:3).
   The gradient itself covers the whole square, but a mask built from the
   very same PNG (its alpha channel) punches it down to only the K's own
   opaque pixels — so the sweep reads as light crossing the mark, not a
   glowing box around it, with none of it visible over the transparent
   margin the source square has around the glyph. */
.eco-core-logo-wrap::after{
  content:''; position:absolute; inset:0;
  /* same gradient/timing/blend as .strat-col--adv::after (the Advantage
     card's own shine, in styles.css) — a continuous back-and-forth
     sweep, not a pause-then-single-pass, so this reads as the same
     effect rather than a different one that just happens to live on the
     same K mark */
  background-image:linear-gradient(100deg, transparent 30%, rgba(255,255,255,.45) 46%, transparent 62%);
  background-size:260% 100%;
  background-position:-60% 0;
  mix-blend-mode:overlay;
  -webkit-mask-image:url('assets/img/imagotipo-konnen.webp');
  mask-image:url('assets/img/imagotipo-konnen.webp');
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  z-index:2; pointer-events:none;
  animation:ecoLogoSweep 4s ease-in-out infinite;
}
@keyframes ecoLogoSweep{
  0%, 100%{ background-position:-60% 0; }
  50%{ background-position:140% 0; }
}

/* the info card — dead center of the whole diagram, right over the box
   photo (which fades out to make room for it). Square with softened
   corners, not round like the badges, so it reads as its own distinct
   surface rather than just another (bigger) node. */
.eco-core-card{
  position:absolute; top:50%; left:50%; z-index:3;
  transform:translate(-50%,-50%) scale(.85);
  width:clamp(207px, 20.7vw, 297px); height:clamp(207px, 20.7vw, 297px);
  border-radius:28px; border:1px solid rgba(255,255,255,.14);
  background:rgba(8,8,9,.55);
  backdrop-filter:blur(20px) saturate(150%); -webkit-backdrop-filter:blur(20px) saturate(150%);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center; padding:12%;
  opacity:0; pointer-events:none;
  transition:opacity .5s cubic-bezier(.16,1,.3,1), transform .5s cubic-bezier(.16,1,.3,1);
}
.eco-orbit-core.is-open .eco-core-card{
  opacity:1; transform:translate(-50%,-50%) scale(1); pointer-events:auto;
}
.eco-core-card-tag{
  display:block; height:25px; width:auto; margin:0 auto 13px;
  object-fit:contain; opacity:.9;
}
.eco-core-card-title{
  font-family:var(--ff-display); font-size:20.5px; letter-spacing:.01em;
  text-transform:uppercase; color:#fff; line-height:1.18; font-weight:700; margin-bottom:11px;
}
.eco-core-card-desc{
  display:-webkit-box; -webkit-line-clamp:5; -webkit-box-orient:vertical; overflow:hidden;
  font-family:var(--ff-body); font-size:13.5px; line-height:1.5; color:var(--silver-1);
}
.eco-orbit-list{position:absolute; inset:0; margin:0; padding:0; list-style:none;}
/* the orbit trick: rotate the anchor out to its angle, then translate
   along its own (now-rotated) local x-axis by --radius — that's what
   places each node without any per-item trig in the CSS itself. --angle
   is now an explicit value set per node in the HTML (see the pie-chart
   comment above) rather than a uniform 360°/15 share, since each
   category's nodes need to be evenly spread across just their own 120°
   third, not the full circle. */
.eco-node{
  position:absolute; top:50%; left:50%; width:0; height:0;
  z-index:1;
  animation:ecoNodeBreathe var(--breathe-duration, 7s) ease-in-out infinite;
  animation-delay:calc(var(--i, 0) * -0.5s);
}
.eco-node.is-open{z-index:6;}
.eco-node.is-hovered{z-index:5;}
/* subtle radial "breathing" — every node drifts a few px closer to and
   farther from the core, forever, on top of its own float bob (a
   perpendicular motion, so the two combine into an organic drift rather
   than cancelling out). translateX here runs along the LOCAL axis this
   element's own rotate() already established, so positive values move
   further OUT along that exact angle — no separate angle math needed.
   Kept smaller (4-5px) than the float bob and on a deliberately
   different period per category (not a clean multiple of the float
   durations) so two neighboring nodes are never at both animations'
   closest-approach point at once. */
@keyframes ecoNodeBreathe{
  0%, 100%{ transform:rotate(var(--angle, 0deg)) translateX(0); }
  50%{ transform:rotate(var(--angle, 0deg)) translateX(var(--breathe-x, 4px)); }
}
.eco-node--cat1{ --breathe-x:4px; --breathe-duration:6.2s; }
.eco-node--cat2{ --breathe-x:4px; --breathe-duration:7.4s; }
.eco-node--cat3{ --breathe-x:5px; --breathe-duration:7.8s; }
/* each category sits at its own distance from the core — category 1 (3
   nodes, all on one arc, 40° apart) has the most breathing room per
   node, so it can sit closest in. Categories 2 and 3 both split into two
   rows instead of one shared arc (see below). */
.eco-node--cat1{--tier-radius:calc(var(--radius) * .65);}
.eco-node--cat2{--tier-radius:calc(var(--radius) * .88);}
.eco-node--cat3{--tier-radius:calc(var(--radius) * .85);}
/* category 2's seven nodes, and category 3's five, no longer share one
   single arc each — split into an inner row (closer to the core) and an
   outer row (further out), with the angles interleaved between the two
   rows (an inner node sits exactly between two outer ones) instead of
   stacked radially under one another. .eco-node--inner overrides both
   categories' own default down to a shared .63× UNLESS a category-
   specific override below applies. Radii were solved together with each
   category's own interleave angle so every row, and the gap between the
   two rows, clears the badges' combined 100px width with real margin at
   the ring's floor size. */
.eco-node--inner{--tier-radius:calc(var(--radius) * .63);}
.eco-node--cat3.eco-node--outer{--tier-radius:calc(var(--radius) * .85);}
/* category 2 pulled in closer to the core on request — both its rows
   (not just one) moved inward together, re-solved so the tightest gap
   in the whole diagram (this category's own cross-row pairs, 15° apart)
   still clears with real margin at the ring's floor size. */
.eco-node--cat2.eco-node--inner{--tier-radius:calc(var(--radius) * .58);}
/* gentle floating bob instead — each node's badge drifts a few px up and
   down in place, forever, like it's suspended rather than pinned. Every
   node gets a different phase (via a negative delay keyed to its own --i,
   so it starts partway through the cycle instead of all 15 launching in
   lockstep) and a slightly different duration per category, so
   neighboring badges are never rising/falling in sync — combined with
   the spacing above, that's what keeps any two badges from ever touching. */
@keyframes ecoNodeFloat{
  0%, 100%{ transform:translateY(0) rotate(calc(-1 * var(--angle, 0deg))); }
  50%{ transform:translateY(var(--float-y, -6px)) rotate(calc(-1 * var(--angle, 0deg))); }
}
.eco-node-content{ animation:ecoNodeFloat var(--float-duration, 5s) ease-in-out infinite; animation-delay:calc(var(--i, 0) * -0.6s); }
.eco-node--cat1 .eco-node-content{ --float-y:-5px; --float-duration:4.4s; }
.eco-node--cat2 .eco-node-content{ --float-y:-6px; --float-duration:5s; }
.eco-node--cat3 .eco-node-content{ --float-y:-7px; --float-duration:5.6s; }
/* hovering a badge pauses its own float (so it holds still to read/click)
   and grows it slightly; every other node dims and shrinks a touch to
   make the hovered one read as focused — a lighter version of the
   click-to-open grow/shrink below, triggered by JS toggling these classes
   on mouseenter/mouseleave (see nosotros.js) */
.eco-node.is-hovered .eco-node-content{animation-play-state:paused;}
.eco-node.is-hovered .eco-node-badge{transform:translate(-50%,-50%) scale(1.18);}
.eco-orbit.has-hover .eco-node:not(.is-hovered):not(.is-open) .eco-node-badge{
  transform:translate(-50%,-50%) scale(.7); opacity:.4;
}

/* the radial lines get the exact same split treatment as the labels, for
   the opposite reason: a spoke used to live inside its own .eco-node, so
   opening that node (z-index:6, to lift its photo above every other
   badge) dragged the spoke up with it — cutting the orange line right
   across the center card once it appeared. Pulling every spoke into its
   own list, painted before the core and every badge, keeps them behind
   the core art and every card at all times, open or not, with nothing
   left to elevate them by mistake. */
.eco-orbit-spokes{position:absolute; inset:0; margin:0; padding:0; list-style:none; z-index:0; pointer-events:none;}
.eco-spoke-node{
  position:absolute; top:50%; left:50%; width:0; height:0;
  animation:ecoSpokeBreathe var(--breathe-duration, 7s) ease-in-out infinite;
  animation-delay:calc(var(--i, 0) * -0.5s);
}
/* stretches the connecting line by the same real distance its node
   breathes outward, so the line's tip always still meets the badge
   instead of falling short or overshooting — scaleX from this element's
   own (zero-size, so effectively a point) origin is exactly the ring's
   center, matching where the line itself is anchored. Dividing a length
   by a length is a valid unitless ratio in calc(), which is what scaleX
   needs. Same --i-keyed delay as .eco-node above keeps this in lockstep
   with its own badge, not just a matching duration. */
@keyframes ecoSpokeBreathe{
  0%, 100%{ transform:rotate(var(--angle, 0deg)) scaleX(1); }
  50%{ transform:rotate(var(--angle, 0deg)) scaleX(calc(1 + var(--breathe-x, 4px) / var(--tier-radius, var(--radius)))); }
}
/* --breathe-x/--breathe-duration come from the same .eco-node--cat1/2/3
   rules below (every spoke also carries that category class) — no need
   to redeclare them here, just consume whatever the node's own copy is. */
.eco-node-spoke{
  position:absolute; top:0; left:0; width:var(--tier-radius, var(--radius)); height:1px;
  transform-origin:0 0;
  background:linear-gradient(90deg, var(--cat-color, rgba(232,119,34,.5)), rgba(232,119,34,0) 88%);
  transition:height .3s ease, background .3s ease;
}
/* the selected node's own line: brighter and thicker at rest, plus a
   slow breathing glow (same ease-in-out "never a hard flicker" language
   as the core rings) and a small streak of light that travels from the
   center out to the badge on a loop — reads as the line actively
   "pointing at" whichever circle is open, not just a static highlight */
.eco-spoke-node.is-open .eco-node-spoke{
  height:2px;
  background:linear-gradient(90deg, rgba(232,119,34,1), rgba(232,119,34,.25) 85%);
  animation:ecoSpokeGlow 2.2s ease-in-out infinite;
}
@keyframes ecoSpokeGlow{
  0%, 100%{ box-shadow:0 0 6px 0 rgba(232,119,34,.3); }
  50%{ box-shadow:0 0 18px 2px rgba(232,119,34,.65); }
}
.eco-node-spoke::after{
  content:''; position:absolute; top:50%; left:-4px;
  width:30px; height:3px; margin-top:-1.5px; border-radius:3px;
  background:linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,214,170,.95) 50%, rgba(255,255,255,0) 100%);
  opacity:0; pointer-events:none;
  filter:drop-shadow(0 0 6px rgba(232,119,34,.9));
}
.eco-spoke-node.is-open .eco-node-spoke::after{
  animation:ecoSpokeTravel 1.5s ease-in-out infinite;
}
@keyframes ecoSpokeTravel{
  0%{ left:-4px; opacity:0; }
  12%{ opacity:1; }
  82%{ opacity:1; }
  100%{ left:calc(var(--tier-radius, var(--radius)) - 30px); opacity:0; }
}
@media (prefers-reduced-motion: reduce){
  .eco-spoke-node.is-open .eco-node-spoke{animation:none;}
  .eco-spoke-node.is-open .eco-node-spoke::after{animation:none; opacity:0;}
  .eco-node, .eco-spoke-node, .eco-node-content{animation:none !important;}
}
/* content is just a rotation anchor sitting exactly at the spoke's tip —
   the badge is pinned to that exact point (translate -50%/-50%) so it
   lands precisely on the ring regardless of anything else on the page.
   Counter-rotated by the same fixed angle as its .eco-node so the badge
   and its number always render upright; the ecoNodeFloat animation above
   (applied to this same element) carries that same rotate through every
   keyframe, so floating never un-levels the badge. */
.eco-node-content{
  position:absolute; top:0; left:var(--tier-radius, var(--radius));
}
/* the button itself is now a bigger, invisible hit area (150px) than the
   circle it shows (100px) — hovering/clicking anywhere in that extra ring
   around the visible badge still counts, instead of only the exact 100px
   circle. Flex-centers the visual inside it, so the visible circle stays
   pinned to the exact same point on the ring as before; only the
   clickable/hoverable footprint grew. */
.eco-node-badge{
  all:unset; box-sizing:border-box; cursor:pointer;
  position:absolute; top:0; left:0; transform:translate(-50%,-50%) scale(1);
  width:135px; height:135px;
  display:flex; align-items:center; justify-content:center;
  transition:transform .5s cubic-bezier(.16,1,.3,1), opacity .5s ease;
}
/* three categories (see the --cat1/2/3 classes on .eco-node/.eco-spoke-node
   in the HTML) get three tones of gray — bright near-white for the
   active-security hardware group (Blindaje), medium gray for the core
   data/tech group (Tecnología), dim/darker gray for the management/support
   group (Soporte) — so the 15 nodes read as three visible clusters using
   only grayscale, the brand orange reserved for the section's own accents.
   Consumed by the badge ring, its glow, the number chip's border and the
   connecting spoke line. */
.eco-node--cat1{ --cat-color:rgba(140,142,148,.7); --cat-glow-1:rgba(140,142,148,.09); --cat-glow-2:rgba(140,142,148,.3); }
.eco-node--cat2{ --cat-color:rgba(230,232,236,.75); --cat-glow-1:rgba(230,232,236,.1); --cat-glow-2:rgba(230,232,236,.24); }
.eco-node--cat3{ --cat-color:rgba(90,92,97,.6); --cat-glow-1:rgba(90,92,97,.08); --cat-glow-2:rgba(90,92,97,.22); }
.eco-node-badge-visual{
  position:relative; width:90px; height:90px; border-radius:50%; overflow:hidden;
  border:2px solid var(--cat-color, rgba(232,119,34,.4));
  box-shadow:0 0 0 4px var(--cat-glow-1, rgba(232,119,34,.07)), 0 0 22px var(--cat-glow-2, rgba(232,119,34,.22));
  transition:border-color .3s ease, box-shadow .3s ease;
}
.eco-node-badge-bg{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:center;
}
.eco-node-badge:hover, .eco-node-badge:focus-visible{transform:translate(-50%,-50%) scale(1.08);}
.eco-node-badge:hover .eco-node-badge-visual, .eco-node-badge:focus-visible .eco-node-badge-visual{
  border-color:var(--orange);
  box-shadow:0 0 0 6px rgba(232,119,34,.14), 0 0 30px rgba(232,119,34,.4);
}

/* floating title tooltip — reads the badge's own data-title (the same
   attribute the center card already reads on click, and the same one
   i18n.js rewrites on a language switch), so it needs no markup or JS of
   its own and stays correct in English automatically. Sits above the
   badge, anchored to the invisible 150px hit-area so it's centered on the
   visible circle regardless of the ring's rotate/counter-rotate math.
   Shown on hover (.is-hovered, toggled by nosotros.js) and on keyboard
   focus, so it works for pointer and keyboard users alike. */
.eco-node-badge::after{
  content:attr(data-title);
  position:absolute;
  bottom:calc(100% - 12.5px); left:50%;
  transform:translate(-50%, 8px);
  padding:8px 16px;
  background:rgba(10,10,12,.94);
  border:1px solid var(--cat-color, rgba(232,119,34,.5));
  border-radius:8px;
  color:#fff;
  font-family:var(--ff-mono); font-size:10.5px; font-weight:700;
  letter-spacing:.13em; text-transform:uppercase; white-space:nowrap;
  box-shadow:0 14px 34px rgba(0,0,0,.5), 0 0 20px var(--cat-glow-2, rgba(232,119,34,.25));
  opacity:0; pointer-events:none;
  transition:opacity .25s ease, transform .25s ease;
  z-index:10;
}
.eco-node-badge::before{
  content:''; position:absolute;
  bottom:calc(100% - 19.5px); left:50%;
  transform:translate(-50%, 8px);
  width:0; height:0;
  border:6px solid transparent; border-top-color:rgba(10,10,12,.94);
  opacity:0; pointer-events:none;
  transition:opacity .25s ease, transform .25s ease;
  z-index:10;
}
.eco-node.is-hovered .eco-node-badge::after, .eco-node-badge:focus-visible::after,
.eco-node.is-hovered .eco-node-badge::before, .eco-node-badge:focus-visible::before{
  opacity:1; transform:translate(-50%, 0);
}
.eco-node.is-open .eco-node-badge::after, .eco-node.is-open .eco-node-badge::before{opacity:0;}
/* selected node: the badge grows and sits above every other one; every
   sibling badge shrinks and dims slightly to make room for it — the same
   grow/shrink relationship the old rectangular gallery had between its
   cards, just applied to circles now */
.eco-node.is-open .eco-node-badge{transform:translate(-50%,-50%) scale(1.85);}
.eco-node.is-open .eco-node-badge-visual{
  border-color:var(--orange);
  box-shadow:0 0 0 8px rgba(232,119,34,.16), 0 0 46px rgba(232,119,34,.5);
}
.eco-orbit.has-open .eco-node:not(.is-open) .eco-node-badge{
  transform:translate(-50%,-50%) scale(.8);
  opacity:.5;
}

/* the badge stays pure image — the little number chip that used to ride
   its bottom-right edge (01-15) has been dropped entirely; the title
   tooltip on hover now does that job instead. Kept as a hidden element
   rather than removed from the markup so it can come back with a single
   rule if ever needed. */
.eco-node-num{display:none;}

/* below 1100px, the ring keeps the exact same layout as desktop — same
   pie wedges, category labels, spokes, breathing/floating nodes — just
   scaled down as one similarity transform. --radius gets a much lower
   floor (115px vs desktop's 342px) and, unlike desktop, the badges
   themselves now scale WITH it (calc(), not a fixed px), because a fixed
   90px badge is exactly what desktop's 342px floor was solved around —
   shrink the ring alone and that same fixed badge would swallow its
   neighbors. Scaling both by the same factor keeps every angle's
   already-verified clearance ratio identical at any size, all the way
   down to the smallest phones. The clamp ceilings below (342px radius,
   90px/135px badge) are chosen to exactly match desktop's own floor
   values, so there's no visible jump crossing the 1100px boundary. */
@media (max-width:1100px){
  .eco-orbit{--radius:clamp(115px, 38vw, 342px);}
  .eco-orbit-core{width:calc(var(--radius) * .376); height:calc(var(--radius) * .376);}
  /* min() rather than a flat 240px so a very narrow phone (well under the
     360-430px range most phones actually ship at) can't push this wider
     than its own viewport and force a horizontal scrollbar */
  .eco-core-card{width:min(240px, 74vw); height:min(240px, 74vw);}
  /* letters would otherwise stay a flat 14.4px regardless of how small
     the ring gets — clamped down proportionally, with a floor so they
     don't disappear entirely on the smallest phones */
  .eco-cat-label span{font-size:clamp(9px, calc(var(--radius) * .042), 14.4px);}
  /* badge + its invisible hit-area, both radius-relative now — same
     90:135 (2:3) ratio desktop uses at its own floor */
  .eco-node-badge{width:calc(var(--radius) * .3947); height:calc(var(--radius) * .3947);}
  .eco-node-badge-visual{width:66.7%; height:66.7%;}
  .eco-node.is-open .eco-node-badge{transform:translate(-50%,-50%) scale(1.35);}
  .eco-orbit.has-open .eco-node:not(.is-open) .eco-node-badge{transform:translate(-50%,-50%) scale(.85);}
  /* the breathing/floating amplitudes are fixed px on desktop (safe there
     because they were verified against a fixed 342px-radius/90px-badge
     floor) — scaled down here by that exact same ratio so the wobble
     never eats a bigger slice of the (now much smaller) gap between
     neighbors than it already safely does at desktop's own floor. */
  .eco-node--cat1{--breathe-x:calc(var(--radius) * .0117);}
  .eco-node--cat2{--breathe-x:calc(var(--radius) * .0117);}
  .eco-node--cat3{--breathe-x:calc(var(--radius) * .0146);}
  .eco-node--cat1 .eco-node-content{--float-y:calc(var(--radius) * -.0146);}
  .eco-node--cat2 .eco-node-content{--float-y:calc(var(--radius) * -.0175);}
  .eco-node--cat3 .eco-node-content{--float-y:calc(var(--radius) * -.0205);}
}
@media (prefers-reduced-motion: reduce){
  .eco-core-logo-wrap::after{animation:none; display:none;}
}

/* ---- CERTIFICADO BASC ---- */
/* the one deliberately light break in this otherwise all-dark page —
   explicit white background + dark ink text, opposite of every other
   section here (which instead opt INTO white text over the page's
   default black). The logo's own card flips the other way, staying
   black so the (now transparent-background) BASC mark reads the same
   way it would on any dark surface. */
.nos-cert{background:var(--white); color:var(--ink);}
/* a touch off-white (not flat white like Certificado right above it) so
   the two light sections read as two distinct blocks instead of one
   continuous slab, without breaking from the page's light/dark rhythm */
#privacidad.nos-cert{background:var(--off-white);}
.nos-cert h2{color:var(--ink);}
.nos-cert-layout{
  display:grid; grid-template-columns:.6fr 1.4fr; gap:60px; align-items:start;
  margin-top:20px;
}
/* Política de Privacidad reuses the same accordion component as
   Certificado BASC, just without the logo/badge column beside it —
   plain full-width, capped so long paragraphs stay readable */
.nos-cert-accordion--full{max-width:820px; margin-top:20px;}
/* ...but deliberately restyled so it doesn't just read as the same
   panel repeated — a numbered legal index (CSS counters, no markup
   change) instead of a plain title list, a left accent bar that lights
   up on the open clause instead of top/bottom hairlines, and a chevron
   instead of the +/x cross (built from the same .nos-cert-plus span via
   borders, so no HTML changes needed there either — its "+" text is
   just hidden). Same JS/behavior underneath, purely a different skin. */
.nos-policy-accordion{counter-reset:policy-clause;}
.nos-policy-accordion .nos-cert-item{
  counter-increment:policy-clause;
  border-top:none; border-left:2px solid var(--line);
  padding:20px 0 20px 22px;
  transition:border-color .3s ease, background .3s ease;
}
.nos-policy-accordion .nos-cert-item:last-child{border-bottom:none;}
.nos-policy-accordion .nos-cert-item.is-open{border-left-color:var(--orange); background:var(--paper);}
.nos-policy-accordion .nos-cert-q h4{display:flex; align-items:baseline; gap:14px;}
.nos-policy-accordion .nos-cert-q h4::before{
  content:counter(policy-clause, decimal-leading-zero);
  font-family:var(--ff-mono); font-size:12px; font-weight:600; color:var(--orange);
}
.nos-policy-accordion .nos-cert-plus{
  font-size:0; width:9px; height:9px; margin-right:4px;
  border-right:1.5px solid var(--silver-3); border-bottom:1.5px solid var(--silver-3);
  transform:rotate(45deg); transition:transform .3s ease, border-color .3s ease;
}
.nos-policy-accordion .nos-cert-item.is-open .nos-cert-plus{
  transform:rotate(-135deg); border-color:var(--orange);
}
.nos-cert-badge{
  display:flex; justify-content:center; align-items:flex-start;
}
.nos-cert-badge img{
  width:100%; max-width:340px; height:auto;
  transition:filter .35s ease, transform .35s ease;
}
.nos-cert-badge img:hover{
  filter:drop-shadow(0 18px 30px rgba(0,0,0,.22));
  transform:scale(1.06);
}
/* a more deliberate "certificate reveal" than the generic fade-up every
   other [data-reveal] element gets — scales in from slightly small
   rather than just sliding up, so the badge itself feels like the
   moment being revealed instead of just another line of copy arriving.
   Same .in class/trigger as the generic version (IntersectionObserver in
   nosotros.js), just its own transform. */
.nos-cert-badge[data-reveal]{
  opacity:0; transform:scale(.72); transition:opacity .8s cubic-bezier(.16,1,.3,1), transform .8s cubic-bezier(.16,1,.3,1);
}
.nos-cert-badge[data-reveal].in{opacity:1; transform:scale(1);}
.nos-cert-item{border-top:1px solid var(--line); padding:22px 0;}
.nos-cert-item:last-child{border-bottom:1px solid var(--line);}
.nos-cert-q{display:flex; justify-content:space-between; align-items:center; gap:20px; cursor:pointer;}
.nos-cert-q h4{font-family:var(--ff-body); text-transform:none; letter-spacing:0; font-size:18px; font-weight:700; color:var(--ink);}
.nos-cert-plus{font-family:var(--ff-mono); font-size:22px; color:var(--orange); flex-shrink:0; transition:transform .25s ease;}
.nos-cert-item.is-open .nos-cert-plus{transform:rotate(45deg);}
/* max-height is set inline by JS (nosotros.js) off the inner wrapper's
   real scrollHeight rather than a guessed flat number — this accordion's
   entries range from a short 4-line stat list to a full policy paragraph
   plus five bullets, and more sections are still being added, so a fixed
   cap would either clip the long ones or leave dead space under the
   short ones. */
.nos-cert-a{max-height:0; overflow:hidden; transition:max-height .4s cubic-bezier(.4,0,.2,1);}
.nos-cert-a-inner{padding-top:16px; display:flex; flex-direction:column; gap:14px;}
.nos-cert-a-inner p{margin:0; color:var(--silver-3);}
.nos-cert-a-inner ul{display:flex; flex-direction:column; gap:10px;}
.nos-cert-a-inner li{position:relative; padding-left:20px; color:var(--silver-3); line-height:1.6;}
.nos-cert-a-inner li::before{
  content:''; position:absolute; left:0; top:10px;
  width:6px; height:6px; border-radius:50%; background:var(--orange);
}
.nos-cert-a-inner li b{color:var(--ink); font-weight:700;}
@media (max-width:900px){
  .nos-cert-layout{grid-template-columns:1fr; gap:32px;}
  .nos-cert-badge{max-width:220px; margin:0 auto;}
}

/* ---- CLOSING CTA ---- */
.nos-cta{position:relative; color:#fff; padding:120px 0; text-align:center; overflow:hidden;}
.nos-cta .wrap{position:relative; z-index:1;}
.nos-cta .eyebrow{justify-content:center; color:var(--orange);}
.nos-cta h2{color:#fff; margin-top:10px;}
.nos-cta h2 .accent{color:var(--orange);}
.nos-cta p{color:var(--silver-2); max-width:520px; margin:22px auto 34px;}
.nos-cta .nos-status{margin:0 auto 22px;}
.nos-cta .btn{margin:0 auto;}
@media (max-width:600px){ .nos-cta{padding:90px 0;} }
