diff --git a/cms/envs/common.py b/cms/envs/common.py index 986b7262d92d..62809d1d245b 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -687,6 +687,7 @@ LMS_ROOT = REPO_ROOT / "lms" ENV_ROOT = REPO_ROOT.dirname() # virtualenv dir /edx-platform is in COURSES_ROOT = ENV_ROOT / "data" +XMODULE_ROOT = REPO_ROOT / "xmodule" GITHUB_REPO_ROOT = ENV_ROOT / "data" @@ -1292,6 +1293,10 @@ STATICFILES_DIRS = [ COMMON_ROOT / "static", PROJECT_ROOT / "static", + # Temporarily adding the following static path as we are migrating the built-in blocks' Sass to vanilla CSS. + # Once all of the built-in blocks are extracted from edx-platform, we can remove this static path. + # Relevant ticket: https://github.com/openedx/edx-platform/issues/35300 + XMODULE_ROOT / "static", ] # Locale/Internationalization diff --git a/common/static/sass/_builtin-block-variables.scss b/common/static/sass/_builtin-block-variables.scss index 2c567c6fb1f4..e232cb57d575 100644 --- a/common/static/sass/_builtin-block-variables.scss +++ b/common/static/sass/_builtin-block-variables.scss @@ -16,7 +16,6 @@ :root { --action-primary-active-bg: $action-primary-active-bg; - --all-text-inputs: $all-text-inputs; --base-font-size: $base-font-size; --base-line-height: $base-line-height; --baseline: $baseline; @@ -26,6 +25,7 @@ --blue-d1: $blue-d1; --blue-d2: $blue-d2; --blue-d4: $blue-d4; + --blue-s1: $blue-s1; --body-color: $body-color; --border-color: $border-color; --bp-screen-lg: $bp-screen-lg; @@ -34,6 +34,8 @@ --danger: $danger; --darkGrey: $darkGrey; --error-color: $error-color; + --error-color-dark: darken($error-color, 11%); + --error-color-light: lighten($error-color, 25%); --font-bold: $font-bold; --font-family-sans-serif: $font-family-sans-serif; --general-color-accent: $general-color-accent; @@ -44,6 +46,12 @@ --gray-l3: $gray-l3; --gray-l4: $gray-l4; --gray-l6: $gray-l6; + --icon-correct: url($static-path + '/images/correct-icon.png'); + --icon-incorrect: url($static-path + '/images/incorrect-icon.png'); + --icon-info: url($static-path + '/images/info-icon.png'); + --icon-partially-correct: url($static-path + '/images/partially-correct-icon.png'); + --icon-spinner: url($static-path + '/images/spinner.gif'); + --icon-unanswered: url($static-path + '/images/unanswered-icon.png'); --incorrect: $incorrect; --lightGrey: $lightGrey; --lighter-base-font-color: $lighter-base-font-color; diff --git a/lms/envs/common.py b/lms/envs/common.py index f2bcfa822b6e..7b4e9c314af8 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1943,6 +1943,10 @@ def _make_mako_template_dirs(settings): COMMON_ROOT / "static", PROJECT_ROOT / "static", NODE_MODULES_ROOT / "@edx", + # Temporarily adding the following static path as we are migrating the built-in blocks' Sass to vanilla CSS. + # Once all of the built-in blocks are extracted from edx-platform, we can remove this static path. + # Relevant ticket: https://github.com/openedx/edx-platform/issues/35300 + XMODULE_ROOT / "static", ] FAVICON_PATH = 'images/favicon.ico' diff --git a/xmodule/assets/tabs/_tabs.scss b/xmodule/assets/tabs/_tabs.scss index ad47d915a230..4b8c2a387a91 100644 --- a/xmodule/assets/tabs/_tabs.scss +++ b/xmodule/assets/tabs/_tabs.scss @@ -31,12 +31,12 @@ .edit-header { box-sizing: border-box; - padding: 18px $baseline; + padding: 18px var(--baseline); top: 0 !important; // ugly override for second level tab override right: 0; - background-color: $blue; - border-bottom: 1px solid $blue-d2; - color: $white; + background-color: var(--blue); + border-bottom: 1px solid var(--blue-d2); + color: var(--white); //Component Name .component-name { @@ -44,16 +44,16 @@ top: 0; left: 0; width: 50%; - color: $white; + color: var(--white); font-weight: 600; em { display: inline-block; - margin-right: ($baseline/4); + margin-right: calc((var(--baseline)/4)); font-weight: 400; - color: $white; + color: var(--white); } } @@ -61,9 +61,9 @@ .editor-tabs { list-style: none; right: 0; - top: ($baseline/4); + top: calc((var(--baseline)/4)); position: absolute; - padding: 12px ($baseline*0.75); + padding: 12px calc((var(--baseline)*0.75)); .inner_tab_wrap { display: inline-block; @@ -73,25 +73,25 @@ @include font-size(14); @include linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0)); - border: 1px solid $blue-d1; + border: 1px solid var(--blue-d1); border-radius: 3px; - padding: ($baseline/4) ($baseline); - background-color: $blue; + padding: calc((var(--baseline)/4)) (var(--baseline)); + background-color: var(--blue); font-weight: bold; - color: $white; + color: var(--white); &.current { - @include linear-gradient($blue, $blue); + @include linear-gradient(var(--blue), var(--blue)); - color: $blue-d1; - box-shadow: inset 0 1px 2px 1px $shadow-l1; - background-color: $blue-d4; + color: var(--blue-d1); + box-shadow: inset 0 1px 2px 1px var(--shadow-l1); + background-color: var(--blue-d4); cursor: default; } &:hover, &:focus { - box-shadow: inset 0 1px 2px 1px $shadow; + box-shadow: inset 0 1px 2px 1px var(--shadow); background-image: linear-gradient(#009fe6, #009fe6) !important; } } @@ -113,7 +113,7 @@ .comp-subtitles-import-list { > li { display: block; - margin: $baseline/2 0; + margin: calc(var(--baseline)/2) 0; } .blue-button { @@ -128,7 +128,7 @@ } .component-tab { - background: $white; + background: var(--white); position: relative; border-top: 1px solid #8891a1; diff --git a/xmodule/assets/video/_accessible_menu.scss b/xmodule/assets/video/_accessible_menu.scss index f7153fa98429..d411925f2390 100644 --- a/xmodule/assets/video/_accessible_menu.scss +++ b/xmodule/assets/video/_accessible_menu.scss @@ -1,11 +1,12 @@ @import 'base/mixins'; +@import 'lms/theme/variables-v1'; $a11y--gray: rgb(127, 127, 127); $a11y--blue: rgb(0, 159, 230); -$a11y--gray-d1: shade($gray, 20%); -$a11y--gray-l2: tint($gray, 40%); -$a11y--gray-l3: tint($gray, 60%); -$a11y--blue-s1: saturate($blue, 15%); +$a11y--gray-d1: var(--gray-d1); +$a11y--gray-l2: var(--gray-l2); +$a11y--gray-l3: var(--gray-l3); +$a11y--blue-s1: var(--blue-s1); %use-font-awesome { font-family: FontAwesome; @@ -32,7 +33,7 @@ $a11y--blue-s1: saturate($blue, 15%); display: none; position: absolute; list-style: none; - background-color: $white; + background-color: var(--white); border: 1px solid #eee; li { @@ -41,7 +42,7 @@ $a11y--blue-s1: saturate($blue, 15%); margin: 0; padding: 0; border-bottom: 1px solid #eee; - color: $white; + color: var(--white); a { display: block; @@ -84,23 +85,23 @@ $a11y--blue-s1: saturate($blue, 15%); &.open { > a { - background-color: $action-primary-active-bg; - color: $very-light-text; + background-color: var(--action-primary-active-bg); + color: var(--very-light-text); &::after { - color: $very-light-text; + color: var(--very-light-text); } } } > a { - @include transition(all $tmg-f2 ease-in-out 0s); + @include transition(all var(--tmg-f2) ease-in-out 0s); @include font-size(12); display: block; border-radius: 0 3px 3px 0; - background-color: $very-light-text; - padding: ($baseline*0.75) ($baseline*1.25) ($baseline*0.75) ($baseline*0.75); + background-color: var(--very-light-text); + padding: calc((var(--baseline)*0.75)) calc((var(--baseline)*1.25)) calc((var(--baseline)*0.75)) calc((var(--baseline)*0.75)); color: $a11y--gray-l2; min-width: 1.5em; line-height: 14px; @@ -113,9 +114,9 @@ $a11y--blue-s1: saturate($blue, 15%); content: "\f0d7"; position: absolute; - right: ($baseline*0.5); + right: calc((var(--baseline)*0.5)); top: 33%; - color: $lighter-base-font-color; + color: var(--lighter-base-font-color); } } @@ -144,7 +145,7 @@ $a11y--blue-s1: saturate($blue, 15%); @extend %ui-depth5; border: 1px solid #333; - background: $white; + background: var(--white); color: #333; padding: 0; margin: 0; @@ -162,8 +163,8 @@ $a11y--blue-s1: saturate($blue, 15%); .menu-item, .submenu-item { - border-top: 1px solid $gray-l3; - padding: ($baseline/4) ($baseline/2); + border-top: 1px solid var(--gray-l3); + padding: calc((var(--baseline)/4)) calc((var(--baseline)/2)); outline: none; & > span { @@ -176,17 +177,17 @@ $a11y--blue-s1: saturate($blue, 15%); &:focus { background: #333; - color: $white; + color: var(--white); & > span { - color: $white; + color: var(--white); } } } .submenu-item { position: relative; - padding: ($baseline/4) $baseline ($baseline/4) ($baseline/2); + padding: calc((var(--baseline)/4)) var(--baseline) calc((var(--baseline)/4)) calc((var(--baseline)/2)); &::after { content: '\25B6'; @@ -202,10 +203,10 @@ $a11y--blue-s1: saturate($blue, 15%); &.is-opened { background: #333; - color: $white; + color: var(--white); & > span { - color: $white; + color: var(--white); } & > .submenu { @@ -220,7 +221,7 @@ $a11y--blue-s1: saturate($blue, 15%); .is-disabled { pointer-events: none; - color: $gray-l3; + color: var(--gray-l3); } } diff --git a/xmodule/assets/video/_display.scss b/xmodule/assets/video/_display.scss index fd5cd73b2105..928f4a915443 100644 --- a/xmodule/assets/video/_display.scss +++ b/xmodule/assets/video/_display.scss @@ -23,7 +23,7 @@ $secondary-light: rgb(219, 139, 175); // UXPL secondary light $cool-dark: rgb(79, 89, 93); // UXPL cool dark & { - margin-bottom: ($baseline*1.5); + margin-bottom: calc((var(--baseline)*1.5)); } .is-hidden { @@ -99,9 +99,9 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark .branding, .wrapper-transcript-feedback { flex: 1; - margin-top: $baseline; + margin-top: var(--baseline); - @include padding-right($baseline); + @include padding-right(var(--baseline)); vertical-align: top; } @@ -147,14 +147,14 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark left: -9999em; display: inline-block; vertical-align: middle; - color: $body-color; + color: var(--body-color); } .brand-logo { display: inline-block; max-width: 100%; - max-height: ($baseline*2); - padding: ($baseline/4) 0; + max-height: calc((var(--baseline)*2)); + padding: calc((var(--baseline)/4)) 0; vertical-align: middle; } } @@ -180,8 +180,8 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark .google-disclaimer { display: none; - margin-top: $baseline; - @include padding-right($baseline); + margin-top: var(--baseline); + @include padding-right(var(--baseline)); vertical-align: top; } @@ -246,7 +246,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark opacity: 0.1; &::after { - background: $white; + background: var(--white); position: absolute; width: 50%; height: 50%; @@ -271,23 +271,23 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark } .closed-captions.is-visible { - max-height: ($baseline * 3); - border-radius: ($baseline / 5); - padding: 8px ($baseline / 2) 8px ($baseline * 1.5); + max-height: calc((var(--baseline) * 3)); + border-radius: calc((var(--baseline) / 5)); + padding: 8px calc((var(--baseline) / 2)) 8px calc((var(--baseline) * 1.5)); background: rgba(0, 0, 0, 0.75); - color: $yellow; + color: var(--yellow); &::before { position: absolute; display: inline-block; top: 50%; - @include left($baseline); + @include left(var(--baseline)); margin-top: -0.6em; font-family: 'FontAwesome'; content: "\f142"; - color: $white; + color: var(--white); opacity: 0.5; } @@ -316,7 +316,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark .video-error, .video-hls-error { - padding: ($baseline / 5); + padding: calc((var(--baseline) / 5)); background: black; color: white !important; // the pattern library headings shim is more scoped } @@ -366,7 +366,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark margin: 0; border: 0; border-radius: 0; - padding: ($baseline / 2) ($baseline / 1.5); + padding: calc((var(--baseline) / 2)) calc((var(--baseline) / 1.5)); background: rgb(40, 44, 46); // UXPL grayscale-cool x-dark box-shadow: none; text-shadow: none; @@ -409,7 +409,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark left: 0; right: 0; z-index: 1; - height: ($baseline / 4); + height: calc((var(--baseline) / 4)); margin-left: 0; border: 1px solid $cool-dark; border-radius: 0; @@ -436,11 +436,11 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark box-sizing: border-box; top: -1px; - height: ($baseline / 4); - width: ($baseline / 4); - margin-left: -($baseline / 8); // center-center causes the control to be beyond the end of the sider + height: calc((var(--baseline) / 4)); + width: calc((var(--baseline) / 4)); + margin-left: calc(-1 * (var(--baseline) / 8)); // center-center causes the control to be beyond the end of the sider border: 1px solid $secondary-base; - border-radius: ($baseline / 5); + border-radius: calc((var(--baseline) / 5)); padding: 0; background: $secondary-base; box-shadow: none; @@ -527,7 +527,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark position: absolute; display: none; - bottom: ($baseline * 2); + bottom: calc((var(--baseline) * 2)); @include right(0); // right-align menus since this whole collection is on the right @@ -571,9 +571,9 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark &.is-active { .speed-option, .control-lang { - @include border-left($baseline/10 solid rgb(14, 166, 236)); + @include border-left(calc(var(--baseline) / 10) solid rgb(14, 166, 236)); - font-weight: $font-bold; + font-weight: var(--font-bold); color: rgb(14, 166, 236); // UXPL primary accent } } @@ -610,9 +610,9 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark .speed-button { .label { - @include padding(0 ($baseline/3) 0 0); + @include padding(0 calc((var(--baseline)/3)) 0 0); - font-family: $font-family-sans-serif; + font-family: var(--font-family-sans-serif); color: rgb(231, 236, 238); // UXPL grayscale-cool x-light @media (max-width: 1120px) { @@ -636,8 +636,8 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark .lang { .language-menu { - width: $baseline; - padding: ($baseline / 2) 0; + width: var(--baseline); + padding: calc((var(--baseline) / 2)) 0; } .control { @@ -685,7 +685,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark display: none; position: absolute; - bottom: ($baseline * 2); + bottom: calc((var(--baseline) * 2)); @include right(0); @@ -695,7 +695,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark .volume-slider { height: 100px; - width: ($baseline / 4); + width: calc((var(--baseline) / 4)); margin: 14px auto; box-sizing: border-box; border: 1px solid $cool-dark; @@ -704,14 +704,14 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark .ui-slider-handle { @extend %ui-fake-link; - @include transition(height $tmg-s2 ease-in-out 0s, width $tmg-s2 ease-in-out 0s); + @include transition(height var(--tmg-s2) ease-in-out 0s, width var(--tmg-s2) ease-in-out 0s); @include left(-5px); box-sizing: border-box; height: 13px; width: 13px; border: 1px solid $secondary-base; - border-radius: ($baseline / 5); + border-radius: calc((var(--baseline) / 5)); padding: 0; background: $secondary-base; box-shadow: none; @@ -763,11 +763,11 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark &:hover { .video-controls { .slider { - height: ($baseline / 1.5); + height: calc((var(--baseline) / 1.5)); .ui-slider-handle { - height: ($baseline / 1.5); - width: ($baseline / 1.5); + height: calc((var(--baseline) / 1.5)); + width: calc((var(--baseline) / 1.5)); } } } @@ -887,7 +887,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark bottom: 0; top: 0; width: 275px; - padding: 0 $baseline; + padding: 0 var(--baseline); display: none; } } @@ -973,14 +973,14 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark box-sizing: border-box; @include transition(none); - background: $black; + background: var(--black); visibility: visible; li { color: #aaa; &.current { - color: $white; + color: var(--white); } } } @@ -1010,17 +1010,17 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark background-position: 50% 50%; background-repeat: no-repeat; background-size: 100%; - background-color: $black; + background-color: var(--black); &.is-html5 { background-size: 15%; } .btn-play.btn-pre-roll { - padding: $baseline; + padding: var(--baseline); border: none; - border-radius: $baseline; - background: $black-t2; + border-radius: var(--baseline); + background: var(--black-t2); box-shadow: none; &::after { @@ -1030,13 +1030,13 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark } img { - height: ($baseline * 4); - width: ($baseline * 4); + height: calc((var(--baseline) * 4)); + width: calc((var(--baseline) * 4)); } &:hover, &:focus { - background: $blue; + background: var(--blue); } } } diff --git a/xmodule/static/css-builtin-blocks/VideoBlockDisplay.css b/xmodule/static/css-builtin-blocks/VideoBlockDisplay.css new file mode 100644 index 000000000000..93c4b6adcec3 --- /dev/null +++ b/xmodule/static/css-builtin-blocks/VideoBlockDisplay.css @@ -0,0 +1,1147 @@ +@import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,400i,600,700"); + +.xmodule_display.xmodule_VideoBlock { + /* stylelint-disable-line */ + /* stylelint-disable-line */ + /* stylelint-disable-line */ + /* stylelint-disable-line */ + /* stylelint-disable-line */ + /* stylelint-disable-line */ +} + +.xmodule_display.xmodule_VideoBlock { + margin-bottom: calc((var(--baseline) * 1.5)); +} + +.xmodule_display.xmodule_VideoBlock .is-hidden, .xmodule_display.xmodule_VideoBlock .video.closed .subtitles { + display: none; +} + +.xmodule_display.xmodule_VideoBlock .video { + background: whitesmoke; + display: block; + margin: 0 -12px; + padding: 12px; + border-radius: 5px; + outline: none; +} + +.xmodule_display.xmodule_VideoBlock .video:after { + content: ""; + display: table; + clear: both; +} + +.xmodule_display.xmodule_VideoBlock .video:focus, .xmodule_display.xmodule_VideoBlock .video:active, .xmodule_display.xmodule_VideoBlock .video:hover { + border: 0; +} + +.xmodule_display.xmodule_VideoBlock .video.is-initialized .video-wrapper .spinner { + display: none; +} + +.xmodule_display.xmodule_VideoBlock .video.is-pre-roll .slider { + visibility: hidden; +} + +.xmodule_display.xmodule_VideoBlock .video.is-pre-roll .video-player { + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video.is-pre-roll .video-player::before { + display: block; + content: ""; + width: 100%; + padding-top: 55%; +} + +.xmodule_display.xmodule_VideoBlock .video .tc-wrapper { + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .tc-wrapper:after { + content: ""; + display: table; + clear: both; +} + +.xmodule_display.xmodule_VideoBlock .video .focus_grabber { + position: relative; + display: inline; + width: 0; + height: 0; +} + +.xmodule_display.xmodule_VideoBlock .video .downloads-heading { + margin: 1em 0 0; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-video-bottom-section { + display: flex; + justify-content: space-between; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-video-bottom-section .wrapper-download-video, +.xmodule_display.xmodule_VideoBlock .video .wrapper-video-bottom-section .wrapper-download-transcripts, +.xmodule_display.xmodule_VideoBlock .video .wrapper-video-bottom-section .wrapper-handouts, +.xmodule_display.xmodule_VideoBlock .video .wrapper-video-bottom-section .branding, +.xmodule_display.xmodule_VideoBlock .video .wrapper-video-bottom-section .wrapper-transcript-feedback { + flex: 1; + margin-top: var(--baseline); + padding-right: var(--baseline); + vertical-align: top; +} + +@media (min-width: 768px) { + .xmodule_display.xmodule_VideoBlock .video .wrapper-downloads { + display: flex; + } +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .hd { + margin: 0; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .wrapper-download-video .video-sources { + margin: 0; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .wrapper-download-transcripts .list-download-transcripts { + margin: 0; + padding: 0; + list-style: none; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .wrapper-download-transcripts .list-download-transcripts .transcript-option { + margin: 0; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .wrapper-download-transcripts .list-download-transcripts .transcript-option a.btn, .xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .wrapper-download-transcripts .list-download-transcripts .transcript-option a.btn-link { + font-size: 16px !important; + font-weight: unset; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .branding { + padding-right: 0; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .branding .host-tag { + position: absolute; + left: -9999em; + display: inline-block; + vertical-align: middle; + color: var(--body-color); +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-downloads .branding .brand-logo { + display: inline-block; + max-width: 100%; + max-height: calc((var(--baseline) * 2)); + padding: calc((var(--baseline) / 4)) 0; + vertical-align: middle; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-transcript-feedback { + display: none; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-transcript-feedback .transcript-feedback-buttons { + display: flex; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-transcript-feedback .transcript-feedback-btn-wrapper { + margin-right: 10px; +} + +.xmodule_display.xmodule_VideoBlock .video .wrapper-transcript-feedback .thumbs-up-btn, +.xmodule_display.xmodule_VideoBlock .video .wrapper-transcript-feedback .thumbs-down-btn { + border: none; + box-shadow: none; + background: transparent; +} + +.xmodule_display.xmodule_VideoBlock .video .google-disclaimer { + display: none; + margin-top: var(--baseline); + padding-right: var(--baseline); + vertical-align: top; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper { + float: left; + margin-right: 2.27273%; + width: 65.90909%; + background-color: black; + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper:hover .btn-play { + color: #0075b4; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper:hover .btn-play::after { + background: #fff; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player-pre, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player-post { + height: 50px; + background-color: #111010; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .spinner { + transform: translate(-50%, -50%); + position: absolute; + z-index: 1; + background: rgba(0, 0, 0, 0.7); + top: 50%; + left: 50%; + padding: 30px; + border-radius: 25%; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .spinner::after { + animation: rotateCW 3s infinite linear; + content: ''; + display: block; + width: 30px; + height: 30px; + border: 7px solid white; + border-top-color: transparent; + border-radius: 100%; + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .btn-play { + transform: translate(-50%, -50%); + position: absolute; + z-index: 1; + top: 46%; + left: 50%; + font-size: 4em; + cursor: pointer; + opacity: 0.1; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .btn-play::after { + background: var(--white); + position: absolute; + width: 50%; + height: 50%; + content: ''; + left: 0; + top: 0; + bottom: 0; + right: 0; + margin: auto; + z-index: -1; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .closed-captions { + left: 5%; + position: absolute; + width: 90%; + box-sizing: border-box; + top: 70%; + text-align: center; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .closed-captions.is-visible { + max-height: calc((var(--baseline) * 3)); + border-radius: calc((var(--baseline) / 5)); + padding: 8px calc((var(--baseline) / 2)) 8px calc((var(--baseline) * 1.5)); + background: rgba(0, 0, 0, 0.75); + color: var(--yellow); +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .closed-captions.is-visible::before { + position: absolute; + display: inline-block; + top: 50%; + left: var(--baseline); + margin-top: -0.6em; + font-family: 'FontAwesome'; + content: "\f142"; + color: var(--white); + opacity: 0.5; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .closed-captions.is-visible:hover, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .closed-captions.is-visible.is-dragging { + background: black; + cursor: move; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .closed-captions.is-visible:hover::before, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .closed-captions.is-visible.is-dragging::before { + opacity: 1; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player { + overflow: hidden; + min-height: 158px; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player > div { + height: 100%; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player > div.hidden { + display: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player .video-error, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player .video-hls-error { + padding: calc((var(--baseline) / 5)); + background: black; + color: white !important; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player object, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player iframe, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player video { + left: 0; + display: block; + border: none; + width: 100%; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player h4 { + text-align: center; + color: white; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-player h4.hidden { + display: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls { + position: relative; + border: 0; + background: #282c2e; + color: #f0f3f5; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls:after { + content: ""; + display: table; + clear: both; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls:hover ul, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls:hover div, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls:focus ul, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls:focus div { + opacity: 1; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .control { + display: inline-block; + vertical-align: middle; + margin: 0; + border: 0; + border-radius: 0; + padding: calc((var(--baseline) / 2)) calc((var(--baseline) / 1.5)); + background: #282c2e; + box-shadow: none; + text-shadow: none; + color: #cfd8dc; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .control:hover, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .control:focus { + background: #171a1b; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .control:active, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .is-active.control, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .active.control { + color: #0ea6ec; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .control .icon { + width: 1em; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .control .icon.icon-hd { + width: auto; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider { + transform-origin: bottom left; + transition: height 0.7s ease-in-out 0s; + box-sizing: border-box; + position: absolute; + bottom: 100%; + left: 0; + right: 0; + z-index: 1; + height: calc((var(--baseline) / 4)); + margin-left: 0; + border: 1px solid #4f595d; + border-radius: 0; + background: #4f595d; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider:after { + content: ""; + display: table; + clear: both; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider .ui-widget-header { + background: #8e3e63; + border: 1px solid #8e3e63; + box-shadow: none; + top: -1px; + left: -1px; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider .ui-corner-all.slider-range { + opacity: 0.3; + background-color: #1e91d3; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider .ui-slider-handle { + transform-origin: bottom left; + transition: all 0.7s ease-in-out 0s; + box-sizing: border-box; + top: -1px; + height: calc((var(--baseline) / 4)); + width: calc((var(--baseline) / 4)); + margin-left: calc(-1 * (var(--baseline) / 8)); + border: 1px solid #cb598d; + border-radius: calc((var(--baseline) / 5)); + padding: 0; + background: #cb598d; + box-shadow: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider .ui-slider-handle:focus, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider .ui-slider-handle:hover { + background-color: #db8baf; + border-color: #db8baf; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .vcr { + float: left; + list-style: none; + border-right: 1px solid #282c2e; + padding: 0; +} + +@media (max-width: 1120px) { + .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .vcr { + margin-right: lh(0.5); + font-size: 0.875em; + } +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .vcr .video_control:focus { + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .vcr .video_control.skip { + white-space: nowrap; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .vcr .vidtime { + padding-left: lh(0.75); + display: inline-block; + color: #cfd8dc; + -webkit-font-smoothing: antialiased; +} + +@media (max-width: 1120px) { + .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .vcr .vidtime { + padding-left: lh(0.5); + } +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls { + float: right; + border-left: 1px dotted #4f595d; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .add-fullscreen, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .grouped-controls, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .auto-advance, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .quality-control { + border-left: 1px dotted #4f595d; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .speed-button:focus, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume > .control:focus, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .add-fullscreen:focus, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .auto-advance:focus, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .quality-control:focus, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .toggle-transcript:focus { + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container { + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu { + transition: none; + position: absolute; + display: none; + bottom: calc((var(--baseline) * 2)); + right: 0; + width: 120px; + margin: 0; + border: none; + padding: 0; + box-shadow: none; + background-color: #282c2e; + list-style: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li { + color: #e7ecee; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li .speed-option, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li .control-lang { + text-align: left; + display: block; + width: 100%; + border: 0; + border-radius: 0; + padding: lh(0.5); + background: #282c2e; + box-shadow: none; + color: #e7ecee; + overflow: hidden; + text-shadow: none; + text-overflow: ellipsis; + white-space: nowrap; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li .speed-option:hover, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li .speed-option:focus, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li .control-lang:hover, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li .control-lang:focus { + background-color: #4f595d; + color: #fcfcfc; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li.is-active .speed-option, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li.is-active .control-lang { + border-left: calc(var(--baseline) / 10) solid #0ea6ec; + font-weight: var(--font-bold); + color: #0ea6ec; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container.is-opened .menu { + display: block; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .speeds, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .lang, +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .grouped-controls { + display: inline-block; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .speeds.is-opened .control .icon { + transform: rotate(-90deg); +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .speeds .speed-button .label { + padding: 0 calc((var(--baseline) / 3)) 0 0; + font-family: var(--font-family-sans-serif); + color: #e7ecee; +} + +@media (max-width: 1120px) { + .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .speeds .speed-button .label { + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + } +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .speeds .speed-button .value { + padding: 0 lh(0.5) 0 0; + color: #e7ecee; + font-weight: bold; +} + +@media (max-width: 1120px) { + .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .speeds .speed-button .value { + padding: 0 lh(0.5); + } +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .lang .language-menu { + width: var(--baseline); + padding: calc((var(--baseline) / 2)) 0; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .lang.is-opened .control .icon { + transform: rotate(90deg); +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume { + display: inline-block; + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume.is-opened .volume-slider-container { + display: block; + opacity: 1; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume:not(:first-child) > a { + border-left: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container { + transition: none; + display: none; + position: absolute; + bottom: calc((var(--baseline) * 2)); + right: 0; + width: 41px; + height: 120px; + background-color: #282c2e; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container .volume-slider { + height: 100px; + width: calc((var(--baseline) / 4)); + margin: 14px auto; + box-sizing: border-box; + border: 1px solid #4f595d; + background: #4f595d; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container .volume-slider .ui-slider-handle { + transition: height var(--tmg-s2) ease-in-out 0s, width var(--tmg-s2) ease-in-out 0s; + left: -5px; + box-sizing: border-box; + height: 13px; + width: 13px; + border: 1px solid #cb598d; + border-radius: calc((var(--baseline) / 5)); + padding: 0; + background: #cb598d; + box-shadow: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container .volume-slider .ui-slider-handle:hover, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container .volume-slider .ui-slider-handle:focus { + background: #db8baf; + border-color: #db8baf; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container .volume-slider .ui-slider-range { + background: #8e3e63; + border: 1px solid #8e3e63; + left: -1px; + bottom: -1px; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .quality-control { + font-weight: 700; + letter-spacing: -1px; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .quality-control.active { + color: #0ea6ec; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .quality-control.is-hidden, .xmodule_display.xmodule_VideoBlock .video.closed .video-wrapper .video-controls .secondary-controls .quality-control.subtitles { + display: none !important; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .toggle-transcript.is-active { + color: #0ea6ec; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .lang > .hide-subtitles { + transition: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper:hover .video-controls .slider { + height: calc((var(--baseline) / 1.5)); +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper:hover .video-controls .slider .ui-slider-handle { + height: calc((var(--baseline) / 1.5)); + width: calc((var(--baseline) / 1.5)); +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .closed-captions { + width: 65%; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen.closed .closed-captions { + width: 90%; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles { + float: left; + overflow: auto; + max-height: 460px; + width: 31.81818%; + padding: 0; + font-size: 14px; + visibility: visible; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles a { + color: #0074b5; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu { + height: 100%; + margin: 0; + padding: 0 3px; + list-style: none; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li { + margin-bottom: 8px; + border: 0; + padding: 0; + color: #0074b5; + line-height: lh(); +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li span { + display: block; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li.current { + color: #333; + font-weight: 700; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li.focused { + outline: #000 dotted thin; + outline-offset: -1px; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li:hover, .xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li:focus { + text-decoration: underline; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li:empty { + margin-bottom: 0; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li.spacing:last-of-type { + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li.spacing:last-of-type .transcript-end { + position: absolute; + bottom: 0; +} + +.xmodule_display.xmodule_VideoBlock .video.closed .video-wrapper { + width: 100%; + background-color: inherit; +} + +.xmodule_display.xmodule_VideoBlock .video.closed .video-wrapper .video-controls.html5 { + bottom: 0; + left: 0; + right: 0; + position: absolute; + z-index: 1; +} + +.xmodule_display.xmodule_VideoBlock .video.closed .video-wrapper .video-player-pre, +.xmodule_display.xmodule_VideoBlock .video.closed .video-wrapper .video-player-post { + height: 0; +} + +.xmodule_display.xmodule_VideoBlock .video.closed .video-wrapper .video-player h3 { + color: black; +} + +.xmodule_display.xmodule_VideoBlock .video.closed .subtitles.html5 { + background-color: rgba(243, 243, 243, 0.8); + height: 100%; + position: absolute; + right: 0; + bottom: 0; + top: 0; + width: 275px; + padding: 0 var(--baseline); + display: none; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen { + background: rgba(0, 0, 0, 0.95); + border: 0; + bottom: 0; + height: 100%; + left: 0; + margin: 0; + padding: 0; + position: fixed; + top: 0; + width: 100%; + vertical-align: middle; + border-radius: 0; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen.closed .tc-wrapper .video-wrapper { + width: 100%; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .video-wrapper .video-player-pre, +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .video-wrapper .video-player-post { + height: 0; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .video-wrapper { + position: static; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .video-wrapper .video-player h3 { + color: white; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper { + width: 100%; + height: 100%; + position: static; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper:after { + content: ""; + display: table; + clear: both; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper .video-wrapper { + height: 100%; + width: 75%; + margin-right: 0; + vertical-align: middle; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper .video-wrapper object, +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper .video-wrapper iframe, +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper .video-wrapper video { + position: absolute; + width: auto; + height: auto; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper .video-controls { + position: absolute; + bottom: 0; + left: 0; + width: 100%; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .subtitles { + height: 100%; + width: 25%; + padding: lh(); + box-sizing: border-box; + transition: none; + background: var(--black); + visibility: visible; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .subtitles li { + color: #aaa; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen .subtitles li.current { + color: var(--white); +} + +.xmodule_display.xmodule_VideoBlock .video.is-touch .tc-wrapper .video-wrapper object, +.xmodule_display.xmodule_VideoBlock .video.is-touch .tc-wrapper .video-wrapper iframe, +.xmodule_display.xmodule_VideoBlock .video.is-touch .tc-wrapper .video-wrapper video { + width: 100%; + height: 100%; +} + +.xmodule_display.xmodule_VideoBlock .video .video-pre-roll { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 100%; + background-color: var(--black); +} + +.xmodule_display.xmodule_VideoBlock .video .video-pre-roll.is-html5 { + background-size: 15%; +} + +.xmodule_display.xmodule_VideoBlock .video .video-pre-roll .btn-play.btn-pre-roll { + padding: var(--baseline); + border: none; + border-radius: var(--baseline); + background: var(--black-t2); + box-shadow: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-pre-roll .btn-play.btn-pre-roll::after { + display: none; +} + +.xmodule_display.xmodule_VideoBlock .video .video-pre-roll .btn-play.btn-pre-roll img { + height: calc((var(--baseline) * 4)); + width: calc((var(--baseline) * 4)); +} + +.xmodule_display.xmodule_VideoBlock .video .video-pre-roll .btn-play.btn-pre-roll:hover, .xmodule_display.xmodule_VideoBlock .video .video-pre-roll .btn-play.btn-pre-roll:focus { + background: var(--blue); +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .slider .ui-slider-handle, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu li, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container .volume-slider .ui-slider-handle, .xmodule_display.xmodule_VideoBlock .video .subtitles .subtitles-menu li, .xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list li { + cursor: pointer; +} + +.xmodule_display.xmodule_VideoBlock .video.closed .subtitles.html5 { + z-index: 0; +} + +.xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .menu-container .menu, .xmodule_display.xmodule_VideoBlock .video .video-wrapper .video-controls .secondary-controls .volume .volume-slider-container { + z-index: 10; +} + +.xmodule_display.xmodule_VideoBlock .video .video-pre-roll, .xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list { + z-index: 1000; +} + +.xmodule_display.xmodule_VideoBlock .video.video-fullscreen, .xmodule_display.xmodule_VideoBlock .video.video-fullscreen .tc-wrapper .video-controls, .xmodule_display.xmodule_VideoBlock .overlay { + z-index: 10000; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu, +.xmodule_display.xmodule_VideoBlock .submenu { + z-index: 100000; +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container > a::after { + font-family: FontAwesome; + -webkit-font-smoothing: antialiased; + display: inline-block; + speak: none; +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container { + position: relative; +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container.open .a11y-menu-list { + display: block; +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list { + top: 100%; + margin: 0; + padding: 0; + display: none; + position: absolute; + list-style: none; + background-color: var(--white); + border: 1px solid #eee; +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list li { + margin: 0; + padding: 0; + border-bottom: 1px solid #eee; + color: var(--white); +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list li a { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--gray-l2); + font-size: 14px; + line-height: 23px; +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list li a:hover, .xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list li a:focus { + color: var(--gray-d1); +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list li.active a { + color: #009fe6; +} + +.xmodule_display.xmodule_VideoBlock .a11y-menu-container .a11y-menu-list li:last-child { + box-shadow: none; + border-bottom: 0; + margin-top: 0; +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container { + display: inline-block; + vertical-align: top; + border-left: 1px solid #eee; +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container.open > a { + background-color: var(--action-primary-active-bg); + color: var(--very-light-text); +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container.open > a::after { + color: var(--very-light-text); +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container > a { + transition: all var(--tmg-f2) ease-in-out 0s; + font-size: 12px; + display: block; + border-radius: 0 3px 3px 0; + background-color: var(--very-light-text); + padding: calc((var(--baseline) * 0.75)) calc((var(--baseline) * 1.25)) calc((var(--baseline) * 0.75)) calc((var(--baseline) * 0.75)); + color: var(--gray-l2); + min-width: 1.5em; + line-height: 14px; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container > a::after { + content: "\f0d7"; + position: absolute; + right: calc((var(--baseline) * 0.5)); + top: 33%; + color: var(--lighter-base-font-color); +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container .a11y-menu-list { + right: 0; +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container .a11y-menu-list li { + font-size: 0.875em; +} + +.xmodule_display.xmodule_VideoBlock .video-tracks .a11y-menu-container .a11y-menu-list li a { + border: 0; + display: block; + padding: 0.70788em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu, +.xmodule_display.xmodule_VideoBlock .submenu { + border: 1px solid #333; + background: var(--white); + color: #333; + padding: 0; + margin: 0; + list-style: none; + position: absolute; + top: 0; + display: none; + outline: none; + cursor: default; + white-space: nowrap; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu.is-opened, +.xmodule_display.xmodule_VideoBlock .submenu.is-opened { + display: block; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .menu-item, +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item, +.xmodule_display.xmodule_VideoBlock .submenu .menu-item, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item { + border-top: 1px solid var(--gray-l3); + padding: calc((var(--baseline) / 4)) calc((var(--baseline) / 2)); + outline: none; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .menu-item > span, +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item > span, +.xmodule_display.xmodule_VideoBlock .submenu .menu-item > span, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item > span { + color: #333; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .menu-item:first-child, +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item:first-child, +.xmodule_display.xmodule_VideoBlock .submenu .menu-item:first-child, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item:first-child { + border-top: none; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .menu-item:focus, +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item:focus, +.xmodule_display.xmodule_VideoBlock .submenu .menu-item:focus, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item:focus { + background: #333; + color: var(--white); +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .menu-item:focus > span, +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item:focus > span, +.xmodule_display.xmodule_VideoBlock .submenu .menu-item:focus > span, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item:focus > span { + color: var(--white); +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item { + position: relative; + padding: calc((var(--baseline) / 4)) var(--baseline) calc((var(--baseline) / 4)) calc((var(--baseline) / 2)); +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item::after, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item::after { + content: '\25B6'; + position: absolute; + right: 5px; + line-height: 25px; + font-size: 10px; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item .submenu, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item .submenu { + display: none; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item.is-opened, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item.is-opened { + background: #333; + color: var(--white); +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item.is-opened > span, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item.is-opened > span { + color: var(--white); +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item.is-opened > .submenu, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item.is-opened > .submenu { + display: block; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .submenu-item .is-selected, +.xmodule_display.xmodule_VideoBlock .submenu .submenu-item .is-selected { + font-weight: bold; +} + +.xmodule_display.xmodule_VideoBlock .contextmenu .is-disabled, +.xmodule_display.xmodule_VideoBlock .submenu .is-disabled { + pointer-events: none; + color: var(--gray-l3); +} + +.xmodule_display.xmodule_VideoBlock .overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: transparent; +} diff --git a/xmodule/static/css-builtin-blocks/VideoBlockEditor.css b/xmodule/static/css-builtin-blocks/VideoBlockEditor.css new file mode 100644 index 000000000000..4a570a5fec89 --- /dev/null +++ b/xmodule/static/css-builtin-blocks/VideoBlockEditor.css @@ -0,0 +1,167 @@ +@import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,400i,600,700"); + +.xmodule_edit.xmodule_VideoBlock { +} + +.xmodule_edit.xmodule_VideoBlock .ui-col-wide { + width: 74.46809%; + margin-right: 2.12766%; + float: left; +} + +.xmodule_edit.xmodule_VideoBlock .ui-col-narrow { + width: 23.40426%; + float: left; +} + +.xmodule_edit.xmodule_VideoBlock .ui-loading { + box-shadow: inset 0 1px 2px 1px rgba(0, 0, 0, 0.2); + padding: 15px 20px; +} + +.xmodule_edit.xmodule_VideoBlock .ui-loading { + animation: fadeIn 0.25s linear 1; + opacity: 0.6; + background-color: #fff; + padding: 30px 20px; + text-align: center; +} + +.xmodule_edit.xmodule_VideoBlock .ui-loading .spin { + display: inline-block; +} + +.xmodule_edit.xmodule_VideoBlock .ui-loading .copy { + padding-left: 5px; +} + +.xmodule_edit.xmodule_VideoBlock .is-hidden { + display: none; +} + +.xmodule_edit.xmodule_VideoBlock .tabs-wrapper { + padding-top: 0; + position: relative; +} + +.xmodule_edit.xmodule_VideoBlock .tabs-wrapper .wrapper-comp-settings { + display: block; +} + +.xmodule_edit.xmodule_VideoBlock .editor-single-tab-name { + display: none; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs { + position: relative; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs:after { + content: ""; + display: table; + clear: both; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header { + box-sizing: border-box; + padding: 18px var(--baseline); + top: 0 !important; + right: 0; + background-color: var(--blue); + border-bottom: 1px solid var(--blue-d2); + color: var(--white); +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .component-name { + position: relative; + top: 0; + left: 0; + width: 50%; + color: var(--white); + font-weight: 600; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .component-name em { + display: inline-block; + margin-right: calc((var(--baseline) / 4)); + font-weight: 400; + color: var(--white); +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .editor-tabs { + list-style: none; + right: 0; + top: calc((var(--baseline) / 4)); + position: absolute; + padding: 12px calc((var(--baseline) * 0.75)); +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .editor-tabs .inner_tab_wrap { + display: inline-block; + margin-left: 8px; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .editor-tabs .inner_tab_wrap a.tab { + font-size: 14px; + font-size: 1.4rem; + background-color: rgba(255, 255, 255, 0.3); + background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0)); + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0)); + border: 1px solid var(--blue-d1); + border-radius: 3px; + padding: calc((var(--baseline) / 4)) var(--baseline); + background-color: var(--blue); + font-weight: bold; + color: var(--white); +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .editor-tabs .inner_tab_wrap a.tab.current { + background-color: var(--blue); + background-image: -webkit-linear-gradient(var(--blue), var(--blue)); + background-image: linear-gradient(to, var(--blue)); + color: var(--blue-d1); + box-shadow: inset 0 1px 2px 1px var(--shadow-l1); + background-color: var(--blue-d4); + cursor: default; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .editor-tabs .inner_tab_wrap a.tab:hover, .xmodule_edit.xmodule_VideoBlock .editor-with-tabs .edit-header .editor-tabs .inner_tab_wrap a.tab:focus { + box-shadow: inset 0 1px 2px 1px var(--shadow); + background-image: linear-gradient(#009fe6, #009fe6) !important; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .is-inactive { + display: none; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .comp-subtitles-entry { + text-align: center; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .comp-subtitles-entry .file-upload { + display: none; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .comp-subtitles-entry .comp-subtitles-import-list > li { + display: block; + margin: calc(var(--baseline) / 2) 0; +} + +.xmodule_edit.xmodule_VideoBlock .editor-with-tabs .comp-subtitles-entry .comp-subtitles-import-list .blue-button { + font-size: 1em; + display: block; + width: 70%; + margin: 0 auto; + text-align: center; +} + +.xmodule_edit.xmodule_VideoBlock .component-tab { + background: var(--white); + position: relative; + border-top: 1px solid #8891a1; +} + +.xmodule_edit.xmodule_VideoBlock .component-tab#advanced { + padding: 0; + border: none; +} diff --git a/xmodule/tests/test_util_builtin_assets.py b/xmodule/tests/test_util_builtin_assets.py index bc26bed3d6be..8fcc300f264a 100644 --- a/xmodule/tests/test_util_builtin_assets.py +++ b/xmodule/tests/test_util_builtin_assets.py @@ -1,6 +1,9 @@ """ Tests for methods defined in builtin_assets.py """ +from pathlib import PosixPath + +from django.conf import settings from unittest import TestCase from unittest.mock import patch @@ -66,3 +69,52 @@ def test_happy_path(self): mimetype='text/css', placement='head', ) + + +class AddCssToFragmentTests(TestCase): + """ + Tests for add_css_to_fragment. + """ + + def test_absolute_path_raises_value_error(self): + fragment = Fragment() + with self.assertRaises(ValueError): + builtin_assets.add_css_to_fragment( + fragment, + "/openedx/edx-platform/xmodule/assets/VideoBlockEditor.css", + ) + + def test_not_css_raises_value_error(self): + fragment = Fragment() + with self.assertRaises(ValueError): + builtin_assets.add_css_to_fragment( + fragment, + "vertical/public/js/vertical_student_view.js" + ) + + def test_misspelled_path_raises_not_found(self): + fragment = Fragment() + with self.assertRaises(FileNotFoundError): + builtin_assets.add_css_to_fragment( + fragment, + "VideoBlockEditorrrrr.css", + ) + + def test_static_file_missing_raises_improperly_configured(self): + fragment = Fragment() + with patch.object(builtin_assets, 'get_static_file_url', lambda _path: None): + with self.assertRaises(ImproperlyConfigured): + builtin_assets.add_css_to_fragment( + fragment, + "VideoBlockEditor.css", + ) + + def test_happy_path(self): + fragment = Fragment() + builtin_assets.add_css_to_fragment(fragment, "VideoBlockEditor.css") + assert fragment.resources[0] == FragmentResource( + kind='url', + data='/static/css-builtin-blocks/VideoBlockEditor.css', + mimetype='text/css', + placement='head', + ) diff --git a/xmodule/util/builtin_assets.py b/xmodule/util/builtin_assets.py index aaedc44cc649..d37996b25d61 100644 --- a/xmodule/util/builtin_assets.py +++ b/xmodule/util/builtin_assets.py @@ -12,6 +12,38 @@ from openedx.core.djangoapps.theming.helpers_static import get_static_file_url +def add_css_to_fragment(fragment, css_relative_path): + """ + Given a css path relative to xmodule/assets, add a compiled CSS URL to the fragment. + + Raises: + * ValueError if {css_relative_path} is absolute or does not end in '.css'. + * FileNotFoundError if edx-platform/xmodule/assets/{css_relative_path} is missing. + * ImproperlyConfigured if the lookup of the static CSS URL fails. This could happen + if CSS wasn't collected, or the staticfiles app is misconfigured. + + Notes: + * This function is theme-aware. That is: If a theme is enabled which provides a compiled + CSS file of the same name, then that CSS file will be used instead. + """ + if not isinstance(css_relative_path, Path): + css_relative_path = Path(css_relative_path) + if css_relative_path.is_absolute(): + raise ValueError(f"css_file_name should be relative; is absolute: {css_relative_path}") + if css_relative_path.suffix != '.css': + raise ValueError(f"css_file_name should be .css file; is: {css_relative_path}") + css_absolute_path = Path(settings.REPO_ROOT) / "xmodule" / "static" / "css-builtin-blocks" / css_relative_path + if not css_absolute_path.is_file(): + raise FileNotFoundError(f"css file not found: {css_absolute_path}") + css_static_path = Path('css-builtin-blocks') / css_relative_path.with_suffix('.css') + css_url = get_static_file_url(str(css_static_path)) # get_static_file_url is theme-aware. + if not css_url: + raise ImproperlyConfigured( + f"Did not find static CSS file {css_static_path} in staticfiles storage. Perhaps it wasn't collected?" + ) + fragment.add_css_url(css_url) + + def add_sass_to_fragment(fragment, sass_relative_path): """ Given a Sass path relative to xmodule/assets, add a compiled CSS URL to the fragment. diff --git a/xmodule/video_block/video_block.py b/xmodule/video_block/video_block.py index 782645c373b0..ea9d1a44280a 100644 --- a/xmodule/video_block/video_block.py +++ b/xmodule/video_block/video_block.py @@ -48,7 +48,7 @@ from xmodule.modulestore.inheritance import InheritanceKeyValueStore, own_metadata from xmodule.raw_block import EmptyDataRawMixin from xmodule.validation import StudioValidation, StudioValidationMessage -from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_sass_to_fragment +from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_css_to_fragment from xmodule.video_block import manage_video_subtitles_save from xmodule.x_module import ( PUBLIC_VIEW, STUDENT_VIEW, @@ -242,7 +242,7 @@ def student_view(self, context): Return the student view. """ fragment = Fragment(self.get_html(context=context)) - add_sass_to_fragment(fragment, 'VideoBlockDisplay.scss') + add_css_to_fragment(fragment, 'VideoBlockDisplay.css') add_webpack_js_to_fragment(fragment, 'VideoBlockDisplay') shim_xmodule_js(fragment, 'Video') return fragment @@ -260,7 +260,7 @@ def studio_view(self, _context): fragment = Fragment( self.runtime.service(self, 'mako').render_cms_template(self.mako_template, self.get_context()) ) - add_sass_to_fragment(fragment, 'VideoBlockEditor.scss') + add_css_to_fragment(fragment, 'VideoBlockEditor.css') add_webpack_js_to_fragment(fragment, 'VideoBlockEditor') shim_xmodule_js(fragment, 'TabsEditingDescriptor') return fragment @@ -276,7 +276,7 @@ def public_view(self, context): return self.student_view(context) fragment = Fragment(self.get_html(view=PUBLIC_VIEW, context=context)) - add_sass_to_fragment(fragment, 'VideoBlockDisplay.scss') + add_css_to_fragment(fragment, 'VideoBlockDisplay.css') add_webpack_js_to_fragment(fragment, 'VideoBlockDisplay') shim_xmodule_js(fragment, 'Video') return fragment