/* SetFile — components.css (heredado del sitio de SetGantt)
   Buttons, nav controls, cards, placeholders, forms, FAQ accordion.
   NOTA: los bloques de microdemo/demo-modal (líneas de vídeo de producto)
   se mantienen sin usar en esta primera entrega — setfile.org no tiene ese
   componente. Se pueden retirar en una pasada de limpieza posterior. */

/* ---- Eyebrow / fine print / highlight text ---- */
.eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: var(--space-3);
}

.fine-print {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}

.subsection-heading {
  text-align: center;
  margin-top: var(--space-10);
}

.subsection-lead {
  text-align: center;
  max-width: 560px;
  margin: 0 auto var(--space-2) auto;
}

.highlight-statement {
  text-align: center;
  font-size: var(--fs-h3);
  font-weight: 700;
  color: var(--color-text-primary);
  max-width: 720px;
  margin: var(--space-8) auto;
}

.asset-caption {
  text-align: center;
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  margin-top: var(--space-3);
}

/* ---- Buttons ---- */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.85rem 1.6rem;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: var(--fs-body);
  border: 1px solid transparent;
  text-decoration: none;
  transition: background-color var(--transition-fast), border-color var(--transition-fast),
    color var(--transition-fast), transform var(--transition-fast);
}

.button:hover {
  text-decoration: none;
  transform: translateY(-1px);
}

.button--primary {
  background-color: var(--color-cta-bg);
  color: var(--color-text-on-accent);
}

.button--primary:hover {
  background-color: var(--color-cta-bg-hover);
  color: var(--color-text-on-accent);
}

.button--secondary {
  background-color: transparent;
  color: var(--color-accent);
  border-color: var(--color-accent-border);
}

.button--secondary:hover {
  background-color: var(--color-accent-soft);
  color: var(--color-accent-hover);
}

.button--ghost {
  padding: 0.6rem 1.1rem;
  font-size: var(--fs-small);
  background-color: transparent;
  color: var(--color-text-primary);
  border-color: var(--color-border-strong);
}

.button--ghost:hover {
  background-color: var(--color-surface-alt);
}

/* ---- Nav toggle (mobile menu button) ----
   Visible by default (mobile-first); hidden again at >=960px in
   responsive.css once .primary-nav is always shown as a static bar.
   Wired up by nav.js (Paso 4). Works as a real disclosure control: the
   full nav list is real markup in the DOM either way, so it stays
   reachable even if JavaScript fails to load (#10 §64, §92). */
.nav-toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 40px;
  height: 40px;
  background: none;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}

.nav-toggle__bar {
  display: block;
  height: 2px;
  background-color: var(--color-text-primary);
  border-radius: 2px;
  transition: transform var(--transition-fast), opacity var(--transition-fast);
}

/* Turn the three bars into a close (×) icon while the menu is open. */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* ---- Language switch ---- */
.lang-switch a {
  color: var(--color-text-secondary);
  font-size: var(--fs-small);
  font-weight: 600;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
}

.lang-switch a:hover {
  text-decoration: none;
  background-color: var(--color-surface-alt);
  color: var(--color-text-primary);
}

.lang-switch a[aria-current="page"] {
  color: var(--color-accent);
  background-color: var(--color-accent-soft);
}

/* ---- Theme toggle ---- */
.theme-toggle {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border-strong);
  background-color: var(--color-surface);
  position: relative;
}

.theme-toggle::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: var(--color-text-primary);
  transition: background-color var(--transition-theme);
}

[data-theme="dark"] .theme-toggle::before {
  background-color: var(--color-theme-toggle-active-dot);
  box-shadow: 0 0 0 3px var(--color-accent-soft);
}

/* ---- Asset placeholders ----
   Structural placeholders for A0x assets. Must read clearly as a real layout
   component (not a broken image) and reserve real dimensions (aspect-ratio
   set inline per instance) to avoid layout shift (#10 §55, §17). */
.asset-placeholder {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  background-color: var(--placeholder-bg);
  border: 1.5px dashed var(--placeholder-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--space-5);
  padding-top: calc(var(--space-5) + 32px);
  text-align: center;
  overflow: hidden;
}

/* Lightweight "browser window" chrome so placeholders read as real software
   waiting for a screenshot, not as generic broken-image boxes (#06 §9:
   "SetGantt debe parecer software, no una imagen promocional"). Pure CSS,
   no extra markup needed per instance. */
.asset-placeholder::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 32px;
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--placeholder-border);
}

.asset-placeholder::after {
  content: "";
  position: absolute;
  top: 12px;
  left: 16px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--placeholder-border);
  box-shadow: 16px 0 0 var(--placeholder-border), 32px 0 0 var(--placeholder-border);
}

/* Same border on all 4 sides as the base .asset-placeholder — deliberately
   NOT a thicker/different-colored border-top like a previous version had.
   Mixing a 3px solid top border with the 1.5px dashed sides on a rounded
   box made the corner curve look visually offset right where the two
   border styles met (confirmed via devtools inspection). A stronger
   box-shadow is enough to read as "featured" without touching the border. */
.asset-placeholder--feature {
  box-shadow: var(--shadow-lg);
}

/* Real product screenshots/videos once captured (replaces .asset-placeholder
   for that instance). Same radius/shadow language so the swap doesn't jar
   visually against sections still showing a placeholder. */
.asset-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.asset-placeholder__label {
  color: var(--placeholder-text);
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.5;
}

.asset-placeholder__label span {
  display: block;
  font-weight: 400;
  margin-top: var(--space-1);
}

/* ---- Callouts ---- */
.callout {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  margin-block: var(--space-6);
}

.callout--emphasis {
  background-color: var(--color-accent-soft);
  border-color: var(--color-accent-border);
  text-align: center;
  border-radius: var(--radius-lg);
}

.callout--emphasis p {
  color: var(--color-text-primary);
  margin-bottom: var(--space-2);
}

.callout--emphasis p:last-child {
  margin-bottom: 0;
}

/* Smaller footprint for secondary-audience or reassurance content, so it
   doesn't compete visually with primary sections (Nico Paso 2 review). */
.callout--compact {
  padding: var(--space-4) var(--space-5);
  margin-block: var(--space-4);
}

.callout--compact h3 {
  font-size: var(--fs-h4);
  margin-bottom: var(--space-2);
}

.callout--compact p:last-child {
  margin-bottom: 0;
}

/* ---- Banner de consentimiento de cookies ----
   Fijo abajo, por encima de todo (incluida la cabecera sticky, z-index
   100) — real, no decorativo: gatea la carga de reCAPTCHA en form.js
   (ver cookie-consent.js). Oculto por defecto vía [hidden]; JS lo muestra
   solo si no hay decisión guardada. */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 200;
  background-color: var(--color-surface);
  border-top: 1px solid var(--color-border-strong);
  box-shadow: var(--shadow-lg);
  padding: var(--space-5) var(--container-padding);
}

.cookie-banner__inner {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.cookie-banner__inner p {
  flex: 1 1 420px;
  margin-bottom: 0;
  font-size: var(--fs-small);
  color: var(--color-text-secondary);
}

.cookie-banner__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.cookie-preferences-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--color-text-primary);
  cursor: pointer;
  text-decoration: underline;
}

.cookie-preferences-link:hover {
  color: var(--color-accent-hover);
}

/* ---- Agentes IA (sección propia, no una card de Servicios) ---- */
.ai-agents__inner {
  max-width: 760px;
  margin-inline: auto;
  text-align: center;
}

.ai-agents__inner p {
  color: var(--color-text-primary);
}

.ai-agents__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background-color: var(--color-bg);
  border: 1px solid var(--color-accent-border);
  color: var(--color-accent);
  font-size: 1.75rem;
  margin-bottom: var(--space-5);
}

/* ---- Capability cards ---- */
.capability-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
}

.capability-card h4 {
  margin-bottom: var(--space-2);
}

.capability-card p {
  margin-bottom: 0;
  font-size: var(--fs-small);
}

/* ---- Benefit list ---- */
.benefit-list {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.benefit-list li {
  color: var(--color-text-secondary);
}

/* Short facts as inline chips instead of stacked explanatory bullets. */
.benefit-list--compact {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.benefit-list--compact li {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-4);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--color-text-secondary);
}

/* ---- Process steps ----
   Markup is a <ul> (not <ol>) precisely so the visual number below is the
   only number that exists, in the DOM and in the accessibility tree — see
   #10 review notes in en/index.html. Explicit list-style reset kept here too
   (on top of the global ul/ol reset in base.css) so this never regresses if
   the component is copied elsewhere. */
.process-steps {
  list-style: none;
}

.process-steps li::marker {
  content: "";
}

/* Reutiliza el estilo .eyebrow (azul, versalitas, pequeño) en vez de la
   antigua insignia circular — mismo lenguaje visual que "Claris Partner
   Platinum · Reseller · Developer" sobre el h1 del hero, discreta y sin
   competir con el título de cada paso. */
.process-steps__index.eyebrow {
  margin-bottom: 0;
}

.process-steps__index {
  flex-shrink: 0;
}

.process-steps p {
  margin-bottom: 0;
}

/* ---- Sequence list ----
   A compact visual strip, not a dominant text list (Nico Paso 2 review,
   second pass): small, uniformly muted, contained in a single bounded
   "track" rather than free-flowing full-width text. It reads as a small
   technical footnote next to the argument, not as 11 things to individually
   read. The argument itself lives in the paragraphs around it. */
.sequence-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0;
  max-width: 640px;
  margin: var(--space-5) auto;
  padding: var(--space-3) var(--space-5);
  background-color: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  text-align: center;
}

.sequence-list li {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--color-text-muted);
}

.sequence-list li:not(:last-child)::after {
  content: "·";
  margin: 0 var(--space-2);
  color: var(--color-border-strong);
}

/* ---- Pricing card ---- */
.pricing-card {
  max-width: 420px;
  margin: 0 auto;
  background-color: var(--color-surface);
  border: 1px solid var(--color-accent-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-8);
  text-align: center;
}

.pricing-card__product {
  font-weight: 700;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--fs-small);
  margin-bottom: var(--space-3);
}

/* Deliberately understated: this is an internal placeholder, not a real
   price, and must not visually dominate the card the way a final price
   would (Nico Paso 2 review). Styled like the other "pending" markers. */
.pricing-card__price {
  display: inline-block;
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--color-text-muted);
  background-color: var(--placeholder-bg);
  border: 1px dashed var(--placeholder-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-4);
  margin-bottom: var(--space-5);
}

.pricing-card__terms {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
}

.pricing-card__terms li {
  color: var(--color-text-secondary);
  font-size: var(--fs-small);
}

.pricing-card__includes {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  margin-bottom: 0;
}

/* Extra breathing room for the Tenant definition that immediately follows
   the pricing card — scoped to that one instance via the adjacent-sibling
   selector so the other three .fine-print usages elsewhere (already fine
   in their own context) are untouched. */
.pricing-card + .fine-print {
  margin-top: var(--space-6);
}

/* ---- FAQ accordion ---- */
.faq-item {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
}

.faq-item summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--color-text-primary);
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary::after {
  content: "+";
  flex-shrink: 0;
  font-size: 1.25rem;
  color: var(--color-accent);
}

.faq-item[open] summary::after {
  content: "−";
}

.faq-item p {
  margin-top: var(--space-3);
  margin-bottom: 0;
}

/* ---- Forms ---- */
/* Groups two short fields (Name + Phone) onto one line once there's room,
   instead of every field taking a full stacked row — shortens the form so
   it's more likely to fit on screen without scrolling. See responsive.css
   for the >=480px two-column version. */
.form-row-group {
  display: grid;
  gap: var(--space-4);
}

.form-row {
  display: grid;
  gap: var(--space-2);
  text-align: left;
}

.form-row label {
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--color-text-primary);
}

.form-row input,
.form-row textarea {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  background-color: var(--color-surface);
  color: var(--color-text-primary);
}

.form-row input:focus-visible,
.form-row textarea:focus-visible {
  border-color: var(--color-accent);
}

.form-row.has-error input,
.form-row.has-error textarea {
  border-color: #d92d20;
}

.form-row__error {
  font-size: var(--fs-small);
  color: #d92d20;
}

.recaptcha-container {
  min-height: 78px;
  border: 1px dashed var(--placeholder-border);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-small);
  color: var(--placeholder-text);
  background-color: var(--placeholder-bg);
}

/* Texto por idioma vía data-pending-label en el HTML (antes hardcodeado
   en inglés — visible tal cual en las páginas es/ca, incoherente con el
   resto de la página traducida). */
.recaptcha-container::before {
  content: attr(data-pending-label);
}

/* Applied by form.js once a real data-sitekey is configured and Google's
   widget has actually been rendered inside the container — the CSS
   placeholder box/copy is only meant for the pending state. */
.recaptcha-container.is-live {
  min-height: 0;
  border: none;
  background: none;
  padding: 0;
  justify-content: flex-start;
}

.recaptcha-container.is-live::before {
  content: none;
}

/* El recaptcha real de Google necesita ~300px de ancho — no cabe al lado
   del botón en una columna estrecha (formulario de contacto en 3
   columnas) sin partirse mal. Se apilan, pero el botón ocupa el mismo
   ancho que el recaptcha/los campos en vez de quedar más corto y suelto. */
.form-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
}

.form-actions .button {
  width: 100%;
}

.form-status {
  font-size: var(--fs-small);
  font-weight: 600;
}

/* Sin mensaje que mostrar (estado inicial): no reserva línea en blanco. */
.form-status:empty {
  display: none;
}

.form-status[data-state="success"] {
  color: #067647;
}

.form-status[data-state="error"] {
  color: #d92d20;
}

/* ---- Footer legal (pending pages) ---- */
.legal-pending {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  cursor: help;
  border-bottom: 1px dashed var(--color-text-muted);
}

/* ---- Translation pending (ES/CA content without approved copy yet) ----
   Per #10 §59: no runtime translation, no silently-invented translation.
   Shows a clear marker plus the approved EN source so rhythm/length can
   still be reviewed while nobody mistakes it for final copy. */
.i18n-pending {
  display: inline-block;
}

.i18n-pending__badge {
  display: inline-block;
  background-color: var(--color-accent-soft);
  color: var(--color-accent);
  border: 1px dashed var(--color-accent-border);
  border-radius: var(--radius-sm);
  padding: 0.15rem 0.6rem;
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.i18n-pending__source {
  display: block;
  margin-top: var(--space-2);
  font-style: italic;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--color-text-muted);
  font-size: var(--fs-small);
}

.button .i18n-pending__badge {
  border-color: currentColor;
}

/* ---- Legal pages (privacy.html / terms.html / cookies.html) ----
   One physical document per topic with EN/ES/CA hardcoded and toggled via
   the `hidden` attribute (legal.js) — see PENDING.md. */

/* Logo (→ setfile.org, external corporate identity) and "SetGantt / by
   SetFile" wordmark grouped visually but no longer a single click target
   with two different destinations — the explicit "Back" link below is the
   only way back to the SetGantt site (Nico review). */
.legal-brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-right: auto;
}

.legal-back-link {
  white-space: nowrap;
}

/* Legal header has fewer, shorter controls than the commercial site's, but
   still lets them wrap onto a second row on very narrow screens rather
   than risk the same overflow the commercial header had before its own
   dedicated breakpoint fix — simplest safe option for a page with no
   mobile-menu system of its own. */
.legal-header .site-header__inner {
  flex-wrap: wrap;
  row-gap: var(--space-2);
}

/* Enlaces cruzados entre los 3 documentos legales, en la cabecera — añadido
   2026-09-03 junto con el botón "Preferencias de cookies" del pie, para que
   cualquier página legal permita saltar directamente a las otras dos. */
.legal-doc-switch {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.legal-cross-link {
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--color-text-secondary);
  text-decoration: none;
  padding: var(--space-1) 0;
  border-bottom: 2px solid transparent;
}

.legal-cross-link:hover {
  color: var(--color-text-primary);
}

.legal-cross-link[aria-current="page"] {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

.legal-lang-switch {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.legal-lang-switch button {
  color: var(--color-text-secondary);
  font-size: var(--fs-small);
  font-weight: 600;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: none;
  border: none;
}

.legal-lang-switch button:hover {
  background-color: var(--color-surface-alt);
  color: var(--color-text-primary);
}

.legal-lang-switch button[aria-current="true"] {
  color: var(--color-accent);
  background-color: var(--color-accent-soft);
}

.legal-content {
  max-width: 720px;
  margin-inline: auto;
  padding-block: var(--space-12);
}

.legal-content h1 {
  margin-bottom: var(--space-5);
}

.legal-placeholder {
  background-color: var(--color-surface-alt);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  margin-top: var(--space-5);
}

.legal-placeholder p:last-child {
  margin-bottom: 0;
}

/* Tabla de cookies (cookies.html) — añadida 2026-09-03. Envuelta en
   .legal-table-wrap con scroll horizontal propio: 5 columnas no caben en
   los 720px de .legal-content en móvil, y la página no debe scrollear en
   horizontal por culpa de una tabla. */
.legal-table-wrap {
  overflow-x: auto;
  margin-block: var(--space-5);
}

.legal-table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-size: var(--fs-small);
}

.legal-table th,
.legal-table td {
  text-align: left;
  padding: var(--space-3);
  border: 1px solid var(--color-border-strong);
  vertical-align: top;
}

.legal-table th {
  background-color: var(--color-surface-alt);
  font-weight: 700;
}

/* ---- 404 / error page (V0.2 PASO 7) ----
   Reuses .legal-content for the same centered/max-width column as the
   legal pages (#26 — "no sobrediseñar": no new layout primitive for a
   single page). */
.notfound-content {
  text-align: center;
}

.notfound-code {
  font-size: clamp(3rem, 2.2rem + 3vw, 5rem);
  font-weight: 700;
  line-height: 1;
  color: var(--color-accent);
  margin-bottom: var(--space-4);
}

.notfound-content .button {
  margin-top: var(--space-5);
}

/* ---- Microdemo + Full Demo (V0.2 PASO 5) ----
   Microdemo: <video class="asset-image microdemo"> reuses the same
   sizing/radius/shadow as .asset-image (#10 §55) — no separate visual
   language for "placeholder vs real asset vs microdemo". No CSS needed to
   hide native controls: the markup simply never sets the "controls"
   attribute (#08/#10 §17). Actual autoplay/reduced-motion behaviour lives
   in microdemo.js, not here — CSS alone cannot query
   prefers-reduced-motion at the JS/attribute level reliably enough per the
   assets procedure (§7/§44: "no confiar unicamente en CSS"). */
.microdemo-block {
  position: relative;
}

/* Watermark-style badge over the video corner (feedback de Nico tras ver
   la nota de texto estática en staging: no debe leerse como si tuviera
   que "avanzar" con la reproducción, sino como una marca fija — mismo
   patrón que un watermark de "preview"). Reutilizado igual dentro del
   modal Full Demo (.demo-modal__video-wrap .demo-badge). Texto real, no
   decorativo — se mantiene expuesto a lectores de pantalla. */
.demo-badge {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 1;
  background-color: rgba(8, 12, 20, 0.72);
  color: #ffffff;
  font-size: var(--fs-tiny);
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  pointer-events: none;
}

/* Custom play/pause control for the autoplaying, looping microdemo — a
   real <button>, not the browser's native <video controls> bar, so the
   "preview watermark" look is kept while still giving WCAG 2.2.2 a way
   to pause the loop. Bottom-right corner so it never collides with the
   top-left .demo-badge. The icon (pause bars vs. play triangle) is
   driven purely by aria-pressed, which microdemo.js keeps in sync with
   the video's real paused/playing state — never a separate flag. */
.microdemo-pause {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
  z-index: 1;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--radius-pill);
  background-color: rgba(8, 12, 20, 0.72);
  cursor: pointer;
}

.microdemo-pause:hover,
.microdemo-pause:focus-visible {
  background-color: rgba(8, 12, 20, 0.88);
}

/* Default state (aria-pressed="false" = currently playing): show a
   pause icon, since that is the action the button will perform. */
.microdemo-pause::before,
.microdemo-pause::after {
  content: "";
  width: 3px;
  height: 12px;
  background-color: #ffffff;
  margin: 0 2px;
}

/* Paused state (aria-pressed="true"): swap to a play triangle. */
.microdemo-pause[aria-pressed="true"]::before {
  width: 0;
  height: 0;
  margin: 0 0 0 2px;
  background-color: transparent;
  border-style: solid;
  border-width: 6px 0 6px 10px;
  border-color: transparent transparent transparent #ffffff;
}

.microdemo-pause[aria-pressed="true"]::after {
  content: none;
}

/* Discreet secondary link under the microdemo — must not compete with
   primary CTAs (prompt V0.2 §19/§45). */
.microdemo-link {
  display: inline-block;
  margin-top: var(--space-3);
  color: var(--color-text-secondary);
  font-size: var(--fs-small);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.microdemo-link:hover,
.microdemo-link:focus-visible {
  color: var(--color-accent-hover);
}

/* ---- Full Demo modal ----
   Plain <dialog>-like overlay built with a native "hidden" attribute
   (same accessible-hiding pattern already used for the legal-language
   blocks in legal.js) instead of a class, so there is no risk of CSS/JS
   getting out of sync on which one wins. No third-party modal library —
   HTML/CSS/JS already solves it (#10 §32 / prompt V0.2 §46). */
.demo-modal[hidden] {
  display: none;
}

.demo-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background-color: rgba(8, 12, 20, 0.72);
}

/* max-width en vw, no un ancho fijo en px: a petición de Nico, el Full
   Demo debe mostrar el vídeo a su tamaño real siempre que quepa en la
   ventana, en vez de reducirlo a un ancho arbitrario — un 960px fijo
   perdía detalle real de la interfaz de SetGantt (fechas, etiquetas
   finas) en pantallas grandes donde sobraba espacio de sitio. */
.demo-modal__dialog {
  position: relative;
  width: auto;
  max-width: 95vw;
  background-color: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-5);
}

.demo-modal__close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background-color: var(--color-surface);
  color: var(--color-text-primary);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}

.demo-modal__close:hover {
  background-color: var(--color-surface-alt);
}

/* Envoltorio solo para poder anclar el badge .demo-badge sobre la esquina
   del vídeo (position: relative); el propio <video> sigue siendo el que
   define el tamaño. */
.demo-modal__video-wrap {
  position: relative;
  display: flex;
  justify-content: center;
}

/* Tamaño real por defecto: el <video> no lleva width/height fijos en el
   HTML del modal, así que el navegador lo dibuja a su resolución
   intrínseca (la del archivo) en cuanto carga los metadatos, reducido
   solo lo justo para caber en la ventana — nunca ampliado por encima de
   su resolución nativa (evita vídeo pixelado en pantallas grandes). */
.demo-modal__video {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 85vh;
  border-radius: var(--radius-md);
  background-color: #000;
}

/* Background scroll lock while the modal is open (microdemo.js toggles
   this on <html>). */
html.has-modal-open {
  overflow: hidden;
}

/* ==========================================================================
   SetFile.org — additions (secciones sin equivalente en el sitio SetGantt)
   Mismo lenguaje visual: tokens, radios, sombras y patrón de tarjeta que el
   resto del sistema. Nada de color en crudo.
   ========================================================================== */

/* ---- Service cards (con icono/captura) ---- */
.service-grid {
  display: grid;
  gap: var(--space-6);
  margin-top: var(--space-8);
}

.service-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.service-card__image {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

/* Se mantiene la imagen (Nico: son recursos reales del sitio original,
   no stock nuevo inventado por nosotros), pero el título es lo que
   queremos transmitir — se le sube tamaño y peso para que gane a la
   imagen en importancia visual en vez de quedar como una etiqueta
   pequeña debajo de la foto. */
.service-card h4 {
  font-size: clamp(1.15rem, 1.05rem + 0.4vw, 1.3rem);
  font-weight: 800;
  margin-bottom: 0;
}

.service-card p {
  margin-bottom: 0;
  font-size: var(--fs-small);
}

.service-card__link {
  font-size: var(--fs-small);
  font-weight: 600;
}

/* ---- Sector cards (grid simple, sin icono real disponible) ---- */
.sector-grid {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-8);
}

.sector-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
}

.sector-card h3 {
  font-size: var(--fs-h4);
  margin-bottom: var(--space-1);
}

.sector-card p {
  margin-bottom: 0;
  font-size: var(--fs-small);
}

/* ---- Team cards ---- */
.team-grid {
  display: grid;
  gap: var(--space-6);
  margin-top: var(--space-8);
}

.team-card {
  text-align: center;
}

.team-card__photo {
  width: 128px;
  height: 128px;
  border-radius: 50%;
  object-fit: cover;
  margin: 0 auto var(--space-4) auto;
  box-shadow: var(--shadow-sm);
}

.team-card__name {
  margin-bottom: var(--space-1);
}

.team-card__role {
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--color-accent);
  margin-bottom: var(--space-3);
}

.team-card p {
  font-size: var(--fs-small);
}

.team-card__linkedin {
  font-size: var(--fs-small);
  font-weight: 600;
}

/* ---- Testimonials ---- */
.testimonial-grid {
  display: grid;
  gap: var(--space-6);
  margin-top: var(--space-8);
}

.testimonial-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.testimonial-card blockquote {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--fs-body);
}

.testimonial-card figcaption {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}

.testimonial-card figcaption cite {
  color: var(--color-text-primary);
  font-weight: 700;
  font-style: normal;
  display: block;
}

/* ---- Integrations list ---- */
.integration-columns {
  display: grid;
  gap: var(--space-6);
  margin-top: var(--space-6);
  max-width: 900px;
  margin-inline: auto;
}

.integration-columns ul {
  display: grid;
  gap: var(--space-2);
}

.integration-columns li {
  color: var(--color-text-secondary);
  font-size: var(--fs-small);
  padding: var(--space-2) var(--space-3);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

/* ---- Certification cards. Una única grid a 2 columnas para las 6
   certificaciones, todas tratadas igual: sello del nivel más alto a la
   izquierda (con los niveles inferiores, reales o "fantasma", en una fila
   pequeña debajo) + título/texto a la derecha, dentro de la misma
   tarjeta. Cada <img> de nivel inferior apunta a un nombre de fichero
   fijo (ver es/index.html): si el sello real todavía no existe, se sirve
   una imagen "fantasma" con ESE MISMO NOMBRE — el día que Nico consiga el
   sello real solo tiene que sustituir el fichero, sin tocar HTML/CSS.
   Developer Essentials (sin niveles inferiores) usa la misma tarjeta,
   simplemente sin la fila de sellos pequeños. */
.cert-cards {
  display: grid;
  gap: var(--space-8); /* más aire entre certificaciones (Nico) */
  margin-top: var(--space-8);
}

.cert-card {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6); /* más aire entre el sello y el título+texto (Nico) */
}

.cert-card__badges {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.cert-card__badge-primary {
  width: 180px; /* x2 (Nico) */
  height: auto;
}

.cert-card__badge-secondary-row {
  display: flex;
  gap: var(--space-2);
}

.cert-card__badge-secondary {
  width: 72px; /* x2 (Nico) */
  height: auto;
}

.cert-card__info h4 {
  margin-bottom: var(--space-2);
}

.cert-card__info p {
  font-size: var(--fs-small);
  margin-bottom: 0;
}

/* ---- Contacto en columnas (intro | datos | formulario), en vez de todo
   apilado y centrado — la altura del bloque la marca la columna del
   formulario (Nombre* → botón Enviar), las otras dos no la superan. ---- */
.contact-layout {
  display: grid;
  gap: var(--space-8);
}

.contact-layout__intro h2 {
  margin-bottom: var(--space-3);
}

/* Antes era su propia columna (3 columnas); ahora va debajo de la intro,
   dentro de la misma columna izquierda (Nico) — separación propia en vez
   de heredar el gap del grid, que solo aplica entre columnas. */
.contact-layout__info {
  margin-top: var(--space-6);
}

.contact-info-item {
  margin-bottom: var(--space-3);
}

.contact-info-item:last-child {
  margin-bottom: 0;
}

.contact-info-item h3 {
  font-size: var(--fs-h4);
  margin-bottom: var(--space-1);
}

.contact-info-item p {
  margin-bottom: 0;
}

.contact-layout__form .contact-form {
  max-width: none;
  margin: 0;
}

/* ---- Intercambio de imagen según tema claro/oscuro (logos con versión
   oscura pendiente: se sirve un "fantasma" con el mismo nombre + "-dark"
   hasta que Nico suba la versión real). ---- */
.theme-logo--dark {
  display: none;
}

[data-theme="dark"] .theme-logo--light {
  display: none;
}

[data-theme="dark"] .theme-logo--dark {
  display: block;
}

/* ---- Certification / partner badges row ---- */
.cert-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

.cert-row img {
  height: 32px;
  width: auto;
}

/* ---- "Why choose us" grid ---- */
.reason-grid {
  display: grid;
  gap: var(--space-5);
  margin-top: var(--space-8);
}

.reason-grid h4 {
  margin-bottom: var(--space-1);
}

.reason-grid p {
  font-size: var(--fs-small);
  margin-bottom: 0;
}
