/* --------------- LOGIN SCREEN --------------- */
@import url('https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css');
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css');
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');

:root{
    --background: #eceff6;

    --gradient-light: #5ca0e6;
    --gradient-dark: #1d62b9;

    --button-blue: #1666b0;
    --button-blue-hover: #0e4c8a;

    --text-background: #f2f6fc;
    --text-background-2: #edf2fc;
    --text-background-hover: #dce9f9;
    --text-background-3: #d9e8ff;

    --header: #e7e7e7;

    --icon-blue: #4078c0;

    --table-border-grey: #dcdcd2;
    --table-border-px: 1px;

    --dark-grey: #999;

    --card-background: #fdfdfd;
}

body {
    /*font-family: Arial, sans-serif;*/
    /*font-family: Roboto, sans-serif;*/
    font-family: Segoe UI, sans-serif;
    background-color: var(--background);
    margin: 0;

    width: 100%;
    height: 100dvh;

    overflow-x: hidden;
    overflow-y: auto;
}

.body-container {
    display: flex;
    flex-direction: column;

    overflow-x: hidden;

    width: 100%;
    min-height: 100%;
    background-color: var(--background);

    position: relative;
}

.page-main .body-container,
.page-fixed .body-container {
    min-height: 100dvh;
    height: auto;
}

.page-fixed .body-container {
    overflow: hidden;
    height: 100dvh;
    min-height: 0;
}

.page-fixed .body-container {
    padding-bottom: 32px;
    box-sizing: border-box;
}

/* Layout rules that vertically center against the viewport read from
   var(--simulated-vh). Default = the real dvh; restricted mode pins it to
   959px so Alt+H matches what a true FullHD window would render. */
:root {
    --simulated-vh: 100dvh;
}

.body-container.restricted {
    max-width: 1920px;
    width: 1920px;
    min-height: 0;
    margin: 0;
    overflow: auto;
    background-color: var(--background);

    position: relative;
    top: 0;
    left: 0;
}

.body-container.restricted--optimistic {
    --simulated-vh: 959px;
    max-height: 959px;
    height: 959px;
}

.body-container.restricted--conservative {
    --simulated-vh: 929px;
    max-height: 929px;
    height: 929px;
}

/* The .page-main / .page-fixed selectors above force min-height: 100dvh and
   (for page-fixed) height: 100dvh, which would otherwise win against the
   restricted cap. Override them so Alt+H actually clamps to FullHD. */
.page-main .body-container.restricted--optimistic,
.page-fixed .body-container.restricted--optimistic {
    min-height: 0;
    height: 959px;
}

.page-main .body-container.restricted--conservative,
.page-fixed .body-container.restricted--conservative {
    min-height: 0;
    height: 929px;
}

/* --------------- HEADER --------------- */

.header {
    background: linear-gradient(to right, var(--gradient-dark), var(--gradient-light));
    padding: 18px 70px;
    display: flex;
    flex-direction: column;
    height: auto;
}

.header__top {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.header__bottom {
    display: flex;
    justify-content: space-between;

    margin-top: 10px;

    padding-left: 55px;
    padding-right: 55px;
    padding-bottom: 30px;
}

.page-main .header__bottom {
    padding-bottom: 0;
}

.header__content {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.header__logo, .header__university-logo {
    height: 60px;
    width: auto;
}

.header__university-logo {
    cursor: pointer;
}

.header__subtitle {
    color: white;
    font-size: 1rem;
    font-style: italic;
    cursor: default;
}

.header__user-info {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    color: white;
}

.header__user-email {
    font-size: 1rem;
    cursor: default;
}

/* Action buttons */
.back-wrapper, .logout-wrapper {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 1.1rem;
    color: var(--button-blue);
    cursor: pointer;
    transition: color 0.2s;
}

.header-left {
    display: flex;
    align-items: center;
    gap: 8px;
}

.header-right {
    display: flex;
    align-items: center;
    gap: 16px;
}

.language-selector select {
    background-color: transparent;
    color: white;
    border: 1px solid rgba(255, 255, 255, 0.4);
    border-radius: 6px;
    padding: 6px 10px;
    font-size: 14px;
    cursor: pointer;
}

.language-selector select:hover {
    border-color: white;
}

.language-selector option {
    color: black;
}

.page-title {
    color: var(--button-blue);
    font-size: 1.5rem;
    font-weight: 600;
    margin-left: 50px;
    margin-right: 50px;
}

.back-wrapper:hover, .logout-wrapper:hover {
    color: var(--button-blue-hover);
}

#backButton, #logoutButton {
    position: relative;
    display: inline-flex; /* or flex if it already is */
    z-index: 1;
}

#backButton::before, #logoutButton::before {
    content: "";
    position: absolute;
    top: -12px;
    bottom: -12px;
    left: -16px;
    right: -16px;
    z-index: -1; /* stay behind actual content */
}

#backButton, #logoutButton {
    visibility: hidden;
}

/* --------------- LOGIN SCREEN --------------- */

#loginScreen {
    margin-top: max(0px, calc((var(--simulated-vh) - 750px) / 3));
}

button {
    width: auto;
    padding: 8px;
    background-color: #007BFF;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}
/* Suppress the black square focus outline on mouse clicks for every
   button. Keyboard-focus (:focus-visible) still gets a visible blue
   ring so we don't break accessibility. Individual buttons can override
   the :focus-visible style if they need a custom one. */
button:focus { outline: none; }
button:focus-visible {
    outline: 2px solid var(--button-blue);
    outline-offset: 2px;
}

/* Form alignment */
form#loginForm {
    margin: 0 auto;
    max-width: 576px;
    text-align: center;
}

/* Labels */
form#loginForm label {
    display: block;
    text-align: center;
    font-weight: 500;
    color: var(--button-blue);
    font-size: 1.8rem;
    margin-top: 20px;
    margin-bottom: 5px;
}

/* Inputs */
form#loginForm input.form-control {
    height: 80px;
    font-size: 1.1rem;
    border-radius: 8px;
    text-align: left;
    padding-left: 20px;
    border: 1px solid var(--table-border-grey);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
}

/* Password visibility toggle wrapper */
.login-input-wrapper {
    position: relative;
}

.login-input-wrapper input[type="password"],
.login-input-wrapper input[type="text"] {
    padding-right: 60px; /* space for the icon */
}

/* Eye icon */
.password-toggle {
    position: absolute;
    top: 50%;
    right: -32px;
    transform: translateY(-50%);
    cursor: pointer;
    color: var(--dark-grey);
    font-size: 1rem;
}

/* On phones the input nearly hits the screen edge, so the desktop
   "park the icon 32px outside the input" trick puts the icon off-screen.
   Bring it inside the input instead (input already reserves 60px of
   right padding for it). */
@media (max-width: 576px) {
    .password-toggle {
        right: 16px;
    }
}

.password-toggle::after {
    content: ''; /* No text content */
    position: absolute;
    top: -20px; /* Expand hitbox above the icon */
    left: -20px; /* Expand hitbox to the left of the icon */
    right: -20px; /* Expand hitbox to the right of the icon */
    bottom: -20px; /* Expand hitbox below the icon */
    background: transparent; /* No background */
    z-index: -1; /* Place it behind the icon */
}

/* Button */
#loginButton, #registerButton, #editProfileButton, #sendLinkButton, #changePasswordButton {
    margin-top: 60px;
    background-color: var(--button-blue);
    border: none;
    font-size: 1.5rem;
    font-weight: bold;
    border-radius: 8px;
    padding: 0.8rem;
    height: 75px;
    width: 300px;
    display: block;
    margin-left: auto;
    margin-right: auto;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

#sendLinkButton, #changePasswordButton {
    margin-top: 32px;
    font-size: 1.1rem;
    height: 50px;
    width: 220px;
    padding: 0.5rem;
}

.forgot-password-sent-message {
    max-width: 480px;
    margin: 0 auto 24px;
    text-align: center;
    color: #444;
    font-size: 1rem;
}

/* --------------- LEGAL ACCEPTANCE MODAL --------------- */

.legal-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9000;
    padding: 16px;
}

.legal-modal {
    background: #e6ecf4;
    border-radius: 12px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    width: min(960px, 100%);
    height: min(95vh, 100%);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.legal-modal__header {
    padding: 24px 32px 16px;
    border-bottom: 1px solid #e7e7e7;
}

.legal-modal__title {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--button-blue);
    margin-bottom: 8px;
}

.legal-modal__subtitle {
    color: #444;
    font-size: 1rem;
    margin-bottom: 12px;
}

.legal-modal__meta {
    color: #666;
    font-size: 0.9rem;
}

.legal-modal__version {
    margin-left: 8px;
    opacity: 0.75;
}

.legal-modal__body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 16px 32px;
    color: #111;
    line-height: 1.55;
}

.legal-modal__section {
    margin-bottom: 28px;
}

.legal-modal__section h2 {
    font-size: 1.7rem;
    font-weight: 700;
    color: var(--button-blue);
    margin-top: 0;
    margin-bottom: 14px;
    border-bottom: 1px solid rgba(22, 102, 176, 0.25);
    padding-bottom: 8px;
}

.legal-modal__content h4 {
    margin-top: 14px;
    margin-bottom: 6px;
    font-size: 1rem;
}

.legal-modal__footer {
    padding: 16px 32px 24px;
    border-top: 1px solid #cfd6e0;
    background: #dbe2ec;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.legal-modal__check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 0.95rem;
    color: #222;
    cursor: pointer;
    margin: 0;
    transition: opacity 0.15s ease;
}

.legal-modal__check input {
    margin-top: 3px;
    flex: 0 0 auto;
}

.legal-modal__check:has(input:disabled) {
    opacity: 0.45;
    cursor: not-allowed;
}

.legal-modal__check input:disabled {
    cursor: not-allowed;
}

.legal-modal__error {
    color: #b00020;
    font-size: 0.9rem;
}

.legal-modal__buttons {
    align-self: flex-end;
    margin-top: 6px;
    display: flex;
    gap: 12px;
    align-items: center;
}

.legal-modal__submit {
    background-color: var(--button-blue);
    color: white;
    border: none;
    border-radius: 8px;
    padding: 10px 28px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
    transition: background-color 0.15s ease, opacity 0.15s ease;
}

.legal-modal__submit:hover:not(:disabled) {
    background-color: var(--button-blue-hover);
}

.legal-modal__submit:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.legal-modal__reject {
    background-color: transparent;
    color: #555;
    border: 1px solid #c0c8d3;
    border-radius: 8px;
    padding: 10px 22px;
    font-size: 1rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.legal-modal__reject:hover {
    background-color: rgba(0, 0, 0, 0.06);
    color: #333;
}

@media (max-width: 576px) {
    .legal-modal {
        height: 100%;
        border-radius: 0;
    }

    .legal-modal__header,
    .legal-modal__body,
    .legal-modal__footer {
        padding-left: 16px;
        padding-right: 16px;
    }

    .legal-modal__buttons {
        align-self: stretch;
        flex-direction: column-reverse;
    }

    .legal-modal__submit,
    .legal-modal__reject {
        width: 100%;
    }
}

/* The .is-invalid input is nested inside .login-input-wrapper, so the default
   Bootstrap sibling selector for .invalid-feedback never matches. Reveal the
   feedback whenever any descendant of the form-group is marked invalid. */
.form-group:has(.is-invalid) > .invalid-feedback {
    display: block;
}

/* Edit-profile country dropdown row: select + live-updating flag.
   The select keeps its full-width behavior; the flag sits to its right
   and never participates in form layout (flex: 0 0 auto + a fixed
   height). The whole row uses align-items: stretch so the flag's slot
   matches the select's height; aspect-ratio derives width. */
.country-row {
    display: flex;
    align-items: center;
    gap: 10px;
}
.country-row > .form-control {
    flex: 1 1 auto;
    min-width: 0;
}
.country-row > .country-flag {
    flex: 0 0 auto;
    height: 28px;
    aspect-ratio: 4 / 3;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.10);
    display: block;
}
.country-row > .country-flag[hidden] {
    display: none;
}

#deleteAccountButton {
    margin-top: 90px;
    background-color: #980101;
    border: none;
    font-size: 1rem;
    border-radius: 8px;
    padding: 0.8rem;
    height: 75px;
    width: 150px;
    display: block;
    margin-left: auto;
    margin-right: auto;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

#loginButton:hover {
    background-color: var(--button-blue-hover);
}

.forgot-password {
    text-align: center;
    margin-top: 20px;
    font-size: 1rem;
}

.forgot-password a {
    color: var(--button-blue);
    font-weight: 600;
    font-size: 0.9rem;
}

/* Create account section */
.create-account {
    text-align: center;
    margin-top: 30px;
    font-size: 1rem;
}

.create-account a {
    color: var(--button-blue);
    font-weight: 600;
}

/* Checkbox testing container */
#testingContainer {
    text-align: left;
}

/* --------------- MAIN NEW --------------- */

.profile-card {
    background-color: var(--text-background);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
    width: 350px;

    display: flex;
    flex-direction: column;
}

.profile-card__top {
    background: var(--button-blue);
    color: white;
    text-align: center;
    padding: 1.5rem;
    flex-shrink: 0;

    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: center;
}

.profile-card__photo {
    width: 150px;
    height: 150px;
    border-radius: 6px;
    object-fit: cover;
    margin-bottom: 1rem;
    cursor: pointer;
}

.profile-card__name-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 0.5rem;
    justify-content: center;
}

.profile-card__name {
    font-size: 1rem;
}

.profile-card__edit-btn {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
}

.profile-card__role {
    font-weight: bold;
    color: white;
    margin-bottom: 0.75rem;
}

.profile-card__stats {
    padding: 1.5rem;
    font-size: 1rem;
    background-color: var(--text-background);
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.profile-card__stats h4 {
    margin-top: 0;
    font-size: 1rem;
}

/* New grid layout for stats */
.stats-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: center;
}

.stat {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 12px;
    align-items: center;
    justify-content: start;
    width: 100%;
    max-width: 320px;
}

/* Replaces old flex-based .stat style */
.stat i {
    justify-self: start;
    color: var(--button-blue);
    font-size: 1rem;
}

.stat-label {
    justify-self: start;
    font-weight: 500;
    color: #333;
}

.stat-value {
    justify-self: start;
    font-weight: bold;
    color: #111;
}

.dashboard-container {
    display: flex;
    gap: 40px;
    padding: 40px 40px;
    max-width: 1200px;
    margin: max(0px, calc((var(--simulated-vh) - 950px) / 3)) auto 0;
}

.action-menu {
    display: flex;
    flex-direction: column;
    gap: 20px;
    flex: 1;
    max-width: 600px;
}

/* Action buttons */
.action-button {
    background-color: var(--text-background);
    border-radius: 14px;
    padding: 1.5rem;
    display: flex;
    align-items: center;
    gap: 1rem;
    cursor: pointer;
    transition: background-color 0.2s ease;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);

    width: 300px;
}

.action-button:hover {
    background-color: var(--text-background-hover);
}

.action-button i {
    font-size: 1.4rem;
    color: var(--icon-blue);
    min-width: 24px;
    text-align: center;
}

.action-button .title {
    font-weight: 600;
    font-size: 1.1rem;
}

.action-button .subtitle {
    font-size: 0.9rem;
    color: #666;
}

/* --------------- EXPANDABLE TABLE --------------- */

.main-layout-button-row {
    width: 94%;
    margin: 0 auto 8px;
}

.table-scroll {
    flex: 1;
    overflow-y: scroll;
    max-height: 100vh;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1)
}

/* Table Styles */
.table-container {
    width: 100%;
    table-layout: fixed;

    border-collapse: separate;
    border-spacing: 0;
}

tr.table-row.selected {
    background-color: var(--text-background-hover);
}

.table-container .even-row {
    background-color: var(--text-background);
}
.table-container .odd-row {
    background-color: var(--text-background-2);
}

.expanded-row {
    display: none;
}

.filter-row input {
    width: 100%;
    background: none;
    border: none;
}

.filter-row input:focus {
    outline: none;
    box-shadow: none;
}

/* Styling for the button row above the table */
.table-button-row {
    display: flex;
    justify-content: flex-start;
    gap: 10px;
    margin-bottom: 20px;
}

/* Button Styling */
.table-button-row button {
    background-color: var(--button-blue);
    color: white;
    border: none;
    padding: 10px 20px;
    font-size: 16px;
    cursor: pointer;
    border-radius: 5px;
    max-width: fit-content;
}

.table-button-row button:hover {
    background-color: var(--button-blue-hover);
}


/* --------------- TREE --------------- */

.columns-container {
    flex: 1;
    min-height: 0;

    width: 94%;
    margin: 0 auto;

    display: flex;
    flex-direction: row;

    gap: 20px;
}

.tree-container {
    flex: 1;
    min-height: 0;

    width: 94%;
    margin: 0 auto;

    display: flex;
    flex-direction: column;
}

.tree-scroll {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    padding-right: 12px;
}

.section-body .tree-scroll {
    box-shadow: none;
}

.tree-root, .tree-root ul {
    list-style-type: none;
    padding-left: 0;
    margin: 0;
}

.tree-node {
    margin: 0;
    padding: 0;
    border-left: 2px solid #ccc;
}

.tree-label {
    display: flex;
    align-items: center;
    padding: 6px 12px;
    margin: 4px 0;
    background-color: #f9f9f9;
    border: 1px solid var(--table-border-grey);
    cursor: pointer;
    font-weight: bold;
    transition: background-color 0.2s ease;
}

.tree-leaf-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
}

.tree-leaf-table td:has(.icon-sprite) {
    vertical-align: middle;
    text-align: center;
}

.rc-card.tree-filters {
    display: flex;
    gap: 12px;
    flex: none;
}

.tree-filter-input {
    margin-bottom: 12px;
    border: 1px solid var(--table-border-grey);
}

.tree-section-title {
    text-align: center;
}

/* --------------- PROFILE --------------- */

.profile-container {
    width: 60%;
    margin: 0 auto;
    margin-top: 16px;
    border: 1px solid #ddd;
    background-color: #f9f9f9;
    padding: 16px;
    border-radius: 6px;
}

.profile-title {
    text-align: center;
    font-weight: bold;
    font-size: 1.4rem;
    margin-bottom: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 40px;
    border-bottom: 1px solid #ccc;
}

.profile-content {
    display: flex;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
}

.profile-left {
    flex: 1;
    min-width: 250px;
}

.profile-right {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 200px;
}

.profile-name {
    font-size: 1.2rem;
    font-weight: bold;
    margin-bottom: 12px;
}

.profile-statistics {
    background-color: #f9f9f9;
    border: 1px solid #ddd;
    padding: 12px;
    border-radius: 8px;
}

.profile-subtitle {
    font-weight: bold;
    margin-bottom: 8px;
    font-size: 1rem;
}

.profile-stat {
    margin: 4px 0;
    font-size: 0.95rem;
}

.profile-picture {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    border: 1px solid #ccc;
    object-fit: cover;
    margin-bottom: 12px;
}

.profile-role {
    font-weight: bold;
    color: #555;
    font-size: 1rem;
}

/* --------------- REPORT CONFIGURATION --------------- */

.page-content {
    display: flex;
    flex-direction: column;

    width: 94%;
    margin: 0 auto;
    box-sizing: border-box;

    gap: 20px;

    padding-bottom: 32px;
}

.report-config-layout {
    max-width: 60%;
}

.legal-layout {
    max-width: 60%;
}

@media (max-width: 768px) {
    .legal-layout {
        max-width: 94%;
    }
}

.rc-logo {
    max-width: 200px;
    height: 70px;
    border-radius: 6px;
    object-fit: cover;
    cursor: pointer;
}

.rc-row-top {
    display: flex;
    flex-direction: row;
    gap: 20px;
    flex: 0 0 auto;
}

.rc-row-bottom {
    display: flex;
    flex-direction: row;
    gap: 20px;
    flex: 1 1 auto;
    min-height: 0;
}

.rc-card {
    background: var(--card-background);
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    padding: 25px 30px;
    flex: 1 1 0;
    box-sizing: border-box;
    min-width: 0;
}

.rc-card__title {
    color: var(--button-blue);
    font-size: 1.4rem;
    font-weight: 600;
    margin-bottom: 20px;
}

/* shared base */
.rc-row,
.rc-row--col {
    display: flex;
    margin-bottom: 10px;
    gap: 12px;
}

.rc-row--col {
    flex-direction: column;
    align-items: stretch;
}

.rc-row {
    align-items: center;
    justify-content: space-between;
}

/* shared child styles */
.rc-row label,
.rc-row--col label {
    font-weight: 500;
    margin-bottom: 0;
}

.rc-row strong,
.rc-row--col strong {
    margin-bottom: 0;
}

.rc-row input,
.rc-row select,
.rc-row button,
.rc-row--col input,
.rc-row--col select,
.rc-row--col button {
    padding: 6px 10px;
    font-size: 1rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    height: auto;
    box-sizing: border-box;
}

/* rc-row specific layout */
.rc-row label {
    flex: 1;
    max-width: 150px;
}

/* The rc-row label rule above is for the leading field label only -
   override it for the radio-option labels inside a toggle group so each
   option sizes to its own span (text + padding) instead of being padded
   out to 150px. Without this, the colored fill on the selected option
   only covers the span while the rest of the label-box stays white,
   making a 3-option group read as 5 segments. */
.rc-row .rc-toggle-option {
    flex: 0 0 auto;
    max-width: none;
}

/* Indent only the label, keep input aligned with the parent row above */
.rc-row--child > label {
    padding-left: 20px;
    box-sizing: border-box;
}

.rc-row strong {
    flex: 1;
    max-width: 100px;
}

.rc-row button {
    flex: auto;
}

.rc-row input,
.rc-row select {
    min-width: 200px;
    flex: 1;
}

/* rc-row--col specific */
.rc-row--col textarea,
.rc-card > textarea {
    width: 100%;
    padding: 6px 10px;
    font-size: 1rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box;
    resize: vertical;
    font-family: inherit;
}

.rc-toggle-group {
    display: flex;
    border: 1px solid #ccc;
    border-radius: 4px;
    overflow: hidden;
    width: fit-content;
}

.rc-row .rc-toggle-group {
    margin-right: auto;
}

.rc-toggle-option {
    display: flex;
    cursor: pointer;
    margin-bottom: 0;
    font-weight: normal;
    max-width: none;
}

.rc-toggle-option:not(:last-child) {
    border-right: 1px solid #ccc;
}

.rc-toggle-option input[type="radio"] {
    display: none;
}

.rc-toggle-option > span {
    padding: 5px 16px;
    font-size: 0.9rem;
    user-select: none;
    background: white;
    color: #666;
    transition: background 0.15s, color 0.15s;
}

.rc-toggle-option input[type="radio"]:checked + span {
    background: var(--button-blue);
    color: white;
}

.rc-checkbox-group {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px 16px;
    margin-top: 6px;
}

.rc-checkbox-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: normal;
    margin-bottom: 0;
    cursor: pointer;
    font-size: 0.95rem;
}

.rc-checkbox-item input[type="checkbox"] {
    margin: 0;
    cursor: pointer;
    flex-shrink: 0;
}

.rc-row input:disabled {
    background: #f0f0f0;
    color: var(--dark-grey);
}

.rc-button {
    background: var(--button-blue);
    color: #fff;
    border: none;
    padding: 8px 16px;
    cursor: pointer;
    border-radius: 4px;
    font-weight: 600;
    font-size: 1rem;
}

button:disabled {
    background: #ccc;
    color: #666;
    border-color: #aaa;
    opacity: 0.7;
    cursor: default;
}

button:disabled:hover {
    background: #ccc;
}

.rc-button-white {
    background: #fff;
    color: var(--button-blue);
    border: none;
    padding: 8px 16px;
    cursor: pointer;
    border-radius: 4px;
    font-weight: 600;
    font-size: 1rem;
}

.rc-button:hover {
    background: var(--button-blue-hover);
}

.rc-button:focus {
    outline: none;
    box-shadow: none;
}


.rc-overlay-wrapper {
    position: relative;
}

.rc-advanced-separator {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 4px;
    background: transparent;
    cursor: pointer;
    font-weight: 500;
    color: #555;
    font-size: 1rem;
    user-select: none;
}

.rc-advanced-separator:hover {
    color: #333;
}

.rc-advanced-chevron {
    font-size: 0.75rem;
    color: #777;
    transition: transform 0.2s;
    flex-shrink: 0;
}

.rc-advanced-chevron--open {
    transform: rotate(90deg);
}

.rc-advanced-line {
    flex: 1;
    height: 2px;
    background: #ccc;
}

.rc-advanced-section {
    flex-direction: column;
    gap: 20px;
}

.rc-card-tree-scroll {
    overflow-y: auto;
    max-height: 300px;
    min-height: 60px;
    padding-right: 4px;
}

/* ---- Teacher reports list (student-reports.html / student_reports.js) ---- */
.sr2-action-row {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.sr2-filter-pills {
    margin-left: 32px;
}
/* Filter pills + sort always sit on their own row below the action buttons
   (basis: 100% guarantees a wrap on the teacher page; on my-reports the
   group is the only row content anyway). The sort wrapper inside uses its
   base `margin-left: auto` rule, so net result: filters left, sort right. */
.sr2-filter-sort-group {
    display: flex;
    align-items: center;
    gap: 24px;
    flex: 1 1 100%;
    flex-wrap: nowrap;
}
.sr2-filter-sort-group .sr2-filter-pills {
    margin-left: 0;
}

/* Filter pills: icon hidden by default (text-only labels). At narrow
   widths the icon swaps in and the text labels (other than "All") hide
   so the pill row collapses to icon-only. */
.sr2-filter-icon {
    display: none;
    margin-right: 6px;
}
@media (max-width: 600px) {
    .sr2-filter-pills .sr2-filter-icon {
        display: inline-block;
        margin-right: 0;
    }
    .sr2-filter-pills .rc-toggle-option:not(:first-child) .sr2-filter-text {
        display: none;
    }
    /* Hide the "Sort by:" label too — saves ~70px so the icon-only filter
       row still fits beside the sort select on phones. */
    .sr2-filter-sort-group .sr2-sort-label {
        display: none;
    }
    /* Let the sort select shrink instead of overflowing the container:
       <select> defaults to the width of its longest option, and the row
       has flex-wrap: nowrap so the overflow was leaking past page-content. */
    .sr2-filter-sort-group,
    .sr2-sort-wrapper {
        min-width: 0;
    }
    .sr2-sort-select {
        min-width: 0;
        max-width: 100%;
    }
}

.sr2-sort-wrapper {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 8px;
    color: #555;
    font-size: 0.95rem;
}
.sr2-sort-select {
    padding: 6px 10px;
    font-size: 0.95rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    background: white;
}

.sr2-cards-wrapper {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 8px 0;
}

.sr2-card {
    position: relative;
    display: grid;
    /* 4-col shell shared by teacher v2 and my-reports.
       Last column is fixed-width (not auto) so the result-group divider
       sits at the same x across cards regardless of report type. */
    grid-template-columns: 72px 1.4fr 2fr 280px;
    align-items: center;
    gap: 16px;
    padding: 16px;
    background: white;
    border: 1px solid #e2e6ea;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(15,23,42,0.08);
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.sr2-card--selected {
    border-color: var(--button-blue, #2f6fed);
    box-shadow: 0 0 0 1px var(--button-blue, #2f6fed) inset;
}
/* "Loading more students…" row used by the student-activity dashboard while
   the chunked metric calls are still in flight. Mirrors the .sr2-card--create
   dashed look but is thinner and not interactive. */
.sa-loading-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 10px;
    border: 2px dashed #c0c8d0;
    background: #fafbfc;
    color: #666;
    padding: 6px 16px;
    font-weight: 500;
    font-size: 0.9rem;
    border-radius: 8px;
    margin-bottom: 8px;
}
.sa-loading-spinner {
    color: var(--button-blue, #2f6fed);
    font-size: 0.95rem;
}

/* Wrapper that lays the two "Create new report" cards (full config + guided)
   side-by-side. Each card takes equal width and wraps on narrow viewports. */
.sr2-create-row {
    display: flex;
    flex-direction: row;
    gap: 12px;
    flex-wrap: wrap;
}
.sr2-create-row > .sr2-card--create {
    flex: 1 1 240px;
    min-width: 0;
}

.sr2-card--create-guided {
    border-color: #b8c4d8;
    background: #f3f7ff;
    color: #3a4a66;
}
.sr2-card--create-guided:hover {
    border-color: var(--button-blue);
    color: var(--button-blue);
}

/* "Create new report" affordance — a dashed-border card that sits at the
   top of the list and opens report config on click. Overrides the base
   .sr2-card grid layout with a centered flex row. */
.sr2-card--create {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 12px;
    border-style: dashed;
    border-width: 2px;
    border-color: #c0c8d0;
    background: #fafbfc;
    box-shadow: none;
    color: #666;
    cursor: pointer;
    padding: 8px 16px;
    font-weight: 500;
    font-size: 1rem;
}
.sr2-card--create:hover {
    border-color: var(--button-blue);
    color: var(--button-blue);
    box-shadow: none;
    transform: translateY(-1px);
}
.sr2-create-icon {
    font-size: 1.1rem;
}

/* Finished cards look identical to active ones — only the green FINISHED
   pill in the right column distinguishes them. */

.sr2-type-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-width: 56px;
    align-self: stretch;
    /* Vertical divider after the type column so the icon/label feels like
       a card index rather than the first metric. Used by both teacher v2
       and my-reports. */
    border-right: 1px solid #d8dde3;
    padding-right: 8px;
}
.sr2-type-icon {
    font-size: 1.3rem;
    color: #555;
}
.sr2-type-label {
    font-size: 0.8rem;
    font-weight: 500;
    color: #666;
    text-transform: capitalize;
}
.sr2-type-id {
    font-size: 0.7rem;
    color: #999;
}

.sr2-title-block {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.sr2-title {
    font-weight: 600;
    color: #222;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sr2-subtitle {
    font-size: 0.85rem;
    color: #777;
}

/* Shared by both pages. The 3-up tracks line up across cards (justify-items
   center), and the trailing padding-right gives the "metric group" breathing
   room before the result-group's left divider. */
.sr2-metric-area {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    align-items: stretch;
    justify-items: start;
    gap: 12px;
    padding-right: 32px;
}
.sr2-metric-area > .sr2-cell {
    justify-content: start;
}
.sr2-metric {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.95rem;
}
.sr2-metric-icon {
    color: #555;
    font-size: 1.1rem;
    width: 1.25em;
    flex: 0 0 1.25em;
    text-align: center;
}
.sr2-metric-icon--enrolled   { color: #1666b0; }
.sr2-metric-icon--passed   { color: #16a34a; }
.sr2-metric-icon--pending    { color: #ca8a04; }
.sr2-metric-icon--incomplete { color: #ea580c; }
.sr2-metric-icon--failed     { color: #dc2626; }
.sr2-metric-label {
    color: #666;
    text-transform: capitalize;
}
.sr2-metric-value {
    font-weight: 600;
    color: #222;
}

.sr2-podium-slot {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.95rem;
}
.sr2-trophy { font-size: 1.1rem; }
.sr2-trophy--gold   { color: #d4a017; }
.sr2-trophy--silver { color: #9aa0a6; }
.sr2-trophy--bronze { color: #b87333; }
.sr2-podium-name {
    color: #222;
    font-weight: 600;
}

.sr2-right-col {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    min-width: 110px;
}
.sr2-dates {
    font-size: 0.8rem;
    color: #777;
    line-height: 1.3;
    text-align: right;
}
.sr2-finished-pill {
    background: var(--button-blue);
    color: white;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 2px 10px;
    border-radius: 12px;
    letter-spacing: 0.5px;
}
.sr2-inactive-pill {
    background: #6b7280;
    color: white;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 2px 10px;
    border-radius: 12px;
    letter-spacing: 0.5px;
}

.sr2-gear-btn,
.sr2-mail-btn {
    background: transparent;
    border: none;
    cursor: pointer;
    color: #888;
    font-size: 1.1rem;
    padding: 8px;
    border-radius: 6px;
    line-height: 1;
    /* Centers the icon when the button is sized to the action cell. */
    display: flex;
    align-items: center;
    justify-content: center;
}
.sr2-gear-btn:hover,
.sr2-mail-btn:hover {
    color: #333;
    background: #eef0f3;
}
/* Disabled state: native `:disabled` selector. Suppresses hover entirely
   (no background change) and drops the icon to a faint grey so it reads
   as "off" at a glance. */
.sr2-mail-btn:disabled,
.sr2-mail-btn:disabled:hover {
    color: #d1d5db;
    background: transparent;
    cursor: not-allowed;
}

/* my-reports self-send mail button: a direct sibling of the score cell and
   rightCol inside the result-group. Inherits size + colors from the shared
   `.sr2-mail-btn` rule so it matches the teacher row's mail icon exactly. */
.sr2-result-group > .mr-mail-btn {
    flex: 0 0 auto;
    align-self: center;
}

/* my-reports cards rebalance the parent grid + result-group internals so
   the three siblings (score / dates / mail) sit with even spacing.
   Teacher cards (.sr2-card without .mr-card) keep their original layout. */
.sr2-card.mr-card {
    /* Trim the metric track from 2fr to 1.4fr and grow the result-group
       column from 280 to 320 so [score | dates | mail] doesn't crowd. */
    grid-template-columns: 72px 1.4fr 1.4fr 320px;
}
.sr2-card.mr-card > .sr2-result-group {
    /* The 32px padding-left was the "margin-left" pushing things off the
       row; tighten it (the divider still sits at this offset). */
    padding-left: 16px;
    /* With three flex items at fixed/intrinsic widths, space-between
       distributes slack as two equal gaps. */
    justify-content: space-between;
}
.sr2-card.mr-card .sr2-result-group .sr2-right-col {
    /* Don't right-align the dates inside their slot — center so the
       gap-to-score and gap-to-mail look symmetric. Drop the flex floor
       so the column sizes to its content. */
    align-items: center;
    min-width: 0;
}
.sr2-card.mr-card .sr2-result-group .sr2-dates {
    text-align: center;
}

/* Stacked action buttons on the right of teacher v2 cards (gear above mail).
   Occupies the same fixed-width slot as my-reports' score cell. The
   `margin-left: auto` pushes the cell to the far right of the result-group,
   absorbing any slack so the icons hug the card's right edge while the
   divider and dates stay where they are. */
.sr2-action-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    align-self: stretch;
    margin-left: auto;
}

/* my-reports has no Add / Send buttons preceding the filter pills, so drop
   the 32px left margin that sr2 uses to separate them from those buttons. */
.mr-action-row .sr2-filter-pills {
    margin-left: 0;
}

/* ============== Result group (teacher v2 + my-reports) ============== */
/* The "result side" of the card: a fixed-width cell (score pill on
   my-reports, gear button on teacher v2) followed by the dates/finished
   column. The divider on its left, and the consistent 110px first-child
   width, make the boundary land at the same x across every card type. */
.sr2-result-group {
    display: flex;
    align-items: center;
    gap: 12px;
    border-left: 1px solid #d8dde3;
    padding-left: 32px;
    align-self: stretch;
}
/* Pin the result-side action/score cell to a fixed width regardless of where
   it sits in the result-group order: my-reports puts the score cell first
   (score | dates), teacher v2 puts the action stack last (dates | actions). */
.sr2-result-group > .sr2-cell--score,
.sr2-result-group > .sr2-action-cell {
    flex: 0 0 110px;
}

/* ============== my-reports (student-side) ============== */
/* Generic cell wrapper — flex-centers its content (a pill, a stacked
   double-pill, a rank-cell, or a sr2-metric / podium-slot tile) inside
   its grid track. Used by both pages. */
.sr2-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
    width: 100%;
}
.sr2-result-group .sr2-cell {
    width: auto;
}

/* Pass-2 loading spinner: a single cell spans all three metric columns
   so the spinner is centered horizontally in the metric area. */
.sr2-cell--loading {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
}
.sr2-metric-spinner {
    font-size: 24px;
    color: #888;
    opacity: 0.7;
}
.sr2-metric-progress {
    font-size: 13px;
    color: #888;
    font-variant-numeric: tabular-nums;
    min-width: 5ch;
    text-align: left;
}

.mr-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
}
.mr-pill--small {
    padding: 5px 12px;
    font-size: 0.8rem;
}
.mr-pill-label {
    font-weight: 500;
    opacity: 0.85;
}
.mr-pill-value {
    font-weight: 700;
}
.mr-pill-icon {
    font-size: 0.85em;
}

.mr-pill--green   { background: #16a34a; color: #ffffff; }
.mr-pill--yellow  { background: #ffca00; color: #111111; }
.mr-pill--red     { background: #dc2626; color: #ffffff; }
.mr-pill--neutral { background: #64748b; color: #ffffff; }

.mr-double-pill {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.mr-rank-cell {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 1rem;
    font-weight: 700;
    color: #222;
}
.mr-rank-icon { font-size: 1.3rem; line-height: 1; }
/* Result-side score pill is bigger than the metric pills (1rem vs 0.8rem)
   so the final number stands out as the card's headline. */
.sr2-result-group .sr2-cell--score .mr-pill {
    font-size: 1rem;
}
.mr-rank-icon--gold    { color: #d4a017; }
.mr-rank-icon--silver  { color: #9aa0a6; }
.mr-rank-icon--bronze  { color: #b87333; }
.mr-rank-icon--default { color: #222; }


/* ---- Mobile / narrow-viewport layout (teacher v2 + my-reports) ----
   Below 992px the card splits into two rows. The desktop 4-col layout
   needs ~1000px to fit the type col (96px) + result group (280px) +
   gaps + a usable 2fr metric track without pills overlapping the title;
   below that we drop to the stacked layout.
     row 1: type | title | dates+finished
     row 2: metrics | score-or-gear
   Only two dividers: a single full-width horizontal line between the rows
   (drawn with a 1px grid row + ::before pseudo so it spans across the
   column gaps without breaks), and a vertical line separating metrics
   from the result cell. */
@media (max-width: 992px) {
    .sr2-card {
        grid-template-columns: 60px 1fr auto;
        grid-template-rows: auto 1px auto;
        grid-template-areas:
            "type    title    dates"
            "rule    rule     rule"
            "metrics metrics  score";
        row-gap: 12px;
        column-gap: 12px;
        padding: 12px 16px;
    }
    .sr2-card::before {
        content: "";
        grid-area: rule;
        background: #d8dde3;
        height: 1px;
        align-self: stretch;
    }
    .sr2-card .sr2-type-col {
        grid-area: type;
        border-right: none;
        padding-right: 0;
        align-self: stretch;
        justify-content: center;
        min-width: 0;
    }
    .sr2-card .sr2-title-block {
        grid-area: title;
    }
    /* `display: contents` makes the result-group's children (score-or-gear
       cell + dates column) become direct grid items, so they can land in
       different rows. */
    .sr2-card .sr2-result-group {
        display: contents;
    }
    .sr2-card .sr2-result-group .sr2-right-col {
        grid-area: dates;
    }
    .sr2-card .sr2-result-group > .sr2-cell--score,
    .sr2-card .sr2-result-group > .sr2-action-cell {
        grid-area: score;
        flex: 0 0 auto;
        /* stretch so the border-left spans the full row height (taller on
           ranking rows because of the stacked SEN/SPE pills); flex centering
           still keeps the score pill / action stack vertically centered. */
        align-self: stretch;
        border-left: 1px solid #d8dde3;
        padding-left: 16px;
    }
    .sr2-card .sr2-metric-area {
        grid-area: metrics;
        padding-right: 0;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
        width: fit-content;
        margin-left: auto;
        margin-right: auto;
    }
    /* my-reports cards on mobile: stack the score pill and the dates +
       finished pill in the same right-hand column to free row 1 for the
       mail icon. Result reads as [type | title | mail] over [metrics |
       score+dates], with the divider running continuously through both
       score and dates rows. Scoped to .mr-card so teacher reports keep
       their 3-column mobile shape (dates in row 1). */
    .sr2-card.mr-card {
        grid-template-columns: 60px 1fr auto;
        grid-template-rows: auto auto auto auto;
        grid-template-areas:
            "type    title    mail"
            "rule    rule     rule"
            "metrics metrics  score"
            "metrics metrics  dates";
        row-gap: 0;
        column-gap: 12px;
    }
    /* Recreate the 12px breathing room above and below the rule via
       margins on the pseudo-element, since row-gap is zero (we want
       score and dates flush against each other). */
    .sr2-card.mr-card::before {
        margin: 12px 0;
    }
    /* Right-col (dates + finished pill) now lives in row 4 of the right
       column, directly under the score pill, sharing the same left
       divider. Center-align so it stacks tidily under the pill. */
    .sr2-card.mr-card .sr2-result-group .sr2-right-col {
        grid-area: dates;
        align-items: center;
        align-self: stretch;
        border-left: 1px solid #d8dde3;
        padding-left: 16px;
        padding-top: 4px;
    }
    .sr2-card.mr-card .sr2-result-group .sr2-dates {
        text-align: center;
    }
    .sr2-card.mr-card .sr2-result-group > .mr-mail-btn {
        grid-area: mail;
        align-self: center;
    }
}

/* ---- Reusable collapsible-section separator ---- */
.cs-separator {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 4px;
    background: transparent;
    cursor: pointer;
    font-weight: 500;
    color: #555;
    font-size: 1rem;
    user-select: none;
}

.cs-separator:hover {
    color: #333;
}

.cs-chevron {
    font-size: 0.75rem;
    color: #777;
    transition: transform 0.2s;
    flex-shrink: 0;
}

.cs-chevron--open {
    transform: rotate(90deg);
}

.cs-line {
    flex: 1;
    height: 2px;
    background: #ccc;
}

.cs-section {
    flex-direction: column;
    gap: 20px;
    padding-top: 12px;
}

.rc-save-row {
    display: flex;
    justify-content: flex-end;
}

.rc-overlay-wrapper.rc-row.rc-button {
    min-width: 50px;
}

.alpha-overlay {
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, 0.75);
    z-index: 10;
    pointer-events: auto;
}

/* --------------- CLOUD COURSES --------------- */

.cloud-courses-filter-parent {
    /*margin-bottom: 20px;*/
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 12px;
}

.cloud-courses-filter {
    /*margin-bottom: 20px;*/

    background: var(--icon-blue);
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    padding: 12px 16px;

    display: flex;
    align-items: center;
    gap: 16px;
}

.cloud-courses-filter input {
    flex: 1;
}

/* Send-to-keys icon button living inside the cloud-courses toolbar
   (right of the search input). Visual matches the per-card send button
   on recommended-ensembles-list (white circle, blue icon, blue ring on
   hover) so the "send" affordance reads consistently across pages. */
.cloud-courses-send-btn {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border: 1px solid white;
    border-radius: 50%;
    background: white;
    color: var(--icon-blue);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.05rem;
    padding: 0;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.cloud-courses-send-btn:hover {
    background: var(--button-blue);
    color: white;
    border-color: white;
}
/* The Send icon carries a red counter pill anchored to its top-right
   corner. Visible whenever the staging list has > 0 courses. position:
   relative on the host button is set above. */
.cloud-courses-send-btn {
    position: relative;
}
.cloud-courses-send-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    box-sizing: border-box;
    background: #c0392b;
    color: white;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.cloud-courses-send-badge[hidden] {
    display: none;
}

/* Inline variant of the red pill, used inside the right-pane "Courses
   list" tab next to the static label. Same colors and shape as the
   corner badge on the download icon, just static-positioned so it
   flows alongside the tab text instead of overlapping it. */
.cc-tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    box-sizing: border-box;
    background: #c0392b;
    color: white;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1;
    border-radius: 10px;
    margin-left: 6px;
    vertical-align: middle;
}
.cc-tab-badge[hidden] {
    display: none;
}

/* Two-row toolbar on mobile: top row holds [category, private,
   search]; bottom row holds [Add, Send, List]. Desktop stays a single
   row by leaving the row wrappers transparent (display: contents),
   so they don't generate a flex item and their children flatten
   into the parent's flex row. */
.cc-toolbar-row {
    display: contents;
}

/* Actions row above the cloud-courses list. Holds the Set-as-favorites
   star and the Send-to-keys download icon. Hidden whenever the user
   has nothing staged (cloud_courses.js _renderStagedList toggles
   the hidden attr). Reuses the send-badge anchoring via position:
   relative on each button so the existing badge CSS keeps working. */
.cc-actions-row {
    /* Mirrors .cloud-courses-filter chrome: blue panel with shadow,
       sits as a fixed toolbar above the staged-list pane (sibling of
       the pane, not a child) so it doesn't move while the list
       scrolls underneath. Top-only border radius matches the filter
       toolbar - sits flush against the list pane below. */
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--icon-blue);
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    padding: 12px 16px;
    margin-bottom: 8px;
}
.cc-actions-row[hidden] {
    display: none;
}
.cc-actions-row-btn {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border: 1px solid var(--icon-blue);
    border-radius: 50%;
    background: white;
    color: var(--icon-blue);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    padding: 0;
    position: relative;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.cc-actions-row-btn:hover {
    background: var(--button-blue);
    color: white;
    border-color: var(--button-blue);
}
/* Favorites star action button: same blue-outlined circle as the
   other action buttons (background + border inherited), but with a
   yellow star inside so the "favorite" intent reads instantly.
   Slightly larger icon so the star sits comfortably in the circle. */
.cc-actions-row-btn--fav {
    color: #fbc02d;
    font-size: 1.05rem;
}
.cc-actions-row-btn--fav:hover {
    color: #fbc02d;
}

/* Per-card eye icon used to jump into the full-screen course-info
   view on mobile (`onMobileInfoRequested`). data-action="show-course-
   info" is what the renderEnsembleCourseCards click router looks for,
   so this is functionally the same trigger as the file-icon — just a
   more explicit visual affordance. */
.course-card-mini-eye {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--icon-blue);
    font-size: 0.95rem;
    cursor: pointer;
    flex: 0 0 auto;
    padding: 2px 4px;
}
.course-card-mini-eye:hover {
    color: var(--button-blue);
}

/* List icon button in the action row. Mirrors the send-icon's circle
   chrome. Mobile-only: hidden on desktop (the staged list lives in
   the right-pane "Courses list" tab there, no need for a separate
   navigation affordance). */
.cloud-courses-list-btn {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border: 1px solid white;
    border-radius: 50%;
    background: white;
    color: var(--icon-blue);
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    font-size: 1.05rem;
    padding: 0;
    position: relative;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.cloud-courses-list-btn:hover {
    background: var(--button-blue);
    color: white;
    border-color: white;
}

/* Private-filter toggle button living between the category icon and
   the search input. Shape mirrors the send button (white circle, sits
   inside the icon-blue toolbar bg). When the filter is OFF (default,
   showing all courses) the lock icon renders normally. When ON
   (private courses hidden), a red diagonal slash is drawn over the
   lock via a ::after pseudo-element to read as "private excluded". */
.cloud-courses-private-filter-btn {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border: 1px solid white;
    border-radius: 50%;
    background: white;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    position: relative;
    overflow: hidden;
    transition: background 0.15s, border-color 0.15s;
}
.cloud-courses-private-filter-btn:hover {
    background: var(--text-background-hover);
}
.cloud-courses-private-filter-btn-icon {
    width: 22px;
    height: 22px;
    background-image: url('../images/visibility/private.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
/* Three-state filter modifiers shared by:
     - cloud-courses + course-groups edit browser (private filter on
       individual courses)
     - course-groups list private filter (has_private on the group)
     - course-groups list visibility filter (is_private on the group)
   Default (no modifier): base icon, no overlay, no filter.
   --no-public:        base icon swaps to cloud (public.png), red slash.
   --no-private:       base icon stays as lock (private.png), red slash.
   --no-everybody:     glyph swap happens in JS (fa-user-lock -> fa-user),
                       red slash overlays.
   --no-creator-only:  glyph stays fa-user-lock, red slash overlays.
   Click cycles per button: none -> first -> second -> none.
   The legacy --active modifier is kept as an alias for the slash for
   any future single-axis filter that wants the same visual. */
.cloud-courses-private-filter-btn--no-public .cloud-courses-private-filter-btn-icon {
    background-image: url('../images/visibility/public.png');
}
.cloud-courses-private-filter-btn--active::after,
.cloud-courses-private-filter-btn--no-public::after,
.cloud-courses-private-filter-btn--no-private::after,
.cloud-courses-private-filter-btn--no-everybody::after,
.cloud-courses-private-filter-btn--no-creator-only::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 6px;
    right: 6px;
    height: 2.5px;
    background: #c0392b;
    transform: translateY(-50%) rotate(-45deg);
    transform-origin: center;
    border-radius: 2px;
}

/* Font Awesome glyph used by the visibility-filter button (sibling of the
   lock-PNG privacy filter). Sized + colored to match. */
.cloud-courses-visibility-filter-btn-icon {
    font-size: 18px;
    color: var(--icon-blue);
    line-height: 1;
}

/* Cloud Courses page-level layout: page wrapper holds a single
   .cc-body that splits into the browser (left) and the tabbed right
   pane. Mirrors the structure of the course-groups edit view so the
   two pages read consistently. */
.cc-page {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}
.cc-body {
    display: flex;
    gap: 16px;
    flex: 1 1 auto;
    min-height: 0;
}
.cc-browser {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.cc-right {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* See the matching note on .cg-edit-right. */
    gap: 0;
}
.cc-list-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 8px;
}
.cc-list-actions {
    display: flex;
    gap: 8px;
    flex: 0 0 auto;
}
.cc-list-row {
    cursor: pointer;
    transition: background 0.12s, outline 0.12s;
}
.cc-list-row--selected {
    background: rgba(22, 102, 176, 0.10);
    outline: 1px solid var(--button-blue);
}
.cc-list-row-icon {
    color: var(--icon-blue);
    font-size: 0.9rem;
    flex: 0 0 auto;
}
/* Lock icon shown on staging-list / group-contents rows for courses
   with visibility === 0. Reuses the same private.png sprite the
   browser-side card uses so the visual is consistent. Sits to the
   left of the per-row × button. */
.cc-list-row-lock {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    background-image: url('../images/visibility/private.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
/* Per-row × remove button. margin-left: auto pushes it to the far
   right of .course-row-top regardless of how long the title is. */
.cc-list-row-remove {
    flex: 0 0 auto;
    margin-left: auto;
    width: 26px;
    height: 26px;
    border: none;
    background: transparent;
    color: #888;
    border-radius: 50%;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.9rem;
    transition: background 0.15s, color 0.15s;
    padding: 0;
}
.cc-list-row-remove:hover {
    background: #c0392b;
    color: white;
}

@media (max-width: 768px) {
    .cc-body {
        flex-direction: column;
        overflow-y: auto;
    }
    .cc-browser,
    .cc-right {
        flex: 0 0 auto;
    }
    /* Pin the filter+Add toolbar to the top while the user scrolls
       the course list. .cc-body is the scroll container on mobile,
       so sticky positions against its top edge. Background stays
       transparent - the blue toolbar (.cloud-courses-filter) inside
       fills the area, so cards scroll cleanly under it without
       needing a white backstop on the parent. */
    .cc-body .cloud-courses-filter-parent {
        position: sticky;
        top: 0;
        z-index: 10;
        padding-bottom: 8px;
        margin-bottom: 0;
    }
    /* Same sticky treatment for the staged-list toolbar on the right.
       Keeps "favorite the list" + "send the list" always reachable
       while the user scrolls the actual list under it. */
    .cc-body .cc-actions-row {
        position: sticky;
        top: 0;
        z-index: 10;
    }

    /* Toolbar splits into two rows on phones: top row [cat, private,
       search], bottom row [Add, Send, List]. The parent .cloud-courses-
       filter becomes a flex column; each .cc-toolbar-row child becomes
       its own flex row. Action row is left-aligned. */
    .cloud-courses-filter {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
    }
    .cc-toolbar-row {
        display: flex;
        align-items: center;
        gap: 12px;
        flex: 0 0 auto;
    }
    .cc-toolbar-row--bottom {
        justify-content: flex-start;
    }
    .cloud-courses-list-btn {
        display: inline-flex;
        /* margin-left: auto pushes the List button to the far right
           of the row while Add + Download stay left-aligned. */
        margin-left: auto;
    }

    /* The desktop's segmented Courses-list/Course-Info tab strip is
       hidden on mobile — the page acts like three separate "screens"
       toggled by JS via .cc-mode-* classes on .cc-page below. */
    .cc-right > .cg-segmented {
        display: none;
    }

    /* Browser mode (default): only the toolbar + browser cards are
       visible. cc-right (which holds the list/info panes) is fully
       hidden so the screen is a clean picking surface. */
    .cc-page.cc-mode-browser .cc-right {
        display: none;
    }
    /* List mode: only ccListPane fills the screen. Browser cards and
       the info pane are hidden; clicking back returns to browser
       mode (handled in JS). */
    .cc-page.cc-mode-list .cc-browser {
        display: none;
    }
    .cc-page.cc-mode-list #ccListPane {
        display: flex !important;
    }
    .cc-page.cc-mode-list #courseInfoPanel {
        display: none !important;
    }
    /* Info mode: only courseInfoPanel fills the screen. */
    .cc-page.cc-mode-info .cc-browser {
        display: none;
    }
    .cc-page.cc-mode-info #ccListPane {
        display: none !important;
    }
    .cc-page.cc-mode-info #courseInfoPanel {
        display: flex !important;
    }
}

.icon-square.cloud-category-icon {
    width: 60px;
    height: 60px;
}

.category-option {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;

    background-color: var(--icon-blue);
    color: white;
    border-radius: 6px;
    padding: 0px 12px;
    cursor: pointer;
    transition: background-color 0.2s ease, transform 0.1s ease;
}
.category-option:hover {
    transform: scale(1.02);
    box-shadow: 0 0 4px #888;
}

.category-option .icon-sprite {
    width: 60px;
    height: 60px;
    background-size: contain;
    background-position: center;
    background-repeat: no-repeat;
    flex-shrink: 0;
}

.category-label {
    white-space: normal;
    word-break: break-word;
    flex: 1;
}

.modal-overlay-background.category-icons-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 15px;
    overflow-y: auto;
}

.rc-row.user-info {
    align-items: unset;
}

#cg-overlay-groups {
    flex: 0.6;
    min-width: 0;
}

#cg-overlay-courses {
    flex: 0.4;
    min-width: 0;
}

/* Right-pane spinner shown while per-group courses are fetched on demand. */
.cg-overlay-courses-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px 0;
}
.cg-overlay-courses-loading i {
    font-size: 24px;
    color: #888;
    opacity: 0.7;
}

/* --------------------- MODAL OVERLAY --------------------- */

.modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 1000;
    justify-content: center;
    align-items: center;
}

.modal-overlay-background {
    background: var(--background);

    width: 80%;
    height: 80%;

    display: flex;

    gap: 16px;

    padding: 16px;
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);

    min-height: 0;
}

/* --------------- SEND-TO-KEYS OVERLAY ---------------
   Layout: vertical stack of [cards-row, footer]. Cards-row holds the
   user-info + courses card on the left and the keys card on the right
   on desktop. On mobile (<=768px) the cards stack and the footer
   naturally lands at the bottom, so the modal reads as a "story"
   (preview -> keys -> action). The .stk-admin class on the overlay is
   toggled by JS based on sessionHasAdvancedPermissions(): when absent,
   the input + Load User + fetched user-data fields are hidden. */
.stk-modal .modal-overlay-background {
    flex-direction: column;
    gap: 12px;
}
.stk-cards-row {
    display: flex;
    gap: 12px;
    flex: 1 1 auto;
    min-height: 0;
}
.stk-card {
    min-width: 0;
    min-height: 0;
}
.stk-card--user { flex: 0.55; }
.stk-card--keys { flex: 0.45; }
.stk-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    flex: 0 0 auto;
}
.stk-courses-section {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
/* Only add the courses-section's top gap when there's an admin-section
   above it. Without this, non-admins see ~10px of empty space stacked
   on top of the card's own padding for no reason. */
.stk-modal.stk-admin .stk-courses-section {
    margin-top: 10px;
}
.stk-modal:not(.stk-admin) .stk-admin-section {
    display: none !important;
}

@media (max-width: 768px) {
    .stk-cards-row {
        flex-direction: column;
        overflow-y: auto;
    }
    .stk-card--user,
    .stk-card--keys {
        flex: 0 0 auto;
    }
    /* On mobile each card sizes to its natural content (cards-row
       scrolls), so the inner tree-scroll's `flex: 1; min-height: 0`
       collapses it to 0 height — the rendered course cards exist but
       the scroll container is invisible. Switch tree-scroll to natural
       content height inside the modal so the list actually paints. */
    .stk-modal .tree-scroll {
        flex: 0 0 auto;
        overflow-y: visible;
    }
    .stk-courses-section {
        flex: 0 0 auto;
        min-height: 0;
    }
}

/* --------------- SPINNER TEXT --------------- */

#loadingContent {
    display: flex;
    flex-direction: column; /* Stack children vertically */
    align-items: center; /* Center children horizontally */
    text-align: center; /* Center text */
    background: rgba(0, 0, 0, 0.5); /* Black background with 80% opacity */
    padding: 20px 20px; /* Add padding for a better appearance */
    border-radius: 8px; /* Rounded corners */
}

/* Spinner Icon */
.spinner-icon {
    font-size: 2.5em;
    color: #ffffff;
}

/* Overlay Text */
#loadingOverlayText {
    color: #ffffff;
    margin-top: 10px;
    font-size: 1.5rem;
    display: block;
    text-align: center;
}

/* Loading Overlay Container */
/* z-index bumped above #popupOverlay (9999) so the global request
   spinner stays visible when it fires while a modal is already open
   (e.g. saving the change-key-owner modal triggers the spinner; it
   must paint on top of the modal, not behind it). */
#loadingOverlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.3);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 10500;
    visibility: hidden;
}

/* --------------------- POPUP --------------------- */

/* Popup overlay styles. Position is `fixed` (not absolute) so the popup
   is always centered in the viewport even on long scrolling pages — same
   fix as #loadingOverlay above. With absolute, the popup centered within
   the parent block instead, which on a scrolling page meant the modal
   could end up off-screen. */
#popupOverlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
    display: none; /* Initially hidden */
    justify-content: center;
    align-items: center;
    z-index: 9999;
}

/* Popup content styles */
#popupContent {
    background: white;
    padding: 20px 22px 16px;
    border-radius: 10px;
    text-align: left;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.15);
    max-width: 440px;
    width: 90%;
}

/* Plain message - no tinted panel, no card-within-card. The button
   hierarchy below carries the visual structure; the message just
   asks the question. */
#popupMessage {
    margin: 0 0 22px 0;
    font-size: 1rem;
    line-height: 1.5;
    color: #1f2937;
}

/* Right-aligned button row. Visual order (left → right): CANCEL
   (text-only) → NO (outlined) → YES (filled). Affirmative on the
   right is the natural rest position for a confirming user. */
#popupButtons {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

/* Shared base. Buttons differ in weight (filled → outlined → text)
   rather than in color, so semantic emphasis comes from hierarchy
   instead of red/green signals. */
.popupButton {
    padding: 8px 14px;
    border: 1px solid transparent;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.2;
    background: transparent;
    transition: background-color 0.12s, border-color 0.12s, color 0.12s;
}

/* YES (primary): filled blue. The "go ahead with what you asked
   about" button - heaviest visual weight. */
.confirmButton {
    background-color: var(--button-blue);
    color: white;
    border-color: var(--button-blue);
}
.confirmButton:hover {
    background-color: var(--button-blue-hover);
    border-color: var(--button-blue-hover);
}

/* YES (danger): filled red. Opt-in via popup.show(..., { danger: true })
   for genuinely destructive primary actions (delete a group,
   unlicense, anonymize). Keeping red exclusive to destructive YES
   means seeing red on a popup actually carries information. */
.confirmButton--danger {
    background-color: #dc2626;
    color: white;
    border-color: #dc2626;
}
.confirmButton--danger:hover {
    background-color: #b91c1c;
    border-color: #b91c1c;
}

/* NO (secondary): outlined ghost. Same chrome as CANCEL would have
   been before - "decline" without the alarm bell. */
.noButton {
    color: #4b5563;
    border-color: #d1d5db;
}
.noButton:hover {
    background-color: #f3f4f6;
    color: #1f2937;
    border-color: #cbd5e1;
}

/* CANCEL: same outlined-ghost chrome as NO. Reads as a sibling
   "don't proceed" button at the same visual weight, with only the
   text differentiating "abort the whole flow" (Cancel) from
   "answer No to the question" (No). */
.cancelButton {
    color: #4b5563;
    border-color: #d1d5db;
}
.cancelButton:hover {
    background-color: #f3f4f6;
    color: #1f2937;
    border-color: #cbd5e1;
}

/* --------------- COMMON ELEMENTS --------------- */

.flex-fit-parent {
    display: flex;
    min-height: 0;
}

.flex-1 {
    flex: 1;
}

.flex-col {
    flex-direction: column;
}

/* TODO: Aca hay una cuestion rara por la tabla de grupos de cursos de report config y la tabla de table.js */
table > tr:first-child td, tr:first-child th,
table tbody:first-child tr:first-child td,
.filter-row td {
    border-top: var(--table-border-px) solid var(--table-border-grey);
}

th:first-child, td:first-child {
    border-left: var(--table-border-px) solid var(--table-border-grey);
}

th, td {
    padding: 8px 12px;
    text-align: left;

    border-bottom: var(--table-border-px) solid var(--table-border-grey);
    border-right: var(--table-border-px) solid var(--table-border-grey);
    /*border-radius: 8px;*/

    /*white-space: normal;*/
    /*word-break: break-word;*/
    /*overflow-wrap: anywhere;*/
}

tr {
    cursor: pointer;
}

thead {
    background-color: var(--header);

    position: sticky;
    top: 0;
}

th {
    background-color: var(--header);
}

tr:nth-child(even) {
    background-color: var(--text-background);
}

tr:nth-child(odd) {
    background-color: var(--text-background-2);
}

tr.selected {
    background-color: var(--text-background-hover);
}

.icon-square {
    width: 40px;
    height: 40px;
    display: inline-block;
    overflow: hidden;
}

.icon-sprite {
    width: 100%;
    height: 100%;
    background-size: contain;
    background-position: center;
    background-repeat: no-repeat;
}

.mrg-r-10 {
    margin-right: 10px;
}

.mrg-r-25 {
    margin-right: 25px;
}

.mrg-r-50 {
    margin-right: 50px;
}

.mrg-l-10 {
    margin-left: 10px;
}

.mrg-l-50 {
    margin-left: 50px;
}

.mrg-t-10 {
    margin-top: 10px;
}

.mrg-t-50 {
    margin-top: 50px;
}

/* --------------- EXTRA INFO --------------- */

.extra-info-main {
    font-family: Arial, sans-serif;
    color: #333;

    display:flex;
    flex: 1;
    flex-direction: column;
    gap: 16px;
}

.extra-info-main .rc-row {
    display: grid;
    grid-template-columns: 110px 1fr; /* Adjust 150px based on the widest label */
    column-gap: 12px;
    align-items: start;
}


.extra-info-main .rc-row strong {
    white-space: nowrap;
}

.extra-info-main .rc-row span {
    overflow-wrap: anywhere;
    word-break: break-word;
    white-space: normal;
}

.extra-info-section {
    border: var(--table-border-px) solid var(--table-border-grey);
    border-radius: 8px;
    overflow: hidden;

    display: flex;
    flex: 1;
    flex-direction: column;
    background-color: var(--text-background);
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.extra-info-title {
    padding: 8px 12px;
    background-color: var(--icon-blue);
    font-weight: bold;
    border-bottom: var(--table-border-px) solid var(--table-border-grey);
    color: white;
}

.extra-info-body {
    background-color: var(--text-background);
    display: flex;
    flex-direction: column;
    gap: 6px;

    padding: 10px 12px;
}

#selectionListPanel .extra-info-body {
    padding: 15px 30px;
    overflow: hidden;
}

.extra-info-body-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 8px;
}

/* --------------- MY DEVICES 2 --------------- */

.key-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.key-card-chevron {
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0.8;
    transition: transform 150ms ease, opacity 150ms ease;
}

.keys-card.is-expanded .key-card-chevron {
    transform: rotate(180deg);
    opacity: 1;
}

.key-details {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid rgba(255, 255, 255, 0.10);
}

.key-details-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 8px;
}

/* --------------- MY DEVICES --------------- */

.keys-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 20px;

    box-shadow: none;

    align-content: start; /* Align rows to top to prevent vertical stretching */
    justify-content: start; /* Optional: align to left if there's room */
}

.info-wrapper {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 5px;
}

.key-info {
    color: #333;
    display: flex;
    align-items: center;
    gap: 6px;
}

.key-info i {
    color: var(--button-blue);
}

.key-info.expired {
    color: red;
}

.key-info.requires-update {
    color: #d17b00; /* orange */
}

/* Optional: style features differently */
/*.key-info.maestro {*/
/*    font-weight: bold;*/
/*    color: #5a3ab9;*/
/*}*/

.usb-icon {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 20px;
    margin-top: 10px;
}

.usb-body {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    background-color: #9255c5;
    color: white;
    font-weight: bold;

    padding: 8px 16px;
    border-top-left-radius: 18px;
    border-bottom-left-radius: 18px;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    position: relative;
    border: 1px solid #000;

    min-width: 100px;
    min-height: 60px;
}

.usb-body span {
    position: relative;
    font-size: 1.3rem;
}

.usb-body.usb-body--maestro {
    background-color: #4b0082;
}

.usb-body.usb-body--maestro span {
    color: gold;
}

.usb-body.usb-body--master {
    background-color: #daa520;
}

.usb-body.usb-body--master span {
    color: darkred;
}

.keys-card--maestro .metric-tile--features .metric-tile-value,
.keys-card--master  .metric-tile--features .metric-tile-value {
    font-weight: 600;
}

.metric-tile.never-expires .metric-tile-value {
    font-style: italic;
    color: #4b5563;
}

.metric-tile.expired .metric-tile-value {
    color: #b00020;
}

.metric-tile.expiring-soon .metric-tile-value {
    color: #bbaa22;
}

.metric-alert {
    position: absolute;
    top: 8px;
    right: 12px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1.5px solid currentColor;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.95rem;
    line-height: 1;
    visibility: hidden;
}

.metric-tile.expired .metric-alert {
    visibility: visible;
    color: #b00020;
}

.metric-tile.expiring-soon .metric-alert,
.metric-tile.requires-update .metric-alert {
    visibility: visible;
    color: #bbaa22;
}

.usb-connector {
    width: 25px;
    height: 40px;
    background-color: #666;
    border: 1px solid #000;
    border-radius: 2px;
    margin-left: -4px;
}

/* --------------- CLOUD COURSES --------------- */

.course-extra-info .extra-info-title {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;

    min-height: 50px;
}

.course-extra-info .extra-info-body {
    padding: 25px 15px 25px 30px;

    flex: 1;
    min-height: 0;
}

.course-name {
    flex-grow: 1;
    font-weight: bold;
    font-size: 16px;
    text-align: center;
}

.module-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-right: 20px;
}

.module-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: #f0f0f0;
    padding: 6px 10px;
    border: 1px solid #ddd;
    border-radius: 3px;
}

.module-row > div {
    flex: 1;
}

.mod-num {
    font-weight: bold;
    max-width: 40px;
}

.mod-name {
    text-align: left;
    padding-left: 10px;
}

.mod-diff {
    text-align: right;
    font-weight: bold;
    max-width: 60px;
    height: 30px;
}

/* --------------- REAL TIME MONITOR --------------- */

.student-card {
    width: unset;
    height: unset;
    border: 1px solid var(--button-blue);
    border-radius: 8px;
    padding: 12px;
}

.student-card .top {
    display: grid; grid-template-columns: 56px 1fr; gap: 10px; width: 100%;
    align-items: center;
}
.student-card img {
    width: 56px; height: 56px; border-radius: 6px; object-fit: cover;
    border: 1px solid var(--table-border-grey);
    background: #fff;
}
.student-card .name { font-weight: 700; color: #1a1a1a; }
.student-card .exercise { color: #444; font-size: .95rem; }
.student-card .stats {
    display: flex; gap: 8px; align-items: center; margin-top: 10px; width: 100%;
}
.pill {
    padding: 4px 8px; border-radius: 999px; font-weight: 700; font-size: .9rem; color: #fff;
    white-space: nowrap;
}
.pill.green { background: #41a853; }     /* success */
.pill.red   { background: #e06161; }     /* danger  */
.pill.blue  { background: var(--button-blue); }
.student-card .footer {
    display: flex; justify-content: flex-end; width: 100%; margin-top: 8px;
}

.rc-row--controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;                /* spacing between the two groups */
}

/* Each group: inline row, no breaking between its own elements */
.rc-control-group {
    display: flex;
    flex-wrap: nowrap;        /* keep label + input + button on one line */
    align-items: center;
    gap: 8px;
    flex: 1;
}

/* --------------- STUDENTS OVERVIEW --------------- */

/* Search bar row */
.students-search-row {
    display: flex;
    align-items: center;
    gap: 10px;

    background: var(--text-background);
    border-radius: 8px;
    padding: 10px 14px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.08);
    border: 1px solid var(--table-border-grey);
}

.students-search-row i {
    color: var(--dark-grey);
    font-size: 1rem;
}

.students-search-row input {
    flex: 1;
    border: none;
    background: transparent;
    font-size: 1rem;
    outline: none;
}

/* my-keys toolbar row: holds the search bar + the EDIT_ANY admin
   lookup (input + button) as siblings. Wraps on narrow viewports so
   the admin controls drop below the search bar on mobile. */
.keys-toolbar-row {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 10px;
}
.keys-toolbar-row .students-search-row {
    flex: 1 1 280px;
    min-width: 0;
}
.keys-admin-filter-input {
    flex: 0 1 220px;
    min-width: 0;
    padding: 8px 12px;
    border: 1px solid var(--table-border-grey);
    border-radius: 8px;
    background: white;
    color: #1f2937;
    font-size: 0.95rem;
}
.keys-admin-filter-input:focus {
    outline: none;
    border-color: var(--button-blue);
}
.keys-admin-filter-reload-btn {
    flex: 0 0 auto;
}

.activity-filters-row {
    display: flex;
    align-items: stretch;
    gap: 12px;
}

.activity-filters-row .students-search-row {
    flex: 1 1 auto;
}

.activity-filter-select {
    flex: 0 0 auto;
    background: var(--text-background);
    border: 1px solid var(--table-border-grey);
    border-radius: 8px;
    padding: 0 14px;
    font-size: 1rem;
    color: #333;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.activity-filter-select:focus {
    outline: none;
    border-color: var(--button-blue);
}

/* Wraps multiple .activity-filter-select children so they share a row even
   when the rest of .activity-filters-row stacks vertically on mobile. */
.activity-filter-selects {
    display: flex;
    flex: 0 0 auto;
    gap: 12px;
}

@media (max-width: 576px) {
    .activity-filters-row {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
    }

    .activity-filter-selects {
        gap: 8px;
    }

    /* Inside the wrapper: split row width equally between selects. */
    .activity-filter-selects > .activity-filter-select {
        flex: 1 1 0;
        width: auto;
        padding: 10px 14px;
    }

    /* Bare select directly in the row (no wrapper): keep full-width stacking
       so existing pages with a single select are unchanged. */
    .activity-filters-row > .activity-filter-select {
        width: 100%;
        padding: 10px 14px;
    }
}

/* --------------- COURSE GROUPS PAGE ---------------
   Layout for course-groups.html. The page hosts two view modes (list /
   edit) toggled in JS:
   - List view: a toolbar (new-group + search) over a vertical list of
     group rows with edit/send/delete buttons.
   - Edit view: name + visibility on top, browser left, a segmented
     right pane that flips between "Group contents" and "Course info"
     so the page stays at two columns at every viewport. */

.cg-list-view {
    display: flex;
    flex-direction: column;
    gap: 16px;
    flex: 1 1 auto;
    min-height: 0;
}
.cg-list-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;       /* let date-filter / private-toggle wrap on narrow viewports */
    flex: 0 0 auto;
}
/* Search grows to fill the toolbar row on desktop; on mobile it
   becomes 100% so it gets its own row (see @media block below). */
.cg-list-toolbar > .students-search-row {
    flex: 1 1 auto;
}
.cg-list-date-filter {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    color: #555;
    font-size: 0.9rem;
    font-weight: 500;
}
.cg-list-date-filter input[type="date"] {
    padding: 6px 10px;
    font-size: 0.95rem;
    border: 1px solid #d8dde3;
    border-radius: 6px;
    background: white;
    color: #222;
    height: 36px;
    box-sizing: border-box;
    line-height: 1.2;
}
/* Align the sort-select's chrome with the date input above so the
   two side-by-side controls read as a matching pair. The base
   `.rtm-sort-select` rule used a different border color (#ccc),
   border-radius (4px), font-size (1rem), and didn't set a fixed
   height — leading to a slightly different look + vertical
   midpoint. Scope the override to `.cg-list-toolbar` so RTM keeps
   its own styling. */
.cg-list-toolbar .rtm-sort-select {
    padding: 6px 10px;
    font-size: 0.95rem;
    border: 1px solid #d8dde3;
    border-radius: 6px;
    background: white;
    color: #222;
    height: 36px;
    box-sizing: border-box;
    line-height: 1.2;
}

@media (max-width: 576px) {
    /* On phones the search takes its own full-width row so the
       smaller filter controls (private toggle, since, sort) can
       group on a second row beneath. */
    .cg-list-toolbar > .students-search-row {
        flex: 1 1 100%;
    }
    /* "Since" and "Sort" lose their text labels on phones — the
       inputs themselves are recognisable enough and the labels
       were taking up a disproportionate share of the row. */
    .cg-list-date-filter > span,
    .cg-list-toolbar .rtm-group-label {
        display: none;
    }
    /* Since + Sort wrappers each grow to fill half of the row.
       Their inner controls fill the wrapper width. */
    .cg-list-date-filter,
    .cg-list-toolbar .rtm-sort-group {
        flex: 1 1 0;
        min-width: 0;
    }
    .cg-list-date-filter input[type="date"],
    .cg-list-toolbar .rtm-sort-select {
        width: 100%;
        min-width: 0;
    }
}
.cg-list-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Vertical padding so the rows' box-shadow (0 1px 3px) at the
       bottom — and the create row at the top — have breathing room
       before overflow-y: auto clips them. */
    padding: 12px 0;
}
.cg-list-empty {
    color: #888;
    text-align: center;
    padding: 24px;
}

.cg-list-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    background: white;
    border: 1px solid #e2e6ea;
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
}
.cg-list-row-main {
    flex: 1 1 auto;
    min-width: 0;
}
.cg-list-row-name {
    font-size: 1rem;
    font-weight: 600;
    color: #222;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cg-list-row-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 16px;
    font-size: 0.85rem;
    color: #666;
    margin-top: 4px;
}
.cg-list-row-privacy,
.cg-list-row-creator-only {
    color: var(--button-blue);
    font-weight: 500;
}
.cg-list-row-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}
/* Extra spacing between the bulk-action buttons (favorites + send) and
   the per-group-row buttons (edit + delete) so the icon strip reads as
   two visual clusters rather than four buttons in a row. */
.cg-list-row-actions > .cg-list-row-btn[data-action="edit"] {
    margin-left: 16px;
}
/* `create_report` is a "new report from this group" action whose target
   isn't the group itself. The --gap-after modifier widens the gap to
   its right so it visually separates from the group-scoped buttons
   (privacy, favorites, send, edit, delete). */
.cg-list-row-actions > .cg-list-row-btn--gap-after {
    margin-right: 12px;
}
.cg-list-row-btn {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border: 1px solid var(--button-blue);
    border-radius: 50%;
    background: white;
    color: var(--button-blue);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.9rem;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    padding: 0;
}
.cg-list-row-btn:hover {
    background: var(--button-blue);
    color: white;
}
.cg-list-row-btn--danger {
    border-color: #c0392b;
    color: #c0392b;
}
.cg-list-row-btn--danger:hover {
    background: #c0392b;
    color: white;
}
/* Favorites action button: same blue-outlined circle as the other
   row buttons (background + border inherited), with a yellow star
   inside so the "favorite" intent reads consistently with the
   cloud-courses set-favorites button. */
.cg-list-row-btn--fav {
    color: #fbc02d;
    font-size: 1.05rem;
}
.cg-list-row-btn--fav:hover {
    color: #fbc02d;
}

/* Create-new-group fake row at the top of the list. Visual matches
   `.sr2-card--create` from teacher/student reports: dashed-border
   chip with subtle background, neutral text that turns blue on
   hover, smaller padding than a regular row. */
.cg-list-row--create {
    justify-content: center;
    gap: 12px;
    border-style: dashed;
    border-width: 2px;
    border-color: #c0c8d0;
    background: #fafbfc;
    box-shadow: none;
    color: #666;
    cursor: pointer;
    padding: 8px 16px;
    font-weight: 500;
    font-size: 1rem;
    transition: border-color 0.15s, color 0.15s, transform 0.15s;
}
.cg-list-row--create:hover {
    border-color: var(--button-blue);
    color: var(--button-blue);
    box-shadow: none;
    /* No translateY lift: the row sits at the top of an
       overflow-y: auto container, so any vertical transform risks
       intersecting the clip edge. Color + border-color shifts on
       hover are enough feedback. */
}
.cg-list-row-create-icon {
    font-size: 1.1rem;
}

/* Both panes host a scrolling list with a pinned header above. Make
   them flex columns with overflow: hidden so the contained list
   element owns the scroll. */
#ccListPane,
#cgContentsPane {
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
#ccListPane .cg-contents-list,
#cgContentsPane .cg-contents-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Padding so the course-card-mini rows don't hug the scroll
       container edges. Important for the selected-row outline (1px
       outside the card border) and for the right-edge scrollbar
       gutter; without this the outline gets clipped and rows look
       cramped against the pane wall. */
    padding: 4px;
}

/* The #courseInfoPanel id now lives on the .course-extra-info.extra-
   info-main div directly (the redundant outer .cg-pane wrapper was
   removed), so the only thing this rule needs to provide is a
   non-overflowing container with a flex-column + min-height: 0 chain
   so each section's .extra-info-body owns its own scroll instead of
   one big pane scroll. The base .extra-info-main rule already covers
   display: flex / flex-direction: column / flex: 1 / gap: 16px.
   `padding-bottom: 8px` matches the section's box-shadow extent
   (0 2px 8px rgba) so the last section's shadow has room to render
   inside the panel's clip box instead of being cut off. */
#courseInfoPanel {
    overflow: hidden;
    min-height: 0;
    padding-bottom: 8px;
}
/* Two flex containers between the pane and the bodies needed
   `min-height: 0` to let internal scroll take effect; without these the
   default `min-height: auto` propagates content height upward and the
   bodies grow tall enough to push the pane out, which is what produced
   the "Activity Modules has barely any space" feeling. */
.course-extra-info.extra-info-main {
    min-height: 0;
}
.course-extra-info .extra-info-section {
    min-height: 0;
    /* The section had a 1px border on every side. With the title bar
       sitting flush against the section's interior, the title bg looked
       2px narrower than the section's outer edge (1px of the section's
       grey border showing on each side at the title row). Drop the
       border; the section's identity is still carried by its background
       color, the icon-blue title strip, and box-shadow. */
    border: none;
}
/* The first section inside #courseInfoPanel sits directly under the
   tabs; flatten its top corners AND drop its top border so the active
   tab's rounded-top + section's flat-top read as one continuous shape
   with no horizontal seam. Bottom corners stay rounded for the
   section's own card look. The section's left/right/bottom borders
   stay; only the top is removed because the tab above now carries the
   visual top edge. */
#courseInfoPanel .extra-info-section:first-child {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
    border-top: none;
}

.cg-edit-view {
    display: flex;
    flex-direction: column;
    gap: 12px;
    flex: 1 1 auto;
    min-height: 0;
}
.cg-edit-meta {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    flex: 0 0 auto;
    /* Visual separation between the [name | visibility | up/down] row
       and the course list below. */
    margin-bottom: 20px;
}
.cg-edit-meta-row {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 200px;
    min-width: 0;
}
.cg-edit-meta-row label {
    font-size: 0.85rem;
    font-weight: 600;
    color: #555;
}
.cg-edit-meta-row input,
.cg-edit-meta-row select {
    padding: 6px 10px;
    font-size: 1rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    background: white;
    /* Defensive: kill any browser-default vertical margin so the input
       sits flush with the row's bottom (the visible separation to the
       list comes from `.cg-edit-meta { margin-bottom }`). */
    margin: 0;
}
/* Up/Down buttons live in the same flex row as Name + Visibility on
   the Group contents tab. align-self: flex-end pulls them down so
   their bottom matches the input's bottom (the meta-rows are flex
   columns with label-on-top + input-on-bottom). */
.cg-edit-meta-actions {
    display: flex;
    flex: 0 0 auto;
    align-self: flex-end;
    gap: 8px;
}

.cg-edit-body {
    display: flex;
    gap: 16px;
    flex: 1 1 auto;
    min-height: 0;
}
.cg-edit-browser {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.cg-edit-right {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* No gap between segmented tabs and the pane below — they're
       visually one piece (tabs sit on top of the pane). */
    gap: 0;
}

/* Tabbed segmented control. Tabs sit flush above their pane: top
   corners rounded, bottom flat, so the active tab + pane read as a
   single rounded-bottom box. Inactive tab is greyed; active tab is
   blue with white text. The wrapper carries the same grey background
   as inactive tabs so the strip reads as a single rounded "tab bar"
   with only the active tab popping out. A 4px margin-bottom separates
   the strip from the pane below. */
.cg-segmented {
    display: flex;
    flex: 0 0 auto;
    background: #c8cfd9;
    border-radius: 8px 8px 0 0;
    margin-bottom: 4px;
}
.cg-segmented-btn {
    flex: 1 1 0;
    border: none;
    /* Inactive tab needs to read as a clearly-greyed-out chip rather
       than blending into the page background (--background = #eceff6).
       This grey is distinctly darker so the affordance reads as
       "disabled-but-clickable". */
    background: #c8cfd9;
    color: #555;
    font-size: 0.95rem;
    font-weight: 500;
    padding: 10px 14px;
    border-radius: 8px 8px 0 0;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.cg-segmented-btn--active {
    background: var(--icon-blue);
    color: white;
}

.cg-pane {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Match the extra-info panel aesthetic (light text-background +
       subtle drop shadow) so the courses-list / group-contents pane
       reads as part of the same family as the course info sections
       beside / paired with it. */
    background: var(--text-background);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    /* No border (the surrounding tabs above + bg color carry the
       visual shape; matches the extra-info-section's border-less look
       after this iteration). */
    border: none;
    /* Tabs above carry the top corners; pane only rounds the bottom. */
    border-radius: 0 0 8px 8px;
    padding: 12px 14px;
}
.cg-contents-meta {
    color: #666;
    font-size: 0.85rem;
    margin-bottom: 8px;
}
.cg-contents-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.cg-contents-empty {
    color: #888;
    text-align: center;
    padding: 24px 8px;
    font-size: 0.9rem;
}
.cg-contents-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: #f7f8fa;
    border-radius: 6px;
}
.cg-contents-row-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.92rem;
    color: #222;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cg-contents-row-remove {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border: none;
    background: transparent;
    color: #888;
    border-radius: 50%;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, color 0.15s;
}
.cg-contents-row-remove:hover {
    background: #c0392b;
    color: white;
}

.cg-edit-footer {
    display: flex;
    gap: 8px;
    flex: 0 0 auto;
    align-items: center;
}
.cg-edit-footer-left,
.cg-edit-footer-right {
    display: flex;
    gap: 8px;
}
.cg-edit-footer-right {
    /* Pushes Cancel/Save to the right regardless of whether the
       Up/Down group on the left is visible (it is on mobile in
       contents mode, hidden on desktop). */
    margin-left: auto;
}
/* Footer Up/Down are mobile-only — desktop keeps them in
   .cg-edit-meta-actions (top of the contents pane). */
.cg-edit-footer-left {
    display: none;
}

@media (max-width: 768px) {
    .cg-edit-body {
        flex-direction: column;
        overflow-y: auto;
    }
    .cg-edit-browser,
    .cg-edit-right {
        flex: 0 0 auto;
    }
    /* Same sticky-toolbar pattern as cloud-courses: pin the filter +
       Add row to the top of the scroll container while the list
       under it scrolls. Transparent background - the blue toolbar
       child fills the visible area. */
    .cg-edit-body .cloud-courses-filter-parent {
        position: sticky;
        top: 0;
        z-index: 10;
        padding-bottom: 8px;
        margin-bottom: 0;
    }
    .cg-list-row {
        flex-wrap: wrap;
    }
    .cg-list-row-actions {
        flex: 1 1 100%;
        justify-content: flex-end;
    }

    /* Course-groups edit view mobile flow: 3-screen mode-switching
       mirrors cloud_courses's cc-mode-* pattern. The cg-edit-view
       gets one of cg-mode-browser / -contents / -info from JS, and
       these rules show the matching pane while hiding the others.
       The desktop segmented control is hidden — mode-switching
       replaces it on mobile. */
    .cg-edit-view > .cg-edit-body > .cg-edit-right > .cg-segmented {
        display: none;
    }

    /* Browser mode (default): only the browser cards visible. Footer
       hidden — Up/Down/Cancel/Save aren't relevant when picking. */
    .cg-edit-view.cg-mode-browser .cg-edit-right {
        display: none;
    }
    .cg-edit-view.cg-mode-browser .cg-edit-footer {
        display: none;
    }

    /* Contents mode: only cgContentsPane visible (full-screen) plus
       the bottom action row (Up/Down on the left, Cancel/Save on the
       right). */
    .cg-edit-view.cg-mode-contents .cg-edit-browser {
        display: none;
    }
    .cg-edit-view.cg-mode-contents #cgContentsPane {
        display: flex !important;
    }
    .cg-edit-view.cg-mode-contents #courseInfoPanel {
        display: none !important;
    }

    /* Info mode: only courseInfoPanel visible (full-screen). Footer
       hidden — no editing actions relevant in info-only view. */
    .cg-edit-view.cg-mode-info .cg-edit-browser {
        display: none;
    }
    .cg-edit-view.cg-mode-info #cgContentsPane {
        display: none !important;
    }
    .cg-edit-view.cg-mode-info #courseInfoPanel {
        display: flex !important;
    }
    .cg-edit-view.cg-mode-info .cg-edit-footer {
        display: none;
    }

    /* On mobile the meta-row Up/Down are hidden (the footer's mobile
       Up/Down take over) so the meta strip just holds Name +
       Visibility. */
    .cg-edit-meta-actions {
        display: none;
    }
    /* Footer's left group (Up/Down) becomes visible on mobile. */
    .cg-edit-footer-left {
        display: flex;
    }
}

/* --------------- TOOLBAR SORT/LABEL PRIMITIVES ---------------
   Used by Real-Time Monitor (filter + sort toolbar) and the
   recommended-ensembles-list page. Keeps "Sort" / "Filter" / "By"
   inline-label + select pairings consistent across pages. The RTM page
   still keeps `flex-shrink: 0; margin-left: 24px` locally because its
   sort group sits next to a flex-growing filter group; standalone
   usages (toolbars with their own gap) don't need that. */
.rtm-sort-group {
    display: flex;
    align-items: center;
    gap: 8px;
}
.rtm-group-label {
    font-size: 1rem;
    font-weight: 600;
    color: #374151;
    white-space: nowrap;
    margin: 0;
    padding: 0;
    line-height: 1;
    text-align: right;
}
/* Self-sufficient styling: matches the visual a select gets from
   `.rc-row select` (border, padding, font, radius), so the control
   looks the same whether or not the surrounding markup is `.rc-row`. */
.rtm-sort-select {
    min-width: 200px;
    padding: 6px 10px;
    font-size: 1rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    height: auto;
    box-sizing: border-box;
}

/* Cards container */
.students-cards-wrapper {
    display: flex;
    flex-direction: column;
    gap: 8px;
    box-sizing: border-box;
}

/* Individual student card – closer to Tailwind example */
.student-summary-card {
    background: #ffffff;
    border-radius: 12px;
    padding: 24px;
    box-shadow: 0 1px 3px rgba(15,23,42,0.08); /* soft shadow */
    border: 1px solid #e5e7eb;

    display: flex;
    flex-direction: column;
    gap: 12px;

    cursor: pointer;
    transition: box-shadow 0.15s ease, transform 0.15s ease, background-color 0.15s ease;
}

.student-summary-card:hover {
    background: #ffffff;
    box-shadow: 0 8px 20px rgba(15,23,42,0.12);
    transform: translateY(-1px);
}

.student-summary-card.no-hover:hover {
    background: #ffffff;
    box-shadow: 0 1px 3px rgba(15,23,42,0.08);
    transform: none;
    cursor: default;
}

/* Card header: name + email + chevron */
.student-card-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
}

.student-card-header--rich {
    margin-bottom: 12px;
}

.student-card-avatar {
    width: 50px;
    height: 50px;
    border-radius: 25%;
    object-fit: cover;
    flex: 0 0 auto;
    margin-right: 12px;
}

/* Activity-dashboard L1: avatar wrap is the positioned container for
   the country-flag badge. The flag overlays the avatar's bottom-right
   corner, so the row's height and width are unchanged whether or not
   the student has a country set. The wrap inherits the avatar's old
   margin-right so the title group still gets its 12px gap. */
.student-card-avatar-wrap {
    position: relative;
    flex: 0 0 auto;
    margin-right: 12px;
}
.student-card-avatar-wrap > .student-card-avatar {
    margin-right: 0;
}
.student-card-avatar-flag {
    position: absolute;
    bottom: -2px;
    right: -3px;
    height: 16px;
    aspect-ratio: 4 / 3;
    border-radius: 2px;
    box-shadow: 0 0 0 1.5px white, 0 1px 2px rgba(0, 0, 0, 0.25);
    display: block;
    pointer-events: none;     /* don't intercept the card's click target */
}

.student-card-title-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.student-card-name {
    font-weight: 600;
    font-size: 1.05rem;
    color: #111827;
    margin-bottom: 2px;
}

.student-card-email {
    font-size: 0.9rem;
    color: #6b7280;
    word-break: break-all;
}

.student-summary-no-card .student-card-name {
    font-size: 1.2rem;
}

.student-summary-no-card .student-card-email {
    font-size: 1rem;
}

/* OPUS Leaderboards: a flag icon sits to the left of the country name on
   each ranking-position card. The slot is .student-card-email reused;
   the .ranking-country-row modifier turns it into a horizontal flex row
   so the flag aligns with the text baseline. */
.ranking-country-row {
    display: flex;
    align-items: center;
    gap: 6px;
    word-break: normal;       /* override .student-card-email's break-all */
}
.ranking-country-flag {
    flex: 0 0 auto;
    /* Height tracks the country text (1em of the parent .student-card-
       email's 0.9rem font); width is fixed via aspect-ratio so the
       flag renders even when the browser doesn't infer intrinsic
       dimensions from the inline SVG <img>. Keeps the flag visually
       paired with the text instead of dwarfing it. */
    height: 1em;
    aspect-ratio: 4 / 3;
    border-radius: 1px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
    display: block;
}

.student-card-chevron {
    color: var(--button-blue);
    font-size: 1.1rem;
    flex-shrink: 0;
    cursor: pointer;
}

/* Metric tiles inside card – more “cardy” look */
.student-card-metrics {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 16px;
}

.student-card-metrics--rich {
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

/* Subcards */
.metric-tile {
    background: var(--text-background);
    border-radius: 8px;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    position: relative;
}

.metric-tile--rich {
    background: #ffffff;
    border-radius: 8px;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    border: 1px solid #e5e7eb;
    box-shadow: 0 1px 3px rgba(15,23,42,0.06);
}

/* EDIT_ANY affordance on otherwise read-only metric tiles. Same shape
   as .metric-tile--rich; the border becomes 1.5px dashed blue so the
   tile reads as "click to edit". Used on the my-keys Admin-username
   tile when sessionHasAdvancedPermissions() is true. */
.metric-tile--editable {
    border: 1.5px dashed var(--button-blue);
    cursor: pointer;
}
.metric-tile--editable:hover {
    background: rgba(22, 102, 176, 0.04);
}

/* Header inside each small tile: icon + label */
.metric-tile-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}

.metric-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--button-blue);
    font-size: 0.9rem;
}

.metric-tile-label {
    font-size: 0.9rem;
    color: #6b7280;
    text-transform: none;
    margin: 0;
}

.metric-tile-value {
    font-size: 1rem;
    color: #111827;
    margin: 0;

    white-space: normal;
    word-break: break-word;
    overflow-wrap: anywhere;
}

/* Pin value (+ trailing mini progress bar, if present) to the bottom of
   each tile inside the rich grid. Keeps the bottom edges aligned across
   all 4 tiles even when the header label wraps to two lines on mobile. */
.metric-tile--rich .metric-tile-value {
    margin-top: auto;
}

/* Slightly bigger value for the Score tile to draw the eye. */
.metric-tile--rich[data-info-key="info.activity.metric.score"] .metric-tile-value {
    font-size: 1.2rem;
}

/*TODO: PARA QUE LOS n/N tengan colorcito rapido indicador de cuanto te falta*/
/*.metric-tile-value.complete {*/
/*    color: #16a34a;*/
/*}*/

/*.metric-tile-value.incomplete {*/
/*    color: #dc2626;*/
/*}*/

/* Small helper for "5 / 7" style, if used elsewhere */
.metric-tile-subvalue {
    font-size: 0.85rem;
    color: #4b5563;
}

/* Bar */
.student-progress-bar {
    position: relative;
    width: 100%;
    height: 8px;
    border-radius: 999px;
    background: #e5e7eb;
    overflow: hidden;
}

.student-progress-bar--mini {
    height: 4px;
    margin-top: 6px;
}

.student-progress-fill {
    position: absolute;
    inset: 0;
    width: 0;
    background: var(--button-blue);
    transition: width 0.25s ease-out;
}

.student-progress-fill.complete {
    background: green;
}

/* Empty state */
.students-empty-state {
    text-align: center;
    font-size: 0.95rem;
    color: #6b7280;
    padding: 20px 10px;
    display: none;
}

/* Existing detail modifiers (for second page) can stay: */
.student-summary-card.student-summary-card--full {
    cursor: default;
}

.ensemble-summary-card .ensemble-card-name {
    font-weight: 600;
}

.ensemble-summary-card .ensemble-card-subtitle {
    font-size: 0.85rem;
    color: #6b7280;
}

.report-summary-card.is-selected {
    outline: 1px solid var(--button-blue);
}

/* --------------- STUDENT ACTIVITY DETAIL --------------- */

/* Container for the entire activity page */
.course-card {
    background: #fff;
    border-radius: 8px;
    padding: 12px;
    margin-bottom: 24px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

/* COURSE HEADER */
.course-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 24px;
}

.course-icon {
    background: #F3E8FF;
    padding: 10px;
    border-radius: 8px;
}

.course-title {
    font-size: 18px;
    color: #111;
    font-weight: 600;
    line-height: 1.2;
    flex: 1;
    /* Flex items default to min-width:auto, which on a div containing
       a long unbreakable token (DICOM UID, URL) is the width of that
       token - the title would then push the whole row past the
       container's right edge. min-width:0 lets the title shrink with
       its row instead. */
    min-width: 0;
}

/* MODULE SECTION */
.module-section {
    border-left: 2px solid #ddd;
    padding-left: 16px;
    margin-bottom: 24px;
}

.module-header {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 16px;
}

.module-title {
    font-size: 16px;
    font-weight: 600;
    color: #222;
}

/* EXERCISE CARD */
.exercise-card {
    background: #F7F7F7;
    border: 1px solid #e5e7eb;
    border-left: 4px solid transparent;
    padding: 16px;
    margin-bottom: 14px;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(15,23,42,0.06);
}

.exercise-passed {
    /*border-left-color: #1976D2;*/
    border-left-color: #2dbd26;
}

.exercise-failed {
    border-left-color: #D32F2F;
}

.exercise-not-scored {
    border-left-color: #616161;
}

.exercise-blind {
    border-left-color: #b3aeda;
}

.exercise-not-attempted {
    border-left-color: #e5cd00;
}

/* EXERCISE HEADER */
.exercise-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
}

.exercise-title-group {
    display: flex;
    align-items: center;
    gap: 8px;
}

.exercise-title {
    font-size: 15px;
    font-weight: 600;
    color: #222;
}

/* PASSED / FAILED BADGE */
.exercise-status {
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 0.8rem;
    font-weight: 600;
}

.status-pass {
    background: #E0F2E9;
    color: #1E7A3C;
}

.status-fail {
    background: #FCE4E4;
    color: #B71C1C;
}

.status-not-scored {
    background: #F0F0F0;
    color: #616161;
}

.status-not-attempted {
    background: #f2f1e1;
    color: #7a761f;
}

/* "Hidden" pill rendered to the left of the regular passed/failed pill when
   the exercise is in blind mode (cases_views.finish IN (2,4)). Only emitted
   by the backend for student callers. */
.exercise-status-group {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.status-hidden {
    background: #e6e3f5;
    color: #4b3e8a;
}

/* TAGS */
.exercise-tags {
    display: flex;
    gap: 8px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}

/* STATS GRID */
.exercise-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
}

.stat-item {
    display: flex;
    align-items: center;
    gap: 8px;
    /*white-space: nowrap;*/
}

.stat-item p {
    margin: 0;
}

.student-stat-label {
    font-size: 0.9rem;
    color: #666;
}

.student-stat-value {
    font-size: 1rem;
    color: #111;
    font-weight: 500;
}

.tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px;
    flex-shrink: 0;
}

.tag.passed {
    background: #E8F5E9;
    color: #2E7D32;
}

.tag.not-passed {
    background: #f5e8e8;
    color: #7d2e2e;
}

.tag.blind {
    background: #e6e3f5;
    color: #4b3e8a;
}

.tag-icon svg {
    display: block;
}

.stat-icon svg {
    display: block;
    color: #6B7280;
}

/* ---------------------------- */

.my-courses-cards-wrapper {
    display: flex;
    flex-direction: column;
    gap: 4px;

    flex: 1;
    min-height: 0;
    overflow-y: auto;
    box-sizing: border-box;
    /* Reserve the vertical scrollbar's space even when not visible so
       cards never re-layout when the bar appears mid-render. Without
       this, a first paint with no scrollbar would size cards to the
       full container width; as soon as content overflows vertically,
       the scrollbar takes ~15px and the already-painted cards end up
       sticking out past the new right edge (the "under the scrollbar"
       symptom in cloud-courses + my-courses). */
    scrollbar-gutter: stable;
}

.key-card {
    border: 1px solid rgba(0,0,0,0.1);
    border-radius: 12px;
    overflow: hidden;
    background: white;

    height: auto;
    flex: 0 0 auto;   /* don’t let flex collapse it */
    min-height: fit-content;
}

.key-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    cursor: pointer;
    user-select: none;
    background: rgba(0,0,0,0.03);
}

.key-title {
    font-weight: 600;
}

.key-meta {
    margin-left: auto;
    opacity: 0.75;
    font-size: 12px;
}

/* Cloud-courses ensemble header splits clicks: title-text → select,
   everything-else → toggle expand. .key-header-rest is the toggle zone.
   flex:1 makes it absorb the horizontal blank space between the title
   and the right-aligned meta+chevron; its natural height keeps the
   vertical padding above/below the title outside any data-action, so
   those clicks are no-ops. */
.key-header-rest {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    justify-content: flex-end;
    cursor: pointer;
}

.key-header-rest .key-meta {
    margin-left: 0;
}

.key-body {
    padding: 10px 12px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.key-card.collapsed .key-body {
    display: none;
}

/* My-courses: ensembles are nested .key-card.ensemble-card inside each
   USB key's .key-body. Hierarchy reads as USB key -> ensemble -> course
   licenses, each with its own collapse toggle. Visually tinted so the
   inner level is distinct from the outer key card. */
.key-card.ensemble-card {
    background: #f8f9fb;
    border-color: rgba(0, 0, 0, 0.08);
}
.key-card.ensemble-card > .key-header {
    background: transparent;
}
.key-card.ensemble-card > .key-body {
    background: white;
}

/* Per-row "unlicense" buttons. The course-row variant tucks to the
   right of the row alongside the favorite star; the ensemble-header
   variant sits between the count and the chevron. Compact, neutral
   until hover (red), and pointer-stops-here so the surrounding row
   click handlers don't fire when the button is clicked. */
.course-unlicense-btn,
.ensemble-unlicense-btn {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border: 1px solid transparent;
    border-radius: 50%;
    background: transparent;
    color: #888;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.85rem;
    padding: 0;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.course-unlicense-btn:hover,
.ensemble-unlicense-btn:hover {
    background: #c0392b;
    color: white;
    border-color: #c0392b;
}

.course-card-mini {
    border: 1px solid rgba(0,0,0,0.10);
    border-radius: 12px;
    padding: 10px 12px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: white;
    box-sizing: border-box;
}

.course-card-mini.selected {
    outline: 1px solid rgba(25,118,210,0.9);
    outline-offset: 0;
}

.key-card.selected {
    outline: 1px solid rgba(25,118,210,0.9);
    outline-offset: -1px;
}

.course-row-top {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Star toggle buttons (per course + per ensemble). Icon-only, no
   chrome; the star color comes from the SVG fill (gold when set,
   transparent otherwise). The `stroke="currentColor"` in the SVG
   picks up the button's text color for the outline, so we set a
   neutral gray default that intensifies on hover. */
.course-fav-btn,
.ensemble-fav-btn {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border: 1px solid transparent;
    border-radius: 50%;
    background: transparent;
    color: #9ca3af;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.course-fav-btn:hover,
.ensemble-fav-btn:hover {
    background: #fff8e1;
    color: #fbc02d;
    border-color: #fbc02d;
}
/* Filled / half stars get the gold outline always so they read as
   "active" even before hover. */
.course-fav-btn[data-fav="1"],
.ensemble-fav-btn[data-fav-state="full"],
.ensemble-fav-btn[data-fav-state="half"] {
    color: #fbc02d;
}

/* Toolbar wrapping the search row + favorites filter. The search row
   takes all available width; the dropdown sits as its own element to
   the right at its natural width. */
.my-courses-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
}
.my-courses-toolbar > .students-search-row {
    flex: 1 1 auto;
    margin-bottom: 0;
    min-width: 0;
}
.my-courses-favorite-filter {
    flex: 0 0 auto;
    padding: 6px 10px;
    border: 1px solid #d8dde3;
    border-radius: 6px;
    background: white;
    color: #1f2937;
    font-size: 0.9rem;
    max-width: 100%;
    box-sizing: border-box;
}
/* On mobile, stack the search and the filter so the dropdown can't
   push past the right margin (its natural width was outgrowing the
   narrow viewport). */
@media (max-width: 768px) {
    .my-courses-toolbar {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
    }
    .my-courses-favorite-filter {
        width: 100%;
    }
}

.course-sub {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 12px;
    opacity: 0.85;
}

/* Course-group overlay: stack each card's sub-info lines (Published,
   Creator username, Creator name) vertically so long usernames / names
   don't push the row past the card edge on any viewport. Scoped to
   #courseGroupOverlay so the horizontal .course-sub layout used in
   my-courses / cloud-courses / course-groups / send-to-keys is untouched. */
#courseGroupOverlay .course-sub {
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
}
.course-sub-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 auto;
    min-width: 0;
}

.course-sub .course-uid {
    font-size: 11px;
    word-break: break-all;
}

/* ------ RECOMMENDED ENSEMBLES --------- */

/* Right panel: no vertical scrolling, constrained area */
.ensemble-info-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    flex: 1 1 50%;
    min-width: 0;
    align-items: center;
}

/* Fill available height */
.ensemble-viewer {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    position: relative;
    width: 100%;
    height: 100%;
}

/* Horizontal scroll for the OUTER PNG (width can exceed viewport) */
.ensemble-scroll {
    height: 100%;
    width: 100%;

    overflow-x: auto;
    overflow-y: hidden;

    scrollbar-width: none;

    display: flex;
    justify-content: center;
    align-items: center;
}
.ensemble-scroll::-webkit-scrollbar {
    display: none;
}

/*
  Canvas shrink-wraps to the OUTER IMAGE width,
  and its height is constrained by the viewer height via the image.
*/
.ensemble-canvas {
    position: relative;
    display: inline-block;
    height: 100%;
}

/* OUTER: height constrained to 100%, width auto (may overflow horizontally) */
.ensemble-outer-image {
    display: block;
    height: 100%;
    width: auto;
}

/* Chapters overlay relative to OUTER image box (the canvas matches it) */
.ensemble-chapters-overlay {
    position: absolute;
    left: 10%;
    bottom: 4%;
    width: 80%;
    height: 19%;

    overflow-x: auto;
    overflow-y: hidden;

    scrollbar-width: none;
    cursor: grab;

    z-index: 10;
}
.ensemble-chapters-overlay::-webkit-scrollbar {
    display: none;
}
.ensemble-chapters-overlay.dragging {
    cursor: grabbing;
}

/* Chapters image: fixed to overlay height; can overflow width → scroll */
.ensemble-chapters-image {
    height: 100%;
    width: auto;

    display: inline-block;

    max-width: none;
    min-width: max-content;
}

/* Spinner overlay inside panel */
.panel-spinner {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    align-items: center;
    justify-content: center;
    z-index: 20;

    /* non-blocking to rest of page; blocks only panel interactions */
    pointer-events: none;

    background: rgba(255, 255, 255, 0.65);
}

.panel-spinner i {
    font-size: 34px;
}

.panel-spinner-text {
    font-size: 14px;
    opacity: 0.85;
}

/* Empty state message */
.ensemble-empty-state {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 18px;
    text-align: center;
    z-index: 10;

    color: #444;
    background: rgba(255,255,255,0.75);
}

@media (max-width: 576px) {

    /* ------- HEADER -------- */

    .header{
        padding:16px 20px;
    }

    .header__subtitle, .header__user-email {
        font-size: 0.6rem;
    }

    .header__bottom,
    .page-main .header__bottom {

        margin-top: 10px;

        padding-left: 15px;
        padding-right: 15px;
        padding-bottom: 25px;
    }

    .header__logo, .header__university-logo{
        max-height:40px;
    }

    .header__logo{
        cursor: pointer;
    }

    /* ------- LOGIN SCREEN -------- */

    /* Vertically center the form in the leftover space below the header.
       .body-container is `display:flex; flex-direction:column`, so flex:1
       claims the remaining height; the inner flex centers the form within. */
    #loginScreen{
        margin-top:0;
        flex:1;
        display:flex;
        align-items:center;
        justify-content:center;
    }

    /* form sizing */
    form#loginForm{
        max-width:350px;
        width:100%;
        padding:0 16px;
    }

    form#loginForm label{
        font-size:1.25rem; /* smaller label on phones */
        margin-top:16px;
    }

    /* inputs: shorter & iOS-friendly font-size */
    form#loginForm input.form-control{
        height:56px;
        font-size:16px;      /* prevents iOS zoom on focus */
        padding-left:16px;
    }

    /* ------- MAIN DASHBOARD -------- */

    /* Stack the profile card and action menu vertically on mobile */
    .dashboard-container {
        flex-direction: column; /* Stack vertically */
        margin: 0;
        padding-top: 0;
        align-items: flex-start;
        gap: 30px;
    }

    .profile-card {
        width: 100%; /* Make profile card take full width */
        margin-bottom: 10px; /* Add some spacing between profile card and buttons */
        height: unset;
    }

    .profile-card__info {
        display: flex;
        flex-direction: column;
    }

    /* On mobile, keep the stats visible — render them as a compact row of
       columns (icon + label on top, value below) beneath the profile card top. */
    .profile-card__stats {
        display: block;
        padding: 15px 12px;
        flex-grow: 0;
        background-color: var(--text-background);
    }

    .profile-card__stats h4 {
        display: none;
    }

    .stats-grid {
        display: flex;
        flex-direction: row;
        gap: 12px;
        align-items: center;
        justify-content: space-around;
    }

    .stat {
        flex: 0 1 auto;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        gap: 6px;
        grid-template-columns: none;
        max-width: none;
        width: auto;
        min-width: 0;
    }

    .stat-label {
        display: none;
    }

    .stat i {
        justify-self: auto;
        font-size: 1rem;
    }

    .stat-value {
        justify-self: auto;
        font-size: 1rem;
    }

    .profile-card__top {
        flex-direction: row;
        justify-content: space-between;
        padding: 1.25rem 1.75rem;
    }

    .action-menu {
        width: 100%; /* Make action menu take full width */
    }

    /* Adjust buttons to be more spaced out vertically */
    .action-button {
        width: 100%; /* Make each action button take the full width of its container */
        margin-bottom: 0; /* Add some spacing between buttons */
    }

    /* Ensure profile card photo doesn't overflow and is responsive */
    .profile-card__photo {
        width: 80px; /* Adjust the photo size */
        height: 80px;
        margin-bottom: unset;
    }

    .page-title {
        font-size: 1.25rem;
        margin-left: 10px;
        margin-right: 10px;
    }

    .logout-text {
        display: none;
    }

    .info-toggle-btn {
        font-size: 1.2rem;
    }
    /* Recommended-ensembles-list toolbar phone overrides live next to
       the default .re-list-toolbar rule further down so the cascade
       order works (the default rule appears later in the stylesheet
       than this @media block, so phone-specific tweaks must sit after
       it). */

    .course-extra-info .extra-info-body {
        padding: 15px;
    }

    #selectionListPanel .extra-info-title {
        display: none;
    }

    #selectionListPanel .extra-info-section {
        border: none;
        background-color: unset;
        box-shadow: unset;
    }

    #selectionListPanel .extra-info-body {
        background-color: unset;
        padding: unset;
    }

    .tree-scroll {
        padding-right: 0;
    }

    .rc-card {
        flex: 0 0 auto;     /* key line: cards size to content */
        min-height: auto;
    }

    .report-config-layout {
        max-width: unset;
    }

    .modal-overlay-background.category-icons-grid {
        grid-template-columns: 1fr;
    }

    #cg-overlay-groups {
        padding: 8px;
        flex: 1;
    }

    #cg-overlay-courses {
        display: none;
    }

    /* Old send-to-keys mobile rules were removed (2026-05-06):
       - `.send-to-keys-user-info .tree-scroll { display: none }` hid the
         courses preview on phones; the new modal layout makes the
         preview the primary content for non-admins, so hiding it is
         wrong.
       - `.send-to-keys-user-info.rc-card { flex: 0 }` and the keys-card
         twin collapsed both cards to 0 height (flex: 0 expands to flex:
         0 1 0%, basis 0, no grow). The new `.stk-card--user/--keys
         { flex: 0 0 auto }` rule above gives them natural content
         height instead. */

    .send-to-keys-user-info {
        padding: 10px;
    }

    .send-to-keys-user-info .user-info {
        flex-direction: column;
    }

    .modal-overlay-background {
        flex-direction: column;
        width: 90%;
        height: 90%;
        padding: 6px;
        overflow-y: auto;
    }

    /* ----------- PAGE CONTENT -------- */
    .page-content {
        width: 100%;
        padding: 0 16px 16px 16px;
        box-sizing: border-box;
    }

    .page-content.legal-layout {
        padding-left: 0;
        padding-right: 0;
    }

    .legal-layout .rc-card {
        padding-left: 25px;
        padding-right: 25px;
    }

    /* Report-config rows: stack label above the control on phones so
       toggle groups (Automatic Report, Incomplete Reminder, Custom
       Email Text, Exercise Types) don't poke past the card edge, and
       so every row has a consistent left-aligned look. Scoped to
       .report-config-layout so other rc-row consumers (send-to-keys
       overlay, profile, etc.) keep their current layout. */
    .report-config-layout .rc-row {
        flex-direction: column;
        align-items: stretch;
        gap: 6px;
    }
    .report-config-layout .rc-row label {
        max-width: none;
    }
    .report-config-layout .rc-row input,
    .report-config-layout .rc-row select {
        min-width: 0;
        width: 100%;
    }
    /* Toggle groups: allow option pills to wrap to a new line instead of
       overflowing. The shared 1px row-border becomes per-pill so wrapped
       options still look bounded. */
    .report-config-layout .rc-row .rc-toggle-group {
        flex-wrap: wrap;
        max-width: 100%;
        overflow: visible;
        border: none;
        gap: 4px;
    }
    .report-config-layout .rc-row .rc-toggle-option {
        border: 1px solid #ccc;
        border-radius: 4px;
    }

    .page-main .body-container {
        height: auto;
        min-height: 100%;
        overflow: visible;
    }

    .student-summary-card {
        padding: 18px 16px;
    }

    .student-card-metrics--rich {
        grid-template-columns: 1fr 1fr;
    }

    .exercise-stats {
        grid-template-columns: repeat(2, 1fr);
    }

    .my-courses-cards-wrapper {
        padding-right: 0;
    }

    .students-cards-wrapper {
        padding-right: 0;
    }

    .ensemble-scroll {
        justify-content: unset;
    }
}


/* ============== Info-mode toggle + popover/modal ===================
   Self-installed by info_mode.js (loaded via common.js). The "?" button
   sits next to .page-title in every page's header__bottom. While
   .info-mode-on is on the body, every [data-info-key] element gets a
   dashed ring + help cursor, and hover (desktop) / tap (mobile) shows
   the explanation -- popover on desktop, full-width modal on mobile. */

.info-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    color: var(--button-blue);
    font-size: 1.4rem;
    line-height: 1;
    /* Nudge the icon down slightly so it sits visually centered with
       .page-title's text glyph (the title's inherited line-height ~1.2
       puts the title's flex-box midpoint a few px below the glyph
       midpoint; without this offset the icon reads as floating high). */
    transform: translateY(2px);
    cursor: pointer;
    padding: 0;
    transition: color 0.15s ease;
}
.info-toggle-btn:hover {
    color: var(--button-blue-hover);
}
.info-toggle-btn:focus {
    outline: none;
}
.info-toggle-btn:focus-visible {
    outline: 2px solid var(--button-blue);
    outline-offset: 2px;
    border-radius: 50%;
}
.info-toggle-btn.active {
    color: var(--button-blue-hover);
}

/* Annotation visual when info-mode is on. Subtle dashed ring + help cursor
   so the user can see at a glance which elements have explanations.
   Position: relative ensures the outline doesn't clip oddly inside flex
   parents that already use overflow. */
body.info-mode-on [data-info-key] {
    outline: 1px dashed rgba(47, 111, 237, 0.6);
    outline-offset: 3px;
    cursor: help;
}

/* Desktop popover: dark, narrow tooltip-style box. Positioned absolutely
   in document coords by info_mode.js. Pointer-events: none so the popover
   never sits between the user and the element they're hovering. */
.info-popover {
    position: absolute;
    z-index: 9999;
    max-width: 340px;
    padding: 12px 14px;
    background: #0f172a;
    color: white;
    font-size: 0.85rem;
    line-height: 1.5;
    border-radius: 6px;
    box-shadow: 0 6px 18px rgba(15, 23, 42, 0.25);
    pointer-events: none;
}

/* Shared summary/detail typography for both popover and modal. The
   summary is the one-line headline; the detail is everything after the
   blank-line separator in the i18n string. white-space: pre-wrap honors
   single \n inside the detail block. */
.info-summary {
    font-weight: 600;
    line-height: 1.4;
}
.info-summary + .info-detail {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.info-detail {
    white-space: pre-wrap;
    opacity: 0.9;
}
/* Inside the white modal the divider needs to be dark, not white. */
.info-modal .info-summary + .info-detail {
    border-top-color: rgba(15, 23, 42, 0.12);
}
.info-modal .info-detail {
    opacity: 1;
    color: #444;
}

/* Mobile modal: centered on viewport with a darkening backdrop. The
   backdrop click is what closes the modal -- the modal itself stops
   clicks from bubbling so taps inside don't accidentally dismiss. */
.info-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    z-index: 10000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.info-modal {
    position: relative;
    background: white;
    color: #222;
    width: 100%;
    max-width: 520px;
    max-height: 80vh;
    overflow: auto;
    padding: 24px 28px 24px 24px;
    border-radius: 10px;
    box-shadow: 0 12px 36px rgba(15, 23, 42, 0.3);
    font-size: 0.95rem;
    line-height: 1.5;
}
.info-modal-body {
    padding-right: 16px;
}
.info-modal-close {
    position: absolute;
    top: 6px;
    right: 10px;
    background: transparent;
    border: none;
    font-size: 1.7rem;
    line-height: 1;
    color: #666;
    cursor: pointer;
    padding: 4px 8px;
}
.info-modal-close:hover {
    color: #222;
}


/* ============== Recommended Ensembles -- list view (V2) ===============
   Parallel-prototype redesign of the recommended-ensembles page. All
   selectors are prefixed `re-list-` so they don't collide with the
   original page's classes. The page renders one horizontally-scrollable
   strip of ensemble cards. */

/* Structural rules (94% width, flex column, etc.) come from the shared
   .tree-container — see the HTML, which combines the two classes.
   .re-list-page only adds the page-specific gap between toolbar and
   strip; everything else stays in sync if .tree-container is ever
   updated. */
.re-list-page {
    gap: 20px;
}

.re-list-toolbar {
    display: flex;
    /* Single row at all viewports; the search shrinks to fit because of
       min-width: 0 on .students-search-row below. The phone breakpoint
       additionally tightens the gap and hides the sort label so search
       and sort never wrap to two rows. */
    flex-wrap: nowrap;
    align-items: center;
    gap: 16px;
    flex: 0 0 auto;
}
.re-list-toolbar .students-search-row {
    /* Allow the search wrapper to shrink below its <input>'s intrinsic
       min-content (default: ~20-char field). Without this it acts as a
       floor and pushes the sort group off the row. */
    min-width: 0;
}
/* Category-select icon in the toolbar. The icon's outer box is a 60x60
   rounded tile in the OPUS icon-blue (matching the .category-option
   chips in the category-select modal); the sprite inside is sized down
   to 50x50 so the colored frame is visible around it. */
.re-list-toolbar .re-list-category-icon {
    width: 60px;
    height: 60px;
    flex: 0 0 auto;
    cursor: pointer;
    background: var(--icon-blue);
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.re-list-toolbar .re-list-category-icon > .icon-sprite {
    width: 50px;
    height: 50px;
}

@media (max-width: 576px) {
    .re-list-toolbar {
        gap: 8px;
    }
    .re-list-toolbar .rtm-group-label {
        display: none;
    }
    .re-list-toolbar .rtm-sort-select {
        min-width: 0;
        width: auto;
    }
}

/* Search uses the canonical `.students-search-row` (already shared with
   my-courses, students-overview, etc.). Sort uses `.rtm-sort-group` /
   `.rtm-group-label` / `.rtm-sort-select` shared with real-time-monitor.
   See those rules elsewhere in this file. */

/* The strip: one row of cards, horizontal scroll. On desktop two-ish
   cards fit at typical widths. On mobile (<=768px) we lock to one card
   per viewport with snap-mandatory so swipe lands on a clean card.
   `cursor: grab` advertises that the strip itself is drag-scrollable
   (JS handler in recommended_ensembles_list.js). user-select is
   disabled across the whole strip so dragging never accidentally
   selects card text. The native scrollbar is hidden across vendors --
   navigation is via drag-scroll, and hiding the bar gives ~16px back
   to the cards' vertical room. `.dragging` is toggled while the strip
   itself is being dragged (chapters overlays use the same class scoped
   to their own element). */
.re-list-strip {
    display: flex;
    gap: 16px;
    overflow-x: auto;
    overflow-y: hidden;
    flex: 1 1 auto;
    min-height: 0;
    /* 4px padding-bottom gives the cards' box-shadow (1px offset + 3px
       blur = ~4px below) room before the strip's overflow-y: hidden
       clips it. Combined with body-container's 32px padding-bottom,
       total visible space below cards is 36px (a hair more than the
       canonical 32, traded for an uncut shadow). */
    padding: 4px 4px 4px 4px;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    scrollbar-width: none;          /* Firefox */
    -ms-overflow-style: none;       /* legacy Edge / IE */
    /* Snap the nearest card to center on scroll-release. Disabled while
       the user is actively dragging (.dragging) since the manual
       drag-scroll writes scrollLeft on every pointermove and a mandatory
       snap would yank back to the nearest snap point on every write. */
    scroll-snap-type: x mandatory;
}
.re-list-strip::-webkit-scrollbar {
    display: none;                  /* WebKit / Blink */
}
.re-list-strip.dragging {
    cursor: grabbing;
    scroll-behavior: auto;       /* avoid the smooth-scroll lag while dragging */
    scroll-snap-type: none;
}

/* Prevent native image-drag (the browser default that lets you drag a
   PNG out of the page) and route every pointer event through the
   image to the surrounding strip / chapters overlay so drag-scroll is
   uninterrupted. The outer image isn't clickable on its own, so losing
   pointer-events on it is harmless. */
.re-list-card-outer,
.re-list-card-chapters {
    -webkit-user-drag: none;
    user-drag: none;
    pointer-events: none;
}

.re-list-empty {
    color: #777;
    font-size: 0.95rem;
    padding: 24px;
    text-align: center;
}

/* Sizing is JS-driven on desktop: a ResizeObserver in
   recommended_ensembles_list.js measures the strip's height and sets
   each card's `width` so card_total_height (= width*993/1023 + footer)
   exactly fits. CSS just provides the column flex shell, the
   visuals, and a sensible default width for the brief moment between
   first paint and the first ResizeObserver callback. Mobile (<=768px)
   overrides below switch to a fixed full-viewport width and skip the
   JS sizing path. */
.re-list-card {
    flex: 0 0 auto;
    align-self: flex-start;
    display: flex;
    flex-direction: column;
    background: white;
    border: 1px solid #e2e6ea;
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
    overflow: hidden;
    box-sizing: border-box;
    scroll-snap-align: center;
}

/* Body holds the outer hero image with the chapters strip OVERLAID on
   top, mirroring the original .ensemble-canvas / .ensemble-chapters-
   overlay positioning (left:10%, bottom:4%, width:80%, height:19%).
   Desktop: `flex: 1 1 auto` makes body fill the card's vertical
   remainder (= card_height - footer); `aspect-ratio: 1023/993` then
   derives body width from that height. Mobile reverts to width-first
   (width:100% + aspect-ratio derives height). The shimmer gradient
   paints the body background until the image lands.
   ---------------------------------------------------------------
   KNOWN LIMITATION (mobile / narrow viewports): the source PNGs are
   designed for desktop and contain text laid out for desktop screen
   sizes. When the body shrinks to fit a phone-width card, the embedded
   text becomes too small to read. The proper long-term fix is to
   re-author mobile-optimized image variants (or replace the bitmap
   info with a structured DOM layout that reflows). The click-to-zoom
   modal in recommended_ensembles_list.js is a usability bridge
   until that authoring work happens, NOT the intended end state. */
.re-list-card-body {
    position: relative;
    overflow: hidden;
    /* Width-driven model: body width = card width (set explicitly by JS
       on desktop -- see resizeCards in recommended_ensembles_list.js --
       or width: 100% on mobile). Body height derives from
       aspect-ratio. flex: 0 0 auto keeps the body at its derived height
       so the footer always sits below the image. */
    flex: 0 0 auto;
    width: 100%;
    aspect-ratio: 1023 / 993;
    background: linear-gradient(90deg, #eef1f4 0%, #f7f8fa 50%, #eef1f4 100%);
    background-size: 200% 100%;
    animation: re-list-shimmer 1.4s linear infinite;
}
.re-list-card-outer {
    display: block;
    width: 100%;
    height: auto;
}
@keyframes re-list-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.re-list-card-chapters-overlay {
    position: absolute;
    left: 10%;
    bottom: 4%;
    width: 80%;
    height: 19%;
    overflow-x: auto;
    overflow-y: hidden;
    cursor: grab;
    z-index: 2;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.re-list-card-chapters-overlay::-webkit-scrollbar {
    display: none;
}
.re-list-card-chapters-overlay.dragging {
    cursor: grabbing;
}
.re-list-card-chapters {
    display: block;
    height: 100%;
    width: auto;
    max-width: none;
    min-width: max-content;
}

/* Footer (below the image) carries name, date, and the paper-plane
   send button. */
.re-list-card-foot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-top: 1px solid #eef1f4;
}
.re-list-card-name {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: #222;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1 1 auto;
    min-width: 0;
}
.re-list-card-date {
    color: #777;
    font-size: 0.82rem;
    flex: 0 0 auto;
}
.re-list-card-send {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border: 1px solid var(--button-blue);
    border-radius: 50%;
    background: white;
    color: var(--button-blue);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
    transition: background 0.15s, color 0.15s;
    padding: 0;
}
.re-list-card-send:hover {
    background: var(--button-blue);
    color: white;
}

/* Expanded mode. Clicking a card body promotes the strip itself to a
   fullscreen overlay - same DOM, same wiring, just a bigger envelope.
   Each card flips to flex: 0 0 100% with snap-center, so left/right
   arrow keys (handled in JS) advance one card at a time. The KNOWN
   LIMITATION note on .re-list-card-body still applies: this is a
   usability bridge until mobile-authored image variants land. */
.re-list-expanded-close {
    position: fixed;
    top: 12px;
    right: 12px;
    z-index: 10001;
    width: 36px;
    height: 36px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.95);
    color: #333;
    cursor: pointer;
    font-size: 1.4rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}
.re-list-expanded-close[hidden] {
    display: none;
}
.re-list-expanded-close:hover {
    background: white;
}

body.re-list-expanded-mode .re-list-strip {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(0, 0, 0, 0.85);
    padding: 24px;
    box-sizing: border-box;
    gap: 24px;
}
/* Cards keep their natural width (JS-driven on desktop, 100% on mobile)
   but center vertically in the now-100vh-tall strip. On desktop the card
   already fills the strip vertically so centering is a visual no-op; on
   mobile the card is body+footer tall and would otherwise sit at the top.
   The transform scales off-center cards down so the one nearest the
   viewport center pops; .is-focused (JS-toggled) restores full size.
   Scroll-snap-align is inherited from the base .re-list-card rule. */
body.re-list-expanded-mode .re-list-card {
    align-self: center;
    transform: scale(0.92);
    transform-origin: center center;
    transition: transform 180ms ease;
}
body.re-list-expanded-mode .re-list-card.is-focused {
    transform: scale(1);
}
/* Drag, wheel, and per-card chapters scroll all keep working unchanged
   - no DOM moves, only the strip's enclosing dimensions change. JS also
   applies inline padding-left/right so the first and last card can be
   centered by arrow-key navigation (see _applyExpandedSidePadding). */

@media (max-width: 576px) {
    body.re-list-expanded-mode .re-list-strip {
        padding: 12px;
        gap: 12px;
    }
}

/* Mobile: one card per viewport, slimmer toolbar. .re-list-page keeps
   the desktop 94% width — same pattern as .columns-container, which
   has no mobile override. Snap is inherited from the base .re-list-strip
   / .re-list-card rules; mobile only needs to switch cards to 100% width. */
@media (max-width: 768px) {
    .re-list-strip {
        gap: 12px;
    }
    .re-list-card {
        flex: 0 0 100%;
    }
}

/* ---------------- CLOUD-COURSES PRIVACY EDIT ---------------- */

/* Clickable cloud icon for owners (and EDIT_ANY admins) on cloud-courses.
   The icon itself keeps its existing 25x25 size; the dashed ring is an
   inline SVG circle painted as background-image so we can control the
   dash length precisely (CSS `border-style: dashed` doesn't expose dash
   density and renders too tightly for the look we want). */
.course-privacy-edit-btn {
    border: none;
    width: 25px;
    height: 25px;
    padding: 2px;
    cursor: pointer;
    line-height: 0;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: transparent;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'><circle cx='20' cy='20' r='18.5' fill='none' stroke='%234078c0' stroke-width='2' stroke-dasharray='8 6'/></svg>");
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-position: center;
    transition: background-color 0.12s;
}
.course-privacy-edit-btn:hover {
    background-color: rgba(64, 120, 192, 0.10);
}
.course-privacy-edit-btn:disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

/* EDIT_ANY admins editing a course they don't own: clickable wrapper
   but no visual chrome (no ring, no hover background). The icon stays
   at its natural 25x25, indistinguishable from the non-editable variant
   except that the cursor turns into a pointer. */
.course-privacy-edit-bare-btn {
    border: none;
    background: transparent;
    padding: 0;
    cursor: pointer;
    line-height: 0;
}
.course-privacy-edit-bare-btn:disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

/* Bulk privacy buttons (cloud-courses staged list + course-groups row).
   Sized like their sibling action buttons. The solid blue ring is
   replaced by the dashed-circle SVG used by the per-card privacy
   affordance (`.course-privacy-edit-btn`) so "click to edit privacy"
   reads consistently across the app. Hover only flips the background
   color (white -> blue, like siblings); the dashed ring and the
   cloud-lock sprite are left untouched. */
.cc-actions-row-btn--privacy,
.cg-list-row-btn--privacy {
    border: none;
    background-color: white;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'><circle cx='20' cy='20' r='18.5' fill='none' stroke='%234078c0' stroke-width='2' stroke-dasharray='8 6'/></svg>");
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-position: center;
}
.cc-actions-row-btn--privacy:hover,
.cg-list-row-btn--privacy:hover {
    background-color: var(--button-blue);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'><circle cx='20' cy='20' r='18.5' fill='none' stroke='%23ffffff' stroke-width='2' stroke-dasharray='8 6'/></svg>");
}
.privacy-cloud-lock-sprite {
    display: inline-block;
    width: 22px;
    height: 22px;
    background-image: url(../images/visibility/private.png);
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
}

/* Privacy modal: re-uses #popupOverlay + #popupContent from popup.js.
   The .privacy-modal class is added to popupContent so the rules below
   scope only to this dialog. Selector specificity is bumped to
   #popupContent.privacy-modal so width/box overrides beat the base
   #popupContent { max-width: 440px } rule (id specificity). */
#popupContent.privacy-modal {
    width: 90%;
    min-width: min(420px, 90vw);
    max-width: min(560px, 92vw);
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.privacy-modal__title {
    font-size: 1.1rem;
    font-weight: 600;
    color: #1f2937;
}
.privacy-modal__subtitle {
    font-size: 0.9rem;
    color: #6b7280;
    margin-top: -8px;
}
.privacy-modal__message {
    font-size: 0.9rem;
    color: #4b5563;
}
.privacy-modal__list-section {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.privacy-modal__list {
    list-style: none;
    padding: 0;
    margin: 0;
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    background: white;
}
.privacy-modal__row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid #f3f4f6;
}
.privacy-modal__row:last-child {
    border-bottom: none;
}
.privacy-modal__row-name {
    flex: 1;
    font-size: 0.92rem;
    color: #1f2937;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.privacy-modal__owner-tag {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #6b7280;
    background: #f3f4f6;
    padding: 2px 8px;
    border-radius: 999px;
}
.privacy-modal__row-remove {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: none;
    background: transparent;
    color: #888;
    border-radius: 50%;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.9rem;
    transition: background 0.15s, color 0.15s;
}
.privacy-modal__row-remove:hover {
    background: #c0392b;
    color: white;
}
.privacy-modal__add-row {
    display: flex;
    gap: 8px;
}
.privacy-modal__add-row input {
    flex: 1;
    padding: 6px 10px;
    border: 1px solid #d8dde3;
    border-radius: 6px;
    font-size: 0.9rem;
    background: white;
    color: #1f2937;
}
.privacy-modal__add-row input:focus {
    outline: none;
    border-color: var(--button-blue);
}

/* ---------------- CHANGE KEY OWNER MODAL ---------------- */

/* Reuses popupOverlay + popupContent from popup.js, same as the
   privacy modal. Specificity bumped via #popupContent.change-owner-modal
   so width overrides beat the base #popupContent rule. */
#popupContent.change-owner-modal {
    width: 90%;
    min-width: min(420px, 90vw);
    max-width: min(560px, 92vw);
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.change-owner-modal__title {
    font-size: 1.1rem;
    font-weight: 600;
    color: #1f2937;
}
.change-owner-modal__subtitle {
    font-size: 0.9rem;
    color: #6b7280;
    margin-top: -8px;
}
.change-owner-modal__section {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px;
    background: #f3f6fb;
    border-radius: 8px;
}
.change-owner-modal__section-header {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #6b7280;
    font-weight: 600;
}
.change-owner-modal__current-line {
    font-size: 0.95rem;
    color: #1f2937;
}
.change-owner-modal__input-row {
    display: flex;
    gap: 8px;
    align-items: center;
}
.change-owner-modal__input-row input {
    flex: 1;
    padding: 6px 10px;
    border: 1px solid #d8dde3;
    border-radius: 6px;
    font-size: 0.9rem;
    background: white;
    color: #1f2937;
    min-width: 0;
}
.change-owner-modal__input-row input:focus {
    outline: none;
    border-color: var(--button-blue);
}
.change-owner-modal__readout {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
}
.change-owner-modal__field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.change-owner-modal__field label {
    font-size: 0.78rem;
    color: #6b7280;
}
.change-owner-modal__field input {
    padding: 5px 8px;
    border: 1px solid #d8dde3;
    border-radius: 6px;
    font-size: 0.9rem;
    background: white;
    color: #1f2937;
    min-width: 0;
}
@media (max-width: 520px) {
    .change-owner-modal__readout {
        grid-template-columns: 1fr;
    }
}

/* ---------- Guided Report wizard ---------- */

.report-guided-layout {
    max-width: 60%;
}
@media (max-width: 1100px) {
    .report-guided-layout { max-width: 92%; }
}

.rg-wizard {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.rg-q {
    /* Inherits rc-card chrome (background, radius, shadow, padding). */
    transition: box-shadow 0.18s ease, transform 0.18s ease;
}

.rg-q-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.rg-subhead {
    font-size: 0.95rem;
    color: #555;
    margin-bottom: 4px;
}

/* Tile grid (used by Q1 ensembles + Q2 types) */
.rg-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px;
}
.rg-tiles--types {
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.rg-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    padding: 16px 12px;
    border: 1px solid #d8dde3;
    border-radius: 8px;
    background: #fff;
    cursor: pointer;
    text-align: center;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
    color: inherit;
    font: inherit;
}
.rg-tile:hover {
    border-color: var(--button-blue);
    box-shadow: 0 2px 8px rgba(47, 111, 237, 0.12);
    transform: translateY(-1px);
}
.rg-tile--selected {
    border-color: var(--button-blue);
    background: #eef4ff;
    box-shadow: 0 2px 8px rgba(47, 111, 237, 0.18);
}
.rg-tile-icon {
    font-size: 1.4rem;
    color: #4b5b7a;
}
.rg-tile--selected .rg-tile-icon { color: var(--button-blue); }
.rg-tile-label {
    font-weight: 600;
    font-size: 0.95rem;
}
.rg-tile-desc {
    font-size: 0.82rem;
    color: #5b6573;
    line-height: 1.35;
}

.rg-or-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 6px;
    flex-wrap: wrap;
}
.rg-or {
    color: #888;
    text-transform: uppercase;
    font-size: 0.8rem;
    letter-spacing: 0.05em;
}

.rg-q1-summary {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 12px;
    margin-top: 6px;
    border-left: 3px solid var(--button-blue);
    background: #f5f9ff;
    border-radius: 4px;
}
.rg-summary-label { font-size: 0.8rem; color: #5b6573; }
.rg-summary-value { font-weight: 600; }

/* Radio choices (Q3, Q4) */
.rg-choices {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.rg-choice {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 4px;
    cursor: pointer;
}
.rg-choice:hover { background: #f4f6fa; }

.rg-custom-dates {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px;
    background: #fafbfc;
    border-radius: 6px;
}

.rg-students-wrap {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 6px;
}
.rg-student-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-height: 220px;
    overflow-y: auto;
}
.rg-student-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 8px;
    background: #f6f8fb;
    border-radius: 4px;
}
.rg-rm-btn {
    background: transparent;
    border: none;
    color: #888;
    cursor: pointer;
    padding: 2px 6px;
    font-size: 0.9rem;
}
.rg-rm-btn:hover { color: #d23; }

.rg-continue { align-self: flex-start; }

/* Toggle rows (Q5) */
.rg-toggle-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px 0;
    border-bottom: 1px solid #eef0f4;
}
.rg-toggle-row:last-child { border-bottom: none; }
.rg-toggle-label {
    font-weight: 500;
}
.rg-toggle-note {
    font-size: 0.8rem;
    color: #888;
    font-style: italic;
}

