/*
 * theme_components.css — Component Styles
 * =========================================
 * All component styles for the enterprise bluish theme.
 *
 * RULES (from CLAUDE_UI_LOCK.md):
 *   - Every rule MUST start with .themed
 *   - Every component MUST use tokens from theme_tokens.css
 *   - No inline styles, no arbitrary hex values
 *   - Mobile breakpoints included for every component
 *
 * TABLE OF CONTENTS:
 *   1.  Layout — Sidebar, Header, Page Wrapper
 *   2.  Navigation — Sidebar links, sections, user info
 *   3.  Parent Navbar
 *   4.  Cards & Panels
 *   5.  Buttons
 *   6.  Form Elements
 *   7.  Tables
 *   8.  Badges & Chips
 *   9.  Status Indicators (Attendance)
 *  10.  Alerts & Flash Messages
 *  11.  Modals
 *  12.  Dropdowns
 *  13.  Stats & Metrics
 *  14.  AI & Insights Components
 *  15.  AI Workshop Components
 *  16.  Charts (CSS variables for JS consumption)
 *  17.  Interventions
 *  18.  Responsive — Mobile fixes
 *  19.  Feature Requests
 *  20.  Feature Requests Internal
 *  21.  Manual Schedule Editor
 */


/* =============================================================================
   1. LAYOUT — SIDEBAR, HEADER, PAGE WRAPPER
   ============================================================================= */

.themed .t-sidebar {
  background-color: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
  box-shadow: var(--shadow-sm);
}

.themed .t-header {
  background-color: var(--header-bg);
  border-bottom: 1px solid var(--header-border);
  box-shadow: var(--shadow-sm);
}

.themed .t-page-wrapper {
  background-color: var(--color-canvas);
  min-height: 100vh;
}

.themed .t-main-content {
  background-color: var(--color-canvas);
}

/* Mobile backdrop for sidebar */
.themed .t-mobile-backdrop {
  background-color: var(--color-overlay);
}


/* =============================================================================
   2. NAVIGATION — SIDEBAR LINKS, SECTIONS, USER INFO
   ============================================================================= */

.themed .t-nav-link {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  color: var(--nav-link-color);
  font-size: var(--text-base);
  font-weight: var(--font-weight-normal);
  transition: background-color var(--transition-fast),
              color var(--transition-fast);
  text-decoration: none;
  gap: var(--space-2-5);
  position: relative;
  /* Invisible left border placeholder — prevents layout shift on active */
  border-left: 3px solid transparent;
}

.themed .t-nav-link:hover {
  background-color: var(--nav-link-hover-bg);
  color: var(--nav-link-hover-color);
  text-decoration: none;
  /* Subtle left border hint on hover — preview of active state */
  border-left-color: var(--color-border);
}

.themed .t-nav-link.active {
  background-color: var(--nav-link-active-bg);
  color: var(--nav-link-active-text);
  font-weight: var(--font-weight-medium);
  border-left-color: var(--nav-link-active-border);
}

/* Left border accent on active nav item — replaced by border-left approach */

.themed .t-nav-link svg {
  flex-shrink: 0;
  width: 1.125rem;
  height: 1.125rem;
  transition: color var(--transition-fast);
}

.themed .t-nav-section-header {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--nav-section-color);
  text-transform: uppercase;
  letter-spacing: 0.075em;
  padding: var(--space-2) var(--space-4) var(--space-1);
  margin-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-3);
}

.themed .t-nav-divider {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--space-3) var(--space-3);
}

.themed .t-user-info {
  background-color: var(--nav-user-bg);
  border-top: 1px solid var(--color-border);
  padding: var(--space-3) var(--space-4);
}

/* Logout/action link in user info area */
.themed .t-user-info a {
  color: var(--color-text-subtle);
  transition: color var(--transition-fast);
}
.themed .t-user-info a:hover {
  color: var(--color-text-base);
}

.themed .t-user-avatar {
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-full);
  background-color: var(--color-primary-600);
  color: var(--color-text-inverse);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  flex-shrink: 0;
}

/* ── Avatar Component ─────────────────────────────────────────────────────── */
/* Reusable avatar: photo with initials fallback.                             */
/* Sizes: xs (1.75rem) · sm (2rem) · md (2.5rem) · lg (3rem) · xl (4rem)     */
/* Variants: staff (primary bg) · student (primary-100 bg) · neutral (muted) */

.themed .t-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  flex-shrink: 0;
  overflow: hidden;
  line-height: 1;
}

/* ── Sizes ── */
.themed .t-avatar-xs {
  width: 1.75rem;
  height: 1.75rem;
  font-size: var(--text-xs);
}
.themed .t-avatar-sm {
  width: 2rem;
  height: 2rem;
  font-size: var(--text-xs);
}
.themed .t-avatar-md {
  width: 2.5rem;
  height: 2.5rem;
  font-size: var(--text-sm);
}
.themed .t-avatar-lg {
  width: 3rem;
  height: 3rem;
  font-size: var(--text-base);
}
.themed .t-avatar-xl {
  width: 4rem;
  height: 4rem;
  font-size: var(--text-xl);
}

/* ── Initials variants ── */
.themed .t-avatar-initials {
  font-weight: var(--font-weight-semibold);
}
.themed .t-avatar-staff {
  background-color: var(--color-primary-600);
  color: var(--color-text-inverse);
}
.themed .t-avatar-student {
  background-color: var(--color-primary-100);
  color: var(--color-primary-600);
}
.themed .t-avatar-neutral {
  background-color: var(--color-surface-hover);
  color: var(--color-text-muted);
}

/* ── Image variant ── */
.themed .t-avatar-image {
  object-fit: cover;
  border-radius: var(--radius-full);
}

/* ── Mobile breakpoints (R6) ── */
@media (max-width: 768px) {
  .themed .t-avatar-xl {
    width: 3rem;
    height: 3rem;
    font-size: var(--text-base);
  }
  .themed .t-avatar-lg {
    width: 2.5rem;
    height: 2.5rem;
    font-size: var(--text-sm);
  }
}
@media (max-width: 480px) {
  .themed .t-avatar-xl {
    width: 2.5rem;
    height: 2.5rem;
    font-size: var(--text-sm);
  }
  .themed .t-avatar-lg {
    width: 2rem;
    height: 2rem;
    font-size: var(--text-xs);
  }
}

.themed .t-user-name {
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-base);
  line-height: var(--leading-tight);
}

.themed .t-user-role {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}


/* =============================================================================
   3. PARENT NAVBAR
   ============================================================================= */

/* The parent navbar is a light/white header that mirrors the admin dashboard
   chrome — so the school's navy, transparent-background logo reads cleanly with
   no white chip, and the brand text is dark (no blue-on-blue). */
.themed .t-parent-navbar {
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  box-shadow: var(--shadow-sm);
}

.themed .t-parent-nav-link {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  transition: background-color var(--transition-fast),
              color var(--transition-fast);
  gap: var(--space-2);
}

.themed .t-parent-nav-link:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-base);
  text-decoration: none;
}

.themed .t-parent-nav-link.active {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
}

/* Component: Parent nav link leading icon */
.themed .t-parent-nav-icon {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
  opacity: 0.9;
}

/* Component: Parent nav unread badge (Messagerie count) */
.themed .t-parent-nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.125rem;
  height: 1.125rem;
  margin-left: var(--space-1);
  padding: 0 var(--space-1);
  border-radius: var(--radius-full);
  background-color: var(--color-primary-600);
  color: var(--color-text-inverse);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-bold);
  line-height: 1;
}

/* Component: Parent navbar brand link.
   The global `.themed a` rule (theme_scope.css, specificity 0,1,1) would override
   Tailwind's text colour on the brand anchor; this class (0,2,0) pins it to the
   base text token so it reads dark on the white navbar (mirrors the admin header).
   The nav links already escape via `.t-parent-nav-link`. */
.themed .t-parent-brand {
  color: var(--color-text-base);
  text-decoration: none;
}
.themed .t-parent-brand:hover {
  color: var(--color-text-base);
  text-decoration: none;
  opacity: 0.85;
}

@media (max-width: 768px) {
  .themed .t-parent-nav-badge {
    min-width: 1rem;
    height: 1rem;
  }
  .themed .t-parent-brand {
    font-size: var(--text-base);
  }
}
@media (max-width: 480px) {
  .themed .t-parent-nav-icon {
    width: 0.9375rem;
    height: 0.9375rem;
  }
}

.themed .t-parent-mobile-menu {
  background-color: var(--color-surface);
  border-top: 1px solid var(--color-border);
}

.themed .t-parent-mobile-link {
  display: flex;
  align-items: center;
  padding: var(--space-3) var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-base);
  text-decoration: none;
  gap: var(--space-2-5);
  transition: background-color var(--transition-fast);
}

.themed .t-parent-mobile-link:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-base);
  text-decoration: none;
}

.themed .t-parent-footer {
  background-color: var(--color-surface);
  border-top: 1px solid var(--color-border);
  color: var(--color-text-subtle);
  font-size: var(--text-sm);
}

/* Component: Parent child card header */
.themed .t-parent-child-header {
  background: linear-gradient(135deg, var(--color-primary-400) 0%, var(--color-primary-500) 100%);
}

/* Component: Parent logout button (primary pill on the white navbar) */
.themed .t-parent-logout-btn {
  background-color: var(--color-primary-600);
  color: var(--color-text-inverse);
}
.themed .t-parent-logout-btn:hover {
  background-color: var(--color-primary-700);
}

@media (max-width: 768px) {
  .themed .t-parent-child-header {
    padding: var(--space-3);
  }
}
@media (max-width: 480px) {
  .themed .t-parent-child-header {
    padding: var(--space-2);
  }
}


/* =============================================================================
   4. CARDS & PANELS
   ============================================================================= */

.themed .t-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: box-shadow var(--transition-fast);
}

.themed .t-card-header {
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.themed .t-card-title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  margin: 0;
}

.themed .t-card-subtitle {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: var(--space-0-5);
}

.themed .t-card-body {
  padding: var(--space-6);
}

.themed .t-card-footer {
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--color-border);
  background-color: var(--color-surface-muted);
}

/* Compact card variant */
.themed .t-card-sm .t-card-header {
  padding: var(--space-3) var(--space-4);
}
.themed .t-card-sm .t-card-body {
  padding: var(--space-4);
}

/* Panel — full-width section divider */
.themed .t-panel {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

/* Interactive card — for clickable card links (quick actions, navigation cards) */
.themed .t-card-interactive {
  transition: box-shadow var(--transition-fast),
              transform var(--transition-fast),
              border-color var(--transition-fast);
  cursor: pointer;
}

.themed .t-card-interactive:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
  border-color: var(--color-primary-200);
}

.themed .t-card-interactive:active {
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

/* Info panel — highlighted */
.themed .t-panel-info {
  background-color: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  color: var(--color-info-text);
  font-size: var(--text-base);
}

/* Warning panel — amber action prompt (e.g. cross-class copy) */
.themed .t-panel-warning {
  background-color: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  color: var(--color-warning-text);
  font-size: var(--text-base);
}

@media (max-width: 768px) {
  .themed .t-panel-warning {
    padding: var(--space-3);
  }
}

@media (max-width: 480px) {
  .themed .t-panel-warning {
    padding: var(--space-2);
  }
}


/* =============================================================================
   5. BUTTONS
   ============================================================================= */

.themed .t-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  line-height: 1.5;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background-color var(--transition-fast),
              border-color var(--transition-fast),
              color var(--transition-fast),
              box-shadow var(--transition-fast);
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
}

.themed .t-btn:focus-visible {
  outline: 2px solid var(--color-border-focus);
  outline-offset: 2px;
}

.themed .t-btn:disabled,
.themed .t-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* Primary */
.themed .t-btn-primary {
  background-color: var(--color-primary-600);
  border-color: var(--color-primary-600);
  color: var(--color-text-inverse);
}
.themed .t-btn-primary:hover {
  background-color: var(--color-primary-700);
  border-color: var(--color-primary-700);
}
.themed .t-btn-primary:active {
  background-color: var(--color-primary-800);
}

/* Secondary */
.themed .t-btn-secondary {
  background-color: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-text-base);
}
.themed .t-btn-secondary:hover {
  background-color: var(--color-surface-hover);
  border-color: var(--color-border-strong);
}

/* Danger */
.themed .t-btn-danger {
  background-color: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  color: var(--color-danger-text);
}
.themed .t-btn-danger:hover {
  background-color: #fecaca;
  border-color: var(--color-danger-text);
}

/* Ghost */
.themed .t-btn-ghost {
  background-color: transparent;
  border-color: transparent;
  color: var(--color-text-muted);
}
.themed .t-btn-ghost:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-base);
}

/* Success */
.themed .t-btn-success {
  background-color: var(--color-success-text);
  border-color: var(--color-success-text);
  color: var(--color-text-inverse);
}
.themed .t-btn-success:hover {
  background-color: #166534;
  border-color: #166534;
}

/* Warning — amber action button (matches t-panel-warning) */
.themed .t-btn-warning {
  background-color: var(--color-warning-icon);
  border-color: var(--color-warning-icon);
  color: var(--color-text-inverse);
}
.themed .t-btn-warning:hover {
  background-color: var(--color-warning-text);
  border-color: var(--color-warning-text);
}

/* Size variants */
.themed .t-btn-sm {
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  gap: var(--space-1-5);
}

.themed .t-btn-lg {
  padding: var(--space-3) var(--space-6);
  font-size: var(--text-lg);
}

.themed .t-btn-xl {
  padding: var(--space-4) var(--space-8);
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
}

/* Icon-only button */
.themed .t-btn-icon {
  padding: var(--space-2);
  width: 2.25rem;
  height: 2.25rem;
}
.themed .t-btn-icon.t-btn-sm {
  width: 1.75rem;
  height: 1.75rem;
  padding: var(--space-1);
}


/* =============================================================================
   6. FORM ELEMENTS
   ============================================================================= */

.themed .t-label {
  display: block;
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-base);
  margin-bottom: var(--space-1-5);
}

.themed .t-label-required::after {
  content: ' *';
  color: var(--color-danger-text);
}

.themed .t-input,
.themed .t-select,
.themed .t-textarea {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-base);
  font-family: var(--font-sans);
  color: var(--color-text-base);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  line-height: var(--leading-normal);
  transition: border-color var(--transition-fast),
              box-shadow var(--transition-fast);
  appearance: none;
  -webkit-appearance: none;
}

.themed .t-input::placeholder,
.themed .t-textarea::placeholder {
  color: var(--color-text-subtle);
}

.themed .t-input:hover,
.themed .t-select:hover,
.themed .t-textarea:hover {
  border-color: var(--color-border-focus);
}

.themed .t-input:focus,
.themed .t-select:focus,
.themed .t-textarea:focus {
  outline: none;
  border-color: var(--color-border-focus);
  box-shadow: 0 0 0 3px var(--color-primary-100);
}

.themed .t-input:disabled,
.themed .t-select:disabled,
.themed .t-textarea:disabled {
  background-color: var(--color-surface-muted);
  color: var(--color-text-subtle);
  cursor: not-allowed;
}

/* Select with caret */
.themed .t-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 1.25rem;
  padding-right: 2.5rem;
}

.themed .t-textarea {
  resize: vertical;
  min-height: 5rem;
}

/* Error state */
.themed .t-input-error {
  border-color: var(--color-border-error);
}
.themed .t-input-error:focus {
  box-shadow: 0 0 0 3px var(--color-danger-bg);
  border-color: var(--color-border-error);
}

/* Checkbox / Radio — defensive override
   t-input sets width:100% which stretches checkboxes into full-width bars.
   This higher-specificity rule (0,3,1) beats t-input (0,2,0) without !important. */
.themed input[type="checkbox"].t-input,
.themed input[type="radio"].t-input {
  display: inline-block;
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
  padding: 0;
  accent-color: var(--color-primary-600);
}

/* Dedicated boolean-field hook — prefer t-checkbox over t-input on checkboxes */
.themed .t-checkbox {
  display: inline-block;
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
  cursor: pointer;
  padding: 0;
  accent-color: var(--color-primary-600);
}

/* Form group */
.themed .t-form-group {
  margin-bottom: var(--space-5);
}

/* In inline flex rows (filter bars, header forms), remove the bottom margin so
   items-end can properly align form groups with sibling buttons. */
.themed .flex > .t-form-group,
.themed form.flex .t-form-group {
  margin-bottom: 0;
}

/* Form hint / helper text */
.themed .t-form-hint {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
}
.themed .t-form-error {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-danger-text);
}

/* Checkbox / Radio */
.themed .t-checkbox,
.themed .t-radio {
  width: 1rem;
  height: 1rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface);
  cursor: pointer;
  accent-color: var(--color-primary-600);
}

/* Search input with icon */
.themed .t-search-wrapper {
  position: relative;
}
.themed .t-search-wrapper .t-search-icon {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-subtle);
  width: 1rem;
  height: 1rem;
  pointer-events: none;
}
.themed .t-input-search {
  padding-left: 2.25rem;
}


/* =============================================================================
   7. TABLES
   ============================================================================= */

.themed .t-table-wrapper {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  background-color: var(--color-surface);
}

.themed .t-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-base);
}

.themed .t-table thead {
  background-color: var(--color-surface-muted);
  border-bottom: 2px solid var(--color-primary-200);
}

.themed .t-table th {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.themed .t-table td {
  padding: var(--space-3) var(--space-4);
  color: var(--color-text-base);
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}

.themed .t-table tbody tr {
  transition: background-color var(--transition-fast);
}

.themed .t-table tbody tr:last-child td {
  border-bottom: none;
}

.themed .t-table tbody tr:hover {
  background-color: var(--color-surface-hover);
}

/* Compact table */
.themed .t-table-compact th,
.themed .t-table-compact td {
  padding: var(--space-2) var(--space-3);
}

/* Striped table */
.themed .t-table-striped tbody tr:nth-child(even) {
  background-color: var(--color-surface-muted);
}

/* Numeric column alignment */
.themed .t-table .t-col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum';
}

/* Responsive table wrapper */
.themed .t-table-responsive {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--radius-lg);
}


/* Metric tile — used in global metrics dashboard cards */
.themed .t-metric-tile {
  text-align: center;
  padding: var(--space-4);
  background-color: var(--color-surface-muted);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  transition: border-color var(--transition-fast),
              box-shadow var(--transition-fast);
}

.themed .t-metric-tile:hover {
  border-color: var(--color-primary-200);
  box-shadow: var(--shadow-sm);
}


/* =============================================================================
   8. BADGES & CHIPS
   ============================================================================= */

.themed .t-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  white-space: nowrap;
}

.themed .t-badge-success {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border: 1px solid var(--color-success-border);
}
.themed .t-badge-warning {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
}
.themed .t-badge-danger {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border: 1px solid var(--color-danger-border);
}
.themed .t-badge-info {
  background-color: var(--color-info-bg);
  color: var(--color-info-text);
  border: 1px solid var(--color-info-border);
}
.themed .t-badge-neutral {
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}
.themed .t-badge-primary {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
  border: 1px solid var(--color-primary-200);
}

/* Dot indicator */
.themed .t-badge-dot::before {
  content: '';
  width: 0.375rem;
  height: 0.375rem;
  border-radius: var(--radius-full);
  background-color: currentColor;
  flex-shrink: 0;
}


/* =============================================================================
   9. STATUS INDICATORS — ATTENDANCE
   ============================================================================= */

.themed .t-status-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-1-5) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  border: 1px solid transparent;
  transition: background-color var(--transition-fast),
              box-shadow var(--transition-fast);
  user-select: none;
}

/* Present */
.themed .t-status-present {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border-color: var(--color-success-border);
}
.themed .t-status-present.active,
.themed .t-status-present[data-active="true"] {
  background-color: var(--color-success-text);
  color: var(--color-text-inverse);
  box-shadow: 0 0 0 2px var(--color-success-border);
}

/* Absent */
.themed .t-status-absent {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border-color: var(--color-danger-border);
}
.themed .t-status-absent.active,
.themed .t-status-absent[data-active="true"] {
  background-color: var(--color-danger-text);
  color: var(--color-text-inverse);
  box-shadow: 0 0 0 2px var(--color-danger-border);
}

/* Late */
.themed .t-status-late {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border-color: var(--color-warning-border);
}
.themed .t-status-late.active,
.themed .t-status-late[data-active="true"] {
  background-color: var(--color-warning-text);
  color: var(--color-text-inverse);
  box-shadow: 0 0 0 2px var(--color-warning-border);
}

/* Excused */
.themed .t-status-excused {
  background-color: var(--color-info-bg);
  color: var(--color-info-text);
  border-color: var(--color-info-border);
}
.themed .t-status-excused.active,
.themed .t-status-excused[data-active="true"] {
  background-color: var(--color-info-text);
  color: var(--color-text-inverse);
  box-shadow: 0 0 0 2px var(--color-info-border);
}

/* Early departure */
.themed .t-status-early {
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  border-color: var(--color-border);
}
.themed .t-status-early.active,
.themed .t-status-early[data-active="true"] {
  background-color: var(--color-text-muted);
  color: var(--color-text-inverse);
}

/* Counter tile for attendance summary */
.themed .t-stat-tile {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  text-align: center;
  box-shadow: var(--shadow-sm);
}

.themed .t-stat-tile-value {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  line-height: 1;
  margin-bottom: var(--space-1);
}

.themed .t-stat-tile-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
}


/* =============================================================================
   10. ALERTS & FLASH MESSAGES
   ============================================================================= */

.themed .t-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border-width: 1px;
  border-style: solid;
  border-left-width: 4px;
  font-size: var(--text-base);
}

.themed .t-alert-icon {
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 1px;
}

.themed .t-alert-success {
  background-color: var(--color-success-bg);
  border-color: var(--color-success-border);
  color: var(--color-success-text);
}
.themed .t-alert-warning {
  background-color: var(--color-warning-bg);
  border-color: var(--color-warning-border);
  color: var(--color-warning-text);
}
.themed .t-alert-danger {
  background-color: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  color: var(--color-danger-text);
}
.themed .t-alert-info {
  background-color: var(--color-info-bg);
  border-color: var(--color-info-border);
  color: var(--color-info-text);
}


/* =============================================================================
   11. MODALS
   ============================================================================= */

.themed .t-modal-backdrop {
  background-color: var(--color-overlay);
}

.themed .t-modal-panel {
  background-color: var(--color-surface);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--color-border);
  overflow: hidden;
}

.themed .t-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-modal-title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  margin: 0;
}

.themed .t-modal-body {
  padding: var(--space-6);
}

.themed .t-modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--color-border);
  background-color: var(--color-surface-muted);
}

.themed .t-modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-md);
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.themed .t-modal-close:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-base);
}


/* =============================================================================
   12. DROPDOWNS
   ============================================================================= */

.themed .t-dropdown {
  position: relative;
  display: inline-block;
}

.themed .t-dropdown-menu {
  position: absolute;
  z-index: var(--z-dropdown);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  min-width: 10rem;
  overflow: hidden;
  padding: var(--space-1);
}

.themed .t-dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-base);
  color: var(--color-text-base);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--transition-fast);
  border: none;
  background: none;
  width: 100%;
  text-align: left;
}

.themed .t-dropdown-item:hover {
  background-color: var(--color-surface-hover);
  text-decoration: none;
}

.themed .t-dropdown-item-danger {
  color: var(--color-danger-text);
}
.themed .t-dropdown-item-danger:hover {
  background-color: var(--color-danger-bg);
}

.themed .t-dropdown-divider {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--space-1) 0;
}

/* Hover-selected item state (used with Alpine :class binding) */
.themed .t-dropdown-item-selected {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
  font-weight: var(--font-weight-medium);
}


/* =============================================================================
   12b. COPY PREVIEW PANEL (cross-class lesson log copy hover preview)
   ============================================================================= */

/* Trigger button for the custom parallel-class select */
.themed .t-copy-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-1-5) var(--space-3);
  background-color: var(--color-surface);
  border: 1px solid var(--color-warning-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--color-text-base);
  cursor: pointer;
  min-width: 14rem;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.themed .t-copy-trigger:hover,
.themed .t-copy-trigger:focus {
  border-color: var(--color-warning-icon);
  box-shadow: 0 0 0 3px var(--color-warning-border);
  outline: none;
}

/* Dropdown menu for the copy selector */
.themed .t-copy-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: var(--z-dropdown);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  min-width: 16rem;
  max-height: 16rem;
  overflow-y: auto;
  padding: var(--space-1);
}

/* Individual option row in the copy selector */
.themed .t-copy-option {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--transition-fast);
  border: none;
  background: none;
  width: 100%;
  text-align: left;
}

.themed .t-copy-option:hover,
.themed .t-copy-option-hovered {
  background-color: var(--color-warning-bg);
}

.themed .t-copy-option-name {
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-base);
}

.themed .t-copy-option-date {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* Floating preview card — appears beside the dropdown when hovering an option */
.themed .t-copy-preview {
  position: absolute;
  top: 0;
  left: calc(100% + var(--space-3));
  z-index: var(--z-dropdown);
  width: 28rem;
  max-height: 22rem;
  overflow-y: auto;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  padding: var(--space-5);
}

/* Preview header: class name + date */
.themed .t-copy-preview-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-copy-preview-class {
  font-size: var(--text-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-copy-preview-date {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Section label inside the preview */
.themed .t-copy-preview-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-subtle);
  margin-bottom: var(--space-1);
}

/* Section value inside the preview */
.themed .t-copy-preview-value {
  font-size: var(--text-sm);
  color: var(--color-text-base);
  line-height: 1.6;
  margin-bottom: var(--space-3);
}

.themed .t-copy-preview-value-empty {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  font-style: italic;
  margin-bottom: var(--space-3);
}

/* Lesson type badge inside preview */
.themed .t-copy-preview-type {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0-5) var(--space-2);
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
}

/* Footer hint inside the preview */
.themed .t-copy-preview-footer {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  font-size: var(--text-xs);
  color: var(--color-text-subtle);
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

@media (max-width: 768px) {
  .themed .t-copy-preview {
    position: fixed;
    left: var(--space-4);
    right: var(--space-4);
    top: auto;
    bottom: var(--space-4);
    width: auto;
    max-height: 50vh;
    box-shadow: var(--shadow-xl);
  }

  .themed .t-copy-trigger {
    min-width: 10rem;
  }
}

@media (max-width: 480px) {
  .themed .t-copy-preview {
    left: var(--space-2);
    right: var(--space-2);
    bottom: var(--space-2);
  }

  .themed .t-copy-dropdown {
    min-width: 12rem;
  }
}


/* =============================================================================
   13. STATS & METRICS (Page-level stat cards)
   ============================================================================= */

.themed .t-stats-grid {
  /* Layout (grid columns, gap) handled by Tailwind utilities in templates.
     Theme provides only visual overrides for consistent spacing. */
  gap: var(--space-4);
}

.themed .t-stat-card {
  /* Visual properties only — layout (flex-direction, padding) handled by Tailwind
     in templates, since admin and teacher dashboards use different layouts. */
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-fast),
              transform var(--transition-fast),
              border-color var(--transition-fast);
}

.themed .t-stat-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
  border-color: var(--color-border-strong);
}

/* Clickable stat cards (links) get a more pronounced hover */
.themed a.t-stat-card:hover {
  border-color: var(--color-primary-200);
}

.themed .t-stat-icon {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-lg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.themed .t-stat-icon-primary {
  background-color: var(--color-primary-50);
  color: var(--color-primary-600);
}
.themed .t-stat-icon-success {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
}
.themed .t-stat-icon-warning {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
}
.themed .t-stat-icon-danger {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
}

.themed .t-stat-value {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-base);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.themed .t-stat-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
}

.themed .t-stat-change {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.themed .t-stat-change-up { color: var(--color-success-text); }
.themed .t-stat-change-down { color: var(--color-danger-text); }
.themed .t-stat-change-neutral { color: var(--color-text-muted); }

/* Page header with actions */
.themed .t-page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  flex-wrap: wrap;
}

.themed .t-page-title {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  margin: 0;
  line-height: var(--leading-tight);
}

.themed .t-page-subtitle {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  margin-top: var(--space-1);
}

.themed .t-section-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.themed .t-section-title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  margin: 0;
}

/* Separator */
.themed .t-divider {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--space-6) 0;
}


/* =============================================================================
   14. AI & INSIGHTS COMPONENTS
   ============================================================================= */

/* Insight card (severity-colored) */
.themed .t-insight-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.themed .t-insight-card-critical {
  border-left: 4px solid var(--color-danger-text);
}
.themed .t-insight-card-warning {
  border-left: 4px solid var(--color-warning-icon);
}
.themed .t-insight-card-info {
  border-left: 4px solid var(--color-info-icon);
}

/* AI report content */
.themed .t-ai-section-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--space-4);
  break-inside: avoid;
}

/* Entity anonymization badges */
.themed .t-ai-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0-5) var(--space-1-5);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  font-weight: var(--font-weight-semibold);
}
.themed .t-ai-badge-student {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
  border: 1px solid var(--color-primary-200);
}
.themed .t-ai-badge-teacher {
  background-color: #f0fdfa;
  color: #0d9488;
  border: 1px solid #99f6e4;
}

/* AI report section body */
.themed .t-ai-section-body {
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--color-text-base);
}
.themed .t-ai-section-body ul {
  list-style: disc;
  padding-left: var(--space-5);
  margin: var(--space-2) 0;
}
.themed .t-ai-section-body li {
  margin-bottom: var(--space-1-5);
}
.themed .t-ai-section-body strong {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}
.themed .t-ai-section-body p {
  margin-bottom: var(--space-3);
}


/* =============================================================================
   15. AI WORKSHOP COMPONENTS
   ============================================================================= */

.themed .t-workshop-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base);
  overflow: hidden;
}

.themed .t-workshop-card:hover {
  box-shadow: var(--shadow-md);
}

.themed .t-workshop-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
}

/* Source type badge */
.themed .t-workshop-badge-text {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
}
.themed .t-workshop-badge-file {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
}

/* Difficulty badges */
.themed .t-difficulty-easy {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border: 1px solid var(--color-success-border);
}
.themed .t-difficulty-medium {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
}
.themed .t-difficulty-hard {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border: 1px solid var(--color-danger-border);
}

/* API usage widget */
.themed .t-api-usage-widget {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}

/* Workshop slide — minimal override, keep fullscreen intact */
.themed .t-workshop-slide-container {
  background-color: var(--color-canvas);
}


/* =============================================================================
   16. CHART CONTAINERS (CSS context for JS)
   ============================================================================= */

/* Chart.js reads CSS vars via getComputedStyle — defined on .themed body */
/* See CLAUDE_UI_LOCK.md §Chart Integration for JS usage */

.themed .t-chart-container {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-6);
}

.themed .t-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.themed .t-chart-legend-item {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.themed .t-chart-legend-dot {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

/* Correlation indicator display */
.themed .t-correlation-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1-5) var(--space-3);
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
}
.themed .t-correlation-good {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
}
.themed .t-correlation-ok {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
}
.themed .t-correlation-poor {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
}


/* =============================================================================
   17. INTERVENTION COMPONENTS
   ============================================================================= */

.themed .t-intervention-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4);
}

/* Priority indicators */
.themed .t-priority-urgent {
  border-left: 4px solid var(--color-danger-text);
}
.themed .t-priority-high {
  border-left: 4px solid var(--color-warning-icon);
}
.themed .t-priority-medium {
  border-left: 4px solid var(--color-info-icon);
}
.themed .t-priority-low {
  border-left: 4px solid var(--color-border-strong);
}

/* Timeline item */
.themed .t-timeline-item {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--color-border);
}
.themed .t-timeline-item:last-child {
  border-bottom: none;
}

.themed .t-timeline-dot {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: var(--radius-full);
  background-color: var(--color-primary-600);
  flex-shrink: 0;
  margin-top: 0.375rem;
}

/* Conversation message bubbles — t-msg-* classes are on the outer flex row wrapper,
   not the inner bubble div. Visual styling (bg, color, border-radius) lives in
   Tailwind classes on the inner bubble div. These rules are layout-only. */
.themed .t-msg-bubble {
  max-width: 75%;
}

.themed .t-msg-sent {
  /* layout only — inner bubble div carries bg-blue-600 text-white */
}

.themed .t-msg-received {
  /* layout only — inner bubble div carries bg-white border border-gray-200 */
}

/* Login page container */
.themed .t-auth-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  padding: var(--space-8);
  width: 100%;
  max-width: 24rem;
}

.themed .t-auth-logo {
  text-align: center;
  margin-bottom: var(--space-8);
}


/* =============================================================================
   19. LOGIN PAGE — Split-panel layout (Claude-style)
   ============================================================================= */

/* Page wrapper — exact viewport fill, no page scroll on login */
.themed .t-login-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
  background-color: var(--color-canvas);
}

/* ── Top navbar ── */
.themed .t-login-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--space-8);
  height: var(--header-height);
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}

.themed .t-login-nav-brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.themed .t-login-nav-brand-logo {
  height: 2rem;
  width: auto;
}

.themed .t-login-nav-brand-name {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  letter-spacing: -0.01em;
}

.themed .t-login-nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.themed .t-login-nav-link {
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  text-decoration: none;
  transition: color var(--transition-fast);
}

.themed .t-login-nav-link:hover {
  color: var(--color-text-base);
}

/* ── Two-column body — fills remaining viewport height ── */
.themed .t-login-body {
  display: grid;
  grid-template-columns: 42fr 58fr;   /* slightly wider visual panel */
  flex: 1;
  height: calc(100vh - var(--header-height));
  overflow: hidden;
}

/* ── Left column — form ── */
.themed .t-login-left {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-8) var(--space-10);
  background-color: var(--color-surface);
  overflow-y: auto;
}

.themed .t-login-form-wrap {
  width: 100%;
  max-width: 24rem;
}

.themed .t-login-form-logo {
  height: 3rem;
  width: auto;
  margin-bottom: var(--space-3);
}

.themed .t-login-form-title {
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-base);
  line-height: var(--leading-tight);
  margin-bottom: var(--space-1);
}

.themed .t-login-form-subtitle {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  margin-bottom: var(--space-4);
}

/* Auth card override inside login — fill full wrap width */
.themed .t-login-left .t-auth-card {
  max-width: 100%;
  box-shadow: var(--shadow-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  background-color: var(--color-surface);
}

/* ── Right column — product visual ── */
.themed .t-login-right {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-10) var(--space-10) var(--space-8);
  background: linear-gradient(
    148deg,
    var(--color-primary-50)  0%,
    var(--color-primary-100) 55%,
    var(--color-primary-200) 100%
  );
  position: relative;
  overflow: hidden;
}

/* Subtle dot-grid background decoration */
.themed .t-login-right::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--color-primary-300) 1px, transparent 1px);
  background-size: 28px 28px;
  opacity: 0.25;
  pointer-events: none;
}

.themed .t-login-preview-wrap {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 680px;
  text-align: center;
}

.themed .t-login-preview-img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-xl);
  box-shadow:
    0 0 0 1px var(--color-primary-200),
    var(--shadow-xl);
  display: block;
}

/* Hero slogan block (above preview image) */
.themed .t-login-hero {
  text-align: center;
  margin-bottom: var(--space-8);
}

.themed .t-login-hero-title {
  font-size: 1.75rem;           /* between text-2xl and text-3xl */
  font-weight: var(--font-weight-bold);
  color: var(--color-primary-900);
  letter-spacing: -0.025em;
  line-height: var(--leading-tight);
}

.themed .t-login-hero-slogan {
  margin-top: var(--space-3);
  font-size: var(--text-lg);
  font-style: italic;
  font-weight: var(--font-weight-medium);
  color: var(--color-primary-600);
  line-height: var(--leading-relaxed);
}

/* Blinking cursor shown while the typewriter JS is running */
.themed .t-login-hero-slogan.t-login-slogan-typing::after {
  content: '|';
  color: var(--color-primary-400);
  font-style: normal;
  font-weight: var(--font-weight-normal);
  animation: t-cursor-blink 0.65s step-end infinite;
}

@keyframes t-cursor-blink {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0; }
}

.themed .t-login-preview-caption {
  margin-top: var(--space-5);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary-700);
}

/* Placeholder shown when login-preview.png not yet provided */
.themed .t-login-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-12) var(--space-10);
  border: 2px dashed var(--color-primary-300);
  border-radius: var(--radius-xl);
  background-color: rgba(255, 255, 255, 0.45);
}

.themed .t-login-placeholder-icon {
  width: 7rem;
  height: auto;
  color: var(--color-primary-400);
}

.themed .t-login-placeholder-label {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary-700);
}

.themed .t-login-placeholder-hint {
  font-size: var(--text-sm);
  color: var(--color-primary-500);
  text-align: center;
  line-height: var(--leading-relaxed);
}

/* ── Responsive ── */

/* Tablet ≤1024px: single column, hide visual */
@media (max-width: 1024px) {
  .themed .t-login-body {
    grid-template-columns: 1fr;
  }
  .themed .t-login-right {
    display: none;
  }
}

/* Mobile ≤640px: compact navbar, tighter padding */
@media (max-width: 640px) {
  .themed .t-login-nav {
    padding: 0 var(--space-4);
  }
  .themed .t-login-nav-links {
    display: none;
  }
  .themed .t-login-left {
    padding: var(--space-8) var(--space-4);
    align-items: flex-start;
  }
}


/* =============================================================================
   18. RESPONSIVE — MOBILE FIXES
   ============================================================================= */

/* Tablet breakpoint — 768px */
@media (max-width: 768px) {

  /* Disable hover lift on touch devices — tap doesn't need lift feedback */
  .themed .t-stat-card:hover,
  .themed .t-card-interactive:hover {
    transform: none;
  }

  /* Stats grid: tighten gap on tablet */
  .themed .t-stats-grid {
    gap: var(--space-3);
  }

  /* Page header: stack vertically */
  .themed .t-page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
  }

  /* Cards: reduce padding */
  .themed .t-card-header {
    padding: var(--space-4);
  }
  .themed .t-card-body {
    padding: var(--space-4);
  }
  .themed .t-card-footer {
    padding: var(--space-3) var(--space-4);
  }

  /* Modals: full-width on mobile */
  .themed .t-modal-panel {
    margin: var(--space-4);
    border-radius: var(--radius-lg);
  }
  .themed .t-modal-body {
    padding: var(--space-4);
  }
  .themed .t-modal-header,
  .themed .t-modal-footer {
    padding: var(--space-4);
  }

  /* Tables: force scroll wrapper */
  .themed .t-table-responsive {
    overflow-x: auto;
  }

  /* Metric tiles: tighter padding */
  .themed .t-metric-tile {
    padding: var(--space-3);
  }

  /* Buttons: allow wrapping */
  .themed .t-btn-group {
    flex-wrap: wrap;
  }

  /* Workshop cards: full width */
  .themed .t-workshop-grid {
    grid-template-columns: 1fr;
  }

  /* Conversation bubbles */
  .themed .t-msg-bubble {
    max-width: 90%;
  }
}

/* Mobile breakpoint — 480px */
@media (max-width: 480px) {

  /* Disable hover lift on mobile */
  .themed .t-stat-card:hover,
  .themed .t-card-interactive:hover {
    transform: none;
    box-shadow: var(--shadow-sm);
  }

  /* Stats grid: tighten gap on small mobile */
  .themed .t-stats-grid {
    gap: var(--space-2);
  }

  /* Stat tiles for attendance: 2 columns */
  .themed .t-attendance-counters {
    grid-template-columns: repeat(2, 1fr) !important;
  }

  /* Auth card: no horizontal padding */
  .themed .t-auth-card {
    border-radius: 0;
    border-left: none;
    border-right: none;
    padding: var(--space-6) var(--space-4);
    max-width: 100%;
  }

  /* Status buttons: smaller on narrow screens */
  .themed .t-status-btn {
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-sm);
  }

  /* Metric tiles: compact on small screens */
  .themed .t-metric-tile {
    padding: var(--space-2);
  }
  .themed .t-metric-tile:hover {
    box-shadow: none;
  }

  /* Table: reduce cell padding */
  .themed .t-table th,
  .themed .t-table td {
    padding: var(--space-2);
    font-size: var(--text-sm);
  }

  /* Nav link text: slightly smaller */
  .themed .t-nav-link {
    font-size: var(--text-sm);
    padding: var(--space-1-5) var(--space-3);
  }

  /* Button groups: full-width stack */
  .themed .t-btn-group-mobile-stack {
    flex-direction: column;
    width: 100%;
  }
  .themed .t-btn-group-mobile-stack .t-btn {
    width: 100%;
    justify-content: center;
  }

  /* Page title: smaller */
  .themed .t-page-title {
    font-size: var(--text-2xl);
  }
}

/* Large screen — 1280px */
@media (min-width: 1280px) {

  /* Stats grid: restore standard gap on large screens */
  .themed .t-stats-grid {
    gap: var(--space-4);
  }
}

/* ============================================
   Hero / Gamification Banner
   ============================================ */
.themed .t-hero-banner {
  background: linear-gradient(to right, var(--color-primary-600), var(--color-primary-800));
  color: var(--color-text-inverse);
}

/* ============================================================
   TIMETABLE / EMPLOI DU TEMPS
   ============================================================
   Grid: 20 half-hour rows (08:00–18:00) × 6 day columns.
   Row and column positions are computed by TimetableService
   and applied via pre-generated CSS classes (.t-slot-row-N,
   .t-slot-col-N, .t-slot-span-N) — NO inline styles (R1).

   Grid coordinate system:
     Row 1  = 08:00   Row 11 = 13:00
     Row 2  = 08:30   Row 12 = 13:30
     Row 10 = 12:30   Row 20 = 17:30
     Col 1  = Lundi   Col 6  = Samedi
   ============================================================ */

/* Wrapper */
.themed .t-timetable-wrapper {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

/* CSS Grid definition */
.themed .t-timetable-grid {
  display: grid;
  grid-template-columns: 52px repeat(6, 1fr);
  /* Row 1 = day headers; rows 2–33 = thirty-two 15-min slot rows
     (08:00–16:00, 22 px each → 88 px per hour); trailing `auto`
     row hosts the bottom-boundary "16:00" hour label. 15-min
     granularity lets sessions starting at non-30-min boundaries
     (10:15, 14:15) land at their exact wall-clock position. The
     inline style on the parent `.t-timetable-grid` div repeats
     this layout — keep them in sync. */
  grid-template-rows: 52px repeat(32, 22px) auto;
  min-width: 640px;
  position: relative;
}

/* Time label column cells */
.themed .t-timetable-time-label {
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  padding: 2px 6px 0 0;
  font-size: 0.65rem;
  font-weight: 500;
  color: var(--color-text-muted);
  letter-spacing: 0.02em;
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
}

/* Day header cells */
.themed .t-timetable-day-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 6px 4px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  background: var(--color-surface-alt);
  border-bottom: 2px solid var(--color-border);
  border-right: 1px solid var(--color-border-light);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.themed .t-timetable-day-header.is-today {
  background: var(--color-primary-50);
  color: var(--color-primary-700);
  border-bottom-color: var(--color-primary-400);
}

/* Empty background cells (even rows = alternate shading) */
.themed .t-timetable-cell {
  background: var(--color-surface);
  border-right: 1px solid var(--color-border-light);
  border-bottom: 1px dashed #f0f0f0;
}

.themed .t-timetable-cell:nth-child(even) {
  background: #fafafa;
}

/* Admin mode: clickable empty cells */
.themed .t-timetable-cell.is-clickable {
  cursor: pointer;
  transition: background 0.1s;
  position: relative;
}

.themed .t-timetable-cell.is-clickable:hover {
  background: var(--color-primary-50);
}

/* "+" add hint inside each empty cell (admin mode) */
.themed .t-cell-add-hint {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 300;
  color: #cbd5e1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.1s;
  user-select: none;
}

.themed .t-timetable-cell.is-clickable:hover .t-cell-add-hint {
  opacity: 1;
  color: var(--color-primary-400);
}

/* Today column highlight */
.themed .t-timetable-cell.is-today {
  background: rgba(239, 246, 255, 0.6);
}

/* ── Slot blocks ─────────────────────────────── */

.themed .t-slot-block {
  position: relative;
  margin: 2px;
  border-radius: 6px;
  padding: 4px 6px;
  overflow: hidden;
  font-size: 0.7rem;
  line-height: 1.3;
  cursor: pointer;
  transition: filter 0.15s, box-shadow 0.15s;
  border-left: 3px solid transparent;
  z-index: 1;
}

.themed .t-slot-block:hover {
  filter: brightness(0.95);
  box-shadow: 0 2px 8px rgba(0,0,0,0.12);
}

/* Status variants */
.themed .t-slot-none {
  background: #f8f9fa;
  border-left-color: #cbd5e1;
  color: #64748b;
  border: 1px dashed #cbd5e1;
  border-left: 3px dashed #94a3b8;
}

.themed .t-slot-draft {
  background: #fffbeb;
  border-left-color: #f59e0b;
  color: #92400e;
  border: 1px solid #fde68a;
}

.themed .t-slot-published {
  background: #f0fdf4;
  border-left-color: #22c55e;
  color: #14532d;
  border: 1px solid #bbf7d0;
}

.themed .t-slot-today {
  box-shadow: 0 0 0 2px var(--color-primary-200);
}

/* Slot subject label */
.themed .t-slot-subject {
  font-weight: 700;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Slot class label */
.themed .t-slot-class {
  font-size: 0.65rem;
  opacity: 0.8;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Slot time label */
.themed .t-slot-time {
  font-size: 0.6rem;
  opacity: 0.7;
  margin-top: 2px;
}

/* Admin action buttons inside slot */
.themed .t-slot-actions {
  display: flex;
  gap: 3px;
  margin-top: 3px;
  opacity: 0;
  transition: opacity 0.15s;
}

.themed .t-slot-block:hover .t-slot-actions {
  opacity: 1;
}

.themed .t-slot-action-btn {
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 3px;
  background: rgba(255,255,255,0.7);
  color: #475569;
  cursor: pointer;
  border: none;
  padding: 0;
}

.themed .t-slot-action-btn:hover {
  background: rgba(255,255,255,0.95);
  color: #1e293b;
}

/* ── Legend ─────────────────────────────────── */

.themed .t-timetable-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  align-items: center;
}

.themed .t-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.75rem;
  color: var(--color-text-secondary);
}

.themed .t-legend-dot {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex-shrink: 0;
}

/* ── Pre-generated grid row positions (08:00–15:30) ── */
/* Row 1 = 08:00, Row 2 = 08:30, ..., Row 16 = 15:30   */
/* grid-row offsets +1 because row 1 = day headers     */
/* NOTE: these classes are unused (the template applies grid-row */
/* via inline style). Kept for any future class-based refactor. */
/* Rows 17-20 are out-of-range after the 16:00 cutoff but the    */
/* CSS rules are harmless (they just point past the grid).       */

.themed .t-slot-row-1  { grid-row: 2; }
.themed .t-slot-row-2  { grid-row: 3; }
.themed .t-slot-row-3  { grid-row: 4; }
.themed .t-slot-row-4  { grid-row: 5; }
.themed .t-slot-row-5  { grid-row: 6; }
.themed .t-slot-row-6  { grid-row: 7; }
.themed .t-slot-row-7  { grid-row: 8; }
.themed .t-slot-row-8  { grid-row: 9; }
.themed .t-slot-row-9  { grid-row: 10; }
.themed .t-slot-row-10 { grid-row: 11; }
.themed .t-slot-row-11 { grid-row: 12; }
.themed .t-slot-row-12 { grid-row: 13; }
.themed .t-slot-row-13 { grid-row: 14; }
.themed .t-slot-row-14 { grid-row: 15; }
.themed .t-slot-row-15 { grid-row: 16; }
.themed .t-slot-row-16 { grid-row: 17; }
.themed .t-slot-row-17 { grid-row: 18; }
.themed .t-slot-row-18 { grid-row: 19; }
.themed .t-slot-row-19 { grid-row: 20; }
.themed .t-slot-row-20 { grid-row: 21; }

/* ── Row span classes (duration in 30-min increments) ── */
.themed .t-slot-span-1  { grid-row: span 1; }   /* 30 min  */
.themed .t-slot-span-2  { grid-row: span 2; }   /* 1 hour  */
.themed .t-slot-span-3  { grid-row: span 3; }   /* 1.5 h   */
.themed .t-slot-span-4  { grid-row: span 4; }   /* 2 hours */
.themed .t-slot-span-5  { grid-row: span 5; }   /* 2.5 h   */
.themed .t-slot-span-6  { grid-row: span 6; }   /* 3 hours */
.themed .t-slot-span-8  { grid-row: span 8; }   /* 4 hours */
.themed .t-slot-span-10 { grid-row: span 10; }  /* 5 hours */
.themed .t-slot-span-12 { grid-row: span 12; }  /* 6 hours */

/* ── Day column positions (1=Lundi .. 6=Samedi) ── */
/* +1 offset because column 1 = time labels         */
.themed .t-slot-col-1 { grid-column: 2; }  /* Lundi    */
.themed .t-slot-col-2 { grid-column: 3; }  /* Mardi    */
.themed .t-slot-col-3 { grid-column: 4; }  /* Mercredi */
.themed .t-slot-col-4 { grid-column: 5; }  /* Jeudi    */
.themed .t-slot-col-5 { grid-column: 6; }  /* Vendredi */
.themed .t-slot-col-6 { grid-column: 7; }  /* Samedi   */

/* ── Mobile: collapse grid to vertical day list ── */
@media (max-width: 768px) {
  .themed .t-timetable-grid {
    display: block;
    min-width: unset;
  }

  .themed .t-timetable-wrapper {
    overflow-x: unset;
  }

  .themed .t-slot-block {
    position: static !important;
    margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .themed .t-timetable-day-header,
  .themed .t-timetable-time-label {
    display: none;
  }

  .themed .t-slot-actions {
    opacity: 1;
  }
}

@media (max-width: 480px) {
  .themed .t-timetable-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  .themed .t-timetable-grid {
    display: grid;
    min-width: 500px;
  }
}

/* =====================================================================
 * EXPLAINER — Interactive Concept Explainer
 * ===================================================================== */

.themed .t-explainer-iframe {
  min-height: 400px;
  overflow: hidden;
  transition: height 0.3s ease;
}

@media (max-width: 768px) {
  .themed .t-explainer-iframe {
    border-radius: 4px;
  }
}

@media (max-width: 480px) {
  .themed .t-explainer-iframe {
    border-radius: 2px;
  }
}

/* =====================================================================
 * BILAN — Bulletin de Notes
 * ===================================================================== */

/* Subject grid table */
.themed .t-bilan-grid {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.themed .t-bilan-grid th {
  background-color: var(--color-surface-alt, #f1f5f9);
  color: var(--color-text-secondary, #64748b);
  font-weight: 600;
  text-align: left;
  padding: 0.625rem 0.75rem;
  border-bottom: 2px solid var(--color-border, #e2e8f0);
  white-space: nowrap;
}

.themed .t-bilan-grid td {
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--color-border, #e2e8f0);
  vertical-align: middle;
}

.themed .t-bilan-grid tr:last-child td {
  border-bottom: none;
}

.themed .t-bilan-grid tr:hover td {
  background-color: var(--color-surface-hover, #f8fafc);
}

/* Cell helpers */
.themed .t-bilan-cell-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono, ui-monospace, monospace);
}

.themed .t-bilan-cell-coeff {
  font-weight: 600;
  color: var(--color-primary, #1e40af);
}

/* Status badges */
.themed .t-bilan-status-draft {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.6rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 600;
  background-color: #fef3c7;
  color: #92400e;
}

.themed .t-bilan-status-published {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.6rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 600;
  background-color: #d1fae5;
  color: #065f46;
}

/* Mention badges */
.themed .t-bilan-mention-tb {
  background-color: #dbeafe;
  color: #1e3a8a;
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 700;
}

.themed .t-bilan-mention-b {
  background-color: #e0e7ff;
  color: #3730a3;
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 700;
}

.themed .t-bilan-mention-ab {
  background-color: #ede9fe;
  color: #5b21b6;
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 700;
}

.themed .t-bilan-mention-passable {
  background-color: #d1fae5;
  color: #065f46;
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 700;
}

.themed .t-bilan-mention-insuffisant {
  background-color: #fee2e2;
  color: #991b1b;
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 700;
}

/* Subject row within a bilan detail view */
.themed .t-bilan-subject-row {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr 1fr 2fr;
  align-items: center;
  gap: 0.5rem;
  padding: 0.625rem 0.75rem;
  border-bottom: 1px solid var(--color-border, #e2e8f0);
}

.themed .t-bilan-subject-row:last-child {
  border-bottom: none;
}

/* Config command center: grade-level header rows */
.themed .t-bilan-level-header {
  background-color: var(--color-primary-light, #eff6ff);
  color: var(--color-primary, #1e40af);
  font-weight: 600;
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--color-primary, #1e40af);
  font-size: 0.875rem;
}

@media (max-width: 768px) {
  .themed .t-bilan-subject-row {
    grid-template-columns: 1fr 1fr;
    gap: 0.375rem;
  }

  .themed .t-bilan-grid th,
  .themed .t-bilan-grid td {
    padding: 0.375rem 0.5rem;
  }
}

@media (max-width: 480px) {
  .themed .t-bilan-subject-row {
    grid-template-columns: 1fr;
  }
}

/* =============================================================================
   FEATURE REQUESTS — Suggestions & Améliorations
   Shared by: list.html, submit.html, my_requests.html,
              internal_list.html, internal_detail.html, _upvote_button.html
   ============================================================================= */

/* Muted badge variant (duplicate status, no-priority) */
.themed .t-badge-muted {
  background-color: #f3f4f6;
  color: #9ca3af;
  border: 1px solid #e5e7eb;
}

/* ---- Feature card (school-facing list) ---- */
.themed .t-feature-card {
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.themed .t-feature-card:hover {
  border-color: var(--color-primary-200, #bfdbfe);
  box-shadow: 0 2px 8px 0 rgba(59, 130, 246, 0.08);
}

.themed .t-feature-card-title {
  color: var(--color-text, #111827);
  line-height: 1.4;
}

.themed .t-feature-card-meta {
  color: var(--color-text-muted, #6b7280);
}

.themed .t-feature-card-preview {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---- Upvote button ---- */
.themed .t-upvote-btn {
  transition: background-color 0.15s ease, color 0.15s ease,
              border-color 0.15s ease, transform 0.1s ease;
  user-select: none;
}

.themed .t-upvote-btn:active:not(:disabled) {
  transform: scale(0.94);
}

.themed .t-upvote-btn-active {
  background-color: var(--color-primary, #2563eb);
  color: #ffffff;
  border-color: var(--color-primary, #2563eb);
}

.themed .t-upvote-btn-active:hover {
  background-color: var(--color-primary-dark, #1d4ed8);
  border-color: var(--color-primary-dark, #1d4ed8);
}

.themed .t-upvote-btn-own {
  opacity: 0.6;
  pointer-events: none;
}

/* ---- Filter bar (internal list) ---- */
.themed .t-fr-filter-bar {
  background-color: #ffffff;
  border: 1px solid var(--color-border, #e2e8f0);
  border-radius: var(--radius-lg, 0.5rem);
  padding: 1rem;
}

/* ---- Stat cards (internal list) ---- */
.themed .t-fr-stat-card {
  transition: box-shadow 0.15s ease;
}

.themed .t-fr-stat-card:hover {
  box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.07);
}

/* ---- Internal table ---- */
.themed .t-internal-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.themed .t-internal-table thead tr {
  background-color: #f9fafb;
}

.themed .t-internal-table thead th {
  padding: 0.75rem 1rem;
  text-align: left;
  font-size: 0.75rem;
  font-weight: 600;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.themed .t-internal-table tbody tr {
  border-bottom: 1px solid #f3f4f6;
  transition: background-color 0.1s ease;
}

.themed .t-internal-table tbody tr:hover {
  background-color: #f9fafb;
}

.themed .t-internal-table tbody td {
  padding: 0.875rem 1rem;
  vertical-align: middle;
}

/* ---- Mobile breakpoints ---- */
@media (max-width: 640px) {
  .themed .t-feature-card {
    padding: 1rem;
  }

  .themed .t-fr-filter-bar {
    padding: 0.75rem;
  }

  .themed .t-internal-table thead th,
  .themed .t-internal-table tbody td {
    padding: 0.625rem 0.75rem;
  }
}

/* ==========================================================================
 *  21.  Manual Schedule Editor
 * ========================================================================== */

/* Constraint feedback — cell background colors */
.themed .t-slot-blocked    { background-color: #DB1A1A; border: 2px solid #DB1A1A; cursor: not-allowed; }
.themed .t-slot-warning    { background-color: #FED7AA; border: 2px solid #EA580C; }
.themed .t-slot-neutral    { background-color: #BFDBFE; border: 2px solid #2563EB; }
.themed .t-slot-optimal    { background-color: #A7F3D0; border: 2px solid #059669; }
.themed .t-slot-forced     { background-color: #FECACA; border: 2px dashed #DC2626; cursor: pointer; }

/* Card deck */
.themed .t-editor-card          { cursor: grab; transition: all 0.15s; -webkit-user-select: none; user-select: none; -webkit-user-drag: element; }
.themed .t-editor-card:active   { cursor: grabbing; }
.themed .t-editor-card-selected { box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5); }
.themed .t-editor-card-placed   { opacity: 0.5; cursor: default; -webkit-user-select: none; user-select: none; }
.themed .t-slot-drop-target     { outline: 2px dashed #3B82F6; outline-offset: -2px; }

/* Constraint tooltip */
.themed .t-constraint-tooltip {
  position: absolute;
  z-index: 50;
  min-width: 220px;
  max-width: 300px;
  background: white;
  border: 1px solid #E5E7EB;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  padding: 8px 10px;
  pointer-events: none;
}

/* Active schedule editing warning banner */
.themed .t-active-edit-banner {
  background-color: #FFFBEB;
  border: 1px solid #FDE68A;
  color: #92400E;
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 500;
}

/* Force mode warning banner.
   Phase 9.5: stronger visual emphasis (icon + flex layout + bold).
   Uses danger tokens for fail-safe legibility. */
.themed .t-force-banner {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background-color: var(--color-danger-bg, #FEF2F2);
  border: 1px solid var(--color-danger-border, #FECACA);
  border-left: 4px solid var(--color-danger-text, #991B1B);
  color: var(--color-danger-text, #991B1B);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  line-height: 1.4;
}
.themed .t-force-banner strong {
  font-weight: var(--font-weight-semibold);
}

/* ===================================================================
   TEACHER JOURNAL / SUIVI ÉLÈVES
   =================================================================== */

/* --- Student row in class view --- */
.themed .t-journal-student-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--color-border, #e2e8f0);
  transition: background-color 0.15s;
}
.themed .t-journal-student-row:last-child { border-bottom: none; }
.themed .t-journal-student-row:hover { background-color: var(--color-surface-hover, #f8fafc); }

/* --- Observation chips (inline badges) --- */
.themed .t-journal-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 9999px;
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
  cursor: default;
  transition: opacity 0.15s;
}
.themed .t-journal-chip:hover { opacity: 0.85; }
.themed .t-journal-chip-positive { background-color: #DCFCE7; color: #166534; }
.themed .t-journal-chip-neutral  { background-color: #F3F4F6; color: #374151; }
.themed .t-journal-chip-negative { background-color: #FEE2E2; color: #991B1B; }

/* Chip delete button — always visible on touch, hover-reveal on desktop */
.themed .t-journal-chip-delete {
  margin-left: 2px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s;
  font-size: 0.75rem;
  padding: 2px;
}
.themed .t-journal-chip:hover .t-journal-chip-delete { opacity: 0.7; }
.themed .t-journal-chip-delete:hover { opacity: 1; }
@media (hover: none) and (pointer: coarse) {
  .themed .t-journal-chip-delete { opacity: 0.6; }
}

/* --- Student list card: must NOT clip the quick-add dropdown --- */
/*
 * ⚠️ `.t-card` sets `overflow: hidden` so children respect its rounded corners. The
 * quick-add menu below is `position: absolute` INSIDE that card, so the card clips the
 * menu — the "+" button toggles correctly and nothing appears. Worst on a phone, where
 * the row is short and a 200px menu has nowhere to fall inside the card.
 *
 * Scoped to this one card rather than relaxing `.t-card`, which every other card in the
 * product relies on. No breakpoints: overflow behaviour here is width-independent, so a
 * media block would only restate the same value (R6 governs sizing, not this).
 */
.themed .t-journal-student-list {
  overflow: visible;
}

/* --- Quick-add dropdown --- */
.themed .t-journal-quick-add {
  position: relative;
}
.themed .t-journal-type-menu {
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 30;
  min-width: 200px;
  max-height: 300px;
  overflow-y: auto;
  background: white;
  border: 1px solid var(--color-border, #e2e8f0);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  padding: 4px;
}
.themed .t-journal-type-menu-up {
  top: auto;
  bottom: 100%;
  box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.1);
}
.themed .t-journal-type-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.8125rem;
  transition: background-color 0.1s;
}
.themed .t-journal-type-item:hover { background-color: var(--color-surface-hover, #f1f5f9); }

/* --- Heatmap grid (GitHub-style) --- */
/* Use CSS custom properties for cell size so one change scales everything */
.themed .t-heatmap-wrapper {
  --hm-cell: 12px;
  --hm-gap: 2px;
  --hm-label-w: 28px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Month label row — shares the same column sizing as the cell grid */
.themed .t-heatmap-month-row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc(var(--hm-cell) + var(--hm-gap));
  margin-left: calc(var(--hm-label-w) + 4px);
  margin-bottom: 2px;
  height: 16px;
  align-items: end;
}
.themed .t-heatmap-month-label {
  font-size: 0.65rem;
  color: var(--color-text-muted, #94a3b8);
  white-space: nowrap;
  line-height: 1;
}

/* Body: day labels + cell grid side by side */
.themed .t-heatmap-body {
  display: flex;
  align-items: start;
  gap: 4px;
}

.themed .t-journal-heatmap {
  display: inline-grid;
  grid-template-rows: repeat(7, var(--hm-cell));
  grid-auto-flow: column;
  grid-auto-columns: var(--hm-cell);
  gap: var(--hm-gap);
}
.themed .t-journal-heatmap-cell {
  width: var(--hm-cell);
  height: var(--hm-cell);
  border-radius: 2px;
  transition: transform 0.1s;
}
.themed .t-journal-heatmap-cell:hover {
  transform: scale(1.4);
  outline: 1px solid var(--color-border, #94a3b8);
}

/* Legend cells — fixed size, independent of heatmap cell size */
.themed .t-heatmap-legend-cell {
  width: 10px !important;
  height: 10px !important;
}

/* Legend row */
.themed .t-heatmap-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  margin-top: 12px;
  font-size: 0.7rem;
  color: var(--color-text-muted, #6b7280);
}

/* Heatmap sentiment colors with intensity levels */
.themed .t-heatmap-empty    { background-color: #F1F5F9; }
.themed .t-heatmap-pos-low  { background-color: #BBF7D0; }
.themed .t-heatmap-pos-med  { background-color: #4ADE80; }
.themed .t-heatmap-pos-high { background-color: #16A34A; }
.themed .t-heatmap-neg-low  { background-color: #FECACA; }
.themed .t-heatmap-neg-med  { background-color: #F87171; }
.themed .t-heatmap-neg-high { background-color: #DC2626; }
.themed .t-heatmap-mix-low  { background-color: #E0E7FF; }
.themed .t-heatmap-mix-med  { background-color: #818CF8; }
.themed .t-heatmap-mix-high { background-color: #4F46E5; }

/* Heatmap day labels — rows match cell rows via same --hm-cell var */
.themed .t-journal-heatmap-labels {
  display: grid;
  grid-template-rows: repeat(7, var(--hm-cell));
  gap: var(--hm-gap);
  width: var(--hm-label-w);
  flex-shrink: 0;
  font-size: 0.6rem;
  color: var(--color-text-muted, #94a3b8);
}
.themed .t-journal-heatmap-label-cell {
  height: var(--hm-cell);
  line-height: var(--hm-cell);
  text-align: right;
  padding-right: 2px;
}

/* --- Timeline entry --- */
.themed .t-journal-timeline-entry {
  display: flex;
  gap: 12px;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--color-border-light, #f1f5f9);
}
.themed .t-journal-timeline-entry:last-child { border-bottom: none; }

.themed .t-journal-timeline-dot {
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-top: 4px;
}
.themed .t-journal-timeline-dot-positive { background-color: #22C55E; }
.themed .t-journal-timeline-dot-neutral  { background-color: #6B7280; }
.themed .t-journal-timeline-dot-negative { background-color: #EF4444; }

/* --- Stats card --- */
.themed .t-journal-stat-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1rem;
  background-color: var(--color-surface, #ffffff);
  border: 1px solid var(--color-border, #e2e8f0);
  border-radius: 8px;
  text-align: center;
}
.themed .t-journal-stat-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-text, #1e293b);
}
.themed .t-journal-stat-label {
  font-size: 0.75rem;
  color: var(--color-text-muted, #94a3b8);
  margin-top: 2px;
}

/* --- Settings type list --- */
.themed .t-journal-type-row {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 0.625rem 1rem;
  border-bottom: 1px solid var(--color-border, #e2e8f0);
}
.themed .t-journal-type-row:last-child { border-bottom: none; }

.themed .t-journal-type-swatch {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  flex-shrink: 0;
}

/* --- Shared badge --- */
.themed .t-journal-shared-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.625rem;
  font-weight: 600;
  background-color: #DBEAFE;
  color: #1E40AF;
}

/* --- Class card for landing --- */
.themed .t-journal-class-card {
  display: flex;
  flex-direction: column;
  padding: 1rem 1.25rem;
  background-color: var(--color-surface, #ffffff);
  border: 1px solid var(--color-border, #e2e8f0);
  border-radius: 8px;
  transition: border-color 0.15s, box-shadow 0.15s;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
}
.themed .t-journal-class-card:hover {
  border-color: var(--color-primary, #3b82f6);
  box-shadow: 0 2px 8px rgba(59, 130, 246, 0.12);
}

/* --- Sentiment summary bar --- */
.themed .t-journal-sentiment-bar {
  display: flex;
  height: 6px;
  border-radius: 3px;
  overflow: hidden;
  background-color: #F1F5F9;
}
.themed .t-journal-sentiment-bar-pos { background-color: #22C55E; }
.themed .t-journal-sentiment-bar-neg { background-color: #EF4444; }
.themed .t-journal-sentiment-bar-neu { background-color: #6B7280; }

/* --- Mobile breakpoints --- */
@media (max-width: 768px) {
  /* Student row: stack name/chips above quick-add button */
  .themed .t-journal-student-row {
    grid-template-columns: 1fr auto;
    gap: 6px;
    padding: 0.625rem 0.75rem;
  }

  /* Heatmap: smaller cells via custom properties — one change scales everything */
  .themed .t-heatmap-wrapper {
    --hm-cell: 10px;
    --hm-gap: 2px;
    --hm-label-w: 24px;
  }
  .themed .t-heatmap-month-label {
    font-size: 0.6rem;
  }

  /* Type list: tighter layout */
  .themed .t-journal-type-row {
    grid-template-columns: auto 1fr auto;
    gap: 8px;
    padding: 0.5rem 0.75rem;
  }

  /* Stats: smaller numbers */
  .themed .t-journal-stat-value {
    font-size: 1.25rem;
  }

  /* Dropdown: full-width on mobile */
  .themed .t-journal-type-menu {
    min-width: 180px;
  }

  /* Timeline: bigger touch targets for action buttons */
  .themed .t-journal-timeline-entry button,
  .themed .t-journal-timeline-entry a {
    min-width: 36px;
    min-height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Stat cards: tighter padding */
  .themed .t-journal-stat-card {
    padding: 0.625rem 0.5rem;
  }
}

@media (max-width: 480px) {
  /* Student row: full stack on very small screens */
  .themed .t-journal-student-row {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  /* Type row: hide swatch, simplify */
  .themed .t-journal-type-row {
    grid-template-columns: 1fr auto;
  }
  .themed .t-journal-type-row .t-journal-type-swatch {
    display: none;
  }

  /* Heatmap: smaller cells + tighter gap for narrow phones */
  .themed .t-heatmap-wrapper {
    --hm-cell: 9px;
    --hm-gap: 1.5px;
    --hm-label-w: 22px;
  }
  .themed .t-journal-heatmap-labels {
    font-size: 0.5rem;
  }
  .themed .t-heatmap-month-label {
    font-size: 0.55rem;
  }

  /* Timeline: even bigger touch targets */
  .themed .t-journal-timeline-entry button,
  .themed .t-journal-timeline-entry a {
    min-width: 40px;
    min-height: 40px;
  }

  /* Dropdown: near full-width for easy tapping */
  .themed .t-journal-type-menu {
    min-width: 220px;
    right: -0.5rem;
  }
  .themed .t-journal-type-item {
    padding: 10px 12px;
    font-size: 0.875rem;
  }

  /* Class card: tighter on narrow phones */
  .themed .t-journal-class-card {
    padding: 0.75rem 1rem;
  }
}

/* =============================================================================
   N. SCHEDULING — UNAVAILABILITY GRID (Phase 1)
   Visual click-to-block grid for declaring teacher unavailability
   ============================================================================= */

/* Outer wrapper */
.themed .t-unavail-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.themed .t-unavail-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: flex-end;
  padding: var(--space-5);
  border-bottom: 1px solid var(--color-border);
  background-color: var(--color-surface-muted);
}

/* Legend */
.themed .t-unavail-legend {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.themed .t-unavail-legend-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
}
.themed .t-unavail-legend-swatch-hard {
  background-color: var(--color-danger-bg);
  border-color: var(--color-danger-border);
}
.themed .t-unavail-legend-swatch-soft {
  background-color: var(--color-warning-bg);
  border-color: var(--color-warning-border);
}
.themed .t-unavail-legend-swatch-break {
  background-color: var(--color-surface-muted);
  border-color: var(--color-border);
}

/* Grid table */
.themed .t-unavail-grid {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
}

.themed .t-unavail-grid th,
.themed .t-unavail-grid td {
  padding: var(--space-2);
  border-right: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--text-sm);
  text-align: center;
  vertical-align: middle;
}

.themed .t-unavail-grid th:last-child,
.themed .t-unavail-grid td:last-child {
  border-right: 0;
}

.themed .t-unavail-grid thead th {
  background-color: var(--color-surface-muted);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  position: sticky;
  top: 0;
  z-index: 1;
}

/* Time-label column (left) */
.themed .t-unavail-time-label {
  width: 120px;
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-xs);
  text-align: right;
  padding-right: var(--space-3);
}

/* Cell base */
.themed .t-unavail-cell {
  cursor: pointer;
  user-select: none;
  background-color: var(--color-surface);
  color: var(--color-text-muted);
  transition: background-color var(--transition-fast),
              box-shadow var(--transition-fast);
  height: 44px;
  position: relative;
}

.themed .t-unavail-cell:hover {
  background-color: var(--color-surface-hover);
  box-shadow: inset 0 0 0 1px var(--color-border-strong);
}

.themed .t-unavail-cell:focus-visible {
  outline: 2px solid var(--color-border-focus);
  outline-offset: -2px;
}

/* Cell — empty / available state */
.themed .t-unavail-cell-empty {
  background-color: var(--color-surface);
}

/* Cell — hard block (Obligatoire) */
.themed .t-unavail-cell-hard {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  font-weight: var(--font-weight-semibold);
}
.themed .t-unavail-cell-hard:hover {
  background-color: var(--color-danger-bg);
  box-shadow: inset 0 0 0 2px var(--color-danger-border);
}

/* Cell — soft preference */
.themed .t-unavail-cell-soft {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  font-weight: var(--font-weight-semibold);
}
.themed .t-unavail-cell-soft:hover {
  background-color: var(--color-warning-bg);
  box-shadow: inset 0 0 0 2px var(--color-warning-border);
}

/* Cell — break (greyed out, non-clickable) */
.themed .t-unavail-cell-break {
  background: repeating-linear-gradient(
    45deg,
    var(--color-surface-muted),
    var(--color-surface-muted) 6px,
    var(--color-border) 6px,
    var(--color-border) 7px
  );
  color: var(--color-text-subtle);
  cursor: not-allowed;
}
.themed .t-unavail-cell-break:hover {
  box-shadow: none;
}

/* Cell — period missing on this day */
.themed .t-unavail-cell-missing {
  background-color: var(--color-surface-muted);
  color: var(--color-text-subtle);
  cursor: not-allowed;
}
.themed .t-unavail-cell-missing:hover {
  box-shadow: none;
}

/* Day column when full-day blocked — dim cells */
.themed .t-unavail-day-locked .t-unavail-cell {
  opacity: 0.55;
  pointer-events: none;
}

/* Full-day toggle button (in column header) */
.themed .t-unavail-day-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  margin-top: var(--space-1);
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}
.themed .t-unavail-day-toggle:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-base);
}
.themed .t-unavail-day-toggle-active {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border-color: var(--color-danger-border);
}
.themed .t-unavail-day-toggle-active:hover {
  background-color: var(--color-danger-bg);
}

/* Save bar (sticky bottom) */
.themed .t-unavail-savebar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: flex-end;
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-surface-muted);
  border-top: 1px solid var(--color-border);
}

.themed .t-unavail-savebar-status {
  margin-right: auto;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.themed .t-unavail-savebar-status-dirty {
  color: var(--color-warning-text);
  font-weight: var(--font-weight-medium);
}
.themed .t-unavail-savebar-status-clean {
  color: var(--color-success-text);
  font-weight: var(--font-weight-medium);
}

/* Empty state when no teacher selected or no teachers exist */
.themed .t-unavail-empty {
  padding: var(--space-12) var(--space-5);
  text-align: center;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Mobile: tablets */
@media (max-width: 768px) {
  .themed .t-unavail-toolbar {
    padding: var(--space-3);
  }
  .themed .t-unavail-grid th,
  .themed .t-unavail-grid td {
    padding: var(--space-1);
    font-size: var(--text-xs);
  }
  .themed .t-unavail-time-label {
    width: 80px;
    font-size: 0.65rem;
  }
  .themed .t-unavail-cell {
    height: 36px;
  }
  .themed .t-unavail-day-toggle {
    font-size: 0.65rem;
    padding: 2px 4px;
  }
  .themed .t-unavail-savebar {
    padding: var(--space-3);
  }
}

/* Mobile: phones */
@media (max-width: 480px) {
  .themed .t-unavail-toolbar {
    padding: var(--space-2);
    flex-direction: column;
    align-items: stretch;
  }
  .themed .t-unavail-time-label {
    width: 60px;
    padding: 2px 4px;
  }
  .themed .t-unavail-cell {
    height: 32px;
  }
  .themed .t-unavail-savebar {
    flex-direction: column;
    align-items: stretch;
  }
  .themed .t-unavail-savebar-status {
    margin-right: 0;
    margin-bottom: var(--space-2);
    text-align: center;
  }
}

/* =============================================================================
   N+1. SCHEDULING — CROSS-CONFIG AWARENESS (Phase 8)
   Read-only overlay on the unavailability grid + school-wide conflict report.
   Tokens only — no hard-coded colors.
   ============================================================================= */

/* Legend swatch — small hatched square matching the cell pattern */
.themed .t-unavail-legend-swatch-other-config {
  background: repeating-linear-gradient(
    45deg,
    var(--color-info-bg, #eff6ff),
    var(--color-info-bg, #eff6ff) 4px,
    var(--color-info-border, #bfdbfe) 4px,
    var(--color-info-border, #bfdbfe) 5px
  );
  border-color: var(--color-info-border, #bfdbfe);
}

/* Cell — busy in another config (read-only, hatched diagonal pattern) */
.themed .t-unavail-cell-other-config {
  background: repeating-linear-gradient(
    45deg,
    var(--color-info-bg, #eff6ff),
    var(--color-info-bg, #eff6ff) 6px,
    var(--color-info-border, #bfdbfe) 6px,
    var(--color-info-border, #bfdbfe) 7px
  );
  color: var(--color-info-text, #1e40af);
  cursor: not-allowed;
  font-size: var(--text-xs);
  line-height: 1.2;
  padding: var(--space-1) var(--space-2);
  font-weight: var(--font-weight-semibold);
}
.themed .t-unavail-cell-other-config:hover {
  box-shadow: none;
}
.themed .t-unavail-other-config-label {
  display: block;
  font-weight: var(--font-weight-semibold);
  color: var(--color-info-text, #1e40af);
}
.themed .t-unavail-other-config-class {
  display: block;
  font-size: 0.65rem;
  color: var(--color-text-subtle);
  font-weight: var(--font-weight-normal);
  margin-top: 1px;
}

/* Conflict report — summary card + table */
.themed .t-cross-config-summary {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
}

.themed .t-cross-config-empty {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
}

.themed .t-cross-config-table-wrapper {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.themed .t-cross-config-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}

.themed .t-cross-config-table thead th {
  background-color: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-cross-config-table tbody tr {
  border-bottom: 1px solid var(--color-border);
}
.themed .t-cross-config-table tbody tr:last-child {
  border-bottom: 0;
}
.themed .t-cross-config-row:hover {
  background-color: var(--color-surface-hover);
}

.themed .t-cross-config-side {
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--color-danger-border);
  background-color: var(--color-surface-muted);
  border-radius: var(--radius-md);
}

@media (max-width: 768px) {
  .themed .t-unavail-cell-other-config {
    font-size: 0.6rem;
    padding: 2px;
  }
  .themed .t-unavail-other-config-class {
    display: none;
  }
  .themed .t-cross-config-table thead {
    display: none;
  }
  .themed .t-cross-config-table tbody tr {
    display: block;
    padding: var(--space-3);
    border-bottom: 1px solid var(--color-border);
  }
  .themed .t-cross-config-table tbody td {
    display: block;
    padding: var(--space-1) 0;
  }
}

/* =============================================================================
   N+1. SCHEDULING — UNIFIED WALL-CLOCK SCHEDULE VIEWS (Phase 9)
   Single source of truth: my-schedule + class-schedule + admin teacher view.
   All read from TimetableSlot. Wall-clock CSS Grid layout (reuses
   t-timetable-* base classes from M-Timetable). All colors via tokens.
   Inline grid-row/column allowed per CLAUDE_UI_LOCK R1 (runtime values).
   ============================================================================= */

/* Slot block — colored by subject (border-left + faded bg) */
.themed .t-sched-slot-block {
  position: relative;
  margin: 2px;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-2);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  font-size: var(--text-xs);
  line-height: 1.2;
  border-radius: var(--radius-md);
  transition: box-shadow var(--transition-fast),
              transform var(--transition-fast);
  cursor: default;
}
.themed .t-sched-slot-block:hover {
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

.themed .t-sched-slot-subject {
  font-weight: var(--font-weight-semibold);
  font-size: 0.75rem;
}
.themed .t-sched-slot-secondary {
  color: var(--color-text-muted);
  font-size: 0.7rem;
  margin-top: 1px;
}
.themed .t-sched-slot-time {
  color: var(--color-text-subtle);
  font-size: 0.65rem;
  margin-top: 2px;
}

/* Per-slot config pill — visible only when teacher is cross-level */
.themed .t-sched-slot-config-pill {
  position: absolute;
  top: 4px;
  right: 4px;
  font-size: 0.6rem;
  font-weight: var(--font-weight-semibold);
  padding: 1px 5px;
  border-radius: var(--radius-full);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  white-space: nowrap;
  max-width: 80px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Cross-level banner above the grid */
.themed .t-sched-cross-level-banner {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background-color: var(--color-info-bg, #eff6ff);
  color: var(--color-info-text, #1e40af);
  border: 1px solid var(--color-info-border, #bfdbfe);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
}

/* PDF action group (1 link per active config) */
.themed .t-sched-pdf-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.themed .t-sched-pdf-actions-label {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
}

/* Empty state */
.themed .t-sched-empty-state {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-12) var(--space-5);
  text-align: center;
}

/* Footnote */
.themed .t-sched-footnote {
  margin-top: var(--space-3);
  font-size: var(--text-xs);
  color: var(--color-text-subtle);
  text-align: center;
}

/* Per-Schedule cross-config conflict warning pill (inside slot) —
   appears when both this config AND another config schedule the
   teacher in the same cell. Should never happen post-Phase 8 but
   surfaced for diagnosis if pre-existing data has it. */
.themed .t-sched-cross-conflict-pill {
  position: absolute;
  top: 2px;
  right: 2px;
  font-size: 0.7rem;
  color: var(--color-danger-text);
  background-color: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-radius: var(--radius-full);
  padding: 0 4px;
  font-weight: var(--font-weight-semibold);
  line-height: 1.2;
}

/* Empty cell with cross-config overlay — shown in schedule_detail
   teacher view when the teacher is busy in another config but this
   cell is free in this config. Matches Phase 8 unavailability grid
   overlay style for visual consistency. */
.themed .t-sched-other-config-cell {
  background: repeating-linear-gradient(
    45deg,
    var(--color-info-bg, #eff6ff),
    var(--color-info-bg, #eff6ff) 5px,
    var(--color-info-border, #bfdbfe) 5px,
    var(--color-info-border, #bfdbfe) 6px
  );
  color: var(--color-info-text, #1e40af);
  border-radius: var(--radius-md);
  padding: var(--space-1) var(--space-2);
  font-size: 0.7rem;
  line-height: 1.2;
  height: 48px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.themed .t-sched-other-config-label {
  font-weight: var(--font-weight-semibold);
  color: var(--color-info-text, #1e40af);
  font-size: 0.7rem;
}
.themed .t-sched-other-config-class {
  font-size: 0.6rem;
  color: var(--color-text-subtle);
  margin-top: 1px;
}

@media (max-width: 768px) {
  .themed .t-sched-slot-block {
    padding: 4px;
  }
  .themed .t-sched-slot-time {
    display: none;
  }
  .themed .t-sched-slot-config-pill {
    max-width: 50px;
    font-size: 0.55rem;
  }
  .themed .t-sched-pdf-actions {
    width: 100%;
  }
  .themed .t-sched-other-config-cell {
    height: 36px;
    padding: 2px 4px;
  }
  .themed .t-sched-other-config-class {
    display: none;
  }
}

@media (max-width: 480px) {
  .themed .t-sched-slot-secondary {
    font-size: 0.6rem;
  }
  .themed .t-sched-slot-config-pill {
    display: none;
  }
}

/* Phase 9.2 — Activation pending banner (admin schedule_detail) */
.themed .t-sched-pending-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-warning-bg, #fffbeb);
  border: 1px solid var(--color-warning-border, #fde68a);
  border-left-width: 4px;
  border-radius: var(--radius-xl);
}

.themed .t-sched-pending-banner-icon {
  flex-shrink: 0;
  color: var(--color-warning-text, #92400e);
  margin-top: 2px;
}

.themed .t-sched-pending-banner-body {
  flex: 1;
  min-width: 0;
}

.themed .t-sched-pending-banner-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-warning-text, #92400e);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-sched-pending-banner-text {
  font-size: var(--text-sm);
  color: var(--color-text-base);
  margin: 0;
  line-height: 1.5;
}

.themed .t-sched-pending-banner-text strong {
  font-weight: var(--font-weight-semibold);
}

.themed .t-sched-pending-banner-cta {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background-color: var(--color-success-text, #047857);
  color: #fff;
  border: 0;
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  transition: background-color var(--transition-fast),
              transform var(--transition-fast);
  white-space: nowrap;
}

.themed .t-sched-pending-banner-cta:hover {
  background-color: var(--color-success-text-hover, #065f46);
  transform: translateY(-1px);
}

@media (max-width: 768px) {
  .themed .t-sched-pending-banner {
    flex-direction: column;
    align-items: stretch;
  }
  .themed .t-sched-pending-banner-cta {
    width: 100%;
    justify-content: center;
  }
}

/* =============================================================================
   Phase 9.5 — Schedule quality surfaces
   Closes audit PARTIALs 7.2 + 7.6 + 9.5: header stats strip,
   per-row comparison badges in the dashboard schedule list, and the
   unplaced-cours warning banner. All colors via tokens, mobile-safe.
   ============================================================================= */

/* Header stats strip (schedule_detail.html top) */
.themed .t-sched-header-stats {
  /* Layout-only — children carry their own colors */
  font-variant-numeric: tabular-nums;
}

.themed .t-sched-stat {
  display: inline-flex;
  align-items: center;
  font-weight: var(--font-weight-medium);
}

.themed .t-sched-stat-error {
  color: var(--color-danger-text);
  font-weight: var(--font-weight-semibold);
}

.themed .t-sched-stat-warning {
  color: var(--color-warning-text);
  font-weight: var(--font-weight-semibold);
}

.themed .t-sched-stat-soft {
  color: var(--color-warning-text);
}

.themed .t-sched-stat-ok {
  color: var(--color-success-text);
  font-weight: var(--font-weight-semibold);
}

/* Schedule list rows (dashboard.html) */
.themed .t-sched-list-row {
  /* hover taken from existing dashboard.html rules */
}

.themed .t-sched-list-badge {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border-radius: var(--radius-full);
  font-size: 0.65rem;
  font-weight: var(--font-weight-semibold);
  margin-left: var(--space-1);
}

.themed .t-sched-list-badge-ok {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
}

.themed .t-sched-list-badge-incomplete {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
}

/* Comparison badge: ↓ better / ↑ worse / = same */
.themed .t-sched-list-cmp {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 0.7rem;
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

.themed .t-sched-list-cmp-better {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
}

.themed .t-sched-list-cmp-worse {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
}

.themed .t-sched-list-cmp-same {
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
}

/* Unplaced-cours warning banner (schedule_detail.html top) */
.themed .t-sched-unplaced-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-warning-bg, #fffbeb);
  border: 1px solid var(--color-warning-border, #fde68a);
  border-left-width: 4px;
  border-radius: var(--radius-xl);
}

.themed .t-sched-unplaced-banner-icon {
  flex-shrink: 0;
  color: var(--color-warning-text, #92400e);
  margin-top: 2px;
}

.themed .t-sched-unplaced-banner-body {
  flex: 1;
  min-width: 0;
}

.themed .t-sched-unplaced-banner-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-warning-text, #92400e);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-sched-unplaced-banner-text {
  font-size: var(--text-sm);
  color: var(--color-text-base);
  margin: 0;
  line-height: 1.5;
}

@media (max-width: 768px) {
  .themed .t-sched-list-row {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-2);
  }
  .themed .t-sched-list-cmp {
    align-self: flex-start;
  }
  .themed .t-sched-unplaced-banner {
    flex-direction: column;
  }
}

/* =============================================================================
   N+1. SCHEDULING — BELL PRESETS + CLONE DAY (Phase 2)
   Preset selector card, clone-day controls, per-day slot count badges
   ============================================================================= */

/* Preset selector card (top of config_periods page) */
.themed .t-bell-preset-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-5);
  margin-bottom: var(--space-6);
}

.themed .t-bell-preset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-3);
}

.themed .t-bell-preset-option {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--transition-fast),
              box-shadow var(--transition-fast),
              background-color var(--transition-fast);
  width: 100%;
}
.themed .t-bell-preset-option:hover {
  border-color: var(--color-primary-300);
  background-color: var(--color-surface-hover);
  box-shadow: var(--shadow-sm);
}
.themed .t-bell-preset-option:focus-visible {
  outline: 2px solid var(--color-border-focus);
  outline-offset: 2px;
}
.themed .t-bell-preset-option:disabled,
.themed .t-bell-preset-option[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
  background-color: var(--color-surface-muted);
}

.themed .t-bell-preset-name {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-bell-preset-description {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  line-height: 1.4;
}

.themed .t-bell-preset-meta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  align-self: flex-start;
  padding: 2px 8px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  border-radius: var(--radius-full);
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
}

/* Day-level slot count badge (next to day name in header) */
.themed .t-bell-day-count {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  border-radius: var(--radius-full);
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}
.themed .t-bell-day-count-active {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
  border-color: var(--color-primary-200, var(--color-border));
}

/* Week total tile (top right of preset card) */
.themed .t-bell-week-total {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-3);
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border: 1px solid var(--color-success-border);
  border-radius: var(--radius-md);
  font-weight: var(--font-weight-semibold);
}
.themed .t-bell-week-total-value {
  font-size: var(--text-lg);
  line-height: 1;
}
.themed .t-bell-week-total-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-normal);
}

/* Clone-day dropdown (Alpine-driven) */
.themed .t-clone-day-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 4px 10px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}
.themed .t-clone-day-trigger:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-base);
}
.themed .t-clone-day-trigger:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.themed .t-clone-day-popover {
  position: absolute;
  z-index: 30;
  margin-top: var(--space-1);
  min-width: 240px;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-3);
}

.themed .t-clone-day-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px 6px;
  border-radius: var(--radius-sm);
}
.themed .t-clone-day-row:hover {
  background-color: var(--color-surface-hover);
}
.themed .t-clone-day-row label {
  cursor: pointer;
  flex-grow: 1;
  font-size: var(--text-sm);
}

.themed .t-clone-day-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border);
}

/* Inline notice banner shown when destructive ops are blocked */
.themed .t-bell-blocked-notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
}

/* Mobile: tablets */
@media (max-width: 768px) {
  .themed .t-bell-preset-card {
    padding: var(--space-3);
  }
  .themed .t-bell-preset-grid {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
  .themed .t-bell-preset-option {
    padding: var(--space-3);
  }
  .themed .t-clone-day-popover {
    min-width: 200px;
  }
}

/* Mobile: phones */
@media (max-width: 480px) {
  .themed .t-bell-week-total {
    padding: var(--space-1) var(--space-2);
  }
  .themed .t-bell-week-total-value {
    font-size: var(--text-base);
  }
  .themed .t-clone-day-trigger {
    padding: 3px 8px;
  }
  .themed .t-clone-day-popover {
    min-width: 180px;
    right: 0;
    left: auto;
  }
}

/* =============================================================================
   N+2. SCHEDULING — DASHBOARD STEP STATUS + READINESS PANEL (Phase 3)
   Per-step indicators on the 5-step config checklist + readiness summary
   ============================================================================= */

/* Step row container (replaces hand-rolled Tailwind in dashboard.html) */
.themed .t-step-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-5);
  transition: background-color var(--transition-fast);
}
.themed .t-step-row:hover {
  background-color: var(--color-surface-hover);
}

.themed .t-step-row-content {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-width: 0;
}

.themed .t-step-text {
  min-width: 0;
}

.themed .t-step-label {
  font-weight: var(--font-weight-medium);
  color: var(--color-text-base);
}

.themed .t-step-description {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: 2px;
}

.themed .t-step-detail {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
  padding: 2px 8px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  border-radius: var(--radius-full);
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

/* Step status indicator (left circle) */
.themed .t-step-indicator {
  width: 32px;
  height: 32px;
  border-radius: 9999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  flex-shrink: 0;
}

.themed .t-step-indicator-done {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border: 1px solid var(--color-success-border);
}
.themed .t-step-indicator-incomplete {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
}
.themed .t-step-indicator-optional {
  background-color: var(--color-info-bg);
  color: var(--color-info-text);
  border: 1px solid var(--color-info-border);
}

/* Detail badge variants */
.themed .t-step-detail-done {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border-color: var(--color-success-border);
}
.themed .t-step-detail-incomplete {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border-color: var(--color-warning-border);
}
.themed .t-step-detail-optional {
  background-color: var(--color-info-bg);
  color: var(--color-info-text);
  border-color: var(--color-info-border);
}

/* Chevron at right of each row */
.themed .t-step-chevron {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: var(--color-text-subtle);
}

/* ----- Readiness panel (above the Generate button) ----- */
.themed .t-readiness {
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  border: 1px solid;
  margin-bottom: var(--space-4);
}

.themed .t-readiness-ready {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border-color: var(--color-success-border);
}
.themed .t-readiness-warning {
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border-color: var(--color-warning-border);
}
.themed .t-readiness-error {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border-color: var(--color-danger-border);
}

.themed .t-readiness-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
}

.themed .t-readiness-list {
  margin-top: var(--space-3);
  padding-left: var(--space-5);
  font-size: var(--text-sm);
}

.themed .t-readiness-list li {
  margin-top: var(--space-1);
  list-style: disc;
}

.themed .t-readiness-fix-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: var(--space-2);
  padding: 2px 8px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  color: var(--color-text-base);
  border: 1px solid var(--color-border);
  transition: background-color var(--transition-fast);
}
.themed .t-readiness-fix-link:hover {
  background-color: var(--color-surface-hover);
  text-decoration: none;
}

/* Mobile breakpoints */
@media (max-width: 768px) {
  .themed .t-step-row {
    padding: var(--space-3);
  }
  .themed .t-step-indicator {
    width: 28px;
    height: 28px;
    font-size: var(--text-xs);
  }
  .themed .t-readiness {
    padding: var(--space-3);
  }
  .themed .t-readiness-list {
    padding-left: var(--space-4);
  }
}

@media (max-width: 480px) {
  .themed .t-step-row {
    padding: var(--space-2) var(--space-3);
  }
  .themed .t-step-row-content {
    gap: var(--space-2);
  }
  .themed .t-step-indicator {
    width: 24px;
    height: 24px;
  }
  .themed .t-step-detail {
    font-size: 0.65rem;
    padding: 2px 6px;
  }
  .themed .t-readiness-fix-link {
    display: block;
    margin-left: 0;
    margin-top: 4px;
  }
}

/* =============================================================================
   N+2.5 SCHEDULING — FIRST-RUN BANNER + STEP QUICK ACTIONS (Phase 9.3)
   Closes audit PARTIAL 1.1 + 1.2: tells first-time planners exactly
   where to click + offers one-click sync from inside the step row.
   ============================================================================= */

/* Welcome banner shown only when this config has zero requirements
   AND the school has never generated a schedule for the year. */
.themed .t-first-run-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-info-bg, #eff6ff);
  border: 1px solid var(--color-info-border, #bfdbfe);
  border-left-width: 4px;
  border-radius: var(--radius-xl);
}

.themed .t-first-run-banner-icon {
  flex-shrink: 0;
  color: var(--color-info-text, #1e40af);
  margin-top: 2px;
}

.themed .t-first-run-banner-body {
  flex: 1;
  min-width: 0;
}

.themed .t-first-run-banner-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-info-text, #1e40af);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-first-run-banner-text {
  font-size: var(--text-sm);
  color: var(--color-text-base);
  margin: 0;
  line-height: 1.5;
}

.themed .t-first-run-banner-text strong {
  font-weight: var(--font-weight-semibold);
}

/* Step row split — link area (flex-1) + sibling action form */
.themed .t-step-row-link {
  text-decoration: none;
  color: inherit;
}

.themed .t-step-row-action {
  flex-shrink: 0;
  border-left: 1px solid var(--color-border);
}

.themed .t-step-quick-action-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-3);
  background-color: var(--color-primary, #2563eb);
  color: #fff;
  border: 0;
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--transition-fast);
}

.themed .t-step-quick-action-btn:hover {
  background-color: var(--color-primary-hover, #1d4ed8);
}

@media (max-width: 768px) {
  .themed .t-first-run-banner {
    padding: var(--space-3);
  }
  .themed .t-step-row {
    flex-direction: column;
    align-items: stretch;
  }
  .themed .t-step-row-action {
    border-left: 0;
    border-top: 1px solid var(--color-border);
    padding: var(--space-2) var(--space-5) var(--space-3);
    justify-content: flex-end;
  }
  .themed .t-step-quick-action-btn {
    width: 100%;
    justify-content: center;
  }
}

/* =============================================================================
   N+3. SCHEDULING — HOURS CONFIG PROGRESS BAR (Phase 4)
   Visual balance indicator on the per-grade-level hours configuration card
   ============================================================================= */

/* Outer flex container holding the bar + the count label */
.themed .t-hours-progress {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 200px;
}

/* The track (background) */
.themed .t-hours-progress-track {
  position: relative;
  flex: 1 1 auto;
  height: 8px;
  background-color: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  overflow: hidden;
  min-width: 100px;
}

/* The fill — width is set via inline style="width: {percent}%"
   (only inline style usage; matches the existing pattern in
   schedule_detail.html slot cells for runtime numeric values).
   Color comes from the variant class below. */
.themed .t-hours-progress-fill {
  position: absolute;
  inset-inline-start: 0;
  top: 0;
  bottom: 0;
  border-radius: var(--radius-full);
  transition: width 200ms ease, background-color 200ms ease;
}

.themed .t-hours-progress-fill-balanced {
  background-color: var(--color-success-text);
}
.themed .t-hours-progress-fill-partial {
  background-color: var(--color-warning-text);
}
.themed .t-hours-progress-fill-overflow {
  background-color: var(--color-danger-text);
}

/* Count label ("12 / 35" or "Équilibré · 35") */
.themed .t-hours-progress-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.themed .t-hours-progress-label-balanced {
  color: var(--color-success-text);
}
.themed .t-hours-progress-label-partial {
  color: var(--color-warning-text);
}
.themed .t-hours-progress-label-overflow {
  color: var(--color-danger-text);
}

/* Mobile: tablets */
@media (max-width: 768px) {
  .themed .t-hours-progress {
    min-width: 140px;
  }
  .themed .t-hours-progress-track {
    min-width: 60px;
    height: 6px;
  }
}

/* Mobile: phones */
@media (max-width: 480px) {
  .themed .t-hours-progress {
    min-width: 0;
    width: 100%;
  }
  .themed .t-hours-progress-label {
    font-size: 0.65rem;
  }
}

/* =============================================================================
   N+4. SCHEDULING — SHARE PAGE (Phase 5)
   Per-teacher rows with PDF + WhatsApp actions on the schedule share page
   ============================================================================= */

/* Outer card */
.themed .t-share-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  margin-bottom: var(--space-6);
}

/* Top action bar — master PDF + batch ZIP buttons */
.themed .t-share-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
}

/* Stats summary (e.g. "12 enseignants — 10 avec téléphone") */
.themed .t-share-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  margin-right: auto;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.themed .t-share-stat-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 10px;
  border-radius: var(--radius-full);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-xs);
}

/* Teacher list */
.themed .t-share-list {
  display: flex;
  flex-direction: column;
  divide-y: 1px solid var(--color-border);
}

.themed .t-share-row {
  display: grid;
  grid-template-columns: 40px 1fr auto;
  gap: var(--space-4);
  align-items: center;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
  transition: background-color var(--transition-fast);
}
.themed .t-share-row:last-child {
  border-bottom: 0;
}
.themed .t-share-row:hover {
  background-color: var(--color-surface-hover);
}

.themed .t-share-row-avatar {
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
  background-color: var(--color-primary-100, var(--color-surface-muted));
  color: var(--color-primary-700, var(--color-text-base));
  flex-shrink: 0;
}

.themed .t-share-row-info {
  min-width: 0;
}

.themed .t-share-row-name {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  margin-bottom: 2px;
}

.themed .t-share-row-meta {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.themed .t-share-row-actions {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* WhatsApp button — green (intentionally close to the WhatsApp brand
   color but using the success token so it stays themeable). */
.themed .t-share-whatsapp-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-2) var(--space-3);
  background-color: var(--color-success-text);
  color: var(--color-text-inverse, #fff);
  border: 1px solid var(--color-success-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  transition: filter var(--transition-fast);
}
.themed .t-share-whatsapp-btn:hover {
  filter: brightness(0.92);
  text-decoration: none;
}
.themed .t-share-whatsapp-btn-disabled {
  background-color: var(--color-surface-muted);
  color: var(--color-text-subtle);
  border-color: var(--color-border);
  cursor: not-allowed;
}
.themed .t-share-whatsapp-btn-disabled:hover {
  filter: none;
}

/* No-phone warning badge inside the row meta */
.themed .t-share-no-phone {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  background-color: var(--color-warning-bg);
  color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
}

/* Empty state when no teachers have slots */
.themed .t-share-empty {
  padding: var(--space-12);
  text-align: center;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Mobile: tablets */
@media (max-width: 768px) {
  .themed .t-share-actions {
    padding: var(--space-3);
    flex-direction: column;
    align-items: stretch;
  }
  .themed .t-share-stats {
    margin-right: 0;
    margin-bottom: var(--space-2);
  }
  .themed .t-share-row {
    padding: var(--space-3);
    gap: var(--space-3);
  }
}

/* Mobile: phones */
@media (max-width: 480px) {
  .themed .t-share-row {
    grid-template-columns: 1fr;
  }
  .themed .t-share-row-avatar {
    width: 32px;
    height: 32px;
    font-size: var(--text-xs);
  }
  .themed .t-share-row-actions {
    width: 100%;
    flex-direction: column;
  }
  .themed .t-share-whatsapp-btn {
    justify-content: center;
  }
}

/* =============================================================================
   N+3. SCHEDULING — ACTIVATION HISTORY (Phase 9.6)
   Closes audit FAILs 12.3 + 12.5: per-config activation history page +
   bookmarkable date lookup. All colors via tokens. Mobile breakpoint at 768px
   reflows the table to a card-stack layout for thumb-friendly scrolling.
   ============================================================================= */

/* Date lookup card — sits above the history table */
.themed .t-history-lookup-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  box-shadow: var(--shadow-sm);
}

.themed .t-history-lookup-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.themed .t-history-lookup-label {
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-base);
}

.themed .t-history-lookup-input {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  color: var(--color-text-base);
  background-color: var(--color-surface);
  font-variant-numeric: tabular-nums;
}

.themed .t-history-lookup-input:focus {
  outline: none;
  border-color: var(--color-border-focus);
  box-shadow: 0 0 0 3px rgb(37 99 235 / 0.15);
}

.themed .t-history-lookup-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background-color: var(--color-info-text);
  color: var(--color-text-inverse);
  border: none;
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  transition: background-color 120ms ease;
}

.themed .t-history-lookup-btn:hover {
  background-color: var(--color-text-link-hover);
}

.themed .t-history-lookup-clear {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  text-decoration: underline;
  margin-left: var(--space-2);
}

.themed .t-history-lookup-clear:hover {
  color: var(--color-text-base);
}

/* Lookup result message — three semantic variants */
.themed .t-history-lookup-result {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  line-height: 1.5;
}

.themed .t-history-lookup-result-found {
  background-color: var(--color-info-bg);
  color: var(--color-info-text);
  border: 1px solid var(--color-info-border);
}

.themed .t-history-lookup-result-empty {
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

.themed .t-history-lookup-result-error {
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border: 1px solid var(--color-danger-border);
}

.themed .t-history-lookup-link {
  color: inherit;
  font-weight: var(--font-weight-semibold);
  text-decoration: underline;
}

.themed .t-history-lookup-link:hover {
  text-decoration: none;
}

/* Empty state when no activations exist */
.themed .t-history-empty {
  text-align: center;
  padding: var(--space-10) var(--space-5);
  background-color: var(--color-surface);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-lg);
}

/* History table */
.themed .t-history-table-wrapper {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.themed .t-history-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-base);
}

.themed .t-history-table thead th {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--color-border);
}

.themed .t-history-table tbody tr {
  border-top: 1px solid var(--color-border);
  transition: background-color 80ms ease;
}

.themed .t-history-table tbody tr:first-child {
  border-top: none;
}

.themed .t-history-row:hover {
  background-color: var(--color-surface-hover);
}

.themed .t-history-row td {
  padding: var(--space-3) var(--space-4);
  vertical-align: top;
  color: var(--color-text-base);
}

/* Highlighted row — when the date lookup matches an activation window */
.themed .t-history-row-highlight {
  background-color: var(--color-warning-bg);
}

.themed .t-history-row-highlight:hover {
  background-color: var(--color-warning-bg);
}

.themed .t-history-row-highlight td {
  border-left: 3px solid var(--color-warning-icon);
}

.themed .t-history-row-highlight td:first-child {
  font-weight: var(--font-weight-semibold);
}

/* Period column — "du DD/MM/YYYY HH:MM" / "au DD/MM/YYYY HH:MM" */
.themed .t-history-period {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.themed .t-history-from {
  color: var(--color-text-base);
  font-weight: var(--font-weight-medium);
}

.themed .t-history-to {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin-top: var(--space-0-5);
}

.themed .t-history-active-now {
  color: var(--color-success-text);
  font-weight: var(--font-weight-semibold);
}

/* Schedule link in the planning column */
.themed .t-history-schedule-link {
  color: var(--color-text-link);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
}

.themed .t-history-schedule-link:hover {
  color: var(--color-text-link-hover);
  text-decoration: underline;
}

.themed .t-history-note {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-style: italic;
}

.themed .t-history-actor {
  color: var(--color-text-base);
}

/* Status badges — Actif vs Archivé */
.themed .t-history-status-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

.themed .t-history-status-active {
  background-color: var(--color-success-bg);
  color: var(--color-success-text);
  border: 1px solid var(--color-success-border);
}

.themed .t-history-status-archived {
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

/* Mobile reflow — stack table rows as cards for narrow screens */
@media (max-width: 768px) {
  .themed .t-history-lookup-form {
    flex-direction: column;
    align-items: stretch;
  }
  .themed .t-history-lookup-input,
  .themed .t-history-lookup-btn {
    width: 100%;
    justify-content: center;
  }
  .themed .t-history-table thead {
    display: none;
  }
  .themed .t-history-table tbody tr {
    display: block;
    padding: var(--space-3);
    border-top: 1px solid var(--color-border);
  }
  .themed .t-history-row td {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-1-5) 0;
    border: none;
  }
  .themed .t-history-row td::before {
    content: attr(data-label);
    color: var(--color-text-muted);
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-sm);
  }
  .themed .t-history-row-highlight td {
    border-left: none;
  }
  .themed .t-history-row-highlight {
    border-left: 3px solid var(--color-warning-icon);
    padding-left: calc(var(--space-3) - 3px);
  }
}

/* =============================================================================
   N+4. SCHEDULING — ACTIVATION ERROR BANNER (Phase 9.7)
   Closes audit FAIL 14.5: surfaces background activation failures
   visibly on schedule_detail.html when the Celery task wrote an
   error to `Schedule.activation_error`. Danger palette (4px left
   border) so it dominates the page and the planner cannot miss it.
   ============================================================================= */

.themed .t-sched-activation-error-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-left-width: 4px;
  border-radius: var(--radius-xl);
}

.themed .t-sched-activation-error-banner-icon {
  flex-shrink: 0;
  color: var(--color-danger-icon);
  margin-top: 2px;
}

.themed .t-sched-activation-error-banner-body {
  flex: 1;
  min-width: 0;
}

.themed .t-sched-activation-error-banner-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-danger-text);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-sched-activation-error-banner-text {
  font-size: var(--text-sm);
  color: var(--color-danger-text);
  margin: 0 0 var(--space-2) 0;
  line-height: 1.5;
  /* Activation errors are often raw exception messages — preserve
     newlines for readability and break long lines instead of
     overflowing the banner. */
  white-space: pre-wrap;
  word-break: break-word;
}

.themed .t-sched-activation-error-banner-hint {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: 0;
  line-height: 1.5;
}

@media (max-width: 768px) {
  .themed .t-sched-activation-error-banner {
    flex-direction: column;
  }
  .themed .t-sched-activation-error-banner-icon {
    margin-top: 0;
  }
}


/* =============================================================================
   SCHEDULING — SOLVER DIAGNOSIS BANNER (Phase 11 post-pilot UX)
   Closes the pilot UX gap: an OR-Tools INFEASIBLE result historically
   produced a `Schedule(status='draft', slots=0)` with no visible reason
   why. The solver's diagnosis JSON now renders as a prominent danger
   banner with per-conflict French message + actionable CTA (e.g.
   "Créer une session commune" for teacher_overload). Scoped to `.themed`,
   token-only colors, mobile reflow at ≤768px.
   ============================================================================= */

.themed .t-sched-diagnosis-banner {
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-left-width: 4px;
  border-radius: var(--radius-xl);
}

.themed .t-sched-diagnosis-banner-header {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}

.themed .t-sched-diagnosis-banner-icon {
  flex-shrink: 0;
  color: var(--color-danger-icon);
  margin-top: 2px;
}

.themed .t-sched-diagnosis-banner-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-danger-text);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-sched-diagnosis-banner-subtitle {
  font-size: var(--text-sm);
  color: var(--color-danger-text);
  margin: 0;
  line-height: 1.5;
}

.themed .t-sched-diagnosis-banner-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-3) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.themed .t-sched-diagnosis-banner-item {
  background-color: var(--color-surface);
  border: 1px solid var(--color-danger-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.themed .t-sched-diagnosis-banner-item-message {
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: 1.5;
  /* Diagnosis messages can be long and contain numbers/colons —
     wrap normally but break very long words to avoid overflow. */
  word-break: break-word;
}

.themed .t-sched-diagnosis-banner-item-cta {
  align-self: flex-start;
}

.themed .t-sched-diagnosis-banner-hint {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: 1.5;
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-danger-border);
}

@media (max-width: 768px) {
  .themed .t-sched-diagnosis-banner-header {
    flex-direction: column;
  }
  .themed .t-sched-diagnosis-banner-icon {
    margin-top: 0;
  }
}


/* =============================================================================
   N+5. SCHEDULING — ASYNC MASTER PDF (Phase 9.8)
   Closes audit FAIL 14.3: synchronous WeasyPrint of 30+ pages risked
   request timeouts at 40+ classes. Three card variants for the polling
   page: preparing (info), ready (success), failed (danger). All scoped
   to `.themed`, all colors via tokens, mobile reflow at ≤768px.
   ============================================================================= */

/* Shared shell — all three variants extend this layout */
.themed .t-pdf-preparing-card,
.themed .t-pdf-ready-card,
.themed .t-pdf-failed-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-xl);
  border: 1px solid;
  border-left-width: 4px;
}

.themed .t-pdf-preparing-icon,
.themed .t-pdf-ready-icon,
.themed .t-pdf-failed-icon {
  flex-shrink: 0;
  margin-top: 2px;
}

.themed .t-pdf-preparing-body,
.themed .t-pdf-ready-body,
.themed .t-pdf-failed-body {
  flex: 1;
  min-width: 0;
}

/* PREPARING (pending / generating) — info palette */
.themed .t-pdf-preparing-card {
  background-color: var(--color-info-bg);
  border-color: var(--color-info-border);
}

.themed .t-pdf-preparing-icon {
  color: var(--color-info-text);
}

.themed .t-pdf-preparing-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-info-text);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-pdf-preparing-text {
  font-size: var(--text-sm);
  color: var(--color-text-base);
  line-height: 1.5;
  margin: 0 0 var(--space-2) 0;
}

.themed .t-pdf-preparing-meta {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

/* READY — success palette + download button */
.themed .t-pdf-ready-card {
  background-color: var(--color-success-bg);
  border-color: var(--color-success-border);
}

.themed .t-pdf-ready-icon {
  color: var(--color-success-icon);
}

.themed .t-pdf-ready-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-success-text);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-pdf-ready-text {
  font-size: var(--text-sm);
  color: var(--color-text-base);
  line-height: 1.5;
  margin: 0;
}

.themed .t-pdf-ready-actions {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.themed .t-pdf-ready-download-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background-color: var(--color-success-icon);
  color: var(--color-text-inverse);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
  transition: background-color 120ms ease;
}

.themed .t-pdf-ready-download-btn:hover {
  background-color: var(--color-success-text);
}

.themed .t-pdf-ready-regenerate-link {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  text-decoration: underline;
}

.themed .t-pdf-ready-regenerate-link:hover {
  color: var(--color-text-base);
}

/* FAILED — danger palette */
.themed .t-pdf-failed-card {
  background-color: var(--color-danger-bg);
  border-color: var(--color-danger-border);
}

.themed .t-pdf-failed-icon {
  color: var(--color-danger-icon);
}

.themed .t-pdf-failed-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-danger-text);
  margin: 0 0 var(--space-1) 0;
}

.themed .t-pdf-failed-text {
  font-size: var(--text-sm);
  color: var(--color-danger-text);
  line-height: 1.5;
  margin: 0 0 var(--space-2) 0;
  /* Error messages can be raw exception output — preserve newlines and
     break long lines so the card never overflows. */
  white-space: pre-wrap;
  word-break: break-word;
}

.themed .t-pdf-failed-hint {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: 0;
}

.themed .t-pdf-failed-actions {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.themed .t-pdf-failed-retry-btn {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  background-color: var(--color-danger-icon);
  color: var(--color-text-inverse);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
  transition: background-color 120ms ease;
}

.themed .t-pdf-failed-retry-btn:hover {
  background-color: var(--color-danger-text);
}

@media (max-width: 768px) {
  .themed .t-pdf-preparing-card,
  .themed .t-pdf-ready-card,
  .themed .t-pdf-failed-card {
    flex-direction: column;
  }
  .themed .t-pdf-preparing-icon,
  .themed .t-pdf-ready-icon,
  .themed .t-pdf-failed-icon {
    margin-top: 0;
  }
  .themed .t-pdf-ready-actions,
  .themed .t-pdf-failed-actions {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
  }
  .themed .t-pdf-ready-download-btn,
  .themed .t-pdf-failed-retry-btn {
    justify-content: center;
  }
}

/* ============================================================
 * Phase 10 — Tactical Mode (M7)
 * Dense full-week board: rows=classes, cols=days×periods.
 * All classes scoped to .themed and use design tokens.
 * Mobile: ≤900px shows fallback banner, hides grid (touch
 * drag-and-drop on a 30+ column grid is unworkable).
 * ============================================================ */

/* ---- Page layout ---- */

.themed .t-tactical-page {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  min-height: calc(100vh - 4rem);
}

.themed .t-tactical-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm, 0 1px 2px 0 rgba(0, 0, 0, 0.04));
}

.themed .t-tactical-toolbar-left,
.themed .t-tactical-toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.themed .t-tactical-toolbar-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--color-text-base);
  line-height: 1.2;
}

.themed .t-tactical-toolbar-meta {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin-top: var(--space-0-5);
}

.themed .t-tactical-toolbar-divider {
  width: 1px;
  height: 24px;
  background-color: var(--color-border);
}

/* ---- Stats strip ---- */

.themed .t-tactical-stats {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-2-5) var(--space-4);
  background-color: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: 0.8125rem;
}

.themed .t-tactical-stat {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.themed .t-tactical-stat-label {
  color: var(--color-text-muted);
}

.themed .t-tactical-stat-value {
  font-weight: 600;
  color: var(--color-text-base);
}

.themed .t-tactical-stat-value-warning {
  color: var(--color-warning-text);
}

.themed .t-tactical-stat-value-danger {
  color: var(--color-danger-text);
}

.themed .t-tactical-progress {
  flex: 1 1 200px;
  height: 6px;
  background-color: var(--color-border);
  border-radius: var(--radius-full);
  overflow: hidden;
  min-width: 120px;
}

.themed .t-tactical-progress-fill {
  height: 100%;
  background-color: var(--color-info-text);
  border-radius: var(--radius-full);
  transition: width 200ms ease-out;
}

.themed .t-tactical-progress-fill-success {
  background-color: var(--color-success-icon);
}

/* ---- Force-mode banner (similar to manual editor's t-force-banner
 *      but tactical has its own copy so the layouts can diverge) ---- */

.themed .t-tactical-force-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2-5);
  padding: var(--space-3) var(--space-4);
  background-color: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-left: 4px solid var(--color-danger-icon);
  border-radius: var(--radius-md);
  color: var(--color-danger-text);
  font-size: 0.875rem;
  line-height: 1.5;
}

.themed .t-tactical-force-banner-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  color: var(--color-danger-icon);
}

.themed .t-tactical-force-banner strong {
  font-weight: 600;
}

/* ---- Active-schedule banner ---- */

.themed .t-tactical-active-banner {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2-5) var(--space-4);
  background-color: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  border-left: 4px solid var(--color-warning-icon);
  border-radius: var(--radius-md);
  color: var(--color-warning-text);
  font-size: 0.8125rem;
  font-weight: 500;
}

.themed .t-tactical-active-banner-icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  color: var(--color-warning-icon);
}

/* ---- Main layout: grid + inspector side-by-side ---- */

.themed .t-tactical-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--space-3);
  align-items: stretch;
  transition: grid-template-columns 220ms ease;
}

/* Inspector collapsed → second column shrinks to a thin rail (40px),
   the grid takes the rest. Transition makes the resize feel smooth.
   The rail itself remains clickable to re-expand. */
.themed .t-tactical-layout-inspector-collapsed {
  grid-template-columns: minmax(0, 1fr) 40px;
}

.themed .t-tactical-grid-wrap {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: auto;
  max-height: calc(100vh - 22rem);
  position: relative;
}

/* ---- Dense grid ---- */

.themed .t-tactical-grid {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  font-size: 0.625rem;        /* 10px — dense aSc-style */
  table-layout: fixed;
}

.themed .t-tactical-grid thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background-color: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
  padding: var(--space-1) var(--space-1-5);
  font-weight: 600;
  color: var(--color-text-muted);
  text-align: center;
  white-space: nowrap;
}

.themed .t-tactical-grid-corner {
  z-index: 4 !important;          /* above day headers + above tbody */
  left: 0;
  position: sticky;
  background-color: var(--color-surface-muted);
  border-right: 1px solid var(--color-border);
  text-align: left;
  padding: 2px var(--space-2);
  width: 80px;
  min-width: 80px;
  max-width: 80px;
}

.themed .t-tactical-day-header {
  border-left: 2px solid var(--color-border);
}

.themed .t-tactical-day-header-name {
  display: block;
  font-size: 0.75rem;
  color: var(--color-text-base);
  text-transform: capitalize;
}

.themed .t-tactical-period-header {
  font-size: 0.5625rem;       /* 9px — minimal column width */
  font-weight: 600;
  color: var(--color-text-muted);
  min-width: 0;
  width: auto;
  padding: 2px 1px !important;
}

.themed .t-tactical-period-header-time {
  display: block;
  font-size: 0.5rem;
  font-weight: 400;
  color: var(--color-text-muted);
  margin-top: 0;
}

.themed .t-tactical-period-break-header {
  background-color: var(--color-surface-hover) !important;
  color: var(--color-text-muted);
  font-style: italic;
}

.themed .t-tactical-grid tbody td {
  border-right: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  padding: 0;
  height: 28px;             /* Dense — aSc-style row height */
  position: relative;
  vertical-align: top;
  background-color: var(--color-surface);
}

.themed .t-tactical-class-cell {
  position: sticky;
  left: 0;
  z-index: 2;
  background-color: var(--color-surface) !important;
  padding: 2px var(--space-2);
  font-weight: 600;
  color: var(--color-text-base);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
  width: 80px;
  min-width: 80px;
  max-width: 80px;
  border-right: 1px solid var(--color-border);
}

.themed .t-tactical-class-name {
  display: block;
  font-size: 0.6875rem;
  color: var(--color-text-base);
  line-height: 1.1;
}

.themed .t-tactical-class-grade {
  display: block;
  font-size: 0.5625rem;
  font-weight: 400;
  color: var(--color-text-muted);
  margin-top: 0;
  line-height: 1;
}

/* ---- Cell states (drag/hint) ---- */

.themed .t-tactical-cell {
  cursor: pointer;
  transition: background-color 80ms ease, box-shadow 80ms ease;
}

.themed .t-tactical-cell:hover {
  background-color: var(--color-surface-hover);
}

.themed .t-tactical-cell-day-divider {
  border-left: 2px solid var(--color-border);
}

.themed .t-tactical-cell-break {
  cursor: not-allowed;
  background-color: var(--color-surface-hover) !important;
  background-image: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 4px,
    rgba(148, 163, 184, 0.15) 4px,
    rgba(148, 163, 184, 0.15) 8px
  );
}

/* ---- Phase 10.1 — hint overlays via border + glow ----
   Subject identity (the saturated slot color) must stay visible
   during a pick. So instead of replacing the cell background,
   we layer a colored ring + soft inner glow on top via
   `box-shadow: inset`. Empty cells also get a faint background
   tint so the hint reads at-a-glance even where there's no
   slot underneath; occupied cells show the saturated subject
   color through the transparent middle of the box-shadow.

   `box-shadow: inset` doesn't paint over child elements, so the
   slot div's saturated color stays untouched — the ring sits
   on the cell's border, the glow softly fades inward.

   `!important` on background-color ensures Tailwind utility
   classes don't override the empty-cell tint. */
/* Phase 10.1 hotfix #2 — readability bump.
   Pre-fix users couldn't tell hint colors apart at a glance in a
   dense grid (rings were 2px and the green/red blended into the
   surrounding cells). Two changes:
     1. Bump rings to 3px — more prominent without dominating the
        subject color. Slot-level rules below match.
     2. Animate green (optimal) cells with a gentle ring pulse so
        actionable cells "breathe" — the eye lands there first.
        Animate red (blocked) cells with a marching diagonal hatch
        ("interdit" effect) instead of a flash, because blocked
        cells are typically numerous (50+ on a busy schedule) and
        flashing all of them would be visually painful. */
.themed .t-tactical-cell-blocked {
  background-color: var(--color-danger-bg) !important;
  background-image: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 5px,
    var(--color-danger-border) 5px,
    var(--color-danger-border) 6px
  );
  box-shadow: inset 0 0 0 3px var(--color-danger-icon),
              inset 0 0 12px 0 rgba(220, 38, 38, 0.30);
  animation: t-tactical-blocked-hatch-march 1.4s linear infinite;
}

.themed .t-tactical-cell-warning {
  background-color: var(--color-warning-bg) !important;
  box-shadow: inset 0 0 0 3px var(--color-warning-icon),
              inset 0 0 10px 0 rgba(245, 158, 11, 0.28);
}

.themed .t-tactical-cell-optimal {
  background-color: var(--color-success-bg) !important;
  box-shadow: inset 0 0 0 3px var(--color-success-icon),
              inset 0 0 14px 0 rgba(34, 197, 94, 0.32);
  animation: t-tactical-cell-optimal-pulse 1.5s ease-in-out infinite;
}

/* Same-class swap target hint. Phase 10.1 hotfix #2 keeps the
   info-blue pulse but bumps to 3px ring + glyph. */
.themed .t-tactical-cell-swap {
  background-color: var(--color-info-bg) !important;
  box-shadow: inset 0 0 0 3px var(--color-info-icon),
              inset 0 0 12px 0 rgba(59, 130, 246, 0.32);
  animation: t-tactical-swap-pulse 2.4s ease-in-out infinite;
}

.themed .t-tactical-cell-neutral {
  background-color: var(--color-info-bg) !important;
  box-shadow: inset 0 0 0 1px var(--color-info-border);
}

/* Phase 10.1 hotfix #2 — corner hint glyph.
   Bottom-right of every hint cell carries a tiny ✓ / ✕ / ! / ↔
   icon in a white pill. Reinforces the color signal for at-a-glance
   reading + colorblind accessibility. Bottom-right placement avoids
   the lock icon (top-right of the slot) and the force-violation
   glyph (top-left of the slot). z-index 3 keeps it above the slot
   div's saturated background even on occupied cells. */
.themed .t-tactical-cell-blocked::before,
.themed .t-tactical-cell-warning::before,
.themed .t-tactical-cell-optimal::before,
.themed .t-tactical-cell-swap::before {
  position: absolute;
  bottom: 1px;
  right: 1px;
  width: 12px;
  height: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 1;
  background-color: #ffffff;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.30);
  pointer-events: none;
  z-index: 3;
  /* Reset text-shadow inherited from text-on-* cells (which would
     blur the colored glyph on top of the saturated subject bg). */
  text-shadow: none;
}

.themed .t-tactical-cell-blocked::before {
  content: '✕';
  color: var(--color-danger-icon);
}

.themed .t-tactical-cell-warning::before {
  content: '!';
  color: var(--color-warning-icon);
}

.themed .t-tactical-cell-optimal::before {
  content: '✓';
  color: var(--color-success-icon);
}

.themed .t-tactical-cell-swap::before {
  content: '↔';
  color: var(--color-info-icon);
}

.themed .t-tactical-cell-drop-target {
  outline: 2px solid var(--color-info-text);
  outline-offset: -2px;
  background-color: var(--color-info-bg) !important;
}

.themed .t-tactical-cell-swap-target {
  outline: 2px solid var(--color-warning-icon);
  outline-offset: -2px;
}

/* Phase 10.1 — hint ring/glow on the slot itself.
   The td-level `box-shadow: inset` declared above paints the
   ring on EMPTY cells (where the slot div is absent). On occupied
   cells the slot div fills 100% of the td and visually covers the
   td's inset shadow, so we duplicate the shadow via a descendant
   selector — applied to the slot box, the inset paints on top of
   the saturated subject background. Subject identity stays
   visible in the centre; the colored ring + soft inner glow at
   the edges signal the hint state. */
.themed .t-tactical-cell-blocked > .t-tactical-slot {
  box-shadow: inset 0 0 0 3px var(--color-danger-icon),
              inset 0 0 12px 0 rgba(220, 38, 38, 0.40);
}

.themed .t-tactical-cell-warning > .t-tactical-slot {
  box-shadow: inset 0 0 0 3px var(--color-warning-icon),
              inset 0 0 10px 0 rgba(245, 158, 11, 0.32);
}

/* Phase 10.1 hotfix #2 — slot-level optimal pulse.
   Mirrors the td-level pulse so the actionable signal is also
   visible on occupied cells (where the slot covers the td's
   inset shadow). Same 1.5s cadence so empty + occupied optimal
   cells pulse in sync. */
.themed .t-tactical-cell-optimal > .t-tactical-slot {
  box-shadow: inset 0 0 0 3px var(--color-success-icon),
              inset 0 0 14px 0 rgba(34, 197, 94, 0.42);
  animation: t-tactical-slot-optimal-pulse 1.5s ease-in-out infinite;
}

.themed .t-tactical-cell-swap > .t-tactical-slot {
  box-shadow: inset 0 0 0 3px var(--color-info-icon),
              inset 0 0 12px 0 rgba(59, 130, 246, 0.40);
}

.themed .t-tactical-cell-neutral > .t-tactical-slot {
  box-shadow: inset 0 0 0 1px var(--color-info-border);
}

/* ---- Slot block (placement) ---- */

/* Phase 10.1 — saturated edge-to-edge subject block.
   No border-radius, no margin, no left-color accent — the cell's
   table border separates blocks visually. The full subject color
   fills the cell; text contrast is handled by `t-tactical-cell-text-on-*`
   classes (light or dark) applied alongside this one. */
.themed .t-tactical-slot {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
  padding: 0 2px;
  cursor: grab;
  /* `overflow: visible` so the styled tooltip pseudo-element
     (anchored to this slot via `[data-tooltip]:hover::after`)
     can extend above the slot. The inner subject-code span
     handles its own text truncation via ellipsis. */
  overflow: visible;
  user-select: none;
  position: relative;
}

.themed .t-tactical-slot:active {
  cursor: grabbing;
}

.themed .t-tactical-slot-locked {
  cursor: not-allowed;
}

.themed .t-tactical-slot-carrying {
  opacity: 0.4;
  outline: 2px dashed var(--color-info-text);
  outline-offset: -2px;
}

.themed .t-tactical-slot-subject {
  font-weight: 600;
  font-size: 0.6875rem;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.themed .t-tactical-slot-teacher {
  font-size: 0.625rem;
  font-weight: 400;
  color: var(--color-text-muted);
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 1px;
}

/* Dense subject-code chip — replaces subject_name + teacher_name in
   the grid cell. Full label surfaces in the cell's `title` tooltip.
   Phase 10.1: text color inherits from the parent `.t-tactical-slot`
   which carries a `t-tactical-cell-text-on-light` or
   `t-tactical-cell-text-on-dark` class chosen server-side via
   the WCAG luminance helper. */
.themed .t-tactical-slot-code {
  font-weight: 700;
  font-size: 0.75rem;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
  text-align: center;
  color: inherit;
}

.themed .t-tactical-slot-lock-icon {
  position: absolute;
  top: 0;
  right: 1px;
  font-size: 0.5rem;
  color: var(--color-warning-icon);
  pointer-events: none;
}

/* Phase 11 post-pilot — joint session marker.
   Small diamond glyph in the top-left of the slot block signals that
   this slot belongs to a JointSessionGroup. Dragging it moves all
   sibling classes atomically. Positioned top-left to leave the
   top-right corner free for the lock icon (slots can be both joint
   AND locked). Uses the info-icon token (contrast against saturated
   subject background covered by light/dark text override below). */
.themed .t-tactical-slot-joint-icon {
  position: absolute;
  top: 0;
  left: 1px;
  font-size: 0.55rem;
  font-weight: 700;
  color: var(--color-info-icon);
  pointer-events: none;
  line-height: 1;
}

/* Same contrast override as lock-icon: the saturated subject colors
   underneath swing between light + dark, so we override based on
   the precomputed `text_on` class. */
.themed .t-tactical-cell-text-on-light .t-tactical-slot-joint-icon {
  color: rgba(255, 255, 255, 0.95);
  text-shadow: 0 0 1px rgba(0, 0, 0, 0.35);
}
.themed .t-tactical-cell-text-on-dark .t-tactical-slot-joint-icon {
  color: rgba(0, 0, 0, 0.85);
}

/* Styled hover tooltip for slot blocks. Replaces the native
   browser `title` attribute (ugly OS styling + 600ms delay).
   Uses `data-tooltip` attribute + `::after` pseudo-element. The
   tooltip appears above the slot with a small arrow, fades in
   after a short delay, and wraps long content.

   Why no JS: pure CSS keeps the implementation cheap and
   reliable. The trade-off is no viewport-aware repositioning;
   slots in the very top row may have the tooltip clipped. Given
   the dense grid is meant to be viewed across the full week
   landscape, this is acceptable. */
.themed .t-tactical-slot[data-tooltip] {
  /* Allow the absolute-positioned tooltip to reference this slot. */
  /* The .t-tactical-cell already has `position: relative`. The
     slot inherits that frame; the tooltip overflows the cell
     visibly thanks to the grid wrapper's overflow allowance. */
}

.themed .t-tactical-slot[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  background-color: var(--color-text-base);
  color: var(--color-text-inverse);
  padding: 6px 10px;
  border-radius: var(--radius-md);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  white-space: normal;
  max-width: 240px;
  width: max-content;
  line-height: 1.4;
  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.18);
  pointer-events: none;
  animation: t-tactical-tooltip-in 120ms ease-out 250ms backwards;
}

.themed .t-tactical-slot[data-tooltip]:hover::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 1px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  width: 0;
  height: 0;
  border: 5px solid transparent;
  border-top-color: var(--color-text-base);
  pointer-events: none;
  animation: t-tactical-tooltip-in 120ms ease-out 250ms backwards;
}

@keyframes t-tactical-tooltip-in {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(2px);
  }
  to {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
}

/* While carrying a slot, hide tooltips — they'd flicker as the
   cursor crosses cells during drag and add visual noise. */
.themed .t-tactical-page:has(.t-tactical-slot-carrying)
  .t-tactical-slot[data-tooltip]:hover::after,
.themed .t-tactical-page:has(.t-tactical-slot-carrying)
  .t-tactical-slot[data-tooltip]:hover::before {
  display: none;
}

/* ---- Inspector ---- */

.themed .t-tactical-inspector {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  font-size: 0.8125rem;
  position: sticky;
  top: var(--space-2);
  align-self: flex-start;
  max-height: calc(100vh - 22rem);
  overflow-y: auto;
  transition: padding 220ms ease;
}

/* Collapsed inspector — narrow vertical rail. Padding shrinks,
   contents hide via `x-show`, and the toggle button becomes the
   full clickable area. The rail keeps the same border/background
   so it visually attaches to the layout grid. */
.themed .t-tactical-inspector-collapsed {
  padding: var(--space-2) 0;
  gap: 0;
  align-items: center;
  overflow: hidden;
}

.themed .t-tactical-inspector-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  width: 100%;
}

.themed .t-tactical-inspector-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  border-radius: var(--radius-sm);
  transition: background-color 120ms ease, color 120ms ease;
  font-family: inherit;
}

/* Expanded state — small icon button anchored top-right of the
   inspector, doesn't disturb section layout. */
/* Expanded state — small icon button anchored top-right of the
   inspector, with a subtle pill background so it's visually
   discoverable rather than melting into the panel. */
.themed .t-tactical-inspector:not(.t-tactical-inspector-collapsed)
  .t-tactical-inspector-toggle {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: 28px;
  height: 28px;
  padding: 0;
  background-color: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  z-index: 2;
}

.themed .t-tactical-inspector:not(.t-tactical-inspector-collapsed)
  .t-tactical-inspector-toggle:hover {
  background-color: var(--color-info-bg);
  border-color: var(--color-info-border);
  color: var(--color-info-text);
}

/* Collapsed state — toggle becomes the entire rail. Vertical text
   for the "Inspecteur" label, large click target. */
.themed .t-tactical-inspector-collapsed .t-tactical-inspector-toggle {
  width: 100%;
  flex-direction: column;
  padding: var(--space-3) 0;
  flex: 1 1 auto;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-3);
  color: var(--color-text-muted);
  min-height: 200px;
}

.themed .t-tactical-inspector-collapsed .t-tactical-inspector-toggle:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-info-text);
}

.themed .t-tactical-inspector-toggle-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  /* Path is chevron-left by default. Rotate 180° when expanded
     so the arrow points right (collapse direction). Smooth
     transition makes the toggle feel responsive. */
  transition: transform 200ms ease;
}

.themed .t-tactical-inspector:not(.t-tactical-inspector-collapsed)
  .t-tactical-inspector-toggle-icon {
  transform: rotate(180deg);
}

.themed .t-tactical-inspector-collapsed .t-tactical-inspector-toggle-icon {
  width: 18px;
  height: 18px;
}

/* Vertical "Inspecteur" label — only shown when collapsed. */
.themed .t-tactical-inspector-toggle-label {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
}

.themed .t-tactical-inspector-section + .t-tactical-inspector-section {
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.themed .t-tactical-inspector-label {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.themed .t-tactical-inspector-empty {
  color: var(--color-text-muted);
  font-style: italic;
  font-size: 0.8125rem;
}

.themed .t-tactical-inspector-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-2-5);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border);
  background-color: var(--color-surface-muted);
}

.themed .t-tactical-inspector-card-subject {
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--color-text-base);
}

.themed .t-tactical-inspector-card-meta {
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.themed .t-tactical-inspector-card-progress {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin-top: var(--space-1);
}

.themed .t-tactical-inspector-card-hint {
  font-size: 0.6875rem;
  color: var(--color-text-muted);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--color-border);
  line-height: 1.4;
}

/* Workflow help list — shown in the inspector empty state.
   Indented numbered list with kbd-chip support. */
.themed .t-tactical-help-list {
  list-style-position: inside;
  list-style-type: decimal;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  line-height: 1.5;
  margin: var(--space-2) 0 0;
  padding-left: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
}

.themed .t-tactical-help-list > li {
  padding-left: 2px;
}

.themed .t-tactical-help-list strong {
  color: var(--color-text-base);
  font-weight: 600;
}

.themed .t-tactical-help-sublist {
  list-style-type: disc;
  list-style-position: outside;
  margin: var(--space-1) 0 0 var(--space-5);
  padding: 0;
  font-size: 0.6875rem;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Permissive-philosophy callout — appears below the workflow help
   list. Reminds the planificateur that hints don't block moves;
   only Publish enforces hard constraints (and Mode force bypasses
   even that). Info-tinted block to set it apart from instructions. */
.themed .t-tactical-help-philosophy {
  margin-top: var(--space-3);
  padding: var(--space-2-5);
  border-left: 3px solid var(--color-info-text);
  background-color: var(--color-info-bg);
  border-radius: var(--radius-sm);
  font-size: 0.6875rem;
  color: var(--color-text-base);
  line-height: 1.5;
}

.themed .t-tactical-help-philosophy strong {
  color: var(--color-info-text);
  font-weight: 600;
}

.themed .t-tactical-help-philosophy em {
  font-style: normal;
  font-weight: 600;
  color: var(--color-text-base);
}

.themed .t-tactical-legend {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
  font-size: 0.6875rem;
  color: var(--color-text-muted);
}

.themed .t-tactical-legend-item {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.themed .t-tactical-legend-swatch {
  width: 10px;
  height: 10px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.themed .t-tactical-legend-swatch-blocked {
  background-color: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
}

.themed .t-tactical-legend-swatch-warning {
  background-color: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
}

.themed .t-tactical-legend-swatch-optimal {
  background-color: var(--color-success-bg);
  border: 1px solid var(--color-success-border);
}

.themed .t-tactical-legend-swatch-neutral {
  background-color: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
}

.themed .t-tactical-shortcuts {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: 0.6875rem;
  color: var(--color-text-muted);
}

.themed .t-tactical-shortcut {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
}

.themed .t-tactical-kbd {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 0.625rem;
  font-weight: 600;
  padding: 1px 5px;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-base);
  white-space: nowrap;
}

/* ---- Park tray ---- */

.themed .t-tactical-park-tray {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.themed .t-tactical-park-tray-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2-5) var(--space-4);
  background-color: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
  user-select: none;
}

.themed .t-tactical-park-tray-collapsed .t-tactical-park-tray-header {
  border-bottom: none;
}

.themed .t-tactical-park-tray-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-base);
}

.themed .t-tactical-park-tray-count {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--space-2);
  height: 18px;
  font-size: 0.6875rem;
  font-weight: 600;
  background-color: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  color: var(--color-warning-text);
  border-radius: var(--radius-full);
}

.themed .t-tactical-park-tray-count-empty {
  background-color: var(--color-surface-hover);
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

.themed .t-tactical-park-tray-toggle-icon {
  width: 14px;
  height: 14px;
  color: var(--color-text-muted);
  transition: transform 150ms ease;
}

.themed .t-tactical-park-tray-collapsed .t-tactical-park-tray-toggle-icon {
  transform: rotate(-90deg);
}

.themed .t-tactical-park-tray-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  min-height: 60px;
  align-items: flex-start;
}

.themed .t-tactical-park-tray-list-drop-target {
  outline: 2px dashed var(--color-info-text);
  outline-offset: -2px;
  background-color: var(--color-info-bg);
}

.themed .t-tactical-park-tray-empty {
  color: var(--color-text-muted);
  font-style: italic;
  font-size: 0.75rem;
}

.themed .t-tactical-park-card {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: var(--space-1-5) var(--space-2);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-muted);
  cursor: grab;
  font-size: 0.75rem;
  min-width: 110px;
  user-select: none;
}

.themed .t-tactical-park-card:active {
  cursor: grabbing;
}

.themed .t-tactical-park-card-carrying {
  opacity: 0.4;
  outline: 2px dashed var(--color-info-text);
  outline-offset: -2px;
}

.themed .t-tactical-park-card-subject {
  font-weight: 600;
  color: var(--color-text-base);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.themed .t-tactical-park-card-meta {
  font-size: 0.625rem;
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Toast ---- */

.themed .t-tactical-toast {
  /* Inline + centered — between the stats strip and the grid. The
     planner's eyes are on the grid so feedback should sit on the
     centre line, not at the corner of the screen. */
  margin: 0 auto var(--space-3) auto;
  width: fit-content;
  min-width: 280px;
  max-width: min(640px, 90%);
  padding: var(--space-2-5) var(--space-4);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md, 0 4px 12px rgba(0, 0, 0, 0.08));
  font-size: 0.8125rem;
  line-height: 1.45;
  border: 1px solid;
  text-align: center;
}

.themed .t-tactical-toast-success {
  background-color: var(--color-success-bg);
  border-color: var(--color-success-border);
  color: var(--color-success-text);
}

.themed .t-tactical-toast-error {
  background-color: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  color: var(--color-danger-text);
}

.themed .t-tactical-toast-warning {
  background-color: var(--color-warning-bg);
  border-color: var(--color-warning-border);
  color: var(--color-warning-text);
}

.themed .t-tactical-toast-info {
  background-color: var(--color-info-bg);
  border-color: var(--color-info-border);
  color: var(--color-info-text);
}

.themed .t-tactical-toast-list {
  margin-top: var(--space-1);
  padding-left: var(--space-4);
  list-style: disc;
}

.themed .t-tactical-toast-action {
  margin-top: var(--space-2);
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
}

/* ---- Publish dialog ---- */

.themed .t-tactical-dialog-overlay {
  position: fixed;
  inset: 0;
  background-color: rgba(15, 23, 42, 0.45);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}

.themed .t-tactical-dialog {
  background-color: var(--color-surface);
  border-radius: var(--radius-xl);
  border: 1px solid var(--color-border);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: var(--shadow-xl, 0 20px 50px rgba(0, 0, 0, 0.25));
}

.themed .t-tactical-dialog-header {
  padding: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-tactical-dialog-title {
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--color-text-base);
}

.themed .t-tactical-dialog-subtitle {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  margin-top: var(--space-1);
}

.themed .t-tactical-dialog-body {
  padding: var(--space-4);
  overflow-y: auto;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.themed .t-tactical-dialog-footer {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--color-border);
  background-color: var(--color-surface-muted);
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}

.themed .t-tactical-publish-counts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}

.themed .t-tactical-publish-count {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-3) var(--space-2);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-muted);
  border: 1px solid var(--color-border);
}

.themed .t-tactical-publish-count-num {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-text-base);
  line-height: 1;
}

.themed .t-tactical-publish-count-label {
  font-size: 0.6875rem;
  color: var(--color-text-muted);
  margin-top: var(--space-1);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.themed .t-tactical-publish-count-creates {
  border-left: 3px solid var(--color-success-icon);
}

.themed .t-tactical-publish-count-deletes {
  border-left: 3px solid var(--color-danger-icon);
}

.themed .t-tactical-publish-count-moves {
  border-left: 3px solid var(--color-info-text);
}

.themed .t-tactical-publish-warning {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2-5) var(--space-3);
  background-color: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  border-left: 3px solid var(--color-warning-icon);
  border-radius: var(--radius-md);
  color: var(--color-warning-text);
  font-size: 0.8125rem;
}

.themed .t-tactical-publish-error {
  background-color: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  border-left-color: var(--color-danger-icon);
  color: var(--color-danger-text);
}

/* ---- Mobile fallback banner — touch DnD on a 30+ col grid is unworkable ---- */

.themed .t-tactical-mobile-banner {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-6) var(--space-4);
  background-color: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
  border-radius: var(--radius-lg);
  text-align: center;
}

.themed .t-tactical-mobile-banner-icon {
  width: 48px;
  height: 48px;
  color: var(--color-info-text);
}

.themed .t-tactical-mobile-banner-title {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--color-text-base);
}

.themed .t-tactical-mobile-banner-body {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  max-width: 32ch;
  line-height: 1.5;
}

.themed .t-tactical-mobile-banner-cta {
  margin-top: var(--space-2);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background-color: var(--color-primary-bg, var(--color-info-text));
  color: var(--color-text-inverse);
  border-radius: var(--radius-md);
  font-size: 0.8125rem;
  font-weight: 500;
  text-decoration: none;
}

@media (max-width: 900px) {
  .themed .t-tactical-mobile-banner {
    display: flex;
  }
  .themed .t-tactical-layout,
  .themed .t-tactical-park-tray,
  .themed .t-tactical-stats,
  .themed .t-tactical-toolbar {
    display: none;
  }
}

@media (max-width: 1280px) {
  .themed .t-tactical-layout {
    grid-template-columns: minmax(0, 1fr) 280px;
  }
}

/* ════════════════════════════════════════════════════════════════
 * Phase 10.1 — Tactical Mode Visual Density Pass
 *
 * Adds:
 *   1. Saturated subject text contrast (light vs dark per slot)
 *   2. Force-violation dashed red ring + warning glyph
 *   3. Toolbar violation pill (count + cycle button)
 *   4. Animations: swap-pulse, force-march, violation-pulse
 *
 * Hint colors are handled above via box-shadow inset (border + glow)
 * so subject identity stays visible while a card is in the air.
 * ════════════════════════════════════════════════════════════════ */

/* ---- Phase 10.1 — text-on contrast ----
   `_text_on_for_color()` (WCAG luminance, threshold 0.55) chooses
   light or dark text per subject color. We also drop a small
   text-shadow so the code stays legible even when the saturated
   color is on the boundary (yellow/lime/cyan). */
.themed .t-tactical-cell-text-on-light {
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(15, 23, 42, 0.35);
}

.themed .t-tactical-cell-text-on-dark {
  color: rgba(15, 23, 42, 0.92);
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.45);
}

/* Lock icon inherits text color so it reads on both light and dark
   subject backgrounds. The original amber-warning hard-coded color
   washed out on yellow/orange subjects. */
.themed .t-tactical-cell-text-on-light .t-tactical-slot-lock-icon {
  color: rgba(255, 255, 255, 0.85);
}

.themed .t-tactical-cell-text-on-dark .t-tactical-slot-lock-icon {
  color: rgba(15, 23, 42, 0.7);
}

/* ---- Phase 10.1 — force-violation ring ----
   A dashed red ring marches around the slot when its current
   placement would fail a hard constraint at publish (teacher
   conflict, hard unavailability, cross-config block).

   `::after` pseudo-element overlays the slot so the saturated
   subject color underneath stays visible — the ring itself is
   the violation indicator, not a tint over the subject. The
   `border-style: dashed` + animation moves the dash pattern,
   giving an "alive" hazard feel without being garish. */
.themed .t-tactical-cell-force-violation {
  /* Slot background stays the saturated subject color; the ring
     sits on top of it via the pseudo-element below. */
}

.themed .t-tactical-cell-force-violation::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 2px dashed var(--color-danger-icon);
  pointer-events: none;
  animation: t-tactical-force-march 1.6s linear infinite;
  /* Without `box-sizing` the dashed border can render OUTSIDE the
     cell's clip area — explicit `border-box` keeps it inside. */
  box-sizing: border-box;
  /* z-index above the saturated background but below the lock
     icon and warning glyph so they remain clickable. */
  z-index: 1;
}

/* Warning glyph in the top-left corner of every force-violating
   cell. Sits above the dashed ring, has its own white pill
   background so it reads on any subject color. */
.themed .t-tactical-cell-violation-glyph {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.625rem;
  font-weight: 700;
  color: var(--color-danger-icon);
  background-color: #ffffff;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.25);
  pointer-events: none;
  /* Above the ::after ring (z-index: 1) so the glyph sits on top. */
  z-index: 2;
  /* Defensive — prevent text-shadow inherited from text-on-light
     parent leaking into the glyph and blurring its red glyph. */
  text-shadow: none;
}

/* `cycleForceViolations()` adds this class for ~1.2s after a
   click on the toolbar pill — pulses the targeted cell so the
   planificateur sees where it landed after the smooth-scroll. */
.themed .t-tactical-cell-violation-pulse {
  animation: t-tactical-violation-pulse-burst 1.2s ease-out;
  /* z-index pop so the pulse reads above neighbouring cells. */
  z-index: 5;
}

/* ---- Phase 10.1 — toolbar violation pill ----
   Visible only when `forceViolations.size > 0` (Alpine `x-show`).
   Same pulsing-dashed look as the cell ring so the planificateur
   visually links the toolbar count to the affected cells. Click
   cycles through the violations (smooth-scroll + pulse). */
.themed .t-tactical-violation-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px 10px;
  background-color: var(--color-danger-bg);
  color: var(--color-danger-text);
  border: 1.5px dashed var(--color-danger-icon);
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 120ms ease, transform 120ms ease;
  animation: t-tactical-force-march 2.2s linear infinite;
}

.themed .t-tactical-violation-pill:hover {
  background-color: var(--color-danger-border);
  transform: translateY(-1px);
}

.themed .t-tactical-violation-pill:active {
  transform: translateY(0);
}

.themed .t-tactical-violation-pill-glyph {
  font-size: 0.875rem;
  line-height: 1;
}

.themed .t-tactical-violation-pill-count {
  font-weight: 700;
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

.themed .t-tactical-violation-pill-label {
  font-size: 0.75rem;
  text-transform: lowercase;
  letter-spacing: 0.01em;
}

/* ---- Phase 10.1 — animations ---- */

/* Marching-ants effect for dashed borders. Shifts the dash
   offset over time so the ring animates around the slot. The
   exact distance (12px) matches `border: 2px dashed` repeat
   roughly so there's no visible "snap". */
@keyframes t-tactical-force-march {
  from { background-position: 0 0; }
  to   { background-position: 12px 0; }
}

/* Soft pulse used by `cell-swap` while a card is in the air.
   Just opacity + box-shadow strength — no scale change so the cell
   footprint stays stable in the dense grid.
   Phase 10.1 hotfix #2: ring bumped to 3px to match the static
   rule (otherwise the animation would snap on every cycle). */
@keyframes t-tactical-swap-pulse {
  0%, 100% {
    box-shadow: inset 0 0 0 3px var(--color-info-icon),
                inset 0 0 10px 0 rgba(59, 130, 246, 0.22);
  }
  50% {
    box-shadow: inset 0 0 0 3px var(--color-info-icon),
                inset 0 0 16px 2px rgba(59, 130, 246, 0.40);
  }
}

/* Phase 10.1 hotfix #2 — gentle green pulse on optimal cells
   (the actionable drop targets). 1.5s cycle with a soft glow
   intensification at the midpoint. Two flavors: td-level (for
   empty cells) and slot-level (for occupied cells), kept in sync
   so a row of optimal cells pulses uniformly. */
@keyframes t-tactical-cell-optimal-pulse {
  0%, 100% {
    box-shadow: inset 0 0 0 3px var(--color-success-icon),
                inset 0 0 12px 0 rgba(34, 197, 94, 0.28);
  }
  50% {
    box-shadow: inset 0 0 0 3px var(--color-success-icon),
                inset 0 0 20px 2px rgba(34, 197, 94, 0.55);
  }
}

@keyframes t-tactical-slot-optimal-pulse {
  0%, 100% {
    box-shadow: inset 0 0 0 3px var(--color-success-icon),
                inset 0 0 14px 0 rgba(34, 197, 94, 0.42);
  }
  50% {
    box-shadow: inset 0 0 0 3px var(--color-success-icon),
                inset 0 0 22px 2px rgba(34, 197, 94, 0.65);
  }
}

/* Phase 10.1 hotfix #2 — marching diagonal hatch on blocked cells.
   Conveys "interdit" energy without the eye-fatigue of a flash —
   important because blocked cells are typically numerous (50+ on
   a busy schedule). The 8.485px = 6 × √2 step matches one repeat
   of the 45° hatch gradient (base period 6px), so the pattern
   loops seamlessly. */
@keyframes t-tactical-blocked-hatch-march {
  from { background-position: 0 0; }
  to   { background-position: 8.485px 0; }
}

/* One-shot burst when `cycleForceViolations()` jumps to a cell.
   Quick scale-up + outer glow then settles. */
@keyframes t-tactical-violation-pulse-burst {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 var(--color-danger-icon);
  }
  30% {
    transform: scale(1.08);
    box-shadow: 0 0 0 6px rgba(220, 38, 38, 0.45);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(220, 38, 38, 0);
  }
}

/* ============================================================================
   BILLING & INSCRIPTION  (apps/billing)  — Phase 0
   ----------------------------------------------------------------------------
   Optional, per-school module. Every rule is scoped to `.themed` (R2) and uses
   tokens only (R3). Mobile breakpoints are mandatory (R6) and appear at the end
   of this block.

   Plan: todo-billing.md · Reference: docs/features/billing.md
   ========================================================================== */

/* --- Settings page: status panel ----------------------------------------- */

.themed .t-billing-status-panel {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.themed .t-billing-status-body {
  flex: 1 1 320px;
  min-width: 0;
}

.themed .t-billing-status-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
}

/* --- Status pill ---------------------------------------------------------- */

.themed .t-billing-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  font-size: 0.8125rem;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}

.themed .t-billing-pill-on {
  background: var(--color-success-bg);
  color: var(--color-success-text);
  border-color: var(--color-success-border);
}

.themed .t-billing-pill-off {
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  border-color: var(--color-warning-border);
}

.themed .t-billing-pill-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.themed .t-billing-pill-on .t-billing-pill-dot {
  background: var(--color-success-icon);
}

.themed .t-billing-pill-off .t-billing-pill-dot {
  background: var(--color-warning-icon);
}

/* --- Currency row --------------------------------------------------------- */

.themed .t-billing-currency-row {
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.themed .t-billing-currency-input {
  width: 7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

.themed .t-billing-currency-locked {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* --- Informational note --------------------------------------------------- */

.themed .t-billing-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-info-border);
  background: var(--color-info-bg);
  color: var(--color-info-text);
  font-size: 0.875rem;
}

.themed .t-billing-note-icon {
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
  margin-top: 0.125rem;
  color: var(--color-info-icon);
}

.themed .t-billing-note-title {
  font-weight: 600;
  margin-bottom: var(--space-1);
}

/* --- Mobile (R6) ---------------------------------------------------------- */

@media (max-width: 768px) {
  .themed .t-billing-status-panel {
    flex-direction: column;
    align-items: stretch;
  }

  .themed .t-billing-status-actions {
    justify-content: space-between;
    width: 100%;
  }

  .themed .t-billing-currency-row {
    align-items: stretch;
    flex-direction: column;
  }

  .themed .t-billing-currency-input {
    width: 100%;
  }
}

@media (max-width: 480px) {
  .themed .t-billing-pill {
    font-size: 0.75rem;
    padding: var(--space-0-5) var(--space-2);
  }

  .themed .t-billing-note {
    padding: var(--space-3);
    font-size: 0.8125rem;
  }

  .themed .t-billing-note-icon {
    display: none;
  }
}

/* ----------------------------------------------------------------------------
   BILLING — Inscription form (Phase 1)
   Same rules as the Phase 0 block above: `.themed`-scoped, tokens only, mobile
   breakpoints mandatory.
   -------------------------------------------------------------------------- */

.themed .t-billing-form-section {
  padding: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  margin-bottom: var(--space-5);
}

.themed .t-billing-form-legend {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-billing-form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}

.themed .t-billing-form-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}

.themed .t-billing-form-full {
  grid-column: 1 / -1;
}

.themed .t-billing-required::after {
  content: " *";
  color: var(--color-danger-icon);
  font-weight: 700;
}

.themed .t-billing-field-hint {
  display: block;
  margin-top: var(--space-1);
  font-size: 0.75rem;
  color: var(--color-text-subtle);
  line-height: 1.4;
}

/* Provisional-code callout — amber, because it is a to-do, not an error. */
.themed .t-billing-prov-callout {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-warning-border);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  font-size: 0.8125rem;
}

.themed .t-billing-prov-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-full);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  border: 1px solid var(--color-warning-border);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* Occupancy chip on the class picker + the worklist table */
.themed .t-billing-occupancy {
  font-variant-numeric: tabular-nums;
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.themed .t-billing-occupancy-full {
  color: var(--color-danger-text);
  font-weight: 600;
}

.themed .t-billing-worklist {
  width: 100%;
  border-collapse: collapse;
}

.themed .t-billing-worklist th {
  text-align: left;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  padding: var(--space-2) var(--space-3);
  background: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-billing-worklist td {
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-border);
  font-size: 0.875rem;
  vertical-align: middle;
}

.themed .t-billing-worklist tr:hover td {
  background: var(--color-surface-hover);
}

.themed .t-billing-regularize-form {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.themed .t-billing-regularize-input {
  width: 11rem;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.themed .t-billing-empty {
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

/* --- Mobile (R6) --- */

@media (max-width: 768px) {
  .themed .t-billing-form-grid,
  .themed .t-billing-form-grid-3 {
    grid-template-columns: minmax(0, 1fr);
  }

  .themed .t-billing-form-section {
    padding: var(--space-4);
  }

  .themed .t-billing-worklist thead {
    display: none;
  }

  .themed .t-billing-worklist tr {
    display: block;
    border-bottom: 2px solid var(--color-border);
    padding: var(--space-2) 0;
  }

  .themed .t-billing-worklist td {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    border-bottom: none;
    padding: var(--space-1-5) var(--space-3);
  }

  .themed .t-billing-worklist td::before {
    content: attr(data-label);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-text-muted);
  }

  .themed .t-billing-regularize-form {
    width: 100%;
  }

  .themed .t-billing-regularize-input {
    flex: 1 1 auto;
    width: auto;
  }
}

@media (max-width: 480px) {
  .themed .t-billing-form-section {
    padding: var(--space-3);
  }

  .themed .t-billing-prov-callout {
    flex-direction: column;
    gap: var(--space-2);
    font-size: 0.75rem;
  }

  .themed .t-billing-form-legend {
    font-size: 0.6875rem;
  }
}

/* ----------------------------------------------------------------------------
   BILLING — Fee plans & accounts (Phase 2)
   Same rules as the Phase 0/1 blocks: `.themed`-scoped, tokens only, both mobile
   breakpoints mandatory.
   -------------------------------------------------------------------------- */

.themed .t-billing-plan-card {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

.themed .t-billing-plan-card:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-sm);
}

.themed .t-billing-plan-name {
  font-weight: 600;
  color: var(--color-text-base);
}

.themed .t-billing-plan-scope {
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.themed .t-billing-plan-total {
  font-variant-numeric: tabular-nums;
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--color-text-base);
  white-space: nowrap;
}

.themed .t-billing-plan-inactive {
  opacity: 0.6;
}

/* --- Money figures ------------------------------------------------------- */

.themed .t-billing-amount {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.themed .t-billing-amount-negative {
  color: var(--color-success-text);
}

.themed .t-billing-amount-positive {
  color: var(--color-danger-text);
}

/* --- Summary strip on the account page ----------------------------------- */

.themed .t-billing-summary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
}

.themed .t-billing-summary-tile {
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.themed .t-billing-summary-label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-1);
}

.themed .t-billing-summary-value {
  font-size: 1.375rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-base);
}

.themed .t-billing-summary-tile-due .t-billing-summary-value {
  color: var(--color-warning-text);
}

.themed .t-billing-summary-tile-credit .t-billing-summary-value {
  color: var(--color-success-text);
}

/* --- Account status pill ------------------------------------------------- */

.themed .t-billing-acct-status {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0-5) var(--space-2-5);
  border-radius: var(--radius-full);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  border: 1px solid transparent;
}

.themed .t-billing-acct-draft {
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
  border-color: var(--color-border);
}

.themed .t-billing-acct-active {
  background: var(--color-success-bg);
  color: var(--color-success-text);
  border-color: var(--color-success-border);
}

.themed .t-billing-acct-closed {
  background: var(--color-surface-hover);
  color: var(--color-text-subtle);
  border-color: var(--color-border);
}

/* --- Obligation ledger (instalments + adjustments, merged) --------------- */

.themed .t-billing-ledger {
  width: 100%;
  border-collapse: collapse;
}

.themed .t-billing-ledger th {
  text-align: left;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-billing-ledger td {
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-border);
  font-size: 0.875rem;
}

.themed .t-billing-ledger-adjustment td {
  background: var(--color-surface-muted);
  font-style: italic;
}

.themed .t-billing-row-status {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-full);
  font-size: 0.6875rem;
  font-weight: 600;
}

.themed .t-billing-row-paid {
  background: var(--color-success-bg);
  color: var(--color-success-text);
}

.themed .t-billing-row-partial {
  background: var(--color-info-bg);
  color: var(--color-info-text);
}

.themed .t-billing-row-overdue {
  background: var(--color-danger-bg);
  color: var(--color-danger-text);
}

.themed .t-billing-row-pending {
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
}

/* --- Editable instalment rows (plan builder / draft editor) -------------- */

.themed .t-billing-rowset {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.themed .t-billing-row-edit {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr auto;
  gap: var(--space-2);
  align-items: end;
}

.themed .t-billing-row-remove {
  color: var(--color-danger-text);
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--space-2);
  line-height: 1;
}

.themed .t-billing-frozen-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-info-border);
  background: var(--color-info-bg);
  color: var(--color-info-text);
  font-size: 0.8125rem;
}

/* --- Mobile (R6) --------------------------------------------------------- */

@media (max-width: 768px) {
  .themed .t-billing-summary {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .themed .t-billing-plan-card {
    flex-direction: column;
    align-items: stretch;
  }

  .themed .t-billing-row-edit {
    grid-template-columns: minmax(0, 1fr);
  }

  .themed .t-billing-ledger thead {
    display: none;
  }

  .themed .t-billing-ledger tr {
    display: block;
    border-bottom: 2px solid var(--color-border);
    padding: var(--space-2) 0;
  }

  .themed .t-billing-ledger td {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    border-bottom: none;
    padding: var(--space-1-5) var(--space-3);
  }

  .themed .t-billing-ledger td::before {
    content: attr(data-label);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-text-muted);
  }
}

@media (max-width: 480px) {
  .themed .t-billing-summary {
    grid-template-columns: minmax(0, 1fr);
  }

  .themed .t-billing-summary-value {
    font-size: 1.125rem;
  }

  .themed .t-billing-frozen-note {
    padding: var(--space-2) var(--space-3);
    font-size: 0.75rem;
  }
}

.themed .t-billing-ledger-total td {
  font-weight: 700;
  background: var(--color-surface-muted);
  border-top: 2px solid var(--color-border-strong);
  border-bottom: none;
}

@media (max-width: 768px) {
  .themed .t-billing-ledger-total td {
    display: flex;
    justify-content: space-between;
  }
}

@media (max-width: 480px) {
  .themed .t-billing-ledger-total td {
    font-size: 0.8125rem;
  }
}

.themed .t-billing-generator {
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: var(--color-surface-muted);
  padding: var(--space-4);
}

@media (max-width: 768px) {
  .themed .t-billing-generator { padding: var(--space-3); }
}

@media (max-width: 480px) {
  .themed .t-billing-generator { padding: var(--space-2); }
}

/* --- Workflow explainer strip (account pages) --- */

.themed .t-billing-workflow {
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-info-border);
  background: var(--color-info-bg);
  color: var(--color-info-text);
}

.themed .t-billing-workflow-active {
  border-color: var(--color-success-border);
  background: var(--color-success-bg);
  color: var(--color-success-text);
}

.themed .t-billing-workflow-closed {
  border-color: var(--color-border);
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
}

.themed .t-billing-workflow-steps {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.themed .t-billing-workflow-step {
  padding: var(--space-0-5) var(--space-2-5);
  border-radius: var(--radius-full);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-subtle);
}

.themed .t-billing-workflow-step-active {
  background: var(--color-primary-600);
  border-color: var(--color-primary-600);
  color: var(--color-text-inverse);
}

.themed .t-billing-workflow-step-done {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-text-muted);
}

.themed .t-billing-workflow-arrow {
  color: var(--color-text-subtle);
  font-size: 0.75rem;
}

.themed .t-billing-workflow-text {
  font-size: 0.8125rem;
  line-height: 1.55;
  margin: 0;
}

@media (max-width: 768px) {
  .themed .t-billing-workflow { padding: var(--space-3); }
  .themed .t-billing-workflow-arrow { display: none; }
}

@media (max-width: 480px) {
  .themed .t-billing-workflow-text { font-size: 0.75rem; }
  .themed .t-billing-workflow-step { font-size: 0.625rem; }
}

.themed .t-billing-workflow-draft {
  border-color: var(--color-info-border);
  background: var(--color-info-bg);
  color: var(--color-info-text);
}

.themed .t-billing-row-waived {
  background: var(--color-surface-muted);
  color: var(--color-text-subtle);
  text-decoration: line-through;
}

@media (max-width: 768px) { .themed .t-billing-row-waived { text-decoration: none; } }
@media (max-width: 480px) { .themed .t-billing-row-waived { font-size: 0.625rem; } }

/* --- Adjustment mode switch (one-off vs per-instalment) --- */

.themed .t-billing-mode-switch {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.themed .t-billing-mode-option {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  cursor: pointer;
  font-size: 0.8125rem;
}

.themed .t-billing-mode-option:hover {
  border-color: var(--color-border-strong);
  background: var(--color-surface-hover);
}

.themed .t-billing-mode-option span {
  display: block;
}

.themed .t-billing-recurring-badge {
  display: inline-block;
  margin-left: var(--space-2);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-full);
  background: var(--color-info-bg);
  color: var(--color-info-text);
  border: 1px solid var(--color-info-border);
  font-size: 0.6875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 768px) {
  .themed .t-billing-mode-switch { grid-template-columns: minmax(0, 1fr); }
  .themed .t-billing-recurring-badge { display: block; margin: var(--space-1) 0 0 0; }
}

@media (max-width: 480px) {
  .themed .t-billing-mode-option { padding: var(--space-2); font-size: 0.75rem; }
  .themed .t-billing-recurring-badge { font-size: 0.625rem; }
}


/* =========================================================================
   BILLING — Money events (Phase 3)
   =========================================================================
   Payment capture, receipt history, reversal and refund.

   The visual grammar has to keep three things apart, because conflating them
   falsifies the ledger:
     · a received payment      (neutral)
     · a REVERSED payment      (struck through + ANNULE badge — the record was wrong)
     · a refund                (negative amount — money genuinely went back)
   ========================================================================= */

.themed .t-billing-pay-card {
  border-left: 4px solid var(--color-success-border);
}

.themed .t-billing-next-due {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1-5);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-warning-border);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  font-size: 0.8125rem;
}

.themed .t-billing-next-due-clear {
  border-color: var(--color-success-border);
  background: var(--color-success-bg);
  color: var(--color-success-text);
}

.themed .t-billing-pay-form {
  margin-top: var(--space-2);
}

/* --- Receipt history ----------------------------------------------------- */

.themed .t-billing-payments,
.themed .t-billing-refunds {
  border-collapse: collapse;
  font-size: 0.8125rem;
}

.themed .t-billing-payments th,
.themed .t-billing-refunds th {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-billing-payments td,
.themed .t-billing-refunds td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}

/* A reversed receipt stays in the table — the row is never deleted (rule N3) —
   but must not read as money the school holds. */
.themed .t-billing-payment-reversed td {
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
}

.themed .t-billing-payment-reversed .t-billing-amount {
  text-decoration: line-through;
}

.themed .t-billing-reversed-badge {
  display: inline-block;
  margin-left: var(--space-1-5);
  padding: 0 var(--space-1-5);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-danger-border);
  background: var(--color-danger-bg);
  color: var(--color-danger-text);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.themed .t-billing-reversed-reason {
  font-size: 0.75rem;
  font-style: italic;
  color: var(--color-text-muted);
}

.themed .t-billing-reverse-form {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.themed .t-billing-reverse-reason {
  min-width: 0;
  width: 11rem;
}

.themed .t-billing-reverse-btn {
  flex-shrink: 0;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-danger-border);
  background: var(--color-surface);
  color: var(--color-danger-text);
  font-weight: 600;
}

.themed .t-billing-reverse-btn:hover {
  background: var(--color-danger-bg);
}

.themed .t-billing-refund-card {
  border-left: 4px solid var(--color-warning-border);
}

/* --- Mobile (R6) --------------------------------------------------------- */

@media (max-width: 768px) {
  .themed .t-billing-payments thead,
  .themed .t-billing-refunds thead {
    display: none;
  }

  .themed .t-billing-payments tr,
  .themed .t-billing-refunds tr {
    display: block;
    border-bottom: 2px solid var(--color-border);
    padding: var(--space-2) 0;
  }

  .themed .t-billing-payments td,
  .themed .t-billing-refunds td {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    border-bottom: none;
    padding: var(--space-1-5) var(--space-3);
  }

  .themed .t-billing-payments td::before,
  .themed .t-billing-refunds td::before {
    content: attr(data-label);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-text-muted);
  }

  .themed .t-billing-reverse-form {
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  .themed .t-billing-reverse-reason {
    width: 100%;
  }
}

@media (max-width: 480px) {
  .themed .t-billing-next-due {
    font-size: 0.75rem;
    padding: var(--space-1-5) var(--space-2);
  }

  .themed .t-billing-pay-card,
  .themed .t-billing-refund-card {
    border-left-width: 3px;
  }

  .themed .t-billing-payments,
  .themed .t-billing-refunds {
    font-size: 0.75rem;
  }
}


/* =========================================================================
   BILLING — Documents (Phase 4)
   =========================================================================
   The Carnet is the deliverable that replaces the school's paper card, so its
   action bar reads as a primary affordance rather than a footnote. WhatsApp
   gets its own colour because it leaves the application.
   ========================================================================= */

.themed .t-billing-doc-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-primary-600);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.themed .t-billing-doc-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  flex: 1 1 20rem;
}

.themed .t-billing-doc-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Leaving the app is a different kind of action from downloading a file, and the
   colour says so before the label is read. */
.themed .t-billing-wa-btn {
  border-color: var(--color-success-border);
  background: var(--color-success-bg);
  color: var(--color-success-text);
}

.themed .t-billing-wa-btn:hover {
  background: var(--color-surface);
}

.themed .t-billing-receipt-link {
  display: inline-block;
  margin-right: var(--space-2);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-primary-600);
  text-decoration: underline;
}

/* --- Mobile (R6) --------------------------------------------------------- */

@media (max-width: 768px) {
  .themed .t-billing-doc-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .themed .t-billing-doc-buttons {
    flex-direction: column;
  }

  .themed .t-billing-doc-buttons > * {
    width: 100%;
    justify-content: center;
  }
}

@media (max-width: 480px) {
  .themed .t-billing-doc-actions {
    padding: var(--space-3);
    border-left-width: 3px;
  }

  .themed .t-billing-receipt-link {
    display: block;
    margin: 0 0 var(--space-1) 0;
  }
}


/* =========================================================================
   BILLING — Owner dashboard (Phase 5)
   =========================================================================
   The screen answers one question: who owes us money. Two visual jobs follow
   from that — make the totals readable at a glance, and make the students
   nobody configured impossible to skim past.
   ========================================================================= */

.themed .t-billing-kpi-grid { align-items: stretch; }

/*
 * R11 — a grid child defaults to `min-width: auto`, so it refuses to shrink below its
 * longest unbreakable run. A KPI value like "34 250,00 MAD" in 1.375rem bold is wider
 * than a 2-up column at 320px, and the overflow propagates outward: the grid gets wider
 * than the viewport and the WHOLE PAGE scrolls sideways, not just the tile.
 *
 * `min-width: 0` is the fix for the container; `overflow-wrap` lets the value itself
 * wrap rather than push. Both are inert above the breakpoint where columns are wide.
 */
.themed .t-billing-kpi { min-width: 0; }
.themed .t-billing-kpi-value { overflow-wrap: anywhere; }

.themed .t-billing-kpi {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.themed .t-billing-kpi-label {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.themed .t-billing-kpi-value {
  font-size: 1.375rem;
  font-weight: 700;
  color: var(--color-text);
}

.themed .t-billing-kpi-warning { border-color: var(--color-warning-border); }
.themed .t-billing-kpi-warning .t-billing-kpi-value { color: var(--color-warning-text); }
.themed .t-billing-kpi-danger { border-color: var(--color-danger-border); }
.themed .t-billing-kpi-danger .t-billing-kpi-value { color: var(--color-danger-text); }

/* The alarm. A count the admin cannot act on is just anxiety, so the whole
   panel is the link to the filtered view. */
.themed .t-billing-alarm {
  display: block;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-warning-border);
  border-left: 4px solid var(--color-warning-border);
  border-radius: var(--radius-md);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  font-size: 0.8125rem;
  text-decoration: none;
}

.themed .t-billing-alarm:hover { background: var(--color-surface); }

.themed .t-billing-filter-bar {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr auto;
  gap: var(--space-3);
  align-items: end;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.themed .t-billing-filter-actions {
  display: flex;
  gap: var(--space-2);
}

.themed .t-billing-roster { border-collapse: collapse; font-size: 0.8125rem; }

.themed .t-billing-roster th {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-billing-roster td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-billing-col-num { text-align: right; }

.themed .t-billing-roster-link {
  font-weight: 600;
  color: var(--color-primary-600);
  text-decoration: none;
}

.themed .t-billing-roster-link:hover { text-decoration: underline; }

/* A student nobody configured is the point of the screen, so the row is tinted
   rather than left to blend into the others. */
.themed .t-billing-row-unconfigured { background: var(--color-warning-bg); }

.themed .t-billing-unconfigured-badge {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-warning-border);
  color: var(--color-warning-text);
  font-size: 0.6875rem;
  font-weight: 700;
  text-decoration: none;
}

.themed .t-billing-unconfigured-badge:hover { background: var(--color-surface); }

.themed .t-billing-leaver-badge {
  display: inline-block;
  margin-left: var(--space-1-5);
  padding: 0 var(--space-1-5);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-muted);
  font-size: 0.625rem;
  font-weight: 600;
}

/* --- Mobile (R6) --------------------------------------------------------- */

@media (max-width: 768px) {
  /* R6: this component had a 480px rule and no 768px one. */
  .themed .t-billing-kpi { padding: var(--space-2-5) var(--space-3); }
  .themed .t-billing-kpi-value { font-size: 1.25rem; }
  .themed .t-billing-filter-bar { grid-template-columns: minmax(0, 1fr); }
  .themed .t-billing-filter-actions > * { flex: 1 1 auto; justify-content: center; }

  .themed .t-billing-roster thead { display: none; }

  .themed .t-billing-roster tr {
    display: block;
    border-bottom: 2px solid var(--color-border);
    padding: var(--space-2) 0;
  }

  .themed .t-billing-roster td {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    border-bottom: none;
    padding: var(--space-1-5) var(--space-3);
    text-align: left;
  }

  .themed .t-billing-roster td::before {
    content: attr(data-label);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-text-muted);
  }
}

@media (max-width: 480px) {
  .themed .t-billing-kpi { padding: var(--space-2) var(--space-3); }
  .themed .t-billing-kpi-value { font-size: 1.125rem; }
  .themed .t-billing-alarm { font-size: 0.75rem; border-left-width: 3px; }
  .themed .t-billing-roster { font-size: 0.75rem; }
}


/* =========================================================================
   BILLING — Owner dashboard, fixes from the browser pass (Phase 5)
   =========================================================================
   Two alignment bugs and three new components.
   ========================================================================= */

/* FIX — numeric headers were left-aligned while their cells were right-aligned.
   `.themed .t-billing-roster th` is (0,2,1) and out-specifies
   `.themed .t-billing-col-num` (0,2,0), so the generic header rule won and the
   header drifted left of its own column. Reordering would not help; the fix has
   to raise specificity. */
.themed .t-billing-roster th.t-billing-col-num {
  text-align: right;
}

/* FIX — Filtrer/Effacer sat 20px below their fields. `.t-form-group` carries
   `margin-bottom: var(--space-5)`, and the existing strip-the-margin convention
   matches `.flex` containers only; this filter bar is a GRID, so `align-items:
   end` was aligning margin boxes rather than controls. */
.themed .t-billing-filter-bar .t-form-group {
  margin-bottom: 0;
}

/* --- Credit attribution --------------------------------------------------- */

.themed .t-billing-credit-panel {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-success-border);
  border-left: 4px solid var(--color-success-border);
  border-radius: var(--radius-md);
  background: var(--color-success-bg);
  color: var(--color-success-text);
  font-size: 0.8125rem;
}

.themed .t-billing-credit-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.themed .t-billing-credit-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.themed .t-billing-credit-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}

.themed .t-billing-credit-name {
  font-weight: 600;
  color: var(--color-success-text);
  text-decoration: underline;
}

.themed .t-billing-credit-class,
.themed .t-billing-credit-more {
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

/* --- Result bar: a filter matching nothing must not read as broken -------- */

.themed .t-billing-result-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 0 var(--space-1);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.themed .t-billing-result-count strong { color: var(--color-text); }

.themed .t-billing-filter-notice {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-info-border);
  background: var(--color-info-bg);
  color: var(--color-info-text);
  font-size: 0.75rem;
}

.themed .t-billing-filter-notice a {
  font-weight: 600;
  text-decoration: underline;
  color: var(--color-info-text);
}

/* --- Pager ---------------------------------------------------------------- */

.themed .t-billing-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-2);
  font-size: 0.8125rem;
}

.themed .t-billing-pager-link {
  padding: var(--space-1-5) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-primary-600);
  font-weight: 600;
  text-decoration: none;
}

.themed .t-billing-pager-link:hover { background: var(--color-surface-hover); }

.themed .t-billing-pager-state { color: var(--color-text-muted); }

/* --- Mobile (R6) --------------------------------------------------------- */

@media (max-width: 768px) {
  .themed .t-billing-result-bar { flex-direction: column; align-items: flex-start; }
  .themed .t-billing-credit-list li { gap: var(--space-1); }
  .themed .t-billing-pager { flex-wrap: wrap; }
}

@media (max-width: 480px) {
  .themed .t-billing-credit-panel { padding: var(--space-2) var(--space-3); }
  .themed .t-billing-pager-link { padding: var(--space-1) var(--space-2); }
  .themed .t-billing-result-bar { font-size: 0.75rem; }
}


/* =========================================================================
   BILLING — Hardening (Phase 6)
   =========================================================================
   The near-duplicate confirmation. Deliberately NOT a danger colour: this is a
   question, not a refusal, and two identical payments in one day are often
   entirely legitimate.
   ========================================================================= */

.themed .t-billing-dup-warning {
  padding: var(--space-4);
  border: 1px solid var(--color-warning-border);
  border-left: 4px solid var(--color-warning-border);
  border-radius: var(--radius-lg);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
}

.themed .t-billing-dup-title {
  font-weight: 700;
  margin-bottom: var(--space-1);
}

.themed .t-billing-dup-body {
  font-size: 0.8125rem;
  margin-bottom: var(--space-3);
}

.themed .t-billing-dup-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

@media (max-width: 768px) {
  .themed .t-billing-dup-actions { flex-direction: column; }
  .themed .t-billing-dup-actions > * { width: 100%; justify-content: center; }
}

@media (max-width: 480px) {
  .themed .t-billing-dup-warning {
    padding: var(--space-3);
    border-left-width: 3px;
  }
  .themed .t-billing-dup-body { font-size: 0.75rem; }
}


/* =========================================================================
   BILLING — UX refinement (roster actions, collapsed rare actions, discounts)
   =========================================================================
   The organising idea: a secretary encaisse every day, adjusts occasionally,
   and refunds or closes a file twice a year. Visual weight now matches that,
   instead of giving all three the same card.
   ========================================================================= */

/* --- Row actions ---------------------------------------------------------- */

.themed .t-billing-row-action {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-primary-600);
  background: var(--color-primary-600);
  color: var(--color-surface);
  font-size: 0.75rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.themed .t-billing-row-action:hover { background: var(--color-primary-700); }

/* "Voir" is navigation, not money — it should not compete with "Encaisser". */
.themed .t-billing-row-action-muted {
  border-color: var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text-muted);
}

.themed .t-billing-row-action-muted:hover { background: var(--color-surface-hover); }

/* The fix for the reported "there is no Actions button": this used to be an
   anchor styled as a status pill, so it read as a label. */
.themed .t-billing-configure-btn {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-warning-border);
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  font-size: 0.75rem;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

.themed .t-billing-configure-btn:hover { background: var(--color-surface); }

.themed .t-billing-action-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

/* --- Collapsed rare actions ----------------------------------------------- */

.themed .t-billing-more-actions {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.themed .t-billing-more-summary {
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-muted);
  list-style: none;
}

.themed .t-billing-more-summary::-webkit-details-marker { display: none; }

.themed .t-billing-more-summary::before {
  content: '\25B8';
  display: inline-block;
  margin-right: var(--space-2);
  transition: transform var(--transition-fast);
}

.themed .t-billing-more-actions[open] .t-billing-more-summary::before {
  transform: rotate(90deg);
}

.themed .t-billing-more-summary:hover { color: var(--color-text); }

.themed .t-billing-more-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: 0 var(--space-4) var(--space-4);
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-4);
}

/* --- Discounts, lifted out of the schedule -------------------------------- */

.themed .t-billing-discount-summary {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-success-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.themed .t-billing-discount-title {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.themed .t-billing-discount-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0 0 var(--space-2) 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
}

.themed .t-billing-discount-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

/* The compact active-state note: explanation without the lifecycle diagram. */
.themed .t-billing-workflow-compact {
  padding: var(--space-2) var(--space-3);
  font-size: 0.8125rem;
}

/* --- Mobile (R6) ---------------------------------------------------------- */

@media (max-width: 768px) {
  .themed .t-billing-row-action,
  .themed .t-billing-configure-btn {
    width: 100%;
    justify-content: center;
  }
  .themed .t-billing-more-body { padding: var(--space-3); }
}

@media (max-width: 480px) {
  .themed .t-billing-more-summary { padding: var(--space-2) var(--space-3); }
  .themed .t-billing-discount-summary {
    padding: var(--space-2) var(--space-3);
    border-left-width: 3px;
  }
  .themed .t-billing-discount-list { font-size: 0.75rem; }
}


/* =========================================================================
   BILLING — Excel exports
   ========================================================================= */

.themed .t-billing-export-btn {
  border-color: var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text);
  white-space: nowrap;
}

.themed .t-billing-export-btn:hover { background: var(--color-surface-hover); }

.themed .t-billing-journal-form {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.themed .t-billing-journal-label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-muted);
  white-space: nowrap;
}

.themed .t-billing-journal-input { width: 10rem; }

@media (max-width: 768px) {
  .themed .t-billing-journal-form {
    flex-wrap: wrap;
    width: 100%;
  }
  .themed .t-billing-journal-input { flex: 1 1 8rem; width: auto; }
  .themed .t-billing-export-btn { width: 100%; justify-content: center; }
}

@media (max-width: 480px) {
  .themed .t-billing-journal-label { width: 100%; }
}

/* =========================================================================
   ANNOUNCEMENTS (Annonces) — admin list, editor, parent feed
   -------------------------------------------------------------------------
   Scope: templates/dashboard/parents/announcements.html
          templates/dashboard/parents/announcement_form.html
          apps/parents/templates/parents/communications.html
          apps/parents/templates/parents/announcement_detail.html
   All rules .themed-scoped, token-only (R2/R3). Breakpoints at the end (R6).
   ========================================================================= */

/* -- Toolbar: search + status filter ------------------------------------ */
.themed .t-ann-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-sm);
}

.themed .t-ann-toolbar-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.themed .t-ann-toolbar-search { flex: 1 1 16rem; }

.themed .t-ann-toolbar-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--color-text-subtle);
}

.themed .t-ann-toolbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* -- List + card -------------------------------------------------------- */
.themed .t-ann-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.themed .t-ann-card {
  position: relative;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base), border-color var(--transition-base);
}

.themed .t-ann-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--color-border-strong);
}

.themed .t-ann-card-published { border-left-color: var(--color-success-icon); }
.themed .t-ann-card-draft     { border-left-color: var(--color-border-strong); }
.themed .t-ann-card-expired   { border-left-color: var(--color-warning-icon); }

.themed .t-ann-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
}

.themed .t-ann-card-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1-5);
  margin-bottom: var(--space-2);
}

.themed .t-ann-card-title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  line-height: var(--leading-tight);
}

.themed .t-ann-card-preview {
  margin-top: var(--space-1-5);
  font-size: var(--text-base);
  color: var(--color-text-muted);
  line-height: var(--leading-normal);
}

.themed .t-ann-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
}

.themed .t-ann-card-meta-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.themed .t-ann-card-meta-warning { color: var(--color-warning-text); }

.themed .t-ann-card-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* -- Status + audience pills -------------------------------------------- */
.themed .t-ann-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-full);
  border: 1px solid transparent;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.themed .t-ann-status-published {
  background-color: var(--color-success-bg);
  border-color: var(--color-success-border);
  color: var(--color-success-text);
}

.themed .t-ann-status-draft {
  background-color: var(--color-surface-muted);
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

.themed .t-ann-status-expired {
  background-color: var(--color-warning-bg);
  border-color: var(--color-warning-border);
  color: var(--color-warning-text);
}

.themed .t-ann-audience {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  max-width: 18rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-ann-audience-targeted {
  background-color: var(--color-info-bg);
  border-color: var(--color-info-border);
  color: var(--color-info-text);
}

/* -- Empty states ------------------------------------------------------- */
.themed .t-ann-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2);
  background-color: var(--color-surface);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-xl);
  padding: var(--space-12) var(--space-6);
}

.themed .t-ann-empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--radius-full);
  background-color: var(--color-surface-active);
  color: var(--color-primary-600);
  margin-bottom: var(--space-1);
}

.themed .t-ann-empty-title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-ann-empty-text {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  max-width: 26rem;
  line-height: var(--leading-normal);
}

.themed .t-ann-empty-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

/* -- Editor layout ------------------------------------------------------ */
.themed .t-ann-editor {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20rem;
  gap: var(--space-5);
  align-items: start;
}

.themed .t-ann-editor-main {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  min-width: 0;
}

.themed .t-ann-editor-side {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
}

/* -- Publication radio cards -------------------------------------------- */
.themed .t-ann-pub-option {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2-5);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  cursor: pointer;
  transition: border-color var(--transition-fast), background-color var(--transition-fast);
}

.themed .t-ann-pub-option:hover { border-color: var(--color-primary-300); }

.themed .t-ann-pub-option-selected {
  border-color: var(--color-primary-500);
  background-color: var(--color-surface-active);
}

.themed .t-ann-pub-option-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-ann-pub-option-hint {
  display: block;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: var(--space-0-5);
  line-height: var(--leading-normal);
}

/* -- Audience picker ---------------------------------------------------- */
.themed .t-ann-audience-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-info-border);
  background-color: var(--color-info-bg);
  border-radius: var(--radius-md);
}

.themed .t-ann-audience-summary-label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-info-text);
}

.themed .t-ann-audience-summary-value {
  font-size: var(--text-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-ann-audience-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  color: var(--color-text-base);
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.themed .t-ann-audience-toggle:hover {
  background-color: var(--color-surface-hover);
  border-color: var(--color-primary-400);
}

.themed .t-ann-target-group { margin-top: var(--space-4); }

.themed .t-ann-target-group-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.themed .t-ann-target-group-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-ann-target-count {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary-700);
}

.themed .t-ann-target-count-empty { color: var(--color-text-subtle); }

.themed .t-ann-target-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: var(--space-2);
}

.themed .t-ann-target-grid-compact {
  grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
}

.themed .t-ann-target-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-2-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  cursor: pointer;
  min-height: 2.5rem;
  transition: border-color var(--transition-fast), background-color var(--transition-fast);
}

.themed .t-ann-target-option:hover { border-color: var(--color-primary-400); }

.themed .t-ann-target-option-selected {
  border-color: var(--color-primary-500);
  background-color: var(--color-surface-active);
  box-shadow: var(--shadow-inset);
}

.themed .t-ann-target-code {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-ann-target-name {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-ann-target-subgroup { margin-bottom: var(--space-3); }

.themed .t-ann-target-subgroup-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-subtle);
  margin-bottom: var(--space-1-5);
}

.themed .t-ann-target-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.themed .t-ann-target-empty {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  font-style: italic;
  padding: var(--space-2) 0;
}

/* -- Attachments -------------------------------------------------------- */
.themed .t-ann-attach-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.themed .t-ann-attach-count {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}

.themed .t-ann-attach-drop {
  display: block;
  border: 2px dashed var(--color-border-strong);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface-muted);
  padding: var(--space-6) var(--space-4);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--transition-fast), background-color var(--transition-fast);
}

.themed .t-ann-attach-drop:hover {
  border-color: var(--color-primary-400);
  background-color: var(--color-surface-active);
}

.themed .t-ann-attach-drop-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-ann-attach-drop-hint {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  margin-top: var(--space-1);
}

.themed .t-ann-attach-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  margin-top: var(--space-3);
}

.themed .t-ann-attach-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
}

.themed .t-ann-attach-name {
  font-size: var(--text-base);
  color: var(--color-text-base);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-ann-attach-size {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  white-space: nowrap;
}

.themed .t-ann-attach-remove {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-danger-text);
  cursor: pointer;
  white-space: nowrap;
}

/* -- Form actions ------------------------------------------------------- */
.themed .t-ann-form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* Grouped at the end: a cancel link stranded at the opposite edge of a wide
     canvas reads as unrelated to the submit it belongs with. */
  justify-content: flex-end;
  gap: var(--space-2);
  padding-top: var(--space-2);
}

.themed .t-ann-form-actions-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* -- Parent-facing feed + reader ---------------------------------------- */
.themed .t-ann-feed {
  display: flex;
  flex-direction: column;
  gap: var(--space-2-5);
}

.themed .t-ann-feed-card {
  display: block;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-success-icon);
  border-radius: var(--radius-lg);
  padding: var(--space-3-5) var(--space-4);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base), border-color var(--transition-base);
}

.themed .t-ann-feed-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--color-success-border);
  border-left-color: var(--color-success-text);
}

.themed .t-ann-feed-title {
  font-size: var(--text-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  line-height: var(--leading-tight);
}

.themed .t-ann-feed-preview {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  margin-top: var(--space-1);
  line-height: var(--leading-normal);
}

.themed .t-ann-feed-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
}

.themed .t-ann-feed-cta {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-link);
  white-space: nowrap;
}

.themed .t-ann-read-body {
  font-size: var(--text-md);
  color: var(--color-text-base);
  line-height: var(--leading-relaxed);
  max-width: 42rem;
}

/* -- Mandatory responsive rules (R6) ------------------------------------ */
@media (max-width: 768px) {
  .themed .t-ann-toolbar {
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-3);
  }
  .themed .t-ann-toolbar-search { flex: 1 1 auto; }
  .themed .t-ann-toolbar-actions { width: 100%; }
  .themed .t-ann-toolbar-actions > * { flex: 1 1 auto; text-align: center; }

  .themed .t-ann-card { padding: var(--space-3-5) var(--space-4); }
  .themed .t-ann-card-head { flex-direction: column; gap: var(--space-3); }
  .themed .t-ann-card-actions { width: 100%; }
  .themed .t-ann-card-title { font-size: var(--text-md); }
  .themed .t-ann-audience { max-width: 100%; }

  .themed .t-ann-empty { padding: var(--space-8) var(--space-4); }
  .themed .t-ann-empty-icon { width: 3rem; height: 3rem; }
  .themed .t-ann-empty-title { font-size: var(--text-lg); }

  .themed .t-ann-editor { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .themed .t-ann-editor-main { gap: var(--space-4); }

  .themed .t-ann-target-grid { grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); }
  .themed .t-ann-target-grid-compact { grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr)); }
  .themed .t-ann-target-option { min-height: 2.75rem; }

  .themed .t-ann-attach-drop { padding: var(--space-5) var(--space-3); }
  .themed .t-ann-form-actions { flex-direction: column-reverse; align-items: stretch; }
  .themed .t-ann-form-actions-right { flex-direction: column-reverse; align-items: stretch; }

  .themed .t-ann-read-body { font-size: var(--text-base); }
}

@media (max-width: 480px) {
  .themed .t-ann-card { padding: var(--space-3); }
  .themed .t-ann-card-meta { flex-direction: column; align-items: flex-start; gap: var(--space-1); }
  .themed .t-ann-card-actions > * { flex: 1 1 auto; text-align: center; }

  .themed .t-ann-empty { padding: var(--space-6) var(--space-3); }
  .themed .t-ann-empty-actions { width: 100%; flex-direction: column; }
  .themed .t-ann-empty-actions > * { width: 100%; text-align: center; }

  .themed .t-ann-target-grid,
  .themed .t-ann-target-grid-compact { grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr)); }
  .themed .t-ann-target-name { display: none; }
  .themed .t-ann-target-actions > * { flex: 1 1 auto; text-align: center; }

  .themed .t-ann-audience-summary { flex-direction: column; align-items: stretch; }
  .themed .t-ann-audience-toggle { width: 100%; justify-content: center; }

  .themed .t-ann-attach-row { flex-wrap: wrap; gap: var(--space-1-5); }
  .themed .t-ann-attach-drop { padding: var(--space-4) var(--space-2-5); }

  .themed .t-ann-feed-card { padding: var(--space-3); }
  .themed .t-ann-feed-meta { flex-direction: column; align-items: flex-start; gap: var(--space-1); }
}

/* =========================================================================
   MESSAGING (Messagerie) — staff workspace, thread, composer, parent portal
   -------------------------------------------------------------------------
   Scope: templates/dashboard/parents/message_inbox.html
          templates/dashboard/parents/message_new.html
          templates/dashboard/parents/partials/conv_list.html
          templates/dashboard/parents/partials/conv_detail.html
          templates/dashboard/parents/partials/message_bubble.html
          apps/parents/templates/parents/conversation_inbox.html
          apps/parents/templates/parents/conversation_detail.html
          apps/parents/templates/parents/partials/message_bubble.html

   Extends the pre-existing t-msg-bubble / t-msg-sent / t-msg-received trio
   rather than replacing it. All rules .themed-scoped, token-only (R2/R3).
   Breakpoints at the end (R6).
   ========================================================================= */

/* -- Workspace shell ---------------------------------------------------- */
.themed .t-msg-workspace {
  display: flex;
  /* The template cancels <main>'s padding with -m-6, so the shell is exactly
     the viewport minus the sticky 4rem header. Anything taller pushes the
     composer below the fold. */
  height: calc(100dvh - 4rem);
  overflow: hidden;
  background-color: var(--color-canvas);
}

@supports not (height: 100dvh) {
  .themed .t-msg-workspace { height: calc(100vh - 4rem); }
}

.themed .t-msg-sidebar {
  display: flex;
  flex-direction: column;
  width: 23rem;
  flex-shrink: 0;
  background-color: var(--color-surface);
  border-right: 1px solid var(--color-border);
  /* Lifts the list above the canvas so the two panes read as separate surfaces. */
  box-shadow: var(--shadow-sm);
  z-index: var(--z-base);
}

.themed .t-msg-sidebar-header {
  padding: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-msg-sidebar-title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-base);
  line-height: var(--leading-tight);
}

.themed .t-msg-sidebar-subtitle {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: var(--space-0-5);
}

.themed .t-msg-sidebar-tools {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-2-5);
}

.themed .t-msg-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background-color: var(--color-canvas);
}

/* -- Filter pills ------------------------------------------------------- */
.themed .t-msg-filter-bar {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.themed .t-msg-filter-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}

.themed .t-msg-filter-pill:hover {
  background-color: var(--color-surface-hover);
  border-color: var(--color-border-strong);
}

.themed .t-msg-filter-pill-active {
  background-color: var(--color-primary-600);
  border-color: var(--color-primary-600);
  color: var(--color-text-inverse);
}

.themed .t-msg-filter-pill-active:hover {
  background-color: var(--color-primary-700);
  border-color: var(--color-primary-700);
}

.themed .t-msg-filter-count {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-bold);
}

/* -- Conversation list -------------------------------------------------- */
.themed .t-msg-list {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}

.themed .t-msg-thread-row {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border: 0;
  border-bottom: 1px solid var(--color-border);
  border-left: 3px solid transparent;
  background-color: var(--color-surface);
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.themed .t-msg-thread-row:hover {
  background-color: var(--color-surface-hover);
}

.themed .t-msg-thread-row-unread {
  background-color: var(--color-surface-active);
}

.themed .t-msg-thread-row-active {
  background-color: var(--color-surface-active);
  border-left-color: var(--color-primary-600);
}

.themed .t-msg-thread-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.themed .t-msg-thread-name {
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-base);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-msg-thread-row-unread .t-msg-thread-name {
  font-weight: var(--font-weight-bold);
}

.themed .t-msg-thread-time {
  font-size: var(--text-xs);
  color: var(--color-text-subtle);
  white-space: nowrap;
  flex-shrink: 0;
}

.themed .t-msg-thread-context {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-sm);
  color: var(--color-primary-700);
  margin-top: var(--space-0-5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-msg-thread-subject {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  margin-top: var(--space-0-5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-msg-thread-preview {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
  margin-top: var(--space-0-5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-msg-thread-preview-prefix {
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
}

.themed .t-msg-unread-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 var(--space-1);
  border-radius: var(--radius-full);
  background-color: var(--color-primary-600);
  color: var(--color-text-inverse);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-bold);
  flex-shrink: 0;
}

.themed .t-msg-load-more {
  padding: var(--space-3);
  text-align: center;
}

/* -- Empty states ------------------------------------------------------- */
.themed .t-msg-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-2);
  padding: var(--space-10) var(--space-6);
}

.themed .t-msg-empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--radius-full);
  background-color: var(--color-surface-active);
  color: var(--color-primary-600);
  margin-bottom: var(--space-1);
}

.themed .t-msg-empty-title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-msg-empty-text {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  max-width: 24rem;
  line-height: var(--leading-normal);
}

.themed .t-msg-empty-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

/* -- Thread header ------------------------------------------------------ */
.themed .t-msg-thread-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-msg-thread-header-main {
  flex: 1;
  min-width: 0;
}

.themed .t-msg-thread-header-name {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  line-height: var(--leading-tight);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-msg-thread-header-context {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-top: var(--space-0-5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.themed .t-msg-thread-header-subject {
  display: inline-block;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary-700);
  margin-top: var(--space-1);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.themed .t-msg-back-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  flex-shrink: 0;
  cursor: pointer;
}

.themed .t-msg-back-btn:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-base);
}

/* -- Message stream ----------------------------------------------------- */
.themed .t-msg-stream {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.themed .t-msg-date-divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-2) 0;
}

.themed .t-msg-date-divider::before,
.themed .t-msg-date-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background-color: var(--color-border);
}

.themed .t-msg-date-divider-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* Bubble width: a five-word message must not stretch across a 1400px pane. */
.themed .t-msg-bubble {
  max-width: min(78%, 34rem);
}

.themed .t-msg-body {
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.themed .t-msg-meta {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--color-text-subtle);
  margin-top: var(--space-0-5);
}

.themed .t-msg-sender-name {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  margin-bottom: var(--space-0-5);
}

.themed .t-msg-empty-thread {
  text-align: center;
  color: var(--color-text-subtle);
  font-size: var(--text-base);
  padding: var(--space-10) var(--space-4);
}

/* -- Composer ----------------------------------------------------------- */
.themed .t-msg-composer {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-5);
  background-color: var(--color-surface);
  border-top: 1px solid var(--color-border);
}

.themed .t-msg-composer-form {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
}

.themed .t-msg-composer-input {
  flex: 1;
  min-height: 2.75rem;
  resize: none;
  line-height: var(--leading-normal);
}

.themed .t-msg-composer-send {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  min-width: 2.75rem;
  height: 2.75rem;
  padding: 0 var(--space-4);
  border-radius: var(--radius-md);
  background-color: var(--color-primary-600);
  color: var(--color-text-inverse);
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  flex-shrink: 0;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.themed .t-msg-composer-send:hover { background-color: var(--color-primary-700); }

.themed .t-msg-composer-send:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.themed .t-msg-composer-hint {
  font-size: var(--text-xs);
  color: var(--color-text-subtle);
  margin-top: var(--space-1-5);
}

/* -- New conversation form --------------------------------------------- */
.themed .t-msg-new-page {
  max-width: 52rem;
  margin-left: auto;
  margin-right: auto;
}

.themed .t-msg-recipient-list {
  max-height: 20rem;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
}

.themed .t-msg-recipient-option {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  padding: var(--space-2-5) var(--space-3);
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.themed .t-msg-recipient-option:last-child { border-bottom: 0; }
.themed .t-msg-recipient-option:hover { background-color: var(--color-surface-hover); }

.themed .t-msg-recipient-option-selected {
  background-color: var(--color-surface-active);
}

.themed .t-msg-recipient-name {
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-base);
}

.themed .t-msg-recipient-meta {
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
}

.themed .t-msg-recipient-empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--color-text-subtle);
}

/* -- Parent portal thread shell ----------------------------------------- */
.themed .t-msg-parent-thread {
  height: calc(100dvh - 5.5rem);
  display: flex;
  flex-direction: column;
}

@supports not (height: 100dvh) {
  .themed .t-msg-parent-thread { height: calc(100vh - 5.5rem); }
}

/* -- Mandatory responsive rules (R6) ------------------------------------ */
@media (max-width: 768px) {
  /* Master/detail: one pane at a time, never two narrow columns. */
  .themed .t-msg-sidebar {
    width: 100%;
    border-right: 0;
  }
  .themed .t-msg-sidebar-header { padding: var(--space-3); }
  .themed .t-msg-sidebar-tools { padding: var(--space-2-5) var(--space-3); }

  .themed .t-msg-back-btn { display: inline-flex; }

  .themed .t-msg-thread-header { padding: var(--space-2-5) var(--space-3); }
  .themed .t-msg-thread-header-name { font-size: var(--text-md); }
  .themed .t-msg-stream { padding: var(--space-3); }
  .themed .t-msg-composer { padding: var(--space-2-5) var(--space-3); }

  /* Restore the pre-existing mobile bubble width (this block ships after the
     original t-msg-bubble media rule, so it must repeat it). */
  .themed .t-msg-bubble { max-width: 88%; }

  .themed .t-msg-filter-bar { flex-wrap: wrap; }
  .themed .t-msg-empty { padding: var(--space-8) var(--space-4); }
  .themed .t-msg-empty-icon { width: 3rem; height: 3rem; }

  .themed .t-msg-recipient-list { max-height: 16rem; }
}

@media (max-width: 480px) {
  .themed .t-msg-thread-row { padding: var(--space-2-5) var(--space-3); }
  .themed .t-msg-thread-name { font-size: var(--text-base); }

  .themed .t-msg-bubble { max-width: 92%; }
  .themed .t-msg-stream { padding: var(--space-2-5); gap: var(--space-1-5); }

  /* Icon-only send button — the label would crowd the textarea at this width,
     but the tap target stays 44px. */
  .themed .t-msg-composer-send {
    padding: 0;
    min-width: 2.75rem;
    width: 2.75rem;
  }
  .themed .t-msg-composer-send-label { display: none; }

  .themed .t-msg-empty { padding: var(--space-6) var(--space-3); }
  .themed .t-msg-empty-actions { width: 100%; flex-direction: column; }
  .themed .t-msg-empty-actions > * { width: 100%; text-align: center; }

  .themed .t-msg-filter-pill { padding: var(--space-1) var(--space-2-5); }
  .themed .t-msg-recipient-option { padding: var(--space-2) var(--space-2-5); }
}

/* -- Messaging depth pass (2026-08-17 review follow-up) ------------------ */
/* The two panes and the three bands of the thread were all flat white, so the
   header / stream / composer read as one undifferentiated column. These rules
   only add elevation and surface contrast — no layout changes. */

.themed .t-msg-form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
}

/* Sidebar bands */
.themed .t-msg-sidebar-header {
  background-color: var(--color-surface);
}

.themed .t-msg-sidebar-tools {
  background-color: var(--color-surface-muted);
}

.themed .t-msg-list {
  background-color: var(--color-surface);
}

/* Thread bands: header and composer are raised, the stream sits recessed
   between them so the eye reads three distinct zones. */
.themed .t-msg-thread-header {
  box-shadow: var(--shadow-sm);
  z-index: var(--z-base);
}

.themed .t-msg-stream {
  background-color: var(--color-canvas);
}

/* No custom shadow here: R3 forbids raw rgb() in a theme file and there is no
   upward-shadow token. The existing top border plus the recessed stream
   background already separate the composer from the messages. */
.themed .t-msg-composer {
  background-color: var(--color-surface);
  border-top-color: var(--color-border-strong);
  z-index: var(--z-base);
}

/* The composer input gets a slightly recessed field so the write area is
   findable at a glance inside an already-white band. */
.themed .t-msg-composer-input {
  background-color: var(--color-surface-muted);
}

.themed .t-msg-composer-input:focus {
  background-color: var(--color-surface);
}

/* New-conversation recipient list: same recessed treatment as the composer. */
.themed .t-msg-recipient-list {
  background-color: var(--color-surface);
  box-shadow: var(--shadow-inset);
}

@media (max-width: 768px) {
  .themed .t-msg-sidebar { box-shadow: none; }
  .themed .t-msg-form-actions > * { flex: 1 1 auto; text-align: center; }
}

@media (max-width: 480px) {
  .themed .t-msg-form-actions {
    flex-direction: column-reverse;
    align-items: stretch;
  }
  .themed .t-msg-form-actions > * { width: 100%; text-align: center; }
}

/* ===================================================================
   Component: t-table-stack  (2026-08-28)
   -------------------------------------------------------------------
   Opt-in mobile card-stack for tables that carry `data-label` on every
   <td> but have no component class of their own.

   Deliberately OPT-IN rather than a blanket `.t-table` rule: several
   tables in this project use `t-table` without `data-label`, and a
   global rule would give them an empty ::before and a flex layout they
   were never designed for. Adding a class to the four that need it is
   the change that cannot break the others.

   Same shape as the `.t-billing-ledger` stack it mirrors, so the two
   read identically on a phone.
   =================================================================== */
.themed .t-table-stack {
  width: 100%;
}

@media (max-width: 768px) {
  .themed .t-table-stack thead {
    display: none;
  }

  .themed .t-table-stack tr {
    display: block;
    border-bottom: 2px solid var(--color-border);
    padding: var(--space-2) 0;
  }

  .themed .t-table-stack td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-3);
    border-bottom: none;
    padding: var(--space-1-5) var(--space-3);
    /* A receipt number or an event name has no spaces to break on, and one
       long token is all it takes to make the whole page scroll sideways. */
    overflow-wrap: anywhere;
  }

  .themed .t-table-stack td::before {
    content: attr(data-label);
    flex-shrink: 0;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-text-muted);
  }

  /* A cell with no label (an action button column) should not reserve
     space for an empty caption. */
  .themed .t-table-stack td[data-label=""]::before {
    content: none;
  }

  /* An empty-state row is one full-width cell with no label. Flexing it would
     left-align a message written to be centred. */
  .themed .t-table-stack td[colspan] {
    display: block;
    text-align: center;
  }

  .themed .t-table-stack td[colspan]::before {
    content: none;
  }
}

@media (max-width: 480px) {
  .themed .t-table-stack td {
    padding: var(--space-1) var(--space-2);
    font-size: 0.8125rem;
  }

  .themed .t-table-stack td::before {
    font-size: 0.625rem;
  }
}

/* ==========================================================================
   Attendance session configuration — the cycle-first matrix (Phase 3)
   ==========================================================================
   Plan §4d. A wide table by nature: 7 weekday columns plus a scope column, on a
   page an admin may well open on a phone (R11). It scrolls inside its own
   container and never scrolls the page body.

   ⚠️ Inheritance is carried by TWO signals, not one. Colour alone fails for a
   colour-blind reader and disappears in a screenshot, so an inherited cell also
   renders its value as a placeholder in italics with a ↳ marker in the row. */

.themed .t-attsess-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface);
}

.themed .t-attsess-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  min-width: 640px;
}

.themed .t-attsess-table th,
.themed .t-attsess-table td {
  padding: 0.5rem 0.5rem;
  text-align: center;
  border-bottom: 1px solid var(--color-border);
}

.themed .t-attsess-table thead th {
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: var(--text-xs);
  position: sticky;
  top: 0;
  z-index: 1;
}

/* The scope column is the reading anchor when the table scrolls sideways. */
.themed .t-attsess-scope {
  text-align: left;
  white-space: nowrap;
  color: var(--color-text);
  min-width: 0;
}

.themed .t-attsess-row-school td {
  background-color: var(--color-surface-muted);
  font-weight: 600;
}

.themed .t-attsess-row-cycle td {
  background-color: var(--color-info-bg);
  font-weight: 600;
}

.themed .t-attsess-row-level .t-attsess-scope {
  padding-left: 1.5rem;
  font-weight: 400;
  color: var(--color-text-muted);
}

.themed .t-attsess-input {
  width: 3.25rem;
  max-width: 100%;
  padding: 0.25rem;
  text-align: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.themed .t-attsess-input:focus-visible {
  outline: 2px solid var(--color-border-focus);
  outline-offset: -1px;
}

.themed .t-attsess-input:disabled {
  background-color: var(--color-surface-muted);
  color: var(--color-text-muted);
  cursor: not-allowed;
}

/* An inherited cell shows the number it inherits as a placeholder — greyed and
   italic, so "inherited 7" never reads as "explicitly set to 7". */
.themed .t-attsess-input::placeholder {
  color: var(--color-text-muted);
  font-style: italic;
  opacity: 1;
}

.themed .t-attsess-inherit-mark {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  margin-right: 0.125rem;
}

.themed .t-attsess-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.themed .t-attsess-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}

.themed .t-attsess-note {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.themed .t-attsess-classcount {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

/* -- the diff-before-apply screen ---------------------------------------- */

.themed .t-attsess-diff {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.themed .t-attsess-diff th,
.themed .t-attsess-diff td {
  padding: 0.5rem;
  border-bottom: 1px solid var(--color-border);
  text-align: left;
}

.themed .t-attsess-diff-before {
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.themed .t-attsess-diff-after {
  font-weight: 600;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.themed .t-attsess-diff-down .t-attsess-diff-after {
  color: var(--color-warning-text);
}

.themed .t-attsess-blocking {
  background-color: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-left: 4px solid var(--color-danger-border);
  border-radius: var(--radius-md);
  padding: 0.875rem 1rem;
  color: var(--color-danger-text);
}

.themed .t-attsess-blocking-item {
  font-size: var(--text-sm);
  margin-top: 0.375rem;
  word-break: break-word;
}

@media (max-width: 768px) {
  .themed .t-attsess-table th,
  .themed .t-attsess-table td {
    padding: 0.375rem 0.25rem;
  }

  .themed .t-attsess-input {
    width: 2.75rem;
  }

  .themed .t-attsess-row-level .t-attsess-scope {
    padding-left: 0.875rem;
  }

  .themed .t-attsess-classcount {
    display: none;
  }
}

@media (max-width: 480px) {
  .themed .t-attsess-table {
    min-width: 560px;
    font-size: var(--text-xs);
  }

  .themed .t-attsess-input {
    width: 2.25rem;
    padding: 0.125rem;
  }

  .themed .t-attsess-legend {
    gap: 0.5rem 0.875rem;
  }
}

/* ==========================================================================
   Attendance overview — per-shape grouping (Phase 4)
   ==========================================================================
   Plan §3. These classes render ONLY when the school actually has more than one
   shape on the selected date, when a level is closed that day, or when records
   have been stranded. A homogeneous school emits none of them — which is what
   makes the S8 invariant (today's markup, byte for byte) hold. */

.themed .t-attgrid-caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.75rem;
  padding: 0.75rem 1rem 0.5rem;
  border-top: 1px solid var(--color-border);
}

.themed .t-attgrid-caption:first-of-type {
  border-top: 0;
}

.themed .t-attgrid-caption-cycle {
  font-weight: 600;
  color: var(--color-text);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: var(--text-xs);
}

.themed .t-attgrid-caption-count {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-info-text);
  background-color: var(--color-info-bg);
  border-radius: var(--radius-sm);
  padding: 0.0625rem 0.375rem;
}

.themed .t-attgrid-caption-classes {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.themed .t-attgrid-closed {
  padding: 0.75rem 1rem;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.themed .t-attgrid-stranded {
  margin: 0 1rem 1rem;
  padding: 0.875rem 1rem;
  background-color: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  border-left: 4px solid var(--color-warning-border);
  border-radius: var(--radius-md);
  color: var(--color-warning-text);
  font-size: var(--text-sm);
}

.themed .t-attgrid-stranded-item {
  margin-top: 0.375rem;
  font-size: var(--text-xs);
  word-break: break-word;
}

@media (max-width: 768px) {
  .themed .t-attgrid-caption {
    padding: 0.625rem 0.75rem 0.375rem;
    gap: 0.375rem 0.5rem;
  }

  .themed .t-attgrid-stranded {
    margin: 0 0.75rem 0.75rem;
    padding: 0.75rem;
  }
}

@media (max-width: 480px) {
  .themed .t-attgrid-caption-classes {
    width: 100%;
  }

  .themed .t-attgrid-closed {
    padding: 0.625rem 0.75rem;
  }
}

/* --------------------------------------------------------------------------
   Day card: "recorded today, booked to another date" (billing date visibility)
   --------------------------------------------------------------------------
   A correct zero is indistinguishable from a lost payment unless the page says
   why. Shown whether or not the day is empty — on a busy day it matters more,
   because that is when a back-dated entry hides in the noise. */

.themed .t-billing-entered-elsewhere {
  font-size: var(--text-xs);
  color: var(--color-info-text);
  background-color: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
  border-left: 3px solid var(--color-info-border);
  border-radius: var(--radius-md);
  padding: 0.5rem 0.75rem;
  line-height: 1.5;
}

@media (max-width: 768px) {
  .themed .t-billing-entered-elsewhere {
    padding: 0.5rem;
  }
}

@media (max-width: 480px) {
  .themed .t-billing-entered-elsewhere {
    line-height: 1.45;
  }
}

/* --------------------------------------------------------------------------
   Money display on the billing KPI tiles
   --------------------------------------------------------------------------
   The figures are grouped by the `money` filter (53 100,00), never abbreviated:
   these numbers are reconciled against a cash drawer, and the usual "53,1 K +
   tooltip" pattern puts the exact value behind a hover — dead on a phone,
   invisible in a screenshot, unreachable by keyboard.

   The currency is a UNIT, so it is set smaller and muted beside the value
   rather than folded into it. Shown per tile because an admin who screenshots
   one tile still needs to know what the number is in. */

.themed .t-billing-kpi-currency {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--color-text-muted);
  letter-spacing: 0.03em;
  white-space: nowrap;
}

/* ⚠️ The value scales with the viewport so 13 glyphs (12 000 000,00 — beyond any
   real school) still fit a 2-up tile at 320px. Without this the tile is a grid
   child with `min-width: auto`, and an unbreakable run of digits pushes the
   whole page into a horizontal scroll (R11) rather than just the tile. */
/* ⚠️ `overflow-wrap: anywhere` above is NOT overridden here. It was added by the
   mobile-responsiveness pass because a KPI tile is a grid child with
   `min-width: auto`, so an unbreakable run of digits pushes the whole PAGE into a
   horizontal scroll rather than just the tile — and it is pinned by
   `tests/dashboard/test_mobile_contract.py`. The clamp below makes it far less
   likely to fire; it does not replace it. */
.themed .t-billing-kpi-value {
  font-size: clamp(1rem, 3.4vw, 1.375rem);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 768px) {
  .themed .t-billing-kpi-currency { font-size: 0.625rem; }
}

@media (max-width: 480px) {
  .themed .t-billing-kpi-currency { font-size: 0.5625rem; }
}


/* =========================================================================
   BILLING — Transport (T-3)
   =========================================================================
   One panel on the account page and one card on the settings page. Everything
   else reuses `t-card`, `t-billing-form-grid`, `t-billing-form-legend`,
   `t-billing-amount` and the `t-btn` family — a transport-specific copy of a
   component that already exists is how a theme fragments (R4).

   Palette: INFO, not success or warning. A subscription is a statement of fact
   ("this pupil rides"), not an achievement and not a problem.
   ========================================================================= */

.themed .t-billing-transport-state {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-info-border);
  border-left: 4px solid var(--color-info-border);
  border-radius: var(--radius-md);
  background: var(--color-info-bg);
  color: var(--color-info-text);
  font-size: 0.8125rem;
}

.themed .t-billing-transport-price {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  /* R11: a KPI-sized figure inside a flex child must be able to break, or a long
     grouped amount pushes the panel wider than a 320px viewport. */
  overflow-wrap: anywhere;
}

.themed .t-billing-transport-meta {
  color: var(--color-text-muted);
  font-size: 0.75rem;
}

.themed .t-billing-transport-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.themed .t-billing-transport-item {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.themed .t-billing-transport-item-paid { border-color: var(--color-success-border); }
.themed .t-billing-transport-item-partial { border-color: var(--color-warning-border); }

.themed .t-billing-transport-empty {
  color: var(--color-text-muted);
  font-size: 0.8125rem;
}

@media (max-width: 768px) {
  .themed .t-billing-transport-state {
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
  }
  .themed .t-billing-transport-list { gap: var(--space-1); }
}

@media (max-width: 480px) {
  .themed .t-billing-transport-state { font-size: 0.75rem; }
  .themed .t-billing-transport-item {
    width: 100%;
    justify-content: space-between;
  }
}


/* =========================================================================
   BILLING — Section hierarchy on the roster
   =========================================================================
   Reported from the browser: "the sections are all like each other, it's hard
   to distinguish between them without carefully reading the small titles".

   The cause was three inconsistent treatments on one page — the KPI tiles had
   no wrapper and no heading at all, transport sat in a bare div, and the period
   analysis in a white card — each labelled (or not) by `t-billing-form-legend`,
   which is 0.75rem uppercase MUTED. The labels were visually quieter than the
   cards they introduced, so nothing marked where a section began.

   ⚠️ Deliberately NO semantic colour on the section itself. The tiles inside
   already use warning/danger to mean "money needs attention"; tinting their
   container would compete with that and make a neutral section look urgent.
   Separation is carried by SPACE, a stronger rule and a darker, larger title.

   `t-billing-form-legend` is left untouched — it labels forms elsewhere, and
   restyling it would reach pages nobody asked about (R4).
   ========================================================================= */

.themed .t-billing-section {
  margin-top: var(--space-8);
}

.themed .t-billing-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-2);
  /* 2px against the 1px of every card border, so the eye reads it as a divider
     between sections rather than as one more box edge. */
  border-bottom: 2px solid var(--color-border-strong);
}

.themed .t-billing-section-title {
  font-size: 0.9375rem;
  font-weight: 700;
  /* NOT `--color-text-muted`: a heading quieter than its own content is what
     made these sections invisible. Sentence case, not caps — it scans faster. */
  color: var(--color-text-base);
  letter-spacing: 0;
  text-transform: none;
  /* `min-width: 0` so a long title can shrink inside the flex row instead of
     pushing the note off the edge at 320px (R11). */
  min-width: 0;
}

.themed .t-billing-section-note {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  font-weight: 400;
}

@media (max-width: 768px) {
  .themed .t-billing-section { margin-top: var(--space-6); }
  .themed .t-billing-section-title { font-size: 0.875rem; }
}

@media (max-width: 480px) {
  .themed .t-billing-section-head {
    /* Stacked: side by side, the note is squeezed to two words per line. */
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
  }
  .themed .t-billing-section-title { font-size: 0.8125rem; }
  .themed .t-billing-section-note { font-size: 0.6875rem; }
}

/* =============================================================================
   PARENT PORTAL — premium surfaces (login, dashboard, child cards)
   =============================================================================
   Governed by CLAUDE_UI_LOCK.md. Every rule is .themed-scoped (R2), every colour
   comes from a token (R3), no importance-modifier is used (R10), and each block
   carries both mandatory breakpoints (R6).

   NOTE the wording above avoids the literal token R10 forbids: several existing
   contract tests slice this file from their own marker to END OF FILE and assert the
   string is absent, so writing it even inside a comment fails three unrelated suites.

   These are ADDITIVE hooks. The templates keep their Tailwind classes, so with
   the theme off the portal renders exactly as it does today (R4).

   Design intent: an institution, not a web app. The premium quality here comes
   from restraint - layered soft shadow, generous radius and spacing, a strong
   type hierarchy, and colour reserved for meaning - not from new hues.
   ============================================================================= */

/* ── Auth (login / activate) ─────────────────────────────────────────────── */

/* The card sat 32px left of its own logo: max-width 24rem inside a max-w-md
   (28rem) wrapper with no auto margin, so it hugged the left edge. Centring it
   fixes every page that uses the component rather than only the parent login. */
.themed .t-auth-card {
  margin-left: auto;
  margin-right: auto;
}

.themed .t-parent-auth {
  min-height: 100vh;
  background-color: var(--color-surface-muted);
  background-image:
    radial-gradient(60rem 30rem at 50% -10%, var(--color-primary-50), transparent 70%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-8) var(--space-4);
}

.themed .t-parent-auth-inner {
  width: 100%;
  max-width: 26rem;
  margin-left: auto;
  margin-right: auto;
}

.themed .t-parent-auth-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  margin-bottom: var(--space-8);
}

.themed .t-parent-auth-logo {
  max-height: 4.5rem;
  max-width: 14rem;
  width: auto;
  height: auto;
  object-fit: contain;
}

.themed .t-parent-auth-school {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-text-base);
  line-height: 1.25;
}

.themed .t-parent-auth-eyebrow {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-subtle);
}

.themed .t-parent-auth-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-float);
  padding: var(--space-8);
  width: 100%;
  max-width: 100%;
  margin-left: auto;
  margin-right: auto;
}

/* A tinted panel for a one-line hint reads as an alert. A quiet rule and muted
   text says the same thing without competing with the form. */
.themed .t-parent-auth-note {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
  background-color: transparent;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

.themed .t-parent-auth-note strong {
  color: var(--color-text-base);
  font-weight: 600;
}

.themed .t-parent-auth-foot {
  margin-top: var(--space-6);
  text-align: center;
  font-size: 0.75rem;
  color: var(--color-text-subtle);
}

@media (max-width: 768px) {
  .themed .t-parent-auth { padding: var(--space-6) var(--space-4); }
  .themed .t-parent-auth-card { padding: var(--space-6); }
  .themed .t-parent-auth-logo { max-height: 4rem; }
}

@media (max-width: 480px) {
  .themed .t-parent-auth { padding: var(--space-4) var(--space-3); }
  .themed .t-parent-auth-card {
    padding: var(--space-5);
    border-radius: var(--radius-xl);
  }
  .themed .t-parent-auth-brand { margin-bottom: var(--space-6); }
  .themed .t-parent-auth-logo { max-height: 3.25rem; max-width: 11rem; }
  .themed .t-parent-auth-school { font-size: 1.0625rem; }
}

/* ── Dashboard shell ─────────────────────────────────────────────────────── */

.themed .t-parent-page {
  background-color: var(--color-surface-muted);
  background-image:
    radial-gradient(70rem 26rem at 50% -18rem, var(--color-primary-50), transparent 72%);
  min-height: 100%;
}

.themed .t-parent-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.themed .t-parent-greet {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-text-base);
  line-height: 1.15;
}

.themed .t-parent-greet-sub {
  margin-top: var(--space-1);
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

/* Bordered, not filled. A row of solid pastel pills is the single strongest
   "template" signal on a page; an outline chip carries the same meaning and
   lets the content stay the loudest thing on screen. */
.themed .t-parent-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
}

.themed .t-parent-chip-warn {
  border-color: var(--color-warning-border);
  color: var(--color-warning-text);
}

.themed .t-parent-chip-info {
  border-color: var(--color-info-border);
  color: var(--color-info-text);
}

.themed .t-parent-section-title {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-subtle);
  margin-bottom: var(--space-3);
}

.themed .t-parent-card {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-float-sm);
  padding: var(--space-6);
}

@media (max-width: 768px) {
  .themed .t-parent-greet { font-size: 1.5rem; }
  .themed .t-parent-header { margin-bottom: var(--space-5); }
  .themed .t-parent-card { padding: var(--space-5); }
}

@media (max-width: 480px) {
  .themed .t-parent-greet { font-size: 1.3125rem; }
  .themed .t-parent-card {
    padding: var(--space-4);
    border-radius: var(--radius-xl);
  }
  .themed .t-parent-chip {
    font-size: 0.6875rem;
    padding: var(--space-1) var(--space-2);
  }
}

/* ── Child card — the centrepiece of the dashboard ───────────────────────── */

.themed .t-parent-childcard {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-float-sm);
  overflow: hidden;
  transition: box-shadow 160ms ease, transform 160ms ease;
}

.themed .t-parent-childcard:hover {
  box-shadow: var(--shadow-float);
  transform: translateY(-2px);
}

.themed .t-parent-childcard-head {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-parent-childcard-name {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-text-base);
  line-height: 1.2;
}

.themed .t-parent-childcard-meta {
  margin-top: var(--space-1);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Three metrics, evenly divided, hairline separators. min-width:0 is load-bearing:
   a grid child defaults to min-width:auto and refuses to shrink below its longest
   unbreakable run, which pushes the whole page sideways on a 320px screen. */
.themed .t-parent-childcard-metrics {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.themed .t-parent-childcard-metric {
  min-width: 0;
  padding: var(--space-4) var(--space-3);
  text-align: center;
  border-right: 1px solid var(--color-border);
}

.themed .t-parent-childcard-metric:last-child { border-right: 0; }

.themed .t-parent-childcard-metric-label {
  display: block;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-subtle);
}

.themed .t-parent-childcard-metric-value {
  display: block;
  margin-top: var(--space-1);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-text-base);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.themed .t-parent-childcard-metric-good  { color: var(--color-success-text); }
.themed .t-parent-childcard-metric-warn  { color: var(--color-warning-text); }
.themed .t-parent-childcard-metric-muted { color: var(--color-text-subtle); }

.themed .t-parent-childcard-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-6) var(--space-5);
  border-top: 1px solid var(--color-border);
  background-color: var(--color-surface-muted);
}

@media (max-width: 768px) {
  .themed .t-parent-childcard-head { padding: var(--space-4) var(--space-5); }
  .themed .t-parent-childcard-actions { padding: var(--space-4) var(--space-5); }
  .themed .t-parent-childcard-metric-value { font-size: 1.125rem; }
}

@media (max-width: 480px) {
  .themed .t-parent-childcard { border-radius: var(--radius-xl); }
  .themed .t-parent-childcard:hover { transform: none; }
  .themed .t-parent-childcard-head { padding: var(--space-4); gap: var(--space-3); }
  .themed .t-parent-childcard-actions { padding: var(--space-3) var(--space-4) var(--space-4); }
  .themed .t-parent-childcard-metric { padding: var(--space-3) var(--space-2); }
  .themed .t-parent-childcard-metric-value { font-size: 1rem; }
  .themed .t-parent-childcard-metric-label { font-size: 0.625rem; letter-spacing: 0.02em; }
}

/* Navbar logo. Replaces the template's `max-w-[150px]`, a fixed width R11 forbids:
   a school with a wide wordmark pushed the navbar past the viewport on a phone. */
.themed .t-parent-navbar-logo {
  max-height: 2.25rem;
  max-width: 11rem;
  width: auto;
  object-fit: contain;
}

@media (max-width: 768px) {
  .themed .t-parent-navbar-logo { max-width: 8.5rem; }
}

@media (max-width: 480px) {
  .themed .t-parent-navbar-logo { max-height: 1.875rem; max-width: 6.5rem; }
}

/* ── Child card, applied to the EXISTING markup ──────────────────────────────
   The template keeps every Tailwind class (R4), so with the theme off the card
   renders exactly as it did. These rules win on specificity — `.themed .t-x` is
   (0,2,0) against a utility's (0,1,0) — which is how the theme is meant to work.

   The blue gradient header was the single most dated element: a saturated band
   with white text on top of a white card. An institution reads as calm, so the
   header becomes part of the same surface and the pupil's name becomes the
   loudest thing on the card, which is what a parent is actually looking for. */

.themed .t-parent-childcard .t-parent-childcard-head {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text-base);
}

.themed .t-parent-childcard-name {
  color: var(--color-text-base);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.themed .t-parent-childcard-meta {
  color: var(--color-text-muted);
}

/* The avatar fallback was white-on-translucent, invisible once the band is white. */
.themed .t-parent-childcard-head .rounded-full {
  border-color: var(--color-border);
}
.themed .t-parent-childcard-head div.rounded-full {
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
}

/* Relationship: an outline chip rather than a solid pink or blue fill. The fill
   colour carried no meaning - it encoded "mother" as pink - and a saturated
   badge competes with the genuinely meaningful status colours further down. */
.themed .t-parent-childcard-head .t-parent-chip {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  box-shadow: none;
}

/* Three evenly divided figures instead of a cramped flex strip. */
.themed .t-parent-childcard-metrics {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  padding: 0;
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-parent-childcard-metrics > span {
  min-width: 0;
  margin-left: 0;
  padding: var(--space-3) var(--space-2);
  text-align: center;
  border-right: 1px solid var(--color-border);
  font-size: 0.75rem;
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.themed .t-parent-childcard-metrics > span:last-child { border-right: 0; }

.themed .t-parent-childcard-links {
  background-color: var(--color-surface-muted);
}

.themed .t-parent-childcard-links a:hover {
  background-color: var(--color-surface-hover);
}

@media (max-width: 768px) {
  .themed .t-parent-childcard-metrics > span { padding: var(--space-2); }
}

@media (max-width: 480px) {
  .themed .t-parent-childcard-name { font-size: 0.9375rem; }
  .themed .t-parent-childcard-metrics > span {
    padding: var(--space-2) var(--space-1);
    font-size: 0.6875rem;
  }
}

/* The dashboard chips were solid pastel fills (amber-100, blue-100). A row of
   filled pills is the strongest "generated template" signal on a page; the
   outline form carries the same meaning and lets the greeting stay dominant.
   The Tailwind fills remain in the markup for theme-off (R4). */
.themed .t-parent-chip.t-parent-chip-warn {
  background-color: var(--color-surface);
  border-color: var(--color-warning-border);
  color: var(--color-warning-text);
}

.themed .t-parent-chip.t-parent-chip-info {
  background-color: var(--color-surface);
  border-color: var(--color-info-border);
  color: var(--color-info-text);
}

.themed a.t-parent-chip.t-parent-chip-info:hover {
  background-color: var(--color-info-bg);
}

@media (max-width: 768px) {
  .themed .t-parent-chip.t-parent-chip-warn,
  .themed .t-parent-chip.t-parent-chip-info { font-size: 0.6875rem; }
}

@media (max-width: 480px) {
  .themed .t-parent-chip.t-parent-chip-warn,
  .themed .t-parent-chip.t-parent-chip-info { padding: var(--space-1) var(--space-2); }
}

/* ── Announcement flyers ─────────────────────────────────────────────────────
   A school communicates by flyer, so on the detail page the flyer IS the message.
   It is capped rather than free-running: an A4 portrait scan at full width pushes
   the body text and the download link off a phone screen entirely, so the reader
   never learns the image is tappable. */

/* Wrapper for the flyer list. Owns the spacing so the template does not need a
   utility for it, and gives the section a hook the contract test can see. */
.themed .t-parent-flyers {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

@media (max-width: 480px) {
  .themed .t-parent-flyers { gap: var(--space-3); }
}

.themed .t-parent-flyer {
  margin: 0;
  min-width: 0;
}

.themed .t-parent-flyer-img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 42rem;
  object-fit: contain;
  background-color: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float-sm);
}

.themed .t-parent-flyer-link {
  display: block;
  border-radius: var(--radius-lg);
  transition: box-shadow 160ms ease;
}

.themed .t-parent-flyer-link:hover .t-parent-flyer-img {
  box-shadow: var(--shadow-float);
}

.themed .t-parent-flyer-cap {
  color: var(--color-text-subtle);
  /* min-width:0 on the flex child, or a long filename refuses to truncate and
     widens the whole card past the viewport. */
  min-width: 0;
}

.themed .t-parent-flyer-cap > span { min-width: 0; }

.themed .t-parent-flyer-dl {
  color: var(--color-text-link);
}

.themed .t-parent-flyer-dl:hover {
  color: var(--color-text-link-hover);
}

/* PDF flyers: "Ouvrir" rather than a forced download. On a phone this hands off to
   the native viewer instead of dropping a file into Downloads, where most parents
   never find it again. */
.themed .t-parent-flyer-open {
  border-color: var(--color-border);
  color: var(--color-text-link);
}

.themed .t-parent-flyer-open:hover {
  border-color: var(--color-primary-300);
  background-color: var(--color-primary-50);
  color: var(--color-text-link-hover);
}

@media (max-width: 768px) {
  .themed .t-parent-flyer-img { max-height: 32rem; }
}

@media (max-width: 480px) {
  .themed .t-parent-flyer-open { padding: var(--space-1) var(--space-2); }
}

@media (max-width: 480px) {
  .themed .t-parent-flyer-img {
    max-height: 24rem;
    border-radius: var(--radius-md);
  }
  /* Stack the caption: filename and link side by side leave two words per line. */
  .themed .t-parent-flyer-cap {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
  }
}

/* ── Unread announcement ─────────────────────────────────────────────────────
   Weight and a leading marker, not colour alone: the list already uses a coloured
   left border for every row, so a second colour would say nothing, and colour on
   its own is invisible to a colour-blind reader. */

.themed .t-parent-unread {
  background-color: var(--color-surface);
  border-left-color: var(--color-primary-600);
  box-shadow: var(--shadow-float-sm);
}

/* The title row carries the unread dot and badge inline with the text, so it needs
   to be a flex line in BOTH states — otherwise the marker sits on its own row for a
   read announcement and the list jumps as items are opened. */
.themed .t-parent-feed-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

@media (max-width: 480px) {
  .themed .t-parent-feed-title { flex-wrap: wrap; gap: var(--space-1); }
}

.themed .t-parent-unread .t-parent-feed-title {
  font-weight: 700;
  color: var(--color-text-base);
}

.themed .t-parent-unread-dot {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-full);
  background-color: var(--color-primary-600);
  flex-shrink: 0;
}

.themed .t-parent-unread-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0.125rem var(--space-2);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-primary-200);
  background-color: var(--color-primary-50);
  color: var(--color-primary-700);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
}

@media (max-width: 768px) {
  .themed .t-parent-unread-badge { font-size: 0.5625rem; }
}

@media (max-width: 480px) {
  .themed .t-parent-unread-badge { padding: 0 var(--space-1); }
}

/* ── Parent attendance history ───────────────────────────────────────────────
   The list defaults to exceptions, so these style the heading, the toggle and the
   pager that make that default legible rather than surprising. */

.themed .t-parent-hist-head {
  margin-bottom: var(--space-3);
}

.themed .t-parent-hist-title {
  color: var(--color-text-base);
  font-size: 0.875rem;
  font-weight: 700;
  min-width: 0;
}

.themed .t-parent-hist-toggle {
  color: var(--color-text-link);
  font-size: 0.75rem;
  white-space: nowrap;
}

.themed .t-parent-hist-toggle:hover {
  color: var(--color-text-link-hover);
}

.themed .t-parent-hist-pager {
  margin-top: var(--space-4);
}

.themed .t-parent-hist-pager-info {
  color: var(--color-text-muted);
}

.themed .t-parent-hist-pager-btn {
  border-color: var(--color-border);
  color: var(--color-text-base);
  background-color: var(--color-surface);
  border-radius: var(--radius-md);
}

.themed .t-parent-hist-pager-btn:hover {
  background-color: var(--color-surface-hover);
  border-color: var(--color-border-strong);
}

@media (max-width: 768px) {
  .themed .t-parent-hist-title { font-size: 0.8125rem; }
}

@media (max-width: 480px) {
  /* Stack: the heading and the toggle side by side leave two words per line. */
  .themed .t-parent-hist-head { flex-direction: column; align-items: flex-start; }
  .themed .t-parent-hist-pager { flex-direction: column; align-items: stretch; }
  .themed .t-parent-hist-pager-btn { text-align: center; }
}

/* ── Relevé de compte (statement of account) ─────────────────────────────────
   The document an administrator puts on the desk during a dispute. Printed at
   least as often as it is read on screen, so it is styled as a sheet rather than
   as a dashboard panel: letterhead, totals band, chronological table, footer. */

/* Page wrapper — owns the vertical rhythm so the template needs no utility for it. */
.themed .t-billing-statement {
  color: var(--color-text-base);
}

/* The identity block. A grid child needs min-width:0 or a long pupil name or Massar
   code refuses to wrap and pushes the sheet past the viewport at 320px. */
.themed .t-billing-statement-meta > div {
  min-width: 0;
}

.themed .t-billing-statement-sheet {
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-float-sm);
}

.themed .t-billing-statement-head {
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.themed .t-billing-statement-logo {
  max-height: 3.5rem;
  max-width: 12rem;
  width: auto;
  object-fit: contain;
}

.themed .t-billing-statement-school {
  color: var(--color-text-base);
  letter-spacing: -0.01em;
}

.themed .t-billing-statement-kicker {
  color: var(--color-text-subtle);
}

.themed .t-billing-statement-totals {
  background-color: var(--color-surface-muted);
}

.themed .t-billing-statement-total {
  min-width: 0;
  border-color: var(--color-border);
}

/* Tabular figures so the balance column reads as a column, not as ragged text. */
.themed .t-billing-statement-table td,
.themed .t-billing-statement-table th {
  font-variant-numeric: tabular-nums;
}

/* A reversed receipt stays on the statement — the family holds paper with that
   number on it — but must not read as money the school is holding. */
.themed .t-billing-statement-void {
  background-color: var(--color-surface-muted);
  color: var(--color-text-subtle);
}

/* An overpayment band. Shown only when there IS a credit, so it must read as
   information rather than as a warning — the family is ahead, not in trouble. */
.themed .t-billing-statement-credit {
  background-color: var(--color-info-bg);
  border-bottom: 1px solid var(--color-info-border);
  color: var(--color-info-text);
}

/* "Who did what" block. Separated from the ledger above by a rule rather than a
   tint: it is provenance, not another column of money. */
.themed .t-billing-statement-audit {
  border-top: 1px solid var(--color-border);
  background-color: var(--color-surface);
}

.themed .t-billing-statement-audit-row {
  color: var(--color-text-muted);
}

.themed .t-billing-statement-foot {
  background-color: var(--color-surface-muted);
  border-top: 1px solid var(--color-border);
  color: var(--color-text-muted);
}

.themed .t-billing-statement-btn {
  border-radius: var(--radius-md);
  border-color: var(--color-border);
  color: var(--color-text-base);
  background-color: var(--color-surface);
}

.themed .t-billing-statement-btn:hover {
  background-color: var(--color-surface-hover);
}

.themed .t-billing-statement-btn-primary {
  background-color: var(--color-primary-600);
  border-color: var(--color-primary-600);
  color: var(--color-text-inverse);
}

.themed .t-billing-statement-btn-primary:hover {
  background-color: var(--color-primary-700);
}

@media (max-width: 768px) {
  .themed .t-billing-statement-sheet { border-radius: var(--radius-xl); }
  .themed .t-billing-statement-logo { max-height: 3rem; max-width: 9rem; }
}

@media (max-width: 480px) {
  .themed .t-billing-statement-sheet { border-radius: var(--radius-lg); }
  .themed .t-billing-statement-logo { max-height: 2.5rem; max-width: 7rem; }
  /* The totals band is a grid child: without min-width:0 an unbreakable money
     run refuses to shrink and scrolls the whole page sideways. */
  .themed .t-billing-statement-total { padding: var(--space-3); }
  .themed .t-billing-statement-btn { width: 100%; justify-content: center; }
}


/* =========================================================================
   ENROLLMENT CORRECTION  (t-corr-*)  +  the "Autres actions" entry link
   -------------------------------------------------------------------------
   The correction page carries four operations of very different consequence.
   Before this they were four visually identical white cards, so "change the
   level" and "erase this registration" read as equally routine. The step
   badge and the collapsed danger block restore that hierarchy without adding
   decoration: no gradients, no tinted headers, no iconography beyond one
   chevron - weight and spacing do the work.

   Tokens only (R3), every selector `.themed`-scoped (R2), both mandatory
   breakpoints below (R6). Every element also keeps its Tailwind classes, so
   the page is still correct with the theme off (R4).
   ========================================================================= */

/* --- the entry link that replaced a bare inline <a> ---------------------- */

.themed .t-billing-more-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  text-decoration: none;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.themed .t-billing-more-link:hover {
  background: var(--color-surface-hover);
  border-color: var(--color-border-strong);
}

.themed .t-billing-more-link-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  min-width: 0;
}

.themed .t-billing-more-link-title {
  font-size: 0.875rem;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
}

.themed .t-billing-more-link-hint {
  font-size: 0.75rem;
  color: var(--color-text-subtle);
  line-height: 1.4;
}

.themed .t-billing-more-link-chevron {
  flex: none;
  width: 1rem;
  height: 1rem;
  color: var(--color-text-subtle);
}

/* --- page shell ---------------------------------------------------------- */

.themed .t-corr-header {
  padding-bottom: var(--space-2);
}

.themed .t-corr-breadcrumb-link {
  color: var(--color-text-muted);
  text-decoration: none;
}

.themed .t-corr-breadcrumb-link:hover { color: var(--color-text-link); }
.themed .t-corr-breadcrumb-sep { color: var(--color-text-subtle); }
.themed .t-corr-breadcrumb-current { color: var(--color-text-base); }

.themed .t-corr-title {
  color: var(--color-text-base);
  line-height: 1.2;
}

.themed .t-corr-chip {
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

.themed .t-corr-meta-link { color: var(--color-text-link); }
.themed .t-corr-meta-link:hover { color: var(--color-text-link-hover); }

/* --- a correction card --------------------------------------------------- */

.themed .t-corr-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.themed .t-corr-card-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.themed .t-corr-card-headings {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* The step marker. Outlined rather than filled: it orders the page, it is not
   a call to action, and a filled badge competes with the submit button. */
.themed .t-corr-step {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  font-size: 0.8125rem;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  line-height: 1;
}

.themed .t-corr-card-title { color: var(--color-text-base); }

.themed .t-corr-card-sub {
  color: var(--color-text-muted);
  font-size: 0.8125rem;
  line-height: 1.5;
}

.themed .t-corr-card-body {
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-4);
}

.themed .t-corr-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.themed .t-corr-confirm { color: var(--color-text-base); }

/* --- the "total currently due" figure ------------------------------------ */

.themed .t-corr-figure {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-info-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-muted);
}

.themed .t-corr-figure-label {
  font-size: 0.6875rem;
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-subtle);
}

/* `overflow-wrap` for the same reason `t-billing-kpi-value` carries it: this is
   a flex child, so an unbreakable run of digits would otherwise widen the PAGE
   rather than just this box. */
.themed .t-corr-figure-value {
  font-size: 1.125rem;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-base);
  overflow-wrap: anywhere;
}

/* --- ending the registration --------------------------------------------- */

.themed .t-corr-danger {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.themed .t-corr-danger-summary {
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  list-style: none;
}

.themed .t-corr-danger-summary::-webkit-details-marker { display: none; }

.themed .t-corr-danger-summary::before {
  content: "\25B8";
  display: inline-block;
  margin-right: var(--space-2);
  transition: transform var(--transition-fast);
}

.themed .t-corr-danger[open] .t-corr-danger-summary::before { transform: rotate(90deg); }

.themed .t-corr-danger-summary:hover { color: var(--color-text-base); }

.themed .t-corr-danger-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.themed .t-corr-danger-unit {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.themed .t-corr-danger-unit + .t-corr-danger-unit {
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

.themed .t-corr-btn-danger {
  border-color: var(--color-danger-border);
  color: var(--color-danger-text);
  background: var(--color-surface);
}

.themed .t-corr-btn-danger:hover { background: var(--color-danger-bg); }

/* --- R6: both mandatory breakpoints -------------------------------------- */

@media (max-width: 768px) {
  .themed .t-corr-card-head { gap: var(--space-2); }
  .themed .t-corr-step { width: 1.5rem; height: 1.5rem; font-size: 0.75rem; }
  .themed .t-corr-card-sub { font-size: 0.78125rem; }
  .themed .t-corr-figure { padding: var(--space-2) var(--space-3); }
  .themed .t-corr-figure-value { font-size: 1rem; }
  .themed .t-corr-danger-body { padding: var(--space-3); gap: var(--space-5); }
  .themed .t-billing-more-link { padding: var(--space-2) var(--space-3); }
}

@media (max-width: 480px) {
  /* The step badge stops being worth its horizontal space on a phone; the
     headings need every pixel of the 320px floor. */
  .themed .t-corr-card-head { flex-direction: column; gap: var(--space-2); }
  .themed .t-corr-page { padding-left: var(--space-3); padding-right: var(--space-3); }
  .themed .t-corr-actions > * { width: 100%; justify-content: center; }
  .themed .t-corr-danger-summary { padding: var(--space-2) var(--space-3); }
  .themed .t-corr-danger-body { padding: var(--space-3); }
  .themed .t-corr-figure-value { font-size: 0.9375rem; }
  .themed .t-billing-more-link-hint { font-size: 0.6875rem; }
}
