Compare commits

..

9 Commits

451 changed files with 48351 additions and 993 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
View File
@@ -34,6 +34,10 @@
}, },
{ {
"title": "Manejo de Objeciones", "title": "Manejo de Objeciones",
"content": "contenido/mo.html"
},
{
"title": "Actividad",
"content": "contenido/08.html" "content": "contenido/08.html"
}, },
{ {
+1 -1
View File
@@ -88,7 +88,7 @@
<div class="w-100"> <div class="w-100">
<div class="ratio ratio-16x9"> <div class="ratio ratio-16x9">
<video id="video" class="embed-responsive-item" controls autoplay poster="video/poster.jpg"> <video id="video" class="embed-responsive-item" controls autoplay poster="video/poster.jpg">
<source src="video/dummy.mp4" type="video/mp4" /> <source src="video/Drossagyn.mp4" type="video/mp4" />
Your browser does not support the video tag. Your browser does not support the video tag.
</video> </video>
<div class="play-button-container"> <div class="play-button-container">
+303
View File
@@ -0,0 +1,303 @@
<style>
.fake {
background-image: url('img/mo.png');
background-size: cover;
background-position: center;
}
/* --- Contenedor de la Burbuja --- */
.speech-bubble {
position: relative;
background: #ffffff; /* Fondo blanco */
color: #333333; /* Texto oscuro para legibilidad */
border-radius: 0.5em;
padding: 1.5rem;
font-size: 1.1rem;
min-height: 120px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); /* Sombra para resaltar sobre el fondo */
transition: all 0.3s ease-in-out;
}
.bubble-text {
line-height: 1.5;
}
/* --- Animaciones de Personajes (Foco visual) --- */
.speaker-active {
transform: scale(1.05);
filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.2));
transition: all 0.3s ease;
}
.speaker-inactive {
opacity: 0.6;
transform: scale(0.95);
transition: all 0.3s ease;
}
/* --- COMPORTAMIENTO MOBILE (Apilamiento vertical de Bootstrap) --- */
@media (max-width: 767.98px) {
/* Apunta hacia arriba (al Médico) */
.speech-bubble-left::after {
content: '';
position: absolute;
left: 50%;
top: -20px;
transform: translateX(-50%);
border: 20px solid transparent;
border-width: 0 20px 20px 20px;
border-bottom-color: #ffffff; /* Coincide con el fondo blanco */
margin: 0;
}
/* Apunta hacia abajo (al Representante) */
.speech-bubble-right::after {
content: '';
position: absolute;
left: 50%;
top: auto;
bottom: -20px;
transform: translateX(-50%);
border: 20px solid transparent;
border-width: 20px 20px 0 20px;
border-top-color: #ffffff; /* Coincide con el fondo blanco */
margin: 0;
}
}
/* --- COMPORTAMIENTO DESKTOP (md y superior) --- */
@media (min-width: 768px) {
/* Apunta hacia la izquierda */
.speech-bubble-left::after {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 0;
height: 0;
border: 20px solid transparent;
border-right-color: #ffffff; /* Coincide con el fondo blanco */
border-left: 0;
margin-top: -20px;
margin-left: -20px;
transform: none;
}
/* Apunta hacia la derecha */
.speech-bubble-right::after {
content: '';
position: absolute;
right: 0;
left: auto;
top: 50%;
width: 0;
height: 0;
border: 20px solid transparent;
border-left-color: #ffffff; /* Coincide con el fondo blanco */
border-right: 0;
margin-top: -20px;
margin-right: -20px;
transform: none;
}
}
</style>
</style>
<div class='page-sco py-3 py-md-4 bg-transparent'>
<div class='container'>
<div class='row justify-content-center align-items-center'>
<div class='col-12 anim0'>
<div class='row justify-content-center align-items-center'>
<div class='col-12 text-center'>
<h2 class='mb-4 fw-semibold text-center'>Manejo de Objeciones</h2>
</div>
<!-- Avatar Médico -->
<div class='col-6 col-md-3 text-center'>
<img src='img/med.png' class='img-fluid speaker-inactive' alt='Médico' id="medico">
</div>
<!-- Contenedor Dinámico de Diálogo -->
<div class='col-12 col-md-6 text-center'>
<div id="dialogue-bubble" class="speech-bubble">
<div id="dialogue-text" class="bubble-text">
<!-- El texto se inyecta dinámicamente mediante JS -->
</div>
</div>
</div>
<!-- Avatar Representante -->
<div class='col-6 col-md-3 text-center'>
<img src='img/rep.png' class='img-fluid speaker-inactive' alt='Representante' id="rep">
</div>
</div>
</div>
</div>
</div>
</div>
<script>
/**
* Módulo de Diálogo Interactivo
* Orquesta la secuencia de texto y audio, manipulando el DOM según el hablante activo.
*/
$(function () {
"use strict";
$('body').addClass('fake');
// Configuración de la secuencia del diálogo
const mo = [
{
text: "No utilizo Drossagyn porque la terapia hormonal aumenta el riesgo de cáncer (principalmente de mama) en las pacientes.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/0027-Drossagyn-ob1.mp3') : null,
img: '#medico'
},
{
text: "Doctor, entiendo perfectamente esa preocupación, porque durante muchos años el tema del riesgo oncológico asociado a la terapia hormonal generó mucha cautela en la práctica clínica.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo01.mp3') : null,
img: '#rep'
},
{
text: "Sin embargo, en los últimos años la evidencia ha permitido confirmar la seguridad de la terapia hormonal.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo02.mp3') : null,
img: '#rep'
},
{
text: "De hecho, este cambio de perspectiva fue tan contundente que en 2025 la FDA retiró las advertencias de seguridad, precisamente porque la evidencia acumulada permitió redefinir el verdadero perfil riesgo-beneficio de estas terapias.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo03.mp3') : null,
img: '#rep'
},
{
text: "Además, cuando hablamos de Drossagyn, estamos hablando de estriol administrado por vía local; la absorción sistémica es mínima, con concentraciones plasmáticas muy bajas, insuficientes para generar la exposición hormonal sostenida que en el pasado se asociaba a preocupación oncológica en las terapias sistémicas.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo04.mp3') : null,
img: '#rep'
},
{
text: "Al mismo tiempo, la administración local de Drossagyn logra una excelente eficacia sobre los tejidos vaginales, restaurando el grosor epitelial, la elasticidad y la lubricación, con un impacto clínico muy claro sobre los síntomas y la calidad de vida de la paciente.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo05.mp3') : null,
img: '#rep'
},
{
text: "Mis pacientes, en general, tienen mala adherencia a tratamientos con cremas vaginales.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/0029-Drossagyn-ob2.mp3') : null,
img: '#medico'
},
{
text: "Entiendo, doctor, de acuerdo con lo que me comenta, que algunas pacientes pueden tener dudas iniciales sobre la aplicación vaginal",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo06.mp3') : null,
img: '#rep'
},
{
text: "Sin embargo, cuando experimentan la mejoría directa en síntomas como resequedad, ardor o dispareunia, la adherencia mejora significativamente.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo07.mp3') : null,
img: '#rep'
},
{
text: "Drossagyn actúa directamente en el tejido afectado, lo que permite una recuperación más fisiológica y eficaz del epitelio vaginal, favoreciendo que la paciente perciba el beneficio y continúe el tratamiento.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo08.mp3') : null,
img: '#rep'
},
{
text: "¿No le parece que valdría mucho la pena transmitir a sus pacientes los beneficios que pueden obtener en relación con su calidad de vida con el uso de Drossagyn?",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo09.mp3') : null,
img: '#rep'
},
{
text: "Reconozco la importancia de la terapia hormonal local, sin embargo, me funciona muy bien Ovestin. ¿Por qué cambiaría?",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/0031-Drossagyn-ob3.mp3') : null,
img: '#medico'
},
{
text: "Doctor, gracias por su comentario.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo10.mp3') : null,
img: '#rep'
},
{
text: "Entiendo con esto que ya cuenta con experiencia en el uso de estriol local. Permítame mencionarle una de las ventajas de Drossagyn: ofrece estriol en una formulación farmacéutica desarrollada bajo estándares europeos y con el respaldo científico de Besins Healthcare, líder global en salud hormonal femenina.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo11.mp3') : null,
img: '#rep'
},
{
text: "Esto le permite contar con una opción confiable dentro de un portafolio especializado en el manejo del síndrome genitourinario de la menopausia. Aunado a lo anterior, Drossagyn es una crema muy ligera y de fácil aplicación que no dejará residuos molestos en la paciente.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo12.mp3') : null,
img: '#rep'
},
{
text: "Un beneficio adicional es que su presentación cubrirá los 3 meses iniciales de tratamiento indicados por las guías para tratar los síntomas genitourinarios de la menopausia.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo13.mp3') : null,
img: '#rep'
},
{
text: "Sin duda, es un tema que puede llamar la atención de sus pacientes.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo14.mp3') : null,
img: '#rep'
},
{
text: "¿no le parece, Doctor?",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo15.mp3') : null,
img: '#rep'
},
];
// Caché de elementos del DOM
const $bubble = $('#dialogue-bubble');
const $text = $('#dialogue-text');
const $medico = $('#medico');
const $rep = $('#rep');
/**
* Ejecuta un nodo de diálogo recursivamente hasta finalizar el array.
* @param {number} index - Índice actual de la conversación.
*/
function playDialogueStep(index) {
// Condición de cierre: Secuencia terminada
if (index >= mo.length) {
if (typeof CourseNav !== 'undefined' && typeof CourseNav.completeLesson === 'function') {
CourseNav.setSlideVisited();
}
return;
}
const currentStep = mo[index];
// 1. Actualizar texto con transición limpia
$text.hide().html(`<p class="mb-0 m-0">${currentStep.text}</p>`).fadeIn(300);
// 2. Gestionar la orientación de la burbuja y el foco en los personajes
if (currentStep.img === '#medico') {
$bubble.removeClass('speech-bubble-right').addClass('speech-bubble-left');
$medico.removeClass('speaker-inactive').addClass('speaker-active');
$rep.removeClass('speaker-active').addClass('speaker-inactive');
} else if (currentStep.img === '#rep') {
$bubble.removeClass('speech-bubble-left').addClass('speech-bubble-right');
$rep.removeClass('speaker-inactive').addClass('speaker-active');
$medico.removeClass('speaker-active').addClass('speaker-inactive');
}
// 3. Reproducir audio e instanciar el listener recursivo
if (typeof CourseNav !== 'undefined' && CourseNav.audioController && currentStep.sound) {
CourseNav.audioController.stopAllSoundsAndPlay(currentStep.sound);
// Asumiendo que CourseNav utiliza Howler.js u otra API basada en eventos (on/once)
currentStep.sound.once("end", function () {
playDialogueStep(index + 1);
});
} else {
// Fallback para entornos de desarrollo donde el audio no esté cargado
console.warn(`[Modo Desarrollo]: Simulando delay para el audio de: ${currentStep.img}`);
setTimeout(() => {
playDialogueStep(index + 1);
}, 4000);
}
}
// Inicializar el diálogo
playDialogueStep(0);
});
</script>
Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

+69 -17
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="es"> <html lang="es">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
@@ -15,9 +15,9 @@
<link rel="stylesheet" href="css/sweetalert2.min.css" /> <link rel="stylesheet" href="css/sweetalert2.min.css" />
<link rel="stylesheet" href="css/swiper-bundle.min.css" /> <link rel="stylesheet" href="css/swiper-bundle.min.css" />
<link rel="stylesheet" href="css/driver.css" /> <link rel="stylesheet" href="css/driver.css" />
<link rel="stylesheet" href="font/roboto/stylesheet.css"> <link rel="stylesheet" href="font/roboto/stylesheet.css" />
<link rel="stylesheet" href="css/theme.min.css" /> <link rel="stylesheet" href="css/theme.min.css" />
<link rel="stylesheet" href="css/sal.css"> <link rel="stylesheet" href="css/sal.css" />
<link rel="stylesheet" href="css/style.min.css" /> <link rel="stylesheet" href="css/style.min.css" />
</head> </head>
<body> <body>
@@ -29,7 +29,10 @@
<a class="navbar-brand p-0 disabled order-1" href="#"> <a class="navbar-brand p-0 disabled order-1" href="#">
<img src="img/template/logo.svg" width="180" alt="Logo" /> <img src="img/template/logo.svg" width="180" alt="Logo" />
</a> </a>
<div id="titleSco" class="flex-grow-1 title_head_sco text-center text-white fw-bold fs-5 order-3 order-md-2"></div> <div
id="titleSco"
class="flex-grow-1 title_head_sco text-center text-white fw-bold fs-5 order-3 order-md-2"
></div>
<div class="d-flex align-items-center text-white order-2 order-md-3 ms-auto"> <div class="d-flex align-items-center text-white order-2 order-md-3 ms-auto">
<!-- <button class="btn-glossary controls-btn me-2" id="btn-glossary" aria-label="Glossary"> <!-- <button class="btn-glossary controls-btn me-2" id="btn-glossary" aria-label="Glossary">
<i class="fa-regular fa-book-section fa-xl"></i> <i class="fa-regular fa-book-section fa-xl"></i>
@@ -39,7 +42,17 @@
<div class="position-relative"> <div class="position-relative">
<svg viewBox="0 0 100 100" class="w-100 h-100"> <svg viewBox="0 0 100 100" class="w-100 h-100">
<circle cx="50" cy="50" r="45" stroke="#f7f7f7" stroke-width="10" fill="none" /> <circle cx="50" cy="50" r="45" stroke="#f7f7f7" stroke-width="10" fill="none" />
<circle id="coursenav-progress-circle" cx="50" cy="50" r="45" stroke="#009ace" stroke-width="10" fill="none" stroke-dasharray="283" stroke-dashoffset="283" /> <circle
id="coursenav-progress-circle"
cx="50"
cy="50"
r="45"
stroke="#009ace"
stroke-width="10"
fill="none"
stroke-dasharray="283"
stroke-dashoffset="283"
/>
</svg> </svg>
<i id="coursenav-audio-icon" class="fa-duotone fa-solid fa-volume"></i> <i id="coursenav-audio-icon" class="fa-duotone fa-solid fa-volume"></i>
</div> </div>
@@ -62,10 +75,20 @@
</header> </header>
<!-- OFFCANVAS DESDE DERECHA --> <!-- OFFCANVAS DESDE DERECHA -->
<div class="offcanvas offcanvas-end bg-green-1 text-white" tabindex="-1" id="coursenav-offcanvas" aria-labelledby="coursenav-offcanvas-label"> <div
class="offcanvas offcanvas-end bg-green-1 text-white"
tabindex="-1"
id="coursenav-offcanvas"
aria-labelledby="coursenav-offcanvas-label"
>
<div class="offcanvas-header"> <div class="offcanvas-header">
<h5 id="coursenav-offcanvas-label" class="offcanvas-title">Índice</h5> <h5 id="coursenav-offcanvas-label" class="offcanvas-title">Índice</h5>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button> <button
type="button"
class="btn-close text-reset"
data-bs-dismiss="offcanvas"
aria-label="Close"
></button>
</div> </div>
<div class="offcanvas-body d-flex flex-column p-0"> <div class="offcanvas-body d-flex flex-column p-0">
<!-- Menú principal --> <!-- Menú principal -->
@@ -96,18 +119,33 @@
<main id="coursenav-main-content"></main> <main id="coursenav-main-content"></main>
<!-- FOOTER --> <!-- FOOTER -->
<footer class="mt-auto py-1 d-flex flex-wrap justify-content-center align-items-center gap-2 gap-md-3 px-2 px-md-4" style="background-color: rgba(220, 220, 220, .7);"> <footer
class="mt-auto py-1 d-flex flex-wrap justify-content-center align-items-center gap-2 gap-md-3 px-2 px-md-4"
style="background-color: rgba(220, 220, 220, 0.7)"
>
<div class="aviso-privacidad flex-fill flex-md-none order-2 order-md-1"> <div class="aviso-privacidad flex-fill flex-md-none order-2 order-md-1">
<p class="mb-0 small text-center text-md-start">Uso exclusivo de capacitación interna, prohibida su reproducción y/o distribución</p> <p class="mb-0 small text-center text-md-start">
Uso exclusivo de capacitación interna, prohibida su reproducción y/o distribución
</p>
</div> </div>
<div class="d-flex justify-content-center align-items-center gap-3 position-relative ms-md-auto flex-fill flex-md-none order-1 order-md-2"> <div
<button id="coursenav-prev-btn" class="coursenav-btn-navigation bg-green-1 text-white" data-bs-toggle="tooltip" class="d-flex justify-content-center align-items-center gap-3 position-relative ms-md-auto flex-fill flex-md-none order-1 order-md-2"
title="Anterior"> >
<button
id="coursenav-prev-btn"
class="coursenav-btn-navigation bg-green-1 text-white"
data-bs-toggle="tooltip"
title="Anterior"
>
<i class="fa-solid fa-arrow-down fa-rotate-90"></i> <i class="fa-solid fa-arrow-down fa-rotate-90"></i>
</button> </button>
<div id="pagination" class="paginacion_sco fw-bold"></div> <div id="pagination" class="paginacion_sco fw-bold"></div>
<button id="coursenav-next-btn" class="coursenav-btn-navigation bg-green-1 text-white" data-bs-toggle="tooltip" <button
title="Siguiente"> id="coursenav-next-btn"
class="coursenav-btn-navigation bg-green-1 text-white"
data-bs-toggle="tooltip"
title="Siguiente"
>
<i class="fa-solid fa-arrow-down fa-rotate-270"></i> <i class="fa-solid fa-arrow-down fa-rotate-270"></i>
</button> </button>
</div> </div>
@@ -121,12 +159,26 @@
</div> </div>
<!-- Offcanvas: inicialmente vacío --> <!-- Offcanvas: inicialmente vacío -->
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasGlossary" aria-labelledby="offcanvasGlossaryLabel"> <div
class="offcanvas offcanvas-end"
tabindex="-1"
id="offcanvasGlossary"
aria-labelledby="offcanvasGlossaryLabel"
>
<div class="offcanvas-header"> <div class="offcanvas-header">
<h1 class="offcanvas-title text-danger text-center amor fw-bold" id="offcanvasGlossaryLabel" style="width: 90%;"> <h1
class="offcanvas-title text-danger text-center amor fw-bold"
id="offcanvasGlossaryLabel"
style="width: 90%"
>
OGestan<sup>®</sup> Plus OGestan<sup>®</sup> Plus
</h1> </h1>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Cerrar"></button> <button
type="button"
class="btn-close text-reset"
data-bs-dismiss="offcanvas"
aria-label="Cerrar"
></button>
</div> </div>
<div class="offcanvas-body overflow-auto"> <div class="offcanvas-body overflow-auto">
<!-- Aquí irá el contenido de manual_pld_ft.html --> <!-- Aquí irá el contenido de manual_pld_ft.html -->
Binary file not shown.
+3 -1
View File
@@ -4,5 +4,7 @@
"path": "." "path": "."
} }
], ],
"settings": {} "settings": {
"liveServer.settings.port": 5501
}
} }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
View File
@@ -30,6 +30,10 @@
}, },
{ {
"title": "Manejo de Objeciones", "title": "Manejo de Objeciones",
"content": "contenido/mo.html"
},
{
"title": "Actividad de aprendizaje",
"content": "contenido/07.html" "content": "contenido/07.html"
}, },
{ {
+1 -1
View File
@@ -88,7 +88,7 @@
<div class="w-100"> <div class="w-100">
<div class="ratio ratio-16x9"> <div class="ratio ratio-16x9">
<video id="video" class="embed-responsive-item" controls autoplay poster="video/poster.jpg"> <video id="video" class="embed-responsive-item" controls autoplay poster="video/poster.jpg">
<source src="video/dummy.mp4" type="video/mp4" /> <source src="video/OGestanPlus.mp4" type="video/mp4" />
Your browser does not support the video tag. Your browser does not support the video tag.
</video> </video>
<div class="play-button-container"> <div class="play-button-container">
+259
View File
@@ -0,0 +1,259 @@
<style>
.fake {
background-image: url('img/mo.png');
background-size: cover;
background-position: center;
}
/* --- Contenedor de la Burbuja --- */
.speech-bubble {
position: relative;
background: #ffffff; /* Fondo blanco */
color: #333333; /* Texto oscuro para legibilidad */
border-radius: 0.5em;
padding: 1.5rem;
font-size: 1.1rem;
min-height: 120px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); /* Sombra para resaltar sobre el fondo */
transition: all 0.3s ease-in-out;
}
.bubble-text {
line-height: 1.5;
}
/* --- Animaciones de Personajes (Foco visual) --- */
.speaker-active {
transform: scale(1.05);
filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.2));
transition: all 0.3s ease;
}
.speaker-inactive {
opacity: 0.6;
transform: scale(0.95);
transition: all 0.3s ease;
}
/* --- COMPORTAMIENTO MOBILE (Apilamiento vertical de Bootstrap) --- */
@media (max-width: 767.98px) {
/* Apunta hacia arriba (al Médico) */
.speech-bubble-left::after {
content: '';
position: absolute;
left: 50%;
top: -20px;
transform: translateX(-50%);
border: 20px solid transparent;
border-width: 0 20px 20px 20px;
border-bottom-color: #ffffff; /* Coincide con el fondo blanco */
margin: 0;
}
/* Apunta hacia abajo (al Representante) */
.speech-bubble-right::after {
content: '';
position: absolute;
left: 50%;
top: auto;
bottom: -20px;
transform: translateX(-50%);
border: 20px solid transparent;
border-width: 20px 20px 0 20px;
border-top-color: #ffffff; /* Coincide con el fondo blanco */
margin: 0;
}
}
/* --- COMPORTAMIENTO DESKTOP (md y superior) --- */
@media (min-width: 768px) {
/* Apunta hacia la izquierda */
.speech-bubble-left::after {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 0;
height: 0;
border: 20px solid transparent;
border-right-color: #ffffff; /* Coincide con el fondo blanco */
border-left: 0;
margin-top: -20px;
margin-left: -20px;
transform: none;
}
/* Apunta hacia la derecha */
.speech-bubble-right::after {
content: '';
position: absolute;
right: 0;
left: auto;
top: 50%;
width: 0;
height: 0;
border: 20px solid transparent;
border-left-color: #ffffff; /* Coincide con el fondo blanco */
border-right: 0;
margin-top: -20px;
margin-right: -20px;
transform: none;
}
}
</style>
</style>
<div class='page-sco py-3 py-md-4 bg-transparent'>
<div class='container'>
<div class='row justify-content-center align-items-center'>
<div class='col-12 anim0'>
<div class='row justify-content-center align-items-center'>
<div class='col-12 text-center'>
<h2 class='mb-4 fw-semibold text-center'>Manejo de Objeciones</h2>
</div>
<!-- Avatar Médico -->
<div class='col-6 col-md-3 text-center'>
<img src='img/med.png' class='img-fluid speaker-inactive' alt='Médico' id="medico">
</div>
<!-- Contenedor Dinámico de Diálogo -->
<div class='col-12 col-md-6 text-center'>
<div id="dialogue-bubble" class="speech-bubble">
<div id="dialogue-text" class="bubble-text">
<!-- El texto se inyecta dinámicamente mediante JS -->
</div>
</div>
</div>
<!-- Avatar Representante -->
<div class='col-6 col-md-3 text-center'>
<img src='img/rep.png' class='img-fluid speaker-inactive' alt='Representante' id="rep">
</div>
</div>
</div>
</div>
</div>
</div>
<script>
/**
* Módulo de Diálogo Interactivo
* Orquesta la secuencia de texto y audio, manipulando el DOM según el hablante activo.
*/
$(function () {
"use strict";
$('body').addClass('fake');
// Configuración de la secuencia del diálogo
const mo = [
{
text: "¿Por qué Ogestan Plus tiene tan poca cantidad de hierro bisglicinato?",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/0026-objecion_1_ogestanplus.mp3') : null,
img: '#medico'
},
{
text: "Doctor, comprendo que la cantidad de hierro en la formulación de Ogestan Plus llame su atención.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo01.mp3') : null,
img: '#rep'
},
{
text: "Permítame compartirle que esta corresponde a la cantidad óptima que debe contener un suplemento alimenticio como lo es Ogestan Plus. Este producto no fue formulado como un medicamento para corregir una anemia ferropénica establecida ni como tratamiento de una deficiencia diagnosticada; para esos casos, por supuesto, usted requerirá esquemas terapéuticos específicos con dosis más altas según el perfil clínico de la paciente.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo02.mp3') : null,
img: '#rep'
},
{
text: "Ogestan Plus está pensado como una suplementación complementaria y de mantenimiento para mujeres en etapa de embarazo e incluso en lactancia, buscando cubrir los requerimientos fisiológicos diarios al sumarse a la alimentación habitual, pero evitando la sobrecarga gastrointestinal que suele comprometer la adherencia, a diferencia de otros hierros como el sulfato ferroso, por ejemplo.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo03.mp3') : null,
img: '#rep'
},
{
text: "Sabemos que la ingesta dietética recomendada de hierro durante el embarazo es de 27 mg al día.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo04.mp3') : null,
img: '#rep'
},
{
text: "En una paciente sin deficiencia previa, una dieta promedio suele aportar entre 12 y 15 mg diarios.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo05.mp3') : null,
img: '#rep'
},
{
text: "Por eso, al aportar 14 mg de hierro bisglicinato, Ogestan Plus permite alcanzar un total cercano a los 27-30 mg diarios, que es justamente el rango fisiológico recomendado para acompañar el embarazo de forma preventiva. Además, no se trata solo de la cantidad, sino de la forma química. ",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo06.mp3') : null,
img: '#rep'
},
{
text: "El hierro bisglicinato tiene una biodisponibilidad superior y una tolerancia digestiva considerablemente mejor que otras sales tradicionales, lo que favorece el apego al tratamiento por parte de las pacientes. Con Ogestan Plus estará seguro y con la tranquilidad de que sus pacientes no cursarán con síntomas gastrointestinales molestos como náusea, diarrea o estreñimiento, por mencionar algunos.",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo07.mp3') : null,
img: '#rep'
}
,
{
text: "Entonces, más que pensar en 'poca cantidad', la pregunta sería: ¿es la dosis fisiológicamente suficiente, bien tolerada y sostenible durante todo el embarazo? Ogestan Plus está diseñado para ofrecer justo ese equilibrio entre eficacia preventiva, biodisponibilidad y adherencia. Interesante, ¿no le parece, doctor?",
sound: typeof CourseNav !== 'undefined' ? CourseNav.createSound('audio/mo/mo08.mp3') : null,
img: '#rep'
}
];
// Caché de elementos del DOM
const $bubble = $('#dialogue-bubble');
const $text = $('#dialogue-text');
const $medico = $('#medico');
const $rep = $('#rep');
/**
* Ejecuta un nodo de diálogo recursivamente hasta finalizar el array.
* @param {number} index - Índice actual de la conversación.
*/
function playDialogueStep(index) {
// Condición de cierre: Secuencia terminada
if (index >= mo.length) {
if (typeof CourseNav !== 'undefined' && typeof CourseNav.completeLesson === 'function') {
CourseNav.setSlideVisited();
}
return;
}
const currentStep = mo[index];
// 1. Actualizar texto con transición limpia
$text.hide().html(`<p class="mb-0 m-0">${currentStep.text}</p>`).fadeIn(300);
// 2. Gestionar la orientación de la burbuja y el foco en los personajes
if (currentStep.img === '#medico') {
$bubble.removeClass('speech-bubble-right').addClass('speech-bubble-left');
$medico.removeClass('speaker-inactive').addClass('speaker-active');
$rep.removeClass('speaker-active').addClass('speaker-inactive');
} else if (currentStep.img === '#rep') {
$bubble.removeClass('speech-bubble-left').addClass('speech-bubble-right');
$rep.removeClass('speaker-inactive').addClass('speaker-active');
$medico.removeClass('speaker-active').addClass('speaker-inactive');
}
// 3. Reproducir audio e instanciar el listener recursivo
if (typeof CourseNav !== 'undefined' && CourseNav.audioController && currentStep.sound) {
CourseNav.audioController.stopAllSoundsAndPlay(currentStep.sound);
// Asumiendo que CourseNav utiliza Howler.js u otra API basada en eventos (on/once)
currentStep.sound.once("end", function () {
playDialogueStep(index + 1);
});
} else {
// Fallback para entornos de desarrollo donde el audio no esté cargado
console.warn(`[Modo Desarrollo]: Simulando delay para el audio de: ${currentStep.img}`);
setTimeout(() => {
playDialogueStep(index + 1);
}, 4000);
}
}
// Inicializar el diálogo
playDialogueStep(0);
});
</script>
Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

+69 -17
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="es"> <html lang="es">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
@@ -15,9 +15,9 @@
<link rel="stylesheet" href="css/sweetalert2.min.css" /> <link rel="stylesheet" href="css/sweetalert2.min.css" />
<link rel="stylesheet" href="css/swiper-bundle.min.css" /> <link rel="stylesheet" href="css/swiper-bundle.min.css" />
<link rel="stylesheet" href="css/driver.css" /> <link rel="stylesheet" href="css/driver.css" />
<link rel="stylesheet" href="font/roboto/stylesheet.css"> <link rel="stylesheet" href="font/roboto/stylesheet.css" />
<link rel="stylesheet" href="css/theme.min.css" /> <link rel="stylesheet" href="css/theme.min.css" />
<link rel="stylesheet" href="css/sal.css"> <link rel="stylesheet" href="css/sal.css" />
<link rel="stylesheet" href="css/style.min.css" /> <link rel="stylesheet" href="css/style.min.css" />
</head> </head>
<body> <body>
@@ -29,7 +29,10 @@
<a class="navbar-brand p-0 disabled order-1" href="#"> <a class="navbar-brand p-0 disabled order-1" href="#">
<img src="img/template/logo.svg" width="180" alt="Logo" /> <img src="img/template/logo.svg" width="180" alt="Logo" />
</a> </a>
<div id="titleSco" class="flex-grow-1 title_head_sco text-center text-white fw-bold fs-5 order-3 order-md-2"></div> <div
id="titleSco"
class="flex-grow-1 title_head_sco text-center text-white fw-bold fs-5 order-3 order-md-2"
></div>
<div class="d-flex align-items-center text-white order-2 order-md-3 ms-auto"> <div class="d-flex align-items-center text-white order-2 order-md-3 ms-auto">
<!-- <button class="btn-glossary controls-btn me-2" id="btn-glossary" aria-label="Glossary"> <!-- <button class="btn-glossary controls-btn me-2" id="btn-glossary" aria-label="Glossary">
<i class="fa-regular fa-book-section fa-xl"></i> <i class="fa-regular fa-book-section fa-xl"></i>
@@ -39,7 +42,17 @@
<div class="position-relative"> <div class="position-relative">
<svg viewBox="0 0 100 100" class="w-100 h-100"> <svg viewBox="0 0 100 100" class="w-100 h-100">
<circle cx="50" cy="50" r="45" stroke="#f7f7f7" stroke-width="10" fill="none" /> <circle cx="50" cy="50" r="45" stroke="#f7f7f7" stroke-width="10" fill="none" />
<circle id="coursenav-progress-circle" cx="50" cy="50" r="45" stroke="#009ace" stroke-width="10" fill="none" stroke-dasharray="283" stroke-dashoffset="283" /> <circle
id="coursenav-progress-circle"
cx="50"
cy="50"
r="45"
stroke="#009ace"
stroke-width="10"
fill="none"
stroke-dasharray="283"
stroke-dashoffset="283"
/>
</svg> </svg>
<i id="coursenav-audio-icon" class="fa-duotone fa-solid fa-volume"></i> <i id="coursenav-audio-icon" class="fa-duotone fa-solid fa-volume"></i>
</div> </div>
@@ -62,10 +75,20 @@
</header> </header>
<!-- OFFCANVAS DESDE DERECHA --> <!-- OFFCANVAS DESDE DERECHA -->
<div class="offcanvas offcanvas-end bg-secondary text-white" tabindex="-1" id="coursenav-offcanvas" aria-labelledby="coursenav-offcanvas-label"> <div
class="offcanvas offcanvas-end bg-secondary text-white"
tabindex="-1"
id="coursenav-offcanvas"
aria-labelledby="coursenav-offcanvas-label"
>
<div class="offcanvas-header"> <div class="offcanvas-header">
<h5 id="coursenav-offcanvas-label" class="offcanvas-title">Índice</h5> <h5 id="coursenav-offcanvas-label" class="offcanvas-title">Índice</h5>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button> <button
type="button"
class="btn-close text-reset"
data-bs-dismiss="offcanvas"
aria-label="Close"
></button>
</div> </div>
<div class="offcanvas-body d-flex flex-column p-0"> <div class="offcanvas-body d-flex flex-column p-0">
<!-- Menú principal --> <!-- Menú principal -->
@@ -96,18 +119,33 @@
<main id="coursenav-main-content"></main> <main id="coursenav-main-content"></main>
<!-- FOOTER --> <!-- FOOTER -->
<footer class="mt-auto py-1 d-flex flex-wrap justify-content-center align-items-center gap-2 gap-md-3 px-2 px-md-4" style="background-color: rgba(24, 53, 104, .7);"> <footer
class="mt-auto py-1 d-flex flex-wrap justify-content-center align-items-center gap-2 gap-md-3 px-2 px-md-4"
style="background-color: rgba(24, 53, 104, 0.7)"
>
<div class="aviso-privacidad flex-fill flex-md-none order-2 order-md-1"> <div class="aviso-privacidad flex-fill flex-md-none order-2 order-md-1">
<p class="mb-0 small text-white text-center text-md-start">Uso exclusivo de capacitación interna, prohibida su reproducción y/o distribución</p> <p class="mb-0 small text-white text-center text-md-start">
Uso exclusivo de capacitación interna, prohibida su reproducción y/o distribución
</p>
</div> </div>
<div class="d-flex justify-content-center align-items-center gap-3 position-relative ms-md-auto flex-fill flex-md-none order-1 order-md-2"> <div
<button id="coursenav-prev-btn" class="coursenav-btn-navigation bg-orange-1 text-white" data-bs-toggle="tooltip" class="d-flex justify-content-center align-items-center gap-3 position-relative ms-md-auto flex-fill flex-md-none order-1 order-md-2"
title="Anterior"> >
<button
id="coursenav-prev-btn"
class="coursenav-btn-navigation bg-orange-1 text-white"
data-bs-toggle="tooltip"
title="Anterior"
>
<i class="fa-solid fa-arrow-down fa-rotate-90"></i> <i class="fa-solid fa-arrow-down fa-rotate-90"></i>
</button> </button>
<div id="pagination" class="paginacion_sco fw-bold"></div> <div id="pagination" class="paginacion_sco fw-bold"></div>
<button id="coursenav-next-btn" class="coursenav-btn-navigation bg-secondary text-white" data-bs-toggle="tooltip" <button
title="Siguiente"> id="coursenav-next-btn"
class="coursenav-btn-navigation bg-secondary text-white"
data-bs-toggle="tooltip"
title="Siguiente"
>
<i class="fa-solid fa-arrow-down fa-rotate-270"></i> <i class="fa-solid fa-arrow-down fa-rotate-270"></i>
</button> </button>
</div> </div>
@@ -121,12 +159,26 @@
</div> </div>
<!-- Offcanvas: inicialmente vacío --> <!-- Offcanvas: inicialmente vacío -->
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasGlossary" aria-labelledby="offcanvasGlossaryLabel"> <div
class="offcanvas offcanvas-end"
tabindex="-1"
id="offcanvasGlossary"
aria-labelledby="offcanvasGlossaryLabel"
>
<div class="offcanvas-header"> <div class="offcanvas-header">
<h1 class="offcanvas-title text-danger text-center amor fw-bold" id="offcanvasGlossaryLabel" style="width: 90%;"> <h1
class="offcanvas-title text-danger text-center amor fw-bold"
id="offcanvasGlossaryLabel"
style="width: 90%"
>
OGestan<sup>®</sup> Plus OGestan<sup>®</sup> Plus
</h1> </h1>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Cerrar"></button> <button
type="button"
class="btn-close text-reset"
data-bs-dismiss="offcanvas"
aria-label="Cerrar"
></button>
</div> </div>
<div class="offcanvas-body overflow-auto"> <div class="offcanvas-body overflow-auto">
<!-- Aquí irá el contenido de manual_pld_ft.html --> <!-- Aquí irá el contenido de manual_pld_ft.html -->
Binary file not shown.
Binary file not shown.
+23
View File
@@ -0,0 +1,23 @@
Copyright <yyyy, yyyy> The Open Group
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
from The Open Group.
+10
View File
@@ -0,0 +1,10 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"liveServer.settings.port": 5501
}
}
+109
View File
@@ -0,0 +1,109 @@
<?xml version="1.0"?>
<!-- filename=adlcp_rootv1p2.xsd -->
<!-- Conforms to w3c http://www.w3.org/TR/xmlschema-1/ 2000-10-24-->
<xsd:schema xmlns="http://www.adlnet.org/xsd/adlcp_rootv1p2"
targetNamespace="http://www.adlnet.org/xsd/adlcp_rootv1p2"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:imscp="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified"
version="ADL Version 1.2">
<xsd:import namespace="http://www.imsproject.org/xsd/imscp_rootv1p1p2" schemaLocation="imscp_rootv1p1p2.xsd"/>
<xsd:element name="location" type="locationType"/>
<xsd:element name="prerequisites" type="prerequisitesType"/>
<xsd:element name="maxtimeallowed" type="maxtimeallowedType"/>
<xsd:element name="timelimitaction" type="timelimitactionType"/>
<xsd:element name="datafromlms" type="datafromlmsType"/>
<xsd:element name="masteryscore" type="masteryscoreType"/>
<xsd:element name="schema" type="newSchemaType"/>
<xsd:simpleType name="newSchemaType">
<xsd:restriction base="imscp:schemaType">
<xsd:enumeration value="ADL SCORM"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="schemaversion" type="newSchemaversionType"/>
<xsd:simpleType name="newSchemaversionType">
<xsd:restriction base="imscp:schemaversionType">
<xsd:enumeration value="1.2"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:attribute name="scormtype">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="asset"/>
<xsd:enumeration value="sco"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:simpleType name="locationType">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="2000"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="prerequisitesType">
<xsd:simpleContent>
<xsd:extension base="prerequisiteStringType">
<xsd:attributeGroup ref="attr.prerequisitetype"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:attributeGroup name="attr.prerequisitetype">
<xsd:attribute name="type" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="aicc_script"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
<xsd:simpleType name="maxtimeallowedType">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="13"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="timelimitactionType">
<xsd:restriction base="stringType">
<xsd:enumeration value="exit,no message"/>
<xsd:enumeration value="exit,message"/>
<xsd:enumeration value="continue,no message"/>
<xsd:enumeration value="continue,message"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="datafromlmsType">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="255"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="masteryscoreType">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="200"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="stringType">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="prerequisiteStringType">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="200"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+153
View File
@@ -0,0 +1,153 @@
//
// Base styles
//
.accordion {
// scss-docs-start accordion-css-vars
--#{$prefix}accordion-color: #{$accordion-color};
--#{$prefix}accordion-bg: #{$accordion-bg};
--#{$prefix}accordion-transition: #{$accordion-transition};
--#{$prefix}accordion-border-color: #{$accordion-border-color};
--#{$prefix}accordion-border-width: #{$accordion-border-width};
--#{$prefix}accordion-border-radius: #{$accordion-border-radius};
--#{$prefix}accordion-inner-border-radius: #{$accordion-inner-border-radius};
--#{$prefix}accordion-btn-padding-x: #{$accordion-button-padding-x};
--#{$prefix}accordion-btn-padding-y: #{$accordion-button-padding-y};
--#{$prefix}accordion-btn-color: #{$accordion-button-color};
--#{$prefix}accordion-btn-bg: #{$accordion-button-bg};
--#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon)};
--#{$prefix}accordion-btn-icon-width: #{$accordion-icon-width};
--#{$prefix}accordion-btn-icon-transform: #{$accordion-icon-transform};
--#{$prefix}accordion-btn-icon-transition: #{$accordion-icon-transition};
--#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon)};
--#{$prefix}accordion-btn-focus-box-shadow: #{$accordion-button-focus-box-shadow};
--#{$prefix}accordion-body-padding-x: #{$accordion-body-padding-x};
--#{$prefix}accordion-body-padding-y: #{$accordion-body-padding-y};
--#{$prefix}accordion-active-color: #{$accordion-button-active-color};
--#{$prefix}accordion-active-bg: #{$accordion-button-active-bg};
// scss-docs-end accordion-css-vars
}
.accordion-button {
position: relative;
display: flex;
align-items: center;
width: 100%;
padding: var(--#{$prefix}accordion-btn-padding-y) var(--#{$prefix}accordion-btn-padding-x);
@include font-size($font-size-base);
color: var(--#{$prefix}accordion-btn-color);
text-align: left; // Reset button style
background-color: var(--#{$prefix}accordion-btn-bg);
border: 0;
@include border-radius(0);
overflow-anchor: none;
@include transition(var(--#{$prefix}accordion-transition));
&:not(.collapsed) {
color: var(--#{$prefix}accordion-active-color);
background-color: var(--#{$prefix}accordion-active-bg);
box-shadow: inset 0 calc(-1 * var(--#{$prefix}accordion-border-width)) 0 var(--#{$prefix}accordion-border-color); // stylelint-disable-line function-disallowed-list
&::after {
background-image: var(--#{$prefix}accordion-btn-active-icon);
transform: var(--#{$prefix}accordion-btn-icon-transform);
}
}
// Accordion icon
&::after {
flex-shrink: 0;
width: var(--#{$prefix}accordion-btn-icon-width);
height: var(--#{$prefix}accordion-btn-icon-width);
margin-left: auto;
content: "";
background-image: var(--#{$prefix}accordion-btn-icon);
background-repeat: no-repeat;
background-size: var(--#{$prefix}accordion-btn-icon-width);
@include transition(var(--#{$prefix}accordion-btn-icon-transition));
}
&:hover {
z-index: 2;
}
&:focus {
z-index: 3;
outline: 0;
box-shadow: var(--#{$prefix}accordion-btn-focus-box-shadow);
}
}
.accordion-header {
margin-bottom: 0;
}
.accordion-item {
color: var(--#{$prefix}accordion-color);
background-color: var(--#{$prefix}accordion-bg);
border: var(--#{$prefix}accordion-border-width) solid var(--#{$prefix}accordion-border-color);
&:first-of-type {
@include border-top-radius(var(--#{$prefix}accordion-border-radius));
> .accordion-header .accordion-button {
@include border-top-radius(var(--#{$prefix}accordion-inner-border-radius));
}
}
&:not(:first-of-type) {
border-top: 0;
}
// Only set a border-radius on the last item if the accordion is collapsed
&:last-of-type {
@include border-bottom-radius(var(--#{$prefix}accordion-border-radius));
> .accordion-header .accordion-button {
&.collapsed {
@include border-bottom-radius(var(--#{$prefix}accordion-inner-border-radius));
}
}
> .accordion-collapse {
@include border-bottom-radius(var(--#{$prefix}accordion-border-radius));
}
}
}
.accordion-body {
padding: var(--#{$prefix}accordion-body-padding-y) var(--#{$prefix}accordion-body-padding-x);
}
// Flush accordion items
//
// Remove borders and border-radius to keep accordion items edge-to-edge.
.accordion-flush {
> .accordion-item {
border-right: 0;
border-left: 0;
@include border-radius(0);
&:first-child { border-top: 0; }
&:last-child { border-bottom: 0; }
// stylelint-disable selector-max-class
> .accordion-collapse,
> .accordion-header .accordion-button,
> .accordion-header .accordion-button.collapsed {
@include border-radius(0);
}
// stylelint-enable selector-max-class
}
}
@if $enable-dark-mode {
@include color-mode(dark) {
.accordion-button::after {
--#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon-dark)};
--#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon-dark)};
}
}
}
+68
View File
@@ -0,0 +1,68 @@
//
// Base styles
//
.alert {
// scss-docs-start alert-css-vars
--#{$prefix}alert-bg: transparent;
--#{$prefix}alert-padding-x: #{$alert-padding-x};
--#{$prefix}alert-padding-y: #{$alert-padding-y};
--#{$prefix}alert-margin-bottom: #{$alert-margin-bottom};
--#{$prefix}alert-color: inherit;
--#{$prefix}alert-border-color: transparent;
--#{$prefix}alert-border: #{$alert-border-width} solid var(--#{$prefix}alert-border-color);
--#{$prefix}alert-border-radius: #{$alert-border-radius};
--#{$prefix}alert-link-color: inherit;
// scss-docs-end alert-css-vars
position: relative;
padding: var(--#{$prefix}alert-padding-y) var(--#{$prefix}alert-padding-x);
margin-bottom: var(--#{$prefix}alert-margin-bottom);
color: var(--#{$prefix}alert-color);
background-color: var(--#{$prefix}alert-bg);
border: var(--#{$prefix}alert-border);
@include border-radius(var(--#{$prefix}alert-border-radius));
}
// Headings for larger alerts
.alert-heading {
// Specified to prevent conflicts of changing $headings-color
color: inherit;
}
// Provide class for links that match alerts
.alert-link {
font-weight: $alert-link-font-weight;
color: var(--#{$prefix}alert-link-color);
}
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
.alert-dismissible {
padding-right: $alert-dismissible-padding-r;
// Adjust close link position
.btn-close {
position: absolute;
top: 0;
right: 0;
z-index: $stretched-link-z-index + 1;
padding: $alert-padding-y * 1.25 $alert-padding-x;
}
}
// scss-docs-start alert-modifiers
// Generate contextual modifier classes for colorizing the alert
@each $state in map-keys($theme-colors) {
.alert-#{$state} {
--#{$prefix}alert-color: var(--#{$prefix}#{$state}-text-emphasis);
--#{$prefix}alert-bg: var(--#{$prefix}#{$state}-bg-subtle);
--#{$prefix}alert-border-color: var(--#{$prefix}#{$state}-border-subtle);
--#{$prefix}alert-link-color: var(--#{$prefix}#{$state}-text-emphasis);
}
}
// scss-docs-end alert-modifiers
+38
View File
@@ -0,0 +1,38 @@
// Base class
//
// Requires one of the contextual, color modifier classes for `color` and
// `background-color`.
.badge {
// scss-docs-start badge-css-vars
--#{$prefix}badge-padding-x: #{$badge-padding-x};
--#{$prefix}badge-padding-y: #{$badge-padding-y};
@include rfs($badge-font-size, --#{$prefix}badge-font-size);
--#{$prefix}badge-font-weight: #{$badge-font-weight};
--#{$prefix}badge-color: #{$badge-color};
--#{$prefix}badge-border-radius: #{$badge-border-radius};
// scss-docs-end badge-css-vars
display: inline-block;
padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x);
@include font-size(var(--#{$prefix}badge-font-size));
font-weight: var(--#{$prefix}badge-font-weight);
line-height: 1;
color: var(--#{$prefix}badge-color);
text-align: center;
white-space: nowrap;
vertical-align: baseline;
@include border-radius(var(--#{$prefix}badge-border-radius));
@include gradient-bg();
// Empty badges collapse automatically
&:empty {
display: none;
}
}
// Quick fix for badges in buttons
.btn .badge {
position: relative;
top: -1px;
}
+40
View File
@@ -0,0 +1,40 @@
.breadcrumb {
// scss-docs-start breadcrumb-css-vars
--#{$prefix}breadcrumb-padding-x: #{$breadcrumb-padding-x};
--#{$prefix}breadcrumb-padding-y: #{$breadcrumb-padding-y};
--#{$prefix}breadcrumb-margin-bottom: #{$breadcrumb-margin-bottom};
@include rfs($breadcrumb-font-size, --#{$prefix}breadcrumb-font-size);
--#{$prefix}breadcrumb-bg: #{$breadcrumb-bg};
--#{$prefix}breadcrumb-border-radius: #{$breadcrumb-border-radius};
--#{$prefix}breadcrumb-divider-color: #{$breadcrumb-divider-color};
--#{$prefix}breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x};
--#{$prefix}breadcrumb-item-active-color: #{$breadcrumb-active-color};
// scss-docs-end breadcrumb-css-vars
display: flex;
flex-wrap: wrap;
padding: var(--#{$prefix}breadcrumb-padding-y) var(--#{$prefix}breadcrumb-padding-x);
margin-bottom: var(--#{$prefix}breadcrumb-margin-bottom);
@include font-size(var(--#{$prefix}breadcrumb-font-size));
list-style: none;
background-color: var(--#{$prefix}breadcrumb-bg);
@include border-radius(var(--#{$prefix}breadcrumb-border-radius));
}
.breadcrumb-item {
// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item {
padding-left: var(--#{$prefix}breadcrumb-item-padding-x);
&::before {
float: left; // Suppress inline spacings and underlining of the separator
padding-right: var(--#{$prefix}breadcrumb-item-padding-x);
color: var(--#{$prefix}breadcrumb-divider-color);
content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)) #{"/* rtl:"} var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped)) #{"*/"};
}
}
&.active {
color: var(--#{$prefix}breadcrumb-item-active-color);
}
}
+147
View File
@@ -0,0 +1,147 @@
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-flex;
vertical-align: middle; // match .btn alignment given font-size hack above
> .btn {
position: relative;
flex: 1 1 auto;
}
// Bring the hover, focused, and "active" buttons to the front to overlay
// the borders properly
> .btn-check:checked + .btn,
> .btn-check:focus + .btn,
> .btn:hover,
> .btn:focus,
> .btn:active,
> .btn.active {
z-index: 1;
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.input-group {
width: auto;
}
}
.btn-group {
@include border-radius($btn-border-radius);
// Prevent double borders when buttons are next to each other
> :not(.btn-check:first-child) + .btn,
> .btn-group:not(:first-child) {
margin-left: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn.dropdown-toggle-split:first-child,
> .btn-group:not(:last-child) > .btn {
@include border-end-radius(0);
}
// The left radius should be 0 if the button is:
// - the "third or more" child
// - the second child and the previous element isn't `.btn-check` (making it the first child visually)
// - part of a btn-group which isn't the first child
> .btn:nth-child(n + 3),
> :not(.btn-check) + .btn,
> .btn-group:not(:first-child) > .btn {
@include border-start-radius(0);
}
}
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-sm > .btn { @extend .btn-sm; }
.btn-group-lg > .btn { @extend .btn-lg; }
//
// Split button dropdowns
//
.dropdown-toggle-split {
padding-right: $btn-padding-x * .75;
padding-left: $btn-padding-x * .75;
&::after,
.dropup &::after,
.dropend &::after {
margin-left: 0;
}
.dropstart &::before {
margin-right: 0;
}
}
.btn-sm + .dropdown-toggle-split {
padding-right: $btn-padding-x-sm * .75;
padding-left: $btn-padding-x-sm * .75;
}
.btn-lg + .dropdown-toggle-split {
padding-right: $btn-padding-x-lg * .75;
padding-left: $btn-padding-x-lg * .75;
}
// The clickable button for toggling the menu
// Set the same inset shadow as the :active state
.btn-group.show .dropdown-toggle {
@include box-shadow($btn-active-box-shadow);
// Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link {
@include box-shadow(none);
}
}
//
// Vertical button groups
//
.btn-group-vertical {
flex-direction: column;
align-items: flex-start;
justify-content: center;
> .btn,
> .btn-group {
width: 100%;
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) {
margin-top: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn {
@include border-bottom-radius(0);
}
// The top radius should be 0 if the button is:
// - the "third or more" child
// - the second child and the previous element isn't `.btn-check` (making it the first child visually)
// - part of a btn-group which isn't the first child
> .btn:nth-child(n + 3),
> :not(.btn-check) + .btn,
> .btn-group:not(:first-child) > .btn {
@include border-top-radius(0);
}
}
+216
View File
@@ -0,0 +1,216 @@
//
// Base styles
//
.btn {
// scss-docs-start btn-css-vars
--#{$prefix}btn-padding-x: #{$btn-padding-x};
--#{$prefix}btn-padding-y: #{$btn-padding-y};
--#{$prefix}btn-font-family: #{$btn-font-family};
@include rfs($btn-font-size, --#{$prefix}btn-font-size);
--#{$prefix}btn-font-weight: #{$btn-font-weight};
--#{$prefix}btn-line-height: #{$btn-line-height};
--#{$prefix}btn-color: #{$btn-color};
--#{$prefix}btn-bg: transparent;
--#{$prefix}btn-border-width: #{$btn-border-width};
--#{$prefix}btn-border-color: transparent;
--#{$prefix}btn-border-radius: #{$btn-border-radius};
--#{$prefix}btn-hover-border-color: transparent;
--#{$prefix}btn-box-shadow: #{$btn-box-shadow};
--#{$prefix}btn-disabled-opacity: #{$btn-disabled-opacity};
--#{$prefix}btn-focus-box-shadow: 0 0 0 #{$btn-focus-width} rgba(var(--#{$prefix}btn-focus-shadow-rgb), .5);
// scss-docs-end btn-css-vars
display: inline-block;
padding: var(--#{$prefix}btn-padding-y) var(--#{$prefix}btn-padding-x);
font-family: var(--#{$prefix}btn-font-family);
@include font-size(var(--#{$prefix}btn-font-size));
font-weight: var(--#{$prefix}btn-font-weight);
line-height: var(--#{$prefix}btn-line-height);
color: var(--#{$prefix}btn-color);
text-align: center;
text-decoration: if($link-decoration == none, null, none);
white-space: $btn-white-space;
vertical-align: middle;
cursor: if($enable-button-pointers, pointer, null);
user-select: none;
border: var(--#{$prefix}btn-border-width) solid var(--#{$prefix}btn-border-color);
@include border-radius(var(--#{$prefix}btn-border-radius));
@include gradient-bg(var(--#{$prefix}btn-bg));
@include box-shadow(var(--#{$prefix}btn-box-shadow));
@include transition($btn-transition);
&:hover {
color: var(--#{$prefix}btn-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
background-color: var(--#{$prefix}btn-hover-bg);
border-color: var(--#{$prefix}btn-hover-border-color);
}
.btn-check + &:hover {
// override for the checkbox/radio buttons
color: var(--#{$prefix}btn-color);
background-color: var(--#{$prefix}btn-bg);
border-color: var(--#{$prefix}btn-border-color);
}
&:focus-visible {
color: var(--#{$prefix}btn-hover-color);
@include gradient-bg(var(--#{$prefix}btn-hover-bg));
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
.btn-check:focus-visible + & {
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
.btn-check:checked + &,
:not(.btn-check) + &:active,
&:first-child:active,
&.active,
&.show {
color: var(--#{$prefix}btn-active-color);
background-color: var(--#{$prefix}btn-active-bg);
// Remove CSS gradients if they're enabled
background-image: if($enable-gradients, none, null);
border-color: var(--#{$prefix}btn-active-border-color);
@include box-shadow(var(--#{$prefix}btn-active-shadow));
&:focus-visible {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
}
.btn-check:checked:focus-visible + & {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
&:disabled,
&.disabled,
fieldset:disabled & {
color: var(--#{$prefix}btn-disabled-color);
pointer-events: none;
background-color: var(--#{$prefix}btn-disabled-bg);
background-image: if($enable-gradients, none, null);
border-color: var(--#{$prefix}btn-disabled-border-color);
opacity: var(--#{$prefix}btn-disabled-opacity);
@include box-shadow(none);
}
}
//
// Alternate buttons
//
// scss-docs-start btn-variant-loops
@each $color, $value in $theme-colors {
.btn-#{$color} {
@if $color == "light" {
@include button-variant(
$value,
$value,
$hover-background: shade-color($value, $btn-hover-bg-shade-amount),
$hover-border: shade-color($value, $btn-hover-border-shade-amount),
$active-background: shade-color($value, $btn-active-bg-shade-amount),
$active-border: shade-color($value, $btn-active-border-shade-amount)
);
} @else if $color == "dark" {
@include button-variant(
$value,
$value,
$hover-background: tint-color($value, $btn-hover-bg-tint-amount),
$hover-border: tint-color($value, $btn-hover-border-tint-amount),
$active-background: tint-color($value, $btn-active-bg-tint-amount),
$active-border: tint-color($value, $btn-active-border-tint-amount)
);
} @else {
@include button-variant($value, $value);
}
}
}
@each $color, $value in $theme-colors {
.btn-outline-#{$color} {
@include button-outline-variant($value);
}
}
// scss-docs-end btn-variant-loops
//
// Link buttons
//
// Make a button look and behave like a link
.btn-link {
--#{$prefix}btn-font-weight: #{$font-weight-normal};
--#{$prefix}btn-color: #{$btn-link-color};
--#{$prefix}btn-bg: transparent;
--#{$prefix}btn-border-color: transparent;
--#{$prefix}btn-hover-color: #{$btn-link-hover-color};
--#{$prefix}btn-hover-border-color: transparent;
--#{$prefix}btn-active-color: #{$btn-link-hover-color};
--#{$prefix}btn-active-border-color: transparent;
--#{$prefix}btn-disabled-color: #{$btn-link-disabled-color};
--#{$prefix}btn-disabled-border-color: transparent;
--#{$prefix}btn-box-shadow: 0 0 0 #000; // Can't use `none` as keyword negates all values when used with multiple shadows
--#{$prefix}btn-focus-shadow-rgb: #{$btn-link-focus-shadow-rgb};
text-decoration: $link-decoration;
@if $enable-gradients {
background-image: none;
}
&:hover,
&:focus-visible {
text-decoration: $link-hover-decoration;
}
&:focus-visible {
color: var(--#{$prefix}btn-color);
}
&:hover {
color: var(--#{$prefix}btn-hover-color);
}
// No need for an active state here
}
//
// Button Sizes
//
.btn-lg {
@include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-border-radius-lg);
}
.btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm);
}
+238
View File
@@ -0,0 +1,238 @@
//
// Base styles
//
.card {
// scss-docs-start card-css-vars
--#{$prefix}card-spacer-y: #{$card-spacer-y};
--#{$prefix}card-spacer-x: #{$card-spacer-x};
--#{$prefix}card-title-spacer-y: #{$card-title-spacer-y};
--#{$prefix}card-title-color: #{$card-title-color};
--#{$prefix}card-subtitle-color: #{$card-subtitle-color};
--#{$prefix}card-border-width: #{$card-border-width};
--#{$prefix}card-border-color: #{$card-border-color};
--#{$prefix}card-border-radius: #{$card-border-radius};
--#{$prefix}card-box-shadow: #{$card-box-shadow};
--#{$prefix}card-inner-border-radius: #{$card-inner-border-radius};
--#{$prefix}card-cap-padding-y: #{$card-cap-padding-y};
--#{$prefix}card-cap-padding-x: #{$card-cap-padding-x};
--#{$prefix}card-cap-bg: #{$card-cap-bg};
--#{$prefix}card-cap-color: #{$card-cap-color};
--#{$prefix}card-height: #{$card-height};
--#{$prefix}card-color: #{$card-color};
--#{$prefix}card-bg: #{$card-bg};
--#{$prefix}card-img-overlay-padding: #{$card-img-overlay-padding};
--#{$prefix}card-group-margin: #{$card-group-margin};
// scss-docs-end card-css-vars
position: relative;
display: flex;
flex-direction: column;
min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106
height: var(--#{$prefix}card-height);
color: var(--#{$prefix}body-color);
word-wrap: break-word;
background-color: var(--#{$prefix}card-bg);
background-clip: border-box;
border: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
@include border-radius(var(--#{$prefix}card-border-radius));
@include box-shadow(var(--#{$prefix}card-box-shadow));
> hr {
margin-right: 0;
margin-left: 0;
}
> .list-group {
border-top: inherit;
border-bottom: inherit;
&:first-child {
border-top-width: 0;
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
&:last-child {
border-bottom-width: 0;
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
}
}
// Due to specificity of the above selector (`.card > .list-group`), we must
// use a child selector here to prevent double borders.
> .card-header + .list-group,
> .list-group + .card-footer {
border-top: 0;
}
}
.card-body {
// Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto;
padding: var(--#{$prefix}card-spacer-y) var(--#{$prefix}card-spacer-x);
color: var(--#{$prefix}card-color);
}
.card-title {
margin-bottom: var(--#{$prefix}card-title-spacer-y);
color: var(--#{$prefix}card-title-color);
}
.card-subtitle {
margin-top: calc(-.5 * var(--#{$prefix}card-title-spacer-y)); // stylelint-disable-line function-disallowed-list
margin-bottom: 0;
color: var(--#{$prefix}card-subtitle-color);
}
.card-text:last-child {
margin-bottom: 0;
}
.card-link {
&:hover {
text-decoration: if($link-hover-decoration == underline, none, null);
}
+ .card-link {
margin-left: var(--#{$prefix}card-spacer-x);
}
}
//
// Optional textual caps
//
.card-header {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
margin-bottom: 0; // Removes the default margin-bottom of <hN>
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-bottom: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
&:first-child {
@include border-radius(var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius) 0 0);
}
}
.card-footer {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-top: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
&:last-child {
@include border-radius(0 0 var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius));
}
}
//
// Header navs
//
.card-header-tabs {
margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
margin-bottom: calc(-1 * var(--#{$prefix}card-cap-padding-y)); // stylelint-disable-line function-disallowed-list
margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
border-bottom: 0;
.nav-link.active {
background-color: var(--#{$prefix}card-bg);
border-bottom-color: var(--#{$prefix}card-bg);
}
}
.card-header-pills {
margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
}
// Card image
.card-img-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: var(--#{$prefix}card-img-overlay-padding);
@include border-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-top,
.card-img-bottom {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
}
.card-img,
.card-img-top {
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-bottom {
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
}
//
// Card groups
//
.card-group {
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
margin-bottom: var(--#{$prefix}card-group-margin);
}
@include media-breakpoint-up(sm) {
display: flex;
flex-flow: row wrap;
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
flex: 1 0 0;
margin-bottom: 0;
+ .card {
margin-left: 0;
border-left: 0;
}
// Handle rounded corners
@if $enable-rounded {
&:not(:last-child) {
@include border-end-radius(0);
> .card-img-top,
> .card-header {
// stylelint-disable-next-line property-disallowed-list
border-top-right-radius: 0;
}
> .card-img-bottom,
> .card-footer {
// stylelint-disable-next-line property-disallowed-list
border-bottom-right-radius: 0;
}
}
&:not(:first-child) {
@include border-start-radius(0);
> .card-img-top,
> .card-header {
// stylelint-disable-next-line property-disallowed-list
border-top-left-radius: 0;
}
> .card-img-bottom,
> .card-footer {
// stylelint-disable-next-line property-disallowed-list
border-bottom-left-radius: 0;
}
}
}
}
}
}
+226
View File
@@ -0,0 +1,226 @@
// Notes on the classes:
//
// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically)
// even when their scroll action started on a carousel, but for compatibility (with Firefox)
// we're preventing all actions instead
// 2. The .carousel-item-start and .carousel-item-end is used to indicate where
// the active slide is heading.
// 3. .active.carousel-item is the current slide.
// 4. .active.carousel-item-start and .active.carousel-item-end is the current
// slide in its in-transition state. Only one of these occurs at a time.
// 5. .carousel-item-next.carousel-item-start and .carousel-item-prev.carousel-item-end
// is the upcoming slide in transition.
.carousel {
position: relative;
}
.carousel.pointer-event {
touch-action: pan-y;
}
.carousel-inner {
position: relative;
width: 100%;
overflow: hidden;
@include clearfix();
}
.carousel-item {
position: relative;
display: none;
float: left;
width: 100%;
margin-right: -100%;
backface-visibility: hidden;
@include transition($carousel-transition);
}
.carousel-item.active,
.carousel-item-next,
.carousel-item-prev {
display: block;
}
.carousel-item-next:not(.carousel-item-start),
.active.carousel-item-end {
transform: translateX(100%);
}
.carousel-item-prev:not(.carousel-item-end),
.active.carousel-item-start {
transform: translateX(-100%);
}
//
// Alternate transitions
//
.carousel-fade {
.carousel-item {
opacity: 0;
transition-property: opacity;
transform: none;
}
.carousel-item.active,
.carousel-item-next.carousel-item-start,
.carousel-item-prev.carousel-item-end {
z-index: 1;
opacity: 1;
}
.active.carousel-item-start,
.active.carousel-item-end {
z-index: 0;
opacity: 0;
@include transition(opacity 0s $carousel-transition-duration);
}
}
//
// Left/right controls for nav
//
.carousel-control-prev,
.carousel-control-next {
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
// Use flex for alignment (1-3)
display: flex; // 1. allow flex styles
align-items: center; // 2. vertically center contents
justify-content: center; // 3. horizontally center contents
width: $carousel-control-width;
padding: 0;
color: $carousel-control-color;
text-align: center;
background: none;
filter: var(--#{$prefix}carousel-control-icon-filter);
border: 0;
opacity: $carousel-control-opacity;
@include transition($carousel-control-transition);
// Hover/focus state
&:hover,
&:focus {
color: $carousel-control-color;
text-decoration: none;
outline: 0;
opacity: $carousel-control-hover-opacity;
}
}
.carousel-control-prev {
left: 0;
background-image: if($enable-gradients, linear-gradient(90deg, rgba($black, .25), rgba($black, .001)), null);
}
.carousel-control-next {
right: 0;
background-image: if($enable-gradients, linear-gradient(270deg, rgba($black, .25), rgba($black, .001)), null);
}
// Icons for within
.carousel-control-prev-icon,
.carousel-control-next-icon {
display: inline-block;
width: $carousel-control-icon-width;
height: $carousel-control-icon-width;
background-repeat: no-repeat;
background-position: 50%;
background-size: 100% 100%;
}
.carousel-control-prev-icon {
background-image: escape-svg($carousel-control-prev-icon-bg) #{"/*rtl:" + escape-svg($carousel-control-next-icon-bg) + "*/"};
}
.carousel-control-next-icon {
background-image: escape-svg($carousel-control-next-icon-bg) #{"/*rtl:" + escape-svg($carousel-control-prev-icon-bg) + "*/"};
}
// Optional indicator pips/controls
//
// Add a container (such as a list) with the following class and add an item (ideally a focusable control,
// like a button) with data-bs-target for each slide your carousel holds.
.carousel-indicators {
position: absolute;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
display: flex;
justify-content: center;
padding: 0;
// Use the .carousel-control's width as margin so we don't overlay those
margin-right: $carousel-control-width;
margin-bottom: 1rem;
margin-left: $carousel-control-width;
[data-bs-target] {
box-sizing: content-box;
flex: 0 1 auto;
width: $carousel-indicator-width;
height: $carousel-indicator-height;
padding: 0;
margin-right: $carousel-indicator-spacer;
margin-left: $carousel-indicator-spacer;
text-indent: -999px;
cursor: pointer;
background-color: var(--#{$prefix}carousel-indicator-active-bg);
background-clip: padding-box;
border: 0;
// Use transparent borders to increase the hit area by 10px on top and bottom.
border-top: $carousel-indicator-hit-area-height solid transparent;
border-bottom: $carousel-indicator-hit-area-height solid transparent;
opacity: $carousel-indicator-opacity;
@include transition($carousel-indicator-transition);
}
.active {
opacity: $carousel-indicator-active-opacity;
}
}
// Optional captions
//
//
.carousel-caption {
position: absolute;
right: (100% - $carousel-caption-width) * .5;
bottom: $carousel-caption-spacer;
left: (100% - $carousel-caption-width) * .5;
padding-top: $carousel-caption-padding-y;
padding-bottom: $carousel-caption-padding-y;
color: var(--#{$prefix}carousel-caption-color);
text-align: center;
}
// Dark mode carousel
@mixin carousel-dark() {
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg-dark};
--#{$prefix}carousel-caption-color: #{$carousel-caption-color-dark};
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter-dark};
}
.carousel-dark {
@include carousel-dark();
}
:root,
[data-bs-theme="light"] {
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg};
--#{$prefix}carousel-caption-color: #{$carousel-caption-color};
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter};
}
@if $enable-dark-mode {
@include color-mode(dark, true) {
@include carousel-dark();
}
}
+66
View File
@@ -0,0 +1,66 @@
// Transparent background and border properties included for button version.
// iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`.
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
.btn-close {
// scss-docs-start close-css-vars
--#{$prefix}btn-close-color: #{$btn-close-color};
--#{$prefix}btn-close-bg: #{ escape-svg($btn-close-bg) };
--#{$prefix}btn-close-opacity: #{$btn-close-opacity};
--#{$prefix}btn-close-hover-opacity: #{$btn-close-hover-opacity};
--#{$prefix}btn-close-focus-shadow: #{$btn-close-focus-shadow};
--#{$prefix}btn-close-focus-opacity: #{$btn-close-focus-opacity};
--#{$prefix}btn-close-disabled-opacity: #{$btn-close-disabled-opacity};
// scss-docs-end close-css-vars
box-sizing: content-box;
width: $btn-close-width;
height: $btn-close-height;
padding: $btn-close-padding-y $btn-close-padding-x;
color: var(--#{$prefix}btn-close-color);
background: transparent var(--#{$prefix}btn-close-bg) center / $btn-close-width auto no-repeat; // include transparent for button elements
filter: var(--#{$prefix}btn-close-filter);
border: 0; // for button elements
@include border-radius();
opacity: var(--#{$prefix}btn-close-opacity);
// Override <a>'s hover style
&:hover {
color: var(--#{$prefix}btn-close-color);
text-decoration: none;
opacity: var(--#{$prefix}btn-close-hover-opacity);
}
&:focus {
outline: 0;
box-shadow: var(--#{$prefix}btn-close-focus-shadow);
opacity: var(--#{$prefix}btn-close-focus-opacity);
}
&:disabled,
&.disabled {
pointer-events: none;
user-select: none;
opacity: var(--#{$prefix}btn-close-disabled-opacity);
}
}
@mixin btn-close-white() {
--#{$prefix}btn-close-filter: #{$btn-close-filter-dark};
}
.btn-close-white {
@include btn-close-white();
}
:root,
[data-bs-theme="light"] {
--#{$prefix}btn-close-filter: #{$btn-close-filter};
}
@if $enable-dark-mode {
@include color-mode(dark, true) {
@include btn-close-white();
}
}
+41
View File
@@ -0,0 +1,41 @@
// Container widths
//
// Set the container width, and override it for fixed navbars in media queries.
@if $enable-container-classes {
// Single container class with breakpoint max-widths
.container,
// 100% wide container at all breakpoints
.container-fluid {
@include make-container();
}
// Responsive containers that are 100% wide until a breakpoint
@each $breakpoint, $container-max-width in $container-max-widths {
.container-#{$breakpoint} {
@extend .container-fluid;
}
@include media-breakpoint-up($breakpoint, $grid-breakpoints) {
%responsive-container-#{$breakpoint} {
max-width: $container-max-width;
}
// Extend each breakpoint which is smaller or equal to the current breakpoint
$extend-breakpoint: true;
@each $name, $width in $grid-breakpoints {
@if ($extend-breakpoint) {
.container#{breakpoint-infix($name, $grid-breakpoints)} {
@extend %responsive-container-#{$breakpoint};
}
// Once the current breakpoint is reached, stop extending
@if ($breakpoint == $name) {
$extend-breakpoint: false;
}
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More