/* ============================================================
   PORTAL — Student-facing scoped polish styles
   Loaded conditionally via $portal_ui flag in includes/header.php.
   ============================================================ */

:root {
    --portal-primary:    #0a2463;
    --portal-secondary:  #1b6b93;
    --portal-accent:     #4fb3d9;
    --portal-success:    #198754;
    --portal-warning:    #f59e0b;
    --portal-danger:     #dc3545;
    --portal-muted:      #6c757d;
    --portal-text:       #1e293b;
    --portal-border:     #e5e7eb;
    --portal-surface:    #ffffff;
    --portal-panel:      #f8fafc;
    --portal-radius-sm:  8px;
    --portal-radius-md:  14px;
    --portal-radius-lg:  20px;
    --portal-shadow-sm:  0 4px 12px rgba(10, 36, 99, 0.06);
    --portal-shadow-md:  0 10px 28px rgba(10, 36, 99, 0.1);
}

/* ============================================================
   PORTAL DASHBOARD (.portal-dashboard)
   ============================================================ */
.portal-dashboard .metric-card {
    padding: 1.25rem 1.35rem;
    border-radius: var(--portal-radius-md);
    border: 1px solid var(--portal-border);
    background: var(--portal-surface);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    height: 100%;
    position: relative;
    overflow: hidden;
}
.portal-dashboard .metric-card::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background: linear-gradient(180deg, var(--portal-primary), var(--portal-secondary));
}
.portal-dashboard .metric-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--portal-shadow-md);
}
.portal-dashboard .metric-card .metric-label {
    text-transform: uppercase;
    letter-spacing: 0.07em;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--portal-secondary);
}
.portal-dashboard .metric-card .metric-value {
    font-size: 1.85rem;
    font-weight: 800;
    color: var(--portal-primary);
    line-height: 1.1;
    margin-top: 0.35rem;
}

.portal-dashboard .dashboard-card {
    padding: 1.5rem;
    border-radius: var(--portal-radius-lg);
    background: var(--portal-surface);
    border: 1px solid var(--portal-border);
    box-shadow: var(--portal-shadow-sm);
}
.portal-dashboard .dashboard-card .card-title-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 1.1rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--portal-border);
}
.portal-dashboard .dashboard-card h4 {
    color: var(--portal-primary);
    font-weight: 700;
    font-size: 1.1rem;
    margin: 0;
}

/* Course list items */
.portal-dashboard .course-item {
    padding: 1.15rem 1.25rem;
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    background: var(--portal-panel);
    margin-bottom: 1rem;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.portal-dashboard .course-item:last-child { margin-bottom: 0; }
.portal-dashboard .course-item:hover {
    border-color: rgba(27, 107, 147, 0.45);
    box-shadow: var(--portal-shadow-sm);
}
.portal-dashboard .course-item .course-title {
    font-weight: 700;
    color: var(--portal-primary);
    font-size: 1rem;
}
.portal-dashboard .course-item .course-instructor {
    font-size: 0.82rem;
    color: var(--portal-muted);
}
.portal-dashboard .course-item .progress-label {
    display: flex;
    justify-content: space-between;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--portal-muted);
    margin-bottom: 0.35rem;
}
.portal-dashboard .course-item .progress-label .pct {
    color: var(--portal-primary);
    font-weight: 800;
}
.portal-dashboard .course-item .progress-bar-track {
    height: 8px;
    background: #e9ecef;
    border-radius: 999px;
    overflow: hidden;
    margin-bottom: 0.85rem;
}
.portal-dashboard .course-item .progress-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--portal-secondary), var(--portal-accent));
    border-radius: 999px;
    transition: width 0.4s ease;
}

/* Status chip variants */
.portal-dashboard .stat-chip,
.portal-dashboard .soft-badge {
    display: inline-block;
    padding: 0.22rem 0.7rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border: 1px solid transparent;
}
.portal-dashboard .stat-chip.info    { background: #cff4fc; color: #055160; border-color: #b6effb; }
.portal-dashboard .stat-chip.success { background: #d1e7dd; color: #0f5132; border-color: #badbcc; }
.portal-dashboard .stat-chip.warning { background: #fff3cd; color: #664d03; border-color: #ffe69c; }
.portal-dashboard .stat-chip.danger  { background: #f8d7da; color: #842029; border-color: #f5c2c7; }
.portal-dashboard .soft-badge {
    background: rgba(27, 107, 147, 0.1);
    color: var(--portal-secondary);
    border-color: rgba(27, 107, 147, 0.2);
}

/* Recent reports table */
.portal-dashboard table.table-clean {
    font-size: 0.88rem;
}
.portal-dashboard table.table-clean thead th {
    background: var(--portal-panel);
    border-bottom: 1px solid var(--portal-border);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--portal-muted);
    padding: 0.7rem 0.85rem;
}
.portal-dashboard table.table-clean tbody td {
    padding: 0.75rem 0.85rem;
    border-bottom: 1px solid var(--portal-border);
    vertical-align: middle;
}
.portal-dashboard table.table-clean tbody tr:last-child td { border-bottom: none; }

/* Sidebar announcement / event cards */
.portal-dashboard .side-item {
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    padding: 1rem 1.1rem;
    background: var(--portal-surface);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.portal-dashboard .side-item:hover {
    border-color: rgba(27, 107, 147, 0.35);
    box-shadow: var(--portal-shadow-sm);
}
.portal-dashboard .side-item .item-title {
    font-weight: 700;
    color: var(--portal-primary);
    font-size: 0.92rem;
    line-height: 1.3;
}
.portal-dashboard .side-item .item-meta {
    font-size: 0.75rem;
    color: var(--portal-muted);
}
.portal-dashboard .side-item .item-preview {
    font-size: 0.82rem;
    color: #475569;
    line-height: 1.5;
    margin-top: 0.5rem;
}

/* Quick actions buttons */
.portal-dashboard .quick-actions .btn {
    border-radius: var(--portal-radius-sm);
    font-weight: 600;
    font-size: 0.85rem;
    padding: 0.6rem 0.9rem;
    text-align: left;
    display: flex;
    align-items: center;
    gap: 0.6rem;
}
.portal-dashboard .quick-actions .btn i {
    font-size: 1rem;
}
.portal-dashboard .quick-actions .btn-accent {
    background: linear-gradient(135deg, var(--portal-primary), var(--portal-secondary));
    border: none;
    color: #fff;
}
.portal-dashboard .quick-actions .btn-accent:hover {
    background: linear-gradient(135deg, #081e52, #155a7b);
    color: #fff;
}

.portal-dashboard .empty-block {
    padding: 1.75rem 1rem;
    text-align: center;
    color: var(--portal-muted);
    border: 1px dashed var(--portal-border);
    border-radius: var(--portal-radius-md);
    background: var(--portal-panel);
    font-size: 0.85rem;
}
.portal-dashboard .empty-block i {
    display: block;
    font-size: 1.75rem;
    margin-bottom: 0.5rem;
    color: #adb5bd;
}

@media (max-width: 767.98px) {
    .portal-dashboard .dashboard-card { padding: 1.15rem; }
    .portal-dashboard .metric-card { padding: 1rem 1.1rem; }
    .portal-dashboard .metric-card .metric-value { font-size: 1.5rem; }
}

/* ============================================================
   PORTAL COURSE PAGE (.portal-course)
   ============================================================ */
.portal-course .dashboard-card {
    padding: 1.5rem;
    border-radius: var(--portal-radius-lg);
    background: var(--portal-surface);
    border: 1px solid var(--portal-border);
    box-shadow: var(--portal-shadow-sm);
}

/* Overall progress bar */
.portal-course .course-progress-wrap {
    background: var(--portal-panel);
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    padding: 1rem 1.15rem;
}

/* Stat tiles under hero */
.portal-course .stat-tile {
    padding: 1rem 1.1rem;
    background: var(--portal-panel);
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    height: 100%;
}

/* Accordion polish */
.portal-course .accordion-item {
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    overflow: hidden;
    background: var(--portal-surface);
}

/* Inner panels (learning materials / module quizzes) */
.portal-course .accordion-body .border.rounded-3 {
    border-color: var(--portal-border) !important;
    border-radius: var(--portal-radius-md) !important;
    background: var(--portal-panel);
}

/* Course-level quizzes panel */
.portal-course .course-quizzes-panel {
    padding: 1.2rem 1.3rem;
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    background: linear-gradient(135deg, rgba(10, 36, 99, 0.03), rgba(27, 107, 147, 0.03));
}

/* Accent button variants */
.portal-course .btn-accent {
    background: linear-gradient(135deg, var(--portal-primary), var(--portal-secondary));
    border: none;
    color: #fff;
    font-weight: 600;
}

/* Sidebar: circular progress ring */
.portal-course .side-card h4 {
    color: var(--portal-primary);
    font-weight: 700;
    font-size: 1rem;
    margin: 0;
}

/* Empty state reuse */
.portal-course .empty-block {
    padding: 1.75rem 1rem;
    text-align: center;
    color: var(--portal-muted);
    border: 1px dashed var(--portal-border);
    border-radius: var(--portal-radius-md);
    background: var(--portal-panel);
    font-size: 0.85rem;
}

@media (max-width: 767.98px) {
}

/* =========================================================================
   PORTAL QUIZ TAKE PAGE (.portal-quiz-take)
   ========================================================================= */
.portal-quiz-take { color: var(--portal-text); }

/* Quiz Hero */
.portal-quiz-take .quiz-hero {
    position: relative;
    overflow: hidden;
    padding: 1.75rem 1.75rem 1.5rem;
}

/* Status strip (timer, answered count, etc.) */
.portal-quiz-take .quiz-status-strip {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.85rem;
    padding: 1rem;
    margin-bottom: 1.25rem;
    background: linear-gradient(135deg, rgba(13, 71, 161, 0.06), rgba(2, 136, 209, 0.05));
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
}
@keyframes quizPulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.08); }
}

/* Case Study — scenario header that introduces a group of sub-questions. */
.portal-quiz-take .quiz-case-header {
    background: linear-gradient(180deg, rgba(13, 71, 161, 0.06), rgba(13, 71, 161, 0.02));
    border: 1px solid rgba(13, 71, 161, 0.25);
    border-left: 4px solid #0d47a1;
    border-radius: var(--portal-radius-md);
    padding: 1.25rem 1.35rem 1rem;
    margin-top: 0.25rem;
}

/* Quiz form + questions */
.portal-quiz-take .quiz-form { margin-top: 0.5rem; }

/* Quiz choice label */
.portal-quiz-take .quiz-choice {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem 1rem;
    background: #fff;
    border: 1.5px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    cursor: pointer;
    transition: all 0.18s ease;
    margin: 0;
}

/* Question-type badge + hint on the taker */
.portal-quiz-take .quiz-qtype-badge {
    display: inline-flex;
    align-items: center;
    background: #eef2ff;
    color: #3730a3;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    padding: 0.25rem 0.6rem;
    border-radius: 999px;
    margin-bottom: 0.5rem;
}

/* SATA checkbox styling — indicates multi-select */
.portal-quiz-take .quiz-choice.is-sata input[type="checkbox"] { accent-color: var(--portal-primary); }

/* Identification text input */
.portal-quiz-take .quiz-text-input { margin-top: 0.75rem; }

/* Fill-in-the-blank inline inputs */
.portal-quiz-take .quiz-inline-blank {
    display: inline-block;
    min-width: 140px;
    max-width: 280px;
    padding: 0.2rem 0.55rem;
    margin: 0 0.25rem;
    border: 1px solid var(--portal-border);
    border-bottom: 2px solid var(--portal-primary);
    border-radius: 4px;
    background: #fdfdff;
    font-weight: 600;
    color: var(--portal-text);
    font-size: inherit;
    line-height: inherit;
    vertical-align: baseline;
}

/* Submit bar */
.portal-quiz-take .quiz-submit-bar {
    position: sticky;
    bottom: 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 1.1rem 1.25rem;
    background: #fff;
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.06);
    margin-top: 0.5rem;
}

/* Result celebration banner — sits above .quiz-result-summary on a
   completed attempt. Tier (excellent/strong/practice/review) is set
   from the score percentage in the template. Presentation-only —
   the data model doesn't carry a pass/fail threshold. */
.portal-quiz-take .quiz-result-banner {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.25rem;
    border-radius: var(--portal-radius-md);
    border: 1px solid;
    margin-bottom: 0.75rem;
}

/* Score gradient varies by tier so excellent results read as
   celebratory rather than identical to a low score. */
.portal-quiz-take .quiz-result-summary[data-score-tier="excellent"] .quiz-result-score-value {
    background: linear-gradient(135deg, #1F7A4D, #2DAA77);
    -webkit-background-clip: text;
    background-clip: text;
}

/* Result summary (completed attempt) */
.portal-quiz-take .quiz-result-summary {
    display: grid;
    grid-template-columns: minmax(220px, 1fr) 2fr;
    gap: 1.25rem;
    padding: 1.5rem;
    background: linear-gradient(135deg, rgba(13, 71, 161, 0.06), rgba(2, 136, 209, 0.06));
    border: 1px solid var(--portal-border);
    border-radius: var(--portal-radius-md);
    margin-bottom: 1rem;
}

/* Review question states */
.portal-quiz-take .quiz-review-list { display: grid; gap: 0.85rem; }

/* SATA "missed" state — correct option the student didn't select */
.portal-quiz-take .quiz-review-choice.is-missed {
    border-color: #2e7d32;
    background: #f1f8e9;
    border-style: dashed;
}

/* Text-answer review (identification / fill_blank) */
.portal-quiz-take .quiz-review-text { display: grid; gap: 0.6rem; margin-top: 0.5rem; }

/* Fill-in-the-blank review: inline chips inside the sentence */
.portal-quiz-take .quiz-review-blanks {
    line-height: 2.2;
    font-size: 1rem;
    margin-top: 0.35rem;
}

/* Rationale block */
.portal-quiz-take .quiz-rationale {
    margin-top: 1rem;
    padding: 0.85rem 1rem;
    border-left: 3px solid #f9a825;
    background: #fffbea;
    border-radius: var(--portal-radius-sm);
}

/* Sidebar side cards */
.portal-quiz-take .quiz-side-card { padding: 1.25rem 1.4rem; }

@media (max-width: 991.98px) {
}
@media (max-width: 575.98px) {
}

/* =========================================================================
   PORTAL RESULTS PAGE (.portal-results)
   ========================================================================= */
.portal-results { color: var(--portal-text); }

/* Hero */
.portal-results .results-hero {
    position: relative;
    overflow: hidden;
    padding: 1.75rem 1.75rem 1.5rem;
}

/* Stat tiles */
.portal-results .results-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.85rem;
}

/* Results table */
.portal-results .results-table-wrap { border-radius: var(--portal-radius-md); overflow: hidden; }

@media (max-width: 991.98px) {
}
@media (max-width: 575.98px) {
}

/* ========== Module completion ========== */
.module-done > .accordion-header .accordion-button {
    background: linear-gradient(to right, #f0fdf4, #ffffff);
}
.module-done-btn { transition: all .2s ease; }
.module-done-btn:disabled { opacity: .6; }

/* ===== Rationale supporting-material viewer (protected route) ===== */
.quiz-rationale-view-btn { font-size: 0.85rem; }
.rationale-modal { border-radius: 14px; overflow: hidden; }
.rationale-modal-body { background: #0f172a; }
.rationale-viewer-wrap {
    position: relative;
    min-height: 65vh;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.rationale-viewer-stage {
    position: relative;
    width: 100%;
    height: 75vh;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: auto;
    background: #0f172a;
}
.rationale-image {
    max-width: 100%;
    max-height: 75vh;
    object-fit: contain;
    user-select: none;
    -webkit-user-drag: none;
    pointer-events: auto;
}
.rationale-pdf {
    width: 100%;
    height: 75vh;
    border: 0;
    background: #fff;
}
/* Watermark overlay with student identity — repeated diagonally so any
   casual screenshot carries traceable text. Pointer-events:none keeps
   the overlay from blocking normal interactions. */
.rationale-watermark {
    position: absolute;
    inset: 0;
    pointer-events: none;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.18);
    font-weight: 600;
    font-size: 1rem;
    text-align: center;
    transform: rotate(-22deg);
    letter-spacing: 0.05em;
    text-shadow: 0 0 2px rgba(0,0,0,0.25);
    background-image:
        repeating-linear-gradient(
            -22deg,
            transparent 0,
            transparent 140px,
            rgba(255,255,255,0.04) 140px,
            rgba(255,255,255,0.04) 142px
        );
    white-space: pre;
    line-height: 2.4;
    padding: 1rem;
}
@media (max-width: 575.98px) {
    .rationale-viewer-stage { height: 65vh; }
    .rationale-pdf { height: 65vh; }
    .rationale-image { max-height: 65vh; }
    .rationale-watermark { font-size: 0.8rem; }
}

/* ============================================================
   LEARNER-FIRST STUDENT DESIGN LAYER (v2)
   Role-scoped under body.portal-ui. Purpose: give the student
   portal a calmer, warmer, more guided feel — softer surfaces,
   roomier rhythm, journey-oriented language — clearly distinct
   from the admin operations console.
   ============================================================ */
body.portal-ui {
    /* Spacing tokens — one step roomier than admin */
    --s-space-1: 4px;
    --s-space-2: 8px;
    --s-space-3: 12px;
    --s-space-4: 16px;
    --s-space-5: 24px;
    --s-space-6: 32px;
    --s-space-7: 48px;
    --s-space-8: 64px;

    /* Surface ramp — very soft */
    --s-surface-0: #ffffff;
    --s-surface-1: #F6FAFB;
    --s-surface-2: #EEF5F6;
    --s-border-subtle: #E3ECEE;
    --s-border-strong: #CCD9DB;

    /* Text */
    --s-text: #0F2030;
    --s-text-secondary: #495869;
    --s-text-muted: #6E7C8C;

    /* Role accent — teal-leaning blue-green, healthcare/calm */
    --s-accent: #2A7F86;
    --s-accent-600: #1F6A70;
    --s-accent-50: rgba(42,127,134,0.08);
    --s-accent-tint: #E8F4F5;

    /* Semantic (shared intent, softer presentation) */
    --s-success: #1f7a4d;
    --s-warning: #9b5a12;
    --s-danger:  #b42318;

    /* Radii — softer than admin */
    --s-radius-sm: 8px;
    --s-radius-md: 12px;
    --s-radius-lg: 16px;
    --s-radius-xl: 20px;

    font-size: 15px;
    color: var(--s-text);
}

/* ---- Shell + Sidebar: light, warm, flat ---- */
body.portal-ui .dashboard-shell {
    background: var(--s-surface-1);
}
body.portal-ui .dashboard-sidebar {
    background: #FBFCFD;
    background-image: none;
    color: var(--s-text);
    border-right: 1px solid var(--s-border-subtle);
    padding: var(--s-space-6) var(--s-space-4) var(--s-space-5);
}
body.portal-ui .dashboard-brand {
    gap: 12px;
    margin-bottom: var(--s-space-5);
    padding-bottom: var(--s-space-4);
    border-bottom: 1px solid var(--s-border-subtle);
}
body.portal-ui .dashboard-brand .fw-bold {
    color: var(--s-text);
    font-size: 15px;
    letter-spacing: -0.005em;
}
body.portal-ui .dashboard-brand small {
    color: var(--s-text-muted) !important;
    font-size: 12px;
}
/* "Signed in as" capsule */
body.portal-ui .dashboard-sidebar .rounded-4[style*="rgba(255,255,255,0.08)"] {
    background: var(--s-accent-tint) !important;
    border: 1px solid var(--s-border-subtle);
    border-radius: var(--s-radius-md) !important;
    padding: var(--s-space-3) var(--s-space-4) !important;
    margin-bottom: var(--s-space-5) !important;
    color: var(--s-text);
}
body.portal-ui .dashboard-sidebar .rounded-4 .fw-semibold {
    color: var(--s-text);
}

/* Student nav — pill-fill active, no groups, flat feel */
body.portal-ui .dashboard-nav .nav-link {
    color: var(--s-text-secondary);
    font-size: 14px;
    font-weight: 500;
    padding: 10px 14px;
    margin-bottom: 2px;
    border-radius: var(--s-radius-sm);
    gap: 12px;
    transition: background-color 140ms ease, color 140ms ease;
}
body.portal-ui .dashboard-nav .nav-link i {
    font-size: 16px;
    color: var(--s-text-muted);
}
body.portal-ui .dashboard-nav .nav-link:hover {
    background: var(--s-surface-2);
    color: var(--s-text);
}
body.portal-ui .dashboard-nav .nav-link.active {
    background: var(--s-accent-tint);
    color: var(--s-accent-600);
    font-weight: 600;
}
body.portal-ui .dashboard-nav .nav-link.active i { color: var(--s-accent); }
body.portal-ui .dashboard-nav .nav-section-label {
    font-size: 10px;
    letter-spacing: 0.1em;
    color: var(--s-text-muted);
    padding: var(--s-space-5) var(--s-space-3) var(--s-space-2);
    font-weight: 700;
    opacity: 0.75;
}
body.portal-ui .dashboard-nav .nav-link .badge.bg-warning {
    background: #FFE9C7 !important;
    color: #8A5A00 !important;
    font-size: 10px;
    font-weight: 700;
    padding: 3px 7px;
    border-radius: 6px;
}

/* ---- Main area + topbar: greeting-ready, more breathing room ---- */
body.portal-ui .dashboard-main {
    padding: var(--s-space-7) var(--s-space-7) var(--s-space-8);
}
body.portal-ui .dashboard-topbar {
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 0 0 var(--s-space-5);
    margin-bottom: var(--s-space-6);
    border-radius: 0;
}
body.portal-ui .dashboard-topbar .metric-label {
    font-size: 11px;
    letter-spacing: 0.1em;
    color: var(--s-text-muted);
    font-weight: 700;
    margin-bottom: 6px;
}
body.portal-ui .dashboard-topbar h2 {
    font-size: 26px !important;
    line-height: 34px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--s-text);
}
body.portal-ui .soft-badge {
    background: var(--s-surface-0);
    border: 1px solid var(--s-border-subtle);
    color: var(--s-text-secondary);
    font-size: 12px;
    font-weight: 600;
    padding: 6px 12px;
    border-radius: 999px;
}

/* ---- Surfaces: softer radii, no inner shadow ---- */
body.portal-ui .metric-card,
body.portal-ui .dashboard-card,
body.portal-ui .page-card {
    background: var(--s-surface-0);
    border: 1px solid var(--s-border-subtle);
    border-radius: var(--s-radius-lg);
    box-shadow: none;
}
body.portal-ui .metric-card { padding: var(--s-space-5); }
body.portal-ui .metric-label {
    font-size: 11px;
    letter-spacing: 0.08em;
    color: var(--s-text-muted);
    font-weight: 700;
}
body.portal-ui .metric-value {
    font-size: 30px;
    font-weight: 700;
    color: var(--s-text);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

/* ---- "Continue learning" hero card (student signature surface) ---- */
body.portal-ui .continue-hero {
    position: relative;
    background:
        linear-gradient(135deg, rgba(42,127,134,0.08) 0%, rgba(42,127,134,0.02) 60%),
        var(--s-surface-0);
    border: 1px solid var(--s-border-subtle);
    border-radius: var(--s-radius-xl);
    padding: var(--s-space-6) var(--s-space-6);
    box-shadow: 0 1px 2px rgba(15,32,48,0.02), 0 10px 28px rgba(42,127,134,0.06);
    overflow: hidden;
}
body.portal-ui .continue-hero::before {
    content: "";
    position: absolute; inset: 0 auto 0 0;
    width: 4px;
    background: var(--s-accent);
}
body.portal-ui .continue-hero .hero-eyebrow {
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--s-accent);
    font-weight: 700;
    margin-bottom: 6px;
}
body.portal-ui .continue-hero .hero-title {
    font-size: 24px;
    line-height: 32px;
    font-weight: 600;
    color: var(--s-text);
    letter-spacing: -0.01em;
}
body.portal-ui .continue-hero .hero-sub {
    font-size: 14px;
    color: var(--s-text-secondary);
    margin-top: 4px;
}
body.portal-ui .continue-hero .hero-cta {
    margin-top: var(--s-space-4);
}

/* ---- Calendar-date block (upcoming session card) ---- */
body.portal-ui .date-block {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 56px; height: 60px;
    background: var(--s-accent-tint);
    color: var(--s-accent-600);
    border-radius: var(--s-radius-md);
    padding: 6px 0;
    line-height: 1;
}
body.portal-ui .date-block .d-day {
    font-size: 22px; font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
body.portal-ui .date-block .d-month {
    font-size: 10px; font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-top: 2px;
    opacity: 0.85;
}

/* ---- Buttons: warmer, more guided ---- */
body.portal-ui .btn {
    font-size: 14px;
    font-weight: 600;
    padding: 9px 16px;
    border-radius: var(--s-radius-sm);
    line-height: 22px;
    transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease, transform 120ms ease;
}
body.portal-ui .btn-sm { font-size: 12.5px; padding: 6px 12px; }
body.portal-ui .btn-primary,
body.portal-ui .btn-accent {
    background: var(--s-accent);
    border-color: var(--s-accent);
    color: #fff;
}
body.portal-ui .btn-primary:hover,
body.portal-ui .btn-accent:hover {
    background: var(--s-accent-600);
    border-color: var(--s-accent-600);
    color: #fff;
}
body.portal-ui .btn-outline-secondary {
    background: var(--s-surface-0);
    border-color: var(--s-border-strong);
    color: var(--s-text-secondary);
}
body.portal-ui .btn-outline-secondary:hover {
    background: var(--s-surface-2);
    color: var(--s-text);
}
/* Hero CTA sizing */
body.portal-ui .btn-hero {
    font-size: 15px;
    padding: 12px 22px;
    border-radius: var(--s-radius-md);
}

/* ---- Focus ring ---- */
body.portal-ui :is(a, button, .btn, input, select, textarea, .nav-link):focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--s-accent);
    border-radius: var(--s-radius-sm);
}

/* ---- Forms: comfortable, friendly ---- */
body.portal-ui .form-label {
    font-size: 13px;
    font-weight: 600;
    color: var(--s-text-secondary);
    margin-bottom: 6px;
}
body.portal-ui .form-control,
body.portal-ui .form-select {
    font-size: 14px;
    padding: 10px 14px;
    border-radius: var(--s-radius-sm);
    border: 1px solid var(--s-border-strong);
    background: var(--s-surface-0);
}
body.portal-ui .form-control:focus,
body.portal-ui .form-select:focus {
    border-color: var(--s-accent);
    box-shadow: 0 0 0 3px var(--s-accent-50);
}
body.portal-ui .form-text { font-size: 12.5px; color: var(--s-text-muted); }

/* ---- Progress: thicker, more encouraging ---- */
body.portal-ui .progress.progress-soft {
    height: 10px;
    background: var(--s-surface-2);
    border-radius: 999px;
}
body.portal-ui .progress.progress-soft .progress-bar {
    background: var(--s-accent);
    border-radius: 999px;
}

/* ---- Status chips (learner tone) ---- */
body.portal-ui .stat-chip {
    font-size: 11px;
    padding: 4px 10px;
    font-weight: 700;
    border-radius: 999px;
    letter-spacing: 0.02em;
}
body.portal-ui .stat-chip.success { background: #E5F3EC; color: var(--s-success); }
body.portal-ui .stat-chip.info    { background: var(--s-accent-tint); color: var(--s-accent-600); }
body.portal-ui .stat-chip.warning { background: #FFF4E5; color: var(--s-warning); }

/* ---- Timeline list (quiz history, activity) ---- */
body.portal-ui .timeline-list li {
    padding: var(--s-space-4) 0;
    border-bottom: 1px solid var(--s-border-subtle);
    align-items: center;
    gap: var(--s-space-4);
}
body.portal-ui .timeline-date {
    min-width: 72px;
    color: var(--s-accent-600);
    font-weight: 700;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
}

/* ---- Tables (student side — comfortable, scan-light) ---- */
body.portal-ui .table,
body.portal-ui table.table-clean {
    font-size: 14px;
}
body.portal-ui .table thead th,
body.portal-ui .table-clean thead th {
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--s-text-muted);
    font-weight: 700;
    background: transparent;
    border-bottom: 1px solid var(--s-border-strong);
    padding: 12px;
}
body.portal-ui .table tbody td {
    padding: 16px 12px;
    border-bottom: 1px solid var(--s-border-subtle);
    vertical-align: middle;
}
body.portal-ui .table tbody tr:hover { background: var(--s-surface-2); }

/* ---- Empty state (encouraging tone) ---- */
body.portal-ui .portal-empty {
    text-align: center;
    padding: var(--s-space-7) var(--s-space-5);
    color: var(--s-text-secondary);
    max-width: 440px;
    margin: 0 auto;
}
body.portal-ui .portal-empty i {
    font-size: 36px;
    color: var(--s-accent);
    opacity: 0.55;
    display: block;
    margin-bottom: var(--s-space-3);
}
body.portal-ui .portal-empty .empty-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--s-text);
    margin-bottom: 6px;
}

/* ---- Accordion (soft learner tone) ---- */
body.portal-ui .accordion {
    border: 1px solid var(--s-border-subtle);
    border-radius: var(--s-radius-lg);
    overflow: hidden;
    background: var(--s-surface-0);
}
body.portal-ui .accordion-item { border: none; border-bottom: 1px solid var(--s-border-subtle); background: transparent; }
body.portal-ui .accordion-item:last-child { border-bottom: none; }
body.portal-ui .accordion-button {
    background: transparent;
    font-size: 15px;
    font-weight: 600;
    color: var(--s-text);
    padding: 16px 20px;
    box-shadow: none !important;
}
body.portal-ui .accordion-button:not(.collapsed) {
    background: var(--s-accent-tint);
    color: var(--s-accent-600);
}
body.portal-ui .accordion-body { padding: var(--s-space-5); }

/* Mobile */
@media (max-width: 991.98px) {
    body.portal-ui .dashboard-main { padding: var(--s-space-4); }
    body.portal-ui .continue-hero { padding: var(--s-space-5); }
    body.portal-ui .continue-hero .hero-title { font-size: 20px; line-height: 28px; }
}

/* =====================================================================
   STEP 4 — Student dashboard identity and landing-page polish
   ===================================================================== */
body.portal-ui .dashboard-sidebar {
    position: relative;
    background:
        linear-gradient(180deg, rgba(255,255,255,0.96) 0%, rgba(247,251,252,0.98) 100%);
}
body.portal-ui .dashboard-sidebar::after {
    content: "";
    position: absolute;
    top: 18px;
    right: 16px;
    left: 16px;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(42,127,134,0.14), transparent);
    pointer-events: none;
}
body.portal-ui .portal-brand-mark {
    width: 48px;
    height: 48px;
    border-radius: 16px;
    background: linear-gradient(145deg, rgba(42,127,134,0.12), rgba(42,127,134,0.05));
    border: 1px solid rgba(42,127,134,0.14);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.75);
}
body.portal-ui .portal-student-card {
    background: linear-gradient(180deg, rgba(232,244,245,0.95), rgba(255,255,255,0.96)) !important;
    border: 1px solid rgba(42,127,134,0.14);
    border-radius: 18px !important;
    box-shadow: 0 10px 24px rgba(42,127,134,0.06);
}
body.portal-ui .portal-student-card__branch {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    font-weight: 700;
    color: var(--s-accent-600);
    background: rgba(255,255,255,0.72);
    border: 1px solid rgba(42,127,134,0.12);
    border-radius: 999px;
    padding: 6px 10px;
}
body.portal-ui .dashboard-nav {
    gap: 2px;
}
body.portal-ui .dashboard-nav .nav-link {
    min-height: 44px;
    display: flex;
    align-items: center;
    border: 1px solid transparent;
}
body.portal-ui .dashboard-nav .nav-link:hover {
    background: rgba(255,255,255,0.82);
    border-color: rgba(42,127,134,0.08);
}
body.portal-ui .dashboard-nav .nav-link.active {
    background: linear-gradient(135deg, rgba(42,127,134,0.14), rgba(42,127,134,0.06));
    border-color: rgba(42,127,134,0.14);
    box-shadow: 0 8px 18px rgba(42,127,134,0.08);
}
body.portal-ui .dashboard-nav .nav-section-label {
    padding-top: var(--s-space-6);
    padding-bottom: var(--s-space-2);
}
body.portal-ui .dashboard-main {
    background:
        radial-gradient(circle at top right, rgba(42,127,134,0.04), transparent 32%),
        linear-gradient(180deg, #fcfefe 0%, #f7fafb 100%);
}
body.portal-ui .dashboard-topbar {
    align-items: flex-end;
}
body.portal-ui .portal-page-intro {
    margin-top: 8px;
    max-width: 680px;
    font-size: 14px;
    line-height: 1.65;
    color: var(--s-text-secondary);
}
body.portal-ui .portal-topbar-actions {
    justify-content: flex-end;
}
body.portal-ui .portal-branch-pill {
    background: rgba(255,255,255,0.9);
    box-shadow: 0 1px 2px rgba(15,32,48,0.03);
}
body.portal-ui .portal-support-link {
    box-shadow: 0 10px 22px rgba(42,127,134,0.16);
}
body.portal-ui .portal-dashboard .metric-card,
body.portal-ui .portal-dashboard .dashboard-card {
    box-shadow: 0 12px 26px rgba(15,32,48,0.04);
}
body.portal-ui .portal-dashboard .metric-card {
    border-radius: 18px;
    background: linear-gradient(180deg, rgba(255,255,255,0.96), rgba(248,251,252,0.98));
}
body.portal-ui .portal-dashboard .metric-card::before {
    width: 5px;
    background: linear-gradient(180deg, var(--s-accent), #5fc4ca);
}
body.portal-ui .portal-dashboard .metric-card .metric-value {
    color: var(--s-text);
}
body.portal-ui .portal-dashboard .dashboard-card {
    border-radius: 22px;
    padding: 1.65rem;
}
body.portal-ui .portal-dashboard .dashboard-card .card-title-row {
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 1.25rem;
}
body.portal-ui .portal-dashboard .dashboard-card h4 {
    color: var(--s-text);
    font-size: 1.06rem;
    font-weight: 700;
}
body.portal-ui .portal-dashboard .section-helper {
    margin-top: 0.28rem;
    font-size: 0.84rem;
    line-height: 1.55;
    color: var(--s-text-muted);
    max-width: 46ch;
}
body.portal-ui .continue-hero {
    border-radius: 24px;
    background:
        radial-gradient(circle at top right, rgba(95,196,202,0.18), transparent 28%),
        linear-gradient(135deg, rgba(42,127,134,0.08) 0%, rgba(42,127,134,0.03) 56%),
        #ffffff;
    padding: 1.9rem 2rem;
}
/* Phase 12 — drop max-width:12ch on hero-title; it forced course
   titles to wrap to 4+ lines on every viewport. The title now flows
   to fit the hero card width. */
body.portal-ui .continue-hero .hero-sub {
    max-width: 58ch;
}
body.portal-ui .portal-dashboard .course-item {
    background: linear-gradient(180deg, rgba(248,251,252,0.96), rgba(255,255,255,0.98));
    border-radius: 18px;
    margin-bottom: 1.1rem;
}
body.portal-ui .portal-dashboard .course-item:hover {
    box-shadow: 0 12px 24px rgba(42,127,134,0.06);
}
body.portal-ui .portal-dashboard .course-next-up {
    background: linear-gradient(135deg, rgba(42,127,134,0.1), rgba(42,127,134,0.03));
    border-left: 3px solid var(--s-accent);
    border-radius: 12px;
}
body.portal-ui .portal-dashboard .side-item {
    background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(249,252,252,0.98));
    border-radius: 18px;
    padding: 1.05rem 1.1rem;
}
body.portal-ui .portal-dashboard .side-item .item-title {
    color: var(--s-text);
}
body.portal-ui .portal-dashboard .quick-actions .btn {
    min-height: 46px;
    border-radius: 14px;
    justify-content: flex-start;
    padding-inline: 14px;
}
body.portal-ui .portal-dashboard .quick-actions .btn-outline-secondary {
    background: rgba(255,255,255,0.96);
}
body.portal-ui .portal-dashboard .timeline-list li {
    padding-top: 1rem;
    padding-bottom: 1rem;
}
body.portal-ui .portal-dashboard .timeline-list .date-block {
    flex: 0 0 auto;
}
@media (max-width: 991.98px) {
    body.portal-ui .dashboard-sidebar {
        border-right: 0;
        border-bottom: 1px solid var(--s-border-subtle);
    }
    body.portal-ui .dashboard-topbar {
        align-items: stretch;
    }
    body.portal-ui .portal-topbar-actions {
        justify-content: flex-start;
    }
}
@media (max-width: 767.98px) {
    body.portal-ui .dashboard-main {
        padding: var(--s-space-4) var(--s-space-3) var(--s-space-6);
    }
    body.portal-ui .dashboard-sidebar {
        padding: var(--s-space-4) var(--s-space-3);
    }
    body.portal-ui .portal-page-intro {
        font-size: 13px;
    }
    body.portal-ui .portal-dashboard .dashboard-card {
        padding: 1.2rem;
        border-radius: 18px;
    }
    body.portal-ui .portal-dashboard .section-helper {
        max-width: none;
    }
}

/* =========================================================================
   STEP 5 — STUDENT INNER PAGE READABILITY POLISH
   ========================================================================= */
.portal-content {
    color: var(--portal-text);
}
.portal-content .page-hint {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    background: linear-gradient(135deg, #eef5ff, #f7fbff);
    border: 1px solid #d9e8fb;
    color: #24466b;
    padding: 0.9rem 1rem;
    border-radius: 16px;
    font-size: 0.92rem;
    line-height: 1.55;
    box-shadow: var(--portal-shadow-sm);
}
.portal-content .page-hint i {
    color: var(--portal-primary);
    font-size: 1rem;
    margin-top: 0.08rem;
}
.portal-content .dashboard-card {
    border-radius: 22px;
    box-shadow: 0 14px 34px rgba(10, 36, 99, 0.08);
}
.portal-content .card-title-row {
    align-items: flex-start;
    padding-bottom: 0.9rem;
    margin-bottom: 1.15rem;
    border-bottom: 1px solid rgba(15, 23, 42, 0.08);
}
.portal-content .card-title-row h4 {
    color: var(--portal-primary);
    font-size: 1.08rem;
    font-weight: 800;
}
.portal-content .card-title-row .text-muted {
    max-width: 62ch;
    line-height: 1.55;
}
.portal-content .dashboard-empty {
    background: linear-gradient(180deg, #ffffff, #fbfdff);
    border: 1px solid rgba(15, 23, 42, 0.08);
    border-radius: 18px;
    padding: 1.15rem 1.2rem;
    box-shadow: var(--portal-shadow-sm);
}
.portal-content .dashboard-empty h5 {
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--portal-primary);
    margin-bottom: 0.45rem;
}
.portal-content .soft-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* Quizzes hub */
.portal-quizzes .quiz-card {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 100%;
}
.portal-quizzes .quiz-card .text-muted { line-height: 1.55; }
.portal-quizzes .quiz-card .small.text-muted { font-size: 0.82rem; }
.portal-quizzes .quiz-card .d-flex.gap-2.flex-wrap {
    margin-top: auto;
    padding-top: 0.3rem;
}

/* Files */
.portal-files .files-table thead th {
    background: #f7fbff;
    color: #5b6b7f;
    font-size: 0.73rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 800;
    border-bottom: 1px solid rgba(15,23,42,0.08);
    padding-top: 0.85rem;
    padding-bottom: 0.85rem;
}
.portal-files .files-table tbody td {
    padding-top: 0.95rem;
    padding-bottom: 0.95rem;
    vertical-align: middle;
}
.portal-files .files-table tbody tr:hover {
    background: rgba(13, 71, 161, 0.03);
}

/* Calendar */
.portal-calendar #calendar-grid {
    padding: 0.2rem;
    border-radius: 18px;
    background: linear-gradient(180deg, #ffffff, #fbfdff);
}
.portal-calendar .calendar-list-item {
    background: linear-gradient(180deg, #ffffff, #fcfdff);
    border-color: rgba(15,23,42,0.08) !important;
    box-shadow: var(--portal-shadow-sm);
}
.portal-calendar .calendar-list-item .fw-semibold {
    color: var(--portal-primary);
    font-size: 1rem;
}
.portal-calendar .calendar-list-item .small { line-height: 1.5; }
.portal-calendar .btn-outline-secondary.active {
    background: rgba(13, 71, 161, 0.08);
    border-color: rgba(13, 71, 161, 0.2);
    color: var(--portal-primary);
}

/* Reports and grades */
.portal-results .page-hint,
.portal-grades .page-hint {
    box-shadow: var(--portal-shadow-sm);
    border-radius: 16px;
}
.portal-results .results-table tbody td,
.portal-grades .table-sm tbody td {
    line-height: 1.45;
}
.portal-results .results-table .btn,
.portal-grades .table-sm .btn {
    border-radius: 10px;
    font-weight: 600;
}
.portal-grades h5 {
    color: var(--portal-primary);
    font-weight: 800;
    letter-spacing: -0.01em;
}
.portal-grades .table-light th {
    background: #f7fbff;
    color: #5b6b7f;
    font-size: 0.73rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Course + quiz page readability boost */
.portal-course .course-intro,
.portal-quiz-take .quiz-rationale-body,
.portal-quiz-take .quiz-case-scenario,
.portal-quiz-take .quiz-qtext {
    max-width: 72ch;
}

@media (max-width: 991.98px) {
    .portal-content .card-title-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.65rem;
    }
    .portal-content .dashboard-card {
        border-radius: 18px;
        padding: 1.15rem;
    }
}
@media (max-width: 575.98px) {
    .portal-content .page-hint {
        font-size: 0.85rem;
        padding: 0.8rem 0.9rem;
    }
    .portal-files .files-table thead th,
    .portal-grades .table-light th {
        font-size: 0.68rem;
    }
}

/* ============================================================
   STEP 6 — ROLE DISTINCTION: STUDENT EXPERIENCE
   Makes student feel lighter, calmer, more guided.
   ============================================================ */
body.portal-ui .dashboard-shell {
    background:
        radial-gradient(circle at top left, rgba(79,179,217,0.12), transparent 28%),
        linear-gradient(180deg, #f7fbfe 0%, #f9fbfd 38%, #f4f8fc 100%);
}

body.portal-ui .dashboard-sidebar {
    background:
        linear-gradient(180deg, rgba(10,36,99,0.96) 0%, rgba(17,64,120,0.94) 52%, rgba(27,107,147,0.92) 100%);
    border-right: 1px solid rgba(255,255,255,0.08);
    box-shadow: inset -1px 0 0 rgba(255,255,255,0.05), 22px 0 44px rgba(10,36,99,0.09);
    padding: 1.5rem 1rem 1.75rem;
}

body.portal-ui .dashboard-brand {
    padding: 0.25rem 0.15rem 0.95rem;
    border-bottom: 1px solid rgba(255,255,255,0.09);
    margin-bottom: 1rem;
}

body.portal-ui .portal-brand-mark {
    width: 48px;
    height: 48px;
    border-radius: 16px;
    background: linear-gradient(135deg, rgba(255,255,255,0.18), rgba(255,255,255,0.06));
    border: 1px solid rgba(255,255,255,0.14);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 12px 24px rgba(8,24,72,0.16);
}

body.portal-ui .portal-student-card {
    background: linear-gradient(180deg, rgba(255,255,255,0.12), rgba(255,255,255,0.07));
    border: 1px solid rgba(255,255,255,0.12);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.06);
}

body.portal-ui .dashboard-nav .nav-section-label {
    color: rgba(255,255,255,0.58);
    letter-spacing: 0.14em;
    padding: 0.95rem 0.8rem 0.38rem;
}

body.portal-ui .dashboard-nav .nav-link {
    border-radius: 16px;
    padding: 0.86rem 1rem;
    font-size: 0.94rem;
    font-weight: 600;
    color: rgba(255,255,255,0.86);
    transition: background-color .18s ease, transform .18s ease, box-shadow .18s ease;
}

body.portal-ui .dashboard-nav .nav-link:hover {
    transform: translateX(2px);
    background: rgba(255,255,255,0.12);
}

body.portal-ui .dashboard-nav .nav-link.active {
    background: linear-gradient(135deg, rgba(255,255,255,0.2), rgba(255,255,255,0.09));
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1), 0 10px 24px rgba(8,24,72,0.12);
    color: #fff;
}

body.portal-ui .dashboard-main {
    padding: 2.1rem 2rem 2.35rem;
}

body.portal-ui .dashboard-topbar {
    border-radius: 24px;
    padding: 1.15rem 1.35rem;
    border: 1px solid rgba(27,107,147,0.08);
    background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(249,252,254,0.96));
    box-shadow: 0 14px 32px rgba(27,107,147,0.07);
}

body.portal-ui .dashboard-topbar h2 {
    color: #0b285f;
    letter-spacing: -0.03em;
}

body.portal-ui .portal-page-intro {
    max-width: 760px;
    color: #5f738f;
    font-size: 0.95rem;
    line-height: 1.65;
}

body.portal-ui .metric-label {
    color: #52708f;
}

body.portal-ui .metric-card,
body.portal-ui .dashboard-card {
    border-radius: 22px;
    border: 1px solid rgba(27,107,147,0.09);
    box-shadow: 0 14px 32px rgba(27,107,147,0.06);
}

body.portal-ui .dashboard-card {
    background: linear-gradient(180deg, rgba(255,255,255,1), rgba(251,253,255,0.98));
}

body.portal-ui .dashboard-card .card-title-row {
    padding-bottom: 0.9rem;
    border-bottom: 1px solid rgba(27,107,147,0.08);
}

body.portal-ui .dashboard-card h4 {
    color: #0d2d66;
    font-size: 1.08rem;
}

body.portal-ui .soft-badge {
    background: rgba(79,179,217,0.12);
    color: #165b7e;
    border: 1px solid rgba(79,179,217,0.18);
}

body.portal-ui .portal-branch-pill {
    background: rgba(79,179,217,0.12);
    border-color: rgba(79,179,217,0.18);
}

body.portal-ui .portal-support-link {
    box-shadow: 0 10px 24px rgba(27,107,147,0.15);
}

body.portal-ui .portal-dashboard .course-item,
body.portal-ui .portal-dashboard .side-item,
body.portal-ui .page-hint,
body.portal-ui .quiz-card,
body.portal-ui .file-card,
body.portal-ui .calendar-card,
body.portal-ui .report-card,
body.portal-ui .grade-card {
    border-radius: 18px;
}

body.portal-ui table.table-clean thead th {
    background: rgba(79,179,217,0.08);
    color: #657a95;
}

body.portal-ui table.table-clean tbody tr:hover {
    background: rgba(79,179,217,0.05);
}

body.portal-ui .empty-block {
    background: linear-gradient(180deg, rgba(255,255,255,0.95), rgba(247,251,254,0.98));
    border-color: rgba(79,179,217,0.18);
    color: #6b7c92;
}

@media (max-width: 991.98px) {
    body.admin-ui .dashboard-main,
    body.portal-ui .dashboard-main {
        padding: 1.15rem;
    }
}

/* ============================================================
   STEP 7 — Final student portal polish pass
   Premium refinement, consistency, and responsiveness
   ============================================================ */
body.portal-ui {
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

body.portal-ui .dashboard-shell {
    background:
        radial-gradient(circle at top right, rgba(79,179,217,0.08), transparent 24%),
        linear-gradient(180deg, #f4f9fc 0%, #eef5fa 100%);
}

body.portal-ui .dashboard-main > * + * {
    margin-top: 1.1rem;
}

body.portal-ui .dashboard-topbar,
body.portal-ui .dashboard-card,
body.portal-ui .metric-card,
body.portal-ui .page-hint,
body.portal-ui .quiz-card,
body.portal-ui .file-card,
body.portal-ui .calendar-card,
body.portal-ui .report-card,
body.portal-ui .grade-card {
    transition: box-shadow .18s ease, border-color .18s ease, transform .18s ease;
}

body.portal-ui .dashboard-card:hover,
body.portal-ui .metric-card:hover,
body.portal-ui .quiz-card:hover,
body.portal-ui .file-card:hover,
body.portal-ui .calendar-card:hover,
body.portal-ui .report-card:hover,
body.portal-ui .grade-card:hover {
    box-shadow: 0 18px 34px rgba(27,107,147,0.09);
}

body.portal-ui .dashboard-card,
body.portal-ui .quiz-card,
body.portal-ui .file-card,
body.portal-ui .calendar-card,
body.portal-ui .report-card,
body.portal-ui .grade-card,
body.portal-ui .page-hint {
    overflow: hidden;
}

body.portal-ui .portal-page-intro,
body.portal-ui .text-muted,
body.portal-ui small.text-muted {
    color: #657993 !important;
}

body.portal-ui .dashboard-nav .nav-link {
    min-height: 2.95rem;
}

body.portal-ui .dashboard-nav .nav-link .badge {
    margin-left: auto;
}

body.portal-ui :is(button, a, input, select, textarea, .nav-link, .accordion-button):focus-visible {
    outline: none;
    box-shadow: 0 0 0 0.2rem rgba(79,179,217,0.18), 0 0 0 1px rgba(11,40,95,0.08);
}

body.portal-ui .dashboard-topbar {
    overflow: hidden;
}

body.portal-ui .dashboard-topbar h2,
body.portal-ui .dashboard-card h4,
body.portal-ui .quiz-card h4,
body.portal-ui .file-card h4,
body.portal-ui .calendar-card h4,
body.portal-ui .report-card h4,
body.portal-ui .grade-card h4 {
    letter-spacing: -0.025em;
}

body.portal-ui .btn-accent,
body.portal-ui .portal-support-link,
body.portal-ui .btn-primary {
    border: 0;
    box-shadow: 0 12px 24px rgba(27,107,147,0.14);
}

body.portal-ui .btn-accent:hover,
body.portal-ui .portal-support-link:hover,
body.portal-ui .btn-primary:hover {
    transform: translateY(-1px);
}

body.portal-ui .soft-badge,
body.portal-ui .portal-branch-pill,
body.portal-ui .status-pill,
body.portal-ui .metric-label {
    letter-spacing: 0.03em;
}

body.portal-ui table.table-clean {
    border-collapse: separate;
    border-spacing: 0;
}

body.portal-ui table.table-clean thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    backdrop-filter: blur(10px);
}

body.portal-ui table.table-clean tbody td {
    line-height: 1.5;
}

body.portal-ui .empty-block {
    border-radius: 18px;
}

body.portal-ui .dashboard-card .card-title-row,
body.portal-ui .quiz-card .card-title-row,
body.portal-ui .file-card .card-title-row,
body.portal-ui .calendar-card .card-title-row,
body.portal-ui .report-card .card-title-row,
body.portal-ui .grade-card .card-title-row {
    margin-bottom: 1rem;
}

body.portal-ui .rationale-block,
body.portal-ui .quiz-rationale,
body.portal-ui .review-rationale {
    line-height: 1.7;
}

body.portal-ui .student-answer,
body.portal-ui .correct-answer,
body.portal-ui .review-answer {
    border-radius: 14px;
}

@media (max-width: 1199.98px) {
    body.portal-ui .dashboard-main {
        padding: 1.55rem 1.4rem 1.8rem;
    }
}

@media (max-width: 991.98px) {
    body.portal-ui .dashboard-topbar {
        padding: 1rem 1rem 1.05rem;
        border-radius: 20px;
    }

    body.portal-ui .dashboard-card,
    body.portal-ui .metric-card,
    body.portal-ui .page-hint,
    body.portal-ui .quiz-card,
    body.portal-ui .file-card,
    body.portal-ui .calendar-card,
    body.portal-ui .report-card,
    body.portal-ui .grade-card {
        border-radius: 18px;
    }
}

@media (max-width: 767.98px) {
    body.portal-ui .dashboard-main > * + * {
        margin-top: 0.9rem;
    }

    body.portal-ui .dashboard-topbar h2 {
        font-size: 1.35rem;
    }

    body.portal-ui table.table-clean thead th {
        position: static;
    }
}

/* ============================================================
   CALENDAR STEP 4 — Student page shell redesign
   ============================================================ */
.portal-calendar .calendar-shell {
    display: grid;
    gap: 1.15rem;
}
.portal-calendar .calendar-page-intro {
    padding: 1.4rem 1.5rem 1.45rem;
    border-radius: 24px;
    background:
      radial-gradient(circle at top right, rgba(79,179,217,0.14), transparent 28%),
      linear-gradient(180deg, rgba(255,255,255,0.98), rgba(247,251,254,0.98));
    border: 1px solid rgba(79,179,217,0.18);
    box-shadow: 0 18px 40px rgba(27,107,147,0.08);
}
.portal-calendar .calendar-page-intro__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
}
.portal-calendar .calendar-kicker {
    display: inline-flex;
    align-items: center;
    padding: 0.38rem 0.75rem;
    border-radius: 999px;
    background: rgba(79,179,217,0.12);
    color: #1b6b93;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 0.75rem;
}
.portal-calendar .calendar-page-intro h3 {
    color: var(--portal-primary);
    font-size: 1.55rem;
    font-weight: 800;
    letter-spacing: -0.03em;
}
.portal-calendar .calendar-page-intro p {
    max-width: 68ch;
    line-height: 1.65;
}
.portal-calendar .calendar-view-switch {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem;
    border-radius: 999px;
    background: rgba(11,40,95,0.05);
    border: 1px solid rgba(11,40,95,0.08);
}
.portal-calendar .calendar-view-switch__btn {
    border: 0;
    background: transparent;
    color: #55708b;
    border-radius: 999px;
    padding: 0.72rem 1rem;
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1;
    transition: background .18s ease, color .18s ease, box-shadow .18s ease;
}
.portal-calendar .calendar-view-switch__btn:hover {
    background: rgba(79,179,217,0.1);
    color: var(--portal-primary);
}
.portal-calendar .calendar-view-switch__btn.is-active {
    background: linear-gradient(135deg, #1b6b93, #4fb3d9);
    color: #fff;
    box-shadow: 0 14px 28px rgba(27,107,147,0.18);
}
.portal-calendar .calendar-view-switch__btn:focus-visible,
.portal-calendar .calendar-filter-bar .form-select:focus-visible,
.portal-calendar .calendar-filter-bar .form-control:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 4px rgba(79,179,217,0.18);
}
.portal-calendar .calendar-summary-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.9rem;
}
.portal-calendar .calendar-summary-card {
    min-height: 138px;
    padding: 1rem 1.05rem;
    border-radius: 20px;
    background: linear-gradient(180deg, #ffffff, #fbfdff);
    border: 1px solid rgba(11,40,95,0.08);
    box-shadow: 0 14px 30px rgba(27,107,147,0.07);
}
.portal-calendar .calendar-summary-card--accent {
    background: linear-gradient(180deg, rgba(27,107,147,0.08), rgba(79,179,217,0.06));
    border-color: rgba(27,107,147,0.16);
}
.portal-calendar .calendar-summary-card__label {
    color: #6a8198;
    font-size: 0.74rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 0.7rem;
}
.portal-calendar .calendar-summary-card__value {
    color: var(--portal-primary);
    font-size: 1.08rem;
    font-weight: 800;
    line-height: 1.3;
    letter-spacing: -0.02em;
    margin-bottom: 0.45rem;
}
.portal-calendar .calendar-summary-card__number {
    color: var(--portal-primary);
    font-size: 2rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.04em;
    margin-bottom: 0.55rem;
}
.portal-calendar .calendar-summary-card__meta {
    color: #647991;
    font-size: 0.87rem;
    line-height: 1.55;
}
.portal-calendar .calendar-main-card {
    padding: 1.2rem 1.2rem 1.15rem;
}

.portal-calendar .calendar-filter-bar {
    display: grid;
    gap: 0.9rem;
    padding: 1rem 1.05rem;
    border-radius: 20px;
    border: 1px solid rgba(11,40,95,0.08);
    background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(247,251,254,0.98));
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.65);
}
.portal-calendar .calendar-filter-bar__search {
    display: grid;
    gap: 0.45rem;
}
.portal-calendar .calendar-filter-bar__grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.8rem;
}
.portal-calendar .calendar-filter-field {
    display: grid;
    gap: 0.42rem;
}
.portal-calendar .calendar-filter-bar__label {
    color: #5b7088;
    font-size: 0.76rem;
    font-weight: 800;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}
.portal-calendar .calendar-search-field {
    position: relative;
}
.portal-calendar .calendar-search-field i {
    position: absolute;
    top: 50%;
    left: 0.9rem;
    transform: translateY(-50%);
    color: #6a8097;
    font-size: 0.95rem;
    pointer-events: none;
}
.portal-calendar .calendar-search-field .form-control,
.portal-calendar .calendar-filter-field .form-select {
    min-height: 46px;
    border-radius: 14px;
    border-color: rgba(11,40,95,0.12);
    background: #fff;
    color: var(--portal-primary);
    box-shadow: 0 10px 20px rgba(27,107,147,0.04);
}
.portal-calendar .calendar-search-field .form-control {
    padding-left: 2.6rem;
}
.portal-calendar .calendar-filter-bar__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding-top: 0.15rem;
}
.portal-calendar .calendar-filter-bar__status {
    display: grid;
    gap: 0.2rem;
}
.portal-calendar .calendar-preference-note {
    display: inline-flex;
    align-items: center;
    gap: 0.38rem;
    color: #5d7992;
    font-size: 0.78rem;
    font-weight: 600;
}
.portal-calendar .calendar-preference-note i {
    color: #1b6b93;
}
.portal-calendar .calendar-filter-summary {
    color: #667d93 !important;
    font-size: 0.84rem !important;
    line-height: 1.55;
}
.portal-calendar .calendar-filter-bar .btn-outline-secondary {
    border-color: rgba(79,179,217,0.2);
    color: var(--portal-primary);
    background: rgba(255,255,255,0.86);
}
.portal-calendar .calendar-filter-bar .btn-outline-secondary:hover {
    border-color: rgba(79,179,217,0.3);
    background: rgba(79,179,217,0.08);
    color: var(--portal-primary);
}
.portal-calendar .calendar-main-card__head {
    align-items: flex-start;
    gap: 1rem;
}
.portal-calendar .calendar-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.85rem;
    justify-content: flex-end;
}
.portal-calendar .calendar-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 0.42rem;
    color: #5f748d;
    font-size: 0.8rem;
    font-weight: 700;
}
.portal-calendar .calendar-legend__dot {
    width: 0.72rem;
    height: 0.72rem;
    border-radius: 999px;
    display: inline-block;
}
.portal-calendar .calendar-legend__dot.is-session { background: #4fb3d9; }
.portal-calendar .calendar-legend__dot.is-exam { background: #ef6b73; }
.portal-calendar .calendar-legend__dot.is-office { background: #6a8bd6; }
.portal-calendar .calendar-legend__dot.is-deadline { background: #f0b24f; }
.portal-calendar .calendar-agenda-header h5 {
    color: var(--portal-primary);
    font-size: 1.02rem;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.portal-calendar .calendar-agenda-group {
    display: grid;
    gap: 0.85rem;
    padding: 0.25rem 0;
}
.portal-calendar .calendar-agenda-group__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.85rem;
    padding-bottom: 0.2rem;
}
.portal-calendar .calendar-agenda-group__title {
    margin: 0;
    color: var(--portal-primary);
    font-size: 1rem;
    font-weight: 800;
    letter-spacing: -0.02em;
}
.portal-calendar .calendar-agenda-group__subtitle {
    color: #6e8197;
    font-size: 0.84rem;
    line-height: 1.55;
    margin-top: 0.18rem;
}
.portal-calendar .calendar-agenda-group__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.46rem 0.8rem;
    border-radius: 999px;
    background: rgba(11,40,95,0.06);
    color: var(--portal-primary);
    font-size: 0.76rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}
.portal-calendar .calendar-agenda-group__items {
    display: grid;
    gap: 0.85rem;
}
.portal-calendar .calendar-list-item {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 1.05rem;
    border-radius: 20px;
    border: 1px solid rgba(11,40,95,0.08);
    background: linear-gradient(180deg, #ffffff, #fcfdff);
    box-shadow: 0 14px 26px rgba(27,107,147,0.06);
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
    cursor: pointer;
}
.portal-calendar .calendar-list-item:hover {
    transform: translateY(-1px);
    border-color: rgba(79,179,217,0.22);
    box-shadow: 0 18px 30px rgba(27,107,147,0.1);
}
.portal-calendar .calendar-list-item__main {
    min-width: 0;
    display: grid;
    gap: 0.42rem;
}
.portal-calendar .calendar-list-item__aside {
    flex: 0 0 auto;
    min-width: 150px;
    text-align: right;
}
.portal-calendar .calendar-list-item__meta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.42rem;
    align-items: center;
}
.portal-calendar .calendar-list-item__title {
    margin: 0;
    color: var(--portal-primary);
    font-size: 1.02rem;
    font-weight: 800;
    line-height: 1.35;
    letter-spacing: -0.02em;
}
.portal-calendar .calendar-list-item__schedule {
    color: #58708a;
    font-size: 0.9rem;
    font-weight: 700;
}
.portal-calendar .calendar-list-item__details {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem 0.85rem;
    color: #6c8197;
    font-size: 0.84rem;
    line-height: 1.5;
}
.portal-calendar .calendar-list-item__details span {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.portal-calendar .calendar-list-item__notes {
    color: #5f7085;
    font-size: 0.88rem;
    line-height: 1.65;
    padding-top: 0.15rem;
}
.portal-calendar .calendar-list-item__provider {
    color: #6f7f93;
    font-size: 0.82rem;
    font-weight: 700;
}
.portal-calendar .calendar-list-item__aside .btn {
    min-width: 130px;
}
.portal-calendar .calendar-list-item__aside .small {
    color: #667d93 !important;
    line-height: 1.5;
}
.portal-calendar #calendar-grid {
    padding: 0.75rem;
    border-radius: 20px;
    background: linear-gradient(180deg, #ffffff, #f9fcff);
    border: 1px solid rgba(79,179,217,0.14);
}
.portal-calendar .fc .fc-toolbar.fc-header-toolbar {
    margin-bottom: 1rem;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.portal-calendar .fc .fc-toolbar-title {
    color: var(--portal-primary);
    font-size: 1.12rem;
    font-weight: 800;
    letter-spacing: -0.02em;
}
.portal-calendar .fc .fc-button {
    background: #fff;
    color: var(--portal-primary);
    border-color: rgba(79,179,217,0.22);
    border-radius: 12px;
    box-shadow: 0 10px 22px rgba(27,107,147,0.06);
    font-weight: 700;
    padding: 0.45rem 0.75rem;
}
.portal-calendar .fc .fc-button:hover,
.portal-calendar .fc .fc-button:focus {
    background: rgba(79,179,217,0.08);
    color: var(--portal-primary);
    border-color: rgba(79,179,217,0.28);
}
.portal-calendar .fc .fc-button.fc-button-active,
.portal-calendar .fc .fc-button:active {
    background: linear-gradient(135deg, rgba(27,107,147,0.12), rgba(79,179,217,0.16));
    color: var(--portal-primary);
    border-color: rgba(79,179,217,0.32);
}
.portal-calendar .fc .fc-daygrid-day.fc-day-today {
    background: rgba(79,179,217,0.08);
}
.portal-calendar .fc .fc-daygrid-day-number {
    font-weight: 700;
    color: var(--portal-primary);
}
@media (max-width: 1199.98px) {
    .portal-calendar .calendar-summary-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .portal-calendar .calendar-filter-bar__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
@media (max-width: 767.98px) {
    .portal-calendar .calendar-page-intro,
    .portal-calendar .calendar-main-card {
        padding: 1rem;
        border-radius: 20px;
    }
    .portal-calendar .calendar-summary-grid {
        grid-template-columns: 1fr;
    }
    .portal-calendar .calendar-filter-bar {
        padding: 0.9rem;
        border-radius: 18px;
    }
    .portal-calendar .calendar-filter-bar__grid {
        grid-template-columns: 1fr;
    }
    .portal-calendar .calendar-filter-bar__actions {
        align-items: stretch;
    }
    .portal-calendar .calendar-filter-bar__status {
        gap: 0.32rem;
    }
    .portal-calendar .calendar-filter-bar__actions .btn {
        width: 100%;
    }
    .portal-calendar .calendar-view-switch {
        width: 100%;
        justify-content: stretch;
    }
    .portal-calendar .calendar-view-switch__btn {
        flex: 1 1 0;
        justify-content: center;
    }
    .portal-calendar .calendar-legend {
        justify-content: flex-start;
    }
    .portal-calendar .calendar-agenda-group__head,
    .portal-calendar .calendar-list-item {
        flex-direction: column;
    }
    .portal-calendar .calendar-list-item__aside {
        width: 100%;
        min-width: 0;
        text-align: left;
    }
    .portal-calendar .calendar-list-item__aside .btn {
        width: 100%;
    }
}

.portal-calendar .calendar-event-modal__dialog {
    max-width: 760px;
}
.portal-calendar .calendar-event-modal {
    border: 1px solid rgba(79,179,217,0.16);
    border-radius: 28px;
    overflow: hidden;
    background: linear-gradient(180deg, #ffffff, #fbfdff);
    box-shadow: 0 28px 60px rgba(17,65,99,0.18);
}
.portal-calendar .calendar-event-modal__header {
    align-items: flex-start;
    padding: 1.35rem 1.4rem 1rem;
    border-bottom: 1px solid rgba(11,40,95,0.08);
    background: radial-gradient(circle at top right, rgba(79,179,217,0.14), transparent 38%), linear-gradient(180deg, rgba(255,255,255,0.98), rgba(247,251,254,0.98));
}
.portal-calendar .calendar-event-modal__header-copy {
    display: grid;
    gap: 0.3rem;
}
.portal-calendar .calendar-event-modal__eyebrow {
    display: inline-flex;
    align-items: center;
    width: fit-content;
    padding: 0.36rem 0.7rem;
    border-radius: 999px;
    background: rgba(79,179,217,0.12);
    color: #1b6b93;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.portal-calendar .calendar-event-modal .modal-title {
    color: var(--portal-primary);
    font-size: 1.35rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.2;
}
.portal-calendar .calendar-event-modal__subtitle {
    color: #5f748d;
    font-size: 0.93rem;
    font-weight: 600;
    line-height: 1.55;
}
.portal-calendar .calendar-event-modal__body {
    padding: 1.2rem 1.35rem 1.35rem;
    display: grid;
    gap: 1rem;
}
.portal-calendar .calendar-event-modal__badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.portal-calendar .calendar-event-modal__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem;
}
.portal-calendar .calendar-event-modal__meta-card {
    padding: 0.9rem 0.95rem;
    border-radius: 18px;
    background: linear-gradient(180deg, #ffffff, #f8fbff);
    border: 1px solid rgba(11,40,95,0.08);
    box-shadow: 0 12px 24px rgba(17,65,99,0.05);
}
.portal-calendar .calendar-event-modal__meta-card.type-info,
.portal-calendar .calendar-event-modal__meta-card.delivery-primary,
.portal-calendar .calendar-event-modal__meta-card.status-info {
    border-color: rgba(79,179,217,0.18);
}
.portal-calendar .calendar-event-modal__meta-card.status-success {
    border-color: rgba(56,166,110,0.22);
    background: linear-gradient(180deg, #ffffff, #f6fcf8);
}
.portal-calendar .calendar-event-modal__meta-card.status-warning,
.portal-calendar .calendar-event-modal__meta-card.type-warning,
.portal-calendar .calendar-event-modal__meta-card.type-danger {
    border-color: rgba(240,178,79,0.22);
    background: linear-gradient(180deg, #ffffff, #fffaf1);
}
.portal-calendar .calendar-event-modal__meta-label {
    color: #70859b;
    font-size: 0.75rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 0.45rem;
}
.portal-calendar .calendar-event-modal__meta-value {
    color: var(--portal-primary);
    font-size: 0.98rem;
    font-weight: 700;
    line-height: 1.5;
}
.portal-calendar .calendar-event-modal__section {
    padding: 0.95rem 1rem;
    border-radius: 18px;
    border: 1px solid rgba(11,40,95,0.08);
    background: rgba(255,255,255,0.9);
}
.portal-calendar .calendar-event-modal__section-label {
    color: #70859b;
    font-size: 0.76rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 0.5rem;
}
.portal-calendar .calendar-event-modal__notes,
.portal-calendar .calendar-event-modal__status-copy {
    color: #576f87;
    font-size: 0.94rem;
    line-height: 1.68;
}
.portal-calendar .calendar-event-modal__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding-top: 0.15rem;
}
.portal-calendar .calendar-event-modal__actions .btn {
    min-width: 155px;
    font-weight: 700;
}
@media (max-width: 767.98px) {
    .portal-calendar .calendar-event-modal__header,
    .portal-calendar .calendar-event-modal__body {
        padding-left: 1rem;
        padding-right: 1rem;
    }
    .portal-calendar .calendar-event-modal__grid {
        grid-template-columns: 1fr;
    }
    .portal-calendar .calendar-event-modal .modal-title {
        font-size: 1.12rem;
    }
    .portal-calendar .calendar-event-modal__actions .btn {
        width: 100%;
    }
}

/* ==========================================================================
   Student portal — Pass 4 closeout layer
   Ships: flattened sidebar with new program-capsule + sidebar-foot,
   hint-banner for empty-state softening, and 2x2 resource-tile grid
   replacing the outline-button "Quick links" list.
   Scoped to body.portal-ui so nothing leaks to admin or public pages.
   ========================================================================== */

/* --- Sidebar: program capsule (replaces the old translucent card) ---- */
body.portal-ui .program-capsule {
    padding: 0.9rem 1rem;
    border-radius: 14px;
    background: rgba(42, 127, 134, 0.06);
    border: 1px solid rgba(42, 127, 134, 0.14);
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}
body.portal-ui .program-capsule__name {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--s-text, #0F2030);
    line-height: 1.3;
}
body.portal-ui .program-capsule__program {
    font-size: 0.8rem;
    color: var(--s-text-muted, #6E7C8C);
    line-height: 1.4;
}
body.portal-ui .program-capsule__branch {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.4rem;
    padding: 0.2rem 0.55rem;
    background: #ffffff;
    border: 1px solid rgba(42, 127, 134, 0.15);
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--s-accent, #2A7F86);
    align-self: flex-start;
}

/* --- Sidebar footer: help link + soft logout ------------------------- */
body.portal-ui .sidebar-foot {
    margin-top: auto;
    padding-top: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
body.portal-ui .sidebar-help-link {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    padding: 0.75rem 0.85rem;
    background: rgba(42, 127, 134, 0.08);
    border: 1px solid rgba(42, 127, 134, 0.16);
    border-radius: 12px;
    text-decoration: none;
    color: var(--s-text, #0F2030);
    transition: background 0.18s ease, border-color 0.18s ease;
}
body.portal-ui .sidebar-help-link:hover {
    background: rgba(42, 127, 134, 0.14);
    border-color: rgba(42, 127, 134, 0.28);
    color: var(--s-text, #0F2030);
}
body.portal-ui .sidebar-help-link i {
    font-size: 1.1rem;
    color: var(--s-accent, #2A7F86);
    margin-top: 0.1rem;
}
body.portal-ui .sidebar-help-link strong {
    display: block;
    font-size: 0.88rem;
    font-weight: 700;
    line-height: 1.3;
}
body.portal-ui .sidebar-help-link span {
    display: block;
    font-size: 0.75rem;
    color: var(--s-text-muted, #6E7C8C);
    line-height: 1.4;
}
body.portal-ui .sidebar-logout-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.85rem;
    font-size: 0.82rem;
    color: var(--s-text-muted, #6E7C8C);
    text-decoration: none;
    border-radius: 8px;
    transition: background 0.18s ease, color 0.18s ease;
}
body.portal-ui .sidebar-logout-link:hover {
    background: rgba(15, 32, 48, 0.04);
    color: var(--s-text, #0F2030);
}
body.portal-ui .sidebar-logout-link i { font-size: 0.95rem; }

/* Ensure dashboard-sidebar can justify its content with sidebar-foot at bottom */
body.portal-ui .dashboard-sidebar {
    display: flex;
    flex-direction: column;
}
body.portal-ui .dashboard-sidebar .dashboard-nav { margin-bottom: 0; }

/* --- Hint banner: soft tip below the empty-state hero --------------- */
body.portal-ui .hint-banner {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 1rem 1.15rem;
    background: linear-gradient(180deg, rgba(42, 127, 134, 0.06) 0%, rgba(42, 127, 134, 0.02) 100%);
    border: 1px solid rgba(42, 127, 134, 0.18);
    border-left: 3px solid var(--s-accent, #2A7F86);
    border-radius: 12px;
    flex-wrap: wrap;
}
body.portal-ui .hint-banner__icon {
    flex: 0 0 auto;
    font-size: 1.15rem;
    color: var(--s-accent, #2A7F86);
    line-height: 1;
    padding-top: 0.15rem;
}
body.portal-ui .hint-banner__body {
    flex: 1 1 260px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
body.portal-ui .hint-banner__body strong {
    font-size: 0.95rem;
    color: var(--s-text, #0F2030);
    font-weight: 700;
}
body.portal-ui .hint-banner__body span {
    font-size: 0.87rem;
    color: var(--s-text-muted, #6E7C8C);
    line-height: 1.5;
}
body.portal-ui .hint-banner__actions {
    display: inline-flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    align-items: center;
}
body.portal-ui .hint-link {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--s-accent, #2A7F86);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color 0.18s ease;
}
body.portal-ui .hint-link:hover {
    border-bottom-color: var(--s-accent, #2A7F86);
    color: var(--s-accent, #2A7F86);
}

/* --- Resource tile grid (replaces outline-button "Quick links" list) -- */
body.portal-ui .resource-tiles {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.6rem;
}
body.portal-ui .resource-tile {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    padding: 0.85rem 0.9rem;
    background: #ffffff;
    border: 1px solid var(--s-border-subtle, #E3ECEE);
    border-radius: 12px;
    text-decoration: none;
    color: var(--s-text, #0F2030);
    transition: border-color 0.18s ease, background 0.18s ease, transform 0.18s ease;
}
body.portal-ui .resource-tile:hover {
    border-color: rgba(42, 127, 134, 0.3);
    background: rgba(42, 127, 134, 0.04);
    transform: translateY(-1px);
    color: var(--s-text, #0F2030);
}
body.portal-ui .resource-tile i {
    font-size: 1.15rem;
    color: var(--s-accent, #2A7F86);
    flex: 0 0 auto;
    margin-top: 0.1rem;
}
body.portal-ui .resource-tile strong {
    display: block;
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1.25;
}
body.portal-ui .resource-tile span {
    display: block;
    font-size: 0.76rem;
    color: var(--s-text-muted, #6E7C8C);
    line-height: 1.4;
    margin-top: 0.15rem;
}
@media (max-width: 575.98px) {
    body.portal-ui .resource-tiles { grid-template-columns: 1fr; }
}

/* Drag and Drop runtime */
.quiz-dragdrop { display:grid; gap:1rem; }
.quiz-dragdrop-instructions,
.quiz-dragdrop-hint { font-size:.95rem; color:#5b6472; }
.quiz-dragdrop-bank { border:1px solid rgba(15,42,68,.12); border-radius:16px; padding:1rem; background:#f8fbff; }
.quiz-dragdrop-bank.is-over { border-color:rgba(31,79,216,.45); box-shadow:0 0 0 3px rgba(31,79,216,.08); }
.quiz-dragdrop-bank-title { font-weight:700; margin-bottom:.75rem; color:#0f2a44; }
.quiz-dragdrop-bank-items { display:flex; flex-wrap:wrap; gap:.75rem; }
.quiz-dd-item,
.quiz-dd-assigned-chip { border:1px solid rgba(15,42,68,.14); background:#fff; color:#0f2a44; border-radius:999px; padding:.65rem .9rem; font-weight:600; box-shadow:0 4px 14px rgba(15,42,68,.06); }
.quiz-dd-item.is-selected { border-color:#1f4fd8; box-shadow:0 0 0 3px rgba(31,79,216,.12); }
.quiz-dd-item.is-assigned { opacity:.4; }
.quiz-dragdrop-targets { display:grid; gap:.9rem; }
.quiz-dd-target { border:1px solid rgba(15,42,68,.12); border-radius:18px; padding:1rem; background:#fff; }
.quiz-dd-target.is-over,
.quiz-dd-target.has-assignment { border-color:rgba(31,79,216,.35); }
.quiz-dd-target-head { display:flex; align-items:center; justify-content:space-between; gap:.75rem; margin-bottom:.75rem; }
.quiz-dd-target-label { font-weight:700; color:#0f2a44; }
.quiz-dd-dropzone { min-height:68px; border:2px dashed rgba(15,42,68,.14); border-radius:14px; background:#f9fbfe; padding:.8rem; display:flex; align-items:center; justify-content:center; outline:none; }
.quiz-dd-target.has-assignment .quiz-dd-dropzone { border-style:solid; background:#f5f9ff; justify-content:flex-start; }
.quiz-dd-dropzone:focus { border-color:#1f4fd8; box-shadow:0 0 0 3px rgba(31,79,216,.12); }
.quiz-dd-placeholder { color:#7b8797; font-size:.92rem; }
.quiz-dd-assigned { display:flex; flex-wrap:wrap; gap:.5rem; }
.quiz-dd-clear-btn { white-space:nowrap; }
.quiz-dragdrop-review { display:grid; gap:.9rem; }
.quiz-dd-review-row { border:1px solid rgba(15,42,68,.12); border-radius:16px; padding:.9rem 1rem; background:#fff; }
.quiz-dd-review-row.is-correct { border-color:rgba(39,174,96,.28); background:#f4fff8; }
.quiz-dd-review-row.is-incorrect { border-color:rgba(220,53,69,.22); background:#fff8f8; }
.quiz-dd-review-target { font-weight:700; color:#0f2a44; margin-bottom:.4rem; }
.quiz-dd-review-values { display:grid; gap:.35rem; }
.quiz-dd-review-line { display:flex; flex-wrap:wrap; gap:.45rem; align-items:center; }
.quiz-dd-review-label { font-size:.82rem; text-transform:uppercase; letter-spacing:.03em; color:#6f7b8a; }
.quiz-dd-review-value { font-weight:600; color:#0f2a44; }
.quiz-dd-review-value.is-correct { color:#1f8b4c; }
.quiz-dd-review-value.is-incorrect { color:#c62839; }

/* ===== Quiz top-level step flow ===== */
.portal-quiz-take .quiz-steps {
  display: grid;
  gap: 1.25rem;
}

/* ============================================================
   Phase X: color-coded Review Navigation sidebar.
   On the post-submission review page each question's nav button
   shows green (correct), red (incorrect), or amber (partial — for
   case studies where some children were right and others wrong).
   The active step gets a stronger ring instead of replacing the
   status color so the student keeps "where am I?" + "did I get it?"
   visible at the same time.
   ============================================================ */
.portal-quiz-take .quiz-step-nav-btn--review {
  display: flex;
  align-items: stretch;
  gap: .7rem;
  padding: .7rem .85rem;
}
/* Active state preserves the correctness color but adds a stronger ring
   + slightly tinted backdrop so the student knows which step they're on. */
.portal-quiz-take .quiz-step-nav-btn--review.is-active {
  box-shadow: 0 0 0 2px rgba(31, 79, 216, 0.4);
  background-color: rgba(31, 79, 216, 0.04);
}
@media (max-width: 991.98px) {
}

.quiz-question-media {
  margin: 0 0 1rem;
  padding: .9rem 1rem;
  border: 1px solid rgba(31,79,216,.14);
  border-radius: 16px;
  background: #f7faff;
}
.quiz-question-media-head {
  display: flex;
  align-items: center;
  gap: .35rem;
  font-weight: 700;
  font-size: .92rem;
  color: #133a77;
  margin-bottom: .6rem;
}
.quiz-question-media-link {
  text-decoration: none;
}
.quiz-question-media-image {
  display: block;
  max-width: 100%;
  max-height: 340px;
  border-radius: 12px;
  border: 1px solid rgba(15,42,68,.10);
  background: #fff;
}
.quiz-question-media-caption {
  margin-top: .45rem;
  font-size: .82rem;
  color: #5f6f89;
}

/* ============================================================
   STUDENT PORTAL THEME — SKY BLUE primary + PINK accents
     SKY    #6FA8D6 / #4A86BE / #3A6FA0  (primary, soft)
     PINK   #C46AA0 / #B44A8A / #9C3A76  (primary accent)
     GREEN  #6E9B2A                        (secondary accent)
     AMBER  #D4B24D                        (tertiary accent)
     NAVY   #1E2A3A                        (text)
   ============================================================ */

/* Retint legacy teal tokens to SKY BLUE so --s-accent* consumers follow */
body.portal-ui {
    --s-accent: #6FA8D6 !important;
    --s-accent-600: #4A86BE !important;
    --s-accent-500: #85B5DC !important;
    --s-accent-50: rgba(111,168,214,0.10) !important;
    --s-accent-tint: #EAF3FA !important;
}

body.portal-ui .dashboard-shell {
    position: relative !important;
    background:
        repeating-linear-gradient(135deg, rgba(111,168,214,0.05) 0px, rgba(111,168,214,0.05) 1px, transparent 1px, transparent 26px),
        radial-gradient(ellipse 1200px 500px at 100% 0%, rgba(111,168,214,0.14) 0%, transparent 60%),
        radial-gradient(ellipse 900px 500px at 0% 100%, rgba(232,182,216,0.30) 0%, transparent 62%),
        linear-gradient(180deg, #F5F9FD 0%, #E5EEF6 100%) !important;
    min-height: 100vh !important;
}
body.portal-ui .dashboard-shell::before {
    content: "" !important;
    position: absolute !important;
    top: 0 !important; left: 0 !important; right: 0 !important;
    height: 3px !important;
    background: linear-gradient(90deg, #6FA8D6 0%, #C46AA0 38%, #6E9B2A 72%, #D4B24D 100%) !important;
    z-index: 20 !important;
    pointer-events: none !important;
}

/* Sidebar — BLUE gradient, PINK accent glow */
body.portal-ui .dashboard-sidebar {
    background:
        radial-gradient(ellipse 500px 300px at 100% 0%, rgba(232,182,216,0.34) 0%, transparent 60%),
        radial-gradient(ellipse 400px 300px at 0% 100%, rgba(212,178,77,0.22) 0%, transparent 60%),
        linear-gradient(180deg, #6FA8D6 0%, #4A86BE 55%, #3A6FA0 100%) !important;
    border-right: 1px solid rgba(58,111,160,0.28) !important;
    position: relative !important;
}
body.portal-ui .dashboard-sidebar::after {
    content: "" !important;
    position: absolute !important;
    top: 0 !important; right: 0 !important; bottom: 0 !important;
    width: 2px !important;
    background: linear-gradient(180deg, transparent 0%, rgba(232,182,216,0.55) 50%, transparent 100%) !important;
    pointer-events: none !important;
}

body.portal-ui .portal-brand-mark {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 48px !important;
    height: 48px !important;
    border-radius: 14px !important;
    background: linear-gradient(180deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.10) 100%) !important;
    border: 1px solid rgba(255,255,255,0.30) !important;
    padding: 4px !important;
}
body.portal-ui .dashboard-brand .fw-bold { color: #FFFFFF !important; }
body.portal-ui .dashboard-brand small { color: rgba(255,255,255,0.78) !important; }

body.portal-ui .program-capsule {
    background: rgba(255,255,255,0.14) !important;
    border: 1px solid rgba(255,255,255,0.22) !important;
    backdrop-filter: blur(6px) !important;
    border-radius: 14px !important;
    padding: 0.9rem 1rem !important;
}
body.portal-ui .program-capsule__name { color: #FFFFFF !important; font-weight: 600 !important; }
body.portal-ui .program-capsule__program { color: rgba(255,255,255,0.82) !important; font-size: 0.82rem !important; }
body.portal-ui .program-capsule__branch {
    color: rgba(232,182,216,0.92) !important;
    font-size: 0.75rem !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 0.35rem !important;
    margin-top: 0.25rem !important;
}

body.portal-ui .dashboard-nav .nav-link {
    color: rgba(255,255,255,0.84) !important;
    border-radius: 10px !important;
    transition: background 0.18s ease, color 0.18s ease, transform 0.15s ease !important;
}
body.portal-ui .dashboard-nav .nav-link i { color: rgba(232,182,216,0.82) !important; }
body.portal-ui .dashboard-nav .nav-link:hover {
    background: rgba(255,255,255,0.12) !important;
    color: #FFFFFF !important;
    transform: translateX(1px) !important;
}
body.portal-ui .dashboard-nav .nav-link:hover i { color: #FBE8F2 !important; }

/* Active state: PINK accent rule on BLUE (cross-accent) */
body.portal-ui .dashboard-nav .nav-link.active {
    background: linear-gradient(180deg, rgba(255,255,255,0.20) 0%, rgba(255,255,255,0.10) 100%) !important;
    color: #FFFFFF !important;
    border-left: 3px solid #E8B6D8 !important;
    box-shadow: 0 1px 0 rgba(255,255,255,0.14) inset !important;
}
body.portal-ui .dashboard-nav .nav-link.active i { color: #F1CFE1 !important; }

body.portal-ui .dashboard-nav .nav-link .badge {
    background: rgba(232,182,216,0.30) !important;
    color: #FBE8F2 !important;
    border: 1px solid rgba(232,182,216,0.50) !important;
}
body.portal-ui .dashboard-nav .nav-link .badge.bg-warning {
    background: #D4B24D !important;
    color: #3E2A00 !important;
    border-color: #B8952D !important;
}

body.portal-ui .sidebar-foot {
    border-top: 1px solid rgba(30, 42, 58, 0.10) !important;
    padding-top: 0.85rem !important;
}
/* Phase 14.1 / 15.J — sidebar bg is a soft pink/rose radial gradient.
   The previous translucent backgrounds (0.55 white, 0.08 teal) let
   the gradient bleed through and washed out the text. Solid white
   surfaces + stronger borders + darker subtitle text fix the
   contrast so both items are clearly readable. */
body.portal-ui .sidebar-help-link,
body.portal-ui .sidebar-logout-link {
    color: #1E2A3A !important;
    border-radius: 12px !important;
    padding: 0.75rem 0.9rem !important;
    background: #ffffff !important;
    border: 1px solid rgba(30, 42, 58, 0.20) !important;
    box-shadow: 0 1px 2px rgba(7, 20, 57, 0.04) !important;
    transition: background 0.18s ease, border-color 0.18s ease, transform 0.06s ease !important;
}
body.portal-ui .sidebar-help-link:hover,
body.portal-ui .sidebar-logout-link:hover {
    background: #F7FAFB !important;
    border-color: rgba(42, 127, 134, 0.45) !important;
    color: #1E2A3A !important;
}
body.portal-ui .sidebar-help-link:active,
body.portal-ui .sidebar-logout-link:active {
    transform: translateY(1px);
}
/* Help-link icon — fully saturated brand teal so it pops. */
body.portal-ui .sidebar-help-link i {
    color: #2A7F86 !important;
    font-size: 1.15rem !important;
    margin-top: 0.1rem !important;
}
/* Help-link title and subtitle — both readable against the white card. */
body.portal-ui .sidebar-help-link strong {
    color: #1E2A3A !important;
    font-weight: 700 !important;
    font-size: 0.92rem !important;
}
body.portal-ui .sidebar-help-link span {
    color: #44546A !important;       /* darker than #5F6B7A; better contrast on white */
    font-size: 0.78rem !important;
    line-height: 1.4 !important;
}
/* Logout button — slightly stronger so it reads as a button, not text. */
body.portal-ui .sidebar-logout-link {
    font-weight: 600 !important;
}
body.portal-ui .sidebar-logout-link i {
    color: #2A7F86 !important;
    font-size: 1.05rem !important;
    margin-right: 0.35rem !important;
}

body.portal-ui .dashboard-main { background: transparent !important; }

body.portal-ui .dashboard-topbar {
    background: rgba(255,255,255,0.92) !important;
    backdrop-filter: blur(10px) saturate(1.06) !important;
    border: 1px solid rgba(111,168,214,0.18) !important;
    border-radius: 18px !important;
    padding: 1.35rem 1.5rem !important;
    box-shadow: 0 1px 0 rgba(255,255,255,0.80) inset,
                0 18px 36px -16px rgba(58,111,160,0.16),
                0 3px 8px rgba(30,42,58,0.06) !important;
    position: relative !important;
    overflow: hidden !important;
}
body.portal-ui .dashboard-topbar::before {
    content: "" !important;
    position: absolute !important;
    top: 0 !important; left: 0 !important; right: 0 !important;
    height: 3px !important;
    background: linear-gradient(90deg, #6FA8D6 0%, #C46AA0 38%, #6E9B2A 72%, #D4B24D 100%) !important;
}
body.portal-ui .dashboard-topbar .metric-label {
    color: #4A86BE !important;
    font-weight: 600 !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase !important;
    font-size: 0.72rem !important;
}
body.portal-ui .dashboard-topbar h2 {
    color: #1E2A3A !important;
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif !important;
    font-weight: 700 !important;
    letter-spacing: -0.01em !important;
}
body.portal-ui .portal-page-intro {
    color: #3B4656 !important;
    margin-top: 0.25rem !important;
    font-size: 0.95rem !important;
}

/* Soft badge / branch pill — PINK cross-accent */
body.portal-ui .soft-badge,
body.portal-ui .portal-branch-pill {
    background: #FBE8F2 !important;
    color: #9C3A76 !important;
    border: 1px solid rgba(196,106,160,0.30) !important;
    font-weight: 600 !important;
    border-radius: 999px !important;
    padding: 0.4rem 0.85rem !important;
}

/* Support CTA — BLUE pill */
body.portal-ui .btn-accent,
body.portal-ui .portal-support-link {
    background: linear-gradient(180deg, #85B5DC 0%, #6FA8D6 100%) !important;
    border: 1px solid #4A86BE !important;
    color: #FFFFFF !important;
    box-shadow: 0 1px 0 rgba(255,255,255,0.28) inset,
                0 10px 22px -10px rgba(111,168,214,0.55),
                0 2px 5px rgba(30,42,58,0.10) !important;
    border-radius: 999px !important;
}
body.portal-ui .btn-accent:hover,
body.portal-ui .portal-support-link:hover,
body.portal-ui .btn-accent:focus-visible,
body.portal-ui .portal-support-link:focus-visible {
    filter: brightness(0.96) !important;
    transform: translateY(-1px) !important;
    color: #FFFFFF !important;
}

/* Metric cards — BLUE primary + PINK 2nd + green/amber on 3rd/4th */
body.portal-ui .metric-card {
    background: rgba(255,255,255,0.94) !important;
    backdrop-filter: blur(8px) !important;
    border: 1px solid rgba(111,168,214,0.14) !important;
    border-radius: 16px !important;
    transition: transform 0.15s ease, box-shadow 0.2s ease !important;
    position: relative !important;
    overflow: hidden !important;
}
body.portal-ui .metric-card::before {
    content: "" !important;
    position: absolute !important;
    top: 0 !important; left: 0 !important; right: 0 !important;
    height: 3px !important;
    background: #6FA8D6 !important;
}
body.portal-ui .row .col-md-6:nth-child(1) .metric-card::before,
body.portal-ui .row .col-xl-3:nth-child(1) .metric-card::before { background: #6FA8D6 !important; }
body.portal-ui .row .col-md-6:nth-child(2) .metric-card::before,
body.portal-ui .row .col-xl-3:nth-child(2) .metric-card::before { background: #C46AA0 !important; }
body.portal-ui .row .col-md-6:nth-child(3) .metric-card::before,
body.portal-ui .row .col-xl-3:nth-child(3) .metric-card::before { background: #6E9B2A !important; }
body.portal-ui .row .col-md-6:nth-child(4) .metric-card::before,
body.portal-ui .row .col-xl-3:nth-child(4) .metric-card::before { background: #D4B24D !important; }
body.portal-ui .metric-card:hover {
    transform: translateY(-2px) !important;
    box-shadow: 0 20px 36px -18px rgba(58,111,160,0.22),
                0 4px 10px rgba(30,42,58,0.08) !important;
}
body.portal-ui .metric-card .metric-label {
    color: #4A86BE !important;
    font-weight: 600 !important;
    letter-spacing: 0.14em !important;
    font-size: 0.70rem !important;
    text-transform: uppercase !important;
}
body.portal-ui .metric-card .metric-value {
    color: #1E2A3A !important;
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif !important;
    font-weight: 700 !important;
    font-size: 2.2rem !important;
    letter-spacing: -0.01em !important;
}

body.portal-ui .form-control:focus,
body.portal-ui .form-select:focus {
    border-color: #6FA8D6 !important;
    box-shadow: 0 0 0 4px rgba(111,168,214,0.14) !important;
}

body.portal-ui .page-card,
body.portal-ui .card {
    background: rgba(255,255,255,0.94) !important;
    border: 1px solid rgba(111,168,214,0.12) !important;
    border-radius: 16px !important;
}

body.portal-ui .dashboard-main h3,
body.portal-ui .dashboard-main h4,
body.portal-ui .dashboard-main h5 { color: #1E2A3A !important; }

body.portal-ui .dashboard-main a:not(.btn):not(.nav-link):not(.metric-card):not(.dropdown-item):not(.page-link) {
    color: #4A86BE !important;
}
body.portal-ui .dashboard-main a:not(.btn):not(.nav-link):not(.metric-card):not(.dropdown-item):not(.page-link):hover {
    color: #6FA8D6 !important;
}

body.portal-ui table.table thead th {
    color: #4A86BE !important;
    border-bottom: 2px solid rgba(111,168,214,0.25) !important;
}
body.portal-ui table.table tbody tr:hover {
    background: rgba(234,243,250,0.55) !important;
}

body.portal-ui .form-check-input:checked {
    background-color: #6FA8D6 !important;
    border-color: #6FA8D6 !important;
}
body.portal-ui .form-check-input:focus {
    border-color: #6FA8D6 !important;
    box-shadow: 0 0 0 0.2rem rgba(111,168,214,0.22) !important;
}

/* Continue-hero (dashboard welcome) — BLUE with PINK accent */
body.portal-ui .continue-hero .hero-title.text-truncate,
body.portal-ui .continue-hero .hero-title {
    overflow: visible !important;
    text-overflow: clip !important;
    white-space: normal !important;
    word-break: break-word !important;
    overflow-wrap: anywhere !important;
    color: #1E2A3A !important;
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif !important;
    font-weight: 700 !important;
    font-size: clamp(1.4rem, 2.4vw, 1.85rem) !important;
    line-height: 1.2 !important;
    letter-spacing: -0.01em !important;
    margin: 0.15rem 0 0.35rem !important;
}

body.portal-ui .continue-hero {
    background: rgba(255,255,255,0.94) !important;
    border: 1px solid rgba(111,168,214,0.14) !important;
    border-radius: 18px !important;
    padding: 1.5rem 1.75rem !important;
    position: relative !important;
    overflow: hidden !important;
    box-shadow: 0 1px 0 rgba(255,255,255,0.80) inset,
                0 18px 36px -18px rgba(58,111,160,0.18),
                0 3px 8px rgba(30,42,58,0.06) !important;
}
body.portal-ui .continue-hero::before {
    background: linear-gradient(180deg, #6FA8D6 0%, #4A86BE 100%) !important;
    width: 4px !important;
}
body.portal-ui .continue-hero .hero-eyebrow {
    color: #4A86BE !important;
    letter-spacing: 0.16em !important;
    font-weight: 700 !important;
}
body.portal-ui .continue-hero .hero-sub { color: #3B4656 !important; }

/* Continue CTA — BLUE pill with PINK glow on hover */
body.portal-ui .btn-hero,
body.portal-ui .btn-hero.btn-primary,
body.portal-ui .continue-hero .btn-primary {
    background: linear-gradient(180deg, #85B5DC 0%, #6FA8D6 100%) !important;
    border: 1px solid #4A86BE !important;
    color: #FFFFFF !important;
    border-radius: 999px !important;
    padding: 0.70rem 1.5rem !important;
    font-weight: 600 !important;
    box-shadow: 0 1px 0 rgba(255,255,255,0.28) inset,
                0 12px 24px -10px rgba(111,168,214,0.55),
                0 3px 6px rgba(30,42,58,0.12) !important;
    transition: transform 0.15s ease, filter 0.2s ease, box-shadow 0.2s ease !important;
}
body.portal-ui .btn-hero:hover,
body.portal-ui .btn-hero.btn-primary:hover,
body.portal-ui .continue-hero .btn-primary:hover,
body.portal-ui .btn-hero:focus-visible,
body.portal-ui .btn-hero.btn-primary:focus-visible,
body.portal-ui .continue-hero .btn-primary:focus-visible {
    filter: brightness(0.96) !important;
    transform: translateY(-1px) !important;
    color: #FFFFFF !important;
    box-shadow: 0 1px 0 rgba(255,255,255,0.28) inset,
                0 16px 28px -12px rgba(111,168,214,0.55),
                0 10px 18px -10px rgba(196,106,160,0.38),
                0 3px 6px rgba(30,42,58,0.12) !important;
}

/* Progress — BLUE fill, soft blue track */
body.portal-ui .progress-soft,
body.portal-ui .progress {
    background: #D6E6F2 !important;
    border-radius: 999px !important;
    overflow: hidden !important;
}
body.portal-ui .progress-soft .progress-bar,
body.portal-ui .progress .progress-bar {
    background: linear-gradient(90deg, #6FA8D6 0%, #4A86BE 100%) !important;
}

body.portal-ui .continue-hero.gradient-hero {
    background: linear-gradient(180deg, #6FA8D6, #4A86BE) !important;
}

/* ============================================================
   Readability fix — Portal course page
   The original styling left the module accordion with three
   readability problems on the QA test course render:
     1. Pill badges painted pink-on-pink (#FBE8F2 bg + #9C3A76 text
        with a 30%-alpha border) — technically WCAG-passing but
        visually muddy.
     2. The "Course Modules" subtitle and per-module description
        previews used .small.text-muted, which resolves to
        var(--s-text-muted) #6E7C8C — too light for short
        instructional copy.
     3. Body type inside the accordion was inheriting a serif/italic
        treatment from the page-level overrides, making 14px copy
        look thin and decorative.
   This block fixes all three plus enforces sans-serif body type.
   Scoped tightly to the course page so other portal screens
   (dashboard, calendar, etc.) are untouched.
   ============================================================ */

/* 1. Force Inter sans-serif + upright style for every text element
      inside the course-page accordion. Course-card heading at the
      top of the page keeps its existing serif treatment elsewhere. */
body.portal-ui.page-course .accordion-button,
body.portal-ui.page-course .accordion-button *,
body.portal-ui.page-course .accordion-body,
body.portal-ui.page-course .accordion-body *,
body.portal-ui .portal-course .accordion-button,
body.portal-ui .portal-course .accordion-button *,
body.portal-ui .portal-course .accordion-body,
body.portal-ui .portal-course .accordion-body * {
    font-family: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif !important;
    font-style: normal !important;
}

/* 2a. Subtitle ("Open any module to study its materials and quizzes")
       and per-module description previews. Was text-muted; pop to
       text-secondary at 500 weight so the instructional copy reads
       clearly without competing with the module title. */
body.portal-ui.page-course .accordion-button .small.text-muted,
body.portal-ui .portal-course .accordion-button .small.text-muted {
    color: var(--s-text-secondary) !important;
    opacity: 1 !important;
    font-weight: 500 !important;
}

/* 2b. Module title strong text + body copy inside accordion bodies
       (description paragraph, lesson rows). Make the regular body
       text fully dark and a touch heavier so it doesn't feel like
       fine print. */
body.portal-ui.page-course .accordion-button strong,
body.portal-ui .portal-course .accordion-button strong {
    color: var(--s-text) !important;
    font-weight: 600 !important;
}
body.portal-ui.page-course .accordion-body .text-muted,
body.portal-ui .portal-course .accordion-body .text-muted,
body.portal-ui.page-course .accordion-body .lesson-meta,
body.portal-ui .portal-course .accordion-body .lesson-meta {
    color: var(--s-text-secondary) !important;
    opacity: 1 !important;
}

/* 3. Soft badges inside the course module accordion. The global
      override at line ~4204 paints these pink-on-pink with
      !important; this MORE-specific selector wins at the same
      priority and uses a stronger contrast pairing: white bg +
      darker plum text + solid pink border. Keeps the cross-accent
      pink design language but makes the labels readable. */
body.portal-ui.page-course .soft-badge,
body.portal-ui .portal-course .soft-badge,
body.portal-ui.page-course .accordion-body .soft-badge,
body.portal-ui .portal-course .accordion-body .soft-badge {
    background: #FFFFFF !important;
    color: #6B2952 !important;
    border: 1px solid #C46AA0 !important;
    font-weight: 700 !important;
    font-family: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif !important;
    letter-spacing: 0.04em !important;
    text-transform: uppercase !important;
}
/* "Done" success-tone badge variant used on completed modules
   should read green instead of plum so the state is unambiguous. */
body.portal-ui.page-course .accordion-button .soft-badge.text-success,
body.portal-ui .portal-course .accordion-button .soft-badge.text-success {
    color: #1F7A4D !important;
    border-color: #1F7A4D !important;
}

/* Course page layout — modules left, Course Progress right sidebar.
   Breakpoint lowered to 768px so the sidebar claims the empty
   right-side space at typical desktop/tablet viewports inside the
   portal scope (where the dashboard nav already eats ~280px). */
body.portal-ui .portal-course-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(220px, 280px);
    gap: 1.5rem;
    align-items: start;
}
body.portal-ui .portal-course-main,
body.portal-ui .portal-course-side {
    min-width: 0;
}
body.portal-ui .portal-course-side .side-card {
    position: sticky;
    top: 1rem;
}

@media (max-width: 767.98px) {
    body.portal-ui .portal-course-layout {
        grid-template-columns: 1fr;
    }
    body.portal-ui .portal-course-side {
        order: -1;
    }
    body.portal-ui .portal-course-side .side-card {
        position: static;
    }
}

/* ============================================================
   Phase 11.I — Student dashboard visual polish
   Conservative upgrades from the visual audit:
     1. Continue Learning hero — warmer accent so it stands out
        as the primary card.
     2. Compact metric "stat strip" at < md instead of three
        ~150 px stacked cards.
     3. Larger / clearer touch targets on small "View all" links.
     4. "Your courses" card slightly elevated for hierarchy.
   Desktop layout (>= lg) unchanged. All scoped to body.portal-ui.
   ============================================================ */

/* 1. Continue Learning hero emphasis. */
body.portal-ui .continue-hero.continue-hero--smart {
    background: linear-gradient(135deg, #FCEDF0 0%, #FFF6E5 60%, #F0FBF2 100%);
    border: 1px solid rgba(196, 69, 122, 0.18);
    box-shadow: 0 8px 28px rgba(196, 69, 122, 0.10);
    border-radius: 18px;
    padding: 1.4rem 1.5rem;
}
body.portal-ui .continue-hero .hero-eyebrow {
    color: #B13269;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
    font-size: 0.78rem;
    margin-bottom: 0.45rem;
}
body.portal-ui .continue-hero .hero-title {
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    font-weight: 600;
    font-size: clamp(1.4rem, 4vw, 1.85rem);
    line-height: 1.2;
    color: #1E2A3A;
    margin-bottom: 0.35rem;
    /* Phase 12.A.4 (revised) — allow long course titles to wrap
       cleanly. We dropped the -webkit-line-clamp because at narrow
       widths with a serif font + long underscored tokens it caused
       visual overlap between clamped lines. Trade-off: a really
       long title can take 4-5 lines on a 360 px phone. The hero is
       the user's primary destination, so taller-but-readable beats
       clamped-and-broken. */
    overflow-wrap: anywhere;
    word-break: break-word;
    hyphens: auto;
}
@media (max-width: 767.98px) {
    body.portal-ui .continue-hero .hero-title {
        font-size: clamp(1.05rem, 4.5vw, 1.35rem);
        line-height: 1.25;
    }
}
@media (max-width: 379.98px) {
    body.portal-ui .continue-hero .hero-title {
        font-size: 1rem;
    }
}
body.portal-ui .continue-hero .btn-hero.btn-primary {
    background: linear-gradient(180deg, #f0267a 0%, #C4457A 52%, #B13269 100%);
    border: 0;
    color: #fff;
    font-weight: 700;
    padding: 0.75rem 1.4rem;
    border-radius: 10px;
    box-shadow: 0 6px 16px rgba(196, 69, 122, 0.30),
                inset 0 1px 0 rgba(255, 255, 255, 0.20);
    min-height: 48px;
}
@media (max-width: 767.98px) {
    body.portal-ui .continue-hero .btn-hero.btn-primary {
        width: 100%;
        justify-content: center;
        display: inline-flex;
        align-items: center;
    }
}

/* 2. Compact metric stat strip on phones.
   Below md (< 768) the three .metric-card tiles render as a tight
   3-up grid in a single ~110 px tall row instead of three ~150 px
   stacked cards. Phase 12.A.1 + 12.A.2: labels can wrap to 2 lines
   so "UPCOMING SESSION" / "LATEST SCORE" / "OVERALL PROGRESS" don't
   ellipsis at narrow widths, and value fonts shrink at < 400 px so
   "60.00%" doesn't clip on Samsung Galaxy S8+ (360 px). */
@media (max-width: 767.98px) {
    body.portal-ui .row.g-4.mb-4 > .col-md-4:has(.metric-card) {
        flex: 0 0 33.333%;
        max-width: 33.333%;
        padding-right: calc(var(--bs-gutter-x) * .35);
        padding-left: calc(var(--bs-gutter-x) * .35);
    }
    body.portal-ui .row.g-4.mb-4 > .col-md-4 > .metric-card,
    body.portal-ui .row.g-4.mb-4 > a.col-md-4 > .metric-card {
        padding: 0.55rem 0.45rem;
        text-align: center;
        min-height: 0;
        /* Keep tile clipping so values don't bleed into the next tile.
           The narrow font below ensures values FIT inside the tile. */
        overflow: hidden;
    }
    body.portal-ui .row.g-4.mb-4 > .col-md-4 .metric-label,
    body.portal-ui .row.g-4.mb-4 > a.col-md-4 .metric-label {
        font-size: 0.62rem;
        line-height: 1.2;
        letter-spacing: 0.04em;
        margin-bottom: 0.4rem;
        /* allow up to 2 lines, then ellipsis */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        white-space: normal;
        overflow: hidden;
        min-height: 1.85rem;
    }
    body.portal-ui .row.g-4.mb-4 > .col-md-4 .metric-value,
    body.portal-ui .row.g-4.mb-4 > a.col-md-4 .metric-value {
        /* On phone the brand serif (Cormorant Garamond) is too wide
           for the narrow tile (~90-110 px). Switch to Inter sans-serif
           with tabular numerals so "100.00%" fits inside every tile
           down to 320 px viewport. The serif is restored at >= md.
           !important needed to defeat the body.portal-ui rule that
           forces font-size: 2.2rem !important. */
        font-family: 'Inter', system-ui, -apple-system, sans-serif !important;
        font-feature-settings: "tnum" 1 !important;
        font-weight: 700 !important;
        font-size: 0.95rem !important;
        line-height: 1.15 !important;
        letter-spacing: 0 !important;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: clip;
    }
    /* Hide the inline ".date-block" pieces and sub-text inside
       the stat strip on phone — only the headline number lands. */
    body.portal-ui .row.g-4.mb-4 > .col-md-4 .date-block,
    body.portal-ui .row.g-4.mb-4 > .col-md-4 .small.text-muted {
        display: none;
    }
    body.portal-ui .row.g-4.mb-4 > .col-md-4 .progress-soft {
        margin-top: 0.35rem;
    }
}
/* Phase 12.A.2 — Samsung S8+ (360) the value font drops further so
   "100.00%" wouldn't clip even at the narrowest tile width (~95 px). */
@media (max-width: 399.98px) {
    body.portal-ui .row.g-4.mb-4 .metric-value {
        font-size: 0.85rem !important;   /* fits "100.00%" at ~75 px tile width */
    }
    body.portal-ui .row.g-4.mb-4 .metric-label {
        font-size: 0.55rem;
    }
}
@media (max-width: 359.98px) {
    body.portal-ui .row.g-4.mb-4 .metric-value {
        font-size: 0.75rem !important;   /* Galaxy S8+ (360) and below */
    }
}
@media (max-width: 339.98px) {
    body.portal-ui .row.g-4.mb-4 .metric-value {
        font-size: 0.7rem !important;    /* Galaxy Z Fold (344), iPhone 5 (320) */
    }
}

/* 3. Bump small dashboard secondary links so they hit ~44 px touch. */
body.portal-ui .card-title-row .btn.btn-sm.btn-outline-secondary {
    min-height: 36px;
    padding: 0.45rem 0.75rem;
}
@media (max-width: 991.98px) {
    body.portal-ui .card-title-row .btn.btn-sm.btn-outline-secondary {
        min-height: 40px;
        padding: 0.5rem 0.85rem;
        font-size: 0.85rem;
    }
}

/* 4. "Your courses" section — slightly elevated as the main work
   surface. Outline accent on the card title-row so it reads as the
   primary card on the dashboard. */
body.portal-ui .dashboard-card .card-title-row h4.mb-0 + .section-helper,
body.portal-ui .dashboard-card .card-title-row h4.mb-1 + .section-helper {
    margin-top: 0.15rem;
}

/* ============================================================
   Phase 11 Bucket B — Student-facing mobile card list.
   Used at < lg in place of desktop tables on /grades/,
   /quizzes/history/, /resources/, /portal/orders/. Each row
   renders as a stacked card. Desktop (>= lg) keeps the table —
   gated by the templates' d-none/d-lg-block + d-lg-none classes.

   Mirrors the admin-side rules in admin.css (Phase 10) but
   scoped to body.portal-ui so the two surfaces stay independent.
   ============================================================ */
body.portal-ui .dashboard-mobile-list {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
body.portal-ui .dashboard-mobile-card {
    border: 1px solid rgba(30, 42, 58, 0.08);
    border-radius: 10px;
    background: #fff;
    padding: 0.85rem 0.95rem;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
body.portal-ui .dashboard-mobile-card-head {
    display: flex;
    align-items: center;
    gap: 0.65rem;
}
body.portal-ui .dashboard-mobile-card-head .avatar-initial,
body.portal-ui .dashboard-mobile-card-head img.dashboard-mobile-card-avatar,
body.portal-ui .dashboard-mobile-card-head .dashboard-mobile-card-icon {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border-radius: 8px;
    object-fit: cover;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #f4f7fb;
    color: #2849D8;
    font-size: 1.1rem;
}
body.portal-ui .dashboard-mobile-card-title {
    font-weight: 600;
    color: #1E2A3A;
    line-height: 1.25;
    font-size: 0.97rem;
    overflow: hidden;
    text-overflow: ellipsis;
}
body.portal-ui .dashboard-mobile-card-subtitle {
    font-size: 0.82rem;
    color: #5F6B7A;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
}
body.portal-ui .dashboard-mobile-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 0.75rem;
    font-size: 0.82rem;
    color: #5F6B7A;
    align-items: center;
}
body.portal-ui .dashboard-mobile-card-meta .meta-label {
    font-weight: 600;
    color: #1E2A3A;
    margin-right: 0.2rem;
}
body.portal-ui .dashboard-mobile-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.25rem;
}
body.portal-ui .dashboard-mobile-card-actions .btn,
body.portal-ui .dashboard-mobile-card-actions form {
    flex: 1 1 auto;
    margin: 0;
}
body.portal-ui .dashboard-mobile-card-actions .btn {
    min-height: 40px;
}

/* ============================================================
   Phase 15.B — Repeated-pattern utility classes.
   Extracted from inline style="..." attrs across portal templates.
   Each replaces a pattern that appeared 3-8 times in templates.
   ============================================================ */
body.portal-ui .icon-empty-state {
    font-size: 2rem;
    opacity: 0.4;
}
body.portal-ui .icon-empty-state-lg {
    font-size: 3rem;
}
body.portal-ui .icon-md {
    font-size: 1.4rem;
}
body.portal-ui .min-width-0 {
    min-width: 0;
}

/* ============================================================
   Phase 14 (item 10) — Quiz exhibit collapsible on mobile.
   Long case-study exhibits used to push the question + answer
   choices below the fold. At < lg the exhibit content is
   collapsed by default; a "View case study" button toggles it
   open. At >= lg the exhibit is always visible (CSS forces the
   collapse open) and the toggle button is hidden. The toggle
   text + icon swap via aria-expanded — no JS required.
   ============================================================ */
@media (min-width: 992px) {
    body.portal-ui .exhibit-content.collapse:not(.show) {
        display: block !important;
    }
}
body.portal-ui .exhibit-toggle {
    color: #2849D8;
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: none;
    line-height: 1;
    flex: 0 0 auto;
}
body.portal-ui .exhibit-toggle:hover {
    color: #1A35A5;
    text-decoration: underline;
}
/* Default state (collapsed) — show "View ..." label, hide "Hide" label */
body.portal-ui .exhibit-toggle .exhibit-toggle-hide {
    display: none;
}
/* Expanded state — flip the labels */
body.portal-ui .exhibit-toggle[aria-expanded="true"] .exhibit-toggle-show {
    display: none;
}
body.portal-ui .exhibit-toggle[aria-expanded="true"] .exhibit-toggle-hide {
    display: inline;
}

/* ============================================================
   Phase 13.D — Course-item compact layout on phones.
   Each course card was 268-295 px tall on phones because of
   helper text + gap + CTA row. Compress at < lg by:
   - Hiding "Pick up where you left off" (helper, redundant)
   - Continue = full-width primary
   - View grade = compact secondary below
   - Drop card padding from 1.5rem to 1rem
   Targets ~180 px card height on iPhone XR.
   ============================================================ */
@media (max-width: 991.98px) {
    body.portal-ui .course-cta-row {
        flex-direction: column;
        align-items: stretch !important;
        margin-top: 0.6rem !important;
        gap: 0.4rem !important;
    }
    body.portal-ui .course-cta-buttons {
        width: 100%;
        gap: 0.4rem !important;
    }
    body.portal-ui .course-cta-primary {
        flex: 1 1 60%;
        min-height: 40px;
    }
    body.portal-ui .course-cta-secondary {
        flex: 1 1 35%;
        min-height: 36px;
    }
    body.portal-ui .portal-dashboard .course-item {
        padding: 1rem;
        margin-bottom: 0.85rem;
    }
}

/* ============================================================
   Phase 12.C — Touch target minimums on portal.
   - Bootstrap's default .btn-close is 31×31; bump to 44×44 in the
     offcanvas drawer header so phone users can hit it.
   - .btn-sm in portal pages defaults to ~30 px; bump to 36 min on
     touch viewports so quiz/course buttons clear WCAG 2.5.5.
   ============================================================ */
body.portal-ui .offcanvas-header .btn-close {
    width: 44px;
    height: 44px;
    padding: 0.7rem;
    background-size: 18px 18px;
}
/* Min height applies to all viewports for portal pages — mouse users
   benefit too, and smoke-test threshold of 36 is a good baseline
   regardless of input modality. */
body.portal-ui .btn.btn-sm,
body.portal-ui a.btn.btn-sm {
    min-height: 36px;
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
}

/* ============================================================
   Phase 11.F — skip-to-content link.
   Hidden until keyboard-focused, then jumps over the sidebar nav.
   Bootstrap's .visually-hidden-focusable handles the visibility;
   we just add positioning + branded styling on focus.
   ============================================================ */
body.portal-ui .portal-skip-link {
    position: fixed;
    top: 8px;
    left: 8px;
    z-index: 1080;
    background: #1E2A3A;
    color: #fff !important;
    padding: 0.55rem 0.95rem;
    border-radius: 8px;
    font-weight: 600;
    text-decoration: none;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}

/* ============================================================
   Phase 11.E — Profile photo sizing.
   180×180 at >= lg (current desktop look), 110×110 at < lg so the
   photo doesn't eat half a phone screen.
   ============================================================ */
body.portal-ui .profile-photo {
    width: 180px;
    height: 180px;
    border-radius: 12px;
    flex: 0 0 auto;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
body.portal-ui .profile-photo--filled {
    object-fit: cover;
    border: 4px solid #C4457A;
}
body.portal-ui .profile-photo--empty {
    background: linear-gradient(135deg, #FCE7F3, #FFF7ED);
    border: 4px dashed #C4457A;
    display: flex;
    align-items: center;
    justify-content: center;
}
body.portal-ui .profile-photo--empty i {
    font-size: 5rem;
    color: #C4457A;
}
@media (max-width: 991.98px) {
    body.portal-ui .profile-photo {
        width: 110px;
        height: 110px;
        border-radius: 10px;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.10);
    }
    body.portal-ui .profile-photo--empty i {
        font-size: 3rem;
    }
}

/* Read-only profile inputs — distinct background tint so students
   know they can't edit them (Phase 11.E). */
body.portal-ui .profile-readonly-field {
    background: #f6f7fa !important;
    color: #5F6B7A !important;
    cursor: not-allowed;
}

/* ============================================================
   Phase 11.D — Quizzes hub page-hint banner.
   Replaces an inline style block on /portal/quizzes/ for code health.
   ============================================================ */
body.portal-ui .portal-page-hint {
    background: #eef4ff;
    border: 1px solid #cfe0f8;
    color: #1e3a5f;
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    font-size: 0.92rem;
    line-height: 1.45;
}

/* ============================================================
   Phase 11.D — My Courses card CTAs.
   At >= lg, primary + secondaries flow on one row.
   At < lg, primary CTA stretches full-width and secondaries split
   the row beneath it (cleaner than 3 buttons wrapping awkwardly).
   ============================================================ */
body.portal-ui .course-card-cta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}
body.portal-ui .course-card-cta-row .course-cta-secondaries {
    display: inline-flex;
    gap: 0.5rem;
}
@media (max-width: 991.98px) {
    body.portal-ui .course-card-cta-row {
        flex-direction: column;
        align-items: stretch;
        gap: 0.4rem;
    }
    body.portal-ui .course-card-cta-row .course-cta-primary {
        width: 100%;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
    body.portal-ui .course-card-cta-row .course-cta-secondaries {
        display: flex;
        gap: 0.4rem;
    }
    body.portal-ui .course-card-cta-row .course-cta-secondaries .btn {
        flex: 1 1 50%;
        min-height: 40px;
    }
}

/* ============================================================
   Phase 9 — Course-learn module accordion (mobile only).
   At < lg the module body collapses behind a chevron button so a
   20-module course doesn't render 20 viewport-screens of detail.
   At >= lg the .module-detail.collapse is forced open so desktop
   layout is unchanged from the pre-Phase-9 design.
   ============================================================ */
@media (min-width: 992px) {
    body.portal-ui .module-detail.collapse:not(.show) {
        display: block !important;
    }
    body.portal-ui .module-toggle {
        display: none !important;
    }
}
@media (max-width: 991.98px) {
    body.portal-ui .module-toggle {
        color: var(--portal-accent, #2A7F86);
        text-decoration: none;
        transition: transform 0.2s ease;
    }
    body.portal-ui .module-toggle[aria-expanded="true"] i {
        transform: rotate(180deg);
    }
    body.portal-ui .module-toggle i {
        transition: transform 0.2s ease;
        display: inline-block;
    }
    body.portal-ui .module-card.module-current {
        border-left: 4px solid var(--portal-accent, #2A7F86);
    }
}

/* ============================================================
   Phase 15.G — Quiz answer choices as large tap cards
   The native input stays in the DOM (visually-hidden) for full
   keyboard / screen-reader compatibility. The label is the tap
   target. Selected state is driven by `:has(input:checked)` —
   modern browsers only, but Bootstrap 5.3+ already requires that.
   ============================================================ */
.choice-card-list {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}

.choice-card {
    /* Reset label defaults */
    margin-bottom: 0;
    cursor: pointer;
    user-select: none;

    /* Card chrome */
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 0.85rem 1rem;
    background: #ffffff;
    border: 1.5px solid rgba(30, 42, 58, 0.14);
    border-radius: 12px;
    box-shadow: 0 1px 0 rgba(7, 20, 57, 0.02);

    /* Touch target — at least 56px tall on phone for easy tapping. */
    min-height: 56px;
    line-height: 1.4;
    transition:
        border-color 0.15s ease,
        background 0.15s ease,
        box-shadow 0.15s ease,
        transform 0.05s ease;
}

.choice-card:hover {
    border-color: var(--portal-accent, #2A7F86);
    background: #f7fbfb;
}

.choice-card:active {
    transform: translateY(1px);
}

/* Keyboard focus ring — driven by the hidden input's :focus-visible
   propagated to the wrapping label via :focus-within. */
.choice-card:focus-within {
    border-color: var(--portal-accent, #2A7F86);
    box-shadow: 0 0 0 3px rgba(42, 127, 134, 0.22);
    outline: none;
}

/* Selected state — driven by :has() (modern browsers). */
.choice-card:has(input:checked) {
    border-color: var(--portal-accent, #2A7F86);
    background: #ecf6f6;
    box-shadow: 0 1px 0 rgba(42, 127, 134, 0.18);
}

.choice-card:has(input:checked) .choice-card-text {
    color: #1E2A3A;
    font-weight: 600;
}

/* Marker — radio = circle, checkbox = rounded square. */
.choice-card-marker {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    margin-top: 0.05rem;
    background: #ffffff;
    border: 2px solid rgba(30, 42, 58, 0.28);
    transition: border-color 0.15s ease, background 0.15s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #ffffff;
    font-size: 0.95rem;
    line-height: 1;
}

.choice-card--radio .choice-card-marker {
    border-radius: 50%;
}

.choice-card--checkbox .choice-card-marker {
    border-radius: 6px;
}

.choice-card--checkbox .choice-card-marker i {
    opacity: 0;
    transform: scale(0.8);
    transition: opacity 0.12s ease, transform 0.12s ease;
}

/* Filled-marker state when input is checked. */
.choice-card:has(input:checked) .choice-card-marker {
    border-color: var(--portal-accent, #2A7F86);
    background: var(--portal-accent, #2A7F86);
}

.choice-card--radio:has(input:checked) .choice-card-marker {
    /* Inner dot for radio */
    box-shadow: inset 0 0 0 4px #ffffff;
}

.choice-card--checkbox:has(input:checked) .choice-card-marker i {
    opacity: 1;
    transform: scale(1);
}

/* Text */
.choice-card-text {
    flex-grow: 1;
    color: #1E2A3A;
    font-size: 0.97rem;
    line-height: 1.45;
    word-break: break-word;
}

/* Phone polish — slightly bigger marker + tighter padding. */
@media (max-width: 767.98px) {
    .choice-card {
        padding: 0.85rem 0.85rem;
        gap: 0.7rem;
        min-height: 60px;
    }
    .choice-card-text {
        font-size: 0.95rem;
    }
}

/* Reduce motion preference — drop the transitions/transform. */
@media (prefers-reduced-motion: reduce) {
    .choice-card,
    .choice-card-marker,
    .choice-card--checkbox .choice-card-marker i {
        transition: none;
    }
    .choice-card:active {
        transform: none;
    }
}

/* ============================================================
   Phase 15.H — Phone bottom-nav bar (5 tabs)
   Fixed to viewport bottom at < lg. Holds 5 evenly-distributed
   tap targets. Drawer hamburger above stays the canonical full
   nav; this bar is the shortcut to the 5 most-used destinations.
   At >= lg the bar is hidden via the d-lg-none class on the
   element itself.
   ============================================================ */
@media (max-width: 991.98px) {
    /* Reserve space at bottom of body so the fixed bar doesn't
       cover the last paragraph / button on long pages. The bar is
       64 px tall; add 4 px breathing room. */
    body.portal-ui {
        padding-bottom: 68px;
    }
    /* Suppress on take-quiz — the take page has its own action bar. */
    body.portal-ui.page-quiz-take {
        padding-bottom: 0;
    }
    body.portal-ui.page-quiz-take .portal-bottom-nav {
        display: none !important;
    }

    .portal-bottom-nav {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1040;
        height: 64px;

        display: grid;
        grid-template-columns: repeat(5, 1fr);
        gap: 0;

        background: #ffffff;
        border-top: 1px solid rgba(30, 42, 58, 0.10);
        box-shadow: 0 -4px 16px rgba(7, 20, 57, 0.08);
        /* Notch / home-indicator safe-area padding for iOS */
        padding-bottom: env(safe-area-inset-bottom, 0);
    }
    /* When the safe-area inset is non-zero, give the bar extra
       height so the icons sit above the home indicator. */
    @supports (padding: env(safe-area-inset-bottom)) {
        .portal-bottom-nav {
            height: calc(64px + env(safe-area-inset-bottom, 0));
        }
        body.portal-ui {
            padding-bottom: calc(68px + env(safe-area-inset-bottom, 0));
        }
    }

    .portal-bottom-tab {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 0.15rem;
        padding: 0.35rem 0.25rem;
        text-decoration: none;
        color: #5F6B7A;
        font-size: 0.7rem;
        line-height: 1.1;
        font-weight: 500;
        transition: color 0.15s ease, background 0.15s ease;
        /* Min touch target — 44 px is WCAG 2.5.5 floor; the 64 px
           parent height already gives us this with breathing room. */
    }
    .portal-bottom-tab:hover {
        color: var(--portal-accent, #2A7F86);
        background: rgba(42, 127, 134, 0.05);
    }
    .portal-bottom-tab:active {
        background: rgba(42, 127, 134, 0.10);
    }
    .portal-bottom-tab i {
        font-size: 1.25rem;
        line-height: 1;
    }
    .portal-bottom-tab.active {
        color: var(--portal-accent, #2A7F86);
        font-weight: 600;
    }
    .portal-bottom-tab.active i {
        /* Subtle 2px lift via top-border so the active tab has a
           visual marker beyond color (color-blind-safe). */
        position: relative;
    }
    .portal-bottom-tab.active::before {
        content: '';
        position: absolute;
        top: 0;
        left: 50%;
        transform: translateX(-50%);
        width: 32px;
        height: 3px;
        border-radius: 0 0 3px 3px;
        background: var(--portal-accent, #2A7F86);
    }
    .portal-bottom-tab {
        position: relative;  /* anchor for the .active::before bar */
    }
}

/* ============================================================
   PHASE 16 — Mobile dashboard polish (final block).
   Scoped to body.portal-ui .portal-dashboard so portal pages
   that DON'T render the dashboard are unaffected. Source order
   gives this block higher priority than older duplicate rules
   above; older rules stay in place untouched (cleanup is a
   separate later phase).

   Acceptance gates this block must satisfy:
     - 390x844: hero <= 240px, metric strip <= 90px,
       first course top <= 600px
     - 320x720: first course top <= 650px
     - Hero course title NEVER wraps past 2 lines on mobile
     - Course CTAs in ONE row at >= 360px
   ============================================================ */

/* B.1 — Continue hero compaction at < lg + hard 2-line title clamp.
   The 2-line clamp is the single most important rule in this block:
   long course titles can no longer blow up the hero. The full title
   still lives in the title="..." attribute for accessibility/hover. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .continue-hero {
        padding: 1.1rem 1.15rem 1.2rem !important;
        border-radius: 18px !important;
        margin-bottom: 1rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-eyebrow {
        font-size: 10px;
        margin-bottom: 4px;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-title {
        font-size: 18px;
        line-height: 24px;
        white-space: normal;          /* override desktop text-truncate */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        text-overflow: ellipsis;
        max-height: 48px;             /* hard ceiling = 2 x 24px */
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-sub {
        font-size: 13px;
        margin-top: 2px;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-progress,
    body.portal-ui .portal-dashboard .continue-hero .progress.progress-soft {
        height: 8px;
        margin-top: 0.6rem;
        max-width: 100%;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta {
        margin-top: 0.85rem;
    }
    body.portal-ui .portal-dashboard .continue-hero .btn-hero {
        padding: 10px 16px;
        font-size: 14px;
        width: 100%;                  /* full-width primary on phone */
    }
    /* "View whole course" secondary — quieter, smaller, centered. */
    body.portal-ui .portal-dashboard .continue-hero .hero-cta a.text-muted {
        font-size: 12px;
        align-self: center;
        margin-top: 0.4rem;
    }
}
@media (max-width: 575.98px) {
    body.portal-ui .portal-dashboard .continue-hero {
        padding: 1rem 1rem 1.1rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-title {
        font-size: 17px;
        line-height: 22px;
        max-height: 44px;             /* clamp still 2 lines, smaller */
    }
}

/* B.2 — Metric chip mode polish. Scoped to .dashboard-metrics-row
   (added in dashboard.html A.6) so portal pages that use the same
   .row.g-4.mb-4 base classes are not affected. Phase 12's existing
   chip-mode rules at lines 3357-3416 still apply (less specific
   selector, same property values) — Phase 16 just tightens spacing.
   Acceptance gate: strip height <= 90px at 390x844. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .dashboard-metrics-row {
        --bs-gutter-x: 0.5rem !important;
        --bs-gutter-y: 0 !important;       /* no vertical gap; tiles stay tight */
        margin-bottom: 1rem !important;
    }
    /* The <a class="col-md-4"> wrapping the Latest Score tile leaks
       a 24px margin-top from Bootstrap's default --bs-gutter-y. Force
       margin-top: 0 on ALL row children so the strip stays tight. */
    body.portal-ui .portal-dashboard .dashboard-metrics-row > .col-md-4,
    body.portal-ui .portal-dashboard .dashboard-metrics-row > a.col-md-4 {
        margin-top: 0 !important;
    }
    body.portal-ui .portal-dashboard .dashboard-metrics-row > .col-md-4 > .metric-card,
    body.portal-ui .portal-dashboard .dashboard-metrics-row > a.col-md-4 > .metric-card {
        padding: 0.4rem 0.4rem !important;
        max-height: 76px;            /* hard cap so all 3 tiles align */
        overflow: hidden;
    }
    body.portal-ui .portal-dashboard .dashboard-metrics-row .metric-label {
        min-height: 1rem !important;       /* was 1.4rem; saves ~6.4px */
        margin-bottom: 0.2rem !important;  /* was 0.4rem; saves ~3px */
        font-size: 0.6rem !important;      /* tighter than Phase 12's 0.62 */
    }
    /* The metric-card::before accent left bar shouldn't add visual
       padding when tiles are short. Trim it tight. */
    body.portal-ui .portal-dashboard .dashboard-metrics-row .metric-card::before {
        width: 3px !important;
    }
    /* Hide the Latest Score quiz-title sub-text on phone — at 94px
       wide tile width, an extra line of muted text is the difference
       between hitting and missing the 90px row height target. The
       value (e.g. "20.00%") still shows. */
    body.portal-ui .portal-dashboard .dashboard-metrics-row .small.text-muted {
        display: none !important;
    }
}

/* B.3 — Course card compaction. Buttons stay in ONE row at >= 360px;
   only stack at very narrow viewports (< 340px) where they would
   otherwise overflow. Keeps mobile course cards 180-200px tall.
   Acceptance gate: course-item height 180-220px at 390x844. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .course-item {
        padding: 0.85rem 0.95rem !important;
        margin-bottom: 0.7rem !important;
        border-radius: 14px !important;
    }
    /* Inner title row — tighter gap and bottom margin so the title
       block doesn't dominate the card. */
    body.portal-ui .portal-dashboard .course-item > .d-flex.flex-column.flex-md-row {
        gap: 0.35rem !important;
        margin-bottom: 0.5rem !important;
    }
    /* Title clamp to 2 lines max — full title still in tooltip via
       title attribute on the inner div is not present, but the
       course title is always under 60 chars so 2 lines is plenty. */
    body.portal-ui .portal-dashboard .course-item .course-title {
        font-size: 0.95rem;
        line-height: 1.25;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        max-height: 2.5em;
    }
    body.portal-ui .portal-dashboard .course-item .course-instructor {
        font-size: 0.78rem;
        margin-top: 0.1rem;
    }
    body.portal-ui .portal-dashboard .course-item .progress.progress-soft {
        height: 6px;
    }
    body.portal-ui .portal-dashboard .course-item .progress-label {
        font-size: 0.78rem;
        margin-bottom: 0.25rem;
    }
    body.portal-ui .portal-dashboard .course-item .course-cta-row {
        margin-top: 0.55rem !important;
        gap: 0.4rem !important;
    }
    body.portal-ui .portal-dashboard .course-item .course-cta-primary {
        flex: 1 1 auto;
        min-height: 40px;
        font-size: 0.85rem;
    }
    body.portal-ui .portal-dashboard .course-item .course-cta-secondary {
        flex: 0 0 auto;
        min-height: 40px;
        font-size: 0.8rem;
        padding: 0.4rem 0.7rem;
    }
}
/* Stack only at the narrowest viewports — Galaxy Z Fold 1 (280),
   iPhone 5 (320), older Android phones with chrome at 339 and below. */
@media (max-width: 339.98px) {
    body.portal-ui .portal-dashboard .course-item .course-cta-buttons {
        width: 100%;
    }
    body.portal-ui .portal-dashboard .course-item .course-cta-primary,
    body.portal-ui .portal-dashboard .course-item .course-cta-secondary {
        flex-basis: 100%;
    }
}

/* B.4 — Recent quiz history row tightening at < lg. The Review pill
   button keeps its 36-40px touch target from Phase 13.C; Phase 16
   just tightens the row padding and supporting text size so the
   3-attempt list reads compact and scan-light. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .timeline-list li {
        padding: 0.7rem 0;
        gap: 0.5rem;
    }
    body.portal-ui .portal-dashboard .timeline-list li .small.text-muted {
        font-size: 0.72rem;
    }
    body.portal-ui .portal-dashboard .timeline-list .stat-chip {
        font-size: 10.5px;
        padding: 3px 8px;
    }
    body.portal-ui .portal-dashboard .timeline-list .btn.btn-sm.btn-outline-secondary {
        min-height: 36px;
        font-size: 0.78rem;
        padding: 0.35rem 0.7rem;
    }
}

/* B.5 — Tablet landscape (lg-only, 992-1199.98px) split.
   Phase 17 update — 70/30 made the right rail too narrow at 1024
   (~222 px). Switching to 64/36 gives the schedule + quick-actions
   cards meaningful breathing room (~250 px+) while the main column
   still gets a small bump over the default 66.67%. Desktop
   >= 1200 px keeps Bootstrap's default 8/4 split unchanged. */
@media (min-width: 992px) and (max-width: 1199.98px) {
    body.portal-ui .portal-dashboard .row.g-4 > .col-lg-8 {
        flex: 0 0 64%;
        max-width: 64%;
    }
    body.portal-ui .portal-dashboard .row.g-4 > .col-lg-4 {
        flex: 0 0 36%;
        max-width: 36%;
    }
}
/* END PHASE 16 BLOCK */

/* ============================================================
   PHASE 17 — Mobile dashboard density polish.
   - Quick Actions: 2-column tap grid (2-2-1) on mobile only.
   - Recent quiz: 2-row layout per item, ~100 px tall.
   - Empty Upcoming Session: ensure the new "—" placeholder
     shows in chip mode (Phase 16 hid .small.text-muted; the
     metric-value placeholder isn't affected and renders).
   Scoped to body.portal-ui .portal-dashboard so it can't bleed
   to other portal surfaces.
   ============================================================ */

/* P17.3 — Quick Actions mobile 2-column grid (2-2-1 layout).
   The desktop copy in the right rail keeps the existing
   d-grid stack styling. This rule only fires on the mobile
   .qa-card-mobile wrapper. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.55rem;
    }
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 0.25rem;
        padding: 0.75rem 0.5rem;
        min-height: 64px;
        font-size: 0.82rem;
        font-weight: 600;
        line-height: 1.2;
        text-align: center;
        background: rgba(255, 255, 255, 0.96);
    }
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn i {
        font-size: 1.2rem;
        color: var(--s-accent, #2A7F86);
    }
    /* Last button (Need help?) spans both columns — 2-2-1 layout. */
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn--full {
        grid-column: 1 / -1;
        flex-direction: row;            /* horizontal layout for the wide row */
        gap: 0.4rem;
    }
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn--full i {
        font-size: 1rem;
    }
}

/* P17.6 — Recent quiz row 2-row compact layout. Each row drops
   from ~142 px to ~96-100 px. Top row holds the title + score
   chip; bottom row holds the course/date + Review pill. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row {
        display: flex;
        flex-direction: column;
        gap: 0.35rem;
        padding: 0.65rem 0;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row-top,
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row-bottom {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        /* Phase 25 — flex children inside a column-flex parent default
           to min-width: auto (intrinsic content width). When the title
           or course is long, the row escapes the li and overflows the
           card. Force width: 100% + min-width: 0 so they sit inside
           the li and shrink/ellipsis the inner text instead. */
        width: 100%;
        min-width: 0;
        max-width: 100%;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-title {
        font-weight: 600;
        font-size: 0.92rem;
        line-height: 1.25;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;            /* keep title on 1 line; truncate */
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta {
        font-size: 0.72rem;
        line-height: 1.2;
        flex: 1 1 auto;
        min-width: 0;
        /* Phase 25 — flex container so course title can truncate
           while the date stays full-width. */
        display: flex;
        align-items: baseline;
        gap: 0.4rem;
        overflow: hidden;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta-course {
        flex: 1 1 auto;
        min-width: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta-date {
        flex-shrink: 0;        /* date never trimmed */
        white-space: nowrap;
        opacity: 0.85;
    }
    /* Bullet between course and date — generated, no template edit. */
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta-date::before {
        content: '·';
        margin-right: 0.4rem;
        opacity: 0.55;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .btn.btn-sm {
        min-height: 32px;
        font-size: 0.72rem;
        padding: 0.25rem 0.6rem;
        white-space: nowrap;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .stat-chip {
        font-size: 10.5px;
        padding: 3px 8px;
    }
}
/* END PHASE 17 BLOCK */

/* ============================================================
   PHASE 18 — Final density polish (tablet landscape + mobile QA
   + 320px micro-spacing). Scoped to body.portal-ui .portal-dashboard.

   Acceptance gates this block must satisfy:
     - 390x844: hero <= 245, metrics <= 85, first course top <= 575,
       first course card <= 200, QA card <= 285, quiz card <= 420
     - 320x720: hero <= 265, first course top <= 625
     - 768x1024: first course top <= 590, course cards <= 170
     - 1024x768: course cards <= 215, empty schedule card <= 420,
       right rail feels balanced
   ============================================================ */

/* P18.A — lg-only tablet landscape compaction (992-1199.98).
   Tablet landscape was the worst remaining surface. The course
   helper text moved from d-lg-inline to d-xl-inline in dashboard.html
   so the helper is hidden here; this CSS just trims the cards
   themselves. Desktop xl+ keeps the existing more-spacious layout. */
@media (min-width: 992px) and (max-width: 1199.98px) {
    body.portal-ui .portal-dashboard .course-item {
        padding: 0.85rem 1rem;
        margin-bottom: 0.7rem;
    }
    body.portal-ui .portal-dashboard .course-item > .d-flex.flex-column.flex-md-row {
        margin-bottom: 0.5rem;
    }
    body.portal-ui .portal-dashboard .course-item .course-cta-row {
        margin-top: 0.6rem !important;
    }
    /* Right rail at lg — tighter card padding so the schedule and
       quick-actions cards don't feel over-padded in the now-wider rail
       (Phase 17 64/36 split). */
    body.portal-ui .portal-dashboard .col-lg-4 .dashboard-card {
        padding: 1.15rem;
    }
    /* Empty-state padding inside the schedule card — was ~3rem, now
       ~1.4rem so the empty card stays under 420 px. */
    body.portal-ui .portal-dashboard .col-lg-4 .portal-empty {
        padding: 1.4rem 1rem;
    }
    body.portal-ui .portal-dashboard .col-lg-4 .portal-empty i {
        font-size: 1.5rem;
    }
    /* Trim the side-item rows in schedule when events DO exist. */
    body.portal-ui .portal-dashboard .col-lg-4 .side-item {
        padding: 0.85rem 0.95rem !important;
    }
}

/* P18.B — Mobile Quick Actions: smaller tap tiles for a tighter card.
   Was: min-height 64 px, padding 0.75 0.5, icon 1.2rem → card ~317 px.
   Now: min-height 56 px, padding 0.55 0.45, icon 1.1rem → card ~270 px.
   Touch targets stay >= WCAG 2.5.5 minimum (44x44). */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid {
        gap: 0.45rem;
    }
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn {
        min-height: 56px;
        padding: 0.55rem 0.45rem;
        font-size: 0.8rem;
    }
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn i {
        font-size: 1.1rem;
    }
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn--full {
        min-height: 48px;
        padding: 0.5rem 0.7rem;
    }
    body.portal-ui .portal-dashboard .qa-card-mobile .qa-grid-btn--full i {
        font-size: 1rem;
    }
}

/* P18.C — 320px micro-spacing + quiz meta truncation.
   At 320 the course buttons stack (per the < 340 rule from Phase 16);
   tighten the gap so the stacked pair adds less vertical noise.
   Also let the quiz history meta truncate course title harder so the
   row doesn't push to 2 lines on a narrow screen. */
@media (max-width: 339.98px) {
    body.portal-ui .portal-dashboard .course-item .course-cta-buttons {
        gap: 0.35rem;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta .d-inline-block {
        max-width: 45%;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .btn.btn-sm {
        font-size: 0.7rem;
        padding: 0.22rem 0.5rem;
    }
}

/* P18.D — Status chip subdued so it doesn't dominate the card title row.
   The Phase 16 chip styling is fine on desktop; on phone it visually
   competes with the course title. Quieter background, same color
   semantics. Scoped to course-item only — quiz history chips stay
   loud (the score IS the headline there). */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .course-item .stat-chip {
        font-size: 10px;
        padding: 2px 7px;
        font-weight: 600;
    }
}
/* END PHASE 18 BLOCK */

/* Final tiny polish (no new Phase block).
   (1) Tabular sans-serif metric values at every breakpoint — Phase 12
       only applied this at < lg, so desktop still rendered numbers in
       Cormorant Garamond. Inter + tabular-nums everywhere keeps the
       three tile values in clean column alignment regardless of
       viewport. Specificity + !important defeat the line-3022 rule.
   (2) lg-only (992-1199) — trim hero + metric-row bottom margin so
       the first course rises above the fold at 1024. */
body.portal-ui .portal-dashboard .metric-card .metric-value {
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif !important;
    font-variant-numeric: tabular-nums !important;
    font-feature-settings: "tnum" 1 !important;
    letter-spacing: 0 !important;
}
@media (min-width: 992px) and (max-width: 1199.98px) {
    body.portal-ui .portal-dashboard .continue-hero { margin-bottom: 1rem !important; }
    body.portal-ui .portal-dashboard .dashboard-metrics-row { margin-bottom: 0.85rem !important; }
    /* Topbar lives in _base.html inside .dashboard-main (above the
       .portal-dashboard wrapper), so the selector cannot be nested. */
    body.portal-ui .dashboard-main > .dashboard-topbar { margin-bottom: 0.9rem !important; }
}

/* ============================================================
   PHASE 21 — Resource card mobile stacking + course-learn header
   compaction + module title row toggle + resource detail mobile.
   Scoped to body.portal-ui so portal/public surfaces don't collide.
   ============================================================ */

/* P21.A — Resource card (templates/resources/_resource_card.html).
   Default (>= 576): horizontal — icon | body | action. Border + padding
   match the original Bootstrap d-flex p-3 styling for visual parity. */
body.portal-ui .resource-card {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 0.9rem 1rem;
    margin-bottom: 0.55rem;
    border: 1px solid var(--s-border-subtle, #DCE6EF);
    border-radius: 12px;
    background: #ffffff;
}
body.portal-ui .resource-card-icon {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 10px;
    background: rgba(42, 127, 134, 0.10);
    color: var(--s-accent, #2A7F86);
    font-size: 1.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
body.portal-ui .resource-card-body {
    flex-grow: 1;
    min-width: 0;            /* allow truncation of long descriptions */
}
body.portal-ui .resource-card-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #5F6B7A;
    margin-bottom: 0.25rem;
}
body.portal-ui .resource-card-meta-sep {
    opacity: 0.5;
}
body.portal-ui .resource-card-title {
    font-weight: 600;
    line-height: 1.3;
}
body.portal-ui .resource-card-title a {
    color: var(--s-text, #1E2A3A);
    text-decoration: none;
}
body.portal-ui .resource-card-title a:hover {
    color: var(--s-accent, #2A7F86);
}
body.portal-ui .resource-card-desc {
    font-size: 0.82rem;
    color: #5F6B7A;
    margin-top: 0.25rem;
    line-height: 1.4;
}
body.portal-ui .resource-card-course {
    font-size: 0.75rem;
    color: #5F6B7A;
    margin-top: 0.3rem;
}
body.portal-ui .resource-card-action {
    flex-shrink: 0;
    display: flex;
    align-items: center;
}
/* P21.B / P26.B — Mobile (< 576): stack vertically, action button
   full-width. P26 update: tighter padding + smaller icon + clamped
   description so card height drops from ~222 px to 150-180 px. */
@media (max-width: 575.98px) {
    body.portal-ui .resource-card {
        flex-direction: column;
        gap: 0.4rem;                    /* was 0.55 */
        padding: 0.65rem 0.8rem;        /* was 0.8 0.85 */
    }
    body.portal-ui .resource-card-icon {
        width: 36px;                    /* was 40 */
        height: 36px;
        font-size: 1.05rem;
    }
    body.portal-ui .resource-card-body {
        width: 100%;
    }
    body.portal-ui .resource-card-meta {
        margin-bottom: 0.15rem;
        font-size: 0.65rem;
    }
    body.portal-ui .resource-card-title {
        font-size: 0.92rem;
        line-height: 1.25;
        /* Title max 2 lines */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
    body.portal-ui .resource-card-action {
        width: 100%;
    }
    body.portal-ui .resource-card-action .btn {
        width: 100%;
        min-height: 40px;
        font-size: 0.85rem;
    }
    body.portal-ui .resource-card-desc {
        font-size: 0.76rem;             /* was 0.78 */
        line-height: 1.35;
        margin-top: 0.15rem;
        /* Limit to 2 lines on phone */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
    body.portal-ui .resource-card-course {
        font-size: 0.7rem;
        margin-top: 0.2rem;
    }
}

/* P21.C — Course-learn header compaction at < lg.
   The header is the first .dashboard-card on the learn page (course
   title + progress + grade summary). Was ~347 px tall at 320/390;
   target 220-260. Cuts: hide "Course overview" button on mobile,
   tighten card padding + internal vertical rhythm. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard > .dashboard-card:first-child {
        padding: 1rem 1.05rem !important;
        margin-bottom: 0.85rem !important;
    }
    /* The "Course overview" pill in the upper-right is reachable from
       the public site and from the breadcrumb in the portal sidebar.
       Hide on phone to reclaim ~35 px of vertical space. */
    body.portal-ui .portal-dashboard > .dashboard-card:first-child a.btn-outline-secondary[href*="/courses/"] {
        display: none;
    }
    body.portal-ui .portal-dashboard > .dashboard-card:first-child h4 {
        font-size: 1.05rem;
        line-height: 1.3;
        margin-bottom: 0.35rem;
    }
    body.portal-ui .portal-dashboard > .dashboard-card:first-child .soft-badge {
        margin-bottom: 0.35rem !important;
        font-size: 0.7rem;
    }
    body.portal-ui .portal-dashboard > .dashboard-card:first-child hr {
        margin-top: 0.7rem !important;
        margin-bottom: 0.7rem !important;
    }
    body.portal-ui .portal-dashboard > .dashboard-card:first-child .progress.progress-soft {
        height: 7px;
    }
}

/* P21.D — Whole module title row clickable. The .module-toggle--full
   button stretches across the row; .module-toggle-label distributes
   title (left) and chevron (right). The chevron rotates when the
   collapse is expanded. */
body.portal-ui .module-toggle.module-toggle--full {
    text-decoration: none !important;
    color: var(--s-text, #1E2A3A) !important;
    border-radius: 8px;
    padding: 0.5rem 0 !important;
    min-height: 44px;
    display: block;
}
body.portal-ui .module-toggle.module-toggle--full:focus-visible {
    outline: 2px solid var(--s-accent, #2A7F86);
    outline-offset: 2px;
}
body.portal-ui .module-toggle-label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.7rem;
    font-weight: 600;
    color: var(--s-text, #1E2A3A);
}
body.portal-ui .module-toggle-title {
    flex: 1 1 auto;
    min-width: 0;
    /* Wrap to 2 lines, then ellipsis. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    line-height: 1.3;
}
body.portal-ui .module-toggle-chevron {
    flex-shrink: 0;
    color: var(--s-accent, #2A7F86);
    transition: transform 0.18s ease;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
body.portal-ui .module-toggle.module-toggle--full[aria-expanded="true"] .module-toggle-chevron {
    transform: rotate(180deg);
}
@media (prefers-reduced-motion: reduce) {
    body.portal-ui .module-toggle-chevron {
        transition: none;
    }
}

/* P21.E — Resource detail page (now extends portal/_base.html).
   Compact mobile H1; tight horizontal rhythm; full-width CTA. */
body.portal-ui.page-resource-detail .resource-detail-card {
    padding: 1.15rem !important;
}
body.portal-ui .resource-detail-header {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--s-border-subtle, #DCE6EF);
    margin-bottom: 0.85rem;
}
body.portal-ui .resource-detail-icon {
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    border-radius: 12px;
    background: rgba(42, 127, 134, 0.10);
    color: var(--s-accent, #2A7F86);
    font-size: 1.6rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
body.portal-ui .resource-detail-headtext {
    flex-grow: 1;
    min-width: 0;
}
body.portal-ui .resource-detail-eyebrow {
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--s-accent, #2A7F86);
    font-weight: 700;
    font-size: 0.72rem;
    margin-bottom: 0.2rem;
}
body.portal-ui .resource-detail-title {
    font-size: clamp(1.1rem, 4vw, 1.55rem);   /* tight at 320, comfy at desktop */
    line-height: 1.25;
    margin: 0 0 0.4rem 0;
    font-weight: 700;
    color: var(--s-text, #1E2A3A);
}
body.portal-ui .resource-detail-context {
    font-size: 0.78rem;
}
body.portal-ui .resource-detail-section + .resource-detail-section {
    border-top: 1px solid var(--s-border-subtle, #DCE6EF);
    padding-top: 0.85rem;
    margin-top: 0.85rem;
}
@media (max-width: 575.98px) {
    body.portal-ui .resource-detail-header {
        gap: 0.65rem;
    }
    body.portal-ui .resource-detail-icon {
        width: 44px;
        height: 44px;
        font-size: 1.25rem;
    }
    body.portal-ui .resource-detail-card .btn-lg {
        font-size: 0.92rem;
        padding: 0.75rem 1rem;
    }
}
/* END PHASE 21 BLOCK */

/* ============================================================
   PHASE 22 — Schedule event cards + Bucket B tap-target bumps.
   - Schedule rows become real cards with date-block, title heading,
     event-type chip, and explicit Join/Watch CTA.
   - Misc. small tap targets (View whole course, Review pills,
     Detailed grade, Open My Reports) bumped to 36 px min-height.
   Scoped to body.portal-ui.
   ============================================================ */

/* P22.A — Schedule event card baseline (>= 576).
   Three-column layout: date-block | body | actions. */
body.portal-ui .schedule-event-list {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
body.portal-ui .schedule-event-card {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem 1rem;
    background: linear-gradient(180deg, rgba(248,251,252,0.96), rgba(255,255,255,0.98));
    border: 1px solid rgba(30, 42, 58, 0.08);
    border-radius: 12px;
}
body.portal-ui .schedule-event-card--past {
    background: rgba(248, 251, 252, 0.5);
    opacity: 0.92;
}
body.portal-ui .schedule-event-date-block {
    flex-shrink: 0;
    width: 56px;
    height: 60px;
    border-radius: 10px;
    background: var(--s-accent-tint, rgba(42, 127, 134, 0.10));
    color: var(--s-accent-600, #20696F);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
body.portal-ui .schedule-event-day {
    font-size: 22px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
body.portal-ui .schedule-event-month {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-top: 2px;
    opacity: 0.85;
}
body.portal-ui .schedule-event-body {
    flex-grow: 1;
}
body.portal-ui .schedule-event-title {
    font-size: 0.98rem;
    line-height: 1.3;
    font-weight: 600;
    margin: 0 0 0.2rem 0;
    /* clamp to 2 lines so very long event titles don't blow the row */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
body.portal-ui .schedule-event-title a {
    color: var(--s-text, #1E2A3A);
    text-decoration: none;
    /* Block-level tap surface so the WHOLE title row is tappable
       at >= 36 px tall, not just the text glyph height (~20 px). */
    display: block;
    min-height: 36px;
    padding: 0.3rem 0;
    margin: -0.3rem 0;        /* visually preserve the same vertical rhythm */
    border-radius: 4px;
}
body.portal-ui .schedule-event-title a:hover,
body.portal-ui .schedule-event-title a:focus-visible {
    color: var(--s-accent, #2A7F86);
    background: rgba(42, 127, 134, 0.04);
}
body.portal-ui .schedule-event-time {
    font-size: 0.78rem;
    margin-bottom: 0.25rem;
}
body.portal-ui .schedule-event-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.3rem;
}
body.portal-ui .schedule-event-chips .soft-badge {
    font-size: 0.7rem;
}
body.portal-ui .schedule-event-actions {
    flex-shrink: 0;
    display: flex;
    gap: 0.4rem;
    align-items: center;
}
body.portal-ui .schedule-event-actions .btn.btn-sm {
    min-height: 36px;
    padding: 0.4rem 0.7rem;
}
body.portal-ui .schedule-event-actions .schedule-event-ics {
    min-width: 38px;     /* icon-only at desktop */
}

/* P22.B — Schedule mobile (< 576): stack body + actions full-width.
   Date-block stays inline next to the title via flex-row but actions
   become full-width buttons under the body for clear tap targets. */
@media (max-width: 575.98px) {
    body.portal-ui .schedule-event-card {
        flex-wrap: wrap;
        padding: 0.75rem 0.85rem;
        gap: 0.6rem;
    }
    body.portal-ui .schedule-event-date-block {
        width: 48px;
        height: 52px;
    }
    body.portal-ui .schedule-event-day { font-size: 18px; }
    body.portal-ui .schedule-event-month { font-size: 9px; }
    body.portal-ui .schedule-event-body {
        flex: 1 1 calc(100% - 60px);   /* sit beside the date-block */
        min-width: 0;
    }
    body.portal-ui .schedule-event-actions {
        flex-basis: 100%;
        gap: 0.5rem;
    }
    body.portal-ui .schedule-event-actions .btn.btn-sm {
        flex: 1 1 auto;
        min-height: 40px;
        font-size: 0.83rem;
    }
    body.portal-ui .schedule-event-title {
        font-size: 0.95rem;
    }
}

/* P22.C — Bucket B tap-target bumps. */
/* "View whole course" secondary link in the dashboard hero — bump
   to 36 px so it satisfies the WCAG floor without losing the
   quiet-secondary feel. */
body.portal-ui .portal-dashboard .continue-hero .hero-cta a.text-muted {
    min-height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.4rem 0.6rem;
    border-radius: 6px;
}

/* "Review" pills inside the dashboard's Recent quiz history card —
   were 32 px after Phase 17. Bump to 36 px. */
body.portal-ui .portal-dashboard .timeline-list .btn.btn-sm.btn-outline-secondary {
    min-height: 36px !important;
}

/* "Detailed grade" link inside the course-learn header — was a 14 px
   text link. Make it a small pill button while keeping the "small"
   feel via reduced font-size. */
body.portal-ui .portal-dashboard > .dashboard-card:first-child a.text-decoration-none[href*="/grades/"] {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 0.4rem 0.7rem;
    border: 1px solid var(--s-border-subtle, #DCE6EF);
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.85);
    color: var(--s-accent-600, #20696F);
    font-weight: 500;
}
body.portal-ui .portal-dashboard > .dashboard-card:first-child a.text-decoration-none[href*="/grades/"]:hover,
body.portal-ui .portal-dashboard > .dashboard-card:first-child a.text-decoration-none[href*="/grades/"]:focus-visible {
    background: var(--s-accent-tint, rgba(42, 127, 134, 0.10));
    border-color: var(--s-accent, #2A7F86);
    text-decoration: none;
}

/* "Open My Reports →" link on /grades/ — same pill treatment. */
body.portal-ui .portal-dashboard a[href*="/quizzes/history/"]:not(.btn):not(.nav-link):not(.portal-bottom-tab) {
    min-height: 36px;
    display: inline-flex;
    align-items: center;
    padding: 0.4rem 0.7rem;
}

/* Dashboard right-rail "Your schedule" widget — event title links
   were 19 px tall. Same fix as the /portal/schedule/ title:
   block-level tap area with negative margin so visual rhythm
   doesn't change. */
body.portal-ui .portal-dashboard .side-item .fw-semibold a {
    display: block;
    min-height: 36px;
    padding: 0.3rem 0;
    margin: -0.3rem 0;
    border-radius: 4px;
}
body.portal-ui .portal-dashboard .side-item .fw-semibold a:hover,
body.portal-ui .portal-dashboard .side-item .fw-semibold a:focus-visible {
    background: rgba(42, 127, 134, 0.05);
    color: var(--s-accent, #2A7F86);
}

/* Phase 23 — Side-item event title 2-line clamp.
   Replaces text-truncate so titles like "[demo] Mid-term self-assessment due"
   show on 2 lines instead of being clipped at "Mid-term self-asse...".
   Full title still in title="..." attribute for hover. */
body.portal-ui .portal-dashboard .side-item .side-item-title-clamp {
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: 1.3;
}

/* Phase 25.B — Dashboard right-rail Schedule widget date-blocks were
   rendering at varying widths (28/37/36/28 px) because the inherited
   .date-block { width: 56px } got shrunk by the parent flex's default
   `flex: 0 1 auto`. Lock the dimensions so all four blocks line up. */
body.portal-ui .portal-dashboard .side-item .date-block {
    width: 56px !important;
    min-width: 56px;
    height: 60px !important;
    flex-shrink: 0;
    flex-basis: 56px;
}

/* ============================================================
   PHASE 26 — Final student-portal polish
   Bucket A. Dashboard:
   - Stack Review pill below meta at <= 360 (was overflowing at 320)
   - Tighten vertical rhythm so first course rises another ~25 px at 320
   ============================================================ */

/* A.1 — Recent quiz history row overflow at <= 360. The bottom row is
   `flex-wrap: nowrap` which let the Review button push past viewport
   when meta + gap + button exceeded the row width. Switch to wrap +
   stack so meta gets full width then Review sits below. */
@media (max-width: 359.98px) {
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row-bottom {
        flex-wrap: wrap;
        align-items: flex-start;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row-bottom .quiz-history-meta {
        flex: 1 1 100%;
        max-width: 100%;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row-bottom .btn.btn-sm {
        margin-top: 0.25rem;
        align-self: flex-end;
    }
}

/* A.2 — Tighten dashboard hero + metrics at <= 360 to lift the
   first course up to ~y=560 target.  The 390+ rules from earlier
   stay; this only shaves 20-25 px specifically at small phones. */
@media (max-width: 359.98px) {
    body.portal-ui .portal-dashboard .continue-hero {
        padding: 0.85rem 0.85rem 0.95rem !important;
        margin-bottom: 0.85rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-title {
        font-size: 16px;
        line-height: 21px;
        max-height: 42px;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta {
        margin-top: 0.65rem;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta .btn-hero {
        padding: 9px 14px;
    }
    body.portal-ui .portal-dashboard .dashboard-metrics-row {
        margin-bottom: 0.7rem !important;
    }
}

/* ============================================================
   Bucket C. /resources/ list mobile density + pagination.
   ============================================================ */

/* C.1 — Mobile resource cards inside /resources/ list (uses the
   .dashboard-mobile-card pattern, NOT .resource-card). Trim padding
   and meta to give a denser feel. */
@media (max-width: 991.98px) {
    body.portal-ui .dashboard-mobile-list .dashboard-mobile-card {
        padding: 0.7rem 0.85rem;
    }
    body.portal-ui .dashboard-mobile-list .dashboard-mobile-card-title {
        font-size: 0.95rem;
        line-height: 1.3;
        /* 2-line title clamp for very long resource titles */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
    body.portal-ui .dashboard-mobile-list .dashboard-mobile-card-subtitle {
        font-size: 0.75rem;
    }
    body.portal-ui .dashboard-mobile-list .dashboard-mobile-card-meta {
        font-size: 0.72rem;
        gap: 0.35rem;
    }
    body.portal-ui .dashboard-mobile-list .dashboard-mobile-card-actions .btn {
        min-height: 40px;
    }
}

/* C.2 — page-hint (the soft blue info banner above the filter card)
   takes too much vertical space at < 576. Shrink it. */
@media (max-width: 575.98px) {
    body.portal-ui .portal-dashboard .page-hint {
        font-size: 0.82rem !important;
        padding: 0.55rem 0.75rem !important;
        line-height: 1.4 !important;
    }
}

/* C.3 — Resource filter card mobile compaction. */
@media (max-width: 991.98px) {
    body.portal-ui .resource-filter-card {
        padding: 0.85rem !important;
    }
    body.portal-ui .resource-filter-toggle {
        min-height: 40px;
    }
    body.portal-ui .resource-filter-form .form-label {
        font-size: 0.75rem;
        margin-bottom: 0.2rem;
    }
}

/* C.4 — Pagination buttons at >= 40x40 on mobile.  Bootstrap's
   default page-link is too small (~32 px). */
@media (max-width: 991.98px) {
    body.portal-ui .pagination .page-link {
        min-width: 40px;
        min-height: 40px;
        padding: 0.5rem 0.75rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-weight: 500;
    }
    body.portal-ui .pagination .page-item.disabled .page-link {
        min-width: 40px;
        min-height: 40px;
    }
}
@media (max-width: 359.98px) {
    /* Tighter at small phones so all numeric pages still fit on one row */
    body.portal-ui .pagination .page-link {
        min-width: 36px;
        min-height: 40px;
        padding: 0.5rem 0.5rem;
    }
}

/* ============================================================
   Bucket D. Mobile back-pill (replaces tiny breadcrumb chains).
   Used on /resources/<>/, /quizzes/<>/<>/, /quizzes/<>/<>/results/<>/.
   !important on min-height because the older btn-sm rule wins by
   source order otherwise.
   ============================================================ */
body.portal-ui a.back-pill,
body.portal-ui .back-pill {
    min-height: 40px !important;
    padding: 0.5rem 0.95rem;
    border-radius: 999px;
    border: 1px solid rgba(42, 127, 134, 0.32);
    color: var(--s-accent-600, #20696F);
    background: rgba(255, 255, 255, 0.85);
    font-weight: 500;
    font-size: 0.85rem;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    text-decoration: none;
}
body.portal-ui .back-pill:hover,
body.portal-ui .back-pill:focus-visible {
    background: var(--s-accent-tint, rgba(42, 127, 134, 0.10));
    border-color: var(--s-accent, #2A7F86);
    color: var(--s-accent-600, #20696F);
    text-decoration: none;
}

/* ============================================================
   Bucket E. Digital products card system.
   Restyled to match the dashboard-card visual language with
   portal-specific classes. Behavior + links untouched.
   ============================================================ */
body.portal-ui .digital-access-card {
    padding: 1rem !important;
    border-radius: 16px !important;
    background: linear-gradient(180deg, rgba(255,255,255,0.96), rgba(248,251,252,0.98));
    border: 1px solid var(--s-border-subtle, #DCE6EF);
    box-shadow: 0 6px 18px rgba(15, 32, 48, 0.04);
    transition: box-shadow 0.2s ease, transform 0.05s ease;
}
body.portal-ui .digital-access-card:hover {
    box-shadow: 0 10px 22px rgba(42, 127, 134, 0.08);
}
body.portal-ui .digital-access-media {
    position: relative;
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 0.85rem;
    background: linear-gradient(135deg, rgba(252, 231, 243, 0.7), rgba(255, 247, 237, 0.7));
}
body.portal-ui .digital-access-image {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
}
body.portal-ui .digital-access-placeholder {
    width: 100%;
    aspect-ratio: 16 / 9;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--s-accent, #2A7F86);
    font-size: 2.4rem;
    background: linear-gradient(135deg, rgba(252, 231, 243, 0.9), rgba(255, 247, 237, 0.9));
}
body.portal-ui .digital-access-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--s-text, #1E2A3A);
    margin-bottom: 0.3rem;
    line-height: 1.3;
    /* Title 2-line clamp so very long product names don't blow up the card. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
body.portal-ui .digital-access-desc {
    font-size: 0.83rem;
    color: #5F6B7A;
    margin-bottom: 0.65rem;
    line-height: 1.4;
    /* Desc 2-line clamp */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
body.portal-ui .digital-access-meta {
    font-size: 0.75rem;
    color: #5F6B7A;
    margin-bottom: 0.85rem;
    line-height: 1.4;
}
body.portal-ui .digital-access-meta-sep {
    margin: 0 0.35rem;
    opacity: 0.55;
}
body.portal-ui .digital-access-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}
body.portal-ui .digital-access-btn-secondary,
body.portal-ui .digital-access-btn-primary {
    flex: 1 1 auto;
    min-height: 40px;
    border-radius: 999px;
    font-size: 0.85rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.45rem 0.8rem;
}
body.portal-ui .digital-access-btn-secondary {
    border: 1px solid rgba(42, 127, 134, 0.32);
    color: var(--s-accent-600, #20696F);
    background: rgba(255, 255, 255, 0.85);
    font-weight: 500;
}
body.portal-ui .digital-access-btn-secondary:hover,
body.portal-ui .digital-access-btn-secondary:focus-visible {
    background: var(--s-accent-tint, rgba(42, 127, 134, 0.10));
    border-color: var(--s-accent, #2A7F86);
    color: var(--s-accent-600, #20696F);
}
body.portal-ui .digital-access-btn-primary {
    background: var(--s-accent, #2A7F86);
    border-color: var(--s-accent, #2A7F86);
    color: #ffffff;
    font-weight: 600;
}
body.portal-ui .digital-access-btn-primary:hover,
body.portal-ui .digital-access-btn-primary:focus-visible {
    background: var(--s-accent-600, #20696F);
    border-color: var(--s-accent-600, #20696F);
    color: #ffffff;
}
@media (max-width: 575.98px) {
    body.portal-ui .digital-access-card {
        padding: 0.85rem !important;
    }
    body.portal-ui .digital-access-actions {
        flex-direction: column;
        gap: 0.4rem;
    }
    body.portal-ui .digital-access-actions .btn {
        width: 100%;
    }
}

/* ============================================================
   Bucket F. /portal/schedule/ "Add to calendar" tap target 44x44.
   The icon-only button (.schedule-event-ics) was 38 px. Bump it.
   ============================================================ */
body.portal-ui .schedule-event-ics {
    min-width: 44px !important;
    min-height: 44px !important;
    padding: 0.5rem 0.75rem;
}
@media (max-width: 575.98px) {
    /* On phone the action is full-width with a label, so just confirm
       min-height. Wider parent gives this naturally. */
    body.portal-ui .schedule-event-ics {
        min-height: 44px !important;
    }
}

/* ============================================================
   Bucket G. /grades/ mobile card compactness.
   Tighten padding while keeping all data + tap targets.
   ============================================================ */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard table.table-clean + .dashboard-mobile-list .dashboard-mobile-card,
    body.portal-ui .portal-dashboard .grade-mobile-card,
    body.portal-ui .portal-dashboard .dashboard-mobile-list .dashboard-mobile-card {
        padding: 0.7rem 0.85rem;
        margin-bottom: 0.55rem;
    }
    body.portal-ui .portal-dashboard .dashboard-mobile-card-actions .btn {
        min-height: 40px;
    }
}
/* END PHASE 26 BLOCK */

/* ============================================================
   PHASE 27 — Final design polish
   1. Dashboard small-phone (<= 360) target: first course top <= 540,
      first course card <= 215.
   2. Course learn module: drop resource-card description on phone,
      tighter module header, target resource ~150-170 px.
   3. Resource title tap target: block-level link with >= 36 px area.
   4. /resources/ pagination: min-width 44.
   5. Quiz history "Open My Grades" pill (template + CSS).
   6. Quiz results visual grouping: calmer dividers between sections,
      better whitespace.
   ============================================================ */

/* P27.1 — Dashboard <= 360 final compaction.
   Hits target first-course-top <= 540 by trimming the hero further,
   compacting the metric strip, and dropping the course-instructor
   line + tighter padding on the first course card. */
@media (max-width: 359.98px) {
    /* Hero: even tighter */
    body.portal-ui .portal-dashboard .continue-hero {
        padding: 0.7rem 0.8rem 0.85rem !important;
        margin-bottom: 0.75rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-eyebrow {
        font-size: 9px;
        margin-bottom: 2px;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-title {
        font-size: 15px;
        line-height: 19px;
        max-height: 38px;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-sub {
        font-size: 12px;
        margin-top: 1px;
    }
    body.portal-ui .portal-dashboard .continue-hero .progress.progress-soft {
        height: 6px;
        margin-top: 0.4rem;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta {
        margin-top: 0.55rem;
    }
    body.portal-ui .portal-dashboard .continue-hero .btn-hero {
        padding: 8px 12px;
        font-size: 13px;
    }
    /* Tighter rhythm between hero -> metrics -> Your courses */
    body.portal-ui .portal-dashboard .dashboard-metrics-row {
        margin-bottom: 0.6rem !important;
    }
    body.portal-ui .portal-dashboard .dashboard-metrics-row > .col-md-4 > .metric-card,
    body.portal-ui .portal-dashboard .dashboard-metrics-row > a.col-md-4 > .metric-card {
        max-height: 64px;
        padding: 0.35rem 0.35rem !important;
    }
    body.portal-ui .portal-dashboard .dashboard-metrics-row .metric-label {
        font-size: 0.55rem !important;
        margin-bottom: 0.15rem !important;
    }
    /* "Your courses" card padding tighter */
    body.portal-ui .portal-dashboard > .col-lg-8 > .dashboard-card,
    body.portal-ui .portal-dashboard .row.g-4 > .col-lg-8 > .dashboard-card {
        padding: 0.95rem !important;
        margin-bottom: 0.85rem !important;
    }
    /* First course card — compact at <= 360 */
    body.portal-ui .portal-dashboard .course-item {
        padding: 0.7rem 0.8rem !important;
        margin-bottom: 0.55rem !important;
    }
    body.portal-ui .portal-dashboard .course-item .course-title {
        font-size: 0.9rem;
        line-height: 1.2;
    }
    /* Hide instructor row at <= 360 — it's filler, the title carries
       the program identity. */
    body.portal-ui .portal-dashboard .course-item .course-instructor {
        display: none;
    }
    /* Status badge a touch smaller */
    body.portal-ui .portal-dashboard .course-item .stat-chip {
        font-size: 9.5px;
        padding: 1px 6px;
    }
    /* Stacked CTAs at <=360 — already stacking; tighten button height */
    body.portal-ui .portal-dashboard .course-item .course-cta-primary,
    body.portal-ui .portal-dashboard .course-item .course-cta-secondary {
        min-height: 36px !important;
        font-size: 0.78rem;
    }
    body.portal-ui .portal-dashboard .course-item .course-cta-row {
        margin-top: 0.45rem !important;
        gap: 0.3rem !important;
    }
}

/* P27.2 — Course learn module + resource compaction.
   Hide the resource-card description on phone (user explicitly OK'd
   "Hide or clamp secondary resource description on phones"). Tighter
   module header. */
@media (max-width: 575.98px) {
    /* Resource card without description — drops ~30 px to hit target. */
    body.portal-ui .module-detail-body .resource-card-desc {
        display: none;
    }
    /* Even tighter resource card padding when description is hidden */
    body.portal-ui .module-detail-body .resource-card {
        padding: 0.6rem 0.75rem;
        gap: 0.35rem;
    }
    body.portal-ui .module-detail-body .resource-card-icon {
        width: 32px;
        height: 32px;
        font-size: 0.95rem;
    }
    body.portal-ui .module-detail-body .resource-card-meta {
        font-size: 0.62rem;
        margin-bottom: 0.1rem;
    }
    body.portal-ui .module-detail-body .resource-card-title {
        font-size: 0.88rem;
    }
    body.portal-ui .module-detail-body .resource-card-course {
        font-size: 0.68rem;
    }
    body.portal-ui .module-detail-body .resource-card-action .btn {
        min-height: 36px;
        font-size: 0.8rem;
    }
}

/* Course learn module header: tighter at < lg.
   The .module-toggle (full-width title button) and adjacent "Mark as
   done" form need less vertical padding. */
@media (max-width: 991.98px) {
    body.portal-ui .module-card .module-detail-body {
        padding-top: 0.4rem;
    }
    body.portal-ui .module-card hr.my-3 {
        margin-top: 0.7rem !important;
        margin-bottom: 0.7rem !important;
    }
    body.portal-ui .module-card .metric-label {
        font-size: 0.78rem;
        margin-bottom: 0.4rem !important;
    }
    body.portal-ui .module-card {
        padding: 0.85rem 0.95rem !important;
        margin-bottom: 0.7rem !important;
    }
}

/* P27.3 — Resource title tap targets.
   Both the in-card resource title and the /resources/ list mobile
   card title get block-level link wrappers with min-height >= 36 px. */
body.portal-ui .resource-card-title a {
    display: block;
    min-height: 36px;
    padding: 0.25rem 0;
    margin: -0.25rem 0;     /* preserve visual rhythm */
    border-radius: 4px;
}
body.portal-ui .resource-card-title a:hover,
body.portal-ui .resource-card-title a:focus-visible {
    background: rgba(42, 127, 134, 0.05);
}
body.portal-ui .dashboard-mobile-list .dashboard-mobile-card-title a {
    display: block;
    min-height: 36px;
    padding: 0.25rem 0;
    margin: -0.25rem 0;
    border-radius: 4px;
}
body.portal-ui .dashboard-mobile-list .dashboard-mobile-card-title a:hover,
body.portal-ui .dashboard-mobile-list .dashboard-mobile-card-title a:focus-visible {
    background: rgba(42, 127, 134, 0.05);
    color: var(--s-accent, #2A7F86);
}

/* P27.4 — Pagination: bump min-width to 44 (was 40). */
@media (max-width: 991.98px) {
    body.portal-ui .pagination .page-link {
        min-width: 44px;
        min-height: 44px;
    }
}
@media (max-width: 359.98px) {
    /* Tighter at <= 360 so all numeric pages still fit */
    body.portal-ui .pagination .page-link {
        min-width: 40px;
        min-height: 44px;
        padding: 0.5rem 0.55rem;
    }
}

/* P27.5 — Quiz history "Open My Grades" pill + page-hint layout.
   The inline text-style link became a real pill button.  page-hint
   now uses flex so on phones the CTA wraps below the text cleanly. */
body.portal-ui .quiz-history-hint {
    background: #eef4ff;
    border: 1px solid #cfe0f8;
    color: #1e3a5f;
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    font-size: 0.92rem;
    line-height: 1.45;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.85rem;
}
body.portal-ui .quiz-history-hint-text {
    flex: 1 1 240px;
    min-width: 0;
}
body.portal-ui .quiz-history-hint-cta {
    flex: 0 0 auto;
    min-height: 40px !important;
    padding: 0.5rem 0.95rem;
    border-radius: 999px;
    border: 1px solid rgba(13, 110, 253, 0.30);
    color: #0d6efd;
    background: rgba(255, 255, 255, 0.85);
    font-weight: 500;
    font-size: 0.85rem;
    white-space: nowrap;
    text-decoration: none;
}
body.portal-ui .quiz-history-hint-cta:hover,
body.portal-ui .quiz-history-hint-cta:focus-visible {
    background: rgba(13, 110, 253, 0.08);
    border-color: #0d6efd;
    color: #0d6efd;
    text-decoration: none;
}
@media (max-width: 575.98px) {
    body.portal-ui .quiz-history-hint {
        font-size: 0.85rem;
        padding: 0.65rem 0.85rem;
        gap: 0.55rem;
    }
    body.portal-ui .quiz-history-hint-cta {
        width: 100%;
    }
}

/* P27.6 — Quiz results visual grouping.
   Calmer section dividers + tighter spacing on the question review
   list. The summary card (top) keeps its hero feel; the review
   stream below gets a clearer "Question N" rhythm so it scans
   faster. Also gives the past-attempts list a portal-card look. */
body.portal-ui .portal-dashboard .case-study-review {
    background: rgba(248, 251, 252, 0.55);
    border-radius: 14px;
    padding: 0.85rem;
    border: 1px solid rgba(30, 42, 58, 0.06);
    margin-bottom: 0.5rem;
}
body.portal-ui .portal-dashboard .case-study-children {
    margin-top: 0.7rem;
    padding-left: 0.5rem;
    border-left: 3px solid rgba(42, 127, 134, 0.2);
}
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .case-study-review {
        padding: 0.7rem 0.7rem;
    }
    body.portal-ui .portal-dashboard .case-study-children {
        margin-left: 0;
        padding-left: 0.4rem;
    }
}
/* "Question-by-question review" section heading: more breathing room
   so the user knows the summary card ended and review begins. */
body.portal-ui .portal-dashboard h5.mb-3 {
    margin-top: 0.5rem;
}
@media (max-width: 575.98px) {
    body.portal-ui .portal-dashboard .dashboard-card {
        margin-bottom: 0.85rem;
    }
}
/* END PHASE 27 BLOCK */

/* ============================================================
   PHASE 28 — Final fine-tuning. CSS-only block; no template touch.
   Trim hero / first course / module / pagination / quiz results
   per the latest measured-vs-target gaps.
   ============================================================ */

/* P28.A — Hero compression at < lg.
   Shave ~30 px off the hero without removing any visible content.
   Title 2-line clamp from earlier phases stays. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .continue-hero {
        padding: 0.7rem 0.95rem 0.85rem !important;
        margin-bottom: 0.75rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-eyebrow {
        font-size: 9.5px !important;
        margin-bottom: 3px !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-title {
        font-size: 16px !important;
        line-height: 21px !important;
        max-height: 42px !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-sub {
        font-size: 12px !important;
        margin-top: 1px !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .progress.progress-soft {
        height: 6px !important;
        margin-top: 0.4rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta {
        margin-top: 0.5rem !important;
        gap: 0.25rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .btn-hero {
        padding: 8px 14px !important;
        font-size: 13px !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta a.text-muted {
        font-size: 10.5px !important;
        margin-top: 0.15rem !important;
    }
}
@media (max-width: 359.98px) {
    body.portal-ui .portal-dashboard .continue-hero {
        padding: 0.6rem 0.7rem 0.7rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-title {
        font-size: 15px !important;
        line-height: 19px !important;
        max-height: 38px !important;
    }
}

/* P28.B — First course position polish.
   Trim metrics-row bottom margin + Your-courses card top padding so
   the first course rises a bit higher with the same content. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .dashboard-metrics-row {
        margin-bottom: 0.75rem !important;
    }
    body.portal-ui .portal-dashboard .row.g-4 > .col-lg-8 > .dashboard-card,
    body.portal-ui .portal-dashboard .col-lg-8 > .dashboard-card:first-child {
        padding-top: 1rem !important;
    }
}

/* P28.C — Course-learn first module compression.
   Resource cards already hit target (~147 px); trim the module-card
   wrapper, hr margins, section-header rhythm + shrink the title row
   (was 151 px tall because the "Mark as done" button wrapped onto
   its own line — now wraps tighter or stays inline). */
@media (max-width: 991.98px) {
    body.portal-ui .module-card {
        padding: 0.6rem 0.85rem !important;
        margin-bottom: 0.55rem !important;
    }
    /* Resource list inside module: tighten gap between resources. */
    body.portal-ui .module-card .module-detail-body > div:last-child {
        margin-top: 0 !important;
    }
    /* If two resources sit inline as `.resource-card` siblings, kill
       extra vertical breathing room between them at < 576. */
    body.portal-ui .module-card .resource-card + .resource-card {
        margin-top: 0.4rem;
    }
    body.portal-ui .module-card hr.my-3 {
        margin-top: 0.55rem !important;
        margin-bottom: 0.55rem !important;
    }
    body.portal-ui .module-card .metric-label {
        font-size: 0.74rem;
        margin-bottom: 0.3rem !important;
    }
    body.portal-ui .module-card .module-detail-body {
        padding-top: 0.3rem !important;
    }
    /* Title row bottom margin tightened. */
    body.portal-ui .module-card > .d-flex {
        margin-bottom: 0.4rem !important;
        gap: 0.5rem !important;        /* was 1rem (gap-3) */
    }
    /* Mark-as-done button compactness so it doesn't wrap to a 2nd
       row OR if it does wrap, it's shorter. */
    body.portal-ui .module-card form button.btn {
        padding: 0.4rem 0.75rem !important;
        font-size: 0.82rem !important;
        min-height: 36px;
    }
    /* Description in module detail body: 2-line clamp (was 51 px on
       2-3 line description). Saves ~17 px without removing the
       text — full text shows on tap-to-expand if the user wants it. */
    body.portal-ui .module-card .module-detail-body > p.text-muted {
        font-size: 0.85rem;
        line-height: 1.4;
        margin-bottom: 0.4rem !important;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
}

/* P28.D — Pagination 44x44 at 320.
   Phase 27 set min-width 40 at <= 360. User wants 44 across the board
   (5 buttons × 44 + gaps ≈ 240 px, fits comfortably in the 290-px
   content area at 320). */
@media (max-width: 359.98px) {
    body.portal-ui .pagination .page-link {
        min-width: 44px !important;
        min-height: 44px !important;
        padding: 0.5rem 0.45rem;
    }
}

/* P28.E — Quiz results scanability.
   Tighten the question-by-question review card grid + per-card
   padding + past-attempts list rows for less vertical drag. No
   change to scoring, rationale, or color-coded answer logic.
   Excludes .module-card so course-learn modules aren't affected. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard h5 + .d-grid {
        gap: 0.7rem !important;
    }
    body.portal-ui .portal-dashboard .d-grid > .dashboard-card:not(.module-card) {
        padding: 0.85rem !important;
    }
    body.portal-ui .portal-dashboard .dashboard-card .list-unstyled li {
        padding: 0.65rem 0 !important;
    }
}
/* END PHASE 28 BLOCK */

/* ============================================================
   PHASE 29 — Force readable sans-serif (Inter) on all student-
   portal headings + display text. Cormorant Garamond was being
   inherited from base stylesheets onto h2-h6 inside .portal-ui;
   this single block locks every student-facing heading to Inter
   without touching public/admin pages. The 14-rule explicit list
   covers .dashboard-card, .module-card, hero, schedule cards,
   case-study reviews, and bare h2-h6 in any .portal-dashboard /
   .portal-course / .portal-content scope.
   ============================================================ */
body.portal-ui h1,
body.portal-ui h2,
body.portal-ui h3,
body.portal-ui h4,
body.portal-ui h5,
body.portal-ui h6,
body.portal-ui .h1,
body.portal-ui .h2,
body.portal-ui .h3,
body.portal-ui .h4,
body.portal-ui .h5,
body.portal-ui .h6,
body.portal-ui .display-1,
body.portal-ui .display-2,
body.portal-ui .display-3,
body.portal-ui .display-4,
body.portal-ui .display-5,
body.portal-ui .display-6 {
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif !important;
}
/* END PHASE 29 BLOCK */

/* ============================================================
   PHASE 30 — /portal/quizzes/ course-card title 2-line clamp.
   Was text-truncate (1-line ellipsis "_stress_ PMHNP Revi...").
   Now wraps to 2 lines + clamps with ellipsis if a 3rd line
   would be needed. Full title preserved in the title attr.
   ============================================================ */
body.portal-ui .quiz-hub-course-title {
    line-height: 1.25;
    font-size: 0.98rem;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break: break-word;
}
@media (max-width: 575.98px) {
    body.portal-ui .quiz-hub-course-title {
        font-size: 0.92rem;
    }
}
/* END PHASE 30 BLOCK */

/* ============================================================
   PHASE 31 — Continue Hero CTA responsive wrap polish.
   The "Resume quiz: <quiz title>" label can be 30-40 chars long.
   On narrow phones it would wrap awkwardly with "15" alone on a
   2nd line. Switch to `text-wrap: balance` (line-balanced) +
   tighter line-height + min-height so the button looks deliberate
   regardless of label length. Modern browsers (Chrome 114+,
   Safari 17+, Firefox 121+) get balanced lines; older browsers
   fall back to natural wrap.
   ============================================================ */
body.portal-ui .btn-hero,
body.portal-ui .btn-hero.btn-primary,
body.portal-ui .continue-hero .btn-primary {
    /* Allow the label to wrap to 2 lines cleanly. */
    white-space: normal !important;
    line-height: 1.3 !important;
    text-align: center;
    /* Modern browsers: balance the line lengths so we never get
       "Resume quiz: _stress_ Quiz 1: Topic" / "15" splits. */
    text-wrap: balance;
    /* Allow break at any character for very long synthetic
       quiz titles without overflowing the button. */
    overflow-wrap: anywhere;
    /* Comfortable touch target even when text wraps. */
    min-height: 44px;
    /* Inline-flex so icon + text vertically center on each line. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
}
@media (max-width: 575.98px) {
    body.portal-ui .btn-hero,
    body.portal-ui .btn-hero.btn-primary,
    body.portal-ui .continue-hero .btn-primary {
        font-size: 14px !important;
        padding: 0.55rem 1.1rem !important;
        line-height: 1.25 !important;
    }
}
@media (max-width: 359.98px) {
    body.portal-ui .btn-hero,
    body.portal-ui .btn-hero.btn-primary,
    body.portal-ui .continue-hero .btn-primary {
        font-size: 13px !important;
        padding: 0.5rem 0.9rem !important;
    }
}
/* END PHASE 31 BLOCK */

/* ============================================================
   PHASE 32 / 34 — Recent quiz history visual polish.
   Phase 34 update: removed the colored left accent stripe (user
   feedback: "remove the green and red line"). Status communication
   stays via the score chip color. Hover tint kept.
   ============================================================ */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row {
    position: relative;
    padding: 0.75rem 0;
    border-radius: 8px;
    transition: background 0.18s ease;
}
/* Hover state — subtle bg tint so the row reads as an actionable item. */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row:hover {
    background: rgba(42, 127, 134, 0.04);
}
/* Title slightly bolder + clamp at 1 line on phone, 2 lines elsewhere. */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-title {
    font-weight: 700;
    color: #1E2A3A;
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-title {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}
/* Better Review pill — use accent color, not muted gray. */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-review-btn {
    min-height: 36px;
    padding: 0.35rem 0.85rem;
    border-radius: 999px;
    border: 1px solid rgba(42, 127, 134, 0.32);
    color: var(--s-accent-600, #20696F);
    background: rgba(255, 255, 255, 0.85);
    font-weight: 500;
    font-size: 0.78rem;
    white-space: nowrap;
    transition: background 0.15s ease, border-color 0.15s ease;
}
body.portal-ui .portal-dashboard .timeline-list .quiz-history-review-btn:hover,
body.portal-ui .portal-dashboard .timeline-list .quiz-history-review-btn:focus-visible {
    background: var(--s-accent-tint, rgba(42, 127, 134, 0.10));
    border-color: var(--s-accent, #2A7F86);
    color: var(--s-accent-600, #20696F);
    text-decoration: none;
}
/* Score chip slightly bolder + tabular nums so 0.00% / 60.00% line up. */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .stat-chip {
    font-weight: 700 !important;
    font-variant-numeric: tabular-nums;
}
/* Score chip status colors — subtle but visible. */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .stat-chip.danger {
    background: rgba(196, 69, 105, 0.12);
    color: #C44569;
}
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .stat-chip.success {
    background: rgba(46, 139, 87, 0.14);
    color: #1F6D45;
}
/* Tighter row gap on narrow phones so 320 doesn't get cramped. */
@media (max-width: 359.98px) {
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row {
        padding-left: 0.7rem;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row::before {
        width: 2.5px;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .quiz-history-review-btn {
        font-size: 0.74rem;
        padding: 0.3rem 0.7rem;
    }
}
/* END PHASE 32 BLOCK */

/* ============================================================
   PHASE 33 / 35 — Recent quiz history meta (HORIZONTAL, all devices).
   User feedback after the column variant: "I want a horizontal device
   responsive in all". Switch the meta back to a horizontal row so
   course + · + date sit side-by-side. Course is allowed to WRAP (no
   nowrap+ellipsis "Hel..." mid-word cut), and flex-wrap lets the date
   drop to a 2nd line gracefully if there's no room on the same line.
   This layout works at 320 → 1440+.
   ============================================================ */
@media (max-width: 991.98px) {
    /* Meta row — horizontal flex with wrap so date follows course
       inline, dropping below only when course consumes the full width. */
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta {
        flex-direction: row !important;
        flex-wrap: wrap !important;
        align-items: baseline !important;
        gap: 0.15rem 0.35rem;          /* row-gap col-gap */
        margin-top: 0.2rem;            /* breathe from title above */
        min-width: 0;
        overflow: visible !important;  /* allow course wrap, no clip */
    }
    /* Course title — wraps freely, no ellipsis. Takes only as much
       width as it needs; long names wrap to a 2nd line within the row. */
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta-course {
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        word-break: break-word;
        flex: 0 1 auto;
        min-width: 0;
        max-width: 100%;
        line-height: 1.4;
        font-size: 0.78rem;
    }
    /* Date — pinned inline beside course, never shrinks, never breaks
       its own text. flex-wrap on the parent moves it to row 2 if no
       room on row 1. */
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta-date {
        flex-shrink: 0;
        white-space: nowrap;
        font-size: 0.72rem;
        opacity: 0.75;
    }
    /* Inline · separator between course and date. Phase 33 (column)
       had hidden it — bring it back for horizontal. */
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta-date::before {
        content: '·' !important;
        display: inline !important;
        margin-right: 0.3rem;
        opacity: 0.55;
    }
    /* Bottom row — Review pill aligns to top-right so it pins to the
       top of the row regardless of how tall the wrapped meta becomes. */
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row-bottom {
        align-items: flex-start !important;
    }
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-review-btn {
        margin-top: 2px;
    }
}
/* END PHASE 33 / 35 BLOCK */

/* Phase 23 — Upcoming Session tile mobile-only date value.
   The .upcoming-session-mobile-value uses the standard .metric-value
   sizing rules from chip mode + Inter font, but its content is short
   ("10 MAY") instead of a percentage so it fits cleanly. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .upcoming-session-mobile-value {
        margin-top: 0.25rem;
        text-align: center;
    }
}

/* Phase 24 — visual consistency follow-ups.
   1. Center OVERALL PROGRESS metric-value at < lg (was left-aligned
      because it sits in a d-flex container that defaults to flex-start).
   2. Top-align schedule-event-card date-blocks so they line up
      vertically across cards of varying title lengths.
   3. Quiz-history row polish: tighter chip, calmer Review button
      so the row reads as one unit instead of competing pieces.
   4. /portal/courses/ secondary CTAs ("Open Quizzes", "Quiz History")
      pick up the same pill shape + accent tint as the primary.
   ========================================================== */

/* P24.1 — Center metric-value content in chip mode. The .d-flex
   wrapper around the OVERALL PROGRESS value defaults to
   justify-content: flex-start. Override at < lg so the value is
   horizontally centered like the other tiles. */
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .dashboard-metrics-row .col-md-4 .metric-card .d-flex {
        justify-content: center !important;
    }
    /* Also center the metric-value itself when it's a direct child. */
    body.portal-ui .portal-dashboard .dashboard-metrics-row .col-md-4 .metric-card > .metric-value {
        text-align: center;
        width: 100%;
    }
    /* Hide the inline progress bar inside the third tile in chip mode
       so the 12% value owns the tile centerline. The full progress
       bar still renders at >= lg. */
    body.portal-ui .portal-dashboard .dashboard-metrics-row .col-md-4 .metric-card > .progress.progress-soft {
        display: none;
    }
}

/* P24.2 — Schedule cards top-align date-blocks.
   Was align-items: center → date-block floated mid-card when titles
   wrapped to 2 lines. Top-align means all date-blocks pin to the
   same Y across cards regardless of title length. */
body.portal-ui .schedule-event-card {
    align-items: flex-start !important;
}

/* P24.3 — Recent quiz history polish. Tighter chip + Review pill +
   calmer typography so the row reads as one unit. */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row {
    padding: 0.7rem 0;
}
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .stat-chip {
    font-size: 9.5px !important;
    padding: 2px 7px !important;
    line-height: 1.4;
    font-weight: 700;
    letter-spacing: 0.02em;
    /* Fixed min-width so chips of different score lengths align. */
    min-width: 56px;
    text-align: center;
}
body.portal-ui .portal-dashboard .timeline-list .quiz-history-title {
    font-size: 0.95rem;
    line-height: 1.3;
    color: var(--s-text, #1E2A3A);
}
body.portal-ui .portal-dashboard .timeline-list .quiz-history-meta {
    color: #5F6B7A;
    font-size: 0.74rem;
}
body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .btn.btn-sm.btn-outline-secondary {
    font-size: 0.78rem;
    padding: 0.32rem 0.7rem;
    border-radius: 999px;        /* full pill — friendlier than rectangular */
    border-color: rgba(30, 42, 58, 0.18);
}

/* P24.4 — /portal/courses/ secondary CTAs pick up pill style.
   The two outline-secondary buttons under the primary "View Course"
   were rectangular boxes — adopt the same border-radius + soft
   accent border so they feel like siblings of the primary, not
   separate cards. Scoped to the secondaries inside .course-card-cta-row
   so it doesn't bleed to other outline-secondary buttons in the portal.
   align-items: center on the wrapper prevents the children from
   stretching to a 2-line-tall (59 px) bug from default flex
   align-items: stretch. */
body.portal-ui .course-card-cta-row .course-cta-secondaries {
    align-items: center !important;
}
body.portal-ui .course-card-cta-row .course-cta-secondaries .btn-outline-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 40px;                       /* explicit, defeats the stretch bug */
    min-height: 40px !important;
    padding: 0.4rem 0.8rem;
    line-height: 1.2;
    border-radius: 999px;
    border: 1px solid rgba(42, 127, 134, 0.32);
    color: var(--s-accent-600, #20696F);
    background: rgba(255, 255, 255, 0.85);
    font-weight: 500;
    font-size: 0.83rem;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
body.portal-ui .course-card-cta-row .course-cta-secondaries .btn-outline-secondary:hover,
body.portal-ui .course-card-cta-row .course-cta-secondaries .btn-outline-secondary:focus-visible {
    background: var(--s-accent-tint, rgba(42, 127, 134, 0.10));
    border-color: var(--s-accent, #2A7F86);
    color: var(--s-accent-600, #20696F);
}
/* Make the primary CTA at least 40 px on mobile so it visually
   anchors above the matched secondaries. */
@media (max-width: 991.98px) {
    body.portal-ui .course-card-cta-row .course-cta-primary {
        min-height: 44px !important;
    }
}
/* END PHASE 22/23/24 BLOCK */

/* ============================================================
   PHASE 36 — Final student-mobile polish (10/10).

   5 measured items remained after Phase 35:
     1. Dashboard hero too tall at 360 (293) and 390 (276) — Phase
        27.1's aggressive trims only fired at <=359.98, so 360-575
        was running on softer Phase 16/B.1 numbers. Add a <=575.98
        middle tier with Phase 27-style numbers.
     2. Dashboard first course Y too low — same root cause + the
        col-lg-8 first dashboard-card padding was 1rem, card-title-row
        margin-bottom was Bootstrap default. Tighten both at <=575.98.
     3. Course-learn first module too heavy (~615 px) — extend P28.C
        with tighter hr, body padding-top, grid gap, title row.
     4. Pagination 44 x 44 at 320 — P28.D already declares !important;
        harden specificity + ensure collectstatic publishes the new
        hashed copy.
     5. Quiz results body too long — trim per-question card padding,
        header mb, rationale mt, and the 3.6 rem score number on the
        summary card. Inline review-choice padding/margin already
        tightened in templates/quizzes/results.html.

   All changes are CSS-only and cap at <=991.98 / <=575.98 / <=359.98
   so desktop and tablet >= lg don't regress.
   ============================================================ */

/* ----- P36.1 — Hero compaction at <=575.98 ----- */
@media (max-width: 575.98px) {
    body.portal-ui .portal-dashboard .continue-hero {
        padding: 0.85rem 0.95rem 1rem !important;
        margin-bottom: 0.85rem !important;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-eyebrow {
        font-size: 9.5px;
        margin-bottom: 3px;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-title {
        font-size: 16px;
        line-height: 21px;
        max-height: 42px;              /* 2 x 21 */
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-sub {
        font-size: 12.5px;
        margin-top: 1px;
    }
    body.portal-ui .portal-dashboard .continue-hero .progress.progress-soft,
    body.portal-ui .portal-dashboard .continue-hero .hero-progress {
        height: 6px;
        margin-top: 0.45rem;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta {
        margin-top: 0.6rem;
    }
    body.portal-ui .portal-dashboard .continue-hero .btn-hero {
        padding: 9px 14px;
        font-size: 13.5px;
    }
    body.portal-ui .portal-dashboard .continue-hero .hero-cta a.text-muted {
        font-size: 11.5px;
        margin-top: 0.25rem;
    }
}

/* ----- P36.2 — First-course Y reduction at <=575.98 ----- */
@media (max-width: 575.98px) {
    body.portal-ui .portal-dashboard .dashboard-metrics-row {
        margin-bottom: 0.75rem !important;
    }
    body.portal-ui .portal-dashboard .col-lg-8 > .dashboard-card:first-child,
    body.portal-ui .portal-dashboard .row.g-4 > .col-lg-8 > .dashboard-card:first-child {
        padding: 0.85rem 0.95rem !important;
        margin-bottom: 0.85rem !important;
    }
    body.portal-ui .portal-dashboard .col-lg-8 > .dashboard-card:first-child .card-title-row {
        margin-bottom: 0.55rem !important;
    }
    body.portal-ui .portal-dashboard .col-lg-8 > .dashboard-card:first-child .card-title-row h4 {
        font-size: 1rem;
    }
    body.portal-ui .portal-dashboard .col-lg-8 > .dashboard-card:first-child .section-helper {
        font-size: 0.78rem;
        margin-top: 0;
    }
}

/* ----- P36.3 — Course-learn first module compression at <=575.98 ----- */
@media (max-width: 575.98px) {
    body.portal-ui .module-card {
        padding: 0.55rem 0.8rem !important;
    }
    body.portal-ui .module-card hr.my-3 {
        margin-top: 0.45rem !important;
        margin-bottom: 0.45rem !important;
    }
    body.portal-ui .module-card .metric-label.small {
        font-size: 0.72rem;
        margin-bottom: 0.25rem !important;
    }
    body.portal-ui .module-card .module-detail-body {
        padding-top: 0.25rem !important;
    }
    /* Inner d-grid (quizzes / resources list) — Bootstrap default
       0.5 rem drops to 0.35 rem so 2-3 child cards stack tighter. */
    body.portal-ui .module-card .module-detail-body .d-grid {
        gap: 0.35rem !important;
    }
    /* Title row — tighter gap so badge + chevron sit closer. */
    body.portal-ui .module-card > .d-flex {
        margin-bottom: 0.3rem !important;
        gap: 0.4rem !important;
    }
    body.portal-ui .module-card .module-toggle .module-toggle-label {
        font-size: 0.96rem;
        line-height: 1.3;
    }
    body.portal-ui .module-card form button.btn {
        padding: 0.35rem 0.7rem !important;
        font-size: 0.8rem !important;
    }
    body.portal-ui .module-card .module-detail-body > p.text-muted {
        margin-bottom: 0.3rem !important;
    }
}

/* ----- P36.4 — Pagination 44 x 44 (harden specificity) -----
   P28.D already declares !important at <=359.98; this layer adds
   one more selector tier so any Bootstrap fallback in cached CSS
   is overridden after collectstatic re-publishes. */
@media (max-width: 359.98px) {
    body.portal-ui .pagination .page-item .page-link,
    body.portal-ui nav[aria-label*="Pagination" i] .page-item .page-link {
        min-width: 44px !important;
        min-height: 44px !important;
        width: auto;
        padding: 0.5rem 0.4rem !important;
        font-size: 0.85rem;
    }
}
@media (min-width: 360px) and (max-width: 991.98px) {
    body.portal-ui .pagination .page-item .page-link {
        min-width: 44px !important;
        min-height: 44px !important;
    }
}

/* ----- P36.5 — Quiz results scannability ----- */
@media (max-width: 991.98px) {
    /* Per-question review card — tighter padding + smaller header
       margin so question text + 4 choices + rationale group reads
       as one unit. */
    body.portal-ui .portal-dashboard .question-card {
        padding: 0.7rem 0.85rem !important;
    }
    body.portal-ui .portal-dashboard .question-card > .d-flex.align-items-start {
        margin-bottom: 0.5rem !important;
    }
    body.portal-ui .portal-dashboard .question-card .alert.alert-light {
        padding: 0.5rem 0.7rem !important;
        margin-top: 0.5rem !important;
        font-size: 0.85rem;
        line-height: 1.45;
    }
    /* Top summary card — score number was 3.6 rem. Trim to 2.8 rem
       (still anchor weight) + smaller pass/fail icon + tighter
       button row gap. */
    body.portal-ui .portal-dashboard .dashboard-card.text-center {
        padding: 1.1rem 1rem !important;
    }
    body.portal-ui .portal-dashboard .dashboard-card.text-center > div[style*="font-size:3.6rem"] {
        font-size: 2.8rem !important;
    }
    body.portal-ui .portal-dashboard .dashboard-card.text-center .icon-empty-state-lg {
        font-size: 2rem !important;
    }
    body.portal-ui .portal-dashboard .dashboard-card.text-center .d-flex.flex-wrap.justify-content-center {
        margin-top: 1rem !important;
        gap: 0.4rem !important;
    }
}
@media (max-width: 575.98px) {
    body.portal-ui .portal-dashboard .question-card {
        padding: 0.6rem 0.75rem !important;
    }
}
/* END PHASE 36 BLOCK */

/* ============================================================
   PHASE 37 — Recent quiz history Review pill touch target.
   Phase 32 set min-height: 36px on .quiz-history-review-btn,
   which renders ~32px tall in practice on the dashboard. Bump
   to >= 40px on all breakpoints, 44px on mobile (matches WCAG
   2.5.5 minimum). Layout, copy, and logic untouched.
   ============================================================ */
body.portal-ui .portal-dashboard .timeline-list .quiz-history-review-btn {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
@media (max-width: 991.98px) {
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-review-btn {
        min-height: 44px;
        padding: 0.45rem 0.95rem;
    }
}
/* Phase 32's <=359.98 override shrank font + padding; preserve
   that smaller text but keep the 44px height. */
@media (max-width: 359.98px) {
    body.portal-ui .portal-dashboard .timeline-list .quiz-history-row .quiz-history-review-btn {
        min-height: 44px;
        padding: 0.4rem 0.8rem;
        font-size: 0.74rem;
    }
}
/* END PHASE 37 BLOCK */

/* ============================================================
   PHASE 38 — Schedule mobile readability.
   1. .schedule-event-title was clamped to 2 lines at 0.95rem on
      phones — that cut "[demo] Mid-term self-assessment quiz" to
      "...self-assessme…". Allow 3 lines + word-break so titles
      finish on their own.
   2. The smallest phones (<= 359.98) get a slight font shrink so
      3 lines still fit without bloating row height.
   3. The "click to expand" helper text on the Past-sessions toggle
      is hidden on phones via Bootstrap utilities in schedule.html
      (Phase 38.A); no CSS rule needed for it.
   ============================================================ */
@media (max-width: 575.98px) {
    body.portal-ui .schedule-event-title {
        -webkit-line-clamp: 3;
        line-clamp: 3;
        word-break: break-word;
        line-height: 1.32;
    }
    body.portal-ui .schedule-event-title a {
        white-space: normal;
    }
}
@media (max-width: 359.98px) {
    body.portal-ui .schedule-event-title {
        font-size: 0.9rem;
        -webkit-line-clamp: 3;
        line-clamp: 3;
    }
}
/* END PHASE 38 BLOCK */

