/* =============================================================================
   Darsak - Design Tokens
   -----------------------------------------------------------------------------
   Status      : approved (docs/design/THEME.md, approved: 2026-08-22)
   Merged      : 2026-08-22, from docs/design/theme/tokens.css (T22.6 work item 1)
   Every token name that existed before this merge is PRESERVED AT ITS CURRENT
   VALUE (layer 2 "legacy" below) - no existing view changes behaviour. Everything
   else is additive.

   LAYERING
   --------
   Layer 1  primitives  : raw ramps. Never referenced from a view.
   Layer 2  legacy      : the 15 tokens that shipped before this merge. Names and
                          values frozen.
   Layer 3  semantic    : role tokens. THIS is what views and components use.
   Layer 4  component   : per-component knobs derived from layer 3.

   CONTRAST
   --------
   Every ratio in the comments was COMPUTED with the WCAG 2.x relative-luminance
   formula, not estimated. AA floor: 4.5:1 body text, 3:1 UI boundaries/graphics.
   Tokens marked  !! FAILS AA  must never carry text or meaning-bearing graphics.
   ========================================================================== */

:root {

  /* ==========================================================================
     LAYER 1 - PRIMITIVES
     ====================================================================== */

  /* --- Green (brand) --- */
  --green-50:  #F0FDF4;   /* in use today as --primary-lighter */
  --green-100: #DCFCE7;   /* in use today as --primary-light   */
  --green-200: #BBF7D0;
  --green-300: #86EFAC;
  --green-400: #4ADE80;
  --green-500: #22C55E;   /* in use today as --primary          */
  --green-600: #16A34A;   /* in use today as --primary-dark     */
  --green-700: #15803D;   /* the first green that passes AA on white          */
  --green-800: #166534;   /* pressed / text on green surfaces                 */
  --green-900: #14532D;

  /* --- Slate (neutral) --- */
  --slate-50:  #F8FAFC;   /* in use today as --bg-subtle    */
  --slate-100: #F1F5F9;
  --slate-200: #E2E8F0;   /* in use today as --border-light */
  --slate-300: #CBD5E1;
  --slate-400: #94A3B8;   /* in use today as --text-muted-3 */
  --slate-500: #64748B;   /* in use today as --text-muted-2 */
  --slate-600: #475569;   /* the missing secondary text step */
  --slate-700: #334155;
  --slate-800: #1E293B;
  --slate-900: #0F172A;   /* in use today as --text-primary */

  /* --- Red / Amber / Blue / Violet (state + accent) --- */
  --red-50:  #FEF2F2;  --red-100: #FEE2E2;  --red-500: #EF4444;
  --red-600: #DC2626;  --red-700: #B91C1C;

  --amber-50:  #FFFBEB;  --amber-100: #FEF3C7;  --amber-500: #F59E0B;
  --amber-600: #D97706;  --amber-700: #B45309;

  --blue-50:  #EFF6FF;  --blue-100: #DBEAFE;  --blue-500: #3B82F6;
  --blue-600: #2563EB;  --blue-700: #1D4ED8;

  --violet-50:  #F5F3FF;  --violet-100: #EDE9FE;
  --violet-500: #8B5CF6;  --violet-600: #7C3AED;

  --white: #FFFFFF;
  --page-tint: #FAFBFC;   /* the app's own off-white; NOT a Tailwind value */


  /* ==========================================================================
     LAYER 2 - LEGACY TOKENS
     FROZEN. Same name, same value. Renaming or re-valuing any of these breaks
     views that reference them today.
     ====================================================================== */

  --primary:         #22C55E;  /* !! 2.28:1 on white - decorative only */
  --primary-dark:    #16A34A;  /* !! 3.30:1 on white - UI only, no text */
  --primary-light:   #DCFCE7;  /* surface */
  --primary-lighter: #F0FDF4;  /* surface */

  --bg-body:    #FAFBFC;
  --bg-card:    #FFFFFF;
  --bg-subtle:  #F8FAFC;

  --text-primary: #0F172A;     /* 17.85:1 on white - PASS AAA */
  --text-muted-2: #64748B;     /*  4.76:1 on white - PASS AA (floor)  */
  --text-muted-3: #94A3B8;     /*  2.56:1 on white - !! FAILS AA      */

  --border-light: #E2E8F0;     /* 1.23:1 - decorative separators only */

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.05);

  --radius-md: 12px;
  --radius-lg: 16px;


  /* ==========================================================================
     LAYER 3 - SEMANTIC ROLES
     Views and components reference ONLY this layer (plus the legacy names that
     already ship). No raw hex in a page, ever.
     ====================================================================== */

  /* --- Brand -------------------------------------------------------------
     --primary-strong (#15803D) is visually within one step of the #198754
     Bootstrap's .btn-success already paints on screen, so adopting it changes
     almost nothing visually while making the value intentional and AA-clean. */
  --primary-surface:  var(--green-50);
  --primary-subtle:   var(--green-100);
  --primary-base:     var(--green-500);
  --primary-strong:   var(--green-700);  /* 5.02:1 on white  - buttons, links */
  --primary-stronger: var(--green-800);  /* 7.13:1 on white  - :active        */
  --on-primary:       var(--white);      /* 5.02:1 on --primary-strong  PASS  */
  --on-primary-subtle: var(--green-800); /* 6.49:1 on --primary-subtle  PASS  */

  /* --- Surfaces (elevation 0 -> 3) --------------------------------------- */
  --surface-page:     var(--page-tint);
  --surface-raised:   var(--white);
  --surface-sunken:   var(--slate-50);
  --surface-hover:    var(--slate-100);
  --surface-inverse:  var(--slate-900);
  --surface-disabled: var(--slate-100);

  /* --- Text -------------------------------------------------------------- */
  --text-strong:    var(--slate-900);
  --text-body:      var(--slate-900);
  --text-secondary: var(--slate-600);  /*  7.58:1 sub-labels, captions  PASS */
  --text-muted:     var(--slate-500);  /*  4.76:1 lowest legal body text     */
  --text-disabled:  var(--slate-400);  /*  2.56:1 - disabled controls ONLY   */
  --text-decorative: var(--slate-400);
  --text-on-inverse: var(--slate-100); /* 16.30:1 on --surface-inverse       */
  --text-brand:     var(--primary-strong);
  --text-link:      var(--primary-strong);
  --text-link-hover: var(--primary-stronger);

  /* --- Borders -----------------------------------------------------------
     Card/table separators are decorative -> --border-subtle is fine at
     1.23:1. An input on a white card has no fill of its own, so its border IS
     the affordance -> --border-input must clear 3:1. */
  --border-subtle:  var(--slate-200);  /* 1.23:1 decorative separators       */
  --border-default: var(--slate-300);  /* 1.48:1 stronger decorative         */
  --border-input:   var(--slate-500);  /* 4.76:1 required control boundary   */
  --border-strong:  var(--slate-700);
  --border-brand:   var(--primary-strong);
  --border-danger:  var(--danger-strong);

  /* --- State: success ---------------------------------------------------- */
  --success:         var(--green-500);
  --success-strong:  var(--green-700);
  --success-surface: var(--green-50);
  --success-border:  var(--green-200);
  --success-text:    var(--green-800);  /* 6.81:1 on --success-surface  PASS */
  --on-success:      var(--white);

  /* --- State: warning ---------------------------------------------------- */
  --warning:         var(--amber-500);
  --warning-strong:  var(--amber-600);
  --warning-surface: var(--amber-50);
  --warning-border:  var(--amber-100);
  --warning-text:    var(--amber-700);  /* 4.84:1 on --warning-surface  PASS */
  --on-warning:      var(--slate-900);

  /* --- State: danger ----------------------------------------------------- */
  --danger:          var(--red-500);
  --danger-strong:   var(--red-600);
  --danger-surface:  var(--red-50);
  --danger-border:   var(--red-100);
  --danger-text:     var(--red-700);    /* 5.91:1 on --danger-surface   PASS */
  --on-danger:       var(--white);

  /* --- State: info --------------------------------------------------------*/
  --info:            var(--blue-500);
  --info-strong:     var(--blue-600);
  --info-surface:    var(--blue-50);
  --info-border:     var(--blue-100);
  --info-text:       var(--blue-700);   /* 6.16:1 on --info-surface     PASS */
  --on-info:         var(--white);

  /* --- State: neutral / pending ------------------------------------------ */
  --neutral-surface: var(--slate-100);
  --neutral-border:  var(--slate-200);
  --neutral-text:    var(--slate-600);
  --neutral-strong:  var(--slate-600);
  --on-neutral:      var(--white);

  /* --- Accents (stat tiles, category chips) ------------------------------ */
  --accent-blue-surface:   var(--blue-100);   --accent-blue-text:   var(--blue-700);
  --accent-amber-surface:  var(--amber-100);  --accent-amber-text:  var(--amber-700);
  --accent-violet-surface: var(--violet-100); --accent-violet-text: var(--violet-600);
  --accent-green-surface:  var(--green-100);  --accent-green-text:  var(--green-800);

  /* --- Rating -------------------------------------------------------------
     Bootstrap's .text-warning (#FFC107) measures 1.63:1 on white. A star is a
     meaning-bearing graphic, so it needs 3:1. amber-600 gives 3.19:1. */
  --rating-filled: var(--amber-600);
  --rating-empty:  var(--slate-300);
  --rating-track:  var(--slate-200);

  /* --- Focus ---------------------------------------------------------------
     One ring, brand-coloured, everywhere - not Bootstrap's default blue. */
  --focus-ring-color:  var(--green-700);
  --focus-ring-width:  3px;
  --focus-ring-offset: 2px;
  --focus-ring-halo:   0 0 0 4px rgba(21, 128, 61, 0.20);
  --focus-ring-color-danger: var(--red-700);
  --focus-ring-color-inverse: var(--green-300);

  /* --- Scrim / overlay ----------------------------------------------------*/
  --scrim:          rgba(15, 23, 42, 0.60);
  --scrim-strong:   rgba(15, 23, 42, 0.80);
  --scrim-media:    rgba(15, 23, 42, 0.75);
  --scrim-skeleton: rgba(15, 23, 42, 0.06);


  /* ==========================================================================
     TYPOGRAPHY
     ====================================================================== */
  --font-sans: 'Tajawal', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Courier New', monospace;

  --fw-regular: 400;
  --fw-medium:  500;
  --fw-bold:    700;

  --fs-display:  3rem;      --lh-display:  1.25;
  --fs-h1:       2.5rem;    --lh-h1:       1.30;
  --fs-h2:       2rem;      --lh-h2:       1.35;
  --fs-h3:       1.75rem;   --lh-h3:       1.40;
  --fs-h4:       1.5rem;    --lh-h4:       1.40;
  --fs-h5:       1.25rem;   --lh-h5:       1.50;
  --fs-h6:       1rem;      --lh-h6:       1.50;
  --fs-body-lg:  1.125rem;  --lh-body-lg:  1.80;
  --fs-body:     1rem;      --lh-body:     1.70;
  --fs-small:    0.875rem;  --lh-small:    1.70;
  --fs-caption:  0.75rem;   --lh-caption:  1.60;

  --tracking-none: 0;
  --tracking-latin-caps: 0.02em;


  /* ==========================================================================
     SPACING - 8pt grid
     ====================================================================== */
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;


  /* ==========================================================================
     RADIUS
     ====================================================================== */
  --radius-xs:     4px;
  --radius-sm:     8px;
  /* --radius-md: 12px  -> layer 2 */
  /* --radius-lg: 16px  -> layer 2 */
  --radius-xl:    20px;
  --radius-2xl:   24px;
  --radius-pill: 999px;   /* the app's dominant shape: .rounded-pill everywhere */
  --radius-circle: 50%;


  /* ==========================================================================
     SHADOW
     ====================================================================== */
  --shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.04);
  /* --shadow-sm, --shadow-md -> layer 2 */
  --shadow-lg: 0 12px 20px -6px rgba(15, 23, 42, 0.10);
  --shadow-xl: 0 20px 25px -5px rgba(15, 23, 42, 0.15);
  --shadow-brand: 0 4px 20px rgba(34, 197, 94, 0.35);
  --shadow-focus: var(--focus-ring-halo);


  /* ==========================================================================
     Z-INDEX LADDER
     ====================================================================== */
  --z-base:              0;
  --z-raised:            1;
  --z-sticky-inner:     10;
  --z-dropdown:       1000;
  --z-fab:            1010;   /* app: AI assistant widget */
  --z-sticky:         1020;   /* app: public navbar, admin sidebar */
  --z-fixed:          1030;
  --z-offcanvas-scrim:1040;
  --z-offcanvas:      1045;
  --z-modal-scrim:    1050;
  --z-modal:          1055;
  --z-popover:        1070;
  --z-tooltip:        1080;
  --z-toast:          1090;


  /* ==========================================================================
     LAYOUT
     ====================================================================== */
  --container-max: 1320px;
  --container-pad: var(--space-4);
  --sidebar-width: 240px;
  --navbar-height: 56px;


  /* ==========================================================================
     MOTION
     ====================================================================== */
  --motion-fast:   150ms;
  --motion-base:   200ms;
  --motion-slow:   320ms;
  --motion-ease:   cubic-bezier(0.4, 0, 0.2, 1);
  --motion-enter:  cubic-bezier(0, 0, 0.2, 1);
  --motion-exit:   cubic-bezier(0.4, 0, 1, 1);


  /* ==========================================================================
     TOUCH TARGETS
     ====================================================================== */
  --tap-min:     44px;
  --tap-compact: 36px;   /* dense admin tables only, with >=8px separation */
  --tap-floor:   24px;   /* absolute WCAG 2.2 AA minimum - never go below  */


  /* ==========================================================================
     LAYER 4 - COMPONENT KNOBS
     ====================================================================== */

  /* Button */
  --btn-height-sm: 36px;
  --btn-height-md: 44px;
  --btn-height-lg: 52px;
  --btn-padding-x-sm: var(--space-3);
  --btn-padding-x-md: var(--space-5);
  --btn-padding-x-lg: var(--space-6);
  --btn-radius: var(--radius-pill);
  --btn-font-weight: var(--fw-bold);
  --btn-icon-gap: var(--space-2);

  /* Field */
  --field-height: 44px;
  --field-radius: var(--radius-pill);
  --field-radius-multiline: var(--radius-md);
  --field-padding-x: var(--space-4);
  --field-bg: var(--surface-raised);
  --field-bg-disabled: var(--surface-disabled);
  --field-border: var(--border-input);
  --field-border-hover: var(--slate-700);
  --field-border-error: var(--danger-strong);
  --field-label-gap: var(--space-2);
  --field-help-gap: var(--space-1);

  /* Card */
  --card-bg: var(--surface-raised);
  --card-border: var(--border-subtle);
  --card-radius: var(--radius-lg);
  --card-padding: var(--space-5);
  --card-shadow: var(--shadow-sm);
  --card-shadow-hover: var(--shadow-md);
  --card-lift-hover: -3px;

  /* Badge */
  --badge-radius: var(--radius-pill);
  --badge-padding-y: var(--space-1);
  --badge-padding-x: var(--space-3);
  --badge-font-size: var(--fs-caption);
  --badge-font-weight: var(--fw-bold);

  /* Table */
  --table-head-bg: var(--surface-sunken);
  --table-head-text: var(--text-secondary);
  --table-row-hover: var(--surface-hover);
  --table-border: var(--border-subtle);
  --table-cell-padding-y: var(--space-3);
  --table-cell-padding-x: var(--space-4);

  /* Avatar - every avatar needs a fallback */
  --avatar-xs: 24px;
  --avatar-sm: 32px;
  --avatar-md: 40px;
  --avatar-lg: 64px;
  --avatar-xl: 96px;
  --avatar-fallback-bg: var(--primary-subtle);
  --avatar-fallback-text: var(--on-primary-subtle);

  /* Toast */
  --toast-radius: var(--radius-md);
  --toast-shadow: var(--shadow-lg);
  --toast-max-width: 360px;

  /* Modal */
  --modal-radius: var(--radius-2xl);
  --modal-shadow: var(--shadow-xl);
  --modal-max-width: 520px;

  /* Nav link (admin sidebar + global navbar) */
  --nav-link-height: 44px;
  --nav-link-radius: var(--radius-pill);
  --nav-link-padding-x: var(--space-4);
  --nav-link-text: var(--text-secondary);
  --nav-link-text-hover: var(--text-strong);
  --nav-link-bg-hover: var(--surface-hover);
  --nav-link-bg-active: var(--primary-subtle);
  --nav-link-text-active: var(--on-primary-subtle);  /* 6.49:1 - was 3.00 */
  --nav-link-marker: var(--primary-strong);
}

/* =============================================================================
   POST-APPROVAL ADDITION -- 2026-08-24 (T22.8, spec section 7-c / NOTES.md section 8)
   22 tokens ported verbatim from docs/design/landing/{index,teachers}.html's
   "0. PROPOSED TOKEN ADDITIONS" block (byte-identical between the two files
   except --measure-display, which only index.html's hero actually consumes).
   Logged in docs/design/THEME.md's "changes after approval" table. Mirrors
   docs/design/theme/tokens.css exactly - same 22 names, same values.
   ========================================================================== */
:root {
  --icon-slot:        20px;
  --icon-in-chip:     20px;
  --icon-chip:        48px;
  --icon-xl:          32px;
  --icon-2xl:         48px;

  --step-num-size:    40px;
  --count-badge-h:    28px;
  --media-h-card:    160px;
  --media-h-map:     400px;
  --marker-w:          3px;
  --hairline:          1px;
  --hairline-strong:   2px;
  --press-offset:      1px;

  --nav-h-desktop:     64px;
  --nav-scroll-offset: 88px;
  --nav-search-basis: 220px;
  --nav-search-max:   420px;
  --menu-min-w:       280px;
  --menu-min-w-wide:  340px;

  --measure-display:  22ch;
  --measure-lede:     54ch;
  --table-min-w:     520px;
}

/* =============================================================================
   POST-APPROVAL ADDITION -- 2026-08-24-b (review findings after the 22 above)
   Three tokens not in the approved mockup at all: the map InfoWindow popup
   (design review, MAJOR - freshly authored T22.8 code) and the signed-in
   account button/name (architecture review, minor - pre-dates T22.8 but sits
   inside the navbar block this task rebuilt). Mirrors
   docs/design/theme/tokens.css exactly.
   ========================================================================== */
:root {
  --map-infowindow-min-w:   160px;
  --nav-account-max-w:      200px;
  --nav-account-name-max-w: 120px;
}

/* =============================================================================
   POST-APPROVAL ADDITION -- 2026-08-25 (T25, docs/design/teacher-apply/NOTES.md
   section 5). 5 tokens ported verbatim from the mockup's "0. PROPOSED TOKEN
   ADDITIONS (T25)" block - see docs/design/theme/tokens.css for the same
   addition with the full rationale comment.
   ========================================================================== */
:root {
  --icon-sm:        16px;
  --icon-lg:        24px;
  --form-max-w:    640px;
  --dl-label-w:    176px;
  --textarea-min-h: 160px;
}

/* =============================================================================
   POST-APPROVAL ADDITION -- T26 (docs/design/admin-teacher-applications/NOTES.md
   section 5-1). The mockup's "PROPOSED TOKEN ADDITIONS" block named 5 tokens;
   only ONE is genuinely new here - --icon-sm/--icon-lg/--textarea-min-h already
   shipped with T25 above (icon-sm/lg at the same values; textarea-min-h at
   160px, which this task deliberately does NOT overwrite with the mockup's
   96px - that would silently shrink T25's live Bio field). The mockup's
   proposed --detail-label-w (168px) is also skipped: the app already has a
   generic description-list component (.dk-dl / --dl-label-w, 176px, T25) that
   covers the exact same role, reused directly below instead of a near-
   duplicate token. Both decisions are disclosed in docs/handoff/T26-views.md.
   ========================================================================== */
:root {
  --table-min-w-wide: 1100px;  /* the 9-column applications table before its wrapper scrolls sideways */
}

/* =============================================================================
   POST-APPROVAL ADDITION -- T25 fixes (2026-08-25, architecture review MINOR:
   .dk-photo-fallback's block-size was a raw 250px while every other value in
   that same rule already used tokens - docs/reviews/architecture/2026-08-25-
   T25-T26-backend.md). Mirrors docs/design/theme/tokens.css exactly.
   ========================================================================== */
:root {
  --photo-hero-h: 250px;  /* .dk-photo-fallback block-size - matches the pre-existing inline style="height:250px" on TeacherProfile.cshtml's sibling <img>, left untouched */
}

/* =============================================================================
   MANDATORY BASE RULES
   Each closes a documented failure mode.
   ========================================================================== */

/* 1. element.hidden in JS does NOTHING without this rule. Before this merge it
      existed only scoped to #teacherRoleNote (Register.cshtml), so every other
      use of .hidden = true anywhere in the app silently no-opped. */
[hidden] { display: none !important; }

/* 2. One visible focus ring, brand-coloured, on every focusable thing.
      Never `outline: none` without an equally visible replacement. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
    border-radius: var(--radius-xs);
}

/* 3. Respect reduced motion. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* 4. Arabic body defaults (values identical to the pre-merge body{} rule below:
      --text-primary === --text-body, --bg-body === --surface-page). */
body {
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
    font-weight: var(--fw-regular);
    color: var(--text-body);
    background-color: var(--surface-page);
    -webkit-font-smoothing: antialiased;
    letter-spacing: var(--tracking-none);
}

/* 5. Numbers, machine identifiers and Latin brand strings stay LTR inside RTL
      prose (bidi trap documented in docs/design/theme/tokens.css). */
.ltr { direction: ltr; unicode-bidi: isolate; text-align: start; }
.num { font-variant-numeric: tabular-nums; direction: ltr; unicode-bidi: isolate; }
.mono { font-family: var(--font-mono); direction: ltr; unicode-bidi: isolate; }

/* 6. Screen-reader-only helper. */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* =============================================================================
   EXISTING COMPONENT STYLES (unchanged by the token merge)
   ========================================================================== */

.card {
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-light);
    background-color: var(--bg-card);
}

.teacher-card {
    transition: all 0.2s ease;
}

.teacher-card:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-3px);
}

/* THEME.md section 9, items 2/15 (T22.7): a white checkmark on --primary (#22C55E) measured
   2.28:1 (needs 3:1 for a meaning-bearing graphic) - moved to --primary-strong (5.02:1). The
   physical top/left also becomes logical (item 15) - this app is RTL-only today, so the
   logical pair that preserves the exact same rendered corner is inset-block-start/
   inset-inline-end (RTL: inline-end = left), not inline-start. NOTE: grep-confirmed unused by
   any current view (the teacher card this badge described predates the T22.8 landing-page/
   Teachers.cshtml rebuild) - fixed for correctness/hygiene, not visually re-verified since
   nothing renders it today. */
.badge-verified {
    position: absolute;
    inset-block-start: var(--space-2);
    inset-inline-end: var(--space-2);
    background: var(--primary-strong);
    color: #fff;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
}

.payment-option {
    border: 1.5px solid var(--border-light);
    border-radius: var(--radius-md);
    padding: 12px 8px;
    text-align: center;
    cursor: pointer;
    transition: all 0.15s ease;
}

.payment-option.selected,
.payment-option:hover {
    border-color: var(--primary);
    background: var(--primary-light);
}

.star-btn {
    cursor: pointer;
    transition: color 0.1s ease;
}

/* THEME.md section 9, item 13 (T22.7): 20px sat outside the 8pt spacing grid - the next step up
   is --space-5 (24px). */
.stat-card {
    background: var(--bg-card);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    transition: box-shadow 0.2s ease;
}

.stat-card:hover {
    box-shadow: var(--shadow-md);
}

.stat-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
}

/* THEME.md section 9, item 15 (T22.7): border-left was physical - RTL-only today, so the
   logical property that preserves the exact same rendered edge is border-inline-end (RTL:
   inline-end = left), matching the T26 responsive rebuild's own .admin-sidecol rule below. */
.admin-sidebar {
    background: var(--bg-card);
    border-inline-end: 1px solid var(--border-light);
    min-height: calc(100vh - 56px);
}

/* THEME.md section 9, items 3/13 (T22.7): the "full redesign" the T26 comment above deferred -
   raw px replaced with 8pt-grid tokens (gap 10px->--space-2, padding 10px 16px->--space-2
   block/--space-4 inline, matching the item's own "8/16px" target exactly), plus a 44px touch
   target floor (THEME 3-6) this link never had. Default/hover colours were already token-driven
   and AA-legal (--text-muted-2 4.76:1, T26's active-state fix already closed the one failing
   pair) - untouched. */
.admin-nav-link {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--tap-min);
    padding-block: var(--space-2);
    padding-inline: var(--space-4);
    border-radius: var(--radius-md);
    color: var(--text-muted-2);
    text-decoration: none;
    font-weight: var(--fw-medium);
    font-size: var(--fs-small);
    transition: background var(--motion-fast) var(--motion-ease), color var(--motion-fast) var(--motion-ease);
}

.admin-nav-link:hover {
    background: var(--bg-subtle);
    color: var(--text-primary);
}

/* Admin nav grouping task (2026-09-07) - the group label above each .admin-nav-group's links.
   A <p>, not a heading or a link: quiet and non-interactive (no tabindex, cannot become a focus
   stop), same weight/size precedent as the existing .dk-menu__title label (line ~945 of this
   file: --fs-caption/--fw-bold/--text-muted) reused here for the identical "small quiet
   sub-label above a group of items" role - tokens only, no raw hex/px. */
.admin-nav-group {
    /* the parent <nav> is itself d-flex/flex-column/gap-1 (Bootstrap utilities in the .cshtml) -
       each group needs the SAME flex-column/gap-1 (--space-1 = Bootstrap's gap-1 = 4px) so the
       links inside one group keep the exact spacing they had before grouping existed; only
       between groups (the rule below) is the gap wider on purpose. */
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}
.admin-nav-group + .admin-nav-group {
    margin-block-start: var(--space-3);
}
.admin-nav-group__title {
    /* THEME.md section 2-4: "letter-spacing ممنوع على العربية إطلاقاً" (forbidden on Arabic -
       it splits connected letters), allowed only up to 0.02em on all-caps LATIN strings - not
       the case here. No text-transform:uppercase either - Arabic has no case. Separation from
       the links below comes from size/weight/color and the block spacing above instead. */
    margin: 0;
    padding-inline: var(--space-4);
    padding-block-end: var(--space-1);
    font-size: var(--fs-caption);
    line-height: var(--lh-caption);
    font-weight: var(--fw-bold);
    color: var(--text-muted);
}

/* T26 (docs/design/THEME.md section 9 #3 / section 2-8): the OLD rule painted
   --primary-dark (#16A34A) on --primary-light (#DCFCE7) = 3.00:1, below the
   4.5:1 text floor. Partial closure of the T22.7 debt item for this one pair
   only (docs/handoff/T26-views.md) - the rest of .admin-nav-link (padding,
   default/hover colours) is untouched, that is the full T22.7 redesign. */
.admin-nav-link {
    position: relative;
}
.admin-nav-link.active {
    background: var(--nav-link-bg-active);
    color: var(--nav-link-text-active);   /* 6.49:1 PASS - was 3.00:1 */
    font-weight: var(--fw-bold);
}
.admin-nav-link.active::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    inset-block: var(--space-2);
    inline-size: var(--marker-w);
    border-radius: var(--radius-pill);
    background: var(--nav-link-marker);
}

/* =============================================================================
   GLOBAL NAVBAR (T22.8) - rebuilt per docs/specs/T22.8-landing-page-and-navbar.md
   section 6.3's four structural rules, ported from the approved mockup's
   SHARED-NAVBAR-CSS block (docs/design/landing/index.html and teachers.html -
   byte-identical between the two, sha256-verified in NOTES.md section 6-4).
   Supersedes the whole T22.6 navbar block this replaces: the old progressive-
   reveal .dk-search, and .dk-desktop-only/.dk-mobile-only/.dk-xl-only (grep-
   confirmed used nowhere outside _Layout.cshtml before this change).
   Logical properties only: no left/right, no margin-left, no border-left.
   ========================================================================== */

.dk-nav {
  --dk-nav-h: var(--navbar-height);
  position: sticky; inset-block-start: 0; z-index: var(--z-sticky);
  background: var(--surface-raised);
  border-block-end: var(--hairline) solid var(--border-subtle);
}
@media (min-width: 992px) { .dk-nav { --dk-nav-h: var(--nav-h-desktop); } }

.dk-nav__inner {
  max-width: var(--container-max); margin-inline: auto;
  padding-inline: var(--container-pad);
  min-height: var(--dk-nav-h);
  display: flex; flex-wrap: nowrap; align-items: center; gap: var(--space-2);
}

/* RULE 1: the brand is an element that is NEVER crowded - it never shrinks,
   it is always first in the DOM, and nothing may occupy its box. */
.dk-brand {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: var(--tap-min); padding-inline: var(--space-2);
  border-radius: var(--radius-pill);
  color: var(--text-strong); font-weight: var(--fw-bold);
  font-size: var(--fs-h5); line-height: var(--lh-h5);
  text-decoration: none;
  flex: 0 0 auto; white-space: nowrap;
}
.dk-brand:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-brand__mark { color: var(--primary-strong); font-size: 1.1em; } /* role: brand - never mirrored */

.dk-rule { inline-size: var(--hairline); block-size: 24px; background: var(--border-subtle); margin-inline: var(--space-1); flex-shrink: 0; }

/* RULE 3: the middle zone carries functional content, so the bar has
   inventory instead of a void. It never grows and never overflows. */
.dk-nav__mid { display: flex; align-items: center; gap: var(--space-1); flex: 0 1 auto; min-inline-size: 0; }

.dk-navlink {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: var(--nav-link-height); padding-inline: var(--space-3);
  border-radius: var(--nav-link-radius);
  color: var(--nav-link-text);              /* #475569 on #FFFFFF = 7.58:1 PASS */
  font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-medium);
  text-decoration: none; white-space: nowrap; background: transparent; border: 0;
  cursor: pointer; flex: 0 0 auto;
  transition: background var(--motion-fast) var(--motion-ease), color var(--motion-fast) var(--motion-ease);
}
.dk-navlink:hover { background: var(--nav-link-bg-hover); color: var(--nav-link-text-hover); }
.dk-navlink:active { background: var(--surface-sunken); }
.dk-navlink[aria-current="page"] {
  background: var(--nav-link-bg-active);
  color: var(--nav-link-text-active);        /* #166534 on #DCFCE7 = 6.49:1 PASS */
  font-weight: var(--fw-bold);
}
.dk-navlink[aria-expanded="true"] { background: var(--surface-hover); color: var(--text-strong); }
.dk-navlink[aria-disabled="true"] {
  color: var(--text-disabled); background: var(--surface-disabled);
  cursor: not-allowed; pointer-events: none;
}
.dk-navlink .fa-chevron-down {
  font-size: .7em; color: var(--text-muted);       /* role: chevron - not directional */
  transition: transform var(--motion-fast) var(--motion-ease);
}
.dk-navlink[aria-expanded="true"] .fa-chevron-down { transform: rotate(180deg); }

/* zone END: search + identity */
.dk-nav__end {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2);
  flex: 1 1 auto; min-inline-size: 0; margin-inline-start: auto;
}

/* T45 fix (design review 2026-09-03 cycle-5 e2e regression, navbar.spec.js:344 "zero element
   overlap at 320px, signed in as teacher") - the notification bell added a FOURTH persistent
   icon button (search-entry/bell/account-entry/menu) to .dk-nav__end for every authenticated
   role, not only teacher (the guest sweep at this width never carries a bell, login/register are
   hidden below 576px, and no automated sweep existed for student/guardian/admin - this was a
   general signed-in-navbar-at-320px overflow, this test just happened to be the one that catches
   it). .dk-nav__end has min-inline-size:0 (by design, so it CAN shrink below its content's own
   width when space is tight) but its icon-button children are flex:0 0 auto (never shrink,
   var(--tap-min) = 44px is the WCAG tap-target floor - reducing it is not an option), so once
   content genuinely does not fit, the group's own box shrinks while its buttons do not, and the
   overflow spills left into .dk-brand's space (Rule 1: brand itself never shrinks or gets
   crowded). The fix narrows the SPACING only (container padding, both gaps) - four 44px buttons
   are untouched - which frees exactly enough width at this one breakpoint (measured live:
   0px overlap after this change, was ~20px before). */
@media (max-width: 359.98px) {
  .dk-nav__inner { padding-inline: var(--space-2); gap: var(--space-1); }
  .dk-nav__end { gap: var(--space-1); }
}

/* QA ticket #29 regression (docs/qa/triage/2026-09-06-navbar-teacher-overlap.md,
   navbar.spec.js:344 "zero element overlap at 320px/375px, signed in as teacher") - commit
   50827e8 added the chat icon as a FIFTH persistent icon button next to the bell above, and
   this time no amount of spacing can fix it: brand (108px, RULE 1 - never shrinks) plus five
   44px icon buttons (search-entry/bell/chat/account-entry/menu, none of which may shrink
   below var(--tap-min) either - same WCAG floor as the T45 fix above) is 328px of
   non-shrinking content alone, already wider than a 320px viewport BEFORE any padding or gap
   is added, so tightening spacing further (T45's own approach, immediately above) cannot
   close a deficit that starts negative. Measured live on the real page: 40px overlap at
   320px, 17px at 375px, 0px from 414px up - the four-icon state the T45 fix already covers
   comfortably.
   Fix: give the chat icon the SAME "hide in the bar below 576px, keep it in the drawer"
   treatment RULE 2 already gives the login/register pair (dk-r-sm) for the identical reason -
   too many things for a phone-width bar. The drawer already carries an identical chat
   link+badge (#dkChatBadgeDrawer, added in the same QA #29 commit right below the bell's own
   drawer mirror), so nothing is dropped, only relocated one click deeper below 576px, exactly
   like the identity pair. This targets the id rather than adding a new dk-r-sm class in
   _Layout.cshtml because that file is precompiled Razor - a class added there cannot be
   proven against the running app without restarting it, which this task could not do; #dkChatBell
   is already part of the currently-running compiled markup, so a site.css-only fix is both
   the smaller diff and the only one verifiable live. The bell (#dkNotifBell, same
   .dk-notifbell class) is deliberately left alone - it was already part of the previously-
   passing four-icon state above and does not need to move. */
@media (max-width: 575.98px) {
  #dkChatBell { display: none; }
}

/* RULE 4: the search entry never disappears. At >=768px it is the field
   itself (which also absorbs all the slack in the bar, so the old 340px void
   cannot come back); below that it is the icon that opens the drawer, where
   the field is the first item. */
.dk-search { display: flex; align-items: center; flex: 1 1 var(--nav-search-basis); min-inline-size: 0; max-inline-size: var(--nav-search-max); }
.dk-search__field {
  display: flex; align-items: center; gap: var(--space-2);
  inline-size: 100%; block-size: var(--field-height);
  padding-inline: var(--field-padding-x);
  background: var(--surface-raised); border: var(--hairline) solid var(--field-border);  /* 4.76:1 PASS */
  border-radius: var(--field-radius);
  min-inline-size: 0;
  transition: border-color var(--motion-fast) var(--motion-ease), box-shadow var(--motion-fast) var(--motion-ease);
}
.dk-search__field:hover { border-color: var(--field-border-hover); }
.dk-search__field:focus-within { border-color: var(--border-brand); box-shadow: var(--focus-ring-halo); }
.dk-search__field input {
  border: 0; outline: 0; background: transparent; inline-size: 100%; block-size: 100%;
  font-family: inherit; font-size: var(--fs-small); line-height: var(--lh-small);
  color: var(--text-body); min-inline-size: 0;
}
.dk-search__field input::placeholder { color: var(--text-muted); opacity: 1; }  /* 4.76:1 PASS */
.dk-search__field > i { color: var(--text-muted); flex-shrink: 0; }             /* role: search */
.dk-search__submit {
  border: 0; background: transparent; color: var(--primary-strong);            /* 5.02:1 PASS */
  font-weight: var(--fw-bold); font-size: var(--fs-small); cursor: pointer;
  padding-inline: var(--space-2); min-block-size: var(--tap-min); flex-shrink: 0;
}
.dk-search__submit:hover { color: var(--primary-stronger); text-decoration: underline; }

/* --- buttons -------------------------------------------------------------- */
.dk-btn {
  display: flex; align-items: center; justify-content: center; gap: var(--btn-icon-gap);
  min-height: var(--btn-height-md); padding-inline: var(--space-5);
  border-radius: var(--btn-radius); font-weight: var(--btn-font-weight);
  font-size: var(--fs-small); line-height: var(--lh-small);
  text-decoration: none; border: var(--hairline) solid transparent; cursor: pointer;
  white-space: nowrap; flex: 0 0 auto;
  transition: background var(--motion-fast) var(--motion-ease),
              border-color var(--motion-fast) var(--motion-ease),
              transform var(--motion-fast) var(--motion-ease);
}
.dk-btn--primary { background: var(--primary-strong); color: var(--on-primary); }   /* 5.02:1 PASS */
.dk-btn--primary:hover { background: var(--primary-stronger); color: var(--on-primary); }
.dk-btn--primary:active { background: var(--primary-stronger); transform: translateY(var(--press-offset)); }
.dk-btn--outline { background: var(--surface-raised); color: var(--text-strong); border-color: var(--border-input); }
.dk-btn--outline:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-btn--outline:active { background: var(--surface-sunken); }
.dk-btn--ghost { background: transparent; color: var(--text-secondary); }
.dk-btn--ghost:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-btn--danger-ghost { background: transparent; color: var(--danger-text); }
.dk-btn--danger-ghost:hover { background: var(--danger-surface); color: var(--danger-text); }
.dk-btn--danger-ghost:focus-visible { outline-color: var(--focus-ring-color-danger); }
.dk-btn[disabled], .dk-btn[aria-disabled="true"] {
  background: var(--surface-disabled); color: var(--text-disabled);
  border-color: var(--border-default); cursor: not-allowed; pointer-events: none;
}
.dk-btn--sm { padding-inline: var(--space-4); }    /* "sm" = narrower, never shorter than 44px */
.dk-btn--lg { min-height: var(--btn-height-lg); padding-inline: var(--space-6); font-size: var(--fs-body); }
.dk-btn--block { inline-size: 100%; padding-inline: var(--space-2); }

.dk-iconbtn {
  inline-size: var(--tap-min); block-size: var(--tap-min);
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-circle); border: 0; background: transparent;
  color: var(--text-secondary); cursor: pointer; flex: 0 0 auto; text-decoration: none;
  transition: background var(--motion-fast) var(--motion-ease);
}
.dk-iconbtn:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-iconbtn:active { background: var(--surface-sunken); }
.dk-iconbtn[aria-expanded="true"] { background: var(--primary-subtle); color: var(--on-primary-subtle); }
/* cycle3-design-fixes / classroom.js - same "this icon button is on" state as the rule above,
   for a toggle driven by JS state (screen-share active) rather than aria-expanded. */
.dk-iconbtn.is-active { background: var(--primary-subtle); color: var(--on-primary-subtle); }

/* --- avatar / account / role badge (signed-in only - outside the mockup's
   guest-only binding scope, so kept from T22.6: grep-confirmed no view outside
   _Layout.cshtml references these). --------------------------------------- */
.dk-avatar {
  inline-size: var(--avatar-sm); block-size: var(--avatar-sm);
  border-radius: var(--radius-circle); object-fit: cover; flex-shrink: 0;
  background: var(--avatar-fallback-bg);
}
.dk-avatar--fallback {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--avatar-fallback-bg); color: var(--avatar-fallback-text);
  font-weight: var(--fw-bold); font-size: var(--fs-small);
}
.dk-account {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: var(--tap-min); padding-inline: var(--space-2);
  border-radius: var(--radius-pill); border: var(--hairline) solid var(--border-subtle);
  background: var(--surface-raised); color: var(--text-strong);
  font-size: var(--fs-small); font-weight: var(--fw-medium); cursor: pointer;
  max-inline-size: var(--nav-account-max-w); flex: 0 0 auto;
}
.dk-account:hover { background: var(--surface-hover); }
.dk-account[aria-expanded="true"] { background: var(--surface-hover); border-color: var(--border-default); }
.dk-account__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: var(--nav-account-name-max-w); }

.dk-rolebadge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding-block: var(--space-1); padding-inline: var(--space-3);
  border-radius: var(--radius-pill); font-size: var(--fs-caption);
  line-height: var(--lh-caption); font-weight: var(--fw-bold);
  background: var(--primary-subtle); color: var(--on-primary-subtle);   /* 6.49:1 */
}
.dk-rolebadge--admin { background: var(--accent-violet-surface); color: var(--accent-violet-text); } /* 4.80:1 */
.dk-rolebadge--guardian { background: var(--info-surface); color: var(--info-text); }                /* 6.16:1 */
.dk-rolebadge--teacher { background: var(--warning-surface); color: var(--warning-text); }           /* 4.84:1 */

/* --- dropdown panel (Bootstrap .dropdown markup, themed) ------------------ */
.dk-menu {
  min-inline-size: var(--menu-min-w); padding: var(--space-2);
  background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  z-index: var(--z-dropdown);
}
.dk-menu--wide { min-inline-size: var(--menu-min-w-wide); }
.dk-menu__head { padding: var(--space-2) var(--space-3); border-block-end: var(--hairline) solid var(--border-subtle); margin-block-end: var(--space-2); }
.dk-menu__title { font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold); color: var(--text-muted); margin: 0; }
.dk-menu__item {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: var(--tap-min); padding-inline: var(--space-3);
  border-radius: var(--radius-md); text-decoration: none; border: 0; background: transparent;
  color: var(--text-body); font-size: var(--fs-small); line-height: var(--lh-small);
  inline-size: 100%; text-align: start; cursor: pointer;
}
.dk-menu__item:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-menu__item:active { background: var(--surface-sunken); }
.dk-menu__item[aria-current="page"] { background: var(--nav-link-bg-active); color: var(--nav-link-text-active); font-weight: var(--fw-bold); }
.dk-menu__item i { inline-size: var(--icon-slot); text-align: center; color: var(--text-muted); flex-shrink: 0; }
.dk-menu__item:hover i { color: var(--primary-strong); }
.dk-menu__item--danger { color: var(--danger-text); }
.dk-menu__item--danger i { color: var(--danger-text); }
.dk-menu__item--danger:hover { background: var(--danger-surface); color: var(--danger-text); }
.dk-menu__sep { block-size: var(--hairline); background: var(--border-subtle); margin-block: var(--space-2); }
.dk-menu__note { padding: var(--space-2) var(--space-3); font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-secondary); }
.dk-menu__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-2) var(--space-3); }

.dk-chip {
  display: inline-flex; align-items: center; gap: var(--space-1);
  min-height: var(--tap-min); padding-inline: var(--space-4);
  border-radius: var(--radius-pill); border: var(--hairline) solid var(--border-default);
  background: var(--surface-raised); color: var(--text-secondary);   /* 7.58:1 PASS */
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-medium);
  text-decoration: none;
}
.dk-chip:hover { border-color: var(--border-brand); background: var(--primary-surface); color: var(--on-primary-subtle); }

/* --- the trust chip: a REAL number (RegionStatsPresenter.ChipText) --------- */
.dk-trust {
  display: flex; align-items: center; gap: var(--space-2);
  min-height: var(--tap-min); padding-inline: var(--space-4);
  border: var(--hairline) solid var(--success-border); background: var(--success-surface);
  border-radius: var(--radius-pill); text-decoration: none;
  color: var(--success-text);                  /* #166534 on #F0FDF4 = 6.81:1 PASS */
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold);
  white-space: nowrap;
}
.dk-trust:hover { background: var(--primary-subtle); color: var(--success-text); }
.dk-trust i { color: var(--primary-strong); }   /* role: shield/verified */

/* --- the drawer (Bootstrap .offcanvas markup, themed) --------------------- */
.dk-drawer__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border-block-end: var(--hairline) solid var(--border-subtle);
}
/* Pre-existing bug found while adding T24's "جدولي" drawer link (docs/handoff/T24-views.md):
   this custom body class never got Bootstrap's OWN .offcanvas-body treatment (flex-grow +
   overflow-y:auto), so on any viewport short enough that the drawer's content exceeds it -
   measured live: 1254px of content in a 900px-tall drawer, well before this task's one extra
   link - everything past the fold was permanently unreachable (no scrollbar at all,
   overflow-y computed as its "visible" default). min-block-size:0 is load-bearing, not
   decorative: without it a flex child's default auto min-height can keep it at its full
   content size regardless of overflow-y, silently defeating the scroll. */
.dk-drawer__body { padding: var(--space-3) var(--space-4) var(--space-5); flex: 1 1 auto; min-block-size: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.dk-drawer__group { margin-block-end: var(--space-4); }
.dk-drawer__grouptitle {
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold);
  color: var(--text-muted); margin: 0 0 var(--space-2); padding-inline: var(--space-2);
}
.dk-drawer__link {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: var(--tap-min); padding-inline: var(--space-2);
  border-radius: var(--radius-md); text-decoration: none;
  color: var(--text-body); font-size: var(--fs-small); font-weight: var(--fw-medium);
  border: 0; background: transparent; inline-size: 100%; text-align: start; cursor: pointer;
  position: relative;
}
.dk-drawer__link:hover { background: var(--surface-hover); }
.dk-drawer__link i { inline-size: var(--icon-slot); text-align: center; color: var(--text-muted); }
.dk-drawer__link[aria-current="page"] { background: var(--nav-link-bg-active); color: var(--nav-link-text-active); font-weight: var(--fw-bold); }
.dk-drawer__link[aria-current="page"]::before {
  content: ""; position: absolute; inset-inline-start: 0; inset-block: var(--space-2);
  inline-size: var(--marker-w); border-radius: var(--radius-pill); background: var(--nav-link-marker);
}
.dk-drawer__link--danger { color: var(--danger-text); }
.dk-drawer__link--danger i { color: var(--danger-text); }
.dk-drawer__link--danger:hover { background: var(--danger-surface); }
.dk-drawer__user {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3); border-radius: var(--radius-lg);
  background: var(--surface-sunken); margin-block-end: var(--space-3);
}
.dk-drawer__sep { block-size: var(--hairline); background: var(--border-subtle); margin-block: var(--space-3); }
/* RULE 2: the identity pair lives in ONE box - it can only move as a pair. */
.dk-drawer__identity { display: flex; flex-direction: column; gap: var(--space-2); margin-block-end: var(--space-4); }

/* --- responsive visibility. These come LAST so they win on equal specificity.
       Bands are chosen so the sum of the visible atoms always fits the bar:
         < 576  brand + search entry + menu button          (RULE 1: three only)
         >=576  + the identity pair, together                        (RULE 2)
         >=768  the search entry becomes the field itself            (RULE 4)
         >=992  + the browse menu                                   (RULE 3)
        >=1200  + the four page anchors, and the menu button retires (RULE 3)
       .dk-r-below-lg is a Darsak addition, not in the mockup's guest-only
       markup: the signed-in avatar-icon needs a <992 tier the mockup's four
       r-* helpers don't provide, to keep the account dropdown at the exact
       >=992 tier it already shipped at under T22.6 (no gap introduced below
       it - see _Layout.cshtml's isAuthenticated branch).
       ---------------------------------------------------------------------- */
.dk-r-sm, .dk-r-md, .dk-r-lg, .dk-r-xl { display: none; }
.dk-r-below-md, .dk-r-below-lg, .dk-r-below-xl { display: flex; }
@media (min-width: 576px)  { .dk-r-sm { display: flex; } }
@media (min-width: 768px)  { .dk-r-md { display: flex; } .dk-r-below-md { display: none; } }
@media (min-width: 992px)  { .dk-r-lg { display: flex; } .dk-r-below-lg { display: none; } }
@media (min-width: 1200px) { .dk-r-xl { display: flex; } .dk-r-below-xl { display: none; } }

/* directional icons mirror in RTL; non-directional ones NEVER do. */
[dir="rtl"] .dk-i-dir { transform: scaleX(-1); }

/* =============================================================================
   MARKETING PAGE ("/") + TEACHER SEARCH PAGE ("/teachers") - T22.8. Ported from
   the approved mockups docs/design/landing/{index,teachers}.html. Every value
   below resolves to a token - zero raw colour/size/spacing/shadow in a
   component rule (spec section 7-c's blanket rule for this task).
   Two classes (.dk-h1/.dk-h2 sizing, .dk-band padding, .dk-section rhythm,
   .dk-field bottom margin) needed a small .dk-page-teachers scope: the two
   mockups were independent standalone files that each set these differently
   for their own page, and merging both into this one shared stylesheet needs
   *some* way to keep both intents - a body class on Teachers.cshtml only,
   with the unscoped rule staying index.html's (the landing page reuses these
   far more: hero h1, twelve section h2s) is the smallest, most conventional
   way to do that. Not a mockup content change - a porting/CSS-architecture
   decision, disclosed in docs/handoff/T22.8-views.md.
   ========================================================================== */

.dk-skip {
  position: absolute; inset-block-start: var(--space-2); inset-inline-start: var(--space-2);
  z-index: var(--z-toast);
  display: inline-flex; align-items: center; min-block-size: var(--tap-min);
  background: var(--primary-strong); color: var(--on-primary);   /* 5.02:1 PASS */
  padding-inline: var(--space-4); border-radius: var(--radius-pill);
  font-weight: var(--fw-bold); font-size: var(--fs-small); text-decoration: none;
  transform: translateY(-200%);
}
.dk-skip:focus { transform: translateY(0); }

/* Bootstrap paints <code> in #d63384 (4.30:1 on the sunken surface - below AA)
   and that colour belongs to no token. Re-point it at the theme. */
code {
  font-family: var(--font-mono); font-size: .9em;
  color: var(--text-strong); background: var(--surface-hover);   /* 16.30:1 PASS */
  padding-inline: var(--space-1); border-radius: var(--radius-xs);
}

.dk-main {
  max-width: var(--container-max); margin-inline: auto;
  padding-inline: var(--container-pad); padding-block: var(--space-5) var(--space-8);
}

.dk-section { margin-block-start: var(--space-8); scroll-margin-block-start: var(--nav-scroll-offset); }
.dk-section:first-child { margin-block-start: 0; }
.dk-page-teachers .dk-section { margin-block-start: var(--space-6); }

.dk-band {
  background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--radius-2xl); padding: var(--space-6) var(--space-5);
}
.dk-band--tint { background: var(--primary-surface); border-color: var(--success-border); }
.dk-band--sunken { background: var(--surface-sunken); }

.dk-sechead { margin-block-end: var(--space-5); }
.dk-sechead--center { text-align: center; }
.dk-eyebrow {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold);
  color: var(--on-primary-subtle); background: var(--primary-subtle);
  padding-block: var(--space-1); padding-inline: var(--space-3);
  border-radius: var(--radius-pill); margin: 0 0 var(--space-3);
}
.dk-h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0 0 var(--space-4); }
.dk-h2 { font-size: var(--fs-h3); line-height: var(--lh-h3); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0 0 var(--space-2); }
.dk-h3 { font-size: var(--fs-h5); line-height: var(--lh-h5); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0 0 var(--space-2); }
.dk-lede { font-size: var(--fs-body-lg); line-height: var(--lh-body-lg); color: var(--text-secondary); margin: 0; }
.dk-text { font-size: var(--fs-body); line-height: var(--lh-body); color: var(--text-secondary); margin: 0; }
.dk-note { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); margin: var(--space-3) 0 0; }
.dk-note i { color: var(--text-muted); margin-inline-end: var(--space-2); }

@media (min-width: 768px) {
  .dk-band { padding: var(--space-7) var(--space-6); }
  .dk-h1 { font-size: var(--fs-display); line-height: var(--lh-display); }
  .dk-h2 { font-size: var(--fs-h2); line-height: var(--lh-h2); }
}
/* teachers.html's page head/results head never scale up at 768px, and its
   .dk-band is flatter than the landing page's - these win at EVERY width by
   selector specificity (2 classes beats 1), not by source order. */
.dk-page-teachers .dk-band { padding: var(--space-5); }
.dk-page-teachers .dk-h1 { font-size: var(--fs-h2); line-height: var(--lh-h2); margin: 0 0 var(--space-2); }
.dk-page-teachers .dk-h2 { font-size: var(--fs-h4); line-height: var(--lh-h4); margin: 0; }

/* --- hero ------------------------------------------------------------- */
.dk-hero { text-align: center; }
.dk-hero .dk-h1 { max-inline-size: var(--measure-display); margin-inline: auto; }
.dk-hero__sub { max-inline-size: var(--measure-lede); margin-inline: auto; }
.dk-hero__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); margin-block-start: var(--space-6); }
.dk-hero__facts { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); margin-block-start: var(--space-6); }
.dk-fact {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding-block: var(--space-2); padding-inline: var(--space-4);
  border-radius: var(--radius-pill); background: var(--surface-raised);
  border: var(--hairline) solid var(--success-border);
  color: var(--text-secondary); font-size: var(--fs-small); line-height: var(--lh-small);
  font-weight: var(--fw-medium);
}
.dk-fact i { color: var(--primary-strong); }
.dk-hero__aside {
  display: inline-flex; align-items: center; gap: var(--space-2);
  margin: var(--space-5) 0 0;
  font-size: var(--fs-small); line-height: var(--lh-small);
  color: var(--text-secondary);            /* 7.24:1 on --primary-surface PASS */
}
.dk-hero__aside i { color: var(--primary-strong); }
.dk-hero__aside a { color: var(--text-link); font-weight: var(--fw-bold); }   /* 4.79:1 PASS */
.dk-hero__aside a:hover { color: var(--text-link-hover); }

/* --- stat strip --------------------------------------------------------- */
.dk-stat {
  background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--card-radius); padding: var(--space-5);
  box-shadow: var(--card-shadow); block-size: 100%;
  display: flex; align-items: center; gap: var(--space-4);
  transition: box-shadow var(--motion-base) var(--motion-ease);
}
.dk-stat:hover { box-shadow: var(--card-shadow-hover); }
.dk-stat__icon {
  inline-size: var(--icon-chip); block-size: var(--icon-chip); border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center; font-size: var(--icon-in-chip);
  background: var(--primary-subtle); color: var(--on-primary-subtle); flex-shrink: 0;
}
.dk-stat__icon--blue   { background: var(--accent-blue-surface);   color: var(--accent-blue-text); }
.dk-stat__icon--violet { background: var(--accent-violet-surface); color: var(--accent-violet-text); }
.dk-stat__icon--amber  { background: var(--accent-amber-surface);  color: var(--accent-amber-text); }
.dk-stat__num { font-size: var(--fs-h3); line-height: var(--lh-h3); font-weight: var(--fw-bold); color: var(--text-strong); }
.dk-stat__label { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); }

/* --- subject / stage browse ---------------------------------------------- */
.dk-subject {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  min-height: var(--tap-min); padding: var(--space-3) var(--space-4);
  background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--radius-md); text-decoration: none; block-size: 100%;
  transition: border-color var(--motion-fast) var(--motion-ease), box-shadow var(--motion-fast) var(--motion-ease);
}
.dk-subject:hover { border-color: var(--border-brand); box-shadow: var(--card-shadow-hover); }
.dk-subject__name { font-size: var(--fs-body); font-weight: var(--fw-bold); color: var(--text-strong); }
.dk-subject__count {
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold);
  color: var(--on-primary-subtle); background: var(--primary-subtle);
  padding-block: var(--space-1); padding-inline: var(--space-3);
  border-radius: var(--radius-pill); white-space: nowrap;
}
.dk-stagerow { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-block-end: var(--space-5); }
.dk-stagechip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  min-height: var(--tap-min); padding-inline: var(--space-5);
  border-radius: var(--radius-pill); border: var(--hairline) solid var(--border-input);
  background: var(--surface-raised); color: var(--text-strong);
  font-size: var(--fs-small); font-weight: var(--fw-bold); text-decoration: none;
}
.dk-stagechip:hover { background: var(--primary-subtle); border-color: var(--border-brand); color: var(--on-primary-subtle); }
.dk-stagechip i { color: var(--primary-strong); }

/* --- teacher card (shared shape - .dk-pin on "/", .dk-regionbadge/.dk-rating
   added on "/teachers" only, spec section 3.3 / NOTES.md section 7) -------- */
.dk-tcard {
  display: flex; flex-direction: column; block-size: 100%;
  background: var(--card-bg); border: var(--hairline) solid var(--card-border);
  border-radius: var(--card-radius); overflow: hidden; box-shadow: var(--card-shadow);
  transition: box-shadow var(--motion-base) var(--motion-ease), transform var(--motion-base) var(--motion-ease);
}
.dk-tcard:hover { box-shadow: var(--card-shadow-hover); transform: translateY(var(--card-lift-hover)); }
.dk-tcard__media { position: relative; background: var(--surface-sunken); }
.dk-tcard__img { inline-size: 100%; block-size: var(--media-h-card); object-fit: cover; display: block; }
.dk-tcard__fallback {
  inline-size: 100%; block-size: var(--media-h-card);
  display: flex; align-items: center; justify-content: center;
  background: var(--avatar-fallback-bg); color: var(--avatar-fallback-text);
  font-size: var(--fs-h2); font-weight: var(--fw-bold);
}
.dk-verified {
  position: absolute; inset-block-start: var(--space-2); inset-inline-end: var(--space-2);
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding-block: var(--space-1); padding-inline: var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--primary-strong); color: var(--on-primary);   /* 5.02:1 PASS - was 2.28:1 */
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold);
}
.dk-tcard__body { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); flex: 1 1 auto; }
.dk-tcard__name { font-size: var(--fs-h6); line-height: var(--lh-h6); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0; }
.dk-tcard__meta { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); margin: 0; }
.dk-tcard__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
.dk-tcard__price { font-size: var(--fs-body); font-weight: var(--fw-bold); color: var(--primary-strong); }  /* 5.02:1 PASS */
.dk-tcard__exp { font-size: var(--fs-small); color: var(--text-secondary); }
.dk-tcard__foot { margin-block-start: auto; padding-block-start: var(--space-2); }
.dk-pin { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-small); color: var(--text-secondary); }
.dk-pin i { color: var(--text-muted); }   /* role: map - never mirrored */
.dk-regionbadge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding-block: var(--space-1); padding-inline: var(--space-3);
  border-radius: var(--radius-pill); background: var(--neutral-surface);
  color: var(--neutral-text);                       /* 6.92:1 PASS */
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-medium);
}
/* rating: the number is ALWAYS written beside the star, and the star uses
   --rating-filled (3.19:1), never Bootstrap's .text-warning (1.63:1). */
.dk-rating { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-small); font-weight: var(--fw-bold); color: var(--text-strong); }
.dk-rating i { color: var(--rating-filled); }   /* role: star - never mirrored */

/* --- price / steps / features / compare / faq / calc / footer ------------ */
.dk-price {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-1);
  background: var(--surface-raised); border: var(--hairline) solid var(--success-border);
  border-radius: var(--card-radius); padding: var(--space-5); block-size: 100%;
}
.dk-price__num { font-size: var(--fs-h2); line-height: var(--lh-h2); font-weight: var(--fw-bold); color: var(--primary-strong); }
.dk-price__label { font-size: var(--fs-small); color: var(--text-secondary); }
.dk-price--accent { background: var(--primary-strong); border-color: var(--primary-strong); }
.dk-price--accent .dk-price__num, .dk-price--accent .dk-price__label { color: var(--on-primary); }  /* 5.02:1 PASS */

.dk-step {
  display: flex; gap: var(--space-4); block-size: 100%;
  background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--card-radius); padding: var(--space-5);
}
.dk-step__num {
  inline-size: var(--step-num-size); block-size: var(--step-num-size); flex-shrink: 0; border-radius: var(--radius-circle);
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-strong); color: var(--on-primary);   /* 5.02:1 PASS */
  font-weight: var(--fw-bold); font-size: var(--fs-h6);
}

.dk-feature {
  block-size: 100%; background: var(--surface-raised);
  border: var(--hairline) solid var(--border-subtle); border-radius: var(--card-radius);
  padding: var(--space-5);
}
.dk-feature__icon {
  inline-size: var(--icon-chip); block-size: var(--icon-chip); border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center; font-size: var(--icon-in-chip);
  background: var(--primary-subtle); color: var(--on-primary-subtle);
  margin-block-end: var(--space-3);
}

.dk-tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.dk-table { inline-size: 100%; border-collapse: collapse; min-inline-size: var(--table-min-w); }
.dk-table th, .dk-table td {
  padding: var(--table-cell-padding-y) var(--table-cell-padding-x);
  border-block-end: var(--hairline) solid var(--table-border);
  text-align: start; font-size: var(--fs-small); line-height: var(--lh-small);
  vertical-align: top;
}
.dk-table thead th { background: var(--table-head-bg); color: var(--table-head-text); font-weight: var(--fw-bold); }
.dk-table thead th.is-brand { color: var(--primary-strong); }
.dk-table tbody th { color: var(--text-strong); font-weight: var(--fw-bold); background: var(--surface-sunken); }
.dk-table td { color: var(--text-secondary); }
.dk-table td.is-brand { color: var(--text-strong); font-weight: var(--fw-medium); background: var(--primary-surface); }
.dk-table tbody tr:last-child th, .dk-table tbody tr:last-child td { border-block-end: 0; }

.dk-statusrow { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-block-start: var(--space-4); }
.dk-status {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding-block: var(--space-1); padding-inline: var(--space-3);
  border-radius: var(--radius-pill); font-size: var(--fs-caption);
  line-height: var(--lh-caption); font-weight: var(--fw-bold);
}
.dk-status--pending  { background: var(--warning-surface); color: var(--warning-text); }  /* 4.84:1 PASS */
.dk-status--accepted { background: var(--success-surface); color: var(--success-text); }  /* 6.81:1 PASS */
.dk-status--rejected { background: var(--danger-surface);  color: var(--danger-text); }   /* 5.91:1 PASS */
.dk-status--ended    { background: var(--neutral-surface); color: var(--neutral-text); }  /* 6.92:1 PASS */

.dk-faq { display: flex; flex-direction: column; gap: var(--space-3); }
.dk-faq__item { background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle); border-radius: var(--radius-md); overflow: hidden; }
.dk-faq__q {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  min-height: var(--tap-min); padding: var(--space-3) var(--space-4);
  font-size: var(--fs-body); font-weight: var(--fw-bold); color: var(--text-strong);
  cursor: pointer; list-style: none;
}
.dk-faq__q::-webkit-details-marker { display: none; }
.dk-faq__q:hover { background: var(--surface-hover); }
.dk-faq__q i { color: var(--text-muted); transition: transform var(--motion-fast) var(--motion-ease); }
.dk-faq__item[open] .dk-faq__q i { transform: rotate(180deg); }
.dk-faq__a { padding: 0 var(--space-4) var(--space-4); font-size: var(--fs-small); line-height: var(--lh-body-lg); color: var(--text-secondary); margin: 0; }

.dk-field { display: flex; flex-direction: column; margin-block-end: var(--space-4); }
.dk-page-teachers .dk-field { margin-block-end: 0; }   /* inside a Bootstrap g-3 grid row - the gutter already spaces fields */
.dk-label { font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold); color: var(--text-strong); margin-block-end: var(--field-label-gap); }
.dk-input {
  /* T25 (NOTES.md 6-4): min-block-size, not a fixed block-size - a single-line
     input still lands at exactly --field-height (its content never asks for
     more), but this lets textarea.dk-input (T25 below) grow to its own
     min-height instead of being clipped to 44px. */
  min-block-size: var(--field-height); padding-inline: var(--field-padding-x);
  border: var(--hairline) solid var(--field-border); border-radius: var(--field-radius);
  background: var(--field-bg); color: var(--text-body);
  font-family: inherit; font-size: var(--fs-body); inline-size: 100%;
  transition: border-color var(--motion-fast) var(--motion-ease), box-shadow var(--motion-fast) var(--motion-ease);
}
.dk-input:hover { border-color: var(--field-border-hover); }
.dk-input:focus-visible { border-color: var(--border-brand); box-shadow: var(--focus-ring-halo); }
.dk-input[disabled] { background: var(--field-bg-disabled); border-color: var(--border-default); color: var(--text-disabled); cursor: not-allowed; }
.dk-input[aria-invalid="true"] { border-color: var(--field-border-error); border-width: var(--hairline-strong); }
/* design review 2026-08-25 [MAJOR follow-up, found while verifying it]: the border above IS
   red once focus lands (confirmed via computed style), but the base :focus-visible rule
   (section 1 near the top of this file) paints a 3px SOLID GREEN outline on every focusable
   element unconditionally, and .dk-input:focus-visible's own green box-shadow halo layers on
   top of that - together they visually drown the thin red border the instant the field the
   fix moves focus to is also invalid (T26's reject-reason field, but this is a T25-era gap in
   the shared .dk-input component, so it silently affected every other field's error state
   too). The approved mockup already carried the fix for this exact combination
   (docs/design/admin-teacher-applications/detail-pending.html) - ported verbatim. */
.dk-input[aria-invalid="true"]:focus-visible { outline-color: var(--focus-ring-color-danger); }
/* T25: a multi-line .dk-input (the Bio field) - own radius, resize handle, floor height. */
textarea.dk-input { border-radius: var(--field-radius-multiline); resize: vertical; min-block-size: var(--textarea-min-h); padding-block: var(--space-3); }
/* T25 (NOTES.md 6-4): select needs room for the chevron .dk-selectwrap positions,
   and optgroup/option get their own weights - .dk-select (teachers.html filters)
   already had this; .dk-input as a <select> did not. */
select.dk-input { appearance: none; -webkit-appearance: none; padding-inline-end: var(--space-7); cursor: pointer; }
select.dk-input optgroup { font-weight: var(--fw-bold); color: var(--text-secondary); }
select.dk-input option { color: var(--text-body); font-weight: var(--fw-regular); }
/* T25 (THEME 2-5, NOTES.md 6-4): help/error are full sentences here, not a short
   caption - 12px (--fs-caption) is below THEME's "no continuous Arabic under
   14px" floor. Bumped to --fs-small for every .dk-help/.dk-error on the site
   (also the "/" calculator and "/teachers" filters) - disclosed in the T25 report. */
.dk-help { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); margin: var(--field-help-gap) 0 0; padding-inline-start: var(--space-4); }
.dk-error {
  display: flex; align-items: flex-start; gap: var(--space-2);
  font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-medium);
  color: var(--danger-text); margin: var(--field-help-gap) 0 0; padding-inline-start: var(--space-4);
}
.dk-error i { margin-block-start: var(--space-1); }

.dk-calc__out {
  background: var(--surface-raised); border: var(--hairline) solid var(--success-border);
  border-radius: var(--card-radius); padding: var(--space-5); text-align: center;
}
.dk-calc__amount { font-size: var(--fs-h2); line-height: var(--lh-h2); color: var(--primary-strong); }
.dk-calc__sentence { font-size: var(--fs-body); line-height: var(--lh-body-lg); color: var(--text-strong); margin: 0; }

.dk-footer { border-block-start: var(--hairline) solid var(--border-subtle); margin-block-start: var(--space-8); padding-block-start: var(--space-6); }
.dk-footer__title { font-size: var(--fs-h6); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0 0 var(--space-3); }
.dk-footer__link { display: flex; align-items: center; min-height: var(--tap-min); color: var(--text-secondary); font-size: var(--fs-small); text-decoration: none; }
.dk-footer__link:hover { color: var(--text-link-hover); text-decoration: underline; }
.dk-footer__legal {
  border-block-start: var(--hairline) solid var(--border-subtle); margin-block-start: var(--space-5);
  padding-block-start: var(--space-4); font-size: var(--fs-small); color: var(--text-secondary);
}

/* --- "/teachers": filters, proximity row, map, results, pagination -------- */
.dk-filters { display: block; }
.dk-selectwrap { position: relative; display: block; }
.dk-selectwrap > i {
  position: absolute; inset-inline-end: var(--space-4); inset-block-start: 50%;
  transform: translateY(-50%); pointer-events: none; color: var(--text-muted);
  font-size: .8em;   /* role: chevron - not directional, never mirrored */
}
.dk-select {
  appearance: none; -webkit-appearance: none;
  block-size: var(--field-height); inline-size: 100%;
  padding-inline: var(--space-4) var(--space-8);
  border: var(--hairline) solid var(--field-border); border-radius: var(--field-radius);
  background: var(--field-bg); color: var(--text-body);
  font-family: inherit; font-size: var(--fs-small); cursor: pointer;
  transition: border-color var(--motion-fast) var(--motion-ease), box-shadow var(--motion-fast) var(--motion-ease);
}
.dk-select:hover { border-color: var(--field-border-hover); }
.dk-select:focus-visible { border-color: var(--border-brand); box-shadow: var(--focus-ring-halo); }
.dk-select[disabled] { background: var(--field-bg-disabled); border-color: var(--border-default); color: var(--text-disabled); cursor: not-allowed; }
select.dk-select--sm { block-size: 36px; font-size: var(--fs-caption); }
.dk-input--sm { block-size: 36px; font-size: var(--fs-caption); padding-inline: var(--space-3); }
/* .dk-select--sm on a <details> (the status checkbox dropdown) must size only its closed-state
   trigger, never the <details> element itself - a fixed block-size there would clip the panel
   when open. */
.dk-statusfilter.dk-select--sm > summary { block-size: 36px; font-size: var(--fs-caption); }

/* Checkbox-dropdown multi-select (the QA status filter, Osama's explicit correction 2026-09-12:
   a native <select multiple> read as an unprofessional listbox - a real dropdown with checkboxes
   is expected). <details>/<summary> gives free keyboard toggling with no extra JS; the summary is
   styled to be visually identical to .dk-select when closed (same tokens, not copy-pasted values). */
.dk-statusfilter { position: relative; }
.dk-statusfilter > summary {
  list-style: none; display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  block-size: var(--field-height); padding-inline: var(--space-4);
  border: var(--hairline) solid var(--field-border); border-radius: var(--field-radius);
  background: var(--field-bg); color: var(--text-body);
  font-family: inherit; font-size: var(--fs-small); cursor: pointer;
}
.dk-statusfilter > summary::-webkit-details-marker { display: none; }
.dk-statusfilter > summary:hover { border-color: var(--field-border-hover); }
.dk-statusfilter > summary:focus-visible { outline: none; border-color: var(--border-brand); box-shadow: var(--focus-ring-halo); }
.dk-statusfilter[open] > summary { border-color: var(--border-brand); }
.dk-statusfilter > summary > i { color: var(--text-muted); font-size: .8em; pointer-events: none; }
.dk-statusfilter__panel {
  position: absolute; inset-inline-start: 0; inset-block-start: calc(100% + var(--space-2)); z-index: 20;
  min-inline-size: 100%; padding: var(--space-3);
  border: var(--hairline) solid var(--field-border); border-radius: var(--field-radius);
  background: var(--surface-raised); box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; gap: var(--space-2);
}
.dk-statusfilter__option { white-space: nowrap; }
.dk-statusfilter__actions {
  display: flex; justify-content: flex-end; gap: var(--space-2);
  padding-block-start: var(--space-3); margin-block-start: var(--space-2);
  border-block-start: var(--hairline) solid var(--border-default);
}

.dk-segrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.dk-seglabel { font-size: var(--fs-small); font-weight: var(--fw-bold); color: var(--text-secondary); }
.dk-seg {
  display: inline-flex; align-items: center; gap: var(--space-2);
  min-height: var(--tap-min); padding-inline: var(--space-4);
  border: var(--hairline) solid var(--border-input); border-radius: var(--radius-pill);
  background: var(--surface-raised); color: var(--text-strong);
  font-size: var(--fs-small); font-weight: var(--fw-medium); text-decoration: none;
  cursor: pointer;
}
.dk-seg:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-seg[aria-current="true"] {
  background: var(--primary-strong); border-color: var(--primary-strong);
  color: var(--on-primary); font-weight: var(--fw-bold);   /* 5.02:1 PASS */
}
.dk-seg[aria-current="true"] i { color: var(--on-primary); }
.dk-seg i { color: var(--text-muted); }
.dk-locstatus { font-size: var(--fs-small); color: var(--text-secondary); }

.dk-maphead {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-h6); font-weight: var(--fw-bold); color: var(--text-strong);
  padding: var(--space-4) var(--space-5) var(--space-3);
}
.dk-maphead i { color: var(--primary-strong); }   /* role: map - never mirrored */
/* FIXED height so a late-loading map cannot shift the page. */
.dk-map { block-size: var(--media-h-map); margin: 0 var(--space-4) var(--space-4); border-radius: var(--radius-lg); overflow: hidden; }

.dk-resulthead { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; margin-block-end: var(--space-4); }
.dk-count {
  display: inline-flex; align-items: center; min-height: var(--count-badge-h);
  padding-inline: var(--space-3); border-radius: var(--radius-pill);
  background: var(--primary-subtle); color: var(--on-primary-subtle);   /* 6.49:1 PASS */
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  margin-inline-start: var(--space-2);
}
.dk-pagestate { font-size: var(--fs-small); color: var(--text-secondary); }

.dk-empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
  padding: var(--space-8) var(--space-5); text-align: center;
  background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--card-radius);
}
.dk-empty > i { font-size: var(--icon-2xl); color: var(--text-decorative); }
/* QA #35: the selector above was a DESCENDANT one, so it also hit the <i> inside every
   .dk-empty__actions button - the empty-state action buttons rendered with a decorative
   2xl grey icon that dwarfed their own label and forced the row to wrap. The decorative
   icon is always a DIRECT child of .dk-empty (verified across every .dk-empty in the
   views), so '>' keeps the intended target and releases the button icons back to the
   .dk-btn sizing every other button on the site already uses. */
.dk-empty__title { font-size: var(--fs-h5); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0; }
/* ticket #32: Library/Search.cshtml's no-results state now offers two return paths (library +
   curricula) - same display:flex + gap shape as .dk-hero__actions/.dk-toolbar__actions. */
.dk-empty__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); }

.dk-pager { display: flex; justify-content: center; gap: var(--space-2); flex-wrap: wrap; margin-block-start: var(--space-6); padding: 0; list-style: none; }
.dk-pager a, .dk-pager span {
  min-inline-size: var(--tap-min); min-block-size: var(--tap-min);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding-inline: var(--space-3); border-radius: var(--radius-pill);
  border: var(--hairline) solid var(--border-default); background: var(--surface-raised);
  color: var(--text-strong); font-size: var(--fs-small); font-weight: var(--fw-medium);
  text-decoration: none;
}
.dk-pager a:hover { background: var(--surface-hover); border-color: var(--border-input); }
.dk-pager [aria-current="page"] {
  background: var(--primary-strong); border-color: var(--primary-strong);
  color: var(--on-primary); font-weight: var(--fw-bold);   /* 5.02:1 PASS */
}
.dk-pager [aria-disabled="true"] {
  background: var(--surface-disabled); border-color: var(--border-default);
  color: var(--text-disabled); pointer-events: none;
}

/* --- base breakpoint (<576px) - THEME.md section 4 breakpoint table:
   "one column, two teacher cards per row, tables become cards". ------------ */
@media (max-width: 575.98px) {
  .dk-tcard__body { padding: var(--space-3); }
  .dk-tcard .dk-btn { font-size: var(--fs-caption); }

  .dk-tablewrap { overflow-x: visible; }
  .dk-table { min-inline-size: 0; }
  .dk-table thead { position: absolute; inline-size: var(--hairline); block-size: var(--hairline); overflow: hidden; clip: rect(0, 0, 0, 0); }
  .dk-table tbody tr { display: block; border-block-end: var(--hairline) solid var(--table-border); }
  .dk-table tbody tr:last-child { border-block-end: 0; }
  .dk-table tbody th,
  .dk-table tbody td { display: block; border-block-end: 0; inline-size: auto; }
  .dk-table tbody th { background: var(--surface-sunken); }
  .dk-table tbody td::before {
    content: attr(data-label);
    display: block;
    font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold);
    color: var(--text-muted); margin-block-end: var(--space-1);
  }
  .dk-table tbody td.is-brand::before { color: var(--primary-strong); }
}

/* --- T26 spec §5-c: large rectangular photo fallback (profile hero image, 250px) - the third
   size in this family alongside .dk-tcard__fallback (card media, 160px) and .dk-avatar--fallback
   (small circular avatars). Neither of those fits here: dk-avatar is a circle, and
   dk-tcard__fallback is locked to --media-h-card (160px), too short for the profile hero. --- */
.dk-photo-fallback {
  inline-size: 100%; block-size: var(--photo-hero-h);
  display: flex; align-items: center; justify-content: center;
  background: var(--avatar-fallback-bg); color: var(--avatar-fallback-text);
  font-size: var(--fs-h1); font-weight: var(--fw-bold);
  border-radius: var(--card-radius) var(--card-radius) 0 0;
}

/* =============================================================================
   /teacher/apply (T25) - ported from docs/design/teacher-apply/{index,errors,
   pending,rejected}.html per NOTES.md section 6-3's "new classes" list. Icons
   are Font Awesome <i> (NOTES.md 6-5: the app still loads FA; SVG-role icons
   arrive with T18) instead of the mockup's inline-SVG sprite - same THEME 3-3
   roles, different implementation. .dk-h1/.dk-h2/.dk-lede/.dk-text/.dk-note and
   .dk-footer* are NOT redefined here - NOTES.md 6-2 lists them as reused as-is
   from the "MARKETING PAGE" block above.
   ========================================================================== */

.dk-page { max-inline-size: var(--form-max-w); margin-inline: auto; display: flex; flex-direction: column; gap: var(--space-5); }
.dk-page__head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2); }

/* --- card (THEME 3-1 "بطاقة") - distinct from the legacy .card/.teacher-card/
   .stat-card Bootstrap-era classes; this is the token-driven version. --------- */
.dk-card { background: var(--card-bg); border: var(--hairline) solid var(--card-border); border-radius: var(--card-radius); box-shadow: var(--card-shadow); }
.dk-card__head { padding: var(--space-4) var(--space-5); border-block-end: var(--hairline) solid var(--border-subtle); display: flex; align-items: center; gap: var(--space-2); }
.dk-card__head i { color: var(--text-brand); }
.dk-card__body { padding: var(--space-5); }
@media (min-width: 768px) {
  .dk-card__head { padding-inline: var(--space-6); }
  .dk-card__body { padding: var(--space-6); }
}

/* --- badges (THEME 3-1 "شارة حالة": pill, 12px, bold, Arabic text always) --- */
.dk-badge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--badge-padding-y) var(--badge-padding-x); border-radius: var(--badge-radius);
  font-size: var(--badge-font-size); line-height: var(--lh-caption); font-weight: var(--badge-font-weight);
  border: var(--hairline) solid transparent; white-space: nowrap;
}
.dk-badge i { font-size: var(--icon-sm); }
.dk-badge--warning { background: var(--warning-surface); color: var(--warning-text); border-color: var(--warning-border); }  /* 4.84:1 PASS */
.dk-badge--success { background: var(--success-surface); color: var(--success-text); border-color: var(--success-border); }  /* 6.81:1 PASS */
.dk-badge--danger  { background: var(--danger-surface);  color: var(--danger-text);  border-color: var(--danger-border); }   /* 5.91:1 PASS */

/* --- alerts (THEME 3-1 "تنبيه": surface + border + text of the state pair, WITH an icon) --- */
.dk-alert {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-md);
  border: var(--hairline) solid transparent;
  font-size: var(--fs-small); line-height: var(--lh-small);
}
.dk-alert__i { margin-block-start: var(--space-1); font-size: var(--icon-lg); }
.dk-alert__b { flex: 1 1 auto; min-inline-size: 0; }
.dk-alert__b p { margin: 0; }
.dk-alert__b p + p { margin-block-start: var(--space-1); }
.dk-alert__b ul { margin: var(--space-2) 0 0; padding-inline-start: var(--space-5); }
.dk-alert__b li + li { margin-block-start: var(--space-1); }
.dk-alert a { color: inherit; font-weight: var(--fw-bold); text-decoration: underline; text-underline-offset: .15em; }
.dk-alert a:hover { text-decoration-thickness: from-font; }
.dk-alert__b li a { display: inline-block; min-block-size: var(--tap-floor); }   /* THEME 4-9: nothing under 24px, even an inline link */
.dk-alert__close { margin-inline-start: auto; margin-block: calc(var(--space-2) * -1); color: inherit; }
.dk-alert--success { background: var(--success-surface); border-color: var(--success-border); color: var(--success-text); }  /* 6.81:1 PASS */
.dk-alert--warning { background: var(--warning-surface); border-color: var(--warning-border); color: var(--warning-text); }  /* 4.84:1 PASS */
.dk-alert--danger  { background: var(--danger-surface);  border-color: var(--danger-border);  color: var(--danger-text); }   /* 5.91:1 PASS */
.dk-alert--info    { background: var(--info-surface);    border-color: var(--info-border);    color: var(--info-text); }     /* 6.16:1 PASS */
.dk-alert:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring-color-danger); outline-offset: var(--focus-ring-offset); }

/* ==========================================================================
   FORM (THEME 3-2: one column, label above, optional marked, specific errors,
   clickable summary, loading submit, help text with aria-describedby)
   ========================================================================== */
.dk-form { display: flex; flex-direction: column; gap: var(--space-5); }
/* Reconciliation: the pre-existing global .dk-field (used by the "/" calculator
   and "/teachers" filters) carries its own margin-block-end for contexts with no
   parent gap. Inside .dk-form the gap above IS the spacing mechanism, so the
   field's own margin is zeroed here - scoped to .dk-form only, so nothing
   outside this page is affected. */
.dk-form .dk-field { margin-block-end: 0; }
.dk-fieldset { border: 0; padding: 0; margin: 0; min-inline-size: 0; }
.dk-fieldset > legend { float: none; inline-size: auto; padding: 0; margin: 0 0 var(--field-label-gap); }  /* undo Bootstrap's legend reset */
.dk-label__opt { font-weight: var(--fw-regular); color: var(--text-secondary); font-size: var(--fs-caption); }
.dk-fieldfoot { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-3); flex-wrap: wrap; }
.dk-counter { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); white-space: nowrap; padding-inline-end: var(--space-4); margin-inline-start: auto; }
.dk-counter.is-max { color: var(--danger-text); font-weight: var(--fw-bold); }

/* --- choice cards (THEME 3-1 "بطاقة اختيار": border --border-default, radius-lg, h-100,
       selected = border + surface + check mark, never colour alone; Register.cshtml pattern) --- */
.dk-choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.dk-choice {
  position: relative; display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--space-2); block-size: 100%; min-block-size: var(--tap-min);
  padding: var(--space-4) var(--space-3);
  background: var(--surface-raised); border: var(--hairline-strong) solid var(--border-default);
  border-radius: var(--radius-lg); cursor: pointer; margin: 0;
  transition: border-color var(--motion-fast) var(--motion-ease), background var(--motion-fast) var(--motion-ease);
}
.dk-choice:hover { border-color: var(--border-brand); }
.dk-choice:focus-within { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
.dk-choice:has(input:checked), .dk-choice.is-selected { border-color: var(--primary-strong); background: var(--primary-surface); }
.dk-choice__icon {
  inline-size: var(--icon-chip); block-size: var(--icon-chip); border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center; font-size: var(--icon-lg);
  background: var(--surface-sunken); color: var(--text-secondary);
}
.dk-choice:has(input:checked) .dk-choice__icon, .dk-choice.is-selected .dk-choice__icon { background: var(--primary-subtle); color: var(--on-primary-subtle); }
.dk-choice__t { font-size: var(--fs-body); font-weight: var(--fw-bold); color: var(--text-strong); }
.dk-choice__h { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); }
.dk-choice__mark { position: absolute; inset-block-start: var(--space-2); inset-inline-start: var(--space-2); color: var(--primary-strong); display: none; font-size: var(--icon-sm); }
.dk-choice:has(input:checked) .dk-choice__mark, .dk-choice.is-selected .dk-choice__mark { display: block; }
.dk-choices.is-error .dk-choice { border-color: var(--danger-strong); }
.dk-choice.is-disabled { opacity: .5; pointer-events: none; }
@media (max-width: 359.98px) { .dk-choices { grid-template-columns: minmax(0, 1fr); } }

/* --- submit row --- */
.dk-submit { display: flex; flex-direction: column; gap: var(--space-3); padding-block-start: var(--space-2); border-block-start: var(--hairline) solid var(--border-subtle); }
.dk-submit .dk-btn { inline-size: 100%; }
@media (min-width: 576px) {
  .dk-submit { flex-direction: row; align-items: center; justify-content: space-between; }
  .dk-submit .dk-btn { inline-size: auto; }
}

/* --- loading button state (THEME 3-1: keeps the brand fill, adds a spinner,
       the WIDTH is frozen by teacher-apply.js) --- */
.dk-spinner {
  inline-size: 1em; block-size: 1em; flex: none;
  border: var(--hairline-strong) solid currentColor; border-block-start-color: transparent;
  border-radius: var(--radius-circle);
  animation: dk-spin calc(var(--motion-slow) * 2) linear infinite;
}
@keyframes dk-spin { to { transform: rotate(360deg); } }
.dk-btn.is-loading, .dk-btn.is-loading[disabled] {
  background: var(--primary-strong); color: var(--on-primary); border-color: var(--primary-strong);
  cursor: progress; pointer-events: none;
}

/* --- read-only summary (Pending state): a definition list, label column from sm up --- */
.dk-dl { margin: 0; display: flex; flex-direction: column; }
.dk-dl__row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-1); padding-block: var(--space-3); border-block-end: var(--hairline) solid var(--border-subtle); }
.dk-dl__row:first-child { padding-block-start: 0; }
.dk-dl__row:last-child { border-block-end: 0; padding-block-end: 0; }
.dk-dl dt { font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold); color: var(--text-secondary); margin: 0; }
.dk-dl dd { margin: 0; font-size: var(--fs-body); line-height: var(--lh-body); color: var(--text-strong); overflow-wrap: anywhere; }
@media (min-width: 576px) {
  .dk-dl__row { grid-template-columns: minmax(0, var(--dl-label-w)) minmax(0, 1fr); gap: var(--space-4); align-items: start; }
}

.dk-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.dk-actions .dk-btn { flex: 1 1 auto; }
@media (min-width: 576px) { .dk-actions .dk-btn { flex: 0 0 auto; } }

/* --- applicant role badge (T25: UserType=Teacher without the Teacher role yet -
   neutral, never the --teacher warning badge, since the role is not granted
   until T26 approval) - alongside the existing --admin/--guardian/--teacher. --- */
.dk-rolebadge--applicant { background: var(--neutral-surface); color: var(--neutral-text); }   /* 6.92:1 PASS */

.dk-avatar--md { inline-size: var(--avatar-md); block-size: var(--avatar-md); }
.dk-menu__user { display: flex; align-items: center; gap: var(--space-3); }
.dk-menu__username { font-weight: var(--fw-bold); }
.dk-menu__subtitle { display: block; font-size: var(--fs-caption); color: var(--text-secondary); }
.dk-drawer__title { font-size: var(--fs-h6); line-height: var(--lh-h6); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0; }
.dk-drawer__username { font-weight: var(--fw-bold); font-size: var(--fs-small); }

/* =============================================================================
   /admin/* SHELL + /admin/teacher-applications (T26) - ported from
   docs/design/admin-teacher-applications/{list,list-empty,detail-pending,
   detail-approved,detail-rejected}.html per NOTES.md section 6. Existing
   components are REUSED before new ones are added (disclosed in
   docs/handoff/T26-views.md): .dk-card/.dk-card__head/.dk-card__body,
   .dk-dl/.dk-dl__row (--dl-label-w), .dk-empty/.dk-empty__title/.dk-text,
   .dk-badge/.dk-badge--warning/success/danger, .dk-field/.dk-label/.dk-input/
   .dk-fieldfoot/.dk-counter/.dk-help/.dk-error, .dk-spinner, .admin-sidebar/
   .admin-nav-link (names kept per NOTES.md section 6-2 "reused as-is" - only
   the active-state fix above and the responsive rules below are new).
   Icons stay Font Awesome <i> (NOTES.md section 4 conflict 6: _Icon/SVG is
   T18, not built yet) - same THEME 3-3 roles as the mockup's inline SVG.
   ========================================================================== */

/* --- 1. ADMIN SHELL - mobile top bar + drawer below 768px (T22.7 direction,
   THEME section 9 #16 / PROGRESS.md T22.7 debt row 1). >=768px unchanged from
   the sticky 240px sidebar that already shipped. ---------------------------- */
.admin-topbar {
  display: none;
}
.admin-shell {
  display: flex;
  min-block-size: 100vh;
}
/* the column keeps the sidebar's surface + border running the full page
   height; the sidebar itself stays sticky at 100vh exactly as before
   (NOTES.md decision 24 - without this the border/background used to cut off
   at the bottom of the viewport on pages taller than 100vh). */
.admin-sidecol {
  flex: none;
  inline-size: var(--sidebar-width);
  background: var(--bg-card);
  border-inline-end: var(--hairline) solid var(--border-light);
}
.admin-sidebar {
  inline-size: var(--sidebar-width);
  position: sticky;
  inset-block-start: 0;
  block-size: 100vh;
  overflow-y: auto;
}
.admin-sidebar__brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
/* design review 2026-08-25 MINOR: the sidebar brand link inherited Bootstrap's
   default blue instead of matching .admin-topbar__brand's --text-strong, so
   the same logo read two different colours between desktop and the mobile
   top bar. */
.admin-sidebar__brand a {
  color: var(--text-strong);
}
.admin-sidebar__close {
  display: none;   /* drawer-only control */
}
.admin-content {
  flex: 1 1 auto;
  min-inline-size: 0;
  padding: var(--space-5);
}
.admin-scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: var(--z-offcanvas-scrim);
  border: 0;
  padding: 0;
  cursor: default;
}

@media (max-width: 767.98px) {
  .admin-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    position: sticky;
    inset-block-start: 0;
    z-index: var(--z-sticky);
    min-block-size: var(--navbar-height);
    padding-inline: var(--space-4);
    background: var(--surface-raised);
    border-block-end: var(--hairline) solid var(--border-subtle);
  }
  .admin-shell {
    display: block;
  }
  .admin-sidecol {
    display: contents;
  }
  .admin-sidebar {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    block-size: 100dvh;
    z-index: var(--z-offcanvas);
    transform: translateX(100%);
    transition: transform var(--motion-base) var(--motion-ease);
    visibility: hidden;
    box-shadow: none;
  }
  .admin-sidebar.is-open {
    transform: none;
    visibility: visible;
    box-shadow: var(--shadow-xl);
  }
  .admin-sidebar__brand {
    padding: var(--space-3) var(--space-4);
    border-block-end: var(--hairline) solid var(--border-subtle);
  }
  .admin-sidebar__close {
    display: inline-grid;
  }
  .admin-content {
    padding: var(--space-4);
  }
}

.admin-topbar__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: var(--tap-min);
  color: var(--text-strong);
  font-weight: var(--fw-bold);
  text-decoration: none;
}

/* .dk-iconbtn itself already exists (T22.8 navbar block above) - reused as-is
   for the drawer's open/close buttons and the modal close button. Only the
   "sm" size (used inside the modal header, THEME 3-1 "36px, floor 24px") is
   new. */
.dk-iconbtn--sm { inline-size: var(--btn-height-sm); block-size: var(--btn-height-sm); }

/* sidebar count badge (spec section 3/5: COUNT(Status = Pending), hidden at
   zero - the server already only renders the <span> when the count is > 0).
   margin-inline-start:auto alone pushes it to the far end - .admin-nav-link
   is already display:flex, no justify-content change needed on the parent. */
.admin-nav-link__count { margin-inline-start: auto; min-inline-size: var(--count-badge-h); justify-content: center; }

/* --- 2. PAGE HEADER (back link, title row, actions, meta line) ------------ */
.adm-back {
  display: inline-flex; align-items: center; gap: var(--space-2); min-block-size: var(--tap-min);
  color: var(--text-secondary); text-decoration: none; font-size: var(--fs-small); font-weight: var(--fw-medium);
  margin-block-end: var(--space-3);
}
.adm-back:hover { color: var(--text-brand); text-decoration: underline; }
.adm-back i { transition: transform var(--motion-fast) var(--motion-ease); }
[dir="rtl"] .adm-back i { transform: scaleX(-1); }   /* role: back - directional, mirrors in RTL */

.adm-head {
  display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between;
  gap: var(--space-3) var(--space-4); margin-block-end: var(--space-5);
}
.adm-head__t { display: flex; flex-direction: column; gap: var(--space-2); min-inline-size: 0; }
.adm-head__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
h1.adm-h1 { font-size: var(--fs-h4); line-height: var(--lh-h4); font-weight: var(--fw-bold); margin: 0; overflow-wrap: anywhere; }
.adm-meta {
  display: flex; flex-wrap: nowrap; align-items: flex-start; gap: var(--space-1) var(--space-3);
  color: var(--text-secondary); font-size: var(--fs-small); line-height: var(--lh-small); margin: 0;
}
.adm-meta i { color: var(--text-muted); margin-block-start: var(--space-1); }
.adm-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
@media (min-width: 768px) { h1.adm-h1 { font-size: var(--fs-h3); line-height: var(--lh-h3); } }
@media (max-width: 575.98px) { .adm-actions { inline-size: 100%; } .adm-actions .dk-btn { flex: 1 1 auto; } }

.adm-alerts { display: flex; flex-direction: column; gap: var(--space-3); margin-block-end: var(--space-5); }

/* --- 3. TABS - links that re-render the list with ?status=... (spec 5) ---- */
.dk-tabs {
  display: flex; gap: var(--space-2); border-block-end: var(--hairline) solid var(--border-subtle);
  overflow-x: auto; -webkit-overflow-scrolling: touch; margin-block-end: var(--space-4);
}
.dk-tab {
  display: inline-flex; align-items: center; gap: var(--space-2); white-space: nowrap;
  min-block-size: var(--tap-min); padding-inline: var(--space-3); background: none; border: 0;
  border-block-end: var(--marker-w) solid transparent; color: var(--text-secondary); text-decoration: none;
  font-family: inherit; font-size: var(--fs-small); font-weight: var(--fw-medium); cursor: pointer; flex: none;
}
.dk-tab:hover { color: var(--text-strong); }
.dk-tab[aria-selected="true"] { color: var(--text-brand); border-block-end-color: var(--primary-strong); font-weight: var(--fw-bold); }

/* --- 4. BADGES / BUTTONS - the two pieces .dk-badge and .dk-btn did not
   already carry (count pill, solid danger button - spec section 4's ruling
   "تغييرات بعد الكتابة" 2026-08-24-a: solid, NOT outline). -------------------- */
.dk-badge--count { background: var(--primary-subtle); color: var(--on-primary-subtle); border-color: var(--success-border); }
.dk-badge--lg { font-size: var(--fs-small); padding-inline: var(--space-4); }

.dk-btn--danger { background: var(--danger-strong); color: var(--on-danger); border-color: var(--danger-strong); }   /* 4.83:1 PASS */
.dk-btn--danger:hover { background: var(--danger-text); border-color: var(--danger-text); color: var(--on-danger); }
.dk-btn--danger:active { transform: translateY(var(--press-offset)); }
.dk-btn--danger:focus-visible { outline-color: var(--focus-ring-color-danger); }
/* loading state reuses .is-loading (already shipped for T25's submit button,
   same .dk-spinner) - no separate [aria-busy] rule needed; aria-busy is set
   alongside .is-loading purely for assistive tech, not for visual styling.
   The existing .dk-btn.is-loading rule hard-codes --primary-strong (it only
   ever had T25's green submit button to serve) - overridden here so a
   loading .dk-btn--danger (the reject button) stays red instead of flashing
   green. Same specificity (two classes each); this rule wins on source order
   since it is appended after the base one. */
.dk-btn--danger.is-loading, .dk-btn--danger.is-loading[disabled] {
  background: var(--danger-strong); color: var(--on-danger); border-color: var(--danger-strong);
}

/* T27 - "إزالة الصورة" trigger (opens the confirm modal): bordered but not filled, distinct
   from both the solid .dk-btn--danger above (T26's modal-confirm button) and the borderless
   .dk-btn--danger-ghost (menu/tertiary rows) - ported verbatim from
   docs/design/teacher-profile-edit/filled.html. */
.dk-btn--danger-outline { background: var(--surface-raised); color: var(--danger-text); border-color: var(--danger-strong); }  /* text 5.91:1 - border 4.83:1 */
.dk-btn--danger-outline:hover { background: var(--danger-surface); color: var(--danger-text); }
.dk-btn--danger-outline:active { background: var(--danger-border); transform: translateY(var(--press-offset)); }
.dk-btn--danger-outline:focus-visible { outline-color: var(--focus-ring-color-danger); }

/* generic disabled state (THEME 3-1 matrix) - the base .dk-btn never had one;
   only the loading combination above did. Excludes .is-loading, which keeps
   its own brand-coloured "still processing" look instead of fading to grey. */
.dk-btn:disabled:not(.is-loading), .dk-btn[aria-disabled="true"]:not(.is-loading) {
  background: var(--surface-disabled); color: var(--text-disabled); border-color: var(--border-default);
  cursor: not-allowed;
}

.dk-card__title { font-size: var(--fs-h6); line-height: var(--lh-h6); font-weight: var(--fw-bold); margin: 0; }

/* --- 5. TABLE - row-link (ONE wrapping link per row, spec section 5) + the
   mobile-card modifier for this specific 9-column table. Scoped under
   .dk-table--apps / .is-link so the shared .dk-table used elsewhere (T22.8
   compare table) is completely untouched. --------------------------------- */
.dk-table--apps { min-inline-size: var(--table-min-w-wide); }
.dk-table tbody tr.is-link { position: relative; }
.dk-table tbody tr.is-link:hover { background: var(--table-row-hover); }
.adm-rowlink { color: var(--text-strong); font-weight: var(--fw-bold); text-decoration: none; }
.adm-rowlink::after { content: ""; position: absolute; inset: 0; }
.dk-table tbody tr.is-link:hover .adm-rowlink { color: var(--text-brand); text-decoration: underline; }
.dk-table tbody tr.is-link:has(.adm-rowlink:focus-visible) {
  outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: calc(-1 * var(--focus-ring-width));
}
@supports selector(tr:has(a:focus-visible)) { .adm-rowlink:focus-visible { outline: none; } }
.dk-table--apps .is-name { white-space: nowrap; }
.dk-table--apps .is-price { white-space: nowrap; }
.dk-table--apps td time { white-space: nowrap; }
/* design review 2026-08-25 MINOR: mockup's .dk-table .is-email rule was never
   ported - dims the e-mail cell against the bold applicant name. */
.dk-table--apps .is-email { color: var(--text-secondary); }

/* QA #37 - a row whose approve/reject controls are disabled because a DIFFERENT row in the
   same table has a pending (undo-able) action in flight. Same is-disabled naming .dk-choice
   already uses for its own disabled state; the controls themselves already look disabled via
   the existing .dk-btn[disabled]/[aria-disabled="true"] rules, this only dims the row as a
   whole so it reads as "not actionable right now" at a glance. */
.dk-table tbody tr.is-disabled { opacity: .55; }

@media (max-width: 575.98px) {
  .dk-table--apps { min-inline-size: 0; display: block; }
  .dk-table--apps thead { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
  .dk-table--apps tbody { display: flex; flex-direction: column; gap: var(--space-3); }
  .dk-table--apps tbody tr {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3) var(--space-4);
    padding: var(--space-4); background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
    border-radius: var(--card-radius); box-shadow: var(--shadow-sm);
  }
  .dk-table--apps tbody td { display: block; padding: 0; border: 0; min-inline-size: 0; overflow-wrap: anywhere; }
  .dk-table--apps tbody td::before {
    content: attr(data-label); display: block; font-size: var(--fs-caption); line-height: var(--lh-caption);
    font-weight: var(--fw-bold); color: var(--text-muted);
  }
  .dk-table--apps td.is-name { grid-column: 1; order: -2; font-size: var(--fs-body); white-space: normal; }
  .dk-table--apps td.is-status { grid-column: 2; order: -1; justify-self: end; }
  .dk-table--apps td.is-email { grid-column: 1 / -1; }
  /* design review 2026-09-04 cycle 6 BLOCKER: the "dd MMM yyyy 'الساعة' hh:mm tt" long
     date+time format this delivery introduced does not fit the 1fr mobile-card column
     while td time keeps white-space:nowrap (rule above, kept for the desktop table) -
     the un-wrappable text overflows its grid cell and either forces real page-level
     horizontal scroll (measured: /Admin/Dashboard/Bookings 364px scrollWidth vs 320px
     clientWidth) or visually overlaps the next cell (/admin/refunds). Same fix shape as
     .is-email above: give the time cell the full row width AND let it wrap once there,
     so no fixed-width column can ever force an overflow regardless of locale/format length. */
  .dk-table--apps td.is-time { grid-column: 1 / -1; }
  .dk-table--apps td.is-time time { white-space: normal; }
  .dk-table--apps td.is-name::before, .dk-table--apps td.is-status::before { display: none; }
  .dk-card--table { background: transparent; border: 0; box-shadow: none; border-radius: 0; }
}

/* --- 6. DETAIL PAGE - grid, history list, reason panel --------------------- */
.adm-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.adm-grid__side { display: grid; gap: var(--space-4); }
@media (min-width: 992px) { .adm-grid { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); } }

/* two small additions to the existing .dk-dl (T25) for the read-only
   application/account fields here: a long-text value (the Bio) and an
   explicitly-empty optional value ("-"). */
.dk-dl dd.is-long { max-inline-size: var(--measure-lede); white-space: pre-line; }
.dk-dl dd .is-empty { color: var(--text-muted); }

.adm-hist { list-style: none; display: flex; flex-direction: column; gap: var(--space-3); padding: 0; margin: 0; }
.adm-hist__it {
  display: grid; gap: var(--space-2); padding: var(--space-3) var(--space-4);
  border: var(--hairline) solid var(--border-subtle); border-radius: var(--radius-md); background: var(--surface-sunken);
}
.adm-hist__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); font-size: var(--fs-small); color: var(--text-strong); }
.adm-hist__row i { color: var(--text-muted); }
.adm-hist__reason { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); margin: 0; }
.adm-hist__none { color: var(--text-secondary); font-size: var(--fs-small); line-height: var(--lh-small); margin: 0; }

.adm-reason {
  background: var(--surface-sunken); border: var(--hairline) solid var(--border-subtle); border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4); font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-body);
  max-inline-size: var(--measure-lede); margin: 0;
}
.adm-reason strong { color: var(--text-strong); }

/* --- 7. MODAL - Bootstrap's own .modal/.modal-dialog/.modal-content drive the
   JS (focus trap, Esc, backdrop, aria-modal); only the visual chrome and the
   header/body/footer layout are re-themed on top of it. ------------------- */
.dk-modal-content { border: 0; border-radius: var(--modal-radius); box-shadow: var(--modal-shadow); }
.modal-dialog:has(.dk-modal-content) { --bs-modal-width: var(--modal-max-width); }
.dk-modal__h { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); padding: var(--space-5) var(--space-5) 0; }
.dk-modal__t { font-size: var(--fs-h5); line-height: var(--lh-h5); font-weight: var(--fw-bold); margin: 0; }
.dk-modal__b { padding: var(--space-4) var(--space-5); display: grid; gap: var(--space-3); }
.dk-modal__b p { color: var(--text-secondary); font-size: var(--fs-small); line-height: var(--lh-body-lg); margin: 0; }
.dk-modal__f { display: flex; gap: var(--space-2); padding: 0 var(--space-5) var(--space-5); flex-wrap: wrap; }
@media (max-width: 575.98px) { .dk-modal__f .dk-btn { flex: 1 1 auto; } }

/* =============================================================================
   /teacher/profile/edit (T27) - ported from docs/design/teacher-profile-edit/
   {index,filled,errors,photo-uploading,photo-rejected,saved,map-unavailable}.html
   per NOTES.md section 6-3's "new classes" list. .dk-page/.dk-h1/.dk-h2/.dk-lede/
   .dk-card/.dk-form/.dk-field/.dk-input/.dk-help/.dk-error/.dk-btn/.dk-alert/
   .dk-badge/.dk-choices/.dk-selectwrap/.dk-counter/.dk-fieldfoot/.dk-submit/
   .dk-empty/.dk-map/.dk-modal*/.dk-avatar--fallback/.dk-locstatus/
   .dk-rolebadge--teacher/.dk-iconbtn--sm are ALL reused as-is (shipped with
   T22.8/T25/T26 above) - nothing below redefines them. Icons stay Font
   Awesome <i> (NOTES.md 6-5: same reason as T25/T26 - _Icon arrives with T18),
   not the mockup's inline-SVG sprite; same THEME 3-3 roles either way.
   ========================================================================== */

/* Secondary link under the h1 - "عرض ملفّي العامّ" (spec section 4). */
.dk-publiclink {
  display: inline-flex; align-items: center; gap: var(--space-2);
  min-block-size: var(--tap-min);
  color: var(--text-link); font-size: var(--fs-small); font-weight: var(--fw-bold);
  text-decoration: underline; text-underline-offset: .15em;
}
.dk-publiclink:hover { color: var(--text-link-hover); }
.dk-card__head .dk-badge { margin-inline-start: auto; }

/* --------------------------------------------------------------------------
   PHOTO CARD (spec section 4 "بطاقة الصورة", section 5 rows 1-2). The upload
   input is a real <input type="file"> kept in the accessible tree with
   .sr-only (never display:none) so it stays keyboard-reachable; its <label>
   is the visible button.
   -------------------------------------------------------------------------- */
.dk-photo { display: flex; flex-direction: column; gap: var(--space-4); }

/* Same crop the search card publishes (--media-h-card, 160px, object-fit:cover)
   so what the teacher approves here is what visitors see. */
.dk-photo__frame {
  position: relative; overflow: hidden;
  border-radius: var(--radius-lg); background: var(--surface-sunken);
  border: var(--hairline) solid var(--border-subtle);
}
.dk-photo__img { inline-size: 100%; block-size: var(--media-h-card); object-fit: cover; display: block; }

/* Empty state of the photo block: the mandatory avatar fallback (THEME 3-1 row
   "صورة رمزية", architecture section 6) at media size. */
.dk-photo__fallback {
  inline-size: 100%; block-size: var(--media-h-card);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-2);
  background: var(--avatar-fallback-bg); color: var(--avatar-fallback-text);   /* 6.49:1 PASS */
  font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: var(--fw-bold);
}
.dk-photo__fallbacknote {
  font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-regular);
  color: var(--on-primary-subtle);   /* 6.49:1 PASS on --avatar-fallback-bg */
}

/* "معاينة" ribbon while a locally chosen file has not been saved yet. */
.dk-photo__flag {
  position: absolute; inset-block-start: var(--space-2); inset-inline-start: var(--space-2);
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding-block: var(--space-1); padding-inline: var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--info-surface); color: var(--info-text);   /* 6.16:1 PASS */
  border: var(--hairline) solid var(--info-border);
  font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: var(--fw-bold);
  margin: 0;
}

.dk-photo__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.dk-photo__actions .dk-btn { flex: 1 1 auto; }
@media (min-width: 576px) { .dk-photo__actions .dk-btn { flex: 0 0 auto; } }

/* The visible <label> that fronts the file input behaves exactly like a button,
   including the focus ring - which must be driven by the INPUT's focus, since a
   label is not focusable itself. */
.dk-filebtn { margin: 0; }
.dk-filebtn:has(input:focus-visible) {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}
.dk-filebtn.is-focus { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
.dk-filebtn[aria-disabled="true"] {
  background: var(--surface-disabled); color: var(--text-disabled);
  border-color: var(--border-default); cursor: not-allowed; pointer-events: none;
}

/* Chosen-file name line (appears only after a file is picked). */
.dk-filename {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary);   /* 7.58:1 PASS */
  padding-inline-start: var(--space-4); margin: 0; overflow-wrap: anywhere;
}
.dk-filename i { color: var(--text-muted); flex: none; }

/* --------------------------------------------------------------------------
   LOCATION CARD (spec section 4 "بطاقة الموقع", section 5 rows 3-5)
   -------------------------------------------------------------------------- */
.dk-loc { display: flex; flex-direction: column; gap: var(--space-4); }
.dk-loc__fieldset { border: 0; padding: 0; margin: 0; min-inline-size: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.dk-loc__fieldset > legend { float: none; inline-size: auto; padding: 0; margin: 0; }

/* .dk-map (shared with /teachers) carries layout margins that belong to THAT
   page, not to the component (NOTES.md section 4-c) - reset to zero here,
   where the map already sits inside .dk-card__body's own padding. */
.dk-loc .dk-map { margin: 0; border: var(--hairline) solid var(--border-default); }
.dk-loc .dk-map--down { border-style: dashed; }
.dk-loc .dk-map--down .dk-empty { background: transparent; border: 0; padding: var(--space-4); }

/* Coordinates readout (spec section 4: western digits, or "لم يُحدَّد موقع بعد"). */
.dk-coords {
  display: flex; align-items: flex-start; gap: var(--space-2);
  font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary);   /* 7.58:1 PASS */
  margin: 0; padding-inline-start: var(--space-4);
}
.dk-coords i { color: var(--text-muted); flex: none; margin-block-start: var(--space-1); }
.dk-coords__v { color: var(--text-strong); font-weight: var(--fw-bold); }
.dk-coords--empty .dk-coords__v { color: var(--text-secondary); font-weight: var(--fw-regular); }

.dk-loc__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.dk-loc__actions .dk-btn { flex: 1 1 auto; }
@media (min-width: 576px) { .dk-loc__actions .dk-btn { flex: 0 0 auto; } }

/* Geolocation status line - "لم نستطع قراءة موقعك…" (spec section 5 row 4).
   .dk-locstatus{font-size;color} already shipped with /teachers (site.css
   line ~1355); only the error modifier is new here. */
.dk-locstatus.is-error { color: var(--danger-text); font-weight: var(--fw-medium); }   /* 5.91:1 PASS */

/* --------------------------------------------------------------------------
   SECTION SPACING - the three data cards + location card stack in one column
   (THEME 3-2-1).
   -------------------------------------------------------------------------- */
.dk-stack { display: flex; flex-direction: column; gap: var(--space-5); }

/* =============================================================================
   POST-APPROVAL ADDITION -- T24 (docs/design/teacher-schedule/NOTES.md section
   5-1). 2 tokens ported verbatim from the mockup's "0. PROPOSED TOKEN
   ADDITIONS (T24)" block - see docs/design/theme/tokens.css for the same
   addition with the full rationale comment.
   ========================================================================== */
:root {
  --preview-day-min: 150px;  /* min track of the 7-day preview grid (auto-fit) */
  --check-size:       20px;  /* the custom checkbox box - sits inside a 44px tap row (--tap-min) */
}

/* ==========================================================================
   PAGE - /teacher/schedule (T24, docs/design/teacher-schedule/, real screen
   docs/handoff/T24-views.md). .dk-page-wide/.dk-card/.dk-form/.dk-field/
   .dk-input/.dk-help/.dk-error/.dk-btn/.dk-alert/.dk-badge/.dk-note/
   .dk-empty/.dk-choices/.dk-choice/.dk-modal*/.dk-fieldset/.dk-selectwrap are
   ALL reused as-is (shipped with T22.8/T25/T26/T27). Only what this screen
   genuinely adds is defined below.
   ========================================================================== */

.dk-page-wide { display: flex; flex-direction: column; gap: var(--space-6); }
.dk-sec { display: flex; flex-direction: column; gap: var(--space-4); }

/* The "add" form is ALWAYS VISIBLE (spec section 4) and lives in the FOOTER of
   the card whose data it feeds - not a side column, never behind a
   disclosure. MEASURED reason (NOTES.md section 3-3): a window chip needs
   ~95px of content ("16:00 - 22:00" at --fs-small/--fw-bold with tabular
   nums), plus its two action buttons need ~109px more to sit on one line.
   Seven such columns need the whole content box; a side column would squeeze
   every chip down to three lines. */
.dk-card__foot {
  border-block-start: var(--hairline) solid var(--border-subtle);
  background: var(--surface-sunken);
  border-end-start-radius: var(--card-radius); border-end-end-radius: var(--card-radius);
  padding: var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-4);
}
@media (min-width: 768px) { .dk-card__foot { padding: var(--space-6); } }
.dk-card__foot .dk-card__title i { color: var(--primary-strong); font-size: var(--icon-sm); }

/* --------------------------------------------------------------------------
   WEEKLY GRID - seven columns from lg up, a day LIST below it (spec section
   4). ONE markup, two layouts (CSS grid only) - nothing duplicated in the DOM.
   -------------------------------------------------------------------------- */
.dk-week { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
@media (min-width: 992px) {
  .dk-week { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space-2); align-items: start; }
}
.dk-day { display: flex; flex-direction: column; gap: var(--space-2); min-inline-size: 0; }
.dk-day__h {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-sunken); border-radius: var(--radius-sm);
  font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold);
  color: var(--text-strong); margin: 0;
}
@media (min-width: 992px) { .dk-day__h { justify-content: center; padding-inline: var(--space-2); } }
.dk-day__list { display: flex; flex-direction: column; gap: var(--space-2); min-inline-size: 0; }
.dk-day__empty {
  font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-muted);
  padding: var(--space-2) var(--space-3); margin: 0;
}
@media (min-width: 992px) { .dk-day__empty { text-align: center; padding-inline: var(--space-1); } }

/* --------------------------------------------------------------------------
   WINDOW CHIP - the unit the teacher acts on. Paused is coded by THREE
   signals (surface, dashed border, the literal word "متوقّفة") - never
   colour alone.
   -------------------------------------------------------------------------- */
.dk-win {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  padding: var(--space-2); min-inline-size: 0;
  background: var(--surface-raised);
  border: var(--hairline) solid var(--border-default);
  border-radius: var(--radius-md);
}
.dk-win__time {
  flex: 1 1 auto; min-inline-size: 0;
  font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold);
  color: var(--text-strong); white-space: nowrap;
}
.dk-win__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); flex: 1 1 auto; }
.dk-win__actions .dk-btn { flex: 1 1 auto; padding-inline: var(--space-2); }
/* the per-chip toggle <form> must not break the actions row's flex layout */
.dk-win__f { display: contents; }
/* dashed border deliberately raised from --border-default (1.48:1, decorative)
   to --border-input so the purely graphic half of the "paused" signal alone
   clears WCAG 1.4.11's 3:1 - measured at 4.55:1 against the chip's own surface. */
.dk-win--paused {
  background: var(--surface-sunken);
  border-style: dashed;
  border-color: var(--border-input);
}
.dk-win--paused .dk-win__time { color: var(--text-secondary); }
.dk-win__state { flex: 0 0 auto; }

.dk-badge--neutral { background: var(--neutral-surface); color: var(--neutral-text); border-color: var(--neutral-border); }
/* Referenced by qa-center.js's STATUS_BADGE_CLASS[1] (InProgress) since T14 but never defined -
   discovered while adding the AwaitingDecision/AwaitingDeploy statuses (2026-09-12) that reuse
   the same badge system; uses the existing --info-* tokens already approved for .dk-rolebadge--guardian. */
.dk-badge--info { background: var(--info-surface); color: var(--info-text); border-color: var(--info-border); }

/* --------------------------------------------------------------------------
   NATURAL PAIR - "from"/"to" side by side. THEME 3-2-1 allows exactly this:
   "no two fields side by side EXCEPT a naturally related pair".
   -------------------------------------------------------------------------- */
.dk-pair { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
@media (min-width: 576px) { .dk-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* --------------------------------------------------------------------------
   CHECKBOX - THEME 3-1 has no checkbox row; this is the first one in the
   product (spec section 4: "اليوم كلّه"). 44px tap row, --border-input
   boundary, one focus ring, checked state coded by a mark, not colour alone.
   -------------------------------------------------------------------------- */
/* position:relative is load-bearing, not decorative: without it the absolutely-positioned
   checkbox below (no explicit inset of its own, by design - it should sit exactly where normal
   flow would have placed it) resolves against the nearest positioned ANCESTOR instead, which
   without this rule is the viewport itself - measured directly in this session via a real
   Playwright click: the checkbox ended up "outside of the viewport" and every click on the
   visible box was swallowed by its own decorative <i>, timing out check()/uncheck() entirely. */
.dk-check { position: relative; display: flex; align-items: center; gap: var(--space-3); min-block-size: var(--tap-min); cursor: pointer; margin: 0; }
.dk-check input[type="checkbox"] { position: absolute; opacity: 0; inline-size: var(--check-size); block-size: var(--check-size); margin: 0; }
.dk-check__box {
  inline-size: var(--check-size); block-size: var(--check-size); flex: none;
  display: flex; align-items: center; justify-content: center;
  border: var(--hairline-strong) solid var(--border-input);
  border-radius: var(--radius-xs); background: var(--field-bg);
  color: var(--on-primary);
  /* purely decorative overlay - every click must reach the real (now correctly positioned)
     checkbox underneath it, belt-and-suspenders alongside the position fix above. */
  pointer-events: none;
  transition: background var(--motion-fast) var(--motion-ease), border-color var(--motion-fast) var(--motion-ease);
}
.dk-check__box i { font-size: var(--icon-sm); opacity: 0; }
.dk-check:hover .dk-check__box { border-color: var(--field-border-hover); }
.dk-check input:checked + .dk-check__box { background: var(--primary-strong); border-color: var(--primary-strong); }
.dk-check input:checked + .dk-check__box i { opacity: 1; }   /* white check on --primary-strong = 5.02:1 PASS */
.dk-check input:focus-visible + .dk-check__box {
  outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset);
}
.dk-check input[disabled] + .dk-check__box { background: var(--field-bg-disabled); border-color: var(--border-default); }
.dk-check input[disabled] ~ .dk-check__t { color: var(--text-disabled); }
.dk-check__t { font-size: var(--fs-body); line-height: var(--lh-body); color: var(--text-strong); }

/* --------------------------------------------------------------------------
   CHOICE CARD MODIFIERS - the exception type. Originally a single-column
   stack for long-sentence labels (see the row layout comment right below),
   but its only three real consumers today (Views/Student/Bookings.cshtml's
   reschedule modal, Views/Home/TeacherProfile.cshtml's T33-a slot picker,
   Views/Teacher/Schedule.cshtml's weekly availability grid - confirmed by a
   project-wide grep before this change) are ALL short time labels ("07:00
   م"), never long sentences - forcing them one-per-row wasted the width a
   short label does not need (Osama's direct design note, 2026-09-01, on the
   TeacherProfile picker screenshot: "لا تضع كل زمن في بلوك بكامل العرض ..
   اجعلهم متجاورين"). Switched to a responsive multi-column grid so short
   choices sit adjacent instead of stacking full-width; base .dk-choices/
   .dk-choice already shipped with T25/T27 - site.css section "FORM (THEME
   3-2)". If a FOURTH consumer ever needs the original one-per-row long-
   sentence layout, give it its own modifier class instead of reverting this
   one - re-litigating short-vs-long per consumer here would silently
   reintroduce the same full-width waste for the three time-pickers above.
   -------------------------------------------------------------------------- */
.dk-choices--stack { grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); }
@media (max-width: 359.98px) { .dk-choices--stack { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dk-choice--row { flex-direction: row; align-items: center; text-align: start; padding: var(--space-3) var(--space-4); }
.dk-choice--row .dk-choice__t { flex: 1 1 auto; min-inline-size: 0; }
.dk-choice--row .dk-choice__mark { position: static; display: none; flex: none; }
.dk-choice--row:has(input:checked) .dk-choice__mark,
.dk-choice--row.is-selected .dk-choice__mark { display: block; }
.dk-choice--row .dk-choice__icon { inline-size: var(--icon-chip); block-size: var(--icon-chip); }

/* A fieldset-level invalid state (the "from/to" PAIR is validated together,
   NOTES.md section 3-4) - the twin of the existing per-input
   .dk-input[aria-invalid="true"] rule (site.css "FORM" section), applied to
   every .dk-input inside an invalid fieldset instead of one input alone. */
.dk-fieldset[aria-invalid="true"] .dk-input { border-color: var(--field-border-error); border-width: var(--hairline-strong); }
.dk-fieldset[aria-invalid="true"] .dk-input:focus-visible { outline-color: var(--focus-ring-color-danger); }

/* --------------------------------------------------------------------------
   EXCEPTION ROW - date, span, kind badge, reason, delete.
   -------------------------------------------------------------------------- */
.dk-exclist { display: flex; flex-direction: column; }
.dk-exc {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  padding-block: var(--space-3); border-block-end: var(--hairline) solid var(--border-subtle);
}
.dk-exc:first-child { padding-block-start: 0; }
.dk-exc:last-child { border-block-end: 0; padding-block-end: 0; }
.dk-exc__main { flex: 1 1 var(--menu-min-w); min-inline-size: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.dk-exc__top { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.dk-exc__date { font-size: var(--fs-body); line-height: var(--lh-body); font-weight: var(--fw-bold); color: var(--text-strong); }
.dk-exc__when { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); white-space: nowrap; }
.dk-exc__reason { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); overflow-wrap: anywhere; }
.dk-exc__actions { flex: 0 0 auto; margin-inline-start: auto; }

/* --------------------------------------------------------------------------
   PREVIEW - seven day cards, auto-fit so they stretch instead of a gap.
   -------------------------------------------------------------------------- */
.dk-prev { display: grid; grid-template-columns: repeat(auto-fit, minmax(var(--preview-day-min), 1fr)); gap: var(--space-3); }
/* Design review fix (docs/reviews/design/ - PASS-WITH-FIXES): auto-fit against the
   --preview-day-min floor alone wrapped the 7th card at ~1200px (measured available column
   ~147.4px against the 150px floor - a narrow miss, not a broken layout, but real). Forcing an
   EXPLICIT 7-column grid from the SAME breakpoint .dk-week already uses removes the floor
   entirely at and above it, so seven cards fit at any width from 992px up regardless of how
   narrow each becomes - a card's own content (day/date/slot chips) already wraps internally
   (.dk-slots is flex-wrap) rather than the whole grid dropping a column. Below 992px the
   auto-fit behaviour above is what the spec actually wants (1 column at 375, 4-then-3 at 768). */
@media (min-width: 992px) {
  .dk-prev { grid-template-columns: repeat(7, minmax(0, 1fr)); }
}
.dk-prevday {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); min-inline-size: 0;
  background: var(--surface-raised);
  border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.dk-prevday--closed { background: var(--neutral-surface); border-color: var(--neutral-border); }
.dk-prevday__h { display: flex; flex-direction: column; gap: var(--space-1); }
.dk-prevday__day { font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold); color: var(--text-strong); }
.dk-prevday__date { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-secondary); }
.dk-slots { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.dk-slot {
  display: inline-flex; align-items: center; min-block-size: var(--tap-floor);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm);
  background: var(--primary-subtle); color: var(--on-primary-subtle);
  font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold);
}

/* the always-visible add forms stay single-column at a readable measure
   (THEME 3-2-1) even though the card around them spans the full width. */
.dk-form--panel { max-inline-size: var(--form-max-w); }
.dk-form--panel .dk-btn { inline-size: 100%; }
@media (min-width: 576px) { .dk-form--panel .dk-btn { inline-size: auto; align-self: flex-start; padding-inline: var(--space-6); } }

/* Tabular digit alignment WITHOUT the LTR/isolate side effect .num carries -
   the time-range order decision (NOTES.md section 3-2) needs tabular digits
   but NOT direction:ltr (that would put the end time first for an Arabic
   reader: "22:00 - 16:00" would read start-last instead of start-first).
   .num stays reserved for ISO dates / ids / anything read as ONE token. */
.dk-tnum { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   PAGE - /teacher/dashboard (T28, docs/design/teacher-dashboard/, real screen
   docs/handoff/T28-views.md). .dk-page-wide/.dk-sec/.dk-card/.dk-btn/
   .dk-alert/.dk-badge/.dk-empty/.dk-stat/.dk-avatar/.dk-note/.dk-actions/
   .dk-h1/.dk-h2 are ALL reused as-is (shipped with T22.8/T24/T25/T26/T27).
   Only what this screen genuinely adds is defined below.
   ========================================================================== */

/* --- page header: h1, the identity line, and the three screen-level actions
   named by spec section 5 ("my schedule" / "my profile" / "my public page"). */
.dk-dashhead { gap: var(--space-4); align-items: stretch; }
.dk-ident { display: flex; align-items: center; gap: var(--space-4); }
.dk-ident__b { display: flex; flex-direction: column; gap: var(--space-1); min-inline-size: 0; }
.dk-ident__name { font-size: var(--fs-h5); line-height: var(--lh-h5); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0; }
.dk-ident__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); margin: 0; }
.dk-ident__dot { color: var(--text-decorative); }
/* The token exists (--avatar-lg, 64px); the class did not until now - moves
   it into the component layer where every other avatar size already lives. */
.dk-avatar--lg { inline-size: var(--avatar-lg); block-size: var(--avatar-lg); font-size: var(--fs-h5); }

/* --- READINESS (spec section 4-a): the primary object of this screen.
   A MET item keeps its row instead of disappearing, and the four rows hold
   the spec's order in every state - so the list never re-shuffles between
   two visits and progress is what the teacher sees. */
.dk-ready__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.dk-ready__item {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
  min-block-size: var(--tap-min); padding-block: var(--space-3);
  border-block-end: var(--hairline) solid var(--border-subtle);
}
.dk-ready__item:first-child { padding-block-start: 0; }
.dk-ready__item:last-child { border-block-end: 0; padding-block-end: 0; }
.dk-ready__i { flex: none; }
.dk-ready__item--todo .dk-ready__i { color: var(--warning-strong); }   /* 3.19:1 as a graphic PASS */
.dk-ready__item--done .dk-ready__i { color: var(--success-strong); }   /* 5.02:1 as a graphic PASS */
/* The status icon and its sentence are ONE wrapping unit: at 375 the action
   drops to a second line while the icon stays glued to the text it qualifies.
   The unit takes a FIXED column instead of all the free space, so the action
   that fixes the item sits right next to it - measured (docs/design/teacher-
   dashboard/NOTES.md section 3-5): pushing the action to the far end put
   ~1500px between "no photo" and "upload one" at 1440 in the first build. */
.dk-ready__l { display: flex; align-items: center; gap: var(--space-3); flex: 0 1 var(--menu-min-w-wide); min-inline-size: 0; }
.dk-ready__t { min-inline-size: 0; margin: 0; font-size: var(--fs-body); line-height: var(--lh-body); color: var(--text-strong); }
.dk-ready__go { flex: 0 0 auto; }
.dk-ready__done { flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold); color: var(--success-text); }
/* The card head icon is brand-green by default (.dk-card__head i); the
   not-bookable head carries the warning role instead. */
.dk-card__head .dk-icon--warn { color: var(--warning-strong); }
/* The one card on this screen that must be read FIRST gets a tinted head - the
   same warning pair the alert component uses, so no new colour enters the page.
   --text-strong on --warning-surface = 17.22:1 (measured, docs/design/teacher-
   dashboard/NOTES.md section 5-3). */
.dk-card--attention .dk-card__head { background: var(--warning-surface); border-block-end-color: var(--warning-border); }

/* --- STATS (spec section 3). NOT interactive by spec section 5: no wrapping
   link, no pointer cursor, no button styling, not focusable - a deliberate
   deviation from THEME 3-1's default .dk-stat:hover shadow (that shadow reads
   as an affordance for a clickable card; these are not). Scoped to THIS
   screen's stat row only - Home/Index.cshtml's own .dk-stat strip keeps the
   theme's shipped default untouched (docs/handoff/T28-views.md). */
.dk-stats .dk-stat:hover { box-shadow: var(--card-shadow); }
/* Three across only from lg. MEASURED: at 768 a three-column strip gives each
   card 235px, which breaks "the open slots this week" onto two cramped lines;
   one card per row there is wider than it needs to be but reads in one glance.
   992 is the same governing breakpoint the T24 screen uses. */
.dk-stats { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
@media (min-width: 992px) { .dk-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* The landing page's .dk-stat reads as one inline phrase ("21 active teachers").
   Here the value can be a SENTENCE ("no ratings yet", spec section 4-e), so the
   value and its label stack instead of running together on one line. */
.dk-stat__b { display: flex; flex-direction: column; min-inline-size: 0; }
/* MEASURED bug this avoids: .num sets direction:ltr, so a stretched flex item
   carrying a number aligns its text to the LEFT inside an RTL card - the value
   would drift away from the label under it. Shrinking each line to its own
   content keeps both on the inline start (the right). */
.dk-stat__b > * { align-self: start; }
.dk-stat__num--text { font-size: var(--fs-h5); line-height: var(--lh-h5); }

/* --- UPCOMING BOOKINGS (spec section 4-d): rows, not a table. The four fields
   fit one line from 576 up and stack at 375 without the sideways scroll a
   four-column table would need there. */
.dk-bklist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.dk-bk {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
  padding-block: var(--space-3); border-block-end: var(--hairline) solid var(--border-subtle);
}
.dk-bk:first-child { padding-block-start: 0; }
.dk-bk:last-child { border-block-end: 0; padding-block-end: 0; }
.dk-bk__main { flex: 1 1 var(--menu-min-w); min-inline-size: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.dk-bk__who { font-size: var(--fs-body); line-height: var(--lh-body); font-weight: var(--fw-bold); color: var(--text-strong); }
.dk-bk__when { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--text-secondary); }
.dk-bk__end { flex: 0 0 auto; margin-inline-start: auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }

/* Real-screen addition beyond the mockup's own annex-only sketch: the "عرض
   الكلّ" control (_ARCHITECTURE.md section 9-2-ب, spec section 4 row د) sits
   below the list with its own breathing room, not flush against the last row. */
.dk-bkall { margin-block-start: var(--space-4); }

/* =============================================================================
   NOTIFICATION BELL (T45, docs/specs/T45-notifications.md section 5) -
   Views/Shared/_Layout.cshtml's global bell + live badge, kept beside .dk-bk*
   above since both are new in this same task. .dk-iconbtn (site.css:819) is
   reused as-is for the button chrome; only the badge dot itself is new here.
   ========================================================================== */
.dk-notifbell { position: relative; }
.dk-notifbell__badge {
  position: absolute; inset-block-start: 2px; inset-inline-end: 2px;
  min-inline-size: 18px; block-size: 18px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-circle); background: var(--danger-strong); color: var(--on-danger);
  font-size: var(--badge-font-size); line-height: 1; font-weight: var(--fw-bold);
  border: 2px solid var(--surface-raised);
}
/* The drawer link's own badge sits inline after the label instead of pinned to
   a corner - .dk-drawer__link is a full-width row, not an icon-only button, so
   there is no icon corner to pin against. */
.dk-drawer__link .dk-notifbell__badge {
  position: static; margin-inline-start: var(--space-2); border: 0;
}

/* =============================================================================
   LIBRARY SCREEN (T52, docs/specs/T52-library-screen.md - mockup docs/design/
   T52-library-screen/{index,empty,search}.html). Every value below resolves to
   an existing token (site.css's own :root, same set the mockup's own
   "PROPOSED TOKEN ADDITIONS" block names) - the four new custom properties are
   the same ones the mockup proposed, added here as the approved layer.
   ========================================================================== */
:root {
  --lib-tile-min-w:    168px;  /* grid tile minimum before wrapping (auto-fill) */
  --lib-tile-icon-chip: 56px;  /* the tinted square behind the type glyph */
  --crumb-max-w:       220px;  /* a single breadcrumb segment before ellipsis */
  --rowmenu-min-w:     176px;  /* row-menu (...) dropdown - four short actions only */
  /* Design review 2026-09-03 cycle-5 - the three token additions the mockup's own "PROPOSED
     TOKEN ADDITIONS" section named that were missing from the first pass (--lib-thumb-h for the
     BLOCKER image-thumbnail fix; --lib-search-max/--quota-bar-h for the two MINOR raw-value
     findings, moved here unchanged from the .dk-toolbar__search/.dk-quota__track rules below). */
  --lib-thumb-h:       96px;   /* real image thumbnail block-size (dk-tile__thumb) */
  --lib-search-max:    360px;  /* toolbar search field max width */
  --quota-bar-h:       8px;    /* storage-quota meter track height */
}

/* --- breadcrumbs --- */
.dk-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); list-style: none; margin: 0; padding: 0; }
.dk-crumbs li { display: flex; align-items: center; gap: var(--space-1); min-inline-size: 0; }
.dk-crumbs .fa-chevron-left { color: var(--text-muted); flex: none; font-size: var(--fs-caption); }
.dk-crumb {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--tap-min); padding-inline: var(--space-3);
  border-radius: var(--radius-md); color: var(--text-secondary); text-decoration: none; font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-medium);
  max-inline-size: var(--crumb-max-w); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dk-crumb:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-crumb[aria-current="page"] { color: var(--text-strong); font-weight: var(--fw-bold); pointer-events: none; }

/* --- storage-quota meter (welcome initiative, NOTES.md section 2-4) --- */
.dk-quota { display: flex; flex-direction: column; gap: var(--space-1); min-inline-size: 200px; }
.dk-quota__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-secondary); }
.dk-quota__track { block-size: var(--quota-bar-h); border-radius: var(--radius-pill); background: var(--rating-track); overflow: hidden; }
.dk-quota__fill { block-size: 100%; border-radius: var(--radius-pill); background: var(--primary-strong); }

/* --- toolbar: upload / new folder / search --- */
.dk-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.dk-toolbar__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.dk-toolbar__search { flex: 1 1 240px; max-inline-size: var(--lib-search-max); margin-inline-start: auto; }
/* ticket #32: this now hosts two back links (library + curricula) side by side, same
   display:flex + gap shape as .dk-toolbar__actions above it. */
.dk-toolbar__back { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-inline-start: auto; }
@media (max-width: 575.98px) {
  .dk-toolbar { flex-direction: column; align-items: stretch; }
  .dk-toolbar__actions { order: 2; }
  .dk-toolbar__actions .dk-btn { flex: 1 1 auto; }
  .dk-toolbar__search { order: 1; max-inline-size: none; margin-inline-start: 0; }
  .dk-toolbar__back { flex-direction: column; margin-inline-start: 0; }
  .dk-toolbar__back .dk-btn { inline-size: 100%; }
}

/* --- library grid: folders then files, one grid, tokens only --- */
.dk-libgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--lib-tile-min-w), 1fr)); gap: var(--space-4); margin: 0; padding: 0; list-style: none; }

.dk-tile {
  /* ticket #35: no overflow:hidden here on purpose - it used to clip the row-menu dropdown
     (Bootstrap positions .dropdown-menu as a DOM sibling inside this card, not a portal), and
     nothing in this card currently needs corner clipping: .dk-tile__thumb already carries its
     own smaller border-radius and sits inside .dk-tile__link's padding, so it never touches the
     card edge. border-radius/box-shadow below still render the card shape regardless. */
  position: relative; display: flex; flex-direction: column; background: var(--card-bg); border: var(--hairline) solid var(--card-border);
  border-radius: var(--card-radius); box-shadow: var(--card-shadow);
  transition: box-shadow var(--motion-fast) var(--motion-ease), transform var(--motion-fast) var(--motion-ease);
}
.dk-tile:hover { box-shadow: var(--card-shadow-hover); transform: translateY(var(--card-lift-hover)); }
.dk-tile:has(.dk-tile__link:focus-visible) { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }

/* the whole visual body is ONE link; the action row sits OUTSIDE as SIBLING
   buttons (spec section 5: never nested inside the link - click-swallow rule) */
.dk-tile__link {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-3);
  padding: var(--space-5) var(--space-4) var(--space-3); text-decoration: none; color: inherit; flex: 1 1 auto;
}
.dk-tile__link:focus-visible { outline: none; }

.dk-tile__glyph {
  inline-size: var(--lib-tile-icon-chip); block-size: var(--lib-tile-icon-chip); border-radius: var(--radius-lg);
  display: flex; align-items: center; justify-content: center; flex: none; font-size: var(--icon-lg);
}
.dk-tile--folder .dk-tile__glyph { background: var(--primary-subtle); color: var(--on-primary-subtle); }
.dk-tile--pdf .dk-tile__glyph    { background: var(--danger-surface); color: var(--danger-text); }
.dk-tile--doc .dk-tile__glyph    { background: var(--info-surface); color: var(--info-text); }
.dk-tile--video .dk-tile__glyph  { background: var(--accent-violet-surface); color: var(--accent-violet-text); }
.dk-tile--file .dk-tile__glyph   { background: var(--neutral-surface); color: var(--neutral-text); }

/* --- real image thumbnail (design review 2026-09-03 cycle-5 blocker fix, mockup
   T52-library-screen/index.html:769-776/PROPOSED TOKEN ADDITIONS) - replaces .dk-tile__glyph
   for an image/* file only; falls back to .dk-tile__glyph on load error (view's onerror). --- */
.dk-tile__thumb { inline-size: 100%; block-size: var(--lib-thumb-h); border-radius: var(--radius-md); object-fit: cover; background: var(--surface-sunken); }

.dk-tile__name {
  font-size: var(--fs-small); line-height: var(--lh-small); font-weight: var(--fw-bold); color: var(--text-strong);
  overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.dk-tile__meta { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-secondary); }
.dk-tile__loc { display: flex; align-items: center; gap: var(--space-1); font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-secondary);
  max-inline-size: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dk-tile__loc i { color: var(--text-muted); }
.dk-tile__badges { display: flex; align-items: center; gap: var(--space-1); flex-wrap: wrap; justify-content: center; }

.dk-tile__actions {
  display: flex; align-items: center; justify-content: center; gap: var(--space-1); padding: var(--space-2) var(--space-2) var(--space-3);
  border-block-start: var(--hairline) solid var(--border-subtle); margin-block-start: auto;
}
.dk-tile__actions .dk-iconbtn { flex: none; }

@media (max-width: 359.98px) { .dk-libgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); } }

/* --- row menu (...) - per-tile action overflow, THEME dropdown pattern --- */
.dk-rowmenu {
  min-inline-size: var(--rowmenu-min-w); padding: var(--space-2); background: var(--surface-raised); border: var(--hairline) solid var(--border-subtle);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); z-index: var(--z-dropdown);
}
.dk-rowmenu__item {
  display: flex; align-items: center; gap: var(--space-3); min-height: var(--tap-min); padding-inline: var(--space-3);
  border-radius: var(--radius-md); text-decoration: none; border: 0; background: transparent; color: var(--text-body); font-family: inherit;
  font-size: var(--fs-small); line-height: var(--lh-small); inline-size: 100%; text-align: start; cursor: pointer;
}
.dk-rowmenu__item:hover { background: var(--surface-hover); color: var(--text-strong); }
.dk-rowmenu__item--danger { color: var(--danger-text); }
.dk-rowmenu__item--danger:hover { background: var(--danger-surface); color: var(--danger-text); }
.dk-rowmenu__sep { block-size: var(--hairline); background: var(--border-subtle); margin-block: var(--space-2); }

/* --- upload dropzone: a bigger, clearer 44px+ target for one native
       <input type="file"> - never a third-party uploader (spec section 0) --- */
.dk-dropzone {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-3); text-align: center;
  padding: var(--space-6) var(--space-4); border: var(--hairline-strong) dashed var(--border-default); border-radius: var(--radius-lg);
  background: var(--surface-sunken); position: relative; cursor: pointer;
  transition: border-color var(--motion-fast) var(--motion-ease), background var(--motion-fast) var(--motion-ease);
}
.dk-dropzone:hover { border-color: var(--border-brand); background: var(--primary-surface); }
.dk-dropzone:has(input:focus-visible) { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
.dk-dropzone input[type="file"] { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; opacity: 0; cursor: pointer; }
.dk-dropzone .fa-cloud-arrow-up { font-size: var(--icon-2xl); color: var(--text-muted); }
.dk-dropzone__t { font-size: var(--fs-body); font-weight: var(--fw-bold); color: var(--text-strong); margin: 0; }
.dk-dropzone__d { font-size: var(--fs-small); color: var(--text-secondary); margin: 0; }
.dk-dropzone__file {
  display: none; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); background: var(--surface-raised);
  border: var(--hairline) solid var(--border-subtle); border-radius: var(--radius-md); font-size: var(--fs-small); color: var(--text-strong); max-inline-size: 100%;
}
.dk-dropzone__file.is-visible { display: flex; }
.dk-dropzone__filename { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- move dialog: destination picker (choice-card family, row variant) --- */
.dk-destlist { display: flex; flex-direction: column; gap: var(--space-2); max-block-size: 260px; overflow-y: auto; padding-inline-end: var(--space-1); }
.dk-dest {
  display: flex; align-items: center; gap: var(--space-3); min-block-size: var(--tap-min); padding-inline: var(--space-3);
  border: var(--hairline) solid var(--border-default); border-radius: var(--radius-md); cursor: pointer;
  transition: border-color var(--motion-fast) var(--motion-ease), background var(--motion-fast) var(--motion-ease);
}
.dk-dest:hover { border-color: var(--border-brand); }
.dk-dest:has(input:checked) { border-color: var(--primary-strong); background: var(--primary-surface); }
.dk-dest:has(input:focus-visible) { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
.dk-dest__t { flex: 1 1 auto; font-size: var(--fs-small); font-weight: var(--fw-medium); color: var(--text-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dk-dest__mark { color: var(--primary-strong); display: none; flex: none; }
.dk-dest:has(input:checked) .dk-dest__mark { display: block; }
.dk-dest--disabled { opacity: .5; pointer-events: none; }

/* ============================================================================
   T77 - classroom (docs/specs/T77-classroom-collaboration.md)
   The whiteboard's full-screen mode, the participant sidebar, the in-session
   chat, the live poll and the participation report. Moved here out of
   Views/Classroom/Live.cshtml's own inline <style> block (THEME.md section 2:
   no raw hex inside a page), so every value below is a token.
   ============================================================================ */

/* --- whiteboard toolbar (was inline in Live.cshtml) --- */
.wb-tool.active { background: var(--primary-strong); color: var(--on-primary); border-color: var(--primary-strong); }
.wb-swatch {
  inline-size: 22px; block-size: 22px; border-radius: var(--radius-circle); border: 2px solid var(--surface-raised);
  box-shadow: 0 0 0 1px var(--border-default); cursor: pointer; padding: 0;
}
.wb-swatch.active { box-shadow: 0 0 0 2px var(--primary-strong); }

/* --- whiteboard full screen (T77 section 1) ---
   The card itself is what goes full screen, so the toolbar stays reachable with
   the board: a canvas alone full screen would leave the teacher with no pen,
   no colour and no way back except the Escape key. */
#whiteboardCard:fullscreen { display: flex; flex-direction: column; background: var(--surface-raised); }
#whiteboardCard:fullscreen .card-body { flex: 1 1 auto; min-block-size: 0; }
#whiteboardCard:fullscreen #whiteboardCanvas { block-size: 100% !important; }
.wb-exit-fullscreen { position: absolute; inset-block-start: var(--space-3); inset-inline-end: var(--space-3); z-index: 2; }

/* --- whiteboard switched off for this participant (T77 section 6) --- */
.wb-blocked-notice {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--surface-inverse) 55%, transparent); color: var(--text-on-inverse);
  text-align: center; z-index: 3; border-radius: var(--radius-md);
}

/* --- sidebar shell --- */
.dk-classroom-side { block-size: 640px; display: flex; flex-direction: column; }
.dk-classroom-side__body { flex: 1 1 auto; min-block-size: 0; overflow-y: auto; }
.dk-classroom-side .nav-tabs .nav-link { padding-inline: var(--space-3); font-size: var(--fs-small); color: var(--text-secondary); }
.dk-classroom-side .nav-tabs .nav-link.active { color: var(--primary-strong); font-weight: var(--fw-bold); }

/* --- participant row (T77 section 6) --- */
.dk-participant {
  display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3);
  border: var(--hairline) solid var(--border-subtle); border-radius: var(--radius-md); background: var(--surface-raised);
}
.dk-participant.is-spotlighted { border-color: var(--primary-strong); background: var(--primary-surface); }
.dk-participant.is-offline { opacity: .65; }
.dk-participant__name { flex: 1 1 auto; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-small); }
.dk-participant__flags { display: flex; gap: var(--space-1); flex: none; }
.dk-participant__flags .badge { font-size: var(--fs-caption); }

/* --- in-session chat (T77 section 4) --- */
.dk-classroom-chat { display: flex; flex-direction: column; block-size: 100%; min-block-size: 360px; }
.dk-classroom-chat__list { flex: 1 1 auto; min-block-size: 0; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-2); padding-block-end: var(--space-2); }
.dk-classroom-chat__composer { flex: none; border-block-start: var(--hairline) solid var(--border-subtle); padding-block-start: var(--space-2); }
.dk-chatmsg { border-radius: var(--radius-md); padding: var(--space-2) var(--space-3); background: var(--surface-sunken); max-inline-size: 100%; }
.dk-chatmsg.is-mine { background: var(--primary-subtle); color: var(--on-primary-subtle); }
.dk-chatmsg__meta { display: flex; gap: var(--space-2); align-items: baseline; font-size: var(--fs-caption); color: var(--text-secondary); }
.dk-chatmsg.is-mine .dk-chatmsg__meta { color: var(--on-primary-subtle); }
.dk-chatmsg__body { font-size: var(--fs-small); overflow-wrap: anywhere; margin: 0; }
.dk-chatmsg__img { max-inline-size: 100%; border-radius: var(--radius-sm); margin-block-start: var(--space-1); display: block; }
.dk-chatmsg__file { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-small); margin-block-start: var(--space-1); }

/* --- live poll (T77 section 5) --- */
.dk-polloption {
  display: flex; align-items: center; gap: var(--space-2); inline-size: 100%; min-block-size: var(--tap-min);
  padding: var(--space-2) var(--space-3); text-align: start;
  border: var(--hairline) solid var(--border-default); border-radius: var(--radius-md); background: var(--surface-raised);
  position: relative; overflow: hidden; cursor: pointer;
}
.dk-polloption[disabled] { cursor: default; }
.dk-polloption.is-mine { border-color: var(--primary-strong); }
.dk-polloption__fill { position: absolute; inset-block: 0; inset-inline-start: 0; background: var(--primary-subtle); z-index: 0; transition: inline-size var(--motion-base) var(--motion-ease); }
.dk-polloption__t { position: relative; z-index: 1; flex: 1 1 auto; font-size: var(--fs-small); }
.dk-polloption__n { position: relative; z-index: 1; flex: none; font-size: var(--fs-caption); color: var(--text-secondary); }

/* --- participation report (T77 section 3) --- */
.dk-reportcard { border: var(--hairline) solid var(--border-subtle); border-radius: var(--radius-md); padding: var(--space-3); margin-block-end: var(--space-3); }
.dk-reportcard__name { font-weight: var(--fw-bold); font-size: var(--fs-small); margin: 0; }
.dk-metric { margin-block-start: var(--space-2); }
.dk-metric__head { display: flex; justify-content: space-between; font-size: var(--fs-caption); color: var(--text-secondary); }
.dk-metric__track { block-size: 8px; border-radius: var(--radius-pill); background: var(--surface-sunken); overflow: hidden; }
.dk-metric__fill { block-size: 100%; background: var(--primary-strong); border-radius: var(--radius-pill); }
.dk-metric__fill--warning { background: var(--warning-strong); }

/* --- session file shelf (T77 section 2) --- */
.dk-material { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border: var(--hairline) solid var(--border-subtle); border-radius: var(--radius-md); }
.dk-material__name { flex: 1 1 auto; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-small); }
.dk-material__size { flex: none; font-size: var(--fs-caption); color: var(--text-secondary); }
