/* ==========================================================================
   Codfy Website — estilos propios, desde cero (sin Bootstrap ni Odoo assets)

   Estado actual: LIENZO EN BLANCO. Solo quedan el chrome del sitio
   (header + footer) y las utilidades que reutiliza /shop. Todo el contenido
   de pruebas (hero, 10 bloques animados, réplica del backend) fue eliminado.
   ========================================================================== */

/* --------------------------------------------------------------------------
   TIPOGRAFÍA — Altone (Eko Bimantara), fuente ÚNICA del sitio.

   Los .TTF originales de la licencia viven en static/src/font/; de ahí se
   generaron los .woff2 que se sirven (misma carpeta, ~25 KB cada uno frente a
   los ~72 KB del TTF). Para regenerar tras cambiar un archivo:
       python3 -c "from fontTools.ttLib import TTFont; f=TTFont('ALTONE-X.TTF'); f.flavor='woff2'; f.save('Altone-X.woff2')"

   OJO: la familia entregada NO trae Bold (700) vertical — solo SemiBold (600)
   y ExtraBold (800). Por eso el CSS del sitio pide 600 donde llevaría negrita.
   -------------------------------------------------------------------------- */
@font-face {
    font-family: "Altone";
    src: url("/c_website/static/src/font/Altone-Regular.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Altone";
    src: url("/c_website/static/src/font/Altone-Medium.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Altone";
    src: url("/c_website/static/src/font/Altone-SemiBold.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Altone";
    src: url("/c_website/static/src/font/Altone-ExtraBold.woff2") format("woff2");
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Altone";
    src: url("/c_website/static/src/font/Altone-MediumOblique.woff2") format("woff2");
    font-weight: 500;
    font-style: italic;
    font-display: swap;
}
/* Bold sí existe, pero SOLO oblicuo (ALTONE-BOLDOBLIQUE.TTF, usWeightClass 700,
   subfamilia "Bold Italic"). Se declara con font-style: italic para que
   `font-weight:700; font-style:italic` case exacto — es el del título del hero. */
@font-face {
    font-family: "Altone";
    src: url("/c_website/static/src/font/Altone-BoldOblique.woff2") format("woff2");
    font-weight: 700;
    font-style: italic;
    font-display: swap;
}

:root {
    /* ======================================================================
       PALETA ESTÁNDAR DEL SITIO — definida por el cliente.
       Es la ÚNICA fuente de verdad del color: no escribir hex sueltos en el
       resto del archivo, siempre var(--cf-*).
       ---------------------------------------------------------------------
         --cf-primary   #0053FF   botones y la palabra "Codfy" en negrita
         --cf-text      #000000   texto general
         --cf-on-primary #FFFFFF  texto sobre botones e iconos
         --cf-ribbon    #E2E2E2   gris del listón de logotipos
         --cf-card      #E5E5E5   tarjetas de "¿Cómo trabajamos?"
       ====================================================================== */
    --cf-primary:     #0053ff;
    --cf-primary-2:   #0041cc;   /* hover del primario (derivado) */
    --cf-text:        #000000;
    --cf-on-primary:  #ffffff;
    --cf-ribbon:      #e2e2e2;
    --cf-card:        #e5e5e5;
    --cf-sec4-bg:     #f2f2f2;   /* fondo de la 4ª sección */
    --cf-panel:       #d3d3d3;   /* panel con muesca de la 4ª sección */

    --cf-bg:        #ffffff;   /* fondo del sitio: blanco puro */
    --cf-surface:   #f7f8fa;   /* footer (no está en la paleta del cliente) */
    --cf-muted:     #5b6472;   /* texto secundario */
    --cf-border:    #e4e7ec;   /* separadores */

    --cf-nav-h:     72px;      /* altura del header en reposo */
    --cf-nav-h-sm:  60px;      /* altura del header con scroll */
    --cf-max:       1120px;    /* ancho del contenido */
    --cf-nav-max:   1800px;    /* ancho del header: casi toda la pantalla */

    --cf-font:      "Altone", -apple-system, BlinkMacSystemFont,
                    "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

    /* Cuerpo ÚNICO de los títulos de sección: "¿Cómo trabajamos?",
       "Digitaliza tu empresa…", "¡Nuestros Servicios!" y el reclamo del CTA.
       Se toca aquí y cambian los cuatro a la vez. El del hero va aparte y más
       grande a propósito: es el título de la página. */
    --cf-title:     clamp(34px, 3.9vw, 58px);
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
}

/* Fuente ÚNICA de todo el sitio: Altone. !important para imponerse sobre la
   fuente de tema de Odoo en las páginas de website_sale. Los iconos
   FontAwesome conservan su fuente por especificidad (su propia regla .fa gana). */
body {
    background: var(--cf-bg);
    color: var(--cf-text);
    font-family: var(--cf-font) !important;
    font-weight: 400;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

/* Odoo pinta sus propios font-family en botones, inputs y encabezados de
   website_sale: los reenganchamos a la fuente del sitio. */
button, input, select, textarea,
h1, h2, h3, h4, h5, h6 { font-family: var(--cf-font); }

/* Odoo pinta fondo propio en estos contenedores del layout: los forzamos a
   blanco para que no se cuele ningún gris del tema. */
#wrapwrap,
#wrapwrap > main { background: var(--cf-bg); }

/* :hover/:focus explícitos: Bootstrap (que Odoo carga) subraya los enlaces al
   pasar el mouse, y la regla `a { text-decoration: none }` sola no lo tapa. */
a, a:hover, a:focus { color: inherit; text-decoration: none; }

/* ==========================================================================
   HEADER — fijo, acompaña la página en todo el scroll.
   Dos estados: reposo (transparente, sin sombra) y .cf-nav--scrolled
   (blanco translúcido, sombra y un poco más compacto). La clase la pone
   app.js a partir de los ~24px de scroll.
   ========================================================================== */
.cf-nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    height: var(--cf-nav-h);
    background: transparent;
    border-bottom: 1px solid transparent;
    transition: height .25s ease,
                background-color .25s ease,
                border-color .25s ease,
                box-shadow .25s ease;
}

/* Al ser fixed no ocupa sitio en el flujo: se lo devolvemos al contenido. */
#wrapwrap > main { padding-top: var(--cf-nav-h); }

.cf-nav--scrolled {
    height: var(--cf-nav-h-sm);
    background: rgba(255, 255, 255, .85);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
            backdrop-filter: saturate(180%) blur(12px);
    border-bottom-color: var(--cf-border);
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04),
                0 10px 28px -20px rgba(16, 24, 40, .45);
}

/* Navegador sin backdrop-filter: fondo blanco sólido (mismo resultado visual). */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .cf-nav--scrolled { background: #ffffff; }
}

/* Rejilla del header: logo | menú | acciones.
   Los dos laterales comparten el mismo `flex: 1 1 0`, así que el menú queda
   centrado respecto a la ventana y no respecto al espacio sobrante. */
.cf-nav__inner {
    /* El header NO se ciñe a --cf-max (1120px) como el resto del contenido:
       ocupa casi todo el ancho de la pantalla, solo con aire en los costados. */
    max-width: var(--cf-nav-max);
    height: 100%;
    margin: 0 auto;
    padding: 0 40px;
    display: flex;
    align-items: center;
}

.cf-nav__side {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
}
.cf-nav__side--end { justify-content: flex-end; gap: 14px; }

/* flex: 0 0 auto en logo, botón y hamburguesa: en pantallas muy estrechas
   (320 px) el flex los comprimía y deformaba. */
.cf-nav__brand { display: inline-flex; align-items: center; flex: 0 0 auto; }
.cf-nav__cta, .cf-nav__burger { flex: 0 0 auto; }

/* Logotipo real (static/src/img/logo.png). Alto fijo, ancho por proporción. */
.cf-nav__logo {
    display: block;
    height: 34px;
    width: auto;
    transition: height .25s ease;
}
.cf-nav--scrolled .cf-nav__logo { height: 28px; }

/* Sin `height` aquí: el 100% que necesita el escritorio (para que los
   desplegables arranquen al borde inferior del header) vive en el media
   query de ≥821px. En móvil el panel debe crecer con su contenido. */
.cf-nav__menu {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 32px;
}

/* Elementos de menú: Altone Regular (400) */
.cf-nav__link {
    color: var(--cf-muted);
    font-size: 15px;
    font-weight: 400;
    transition: color .15s ease;
}
.cf-nav__link:hover { color: var(--cf-text); }

/* ---------- Desplegables (sin JS) ----------
   Dos comportamientos SEPARADOS POR BREAKPOINT, nunca mezclados:
     · ≥821px  → panel flotante que abre con hover/foco (bloque de más abajo)
     · ≤820px  → acordeón dentro del menú hamburguesa (bloque RESPONSIVE)
   Están en @media excluyentes a propósito: cuando las reglas de escritorio
   vivían fuera del media query, el `transform: translate(-50%)` del hover
   seguía aplicándose en móvil y sacaba el submenú de la pantalla. */

/* Checkbox de estado: invisible pero enfocable, así el teclado también abre
   el acordeón en móvil (Tab + Espacio). No usar display:none. */
.cf-sub__checkbox {
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0;
    pointer-events: none;
}
.cf-sub__checkbox:focus-visible ~ .cf-nav__link--parent {
    outline: 2px solid var(--cf-primary);
    outline-offset: 4px;
    border-radius: 4px;
}

.cf-nav__link--parent {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.cf-caret {
    width: 6px; height: 6px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    transition: transform .2s ease;
}

.cf-nav__dropdown { display: flex; flex-direction: column; }

.cf-nav__sublink {
    font-size: 15px;
    font-weight: 400;
    color: var(--cf-muted);
    transition: background .15s ease, color .15s ease;
}
.cf-nav__sublink:hover {
    background: rgba(0, 83, 255, .07);
    color: var(--cf-primary);
}

/* ---------- ESCRITORIO: panel flotante con hover ---------- */
@media (min-width: 821px) {
    .cf-nav__menu { height: 100%; }

    /* El item ocupa TODO el alto del header para que el panel arranque justo
       en su borde inferior: si quedara un hueco, el puntero perdería el hover
       al bajar del texto al panel. */
    .cf-nav__item {
        position: relative;
        height: 100%;
        display: flex;
        align-items: center;
    }

    .cf-nav__dropdown {
        position: absolute;
        top: 100%;
        left: 50%;
        min-width: 216px;
        padding: 8px;
        background: var(--cf-bg);
        border: 1px solid var(--cf-border);
        border-radius: 14px;
        box-shadow: 0 12px 32px -12px rgba(14, 13, 50, .22);
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transform: translate(-50%, 4px);
        transition: opacity .18s ease, transform .18s ease, visibility .18s;
    }
    .cf-nav__item:hover .cf-nav__dropdown,
    .cf-nav__item:focus-within .cf-nav__dropdown {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transform: translate(-50%, 0);
    }
    .cf-nav__item:hover .cf-caret,
    .cf-nav__item:focus-within .cf-caret { transform: rotate(-135deg) translate(-1px, -1px); }
    .cf-nav__item:hover > .cf-nav__link--parent { color: var(--cf-text); }

    .cf-nav__sublink {
        padding: 9px 12px;
        border-radius: 9px;
        white-space: nowrap;
    }
}

/* Botón "Iniciar sesión": Altone Medium (500).
   Píldora delgada: texto grande con poco aire alrededor. El line-height
   ajustado es lo que de verdad adelgaza el botón (el 1.6 del body lo
   engordaba casi 10 px por sí solo). */
.cf-nav__cta {
    padding: 4px 16px;
    border-radius: 999px;
    background: var(--cf-primary);
    color: var(--cf-on-primary) !important;
    font-weight: 500;
    font-size: 17px;
    line-height: 1.35;
    white-space: nowrap;
    transition: background .15s ease;
}
.cf-nav__cta:hover { background: var(--cf-primary-2); }

/* --------------------------------------------------------------------------
   SESIÓN INICIADA — desplegable de usuario.
   El marcado lo pone `portal.user_dropdown` de Odoo; aquí solo se le da el
   aspecto del navbar. La apertura/cierre la maneja el JS de Bootstrap que ya
   viene en web.assets_frontend, por eso no hay JS propio.
   -------------------------------------------------------------------------- */
.cf-nav__user {
    flex: 0 0 auto;
    list-style: none;
    margin: 0;
    padding: 0;
}
.cf-nav__userlink {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 14px 4px 4px;
    border: 1px solid var(--cf-border);
    border-radius: 999px;
    color: var(--cf-text) !important;
    font-weight: 500;
    font-size: 16px;
    line-height: 1.35;
    white-space: nowrap;
    text-decoration: none;
    transition: border-color .15s ease, background .15s ease;
}
.cf-nav__userlink:hover { border-color: var(--cf-primary); background: var(--cf-surface); }

/* Alto fijo: el avatar llega como <img width=24 height=24> y sin esto el
   navbar da un salto cuando la imagen termina de cargar. */
.cf-nav__avatar {
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    border-radius: 50%;
    object-fit: cover;
}
.cf-nav__username {
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cf-nav__usermenu {
    border: 1px solid var(--cf-border);
    border-radius: 12px;
    padding: 6px;
    margin-top: 10px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .12);
    font-size: 15px;
}
.cf-nav__usermenu .dropdown-item { border-radius: 8px; padding: 8px 12px; }
.cf-nav__usermenu .dropdown-item:active { background: var(--cf-primary); color: var(--cf-on-primary); }

/* En móvil el nombre estorba junto a la hamburguesa: queda solo el avatar. */
@media (max-width: 991px) {
    .cf-nav__username { display: none; }
    .cf-nav__userlink { padding: 4px; border-color: transparent; }
}

/* Menú móvil por CSS puro (sin JS) */
.cf-nav__checkbox,
.cf-nav__burger { display: none; }

/* ==========================================================================
   HERO PRINCIPAL — texto a la izquierda, imágenes a la derecha.
   Comparte el ancho del header (--cf-nav-max + 40px de aire), NO el ancho de
   contenido --cf-max, para que ambos bloques queden alineados en pantalla.
   ========================================================================== */
/* El hero es el lienzo del cuarto de anillo, anclado a su esquina inferior
   derecha (el borde inferior es justo donde empieza el listón de logos). */
.cf-hero {
    position: relative;
    overflow: hidden;
}
.cf-hero__arc {
    position: absolute;
    z-index: 2;               /* por ENCIMA del círculo lila */
    right: 0;
    bottom: 0;
    width: clamp(140px, 19vw, 310px);
    height: auto;
    color: var(--cf-primary);  /* el path usa currentColor */
    pointer-events: none;
}

.cf-hero__inner {
    position: relative;
    z-index: 1;               /* el contenido, por encima del anillo */
    max-width: var(--cf-nav-max);
    margin: 0 auto;
    padding: 72px 40px 96px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 56px;
    align-items: center;
}

/* Título: Altone Bold Oblique (700 + italic) */
.cf-hero__title {
    margin: 0 0 24px;
    font-size: clamp(34px, 4.4vw, 66px);
    font-weight: 700;
    font-style: italic;
    line-height: 1.06;
    letter-spacing: -0.02em;
    color: var(--cf-text);
    /* Sin `text-wrap: balance`: los cortes de línea son explícitos (<br/> en
       la plantilla) y el balanceo automático los pelearía. */
}

/* La palabra "odoo" del título es el logotipo. En `em` para que escale con el
   título; el ajuste vertical lo alinea con la base del texto. */
.cf-hero__odoo {
    display: inline-block;
    /* .52em + 20px medidos en escritorio (título a 63.36px → 20/63.36 = .32em).
       Se mantiene en `em` para que siga escalando con el título. */
    height: .84em;
    width: auto;
    vertical-align: baseline;
    margin: 0 .06em;
}

/* Bajada: Altone Medium (500) */
.cf-hero__sub {
    margin: 0;
    max-width: 620px;
    font-size: clamp(16px, 1.15vw, 20px);
    font-weight: 500;
    line-height: 1.55;
    color: var(--cf-muted);
}

/* Botón "Conocer más": misma píldora que el de sesión, con un resplandor
   detrás. El brillo es una copia del propio botón desenfocada y desplazada
   hacia abajo (::before con z-index:-1), no un box-shadow: así el halo tiene
   la forma exacta de la píldora y puede desbordarla como una luz real. */
.cf-hero__cta {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-top: 36px;
    /* Más aire que el botón del header: este es el CTA principal de la página */
    padding: 15px 36px;
    border-radius: 999px;
    background: var(--cf-primary);
    color: var(--cf-on-primary) !important;
    font-size: 17px;
    font-weight: 500;
    font-style: italic;   /* Altone Medium Oblique */
    line-height: 1.35;
    white-space: nowrap;
    isolation: isolate;   /* contiene el z-index:-1 del halo */
    transition: background .18s ease, transform .18s ease;
}
.cf-hero__cta::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 4px 6px -10px;          /* desplazado hacia abajo: luz por detrás */
    border-radius: inherit;
    background: var(--cf-primary);
    filter: blur(18px);
    opacity: .55;
    transition: opacity .18s ease, filter .18s ease, transform .18s ease;
}
.cf-hero__cta:hover { background: var(--cf-primary-2); transform: translateY(-1px); }
.cf-hero__cta:hover::before { opacity: .8; filter: blur(24px); transform: scale(1.06); }

/* Quien pida menos movimiento conserva el halo, pero sin desplazamientos. */
@media (prefers-reduced-motion: reduce) {
    .cf-hero__cta, .cf-hero__cta::before { transition: none; }
    .cf-hero__cta:hover { transform: none; }
    .cf-hero__cta:hover::before { transform: none; }
}

/* Columna derecha: escenario de la composición por capas. La imagen base va
   en el flujo y define el alto; las capas siguientes irán en absoluto sobre
   ella (por eso el position: relative). */
/* El escenario mide la mitad de la columna (y va centrado): así el círculo
   marca el tamaño de la composición y las capas que se monten encima siguen
   usando sus mismas coordenadas. */
/* El círculo se estira al alto de la columna de texto (align-self: stretch),
   nunca al revés: así el alto del hero lo sigue mandando el texto y agrandar
   la imagen NO puede añadir scroll. Los márgenes negativos le dan 96px extra
   invadiendo el padding del hero, también sin alterar el alto de la fila.
   La proporción es la del PNG (7054x8046), así que la caja coincide con el
   círculo y las capas que se monten encima conservan sus coordenadas. */
/* Clave: manda la ALTURA, no el ancho. La columna se estira al alto de la
   fila (que fija el texto) y el círculo se dimensiona por esa altura, con el
   ancho derivado de su proporción. Así agrandarlo NUNCA puede alargar el hero
   ni añadir scroll. Los márgenes negativos le regalan 112px extra invadiendo
   el padding del hero, que también es alto ya existente.
   (Con `aspect-ratio` en la caja pasaba lo contrario: mandaba el ancho de la
   columna y el hero crecía de 686 a 816px.) */
.cf-hero__media {
    position: relative;
    align-self: center;
    /* Márgenes negativos: el círculo invade el padding del hero, alto que ya
       existía. Así crece bastante más de lo que alarga la sección. */
    margin: -40px 0 -72px;
    display: flex;
    justify-content: center;
    min-width: 0;
}
/* Mide exactamente el círculo: es el sistema de coordenadas de las capas
   que se monten encima (van dentro, en absoluto). */
.cf-hero__stack {
    position: relative;
    width: 89%;
    max-width: 100%;
    /* Desplazado 50px a la derecha. Con transform y no con margen: no altera
       la maquetación, así que no puede provocar desbordes ni recolocar nada. */
    transform: translateX(50px);
}
.cf-hero__img--base {
    display: block;
    width: 100%;
    height: auto;
}

/* Contenedores de capa: guardan la POSICIÓN. La imagen de dentro se deja
   libre para GSAP (entrada y hover), así una cosa no pisa a la otra.
   La sombra vive en la imagen para que acompañe al escalar en el hover. */
.cf-hero__layer > img {
    display: block;
    width: 100%;
    height: auto;
    filter: drop-shadow(0 clamp(5px, 1.25vw, 18px) clamp(8px, 1.8vw, 26px) rgba(14, 13, 50, .28));
    will-change: transform;
}
.cf-hero__layer--phone > img {
    height: 100%;
    width: auto;
    filter: none;          /* el mockup ya trae su propia sombra */
}

/* Capa 3: tarjeta de Odoo, encima del móvil y anclada arriba a la izquierda.
   La sombra va con drop-shadow y no con box-shadow: el PNG es una tarjeta
   girada en 3D con transparencia, y drop-shadow sigue el contorno real del
   canal alfa en vez de dibujar un rectángulo. */
.cf-hero__layer--card {
    position: absolute;
    z-index: 2;
    top: 6%;
    /* Anclada en % (no en px) para que acompañe al círculo al escalar. Un 20%
       la deja montada sobre la mitad superior del móvil, no al ras de su
       borde izquierdo. */
    left: 20%;
    width: 50%;
    height: auto;
    /* En % del propio elemento (no en px): el % escala con la imagen, así la
       composición se mantiene idéntica en cualquier tamaño de círculo.
       Equivale a los -50px/-25px medidos en escritorio. */
    transform: translate(-17.24%, -10.55%);
}

/* Capa 4: tarjetas de indicadores, en la parte baja del móvil. */
.cf-hero__layer--stats {
    position: absolute;
    z-index: 2;
    bottom: 6%;
    left: 20%;
    width: 48.4%;            /* 52% → −15% → +10% */
    height: auto;
    /* En % del propio elemento, igual que la tarjeta superior: escala con el
       círculo en vez de quedarse en píxeles fijos.
       El -74.15% vertical es el valor exacto para que la caja de esta imagen
       quede JUSTO por debajo de la tarjeta 4, sin solaparla, en cualquier
       ancho de pantalla. */
    transform: translate(-46.26%, -74.15%);   /* 20px a la derecha */
}

/* Capa 2: el móvil, centrado sobre el círculo y algo más alto que él para
   que sobresalga por arriba y por abajo. */
.cf-hero__layer--phone {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    height: 86%;          /* 112% → −30% → +10% */
    width: auto;
    max-width: none;
}

/* ==========================================================================
   LISTÓN DE CONFIANZA — banda gris a todo el ancho, con marquesina infinita
   ========================================================================== */
.cf-trust {
    width: 100%;
    background: var(--cf-ribbon);
    border-top: 1px solid var(--cf-border);
    border-bottom: 1px solid var(--cf-border);
}

/* El contenido se alinea con el header y el hero (mismo ancho máximo) aunque
   la banda gris sangre de borde a borde. */
.cf-trust__inner {
    max-width: var(--cf-nav-max);
    margin: 0 auto;
    padding: 22px 40px;
    display: flex;
    align-items: center;
    gap: 40px;
}

/* Rótulo: Altone Medium Oblique (500 + italic) */
.cf-trust__label {
    flex: 0 0 auto;
    margin: 0;
    font-size: 15px;
    font-weight: 500;
    font-style: italic;
    line-height: 1.3;
    color: var(--cf-text);   /* negro de la paleta, no el gris secundario */
    text-align: center;   /* "en nosotros" centrado bajo la primera línea */
    white-space: nowrap;
}

/* Ventana de la marquesina. El degradado de máscara difumina los logos al
   entrar y salir, en vez de cortarlos en seco contra el borde. */
.cf-trust__marquee {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 48px,
                                        #000 calc(100% - 48px), transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 48px,
                                        #000 calc(100% - 48px), transparent 100%);
}

/* Pista: dos grupos idénticos en fila. Al desplazarse -50% (el ancho exacto
   de un grupo) el segundo cae donde estaba el primero y el ciclo es continuo,
   sin salto visible. */
.cf-trust__track {
    display: flex;
    width: max-content;
    animation: cf-marquee 34s linear infinite;
    will-change: transform;
}
.cf-trust__group {
    display: flex;
    align-items: center;
    gap: 56px;
    padding-right: 56px;   /* mismo hueco entre el último y el primero */
}
.cf-trust__marquee:hover .cf-trust__track { animation-play-state: paused; }

@keyframes cf-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* Logos. Caja común de 140x44 con `max-*` en vez de alto fijo: unos son
   palabras muy anchas (Innovando, Inflexyon) y otros casi cuadrados (Snack
   Box), y con un solo alto fijo los anchos se irían a 230px o a 35px. Al
   limitar las DOS medidas, cada logo entra en la misma caja y todos pesan
   ópticamente lo mismo. Los archivos van exportados al doble (280x88), así
   que se dibujan justo a la mitad y se ven nítidos en pantallas retina.

   `width/height: auto` y no `object-fit`: así el elemento mide lo que mide el
   logo y los huecos entre ellos quedan iguales, sin bandas vacías. */
.cf-trust__logo {
    flex: 0 0 auto;
    max-width: 140px;
    max-height: 44px;
    width: auto;
    height: auto;
}

@media (prefers-reduced-motion: reduce) {
    .cf-trust__track { animation: none; }
}

/* ==========================================================================
   ¿CÓMO TRABAJAMOS? — bloque centrado
   ========================================================================== */
/* Ancho amplio: el párrafo lleva cortes de línea explícitos y necesita sitio
   para resolverse en 3 líneas sin que el navegador las parta por su cuenta. */
.cf-how__inner {
    max-width: 1320px;
    margin: 0 auto;
    padding: 88px 40px;
    text-align: center;
}

/* Título: Altone Bold Oblique (700 + italic), sin versalitas: se escribe tal
   cual, solo con la C inicial en mayúscula. */
.cf-how__title {
    margin: 0 0 24px;
    font-size: var(--cf-title);
    font-weight: 700;
    font-style: italic;
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--cf-text);
}

/* Cuerpo: Altone Medium (500) */
.cf-how__text {
    margin: 0;
    font-size: clamp(16px, 1.15vw, 19px);
    font-weight: 500;
    line-height: 1.65;
    color: var(--cf-muted);
}

/* "Codfy" destacado en el azul del logotipo.
   OJO: la familia no tiene Bold (700) VERTICAL — solo oblicuo. Al pedir 700
   en estilo normal, el algoritmo de CSS Fonts busca primero pesos ≥700 y cae
   en ExtraBold (800), que es una cara real: no hay negrita sintética. */
.cf-brand-word {
    font-weight: 700;
    color: var(--cf-primary);
}

/* ==========================================================================
   CARRUSEL DE 3 TARJETAS — la central grande, las laterales pequeñas
   ========================================================================== */
/* La sección es el lienzo del arco: se posiciona para que el fondo azul se
   ancle a su borde inferior y las tarjetas queden superpuestas encima. */
.cf-cards {
    /* Ancho del arco, en vw para poder derivar su alto en los calc() de abajo.
       La imagen mide 7054×2877 → proporción 2.45, así que alto = ancho / 2.45.
       Los +200px lo agrandan a petición del cliente: como va anclado abajo y
       la sección lo recorta, el arco crece hacia arriba y hacia los lados
       (la cúpula sube 200/2.45 = 82px), sin dejar hueco por abajo. */
    --cf-arc-w: calc(60vw + 200px);
    position: relative;
    overflow: hidden;
}

.cf-cards__inner {
    position: relative;
    z-index: 1;               /* por encima del arco */
    max-width: var(--cf-nav-max);
    margin: 0 auto;
    padding: 0 40px 72px;
}

/* Arco azul de fondo: a sangre de borde a borde, pegado abajo y conservando
   su proporción. Absoluto, así que no aporta alto a la sección; si sobra,
   se recorta por el overflow de .cf-cards. */
.cf-arc {
    position: absolute;
    z-index: 0;
    bottom: 0;
    left: 50%;
    width: var(--cf-arc-w);
    transform: translateX(-50%);    /* centrado */
    line-height: 0;
    pointer-events: none;
}
.cf-arc__img {
    display: block;
    width: 100%;
    height: auto;
}

/* Fila: flecha · escenario · flecha. Con los botones pegados a las tarjetas
   en vez de anclados a los bordes del contenedor, que mide 1800px y los
   dejaría a media pantalla de distancia. */
.cf-cards__carousel {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

.cf-cards__nav {
    flex: 0 0 auto;
    /* Las laterales van escaladas a 0.87: su caja de layout es ~24px más
       ancha que lo que se ve, y sin este acercamiento la flecha queda
       flotando lejos de la tarjeta. */
    margin: 0 -14px;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    padding: 0;
    border: 1px solid var(--cf-border);
    border-radius: 50%;
    background: #ffffff;
    cursor: pointer;
    box-shadow: 0 10px 24px -18px rgba(16, 24, 40, .55);
    transition: background .15s ease, border-color .15s ease;
}
.cf-cards__nav:hover {
    background: var(--cf-primary);
    border-color: var(--cf-primary);
}
.cf-cards__nav:focus-visible {
    outline: 2px solid var(--cf-primary);
    outline-offset: 3px;
}

/* Chevron dibujado con bordes: sin iconos externos ni fuente de iconos. */
.cf-cards__chev {
    width: 10px;
    height: 10px;
    border-right: 2px solid var(--cf-text);
    border-bottom: 2px solid var(--cf-text);
    transition: border-color .15s ease;
}
.cf-cards__nav:hover .cf-cards__chev { border-color: var(--cf-on-primary); }
/* El desplazamiento compensa que el chevron pesa hacia una esquina: así
   queda ópticamente centrado dentro del círculo. */
.cf-cards__nav--prev .cf-cards__chev { transform: rotate(135deg) translate(-2px, -2px); }
.cf-cards__nav--next .cf-cards__chev { transform: rotate(-45deg)  translate(-2px, -2px); }

/* Indicadores. OJO CON EL COLOR: a esta altura los puntos caen SOBRE el arco
   azul (comprobado muestreando el píxel del fondo de 1025 a 2560px), así que
   van en blanco — en azul sobre azul el activo desaparecía. Además el activo
   se alarga, así que se distingue aunque el contraste falle. */
.cf-cards__dots {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 9px;
    margin-top: -8px;   /* el escenario ya trae 40px de aire abajo */
}
.cf-cards__dot {
    width: 9px;
    height: 9px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, .5);
    cursor: pointer;
    transition: width .25s ease, background .25s ease;
}
.cf-cards__dot:hover { background: rgba(255, 255, 255, .78); }
.cf-cards__dot--active {
    width: 26px;
    background: var(--cf-on-primary);
    cursor: default;
}
.cf-cards__dot:focus-visible {
    outline: 2px solid var(--cf-primary);
    outline-offset: 3px;
}

/* Las tres tarjetas miden lo mismo en el DOM; la diferencia de tamaño es un
   `scale`. Así el reordenado se anima con transform (barato y fluido) y el
   texto no se remaqueta al cambiar de posición. */
.cf-cards__stage {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 28px;
    padding: 40px 0;   /* sitio para que la central crezca sin recortarse */
}

/* OJO: escala y opacidad NO se declaran aquí. Las controla GSAP desde
   app.js (es quien anima el reordenado), y si el CSS también escribiera
   `transform` los dos se pisarían. Aquí solo va lo estático. */
.cf-card {
    /* 0 1 (encoge) y no 0 0: entre 1025 y ~1250px las tres tarjetas suman más
       que el contenedor, y con ancho fijo el overflow de la sección las
       recortaba. min-width:0 permite que el contenido acompañe. */
    flex: 0 1 372px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 18px;
    background: var(--cf-card);
    border: 1px solid var(--cf-border);
    border-radius: 22px;
    cursor: pointer;
    transform-origin: center center;
    transition: box-shadow .3s ease;
}
.cf-card--active {
    box-shadow: 0 26px 54px -32px rgba(14, 13, 50, .45);
    cursor: default;
    z-index: 2;
}

/* Marco de la foto. Las tres imágenes están recortadas al MISMO tamaño
   (924x494) y sin el margen transparente que traían horneado, por eso el
   aspect-ratio es exactamente el suyo: así llenan la caja al píxel y el gris
   de fondo no asoma por ningún borde (solo se ve mientras cargan).
   El redondeado lo pone el CSS, no la imagen. */
.cf-card__media {
    aspect-ratio: 924 / 494;
    overflow: hidden;
    border-radius: 14px;
    background: #eef0f4;
}
.cf-card__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.cf-card__title {
    margin: 0;
    font-size: 21px;
    font-weight: 600;
    line-height: 1.25;
    color: var(--cf-text);
}
.cf-card__text {
    margin: 0;
    font-size: 15px;
    font-weight: 400;
    line-height: 1.55;
    color: var(--cf-muted);
}

/* Pie: icono a la izquierda y botón en la misma línea */
.cf-card__foot {
    margin-top: auto;
    padding-top: 6px;
    display: flex;
    align-items: center;
    gap: 14px;
}
/* Icono de la tarjeta. Las imágenes ya traen su propio círculo de fondo, así
   que aquí no hace falta ni borde ni relleno: solo el tamaño. */
.cf-card__icon {
    flex: 0 0 auto;
    display: block;
    width: 44px;
    height: 44px;
}
.cf-card__btn {
    margin-left: auto;   /* el icono queda a la izquierda y el botón pegado a la derecha */
    padding: 9px 22px;
    border-radius: 999px;
    background: var(--cf-primary);
    color: var(--cf-on-primary) !important;
    font-size: 15px;
    font-weight: 500;
    line-height: 1.35;
    white-space: nowrap;
    transition: background .15s ease;
}
.cf-card__btn:hover { background: var(--cf-primary-2); }

/* Frase de cierre bajo las tarjetas: Altone Medium Oblique, centrada,
   a la mitad del tamaño anterior (32px → 16px en escritorio). */
.cf-cards__claim {
    max-width: 820px;
    margin: 28px auto 0;
    font-size: clamp(14px, 1.1vw, 16px);
    font-weight: 500;
    font-style: italic;
    line-height: 1.25;
    letter-spacing: -0.01em;
    text-align: center;
    color: var(--cf-on-primary);   /* cae sobre el arco azul */
}

/* ==========================================================================
   SECCIÓN 4 — banda a sangre con fondo propio. Contenido pendiente.
   ========================================================================== */
.cf-sec4 {
    width: 100%;
    background: var(--cf-sec4-bg);
}
.cf-sec4__inner {
    max-width: var(--cf-nav-max);
    margin: 0 auto;
    padding: 96px 40px;
}

/* Mismo tratamiento que el título de "¿Cómo trabajamos?": Altone Bold Oblique,
   centrado. Los saltos de línea son explícitos (<br/> en la plantilla). */
.cf-sec4__title {
    /* Mismo ancho máximo que el panel y centrado igual, para que su borde
       izquierdo caiga en la misma vertical que el del panel. */
    max-width: 1320px;
    margin: 0 auto 56px;
    font-size: var(--cf-title);
    font-weight: 700;
    font-style: italic;
    line-height: 1.15;
    letter-spacing: -0.01em;
    text-align: left;
    color: var(--cf-text);
}

.cf-sec4__panelwrap {
    /* Radio de la muesca. Escala con la pantalla pero con topes, para que el
       icono no quede diminuto en móvil ni gigante en monitores grandes. */
    --cf-notch: clamp(46px, 6.6vw, 94px);

    position: relative;
    max-width: 1320px;
    margin: 0 auto;
}

/* Fondo del panel: gris con esquinas redondeadas y la muesca recortada con
   una máscara radial. Va en su PROPIA capa y no en el contenedor porque la
   máscara afecta también a los hijos: si estuviera en el wrapper, recortaría
   el icono justo por donde debe verse. */
.cf-sec4__panelbg {
    position: absolute;
    inset: 0;
    background: var(--cf-panel);
    border-radius: 37px;
    -webkit-mask-image: radial-gradient(circle var(--cf-notch) at 85% 0,
                                        transparent calc(100% - 1px), #000 100%);
            mask-image: radial-gradient(circle var(--cf-notch) at 85% 0,
                                        transparent calc(100% - 1px), #000 100%);
}

/* Icono centrado en la muesca, con 15px de separación real con el gris a
   cualquier tamaño: su radio es el de la muesca menos ese hueco. */
.cf-sec4__icon {
    position: absolute;
    z-index: 1;
    left: 85%;
    top: 0;
    width: calc(2 * (var(--cf-notch) - 15px));
    height: auto;
    transform: translate(-50%, -50%);
    animation: cf-latido 3s ease-in-out infinite;
}

/* Luz palpitante tenue. Va con drop-shadow y no con box-shadow: así el halo
   sigue el contorno redondo real del icono (canal alfa) en vez de la caja.
   Dos sombras superpuestas — una cercana y otra amplia — para que el brillo
   se difumine en vez de marcar un borde. */
@keyframes cf-latido {
    0%, 100% {
        filter: drop-shadow(0 0 4px rgba(0, 83, 255, .30))
                drop-shadow(0 0 10px rgba(0, 83, 255, .12));
    }
    50% {
        filter: drop-shadow(0 0 14px rgba(0, 83, 255, .55))
                drop-shadow(0 0 30px rgba(0, 83, 255, .28));
    }
}

@media (prefers-reduced-motion: reduce) {
    .cf-sec4__icon { animation: none; }
}

/* Contenido: dos tercios de texto y un tercio de imagen */
.cf-sec4__content {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: clamp(28px, 3.5vw, 56px);
    align-items: center;
    padding: clamp(36px, 4vw, 64px);
}

/* Cuerpo en Altone Medium (500) y un cuerpo mayor. El panel es CSS, así que
   crece solo para acomodarlo. */
.cf-sec4__text p {
    margin: 0 0 20px;
    font-size: clamp(16px, 1.45vw, 21px);
    font-weight: 500;
    line-height: 1.6;
    color: var(--cf-text);
    text-align: justify;
    /* Con el texto justificado, la partición evita los "ríos" de espacio
       blanco entre palabras largas (implementación, personalización…). */
    hyphens: auto;
}
.cf-sec4__text p:last-child { margin-bottom: 0; }

/* Lema en azul y negrita. Igual que .cf-brand-word: la familia no tiene Bold
   vertical, así que el 700 en estilo normal resuelve a ExtraBold (800), que
   es una cara real de Altone — nada de negrita sintética. */
/* Selector con el `p` incluido: `.cf-sec4__text p` (clase+elemento) le gana en
   especificidad a la clase suelta y le imponía su peso 500. */
.cf-sec4__text p.cf-sec4__claim {
    font-weight: 700;
    color: var(--cf-primary);
    letter-spacing: .01em;
}

/* Pegada abajo: en el centro quedaba justo bajo la muesca y se veía apretada
   contra ella. Alineada al pie, gana toda esa separación. */
.cf-sec4__media {
    align-self: end;
    margin-bottom: clamp(24px, 3.5vw, 56px);   /* la despega del pie */
}
/* Un poco más grande que su columna: crece hacia la izquierda, invadiendo el
   hueco entre columnas, para no salirse del panel por la derecha.
   El -12% se recorta a -7% para dejar 20px más de aire con el texto. */
.cf-sec4__media img {
    display: block;
    width: 107%;
    max-width: none;
    margin-left: -7%;
    height: auto;
    transform: translateY(10px);   /* 10px más abajo */
}

/* ==========================================================================
   SECCIÓN 5 — por ahora solo el panel azul. Es un <img> y no un fondo CSS
   porque la sección no lleva contenido dentro: así conserva su proporción
   sola y no hay que fijarle alto. Mismo tope de 1320px que el panel de la
   sección 4, para que los dos bordes caigan en la misma vertical.
   ========================================================================== */
.cf-sec5 {
    width: 100%;
    background: var(--cf-bg);
}
.cf-sec5__inner {
    max-width: var(--cf-nav-max);
    margin: 0 auto;
    padding: 96px 40px;
}
/* El título va ENCIMA del panel, así que este es el contenedor de referencia:
   la imagen marca el alto y el título se posiciona en % sobre ella, de modo
   que la separación con el borde superior se mantiene al escalar. */
.cf-sec5__panelwrap {
    position: relative;
    max-width: 1320px;
    margin: 0 auto;
}
.cf-sec5__panel {
    display: block;
    width: 100%;
    height: auto;
}

/* Mismo tratamiento que los demás títulos del sitio (Altone Bold Oblique),
   pero en blanco porque cae sobre el azul. */
.cf-sec5__title {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    /* Separación = 9% del alto del panel + 20px, pero expresada sobre el
       ANCHO: un `top: 9%` se resolvería contra el alto del contenedor, que
       incluye las tarjetas, y al apilarse en móvil el título se iba con
       ellas. Como el panel mide 3.012:1, ese 9% de su alto equivale a
       9/3.012 = 2.99% de su ancho, y los márgenes en % sí van por ancho. */
    margin: calc(2.99% + 20px) 0 0;
    padding: 0 24px;
    font-size: var(--cf-title);
    font-weight: 700;
    font-style: italic;
    line-height: 1.15;
    letter-spacing: -0.01em;
    text-align: center;
    color: var(--cf-on-primary);
}

/* Fila de tarjetas a caballo del borde inferior del panel: la mitad de su
   alto queda dentro del azul y la otra mitad sobresale por abajo.

   El truco es que van EN FLUJO detrás de la imagen (nada de position:absolute)
   y se suben con un margen negativo de medio alto de tarjeta. Así el propio
   contenedor ya reserva el sitio de la mitad que sobresale — alto del panel +
   media tarjeta — y no hay que compensar a mano ningún padding.

   El margen se calcula, no se adivina: los márgenes en % se resuelven contra
   el ANCHO del contenedor, igual que el ancho de las columnas, así que la
   cuenta se mantiene exacta a cualquier tamaño de pantalla. Las cuatro
   imágenes miden 600x931, de ahí el factor 931/600. */
.cf-sec5__cards {
    --cf-s5-pad: 4%;
    --cf-s5-gap: 2.5%;
    --cf-s5-card-w: calc((100% - 2 * var(--cf-s5-pad) - 3 * var(--cf-s5-gap)) / 4);
    --cf-s5-card-h: calc(var(--cf-s5-card-w) * 931 / 600);

    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--cf-s5-gap);
    padding: 0 var(--cf-s5-pad);
    margin-top: calc(var(--cf-s5-card-h) / -2);
}
.cf-sec5__card {
    display: block;
    width: 100%;
    height: auto;
}

/* ==========================================================================
   SECCIÓN 6 — llamada a la acción. Banda a sangre con el MISMO gris que el
   listón de logotipos (--cf-ribbon), y el contenido alineado al ancho del
   header y el hero.
   ========================================================================== */
.cf-cta {
    width: 100%;
    background: var(--cf-ribbon);
    border-top: 1px solid var(--cf-border);
    border-bottom: 1px solid var(--cf-border);
}
.cf-cta__inner {
    max-width: var(--cf-nav-max);
    margin: 0 auto;
    padding: 64px 40px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 48px;
}

/* Altone Bold Oblique, igual que los títulos del sitio. Cuerpo grande: es el
   reclamo de la sección, no un pie. El `flex: 1` le da todo el ancho que
   sobra tras los botones, que son los que mandan (no se encogen). */
.cf-cta__text {
    flex: 1 1 auto;
    margin: 0;
    font-size: var(--cf-title);
    font-weight: 700;
    font-style: italic;
    line-height: 1.1;
    letter-spacing: -0.015em;
    color: var(--cf-text);
}

/* Cifras de ancho fijo: mientras el contador sube, "1" y "7" ocupan lo mismo
   y la línea no baila. */
.cf-cta__count { font-variant-numeric: tabular-nums; }

.cf-cta__actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    /* Separación amplia: cada botón lleva halo y con poco hueco los dos
       resplandores se tocaban. */
    gap: 34px;
}

/* Misma píldora que el CTA del hero, halo incluido: es una copia del propio
   botón desenfocada por detrás (::before con z-index:-1), no un box-shadow,
   así el resplandor tiene la forma exacta de la píldora. Cada botón brilla de
   su color: azul el sólido, blanco el de contorno. */
.cf-cta__btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    padding: 16px 40px;
    border-radius: 999px;
    font-size: 18px;
    font-weight: 500;
    font-style: italic;
    line-height: 1.35;
    white-space: nowrap;
    isolation: isolate;   /* contiene el z-index:-1 del halo */
    transition: background .15s ease, color .15s ease;
}
.cf-cta__btn::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 2px 4px -6px;
    border-radius: inherit;
    filter: blur(16px);
    opacity: .6;
    transition: opacity .18s ease, filter .18s ease;
}
.cf-cta__btn:hover::before { opacity: .85; filter: blur(22px); }

.cf-cta__btn--solid {
    background: var(--cf-primary);
    color: var(--cf-on-primary) !important;
}
.cf-cta__btn--solid::before { background: var(--cf-primary); }
.cf-cta__btn--solid:hover { background: var(--cf-primary-2); }

.cf-cta__btn--ghost {
    background: #ffffff;
    color: var(--cf-primary) !important;
}
/* El halo blanco necesita más opacidad y menos desenfoque: sobre el gris del
   listón, un blanco muy difuminado casi no se ve. */
.cf-cta__btn--ghost::before {
    background: #ffffff;
    filter: blur(13px);
    opacity: .95;
}
.cf-cta__btn--ghost:hover { background: #f4f7ff; }
.cf-cta__btn:focus-visible {
    outline: 2px solid var(--cf-primary);
    outline-offset: 3px;
}

/* ==========================================================================
   CONTACTO — tarjeta partida: mitad azul con los anillos y mitad blanca con
   el formulario. Reutiliza el lenguaje del resto del sitio: el cuarto de
   anillo del hero, los anillos concéntricos de "¡Nuestros Servicios!" y la
   píldora con halo de los CTA.
   ========================================================================== */
.cf-form {
    position: relative;
    width: 100%;
    background: var(--cf-bg);
}

.cf-form__inner {
    position: relative;
    z-index: 1;
    max-width: var(--cf-max);
    margin: 0 auto;
    padding: 72px 40px 96px;
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    align-items: stretch;
    /* Sin gap: las dos mitades se tocan y forman UNA tarjeta. */
}

/* ---------- Mitad azul ---------- */
.cf-form__panel {
    position: relative;
    overflow: hidden;
    border-radius: 28px 0 0 28px;
    background: var(--cf-primary);
    padding: clamp(32px, 3.4vw, 52px);
    display: flex;
    align-items: center;
}
.cf-form__rings {
    position: absolute;
    z-index: 0;
    /* Más grande que la caja y descentrado: se ve un trozo de los anillos,
       como en el panel de la sección 5, no el dibujo completo centrado. */
    left: -30%;
    top: -20%;
    width: 160%;
    height: 140%;
    color: rgba(255, 255, 255, .2);
    pointer-events: none;
}
.cf-form__panelbody { position: relative; z-index: 1; }

.cf-form__eyebrow {
    margin: 0 0 14px;
    font-size: 13px;
    font-weight: 500;
    font-style: italic;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .72);
}
.cf-form__title {
    margin: 0 0 18px;
    font-size: clamp(30px, 3.1vw, 46px);
    font-weight: 700;
    font-style: italic;
    line-height: 1.08;
    letter-spacing: -0.015em;
    color: var(--cf-on-primary);
}
.cf-form__lead {
    margin: 0 0 30px;
    font-size: clamp(15px, 1.1vw, 17px);
    font-weight: 500;
    line-height: 1.55;
    color: rgba(255, 255, 255, .88);
}

.cf-form__data { display: flex; flex-direction: column; gap: 10px; }
.cf-form__datum {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: 16px;
    font-weight: 500;
    color: var(--cf-on-primary) !important;
}
.cf-form__datum:hover { opacity: .82; }
.cf-form__datumico {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .16);
}
/* Todos los iconos al mismo tamaño real. Antes eran glifos de texto y cada
   carácter se dibujaba a su aire: la arroba salía grande y el teléfono y el
   reloj, diminutos. */
.cf-form__datumico svg {
    width: 18px;
    height: 18px;
    display: block;
}

/* ---------- Mitad blanca ---------- */
.cf-form__card {
    border-radius: 0 28px 28px 0;
    background: var(--cf-bg);
    padding: clamp(28px, 3.4vw, 48px);
    box-shadow: 0 40px 80px -50px rgba(16, 24, 40, .55);
}

/* ---------- Campos con etiqueta flotante ---------- */
.cf-fld { position: relative; margin-bottom: 14px; }

.cf-fld__input {
    display: block;
    width: 100%;
    /* El relleno superior deja sitio a la etiqueta cuando sube */
    padding: 25px 18px 10px;
    border: 1px solid transparent;
    border-radius: 16px;
    background: #f1f4f9;
    font-family: var(--cf-font);
    font-size: 16px;   /* por debajo de 16px iOS hace zoom al enfocar */
    font-weight: 500;
    line-height: 1.35;
    color: var(--cf-text);
    transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.cf-fld__input:hover { background: #eaeef6; }
.cf-fld__input:focus {
    outline: none;
    background: var(--cf-bg);
    border-color: var(--cf-primary);
    box-shadow: 0 0 0 4px rgba(0, 83, 255, .13);
}

.cf-fld__label {
    position: absolute;
    left: 19px;
    top: 17px;
    font-size: 16px;
    font-weight: 500;
    color: #8a92a1;
    pointer-events: none;   /* el clic pasa al campo */
    transition: top .16s ease, font-size .16s ease, color .16s ease;
}
/* Sube cuando el campo tiene foco o contenido. `:placeholder-shown` es lo que
   detecta el "vacío", y por eso el HTML lleva placeholder=" ".

   OJO con el selector: la parte de :placeholder-shown va acotada a input y
   textarea A PROPÓSITO. Un <select> también lleva .cf-fld__input y nunca
   puede mostrar placeholder, así que `:not(:placeholder-shown)` se cumple
   siempre en él y su etiqueta salía flotada desde el principio. */
.cf-fld__input:focus + .cf-fld__label,
input.cf-fld__input:not(:placeholder-shown) + .cf-fld__label,
textarea.cf-fld__input:not(:placeholder-shown) + .cf-fld__label {
    top: 8px;
    font-size: 11.5px;
    letter-spacing: .04em;
    color: var(--cf-primary);
}

/* El <select> no admite :placeholder-shown: su etiqueta sube con :valid, que
   solo se cumple al elegir una opción distinta de la vacía. */
.cf-fld__select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 44px;
    cursor: pointer;
    /* El texto queda transparente mientras no hay elección: así no se ve la
       opción vacía solapada con la etiqueta grande. */
    color: transparent;
}
.cf-fld__select:valid { color: var(--cf-text); }
.cf-fld__select:valid + .cf-fld__label,
.cf-fld__select:focus + .cf-fld__label {
    top: 8px;
    font-size: 11.5px;
    letter-spacing: .04em;
    color: var(--cf-primary);
}
.cf-fld__chev {
    position: absolute;
    right: 20px;
    top: 26px;
    width: 8px;
    height: 8px;
    border-right: 2px solid #8a92a1;
    border-bottom: 2px solid #8a92a1;
    transform: rotate(45deg);
    pointer-events: none;
}

.cf-fld--area .cf-fld__label { top: 17px; }
.cf-fld__area {
    resize: vertical;
    min-height: 104px;
    padding-top: 28px;
}

.cf-fld__error {
    margin: 6px 0 0 4px;
    font-size: 13px;
    font-weight: 500;
    color: #c4304b;
    /* El mensaje entra desplazado un pelo: el movimiento es lo que hace que
       se note que ha aparecido algo, sin necesidad de parpadeos. */
    animation: cf-fld-error-in .18s ease-out both;
}
@keyframes cf-fld-error-in {
    from { opacity: 0; transform: translateY(-3px); }
    to   { opacity: 1; transform: none; }
}

/* ---------- Campo inválido ----------
   Lo marca app.js (`.cf-fld--error`), NUNCA el selector :invalid del
   navegador: :invalid casa desde el primer instante y pintaría de rojo un
   formulario vacío que nadie ha tocado todavía. */
.cf-fld--error .cf-fld__input {
    border-color: #d64560;
    background: #fdf5f6;
}
.cf-fld--error .cf-fld__input:focus {
    border-color: #c4304b;
    box-shadow: 0 0 0 4px rgba(196, 48, 75, .15);
}
/* Los tres selectores repiten los de la etiqueta flotante de arriba, que al
   llevar `.cf-fld__input` + pseudoclase pesan más que un simple
   `.cf-fld--error .cf-fld__label` y dejaban la etiqueta en azul sobre un
   campo en rojo. */
.cf-fld--error .cf-fld__label,
.cf-fld--error .cf-fld__input:focus + .cf-fld__label,
.cf-fld--error input.cf-fld__input:not(:placeholder-shown) + .cf-fld__label,
.cf-fld--error textarea.cf-fld__input:not(:placeholder-shown) + .cf-fld__label {
    color: #c4304b;
}

/* Sacudida corta al marcar. Es la única señal para quien no distingue bien el
   rojo, así que no depende del color. */
.cf-fld--error .cf-fld__input {
    animation: cf-fld-shake .3s ease-in-out both;
}
@keyframes cf-fld-shake {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-4px); }
    75%      { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
    .cf-fld__error,
    .cf-fld--error .cf-fld__input { animation: none; }
}
.cf-form__fail {
    margin: 0 0 14px;
    padding: 12px 14px;
    border-radius: 12px;
    background: #fdeef1;
    font-size: 14px;
    font-weight: 500;
    color: #c4304b;
}

/* Botón: la misma píldora con halo que los CTA del sitio. */
.cf-form__btn {
    position: relative;
    display: block;
    width: 100%;
    margin-top: 10px;
    padding: 17px 32px;
    border: 0;
    border-radius: 999px;
    background: var(--cf-primary);
    color: var(--cf-on-primary);
    font-family: var(--cf-font);
    font-size: 17px;
    font-weight: 500;
    font-style: italic;
    cursor: pointer;
    isolation: isolate;
    transition: background .15s ease, transform .15s ease;
}
.cf-form__btn::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 3px 8px -8px;
    border-radius: inherit;
    background: var(--cf-primary);
    filter: blur(18px);
    opacity: .55;
    transition: opacity .18s ease, filter .18s ease;
}
.cf-form__btn:hover { background: var(--cf-primary-2); transform: translateY(-1px); }
.cf-form__btn:hover::before { opacity: .8; filter: blur(24px); }
.cf-form__btn[disabled] { opacity: .6; cursor: default; transform: none; }
.cf-form__btn[disabled]::before { opacity: .3; }

.cf-form__legal {
    margin: 14px 0 0;
    font-size: 12.5px;
    font-weight: 400;
    line-height: 1.45;
    text-align: center;
    color: var(--cf-muted);
}

/* Trampa antispam: fuera de la vista sin display:none ni visibility, que
   algunos bots detectan y saltan. */
.cf-form__trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* ---------- Panel de éxito ---------- */
.cf-form__ok { text-align: center; padding: 30px 8px; }
.cf-form__okicon {
    display: grid;
    place-items: center;
    width: 68px;
    height: 68px;
    margin: 0 auto 20px;
    border-radius: 50%;
    background: var(--cf-primary);
    color: var(--cf-on-primary);
    box-shadow: 0 18px 34px -18px rgba(0, 83, 255, .8);
}
.cf-form__okicon svg { width: 30px; height: 30px; }
.cf-form__oktitle {
    margin: 0 0 10px;
    font-size: 28px;
    font-weight: 700;
    font-style: italic;
    color: var(--cf-text);
}
.cf-form__oktext {
    margin: 0;
    font-size: 16px;
    font-weight: 500;
    color: var(--cf-muted);
}

/* ==========================================================================
   FOOTER
   ========================================================================== */
.cf-footer {
    background: var(--cf-surface);
    border-top: 1px solid var(--cf-border);
}
.cf-footer__inner {
    max-width: var(--cf-max);
    margin: 0 auto;
    padding: 56px 24px 32px;
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 40px;
}
.cf-footer__brandcol .cf-nav__brand { margin-bottom: 14px; }
.cf-footer__brandcol .cf-nav__logo { height: 30px; }
.cf-footer__tagline { color: var(--cf-muted); margin: 0; max-width: 280px; }
.cf-footer__title {
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--cf-muted);
    margin: 0 0 16px;
}
.cf-footer__col { display: flex; flex-direction: column; }
.cf-footer__link {
    color: var(--cf-text);
    padding: 6px 0;
    font-size: 15px;
    transition: color .15s ease;
}
.cf-footer__link:hover { color: var(--cf-primary); }
.cf-footer__bar {
    border-top: 1px solid var(--cf-border);
    padding: 20px 24px;
    text-align: center;
    color: var(--cf-muted);
    font-size: 14px;
}

/* ==========================================================================
   UTILIDADES compartidas (las usan las plantillas de /shop)
   ========================================================================== */
.cf-container { max-width: var(--cf-max); margin: 0 auto; padding: 0 24px; }

.cf-eyebrow {
    display: inline-block;
    font-size: 13px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--cf-primary);
    font-weight: 600;   /* Altone no trae Bold 700: SemiBold es el peso alto real */
    margin-bottom: 16px;
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

/* Tablet: las 4 columnas del footer se aprietan antes de llegar al móvil.
   Va ANTES del bloque de 820px para que ese gane en la cascada. */
@media (max-width: 1024px) {
    .cf-footer__inner { grid-template-columns: 1fr 1fr; }

    /* El hero pasa a una columna: primero el texto, luego las imágenes.
       minmax(0,1fr) y no 1fr: con `1fr` el mínimo de la columna es el
       min-content del contenido, y el marco de imágenes (aspect-ratio +
       min-height) exigía 352px de ancho, desbordando la pantalla a 320px. */
    .cf-hero__inner {
        grid-template-columns: minmax(0, 1fr);
        gap: 40px;
        padding: 56px 40px 72px;
    }
    .cf-hero__sub { max-width: none; }
    /* En una sola columna, el 50% dejaría el círculo diminuto: aquí ocupa más
       proporción de la pantalla, con un tope para que no crezca en tablet. */
    /* En una sola columna no hay columna de texto que marque la altura: el
       círculo vuelve a dimensionarse por ancho y sin márgenes negativos. */
    .cf-hero__media { align-self: auto; margin: 0; }
    /* En una sola columna el círculo va centrado, sin desplazamiento */
    .cf-hero__stack { width: 84%; max-width: 408px; transform: none; }

    /* Tarjetas: por debajo de 1025px no caben tres en fila. Se reparten en una
       rejilla que se adapta sola (2 columnas en tablet, 1 en móvil). Sin
       scroll horizontal, sin tarjetas cortadas y sin reordenado — app.js usa
       este mismo umbral para desactivar el efecto. */
    .cf-cards__stage {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
        /* stretch, no el `center` heredado: las de una misma fila deben
           igualar altura aunque su texto sea más corto. */
        align-items: stretch;
        gap: 20px;
        padding: 24px 20px 32px;
    }
    .cf-card {
        flex: none;                  /* manda la rejilla, no el flex */
        cursor: default;
    }

    /* Sin carrusel no hay nada que navegar: las tres tarjetas se ven a la vez
       en la rejilla, así que flechas e indicadores sobran. */
    .cf-cards__carousel { display: block; }
    .cf-cards__nav,
    .cf-cards__dots { display: none; }

    /* Arco a sangre: más ancho que la pantalla, así la curva queda suave y el
       azul llega a ambos bordes en vez de flotar con márgenes blancos. El tope
       de 1100px garantiza que nunca baje del ancho del viewport en este rango.
       El relleno inferior sitúa la frase DENTRO del azul (~45% de su alto),
       donde la curva es ancha y el texto blanco se lee entero. */
    .cf-cards { --cf-arc-w: min(140vw, 1100px); }
    .cf-cards__inner { padding-bottom: calc(var(--cf-arc-w) / 2.45 * 0.45 + 24px); }
    .cf-cards__claim { margin-top: 20px; }

    /* Con cuatro columnas aquí las tarjetas quedan ilegibles (el texto va
       DENTRO de la imagen y no se puede remaquetar): pasan a dos y se sitúan
       DEBAJO del panel. El montaje a caballo del borde es una composición de
       escritorio; a dos columnas la tarjeta es tan alta que medio alto suyo
       supera al del panel entero y lo taparía. */
    .cf-sec5__cards {
        grid-template-columns: repeat(2, 1fr);
        gap: 20px;
        padding: 0;
        margin-top: 24px;
    }

    /* La tarjeta partida se apila: azul arriba, formulario debajo. Las
       esquinas redondeadas se reparten en horizontal en vez de en vertical
       para que las dos mitades sigan leyéndose como una sola tarjeta. */
    .cf-form__inner {
        grid-template-columns: minmax(0, 1fr);
        padding: 56px 20px 72px;
    }
    .cf-form__panel { border-radius: 28px 28px 0 0; }
    .cf-form__card  { border-radius: 0 0 28px 28px; }

    /* En una sola columna el texto y los botones no compiten por el ancho */
    .cf-cta__inner {
        flex-direction: column;
        align-items: flex-start;
        gap: 28px;
        padding: 56px 20px;
    }
}

/* Móvil: dos columnas dejarían cada tarjeta en ~165px y su texto sería
   ilegible. Una sola columna, con tope para que no se estire. */
@media (max-width: 560px) {
    .cf-sec5__cards {
        grid-template-columns: 1fr;
        max-width: 360px;
        margin-left: auto;
        margin-right: auto;
    }

    /* Los dos botones en fila no caben: apilan a todo el ancho */
    .cf-cta__actions {
        flex-direction: column;
        align-items: stretch;
        align-self: stretch;
    }
    .cf-cta__btn { justify-content: center; }
}

@media (max-width: 820px) {
    /* En pantallas chicas el aire lateral de 40px se come el espacio útil */
    .cf-nav__inner { padding: 0 20px; }
    .cf-hero__inner { padding: 40px 20px 56px; }

    /* El listón apila: rótulo arriba, marquesina abajo a todo el ancho. */
    .cf-trust__inner {
        flex-direction: column;
        align-items: flex-start;
        gap: 16px;
        padding: 20px;
    }
    .cf-trust__marquee { width: 100%; }
    .cf-trust__group { gap: 40px; padding-right: 40px; }

    .cf-how__inner { padding: 56px 20px; }
    .cf-sec4__inner { padding: 56px 20px; }
    .cf-sec5__inner { padding: 56px 20px; }
    .cf-sec4__title { margin-bottom: 32px; }
    /* El panel apila: primero el texto, la imagen debajo */
    .cf-sec4__content {
        grid-template-columns: 1fr;
        gap: 28px;
    }
    /* Apilado: la imagen vuelve a su tamaño y se centra */
    .cf-sec4__media { max-width: 420px; margin: 0 auto; }
    .cf-sec4__media img { width: 100%; margin-left: 0; }

    .cf-nav__menu { padding-left: 20px; padding-right: 20px; }

    .cf-nav__burger {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        width: 26px;
        height: 18px;
        cursor: pointer;
    }
    .cf-nav__burger span {
        display: block;
        height: 2px;
        width: 100%;
        background: var(--cf-text);
        border-radius: 2px;
        transition: transform .2s ease, opacity .2s ease;
    }
    .cf-nav__menu {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: flex-start;
        gap: 0;
        /* Colapsado: sin padding ni borde. Con box-sizing:border-box el
           max-height:0 no puede comerse el padding, y dejaba asomando una
           franja del desplegable bajo el header. */
        padding: 0 24px;
        background: var(--cf-bg);
        border-bottom: 1px solid transparent;
        max-height: 0;
        overflow: hidden;
        transition: max-height .25s ease, padding .25s ease,
                    border-color .25s ease, box-shadow .25s ease;
    }
    /* Alto máximo por viewport (no fijo): con los acordeones abiertos el
       contenido crece, y el panel hace scroll en vez de recortarse. */
    .cf-nav__checkbox:checked ~ .cf-nav__menu {
        max-height: calc(100vh - var(--cf-nav-h-sm));
        overflow-y: auto;
        padding: 12px 24px 20px;
        border-bottom-color: var(--cf-border);
        box-shadow: 0 12px 24px -18px rgba(16, 24, 40, .5);
    }
    /* En el desplegable los enlaces ocupan toda la fila; el botón de sesión
       se queda arriba, a la derecha, junto a la hamburguesa. */
    .cf-nav__link { width: 100%; padding: 12px 0; }
    .cf-nav__cta { padding: 4px 14px; font-size: 15px; }

    /* Los desplegables son acordeones dentro de la lista. Aquí NO interviene
       el hover (en táctil se queda pegado): manda el checkbox. */
    .cf-nav__item { width: 100%; }
    .cf-nav__link--parent { width: 100%; justify-content: space-between; }

    .cf-nav__dropdown {
        max-height: 0;
        overflow: hidden;
        padding-left: 14px;
        margin-left: 2px;
        border-left: 2px solid var(--cf-border);
        transition: max-height .25s ease, padding .25s ease;
    }
    .cf-sub__checkbox:checked ~ .cf-nav__dropdown {
        max-height: 260px;
        padding-bottom: 4px;
    }
    .cf-sub__checkbox:checked ~ .cf-nav__link--parent .cf-caret {
        transform: rotate(-135deg) translate(-1px, -1px);
    }
    .cf-nav__sublink { padding: 10px 0; }

    .cf-footer__inner { grid-template-columns: 1fr; gap: 32px; }
}

/* ==========================================================================
   CITAS (módulo nativo `appointment` de Enterprise)

   Se reviste la interfaz NATIVA sin tocar sus plantillas: solo CSS sobre las
   clases que Odoo ya pinta. Así el módulo se puede actualizar sin que se
   rompa nada nuestro, y las preguntas que se añadan desde Citas > Tipos de
   cita salen ya con este estilo, sean del tipo que sean.

   Los ganchos son sus dos contenedores de página:
     #wrap.o_appointment_index   → listado de tipos de cita
     #wrap.o_wappointment_wrap   → calendario y formulario
   ========================================================================== */

/* Odoo pinta sus botones con el color primario del TEMA (un vinotinto), no
   con la paleta del cliente. Se reenganchan a nuestro azul dentro del flujo
   de citas. Lleva !important porque Bootstrap declara estas mismas
   propiedades con variables propias y su regla es igual de específica. */
.o_appointment_index .btn-primary,
.o_wappointment_wrap .btn-primary {
    background: var(--cf-primary) !important;
    border-color: var(--cf-primary) !important;
    color: var(--cf-on-primary) !important;
    border-radius: 999px;
    padding: 13px 30px;
    font-weight: 500;
    font-style: italic;   /* Altone Medium Oblique, como los CTA del sitio */
    transition: background .15s ease;
}
.o_appointment_index .btn-primary:hover,
.o_wappointment_wrap .btn-primary:hover {
    background: var(--cf-primary-2) !important;
    border-color: var(--cf-primary-2) !important;
}
.o_appointment_index a,
.o_wappointment_wrap a { color: var(--cf-primary); }

/* Títulos de las tres vistas: Altone Bold Oblique como los de la home, pero
   un punto más discretos (aquí el protagonista es el calendario). */
.o_appointment_index h1,
.o_wappointment_wrap h1 {
    font-size: clamp(26px, 2.6vw, 38px);
    font-weight: 700;
    font-style: italic;
    letter-spacing: -0.015em;
    color: var(--cf-text);
}

/* --------------------------------------------------------------------------
   1 · LISTADO DE TIPOS DE CITA
   -------------------------------------------------------------------------- */
.o_appointment_index .o_appointment_choice { padding-bottom: 72px; }

.o_appointment_index .o_wappointment_card {
    border: 1px solid var(--cf-border);
    border-radius: 22px;
    overflow: hidden;   /* recorta la imagen contra las esquinas redondeadas */
    transition: box-shadow .25s ease, transform .25s ease;
}
.o_appointment_index .o_wappointment_card:hover {
    transform: translateY(-3px);
    box-shadow: 0 26px 54px -34px rgba(16, 24, 40, .5);
}
.o_appointment_index .o_wappointment_card .card-title {
    font-size: 20px;
    font-weight: 600;
    color: var(--cf-text);
}
.o_appointment_index .o_wappointment_card_location {
    color: var(--cf-muted) !important;
    font-weight: 500;
}
.o_appointment_index .o_wappointment_card .btn-primary { width: 100%; }

/* Buscador: misma píldora que los campos del formulario de contacto */
.o_appointment_index .o_searchbar_form .input-group {
    border: 1px solid var(--cf-border);
    border-radius: 999px;
    overflow: hidden;
    background: #f1f4f9;
}
.o_appointment_index .o_searchbar_form .form-control {
    background: transparent !important;
    border: 0;
    padding: 12px 20px;
    font-size: 15px;
    box-shadow: none;
}
.o_appointment_index .o_searchbar_form .btn { background: transparent; border: 0; }

/* --------------------------------------------------------------------------
   2 · CALENDARIO Y SELECCIÓN DE HORA

   Aquí NO se repinta el Bootstrap de Odoo: se rehace la pieza. La rejilla
   nativa es una <table> con botones cuadrados; encima se construye un
   calendario con cabecera azul, días circulares y horas en fichas con barra
   de acento. Todo con las clases que ya emite el módulo, sin tocar su QWeb.
   -------------------------------------------------------------------------- */

/* ---- Tarjeta del calendario ---- */
.o_wappointment_wrap #calendar {
    border: 0 !important;
    border-radius: 24px !important;
    overflow: hidden;
    background: var(--cf-bg);
    /* El anillo de 1px va en la sombra y no en `border`: así no suma al
       tamaño de la caja y la cabecera azul llega limpia hasta el borde. */
    box-shadow: 0 0 0 1px var(--cf-border),
                0 34px 70px -48px rgba(16, 24, 40, .6);
}

/* Cabecera: banda azul con degradado, como el panel de contacto */
.o_wappointment_wrap #calendarHeader {
    padding: 18px 16px !important;
    border-bottom: 0 !important;
    background: linear-gradient(135deg, var(--cf-primary) 0%, var(--cf-primary-2) 100%);
}
.o_wappointment_wrap .o_appointment_month_name {
    font-size: 20px;
    font-weight: 700;
    font-style: italic;
    letter-spacing: -0.01em;
    color: var(--cf-on-primary);
    text-transform: capitalize;
}
/* Flechas de mes: círculos translúcidos sobre el azul */
.o_wappointment_wrap #prevCal,
.o_wappointment_wrap #nextCal {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0 !important;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18) !important;
    color: var(--cf-on-primary) !important;
    transition: background .15s ease;
}
.o_wappointment_wrap #prevCal:hover,
.o_wappointment_wrap #nextCal:hover { background: rgba(255, 255, 255, .34) !important; }

/* ---- Rejilla ---- */
.o_wappointment_wrap #calendar table {
    padding: 14px 12px 18px;
    border-collapse: separate;
    border-spacing: 0 4px;
}
.o_wappointment_wrap .o_website_calendar_weekdays th {
    padding-bottom: 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #9aa2b1;
}
/* El gris de las columnas de fin de semana ensucia la rejilla: fuera. La
   distinción ya la da que esos días no tengan horas disponibles. */
.o_wappointment_wrap td.o_weekend { background: transparent !important; }

/* ---- Días: círculos, no botones cuadrados ----
   El :not(.d-none) es imprescindible: los días que caen fuera del mes llevan
   esa clase de Bootstrap para ocultarse, y un `display: grid !important` sin
   filtrar los volvía a mostrar. */
.o_wappointment_wrap .o_day_wrapper:not(.d-none) {
    display: grid !important;
    place-items: center;
    width: 42px;
    height: 42px;
    margin: 0 auto !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 50% !important;
    font-size: 15px;
    font-weight: 500;
    color: #b6bcc8;              /* día sin disponibilidad: apagado */
    background: transparent;
}

/* Día con horas libres */
.o_wappointment_wrap .o_day_wrapper.o_slot_button {
    background: rgba(0, 83, 255, .07);
    color: var(--cf-primary) !important;
    font-weight: 600;
    cursor: pointer;
    transition: background .18s ease, color .18s ease,
                transform .18s ease, box-shadow .18s ease;
}
.o_wappointment_wrap .o_day_wrapper.o_slot_button:hover {
    background: rgba(0, 83, 255, .16);
    transform: translateY(-1px) scale(1.06);
}
/* Día elegido: relleno sólido con halo. `.active` la pone el JS nativo. */
.o_wappointment_wrap .o_day_wrapper.o_slot_button.active,
.o_wappointment_wrap .o_day_wrapper.o_slot_selected {
    background: var(--cf-primary) !important;
    color: var(--cf-on-primary) !important;
    transform: none;
    box-shadow: 0 0 0 4px rgba(0, 83, 255, .16),
                0 12px 22px -12px rgba(0, 83, 255, .9);
}

/* Hoy: punto azul debajo del número, en vez del subrayado nativo */
.o_wappointment_wrap td.o_today .o_day_wrapper { position: relative; }
.o_wappointment_wrap td.o_today .o_day_wrapper::after {
    content: "";
    position: absolute;
    bottom: 6px;
    left: 50%;
    width: 4px;
    height: 4px;
    margin-left: -2px;
    border-radius: 50%;
    background: currentColor;
    opacity: .75;
}

/* ---- Horas ---- */
.o_wappointment_wrap .o_appointment_calendar_form label { color: var(--cf-muted); }

.o_wappointment_wrap .o_slot_hours {
    position: relative;
    overflow: hidden;
    align-items: flex-start !important;
    padding: 13px 16px 13px 20px;
    border: 1px solid var(--cf-border) !important;
    border-radius: 14px !important;
    background: var(--cf-bg);
    color: var(--cf-text) !important;
    font-size: 16px;
    font-weight: 600;
    text-align: left;
    transition: background .18s ease, border-color .18s ease,
                transform .18s ease, box-shadow .18s ease;
    /* Las horas las inyecta el JS al elegir día: la animación se reproduce
       sola en cada cambio de día, sin una línea de JavaScript nuestra. */
    animation: cf-slot-in .28s ease both;
}
/* Barra de acento a la izquierda: crece al pasar el ratón */
.o_wappointment_wrap .o_slot_hours::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: var(--cf-primary);
    transform: scaleY(0);
    transition: transform .2s ease;
}
.o_wappointment_wrap .o_slot_hours:hover {
    background: rgba(0, 83, 255, .05);
    border-color: rgba(0, 83, 255, .45) !important;
    transform: translateY(-2px);
    box-shadow: 0 14px 24px -16px rgba(0, 83, 255, .95);
}
.o_wappointment_wrap .o_slot_hours:hover::before { transform: scaleY(1); }
.o_wappointment_wrap .o_slot_hours.o_slot_selected,
.o_wappointment_wrap .o_slot_hours.active {
    background: var(--cf-primary) !important;
    border-color: var(--cf-primary) !important;
    color: var(--cf-on-primary) !important;
}
.o_wappointment_wrap .o_slot_hours.o_slot_selected::before,
.o_wappointment_wrap .o_slot_hours.active::before { transform: scaleY(1); background: #fff; }

@keyframes cf-slot-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .o_wappointment_wrap .o_slot_hours { animation: none; }
}

/* Zona horaria: control auxiliar, en chip pequeño */
.o_wappointment_wrap .o_appointment_timezone_selection {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 16px;
    font-size: 13.5px;
    color: var(--cf-muted);
}
.o_wappointment_wrap .o_appointment_timezone_selection select {
    width: auto;
    /* Los nombres de zona son largos (America/Mexico_City): con 260px se
       cortaban dentro del propio control. */
    max-width: 320px;
    padding: 8px 36px 8px 16px;
    border-radius: 999px;
    font-size: 13.5px;
    font-weight: 500;
}

/* ---- Columna de resumen ---- */
.o_wappointment_wrap .o_appointment_details_column {
    align-self: start;
    padding: clamp(20px, 2.2vw, 28px);
    border: 1px solid var(--cf-border);
    border-radius: 22px;
    background: #f8fafc;
}
.o_wappointment_wrap .o_appointment_details_column h4 {
    font-weight: 700;
    font-style: italic;
    color: var(--cf-text);
}
.o_wappointment_wrap .o_appointment_details_column .text-uppercase {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    color: var(--cf-muted) !important;
}
.o_wappointment_wrap .o_appointment_details_type i,
.o_wappointment_wrap .o_appointment_details_column .fa,
.o_wappointment_wrap .o_appointment_details_column .oi { color: var(--cf-primary); }

/* --------------------------------------------------------------------------
   3 · FORMULARIO DE RESERVA

   Mismo aspecto que el formulario de contacto: relleno suave, esquinas de
   16px y anillo azul al enfocar. Se estiliza por TIPO de control
   (.form-control, .form-select, .form-check-input), no pregunta por
   pregunta, para que cualquier pregunta nueva que se cree en el módulo
   —texto, teléfono, desplegable, opción única o casillas— salga ya bien.
   -------------------------------------------------------------------------- */
.o_wappointment_wrap .o_appointment_attendee_form {
    padding: clamp(24px, 2.6vw, 36px);
    border: 1px solid var(--cf-border);
    border-radius: 22px;
    box-shadow: 0 30px 60px -50px rgba(16, 24, 40, .5);
}

.o_wappointment_wrap .col-form-label,
.o_wappointment_wrap .o_appointment_attendee_form label {
    font-weight: 500 !important;
    font-size: 15px;
    color: var(--cf-text);
}

.o_wappointment_wrap .form-control,
.o_wappointment_wrap .form-select {
    padding: 13px 16px;
    border: 1px solid transparent;
    border-radius: 16px;
    /* background-COLOR y no el atajo `background`: el atajo borra también la
       imagen de fondo, y en .form-select esa imagen ES la flecha del
       desplegable, que desaparecía. */
    background-color: #f1f4f9;
    font-family: var(--cf-font);
    font-size: 16px;   /* por debajo de 16px iOS hace zoom al enfocar */
    font-weight: 500;
    color: var(--cf-text);
    transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.o_wappointment_wrap .form-control:hover,
.o_wappointment_wrap .form-select:hover { background-color: #eaeef6; }
.o_wappointment_wrap .form-control:focus,
.o_wappointment_wrap .form-select:focus {
    background-color: var(--cf-bg);
    border-color: var(--cf-primary);
    box-shadow: 0 0 0 4px rgba(0, 83, 255, .13);
}
.o_wappointment_wrap textarea.form-control { min-height: 120px; resize: vertical; }

/* Opción única y casillas: el `accent-color` tiñe el control nativo del
   navegador sin tener que redibujarlo, así conserva su accesibilidad. */
.o_wappointment_wrap .form-check-input {
    width: 18px;
    height: 18px;
    margin-top: .15em;
    border-color: #c3cad6;
    accent-color: var(--cf-primary);
}
.o_wappointment_wrap .form-check-input:checked {
    background-color: var(--cf-primary);
    border-color: var(--cf-primary);
}
.o_wappointment_wrap .form-check-input:focus {
    border-color: var(--cf-primary);
    box-shadow: 0 0 0 4px rgba(0, 83, 255, .13);
}
/* Las casillas de una pregunta múltiple vienen dentro de un .form-control
   con borde: sobra, ya las agrupa la etiqueta. */
.o_wappointment_wrap .checkbox.form-control {
    background: transparent;
    border: 0;
    padding-left: 0;
}

.o_wappointment_wrap .o_appointment_form_confirm_btn { min-width: 220px; }
.o_wappointment_wrap .o_appointment_input_guest_add { font-weight: 500; }
.o_wappointment_wrap .o_appointment_validation_error,
.o_wappointment_wrap .o_appointment_error_text {
    border: 0;
    border-radius: 12px;
    background: #fdeef1;
    color: #c4304b;
    font-weight: 500;
}

@media (max-width: 820px) {
    .o_wappointment_wrap .o_appointment_details_column { margin-bottom: 24px; }
    .o_wappointment_wrap .o_appointment_attendee_form { padding: 20px; }
}

/* --- Retoques tras ver el render ------------------------------------------ */

/* Odoo tiñe con el primario del TEMA no solo los botones: también los enlaces
   `.text-primary` ("Iniciar sesión" del título) y los `.btn-link` ("Agregar
   invitados"). Se reenganchan al azul del cliente. */
.o_appointment_index .text-primary,
.o_wappointment_wrap .text-primary,
.o_appointment_index .btn-link,
.o_wappointment_wrap .btn-link { color: var(--cf-primary) !important; }
.o_wappointment_wrap .btn-link .oi,
.o_wappointment_wrap .btn-link .fa { color: inherit; }


/* --------------------------------------------------------------------------
   4 · CONFIRMACIÓN DE LA CITA

   Odoo la resuelve con una rejilla de Bootstrap (filas col-3 / col-9) y un
   botón rojo de cancelar. Aquí se convierte en una tarjeta de éxito con el
   mismo lenguaje que el panel de "¡Mensaje enviado!" del formulario de
   contacto: insignia circular, título en Altone Bold Oblique y los datos
   como lista con separadores finos.

   La página comparte contenedor con el resto del flujo
   (#wrap.o_wappointment_wrap), así que hereda ya tipografía y botones; lo de
   aquí es solo lo propio de esta vista.
   -------------------------------------------------------------------------- */

/* Insignia de éxito: el icono nativo es un `fa-check-circle` verde suelto.
   Se convierte en una pastilla azul de la marca, como la del formulario. */
.o_wappointment_wrap .fa-check-circle.text-success {
    display: inline-grid;
    place-items: center;
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: var(--cf-primary);
    color: var(--cf-on-primary) !important;
    font-size: 26px;
    box-shadow: 0 16px 30px -16px rgba(0, 83, 255, .85);
}
.o_wappointment_wrap h2 {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 4px;
    font-size: clamp(28px, 2.8vw, 40px);
    font-weight: 700;
    font-style: italic;
    letter-spacing: -0.015em;
    color: var(--cf-text);
}
/* Línea con el nombre de quien reserva y el tipo de cita */
.o_wappointment_wrap h4.py-3 {
    font-size: 17px;
    font-weight: 500;
    color: var(--cf-muted);
}

/* Separación entre las dos tarjetas. El aire lo daban las clases `pe-md-4` y
   `px-md-4` de Bootstrap, que son relleno INTERIOR de cada columna: al
   convertirlas en tarjetas con fondo y borde, ese aire quedó dentro y las dos
   cajas se tocaron. Se estrechan las columnas para que el hueco quede entre
   ellas (la fila ya viene con justify-content: space-between). */
.o_wappointment_wrap .o_appointment_validation_details { row-gap: 20px; }

@media (min-width: 768px) {
    .o_wappointment_wrap .o_appointment_validation_details > .col-md-8 {
        flex: 0 0 auto;
        width: calc(66.6667% - 14px);
    }
    .o_wappointment_wrap .o_appointment_validation_details > .col-md-4 {
        flex: 0 0 auto;
        width: calc(33.3333% - 14px);
    }
}

/* Bloque de datos: tarjeta con filas separadas por líneas finas */
.o_wappointment_wrap .o_appointment_validation_details > .col-12:first-child {
    padding: clamp(22px, 2.4vw, 34px) !important;
    border: 1px solid var(--cf-border);
    border-radius: 22px;
    background: var(--cf-bg);
    box-shadow: 0 30px 60px -50px rgba(16, 24, 40, .5);
}
.o_wappointment_wrap .o_appointment_validation_details .row.mb-4 {
    margin: 0 0 14px !important;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--cf-border);
}
.o_wappointment_wrap .o_appointment_validation_details .row.mb-4:last-child {
    margin-bottom: 0 !important;
    padding-bottom: 0;
    border-bottom: 0;
}
/* Etiqueta de cada dato: rótulo pequeño en mayúsculas */
.o_wappointment_wrap .o_appointment_validation_details .col-3 span.text-muted {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #9aa2b1 !important;
}
.o_wappointment_wrap .o_appointment_validation_details .col-9 { color: var(--cf-text); }
.o_wappointment_wrap .o_appointment_validation_details .col-9 .text-muted { color: var(--cf-muted) !important; }

/* Botones de "añadir a mi calendario": píldoras de contorno, no cajas grises */
.o_wappointment_wrap .o_appointment_add_to_calendar_btns .btn {
    padding: 10px 18px;
    border: 1px solid var(--cf-border) !important;
    border-radius: 999px;
    background: var(--cf-bg) !important;
    font-size: 14px;
    font-weight: 500;
    color: var(--cf-text) !important;
    transition: border-color .15s ease, background .15s ease, transform .15s ease;
}
.o_wappointment_wrap .o_appointment_add_to_calendar_btns .btn:hover {
    border-color: var(--cf-primary) !important;
    background: rgba(0, 83, 255, .05) !important;
    transform: translateY(-1px);
}

/* Asistentes: el check de confirmado en verde chilla al lado del azul */
.o_wappointment_wrap .o_appointment_validation_details .fa-check { color: #12a150 !important; }

/* Cancelar: acción destructiva y secundaria. Un botón rojo sólido compite
   con el mensaje de éxito; se deja como contorno discreto. */
.o_wappointment_wrap .btn-danger {
    padding: 11px 24px !important;
    border: 1px solid #e6b3bd !important;
    border-radius: 999px;
    background: transparent !important;
    color: #c4304b !important;
    font-size: 14px;
    font-weight: 500;
    font-style: normal;
    transition: background .15s ease, border-color .15s ease;
}
.o_wappointment_wrap .btn-danger:hover {
    background: #fdeef1 !important;
    border-color: #c4304b !important;
}
.o_wappointment_wrap .o_appointment_cancel_link { color: var(--cf-muted); font-size: 14px; }

/* Columna del operador */
.o_wappointment_wrap .o_appointment_validation_details > .col-md-4 {
    align-self: start;
    padding: clamp(20px, 2.2vw, 26px) !important;
    border: 1px solid var(--cf-border);
    border-radius: 22px;
    background: #f8fafc;
}
.o_wappointment_wrap .o_appointment_user_short_card {
    background: transparent;
    border: 0;
}
/* El blanco no lo pinta la tarjeta sino su .card-body (rgba(255,255,255,.9)
   del tema de Odoo): dejaba una banda blanca sobre el gris de la columna. */
.o_wappointment_wrap .o_appointment_user_short_card .card-body {
    padding: 0;
    background: transparent !important;
}
.o_wappointment_wrap .o_appointment_user_short_card h5 {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: var(--cf-text);
}
/* El cargo del operador y su lista de datos vienen vacíos cuando no están
   configurados, y dibujaban una raya y un recuadro sueltos bajo el nombre.
   OJO: sin `:empty`, porque esos nodos traen un espacio en blanco dentro y
   para CSS un espacio ya cuenta como contenido — la regla no aplicaba. */
.o_wappointment_wrap .o_appointment_card_user_fct {
    margin: 0 !important;
    border: 0 !important;
}
.o_wappointment_wrap .o_appointment_user_short_card .list-group,
.o_wappointment_wrap .o_appointment_user_short_card .list-group-item {
    border: 0;
    padding-left: 0;
    background: transparent;
}

/* --------------------------------------------------------------------------
   CITAS · "Seleccione con quién se reunirá"
   El marcado sigue siendo el nativo (ver la herencia `cita_operadores` en
   templates.xml); aquí solo se le da el lenguaje visual del sitio.
   -------------------------------------------------------------------------- */

/* El wrap nativo lleva h-100 y con pocas tarjetas dejaba media pantalla en
   blanco antes del footer. Alto automático + un mínimo para que la página no
   quede raquítica. */
.o_wappointment_select_operator,
#wrap.o_wappointment_wrap:has(.o_wappointment_select_operator) {
    height: auto !important;
}
.o_wappointment_select_operator { padding-bottom: 64px; }

.cf-cita__grid { margin-top: 8px; }

.o_wappointment_select_operator .o_wappointment_card {
    border: 1px solid var(--cf-border);
    border-radius: 18px;
    overflow: hidden;
    background: var(--cf-bg);
    transition: box-shadow .25s ease, transform .25s ease, border-color .25s ease;
}
.o_wappointment_select_operator .o_wappointment_card:hover {
    transform: translateY(-3px);
    border-color: var(--cf-primary);
    box-shadow: 0 26px 54px -34px rgba(16, 24, 40, .5);
}

/* Bloque de iniciales. Sustituye al ratio-16x9 nativo, así que necesita su
   propia altura: sin ella el <header> colapsaría a 0. */
.cf-cita__avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 150px;
    background: var(--cf-primary);
}
/* Cuatro tonos de la misma familia azul: distinguen a un operador de otro sin
   salirse de la marca. El índice sale de `staff_user.id % 4`. */
.cf-cita__avatar--0 { background: #0053ff; }
.cf-cita__avatar--1 { background: #0035a6; }
.cf-cita__avatar--2 { background: #2f7bff; }
.cf-cita__avatar--3 { background: #001f66; }
.cf-cita__iniciales {
    font-size: 46px;
    font-weight: 800;
    line-height: 1;
    letter-spacing: .02em;
    color: var(--cf-on-primary);
}
/* Si algún día se activan las fotos reales, ocupan el bloque entero. */
.cf-cita__foto {
    width: 100%;
    height: 100%;
    background-size: cover;
    background-position: center;
}

.o_wappointment_select_operator .card-body {
    padding: 22px 24px 24px;
    text-align: center;
}
.o_wappointment_select_operator .card-body h5 {
    font-size: 21px;
    font-weight: 600;
    color: var(--cf-text);
}

/* Píldora de acción. Es un <span>, no un enlace: quien navega con teclado
   activa la tarjeta entera, así que no debe recibir foco por su cuenta. */
.cf-cita__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 14px;
    padding: 8px 22px;
    border-radius: 999px;
    background: var(--cf-primary);
    color: var(--cf-on-primary);
    font-weight: 500;
    font-size: 16px;
    transition: background .15s ease;
}
.o_wappointment_card:hover .cf-cita__btn { background: var(--cf-primary-2); }

/* En móvil la tarjeta nativa se vuelve horizontal (d-flex d-md-block): el
   bloque de iniciales pasa a ser una columna estrecha a la izquierda. */
@media (max-width: 767px) {
    .cf-cita__avatar { height: auto; width: 96px; align-self: stretch; }
    .cf-cita__iniciales { font-size: 30px; }
    .o_wappointment_select_operator .card-body { text-align: left; padding: 18px 20px; }
}

/* ==========================================================================
   EN CONSTRUCCIÓN — páginas de los menús Odoo y Soluciones todavía sin
   contenido. La escena del cavernícola es SVG en línea; lo que se mueve lo
   anima app.js con GSAP (initObra).
   ========================================================================== */
.cf-obra { width: 100%; background: var(--cf-bg); }
.cf-obra__inner {
    max-width: var(--cf-max);
    margin: 0 auto;
    padding: 64px 40px 88px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: 48px;
    align-items: center;
}

.cf-obra__eyebrow {
    margin: 0 0 14px;
    font-size: 13px;
    font-weight: 500;
    font-style: italic;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--cf-primary);
}
.cf-obra__title {
    margin: 0 0 18px;
    font-size: var(--cf-title);
    font-weight: 700;
    font-style: italic;
    line-height: 1.08;
    letter-spacing: -0.015em;
    color: var(--cf-text);
}
.cf-obra__lead {
    margin: 0 0 30px;
    max-width: 460px;
    font-size: clamp(16px, 1.15vw, 19px);
    font-weight: 500;
    line-height: 1.55;
    color: var(--cf-muted);
}

.cf-obra__acciones { display: flex; flex-wrap: wrap; gap: 14px; }
.cf-obra__btn {
    display: inline-flex;
    align-items: center;
    padding: 15px 32px;
    border-radius: 999px;
    background: var(--cf-primary);
    color: var(--cf-on-primary) !important;
    font-size: 16px;
    font-weight: 500;
    font-style: italic;
    white-space: nowrap;
    transition: background .15s ease;
}
.cf-obra__btn:hover { background: var(--cf-primary-2); }
.cf-obra__btn--ghost {
    background: transparent;
    border: 1px solid var(--cf-border);
    color: var(--cf-primary) !important;
}
.cf-obra__btn--ghost:hover { background: rgba(0, 83, 255, .06); }

.cf-obra__escena svg {
    display: block;
    width: 100%;
    height: auto;
    /* overflow visible: el polvo y la piedra se salen del viewBox al animar */
    overflow: visible;
}

@media (max-width: 1024px) {
    .cf-obra__inner {
        grid-template-columns: minmax(0, 1fr);
        gap: 32px;
        padding: 48px 20px 64px;
    }
    /* La escena primero en pantallas pequeñas: es lo que cuenta la historia */
    .cf-obra__escena { order: -1; max-width: 460px; }
}

/* --- Datos de contacto del footer ----------------------------------------
   Columna propia: la del padre (.cf-footer__col) no la heredan los hijos, y
   sin esto los dos teléfonos salían pegados en la misma línea. */
.cf-footer__datos {
    display: flex;
    flex-direction: column;
    margin-top: 14px;
}
.cf-footer__rotulo {
    margin: 0 0 4px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #9aa2b1;
}

/* --- Aviso de alcance del formulario de contacto -------------------------- */
.cf-form__nota {
    display: flex;
    gap: 12px;
    margin-bottom: 22px;
    padding: 14px 16px;
    border-radius: 14px;
    /* Ámbar y no rojo: es una aclaración, no un error. El tono ya está en la
       paleta del sitio (la túnica del cavernícola). */
    background: #fff8e8;
    border: 1px solid #f3dfae;
}
.cf-form__notaico {
    flex: 0 0 auto;
    font-size: 16px;
    line-height: 1.4;
    color: #b4791b;
}
.cf-form__nota b {
    display: block;
    margin-bottom: 2px;
    font-size: 14px;
    font-weight: 600;
    color: #7a5310;
}
.cf-form__nota p {
    margin: 0;
    font-size: 13.5px;
    font-weight: 400;
    line-height: 1.5;
    color: #8a6318;
}
.cf-form__nota a {
    color: #7a5310 !important;
    font-weight: 500;
    text-decoration: underline !important;
}

/* El horario no es un enlace: mismo aspecto, sin comportamiento de enlace. */
.cf-form__datum--texto { cursor: default; }
.cf-form__datum--texto:hover { opacity: 1; }

/* Distintivo de partner. Ancho fijo y no alto: es un logotipo apaisado (2:1) y
   con un alto igual al del logo de Codfy saldría tan pequeño que no se leería
   el "Learning Partner". */
.cf-footer__partner {
    display: block;
    width: 70px;
    height: auto;
    margin-top: 22px;
}
