:root {
    --color-primary-base: 46 117 163;
    --color-primary-gradient: 36 77 103;
    --color-primary-button-text: 46 117 163;
    --color-primary-button-alternative-text: 255 255 255;

    --color-secondary-base: 243 126 47;
    --color-secondary-gradient: 224 100 16;
    --color-secondary-button-text: 255 255 255;

    --color-tertiary-base: 51 51 51;
    --color-tertiary-gradient: 0 0 0;
    --color-tertiary-button-text: 255 255 255;

    --color-success-base: 119 170 12;
    --color-success-gradient: 83 127 0;
    --color-success-button-text: 255 255 255;

    --color-info-base: 13 123 253;
    --color-info-gradient: 0 84 211;
    --color-info-button-text: 255 255 255;

    --color-warning-base: 245 206 1;
    --color-warning-gradient: 186 152 0;
    --color-warning-button-text: 0 0 0;

    --color-danger-base: 223 59 59;
    --color-danger-gradient: 180 0 21;
    --color-danger-button-text: 255 255 255;

    --color-form-base: 46 117 163;
}

/* ── estudy.local branded override: logged-in area (authenticated SPA) ──
   Global, no body-class scope needed — .app-sidebar only renders at all when
   securityStore.isAuthenticated is true (DashboardLayout.vue's own v-if), so
   this can't leak into the anonymous/public pages. Tone adjusted 2026-07-13
   (María, tested live in DevTools on a secondary monitor): the original
   $ec-negro-matching #0a0a0a read as too dark / low-contrast there — #1e1e1e
   is deliberately a shade lighter than the rest of the dark brand palette,
   scoped only to the sidebar for readability, not meant to match $ec-negro. */
body .app-sidebar {
    background-color: #1e1e1e !important;
}

/* Inactive sidebar item text — bumped to pure white 2026-07-13 (María, same
   secondary-monitor contrast check as the background above); the earlier
   rgb(210,210,210) didn't stand out enough there. */
.app-sidebar {
    color: rgb(255, 255, 255) !important;
}

/* Active/expanded panel header text (core uses --color-primary-base, a blue
   meant for the light background) — our own accent blue instead. Scoped to
   .p-panelmenu-header-active only (not its shared :hover selector in core),
   so hovering an inactive header keeps its own hover color. Value adjusted
   2026-07-13 (María, DevTools) for better contrast against the lighter
   #1e1e1e sidebar background above. */
.app-sidebar .p-panelmenu-header.p-panelmenu-header-active {
    color: rgb(40, 128, 255) !important;
}

/* Sub-items currently active/expanded under an active header. */
.app-sidebar .router-link-exact-active,
.app-sidebar .router-link-url-active {
    color: rgb(148, 181, 225) !important;
}

/* Active sub-item row inside an expanded submenu: left accent border + subtle
   tinted background, so it stands out as a distinct "you are here" row, not
   just differently-colored text. Tested live in DevTools (María, 2026-07-13). */
.app-sidebar .p-panelmenu-submenu .p-menuitem-link.router-link-exact-active,
.app-sidebar .p-panelmenu-submenu .p-menuitem-link.router-link-url-active {
    border-left: 4px solid #98cbff;
    background-color: rgba(74, 144, 217, 0.12);
}

/* Removes core's 1px solid border-bottom on .app-sidebar__bottom (the block
   holding CategoryLinks/PageList/the copyright line above) — read as a boxed-
   in strip against the dark sidebar; drop it entirely. */
.app-sidebar__bottom {
    border-bottom-width: 0 !important;
    border-style: none !important;
}

/* Hides the "Created with Chamilo <year>" line (core, unmodified —
   assets/vue/components/layout/Sidebar.vue:46, `<p v-html="t('Created with
   Chamilo copyright year', ...)" />`, rendered unconditionally, no platform
   setting/v-if controls it). CategoryLinks/PageList (its siblings inside
   .app-sidebar__bottom) don't render a plain <p>, so this only matches this
   one line — cheaper than forking the whole (actively-developed) Sidebar.vue
   component just to drop one line. */
.app-sidebar__bottom > p {
    display: none !important;
}

/* Neutralizes assets/vue/composables/pageBackground.js: on 5 specific
   authenticated pages (My Courses, Social, admin platform/session dashboards,
   Sessions) it sets a decorative repeating background image + 200px of
   bottom padding on .app-main via INLINE style (el.style.paddingBottom =
   "200px", etc.). Our AuthenticatedFooter.vue's negative margin-bottom only
   cancels the normal static ~32px Tailwind padding — on those 5 pages the
   leftover ~168px showed through as a visible gap below the footer. Since
   the decorative image was designed for the original light theme anyway
   (confirmed with María, 2026-07-13, fine to drop it), just override both
   properties back to the normal static value everywhere in the logged-in
   area — safe to apply unscoped, since anonymous pages never match any of
   that composable's page-background keys. */
.app-main {
    background-image: none !important;
    /* Matches core's own pb-4 (mobile) / md:pb-8 (>=768px) Tailwind values —
       same breakpoint AuthenticatedFooter.vue's margin-bottom already targets. */
    padding-bottom: 1rem !important;
}
@media (min-width: 768px) {
    .app-main {
        padding-bottom: 2rem !important;
    }
}

/* ── estudy.local branded override: logged-in area header (TopbarLoggedIn.vue,
   core, unmodified — assets/vue/components/layout/TopbarLoggedIn.vue) ──
   Structure/effect (dark bg + bottom accent stripe + shadow) matches
   eCertificate's private-area navbar (ecertificate.local/web/css/site.css,
   "PRIVATE AREA – VISUAL MODERNIZATION" section, ~line 1711:
   `body.site .navbar { background-color:#1c2333!important; border-bottom:3px
   solid #2563eb; box-shadow:0 2px 12px rgba(0,0,0,.45); }`), read there for
   reference only — not copied verbatim (their accent is blue/gold, ours is
   $ec-acento, #1a6fc4, the SAME accent used for the footer below and already
   used site-wide for buttons/links, chosen deliberately so the header and
   footer accent stripes read as one consistent color, not two similar blues).
   `:not(.app-topbar--custom-template)` scopes this to the AUTHENTICATED
   topbar only — the anonymous one (TopbarNotLoggedIn.vue) already has its own
   dark styling via that modifier class, scoped in its own component file. */
.app-topbar:not(.app-topbar--custom-template) {
    background-color: #0a0a0a !important;
    border-bottom: 3px solid #1a6fc4 !important;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
}

/* Icons (create-course, tour, ticket, inbox) default to a gray meant for the
   light background core normally uses here — swap for white so they're
   visible against the new dark bar. */
.app-topbar:not(.app-topbar--custom-template) .item-button__icon {
    color: #fff !important;
}

/* ── estudy.local branded override: legacy classic-PHP auth pages ──
   These pages (lost-password, standalone /login, etc.) render through
   layout_one_col.html.twig -> base-layout.html.twig, the SAME shared
   layout/head as the Vue SPA, so this global theme file (already loaded on
   every page via theme_asset_link_tag('colors.css') in head.html.twig)
   reaches them too — no core Twig/SCSS edit needed, this file IS the
   designated instance-customization surface (same category as the logo
   images in this same folder). Scoped to body.page-tool-auth (confirmed
   via curl against the real rendered page) so it never touches the Vue
   SPA's own pages (page-home, etc.) or the authenticated dashboard. */
body.page-tool-auth {
    background: #0a0a0a;
    color: rgba(255, 255, 255, 0.85);
}

body.page-tool-auth #sectionMainContent {
    max-width: 460px;
    margin: 80px auto;
    padding: 32px 28px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
}

body.page-tool-auth h1 {
    color: #fff !important;
    font-family: "Roboto Condensed", "Segoe UI", Helvetica, Arial, sans-serif;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    padding-bottom: 12px;
}

body.page-tool-auth h1 hr {
    display: none;
}

body.page-tool-auth label {
    color: rgba(255, 255, 255, 0.85) !important;
}

/* PrimeVue's floating label (public/build/app.css: ".p-floatlabel-on:has(input.p-filled)
   label{ top:0; transform: translateY(-50%); ...}") centers the floated label
   exactly ON .p-floatlabel's own top edge, i.e. half above / half overlapping
   the input's top border — the input has no top clearance for it, so on
   lostPassword.php the label's bottom half visually collides with the input.
   Simplest fix: give the wrapper itself some top padding so the input (a
   normal-flow child) starts lower, leaving room for the label above it
   without touching it — no HTML/JS change needed. */
body.page-tool-auth .p-floatlabel {
    padding-top: 16px;
}

body.page-tool-auth .p-floatlabel label {
    /* Matches #sectionMainContent's own card background above (rgba white
       overlay on the #0a0a0a page bg), not a flat color, so it keeps
       blending in even if the card's tint ever changes. */
    background: rgba(255, 255, 255, 0.04) !important;
    color: rgba(255, 255, 255, 0.85) !important;
}

body.page-tool-auth small {
    color: rgba(255, 255, 255, 0.5) !important;
}

body.page-tool-auth .p-inputtext {
    background: #fff !important;
    color: #0a0a0a !important;
    border: 1px solid rgba(255, 255, 255, 0.16) !important;
}

body.page-tool-auth .btn.btn--success {
    background: #1a6fc4 !important;
    border-color: #1a6fc4 !important;
    color: #fff !important;
}

body.page-tool-auth .btn.btn--success:hover {
    background: #0ea5e9 !important;
    border-color: #0ea5e9 !important;
}

body.page-tool-auth a {
    color: #a78bfa;
}

body.page-tool-auth a:hover {
    color: #fff;
}

/* ── estudy.local branded override: standalone /login (Vue SPA route) ──
   Confirmed via curl: this route's real body class is "page-login" (not
   page-tool-auth — that one's only for the classic PHP auth pages above).
   Login.vue itself is untouched (core component) — only restyling its
   already-known classes (.login-section*, PrimeVue .p-inputtext/.p-button)
   globally, scoped to this page only. */
body.page-login {
    background: #0a0a0a;
}

body.page-login .login-section {
    max-width: 420px;
    margin: 0 auto;
    padding: 40px 28px;
}

body.page-login .login-section__title {
    color: #fff !important;
}

body.page-login .login-section__form label,
body.page-login .login-section__form a:not(.btn) {
    color: rgba(255, 255, 255, 0.7) !important;
}

body.page-login .p-inputtext {
    background: #fff !important;
    color: #0a0a0a !important;
    border: 1px solid rgba(255, 255, 255, 0.16) !important;
}

body.page-login .p-button {
    background: #1a6fc4 !important;
    border-color: #1a6fc4 !important;
    color: #fff !important;
}

body.page-login .p-button:hover {
    background: #0ea5e9 !important;
    border-color: #0ea5e9 !important;
}

body.page-login .btn--primary-outline {
    background: transparent !important;
    border: 1.5px solid rgba(255, 255, 255, 0.4) !important;
    color: #fff !important;
}

body.page-login .btn--primary-outline:hover {
    border-color: #a78bfa !important;
    color: #a78bfa !important;
}

/* ── estudy.local branded override: /catalogue/courses (Vue SPA route) ──
   Confirmed via curl: body class is "page-catalogue" (derivePageTypeClasses()
   in assets/vue/router/index.js maps any /catalogue* path to it). Approved
   scope (2026-07-10): dark background + contained width only — course cards,
   the "Sort by" dropdown and the advanced-search panel already render with
   their own explicit bg-white/text-gray-* Tailwind classes (light "cards"
   floating on the dark page), so they're intentionally left untouched here.
   No core Vue component edited — CatalogueCourses.vue stays core, only its
   already-rendered classes are targeted globally from this instance file. */
body.page-catalogue {
    background: #0a0a0a;
}

/* Scoped to .app-main__content (the flex:1 content wrapper added later for the
   shared footer, var/vue_templates/components/layout/DashboardLayout.vue), NOT
   to .app-main itself. This rule originally targeted .app-main directly — that
   also constrained PublicFooter (added afterwards, a sibling of
   .app-main__content, not a descendant) to the same 1100px box, breaking its
   full-bleed-x edge-to-edge width, since full-bleed-x's negative margins only
   escape .app-main's own padding, not an extra max-width imposed on .app-main
   itself. Containing .app-main__content instead keeps the catalogue's real
   content readable-width while leaving .app-main (and therefore the footer)
   full-width, consistent with every other page. */
body.page-catalogue .app-main__content {
    max-width: 1100px;
    margin: 0 auto;
}

/* Only affects text with no explicit (Tailwind !important) color class of its
   own — i.e. the bare heading + "Total/Matching courses" line that sit
   directly on the dark page background. Card/dropdown/filter text already
   carries its own explicit color utility and is unaffected by inheritance. */
body.page-catalogue .catalogue-courses {
    color: rgba(255, 255, 255, 0.85);
}

body.page-catalogue .section-header {
    border-bottom-color: rgba(255, 255, 255, 0.15) !important;
}

/* Cookie consent banner (src/CoreBundle/Resources/views/Layout/cookie_banner.html.twig)
   uses Tailwind's .text-gray-90 (color: rgb(51 51 51) !important — dark gray,
   meant for its own light bg-warning/15 background) for its main text — reads
   as invisible against the new dark theme. Scoped to #chamilo-cookie-banner
   only, so .text-gray-90 keeps working everywhere else it's already used correctly. */
#chamilo-cookie-banner .text-gray-90 {
    color: rgba(255, 255, 255, 0.9) !important;
}

/* "+ More" toggle button — core gives it bg-white, which combined with the
   .text-gray-90 fix above (now white) made it white-on-white until hover. */
#chamilo-cookie-banner-toggle {
    background-color: #0ea5e9 !important;
    border-color: #0ea5e9 !important;
    color: #fff !important;
}
#chamilo-cookie-banner-toggle:hover {
    background-color: #00439a !important;
    border-color: #00439a !important;
    color: #fff !important;
}