/*
 * CEI Interactive Exercises — Lesson Layout v2.2.0
 *
 * Scope: todo vive bajo .ecoleng-doc para no afectar Astra ni Topics antiguos.
 * Tokens canónicos: notas/auditoria-css.md §4.1–§4.3. Charte: §0.
 */

/* ========================================================================
 * 1. Tokens canónicos (solo dentro del wrapper)
 * ====================================================================== */
.ecoleng-doc {
    --ecoleng-blue: #1895BD;
    --ecoleng-blue-dark: #116E8C;
    --ecoleng-green: #1FA7A2;
    --ecoleng-purple: #8A2976;
    --ecoleng-ink: #222221;
    --ecoleng-black: #000000;
    --ecoleng-white: #FFFFFF;
    --ecoleng-border: #EEEEEE;
    --ecoleng-soft: #F4F7FA;
    --ecoleng-soft-blue: #EAF7FB;
    --ecoleng-soft-purple: #F7EEF5;
    --ecoleng-soft-green: #EAF8F7;
    --ecoleng-shadow: 0 12px 32px rgba(0, 0, 0, .08);
    --ecoleng-shadow-soft: 0 12px 28px rgba(34, 34, 33, .08);
    --ecoleng-radius: 15px;
    --ecoleng-container: 1280px;

    --ecoleng-font-heading: "Barlow Semi Condensed", "Arial Narrow", Arial, sans-serif;
    --ecoleng-font-body: Roboto, Arial, sans-serif;
    --ecoleng-font-mono: "Roboto Condensed", Arial, sans-serif;
}

/* ========================================================================
 * 2. Wrapper base + reset muy suave (no agresivo, convive con Astra)
 * ====================================================================== */
.ecoleng-doc {
    max-width: var(--ecoleng-container);
    margin-inline: auto;
    color: var(--ecoleng-ink);
    font-family: var(--ecoleng-font-body);
    line-height: 1.55;
    font-size: 16px;
}

.ecoleng-doc *,
.ecoleng-doc *::before,
.ecoleng-doc *::after {
    box-sizing: border-box;
}

.ecoleng-doc h1,
.ecoleng-doc h2,
.ecoleng-doc h3,
.ecoleng-doc h4 {
    font-family: var(--ecoleng-font-heading);
    color: var(--ecoleng-ink);
    line-height: 1.15;
    margin: 0 0 .5em;
    font-weight: 700;
}

.ecoleng-doc h1 { font-size: clamp(1.8rem, 2.6vw + 1rem, 2.8rem); }
.ecoleng-doc h2 { font-size: clamp(1.4rem, 1.2vw + 1rem, 1.9rem); }
.ecoleng-doc h3 { font-size: clamp(1.15rem, .6vw + 1rem, 1.4rem); }
.ecoleng-doc h4 { font-size: 1.05rem; }

.ecoleng-doc p {
    margin: 0 0 1em;
}

.ecoleng-doc a {
    color: var(--ecoleng-blue-dark);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.ecoleng-doc a:hover {
    color: var(--ecoleng-purple);
}

.ecoleng-doc img {
    max-width: 100%;
    height: auto;
    border-radius: var(--ecoleng-radius);
}

.ecoleng-doc ul,
.ecoleng-doc ol {
    padding-inline-start: 1.3em;
    margin: 0 0 1em;
}

.ecoleng-doc li + li {
    margin-top: .25em;
}

/* ========================================================================
 * 3. Hero
 * ====================================================================== */
.ecoleng-doc__hero {
    position: relative;
    background: linear-gradient(135deg, var(--ecoleng-soft-blue), var(--ecoleng-soft-purple));
    border: 1px solid var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    padding: clamp(1.25rem, 2vw + 1rem, 2.5rem);
    margin-bottom: 1.5rem;
    box-shadow: var(--ecoleng-shadow-soft);
}

.ecoleng-doc__hero-grid {
    display: grid;
    grid-template-columns: 1.2fr 0.8fr;
    gap: clamp(1rem, 2vw, 2rem);
    align-items: center;
}

.ecoleng-doc__hero-img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--ecoleng-radius);
    box-shadow: var(--ecoleng-shadow);
}

/* v2.2.12: el título del hero ahora va en <h2> (para no duplicar el <h1> del
   título del CPT de WordPress). Lo estilamos visualmente como un h1 dentro
   del hero, conservando su peso editorial. */
.ecoleng-doc .ecoleng-doc__hero > div > h2:first-of-type,
.ecoleng-doc .ecoleng-doc__hero-grid h2:first-of-type {
    font-family: var(--ecoleng-font-heading);
    font-size: clamp(1.6rem, 2vw + 1rem, 2.4rem);
    line-height: 1.15;
    margin: .25em 0 .5em;
    color: var(--ecoleng-ink);
}

.ecoleng-doc__lead {
    font-size: 1.08rem;
    color: #3c3c3b;
    margin-bottom: 0;
}

/* ========================================================================
 * 4. Topbar sticky (herramientas audio/acciones)
 * ====================================================================== */
.ecoleng-doc__topbar {
    position: sticky;
    top: 0;
    z-index: 5;
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: center;
    padding: .6rem .9rem;
    margin-bottom: 1rem;
    background: rgba(255, 255, 255, .95);
    backdrop-filter: saturate(1.2) blur(6px);
    border: 1px solid var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    box-shadow: var(--ecoleng-shadow-soft);
}

/* ========================================================================
 * 5. Layout principal (TOC arriba como bloque, contenido debajo)
 *    No usamos sticky/sidebar para evitar solaparse con el menú lateral
 *    de LearnDash y comprimir el ancho del contenido.
 * ====================================================================== */
.ecoleng-doc__layout {
    display: block;
}

.ecoleng-doc__toc {
    margin-bottom: 1.5rem;
    padding: 1rem 1.1rem;
    background: var(--ecoleng-white);
    border: 1px solid var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    box-shadow: var(--ecoleng-shadow-soft);
}

.ecoleng-doc__toc > summary {
    cursor: pointer;
    font-family: var(--ecoleng-font-heading);
    font-weight: 600;
    color: var(--ecoleng-ink);
    list-style: none;
}

.ecoleng-doc__toc > summary::-webkit-details-marker { display: none; }

.ecoleng-doc__toc > summary::after {
    content: '▾';
    float: right;
    transition: transform .2s ease;
}

.ecoleng-doc__toc[open] > summary::after { transform: rotate(180deg); }

.ecoleng-doc__toc ol,
.ecoleng-doc__toc ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.ecoleng-doc__toc a {
    display: block;
    padding: .35rem .5rem;
    border-radius: 8px;
    color: var(--ecoleng-ink);
    text-decoration: none;
    font-size: .95rem;
}

.ecoleng-doc__toc a:hover,
.ecoleng-doc__toc a.is-active {
    background: var(--ecoleng-soft-blue);
    color: var(--ecoleng-blue-dark);
}

/* ========================================================================
 * 6. Section cards
 * ====================================================================== */
.ecoleng-doc__section {
    background: var(--ecoleng-white);
    border: 1px solid var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    padding: clamp(1.1rem, 1.5vw + .5rem, 2rem);
    margin-bottom: 1.25rem;
    box-shadow: var(--ecoleng-shadow-soft);
}

.ecoleng-doc__section-header {
    display: flex;
    align-items: baseline;
    gap: .75rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.ecoleng-doc__section-tag {
    display: inline-block;
    padding: .2rem .7rem;
    border-radius: 999px;
    background: var(--ecoleng-soft-purple);
    color: var(--ecoleng-purple);
    font-family: var(--ecoleng-font-heading);
    font-size: .78rem;
    letter-spacing: .04em;
    text-transform: uppercase;
}

/* ========================================================================
 * 7. Cards genéricas + modificadores
 * ====================================================================== */
.ecoleng-doc__card {
    background: var(--ecoleng-white);
    border: 1px solid var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    padding: 1rem 1.1rem;
    box-shadow: var(--ecoleng-shadow-soft);
}

.ecoleng-doc__card + .ecoleng-doc__card {
    margin-top: .75rem;
}

.ecoleng-doc__card--info   { background: var(--ecoleng-soft-blue); border-color: transparent; }
.ecoleng-doc__card--rule   { background: var(--ecoleng-soft-purple); border-color: transparent; }
.ecoleng-doc__card--mini   { padding: .6rem .8rem; font-size: .92rem; }
.ecoleng-doc__card--phrase { background: var(--ecoleng-soft); }
.ecoleng-doc__card--letter { text-align: center; font-family: var(--ecoleng-font-heading); }
.ecoleng-doc__card--resource { display: flex; gap: .75rem; align-items: center; }
.ecoleng-doc__card--pdf    { border-inline-start: 5px solid var(--ecoleng-purple); }

/* ========================================================================
 * 8. Callouts (borde izquierdo coloreado)
 * ====================================================================== */
.ecoleng-doc__callout {
    padding: .9rem 1rem;
    border-radius: var(--ecoleng-radius);
    border-inline-start: 5px solid var(--ecoleng-blue);
    background: var(--ecoleng-soft-blue);
    margin: 0 0 1rem;
}

.ecoleng-doc__callout--green {
    border-inline-start-color: var(--ecoleng-green);
    background: var(--ecoleng-soft-green);
}

.ecoleng-doc__callout--purple {
    border-inline-start-color: var(--ecoleng-purple);
    background: var(--ecoleng-soft-purple);
}

/* ========================================================================
 * 9. Diálogos
 * ====================================================================== */
.ecoleng-doc__dialogue {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    padding: 1rem;
    background: var(--ecoleng-soft);
    border-radius: var(--ecoleng-radius);
}

.ecoleng-doc__line {
    display: grid;
    grid-template-columns: minmax(80px, auto) 1fr auto auto;
    gap: .6rem;
    align-items: center;
}

.ecoleng-doc__speaker {
    font-family: var(--ecoleng-font-heading);
    font-weight: 700;
    color: var(--ecoleng-purple);
}

/* ========================================================================
 * 10. Botones (unificados)
 * ====================================================================== */
.ecoleng-doc__btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .55rem 1rem;
    font-family: var(--ecoleng-font-body);
    font-size: .95rem;
    line-height: 1.2;
    border: 1px solid transparent;
    border-radius: 8px;
    background: var(--ecoleng-white);
    color: var(--ecoleng-ink);
    cursor: pointer;
    transition: background-color .2s ease, color .2s ease, border-color .2s ease;
    text-decoration: none;
}

.ecoleng-doc__btn:hover { background: var(--ecoleng-soft); }

.ecoleng-doc__btn--primary   { background: var(--ecoleng-blue); color: #fff; }
.ecoleng-doc__btn--primary:hover { background: var(--ecoleng-blue-dark); }
.ecoleng-doc__btn--secondary { background: var(--ecoleng-purple); color: #fff; }
.ecoleng-doc__btn--secondary:hover { background: #6d1f5c; }
.ecoleng-doc__btn--green     { background: var(--ecoleng-green); color: #fff; }
.ecoleng-doc__btn--ghost     { background: transparent; border-color: var(--ecoleng-border); }
.ecoleng-doc__btn--stop      { background: #b42318; color: #fff; }
.ecoleng-doc__btn--stop:hover { background: #8e1a13; color: #fff; }

.ecoleng-doc__btn:disabled {
    opacity: .55;
    cursor: not-allowed;
}

/* ========================================================================
 * 11. Badges y pills
 * ====================================================================== */
.ecoleng-doc__badge,
.ecoleng-doc__pill {
    display: inline-block;
    padding: .2rem .65rem;
    font-size: .78rem;
    font-family: var(--ecoleng-font-heading);
    letter-spacing: .04em;
    border-radius: 999px;
    background: var(--ecoleng-soft);
    color: var(--ecoleng-ink);
}

.ecoleng-doc__badge--blue   { background: var(--ecoleng-soft-blue);  color: var(--ecoleng-blue-dark); }
.ecoleng-doc__badge--green  { background: var(--ecoleng-soft-green); color: var(--ecoleng-green); }
.ecoleng-doc__badge--purple { background: var(--ecoleng-soft-purple);color: var(--ecoleng-purple); }

/* ========================================================================
 * 12. Help (<details> con ayuda ES/EN oculta)
 * ====================================================================== */
.ecoleng-doc__help {
    background: var(--ecoleng-soft);
    border: 1px dashed var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    padding: .6rem .9rem;
    margin: .5rem 0;
}

.ecoleng-doc__help > summary {
    cursor: pointer;
    font-family: var(--ecoleng-font-heading);
    color: var(--ecoleng-purple);
    list-style: none;
}

.ecoleng-doc__help > summary::marker { content: ""; }
.ecoleng-doc__help > summary::before { content: "▸ "; }
.ecoleng-doc__help[open] > summary::before { content: "▾ "; }

/* ========================================================================
 * 13. Notepad y producción (textarea persistente)
 * ====================================================================== */
.ecoleng-doc__notepad,
.ecoleng-doc__production {
    width: 100%;
    min-height: 140px;
    padding: .9rem;
    font: inherit;
    font-family: var(--ecoleng-font-body);
    background: var(--ecoleng-white);
    border: 1px solid var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    resize: vertical;
}

.ecoleng-doc__notepad:focus,
.ecoleng-doc__production:focus {
    outline: 2px solid var(--ecoleng-blue);
    outline-offset: 2px;
}

/* ========================================================================
 * 14. Floating reader + traduction (panel de selección)
 * ====================================================================== */
/* Se appendea al <body>, fuera de .ecoleng-doc, para evitar que cualquier
   transform de un ancestro rompa position:fixed. Valores hardcoded. */
.ecoleng-doc__floating-reader {
    position: fixed;
    z-index: 9999;
    width: min(420px, calc(100vw - 24px));
    display: block;
    padding: .75rem;
    background: #FBF6FA;
    border: 2px solid #D8B4D0;
    border-radius: 15px;
    box-shadow:
        0 26px 70px rgba(34, 34, 33, .24),
        0 8px 22px rgba(138, 41, 118, .12),
        0 0 0 1px rgba(138, 41, 118, .10);
    transform: translate(-50%, calc(-100% - 12px));
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s ease, transform .15s ease;
    font-family: Roboto, Arial, sans-serif;
    color: #222221;
}

.ecoleng-doc__floating-reader.is-above {
    transform: translate(-50%, calc(-100% - 12px));
}

.ecoleng-doc__floating-reader.is-below {
    transform: translate(-50%, 12px);
}

.ecoleng-doc__floating-reader.is-visible {
    opacity: 1;
    pointer-events: auto;
}

.ecoleng-doc__floating-reader-preview {
    display: grid;
    grid-template-columns: 1fr 30px;
    gap: .5rem;
    align-items: start;
    padding-bottom: .55rem;
    margin-bottom: .6rem;
    border-bottom: 1px solid rgba(138, 41, 118, .20);
}

.ecoleng-doc__floating-reader-preview span {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: .92rem;
    line-height: 1.35;
    color: #3c3c3b;
}

.ecoleng-doc__floating-reader-preview button[data-action="close"] {
    width: 30px;
    height: 30px;
    padding: 0;
    border-radius: 8px;
    font-size: 1.15rem;
    line-height: 1;
    background: #F4F7FA;
}

.ecoleng-doc__floating-reader-controls,
.ecoleng-doc__floating-reader-translate {
    display: flex;
    align-items: center;
    gap: .45rem;
    flex-wrap: wrap;
}

.ecoleng-doc__floating-reader-controls + .ecoleng-doc__floating-reader-translate {
    margin-top: .55rem;
    padding-top: .55rem;
    border-top: 1px solid rgba(138, 41, 118, .20);
}

.ecoleng-doc__floating-reader label {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 42px;
    padding: .15rem .3rem .15rem .6rem;
    border: 1px solid #EEEEEE;
    border-radius: 8px;
    background: #FFFFFF;
    color: #222221;
    font-size: .84rem;
    font-weight: 600;
}

.ecoleng-doc__floating-reader select {
    min-height: 38px;
    border: 0;
    border-left: 1px solid #EEEEEE;
    padding: 0 .35rem;
    background: #FFFFFF;
    color: #222221;
    font: inherit;
    cursor: pointer;
}

.ecoleng-doc__floating-reader button {
    padding: .45rem .8rem;
    font: inherit;
    font-size: .86rem;
    font-weight: 600;
    background: #EAF7FB;
    border: 1px solid #EEEEEE;
    border-radius: 8px;
    cursor: pointer;
    color: #222221;
    transition: background .15s ease, color .15s ease, border-color .15s ease, opacity .15s ease;
}

.ecoleng-doc__floating-reader button:not([data-action="close"]) {
    min-height: 42px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 .9rem;
    line-height: 1.1;
}

.ecoleng-doc__floating-reader button[data-action="play"] {
    background: #F7EEF5;
    color: #8A2976;
    border-color: #8A2976;
}
.ecoleng-doc__floating-reader button[data-action="play"]:hover {
    background: #F1E3EE;
    color: #6e1f5e;
    border-color: #6e1f5e;
}

.ecoleng-doc__floating-reader button[data-action="translate"] {
    background: #EEF8FB;
    color: #116E8C;
    border: 2px solid #5DB9D0;
}
.ecoleng-doc__floating-reader button[data-action="translate"]:hover {
    background: #DDF1F7;
    border-color: #1895BD;
}

.ecoleng-doc__floating-reader button[data-action="stop"] {
    background: #FFF3F0;
    color: #a8201a;
    border-color: #a8201a;
}
.ecoleng-doc__floating-reader button[data-action="stop"]:hover {
    background: #FBE3DE;
    color: #8e1a13;
    border-color: #8e1a13;
}

.ecoleng-doc__floating-reader button:disabled {
    opacity: .58;
    cursor: wait;
}

.ecoleng-doc__floating-reader-result {
    margin-top: .65rem;
    padding: .7rem .8rem;
    border-radius: 10px;
    background: #F7EEF5;
    color: #222221;
    font-size: .92rem;
    line-height: 1.4;
}

.ecoleng-doc__floating-reader-result.is-loading {
    background: #F4F7FA;
    color: #3c3c3b;
}

.ecoleng-doc__floating-reader-result.is-error,
.ecoleng-doc__floating-reader-result.is-warning {
    background: #FFF3F0;
    color: #8e1a13;
}

.ecoleng-doc__floating-reader-result.is-success {
    background: #F7EEF5;
    border: 1px solid #E8D3E3;
}

@media (max-width: 640px) {
    .ecoleng-doc__floating-reader {
        left: 12px !important;
        right: 12px;
        top: auto !important;
        bottom: 12px;
        width: auto;
        max-height: min(70vh, 520px);
        overflow: auto;
        transform: none;
    }

    .ecoleng-doc__floating-reader.is-above,
    .ecoleng-doc__floating-reader.is-below {
        transform: none;
    }

    .ecoleng-doc__floating-reader-controls,
    .ecoleng-doc__floating-reader-translate {
        display: grid;
        grid-template-columns: 1fr 1fr;
        align-items: stretch;
    }

    .ecoleng-doc__floating-reader-controls label,
    .ecoleng-doc__floating-reader-translate label {
        grid-column: 1 / -1;
        justify-content: space-between;
    }

    .ecoleng-doc__floating-reader button {
        justify-content: center;
        width: 100%;
    }
}

/* ========================================================================
 * 15. PDF links + footer CTA
 * ====================================================================== */
.ecoleng-doc__pdf-links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: .75rem;
}

.ecoleng-doc__footer-cta {
    margin-top: 2rem;
    padding: 1.25rem 1.5rem;
    background: linear-gradient(135deg, var(--ecoleng-purple), #6d1f5c);
    color: #fff;
    border-radius: var(--ecoleng-radius);
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: center;
    justify-content: space-between;
    box-shadow: var(--ecoleng-shadow);
}

.ecoleng-doc__footer-cta h3 { color: #fff; margin: 0; }
.ecoleng-doc__footer-cta .ecoleng-doc__btn { background: #fff; color: var(--ecoleng-purple); }

/* ========================================================================
 * 16. Toast de feedback (copy, saved)
 * ====================================================================== */
.ecoleng-doc__toast {
    position: fixed;
    left: 50%;
    bottom: 1.5rem;
    transform: translateX(-50%) translateY(20px);
    z-index: 10000;
    padding: .55rem 1rem;
    background: var(--ecoleng-ink, #222221);
    color: #fff;
    font-size: .9rem;
    border-radius: 999px;
    box-shadow: var(--ecoleng-shadow, 0 12px 32px rgba(0, 0, 0, .08));
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease, transform .2s ease;
}

.ecoleng-doc__toast.is-visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ========================================================================
 * 17. Speakable (texto resaltado mientras el TTS lo lee)
 * ====================================================================== */
.ecoleng-doc__speakable.is-speaking,
.ecoleng-doc [data-speakable].is-speaking {
    background: linear-gradient(transparent 60%, rgba(24, 149, 189, .25) 60%);
    border-radius: 4px;
}

/* ========================================================================
 * 18. Tabs (data-tab / data-tab-panel)
 * ====================================================================== */
.ecoleng-doc__tabs {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    border-bottom: 1px solid var(--ecoleng-border);
    margin-bottom: 1rem;
}

.ecoleng-doc__tabs [data-tab] {
    padding: .5rem 1rem;
    background: transparent;
    border: none;
    cursor: pointer;
    font-family: var(--ecoleng-font-heading);
    color: var(--ecoleng-ink);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.ecoleng-doc__tabs [data-tab].is-active {
    color: var(--ecoleng-purple);
    border-bottom-color: var(--ecoleng-purple);
}

.ecoleng-doc [data-tab-panel] { display: none; }
.ecoleng-doc [data-tab-panel].is-active { display: block; }

/* ========================================================================
 * 19. Responsive
 * ====================================================================== */
@media (max-width: 860px) {
    .ecoleng-doc__hero-grid {
        grid-template-columns: 1fr;
    }
}

/* ========================================================================
 * 20. Print
 * ====================================================================== */
@media print {
    .ecoleng-doc__topbar,
    .ecoleng-doc__toc,
    .ecoleng-doc__floating-reader,
    .ecoleng-doc__footer-cta,
    .ecoleng-doc__btn {
        display: none !important;
    }

    .ecoleng-doc__layout {
        grid-template-columns: 1fr;
    }

    .ecoleng-doc__section,
    .ecoleng-doc__card,
    .ecoleng-doc__hero {
        box-shadow: none;
        border-color: #ccc;
        break-inside: avoid;
    }
}

/* ========================================================================
 * 21. Batch v2.2.7 — fixes acumulados tras validación 1.1.1 V1 (revisión 2)
 * Ver notas/registro-correcciones.md (issues #4, #6, #7, #8, #9, #10, #11,
 * #12, #13, #14, #15)
 * ====================================================================== */

/* #11 TOC summary: legible en PC + separación con la lista */
.ecoleng-doc .ecoleng-doc__toc > summary {
    font-size: 1.15rem;
    font-weight: 700;
    padding: .15rem 0;
}
.ecoleng-doc .ecoleng-doc__toc[open] > summary {
    margin-bottom: .75rem;
    padding-bottom: .6rem;
    border-bottom: 1px solid var(--ecoleng-border);
}

/* #9 Help summary: legible en PC + separación con el contenido */
.ecoleng-doc .ecoleng-doc__help > summary {
    font-size: 1.1rem;
    font-weight: 700;
    padding: .15rem 0;
}
.ecoleng-doc .ecoleng-doc__help[open] > summary {
    margin-bottom: .7rem;
}

/* #8 Botón base Écouter: evitar que el hover del tema vuelva el texto invisible */
.ecoleng-doc .ecoleng-doc__btn:not([class*="ecoleng-doc__btn--"]):hover {
    color: var(--ecoleng-ink);
}

/* #12 / #13 / #14 Botones TTS (Écouter, Écouter le dialogue, Écouter lentement):
   fondo corporativo morado, texto blanco legible, ancho ajustado al texto.
   Se aplica a todos los .ecoleng-doc__btn que lleven un data-tts-* (la única
   función real de estos botones en los Topics). Prevalece sobre el modifier
   --ghost que ChatGPT emite por defecto. */
.ecoleng-doc .ecoleng-doc__btn[data-tts-text],
.ecoleng-doc .ecoleng-doc__btn[data-tts-target] {
    background: var(--ecoleng-purple);
    color: #FFFFFF;
    border-color: var(--ecoleng-purple);
    width: fit-content;
    max-width: max-content;
}
.ecoleng-doc .ecoleng-doc__btn[data-tts-text]:hover,
.ecoleng-doc .ecoleng-doc__btn[data-tts-target]:hover {
    background: #6d1f5c;
    border-color: #6d1f5c;
    color: #FFFFFF;
}

/* #14 Bloque frase-modelo + botón TTS: botón a la izquierda de la frase en PC,
   apilado en móvil. El prompt MASTER_v3 §9bis obliga a envolver cada par en
   <div class="ecoleng-doc__formule"><button…/><p…/></div>. */
.ecoleng-doc .ecoleng-doc__formule {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin: .5rem 0;
}
.ecoleng-doc .ecoleng-doc__formule > .ecoleng-doc__btn {
    flex: 0 0 auto;
}
.ecoleng-doc .ecoleng-doc__formule > p {
    margin: 0;
    flex: 1 1 auto;
}
@media (max-width: 640px) {
    .ecoleng-doc .ecoleng-doc__formule {
        flex-direction: column;
        align-items: flex-start;
        gap: .4rem;
    }
}

/* #10 / #15 Botones de Téléchargements: morado, texto blanco, centrados,
   sin subrayado */
.ecoleng-doc .ecoleng-doc__pdf-links {
    justify-content: center;
    justify-items: center;
}
.ecoleng-doc .ecoleng-doc__pdf-links .ecoleng-doc__btn,
.ecoleng-doc .ecoleng-doc__pdf-links .ecoleng-doc__btn:visited {
    background: var(--ecoleng-purple);
    color: #FFFFFF;
    border-color: var(--ecoleng-purple);
    text-decoration: none;
    text-align: center;
    justify-content: center;
}
.ecoleng-doc .ecoleng-doc__pdf-links .ecoleng-doc__btn:hover {
    background: #6d1f5c;
    border-color: #6d1f5c;
    color: #FFFFFF;
    text-decoration: none;
}
.ecoleng-doc .ecoleng-doc__pdf-links .ecoleng-doc__btn:hover,
.ecoleng-doc .ecoleng-doc__pdf-links .ecoleng-doc__btn:focus {
    text-decoration: none;
}

/* #16bis Radios suaves también en FloatingReader y toast (coherencia global) */
.ecoleng-doc__floating-reader button {
    border-radius: 8px;
}
.ecoleng-doc__toast { border-radius: 10px; }

/* #17 Chips de caracteres copiables (Accents et ponctuation).
   Estilo sutil, NO es un botón morado duro. Aplicar en el prompt con la
   clase .ecoleng-doc__char-chip a los <button data-copy-text="é">, no con
   .ecoleng-doc__btn. */
.ecoleng-doc .ecoleng-doc__char-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.2rem;
    padding: .25rem .55rem;
    margin: .15rem;
    font-family: var(--ecoleng-font-body);
    font-size: 1rem;
    line-height: 1.2;
    color: var(--ecoleng-ink);
    background: var(--ecoleng-soft);
    border: 1px solid var(--ecoleng-border);
    border-radius: 6px;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
.ecoleng-doc .ecoleng-doc__char-chip:hover,
.ecoleng-doc .ecoleng-doc__char-chip:focus-visible {
    background: #e9edf2;
    border-color: #c9d0d8;
    outline: none;
}
.ecoleng-doc .ecoleng-doc__char-chip:active {
    background: #dde2ea;
}

/* #18 Écouter en líneas de diálogo: alineado a la izquierda del Lent con
   ancho mínimo fijo → las columnas Écouter / Lent quedan siempre alineadas
   en vertical (fin del fit-content variable dentro del grid). */
.ecoleng-doc .ecoleng-doc__line .ecoleng-doc__btn[data-tts-text] {
    min-width: 100px;
    width: 100px;
    max-width: 100px;
    justify-content: center;
}
.ecoleng-doc .ecoleng-doc__line .ecoleng-doc__btn--stop,
.ecoleng-doc .ecoleng-doc__line [data-tts-rate] {
    min-width: 100px;
    width: 100px;
    max-width: 100px;
    justify-content: center;
}

/* #20 Botones de acciones de ejercicio (Vérifier / Effacer / Indice):
   altura equivalente, separación clara, alineación consistente */
.ecoleng-doc .cei-exercise__actions {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
    align-items: stretch;
    margin-top: 1rem;
}
.ecoleng-doc .cei-exercise__actions > button {
    min-height: 42px;
    padding: .55rem 1.1rem;
    border-radius: 8px;
    line-height: 1.2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* #4 Inputs de fill-in-the-blank con ancho mínimo definido */
.ecoleng-doc .cei-exercise input[type="text"],
.ecoleng-doc .cei-exercise__input,
.ecoleng-doc input[type="text"].cei-exercise__input {
    min-width: 8ch;
    padding: .35rem .6rem;
    border: 1px solid var(--ecoleng-border);
    border-radius: 8px;
    font: inherit;
}

/* #6 dialogue-choice: ocultar la data cruda del ejercicio
   (el JS mueve las opciones a __options-area, pero el contenedor fuente
   seguía visible bajo la UI interactiva) */
.ecoleng-doc .cei-exercise__dialogue-data {
    display: none;
}

/* #7 dialogue-choice: el chat-history arranca casi invisible sin mensajes
   (flex-grow:1 sin min-height); garantizar altura legible desde el inicio */
.ecoleng-doc .cei-exercise__chat-history {
    min-height: 200px;
}

/* ========================================================================
 * 22. Batch v2.2.10 — correcciones post-validación V2 (#22, #23, #24)
 * ====================================================================== */

/* #47 v2.2.15 — V6 emite 4 hijos en .ecoleng-doc__line (speaker <span>
   hermano de <p>, no anidado): minmax(80px,auto) 1fr 100px 100px.
   Reemplaza al override v2.2.10 de 3 cols (asumía speaker anidado en <p>). */
.ecoleng-doc .ecoleng-doc__line {
    grid-template-columns: minmax(80px, auto) 1fr 100px 100px;
}
@media (max-width: 640px) {
    /* Móvil: speaker arriba (span 2 cols), replique debajo (span 2 cols),
       Écouter y Lent en fila propia 50/50. */
    .ecoleng-doc .ecoleng-doc__line {
        grid-template-columns: 1fr 1fr;
        grid-auto-flow: row;
        row-gap: .5rem;
    }
    .ecoleng-doc .ecoleng-doc__line > .ecoleng-doc__speaker,
    .ecoleng-doc .ecoleng-doc__line > p {
        grid-column: 1 / -1;
    }
    .ecoleng-doc .ecoleng-doc__line .ecoleng-doc__btn[data-tts-text],
    .ecoleng-doc .ecoleng-doc__line [data-tts-rate] {
        width: 100%;
        max-width: none;
        min-width: 0;
    }
}

/* v2.2.12 #31 Topbar: en móvil, cuando los 3 botones se apilan por
   flex-wrap, el gap vertical (row-gap) queda apretado. Explicitamos un
   row-gap mayor para que respiren. */
@media (max-width: 640px) {
    .ecoleng-doc .ecoleng-doc__topbar {
        row-gap: .55rem;
    }
}

/* #23 (revertido en v2.2.11): MASTER_v3 ahora obliga a envolver las
   .cei-exercise__card en .cei-exercise__deck-container, que ya tiene el grid
   2/3/auto-fill en cei-styles.css (intocable). El override previo convertía
   el propio .cei-exercise en grid 2-col y dejaba el deck-container encerrado
   en 1 sola columna. Quitado para que la regla intocable funcione limpia. */

/* #24 tap-to-match con wrapper __match-columns (en plural) — Codex emite la
   clase nueva pero el CSS intocable sólo conoce __match-container. Replicamos
   el layout de dos columnas para la clase emitida en el scope .ecoleng-doc. */
.ecoleng-doc .cei-exercise__match-columns {
    display: flex;
    justify-content: space-between;
    gap: 20px;
}
.ecoleng-doc .cei-exercise__match-columns > .cei-exercise__match-column {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
@media (max-width: 640px) {
    .ecoleng-doc .cei-exercise__match-columns {
        flex-direction: column;
        gap: 12px;
    }
}

/* #29 tap-to-match — match-item con el estilo corporativo de botón en el scope
   .ecoleng-doc. El CSS intocable (cei-styles.css) los pinta blanco sobre tarjeta
   blanca (borde #EEEEEE casi invisible). Aquí reposo = morado de marca con texto
   blanco (como los botones TTS), y estados claros al seleccionar/emparejar.
   Scopeado SOLO a .ecoleng-doc → topics antiguos sin wrapper (p.ej. "Relacionar
   Horas") quedan intactos. Ver notas/registro-correcciones.md issue #83. */
.ecoleng-doc .cei-exercise__match-item {
    background-color: var(--ecoleng-purple);   /* #8A2976 morado marca */
    border: 1px solid var(--ecoleng-purple);
    color: #FFFFFF;                             /* texto blanco legible */
}
.ecoleng-doc .cei-exercise__match-item:hover {
    background-color: #6d1f5c;                  /* morado más oscuro, igual que TTS */
    border-color: #6d1f5c;
}
.ecoleng-doc .cei-exercise__match-item.is-selected {
    background-color: var(--ecoleng-blue);      /* azul marca = seleccionado */
    border-color: var(--ecoleng-blue-dark);
    color: #FFFFFF;
    transform: scale(1.03);
}
.ecoleng-doc .cei-exercise__match-item.is-matched {
    background-color: var(--ecoleng-green);     /* verde marca = emparejado OK */
    border-color: var(--ecoleng-green);
    color: #FFFFFF;
    opacity: 1;                                 /* quita el apagado del 0.7 */
    cursor: default;
}

/* #30 tap-to-match — separación vertical entre filas de botones cuando el markup
   usa __match-container con <div> internos sin clase (los botones fluyen en varias
   filas sin gap vertical). Convertimos cada <div> de columna en flex-wrap con gap
   en ambos ejes. Scopeado a .ecoleng-doc → topics antiguos (p.ej. "Relacionar
   Horas", sin wrapper) quedan intactos. Ver notas/registro-correcciones.md issue #83. */
.ecoleng-doc .cei-exercise__match-container > div {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;                                  /* gap horizontal Y vertical entre filas */
    align-content: flex-start;
}

/* ========================================================================
 * 23. Batch v2.2.14 — fixes editoriales tras validación 1.1.1 V5 (topic 18525)
 * Ver notas/registro-correcciones.md issues #37, #38, #39
 * ====================================================================== */

/* #38 — Crédits: separación visual del contenido anterior. La estructura HTML
   la inyecta pipeline/import_wp.py:build_credits_html() al final del wrapper. */
.ecoleng-doc .ecoleng-doc__credits {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--ecoleng-border);
    font-size: .85rem;
    color: var(--ecoleng-ink);
    opacity: .85;
}
.ecoleng-doc .ecoleng-doc__credits h3 {
    font-size: 1rem;
    margin: 0 0 .5rem;
    color: var(--ecoleng-purple);
}
.ecoleng-doc .ecoleng-doc__credits ul {
    margin: 0;
    padding-left: 1.2rem;
}
.ecoleng-doc .ecoleng-doc__credits li + li {
    margin-top: .35rem;
}
.ecoleng-doc .ecoleng-doc__credits a {
    color: var(--ecoleng-purple);
}

/* #39 — Imágenes intercaladas en secciones (rol "section" del manifest).
   Codex las renderiza con esta clase justo después del <h2> de cada sección. */
.ecoleng-doc .ecoleng-doc__section-img {
    display: block;
    width: 100%;
    max-width: 720px;
    height: auto;
    margin: 1.25rem auto 1.75rem;
    border-radius: var(--ecoleng-radius);
    box-shadow: var(--ecoleng-shadow-soft);
    object-fit: cover;
}

/* #45 — Cards "resource" (Ressources utiles): el flex-row con 3 hijos
   (h3, p, a "Découvrir") se desborda en móvil. Stack vertical en <=860px y
   alinear la "a" como bloque al final. */
@media (max-width: 860px) {
    .ecoleng-doc .ecoleng-doc__card--resource {
        flex-direction: column;
        align-items: flex-start;
        gap: .55rem;
    }
    .ecoleng-doc .ecoleng-doc__card--resource > a.ecoleng-doc__btn {
        align-self: flex-start;
    }
}

/* #46 — Fallback de chips de Accents: Codex puede emitir las clases legacy
   __copybar / __copychip / __accents-bar / __accent-key (v5 externo) en lugar
   de la canónica __char-chip. Aliasamos para que reciban el mismo estilo. */
.ecoleng-doc .ecoleng-doc__copybar,
.ecoleng-doc .ecoleng-doc__accents-bar {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin: .5rem 0;
}
.ecoleng-doc .ecoleng-doc__copychip,
.ecoleng-doc .ecoleng-doc__accent-key,
.ecoleng-doc button.ecoleng-doc__copychip,
.ecoleng-doc button.ecoleng-doc__accent-key {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.2rem;
    padding: .25rem .55rem;
    margin: .15rem;
    font-family: var(--ecoleng-font-body);
    font-size: 1rem;
    line-height: 1.2;
    color: var(--ecoleng-ink);
    background: var(--ecoleng-soft);
    border: 1px solid var(--ecoleng-border);
    border-radius: 6px;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
.ecoleng-doc .ecoleng-doc__copychip:hover,
.ecoleng-doc .ecoleng-doc__copychip:focus-visible,
.ecoleng-doc .ecoleng-doc__accent-key:hover,
.ecoleng-doc .ecoleng-doc__accent-key:focus-visible {
    background: #e9edf2;
    border-color: #c9d0d8;
    outline: none;
}
.ecoleng-doc .ecoleng-doc__copychip:active,
.ecoleng-doc .ecoleng-doc__accent-key:active {
    background: #dde2ea;
}

/* #47 — Topbar (Écouter/Lent/Stop la página): en móvil el sticky molesta más
   que ayuda — el FloatingReader ya cubre la necesidad cuando el usuario
   selecciona texto. Que se quede en su posición y desaparezca al hacer scroll. */
@media (max-width: 860px) {
    .ecoleng-doc .ecoleng-doc__topbar {
        position: static;
        backdrop-filter: none;
    }
}

/* ========================================================================
 * 24. Batch v2.2.17 — fixes post-validación 1.1.1 V8 (topic 18986 prod)
 * Ver notas/registro-correcciones.md issues #53 + nuevos 2026-05-08
 * ====================================================================== */

/* (A) Callout: el último hijo (típicamente <p>) arrastra `margin-bottom: 1em`
   de la regla genérica de párrafo, dejando aire vacío entre el texto y el
   borde inferior del callout. Forzamos sin margin en el último hijo. */
.ecoleng-doc .ecoleng-doc__callout > *:last-child {
    margin-bottom: 0;
}

/* (#53 / D) Chips de "Accents et ponctuation française": el contenedor
   `.ecoleng-doc__card--letter` solo tenía `text-align: center`, lo que
   no garantiza layout horizontal cuando los <button> hijos se renderizan
   block (Astra/LearnDash o reset del tema pueden forzarlo). Convertimos
   el contenedor explícitamente en flex container con wrap → parrilla
   horizontal centrada, idéntico al fallback ya existente para
   `__copybar` / `__accents-bar` (alias legacy). */
.ecoleng-doc .ecoleng-doc__card--letter {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: .35rem;
}

/* (C) `.ecoleng-doc__production` aparece en MASTER_v4 como contenedor
   `<div>` que envuelve un `<textarea>` + un `<button>` (Envoyer pour
   correction). El CSS heredado de v2.2.0 aplicaba estilos de TEXTAREA
   (min-height: 140px, padding .9rem, border, etc.) directamente al
   selector `.ecoleng-doc__production` — al ser un `<div>`, el padding
   superior empujaba el botón muy abajo y dejaba aire excesivo arriba.
   Restringimos los estilos de textarea al elemento textarea real, y
   damos al `<div>__production` un layout limpio con stack vertical. */
.ecoleng-doc div.ecoleng-doc__production {
    display: flex;
    flex-direction: column;
    gap: .75rem;
    align-items: stretch;
    min-height: 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
}
.ecoleng-doc div.ecoleng-doc__production > .ecoleng-doc__btn,
.ecoleng-doc div.ecoleng-doc__production > button {
    align-self: flex-start;
}
.ecoleng-doc div.ecoleng-doc__production > textarea {
    width: 100%;
    min-height: 140px;
    padding: .9rem;
    font: inherit;
    font-family: var(--ecoleng-font-body);
    background: var(--ecoleng-white);
    border: 1px solid var(--ecoleng-border);
    border-radius: var(--ecoleng-radius);
    resize: vertical;
}
.ecoleng-doc div.ecoleng-doc__production > textarea:focus {
    outline: 2px solid var(--ecoleng-blue);
    outline-offset: 2px;
}

/* (B) Refuerzo del grid de `.ecoleng-doc__line` para garantizar que
   Écouter y Lent queden en la **misma fila** a la derecha del speaker
   y la réplica, no apilados verticalmente. Ya estaba declarado en §22
   (v2.2.15) pero subimos especificidad para vencer caché/overrides
   residuales del tema. */
.ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line {
    display: grid;
    grid-template-columns: minmax(80px, auto) 1fr 100px 100px;
    align-items: center;
    gap: .6rem;
}
.ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line > .ecoleng-doc__btn {
    grid-row: auto;
    align-self: center;
}

/* v2.2.19 — Defensa CSS contra <br> espurios de wpautop dentro de los
   contenedores que dependen de orden DOM estricto. El filtro PHP de
   v2.2.18 no alcanza todos los paths de render de LearnDash en
   producción, así que ocultamos los <br> en los lugares donde nunca
   deben existir. `display: none` los retira del flujo y del grid sin
   afectar el conteo de columnas. */
.ecoleng-doc .ecoleng-doc__line > br,
.ecoleng-doc .ecoleng-doc__production > br,
.ecoleng-doc .ecoleng-doc__formule > br,
.ecoleng-doc .ecoleng-doc__topbar > br,
.ecoleng-doc .ecoleng-doc__pdf-links > br,
.ecoleng-doc .ecoleng-doc__footer-cta > br,
.ecoleng-doc .ecoleng-doc__card--letter > br,
.ecoleng-doc .ecoleng-doc__card--resource > br,
.ecoleng-doc .cei-exercise__actions > br,
.ecoleng-doc .cei-exercise__solution > br,
.ecoleng-doc .cei-exercise__solution-summary > br {
    display: none;
}

/* v2.2.20 — wpautop también mete <br> DENTRO de algunos elementos cuando
   el HTML fuente tiene whitespace+newline alrededor del texto (típico
   en `<button>\n  Envoyer pour correction\n</button>` → se convierte en
   `<button><br>Envoyer pour correction<br></button>`, y el botón pasa a
   tener 3 "líneas" de altura). Anulamos los <br> dentro de:
   - botones del wrapper
   - <a> con clase de botón (ej. PDFs, footer CTA)
   - <h1>..<h4> y <p> dentro del wrapper (whitespace de indentado).
   No afectamos los <br> dentro de help, notepad o textareas — ahí sí
   pueden tener uso editorial legítimo. */
.ecoleng-doc button > br,
.ecoleng-doc a.ecoleng-doc__btn > br,
.ecoleng-doc h1 > br,
.ecoleng-doc h2 > br,
.ecoleng-doc h3 > br,
.ecoleng-doc h4 > br {
    display: none;
}

/* ========================================================================
 * 25. Batch v2.2.21 — fix regresión móvil tras v2.2.19/§24 (issue #57)
 * ====================================================================== */

/* La regla v2.2.19 `.ecoleng-doc__dialogue .ecoleng-doc__line` (especificidad
   0,3,0) le ganaba a la override móvil de §22 línea 825 `.ecoleng-doc
   .ecoleng-doc__line` (especificidad 0,2,0), por lo que en móvil seguía
   aplicándose el grid 4-cols → frases desbordaban el contenedor y los
   botones quedaban apretados sin padding. Subimos especificidad de las
   reglas móvil para que ganen siempre. */
@media (max-width: 640px) {
    /* Stack vertical: speaker arriba, replique debajo (ambos span 2 cols),
       luego Écouter y Lent en fila propia 50/50. */
    .ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line {
        grid-template-columns: 1fr 1fr;
        grid-auto-flow: row;
        row-gap: .5rem;
        column-gap: .5rem;
    }
    .ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line > .ecoleng-doc__speaker,
    .ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line > p {
        grid-column: 1 / -1;
    }
    /* Botones del diálogo en móvil: 50/50 con padding interno respirable.
       Subimos especificidad sobre la regla §21 línea 755 que fija
       width: 100px (selector `.ecoleng-doc .ecoleng-doc__line .ecoleng-doc__btn[data-tts-text]`,
       0,3,1). Añadimos `.ecoleng-doc__dialogue` para llegar a 0,4,1. */
    .ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line .ecoleng-doc__btn[data-tts-text],
    .ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line .ecoleng-doc__btn[data-tts-rate],
    .ecoleng-doc .ecoleng-doc__dialogue .ecoleng-doc__line [data-tts-rate] {
        width: 100%;
        max-width: none;
        min-width: 0;
        padding: .55rem 1rem;
    }
}

/* Garantía adicional: el wrapper `.ecoleng-doc` y sus hijos directos no
   deben permitir desbordamiento horizontal en móvil — si una palabra larga
   o un bloque inflado se sale, debe ajustarse en lugar de empujar el
   layout completo. */
.ecoleng-doc {
    overflow-wrap: break-word;
    word-break: normal;
}
.ecoleng-doc .ecoleng-doc__dialogue,
.ecoleng-doc .ecoleng-doc__section,
.ecoleng-doc .ecoleng-doc__hero {
    max-width: 100%;
    overflow-x: hidden;
}

/* ========================================================================
 * 26. Batch v2.2.24 — espaciado móvil estrecho en LearnDash Focus Mode
 * ====================================================================== */

/* En pantallas muy estrechas, LearnDash añade 27px por lado a
   `.ld-focus-content`. Sumado al padding propio de cards/secciones, el texto
   útil queda demasiado estrecho. Ensanchamos solo el wrapper de contenido de
   Lessons/Topics en Focus Mode para cubrir también contenidos legacy sin
   tocar globalmente `.ld-focus-content`. */
@media (max-width: 480px) {
    body.ld-in-focus-mode.single-sfwd-topic .ld-focus-content > .learndash,
    body.ld-in-focus-mode.single-sfwd-lessons .ld-focus-content > .learndash,
    body.ld-in-focus-mode.single-sfwd-topic .ld-focus-content > .learndash-wrapper.ld-layout,
    body.ld-in-focus-mode.single-sfwd-lessons .ld-focus-content > .learndash-wrapper.ld-layout {
        width: calc(100% + 34px);
        max-width: none;
        margin-left: -17px;
        margin-right: -17px;
    }

    .ecoleng-doc .ecoleng-doc__hero,
    .ecoleng-doc .ecoleng-doc__section {
        padding: 15px;
    }

    .ecoleng-doc .ecoleng-doc__card,
    .ecoleng-doc .ecoleng-doc__callout {
        padding: 11px 12px;
    }

    .ecoleng-doc ul,
    .ecoleng-doc ol {
        padding-inline-start: 1.05em;
    }
}

/* ========================================================================
 * 27. Batch v2.2.27 — Solution desplegable para ejercicios cerrados
 * ====================================================================== */

.ecoleng-doc .cei-exercise__solution {
    display: block;
    box-sizing: border-box;
    width: fit-content;
    max-width: 100%;
    margin-top: .75rem;
    padding: 0;
    border: 1px solid var(--ecoleng-purple, #8A2976);
    border-radius: 8px;
    background: #F5F8FB;
    color: var(--ecoleng-purple, #8A2976);
    box-shadow: none;
    overflow: hidden;
}

.ecoleng-doc .cei-exercise__solution[open] {
    width: 100%;
    border-color: var(--ecoleng-purple, #8A2976);
    border-radius: var(--ecoleng-radius, 15px);
    background: #F5F8FB;
}

.ecoleng-doc .cei-exercise__solution-summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    box-sizing: border-box;
    width: fit-content;
    max-width: 100%;
    min-height: 42px;
    padding: .55rem 1.1rem;
    border: 0;
    background: transparent;
    color: var(--ecoleng-purple, #8A2976);
    cursor: pointer;
    user-select: none;
    list-style: none;
    font-family: var(--ecoleng-font-body);
    font-size: .95rem;
    font-weight: 700;
    line-height: 1.2;
}

.ecoleng-doc .cei-exercise__solution[open] > .cei-exercise__solution-summary {
    width: 100%;
    justify-content: flex-start;
}

.ecoleng-doc .cei-exercise__solution-summary::-webkit-details-marker {
    display: none;
}

.ecoleng-doc .cei-exercise__solution-summary::marker {
    content: "";
}

.ecoleng-doc .cei-exercise__solution:not([open]) > .cei-exercise__solution-summary:hover {
    background: #F5F8FB;
}

.ecoleng-doc .cei-exercise__solution-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: auto;
    height: auto;
    margin-left: .2rem;
    background: transparent;
    color: var(--ecoleng-purple, #8A2976);
    font-size: 1.1rem;
    font-weight: 800;
    line-height: 1;
    transition: transform .18s ease;
}

.ecoleng-doc .cei-exercise__solution[open] .cei-exercise__solution-arrow {
    transform: rotate(180deg);
}

.ecoleng-doc .cei-exercise__solution-body {
    padding: .35rem 1.1rem 1rem;
    color: var(--ecoleng-ink, #222221);
}

.ecoleng-doc .cei-exercise__solution-body > *:last-child {
    margin-bottom: 0;
}

/* ======================================================================
 * 28. Patch v2.2.28 — sommaire plus lisible sur Course/Lesson/Topic
 * ====================================================================== */

.ecoleng-doc .ecoleng-doc__toc > summary,
.ecoleng-doc .ecoleng-doc__toc > details > summary {
    font-size: 1.35rem;
    line-height: 1.15;
    letter-spacing: 0;
    font-family: var(--ecoleng-font-heading);
    font-weight: 700;
    color: var(--ecoleng-ink);
    list-style: none;
    cursor: pointer;
    padding: .15rem 0;
}

.ecoleng-doc .ecoleng-doc__toc > details > summary::-webkit-details-marker {
    display: none;
}

.ecoleng-doc .ecoleng-doc__toc > details > summary::marker {
    content: "";
}

.ecoleng-doc .ecoleng-doc__toc > details > summary::after {
    content: '▾';
    float: right;
    transition: transform .2s ease;
}

.ecoleng-doc .ecoleng-doc__toc > details[open] > summary::after {
    transform: rotate(180deg);
}

.ecoleng-doc .ecoleng-doc__toc > details[open] > summary {
    margin-bottom: .75rem;
    padding-bottom: .6rem;
    border-bottom: 1px solid var(--ecoleng-border);
}

/* ======================================================================
 * 31. Patch v2.2.32 — botones de lectura TTS (toggle Écouter/Arrêter) +
 *      slider de vitesse inyectado por JS.
 *
 *  - El JS (módulo Tts) marca los botones de lectura con .cei-tts-btn y los
 *    normaliza a estructura icono+label (<span class="btn-icon"> + <span class="btn-label">).
 *  - El botón de lectura gana degradado morado + sombra; al sonar pasa a
 *    .is-playing (degradado azul Ecoleng) y el JS cambia el icono ▶→■ y el
 *    texto Écouter→Arrêter.
 *  - El slider .cei-tts-rate se inyecta tras el botón, salvo en diálogos
 *    (.ecoleng-doc__line) y en botones de topbar (data-tts-stop).
 *  - Todo scopeado a .ecoleng-doc → retroactivo en topics publicados, sin
 *    afectar a topics antiguos sin wrapper.
 *  Ver notas/registro-correcciones.md y demo demo-ecouter-toggle-v3.html.
 * ====================================================================== */

/* --- Botón de lectura: hereda geometría de .ecoleng-doc__btn, añade degradado --- */
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn {
    background: linear-gradient(135deg, #a8418f 0%, var(--ecoleng-purple) 100%);
    border-color: transparent;
    color: #fff;
    box-shadow: 0 2px 6px rgba(138, 41, 118, .35);
    transition: filter .15s ease, box-shadow .15s ease;
}
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn:hover {
    background: linear-gradient(135deg, #a8418f 0%, var(--ecoleng-purple) 100%);
    filter: brightness(1.05);
}
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn:active { filter: brightness(.97); }

/* estado "suena": mismo botón en azul Ecoleng degradado */
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn.is-playing {
    background: linear-gradient(135deg, #1fb0db 0%, var(--ecoleng-blue) 100%);
    box-shadow: 0 2px 6px rgba(24, 149, 189, .35);
}
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn.is-playing:hover {
    background: linear-gradient(135deg, #1fb0db 0%, var(--ecoleng-blue) 100%);
    filter: brightness(1.05);
}

/* icono play/stop dibujado con CSS (no glifos de texto: tamaño idéntico y nítido
   en cualquier fuente/navegador). El JS solo togglea .is-playing; el .btn-icon
   queda como caja-ancla vacía y el ::before pinta el triángulo o el cuadrado.
   currentColor → heredan el blanco del texto del botón. */
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn .btn-icon {
    font-size: 0;            /* anula cualquier glifo de texto residual */
    width: 13px;
    height: 13px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
/* ▶ triángulo (reposo) — un poco más grande que el cuadrado */
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn:not(.is-playing) .btn-icon::before {
    content: "";
    display: block;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 7px 0 7px 12px;   /* alto 14px, ancho 12px */
    border-color: transparent transparent transparent currentColor;
}
/* ■ cuadrado (sonando) */
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn.is-playing .btn-icon::before {
    content: "";
    display: block;
    width: 10px;
    height: 10px;
    background: currentColor;
}

/* label: caja fija — "Écouter" y "Arrêter" tienen distinto ancho de glifos */
.ecoleng-doc .ecoleng-doc__btn.cei-tts-btn .btn-label {
    display: inline-block;
    min-width: 4.2em;
    text-align: center;
}

/* --- Slider de vitesse inyectado --- */
.ecoleng-doc .cei-tts-rate {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-inline-start: 12px;
    font-family: var(--ecoleng-font-body);
    font-size: .9rem;
    color: var(--ecoleng-ink);
    vertical-align: middle;
}
.ecoleng-doc .cei-tts-rate label { white-space: nowrap; }

/* Reset fuerte para sortear estilos de range del tema/WP (thumb descentrado). */
.ecoleng-doc .cei-tts-rate input[type="range"] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    box-sizing: border-box;
    width: 120px;
    height: 14px;            /* alto total = tamaño del thumb, para centrarlo bien */
    margin: 0;
    padding: 0;
    background: transparent; /* el color va en el track, no en el input */
    cursor: pointer;
    outline: none;
    vertical-align: middle;
}
/* WebKit: pista explícita de 4px + thumb centrado con margin-top negativo */
.ecoleng-doc .cei-tts-rate input[type="range"]::-webkit-slider-runnable-track {
    -webkit-appearance: none;
    appearance: none;
    height: 4px;
    border-radius: 2px;
    border: none;
    background: linear-gradient(to right,
        #c9a3c0 0%,
        #c9a3c0 var(--fill, 30%),
        #ececec var(--fill, 30%),
        #ececec 100%);
}
.ecoleng-doc .cei-tts-rate input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    box-sizing: border-box;
    width: 14px;
    height: 14px;
    margin-top: -5px;        /* (4px track - 14px thumb) / 2 = -5px → centra el thumb */
    border-radius: 50%;
    background: var(--ecoleng-purple);
    border: none;
    cursor: pointer;
}
/* Firefox: track + thumb (Firefox ya centra el thumb sobre el track) */
.ecoleng-doc .cei-tts-rate input[type="range"]::-moz-range-track {
    height: 4px;
    border-radius: 2px;
    border: none;
    background: #ececec;
}
.ecoleng-doc .cei-tts-rate input[type="range"]::-moz-range-progress {
    height: 4px;
    border-radius: 2px;
    background: #c9a3c0;
}
.ecoleng-doc .cei-tts-rate input[type="range"]::-moz-range-thumb {
    box-sizing: border-box;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--ecoleng-purple);
    border: none;
    cursor: pointer;
}

.ecoleng-doc .cei-tts-rate .rate-value {
    min-width: 2.2em;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--ecoleng-ink);
    opacity: .7;
}

/* --- Móvil: el slider baja debajo del botón, ancho disponible --- */
@media (max-width: 640px) {
    .ecoleng-doc .cei-tts-rate {
        display: flex;
        width: 100%;
        margin-inline-start: 0;
        margin-top: 8px;
    }
    .ecoleng-doc .cei-tts-rate input[type="range"] {
        flex: 1 1 auto;
        width: auto;
    }
}
