/* /Components/Dialogs/MistakeManagerDialog.razor.rz.scp.css */
/* Scoped to MistakeManagerDialog.razor (Blazor CSS isolation). It exists for one thing: the read-only
   ayah label under the add/edit row, which replaced the drawer's only piece of Mushaf text being
   absent entirely.

   NO FONT FAMILY IS NAMED HERE, ON PURPOSE
   The label carries app.css's .mateen-ayah class, which is the single documented route by which a
   KFGQPC family may reach the DOM, and the SIZE alone is overridden inline from the markup
   (MistakeManagerDialog.MistakeAyahStyle). The rules below only undo the parts of that shared class
   which are authored for a centred verse paragraph on the Rewayah page and are wrong for a label
   inside a form.

   A NEAR-DUPLICATE OF TicketFormDialog.razor.css'S OWN .mistake-ayah BLOCK, AND IT HAS TO BE
   CSS isolation is per component: the two dialogs render the same label for the same reason (this one
   edits an existing ticket's mistakes, that one stages them while creating), but neither can see the
   other's scoped stylesheet, and the shared alternative is wwwroot/app.css. This label itself stayed
   here when the surrounding layout got a third consumer's worth of shared CSS (2026-09-29, the entry
   row moving inline and the recorded-mistake cards): the label+text pairing below is a small enough
   rule that duplicating it is still cheaper than the indirection of sharing it, unlike the row-sizing
   and card classes, which did move to app.css - see that file's own .mateen-mistake-ayah-text and
   .mateen-mistake-card comments. Keep the two dialogs' copies in step.

   NO LONGER width:100%/margin-top - this used to be a standalone block sitting on its own row below
   the entry form (hence a full-width block with room above it). It now has two different callers
   within this file: the entry row's ayah-text item (a flex child of the MudStack Row, sized 50% by
   app.css's .mateen-mistake-ayah-text, which this class is combined with) and each recorded-mistake
   card's own ayah slot (sized by app.css's .mateen-mistake-card__ayah). Both already own their outer
   sizing/spacing, so this block is left to do only the one thing it does in both places: lay the
   "Ayah ..." caption and the Mushaf text out on one baseline-aligned line, at whatever width its
   caller gives it. */
.mistake-ayah[b-w2avz1mxqc] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

/* A caption in place of a field's floating label, so the line stays self-describing without being a
   field. Small and secondary: the verse is the content. */
.mistake-ayah__label[b-w2avz1mxqc] {
    flex: 0 0 auto;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.mistake-ayah__text[b-w2avz1mxqc] {
    /* Takes everything left over, which is what pushes the verse out to the right. */
    flex: 1 1 auto;
    /* .mateen-ayah centres verse text for the Mushaf page; as a label it has to start at the reading
       edge, which in this RTL span is the right one - so the text hugs the right edge of the drawer,
       where the extra room was asked for. */
    text-align: start;
    /* The verse is the only RTL run in the block; isolation keeps the latin caption beside it from
       being reordered by the bidi algorithm. */
    unicode-bidi: isolate;
    /* A long ayah wraps instead of stretching the drawer; .mateen-ayah's generous line-height keeps the
       stacked diacritics clear of the line below. */
    overflow-wrap: anywhere;
}

/* No text imported for this rewayah - the ordinary case, so it reads as a quiet note in the app's own
   UI font (NOT .mateen-ayah: there is no Arabic here to set in a Mushaf face). */
.mistake-ayah__missing[b-w2avz1mxqc] {
    font-size: 0.8125rem;
    font-style: italic;
    color: var(--mud-palette-text-secondary);
}
/* /Components/Dialogs/NextSessionTaskFormDialog.razor.rz.scp.css */
/* Scoped to NextSessionTaskFormDialog. The plan cards are the same white-card radio idiom as
   TicketFormDialog (.ticket-white-card / .ticket-plan-card): white in both modes, with the palette
   variables re-pinned so every text/icon inside resolves to dark-on-white regardless of theme. */
.nst-white-card[b-b14puc7tb3] {
    background-color: #FFFFFF;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    --mud-palette-text-primary: #2A2740;
    --mud-palette-text-secondary: #6B667F;
    --mud-palette-primary: #471671;
    --mud-palette-lines-default: #E2DFEE;
    --mud-palette-action-default: rgba(0, 0, 0, 0.54);
    --mud-palette-action-default-hover: rgba(0, 0, 0, 0.04);
}

    .nst-white-card[b-b14puc7tb3]  .mud-typography,
    .nst-white-card .nst-plan-title[b-b14puc7tb3] {
        color: var(--mud-palette-text-primary);
    }

    .nst-white-card .nst-plan-detail[b-b14puc7tb3] {
        color: var(--mud-palette-text-secondary);
    }

.nst-plan-summary[b-b14puc7tb3] {
    padding: 12px 14px;
}

.nst-plan-cards[b-b14puc7tb3]  .mud-radio-group {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    max-height: 296px;
    overflow-y: auto;
    padding: 2px;
}

.nst-plan-card[b-b14puc7tb3] {
    flex: 0 0 auto;
    transition: border-color .15s ease, box-shadow .15s ease;
}

    .nst-plan-card:hover[b-b14puc7tb3] {
        border-color: color-mix(in srgb, var(--mud-palette-primary) 50%, transparent);
    }

    .nst-plan-card:has(.mud-checked)[b-b14puc7tb3] {
        border-color: var(--mud-palette-primary);
        box-shadow: 0 0 0 1px color-mix(in srgb, var(--mud-palette-primary) 35%, transparent);
    }

    .nst-plan-card[b-b14puc7tb3]  .mud-input-control,
    .nst-plan-card[b-b14puc7tb3]  .mud-input-control-input-container {
        width: 100%;
    }

    .nst-plan-card[b-b14puc7tb3]  .mud-radio {
        width: 100%;
        padding: 6px 10px;
        min-width: 0;
        align-items: flex-start;
    }

    .nst-plan-card[b-b14puc7tb3]  .mud-radio .mud-typography {
        color: var(--mud-palette-text-primary);
        min-width: 0;
        overflow-wrap: anywhere;
    }

.nst-plan-title[b-b14puc7tb3] {
    display: block;
    font-weight: 600;
}

.nst-plan-detail[b-b14puc7tb3] {
    display: block;
    font-size: 0.75rem;
    line-height: 1.3;
}

/* The "Ayat" field: a div around a MudField that opens AyahRangePickerDialog (same as the ticket form). */
.nst-ayah-range[b-b14puc7tb3] {
    flex: 1 1 150px;
    cursor: pointer;
    border-radius: 4px;
}

    .nst-ayah-range:focus-visible[b-b14puc7tb3] {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: 2px;
    }

.nst-ayah-range--locked[b-b14puc7tb3] {
    cursor: default;
}

.nst-ayah-range__value[b-b14puc7tb3] {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
/* /Components/Dialogs/PlanFormDialog.razor.rz.scp.css */
/* ===================================================================================
   WHITE CARDS IN THIS DIALOG (shared base)
   ===================================================================================
   Two places in this form were asked to sit in a card with a white background:
     .plan-direction-card  - one per "Direction" radio option (create branch);
     .plan-summary-card    - the read-only plan + its details (edit branch).
   Both take this base class so they stay one idiom; each adds only its own layout below.

   Treatment is the app's existing card language rather than something invented: white surface +
   1px --mud-palette-lines-default hairline + 14px radius, i.e. .mateen-landing-card /
   .mateen-home-plan-card / .mateen-home-feature-card in app.css. Only the padding differs per use
   (those landing panels run 22-26px, far too much inside a drawer whose fields are 48px rows).

   WHITE IN BOTH MODES - AND WHY EVERY FOREGROUND IS PINNED WITH IT
   -----------------------------------------------------------------------------------
   The request was literally a WHITE background, so this is #FFFFFF in light AND dark mode, not
   var(--mud-palette-surface) (which would be the navy #121A3F in dark, i.e. what every other card
   in the app does - that is the one-line alternative if the white blocks read wrong against the
   dark drawer: swap the background-color below for var(--mud-palette-surface) and drop the
   variable pins).

   A white panel in dark mode is exactly the trap that produced the invisible white-on-white drawer
   header on 2026-10-03: the contents would still take the DARK palette - the radio label and the
   plan summary line inherit --mud-palette-text-primary (#E9EAEE, 1.20:1 on white, measured) and the
   radio glyph takes --mud-palette-primary (#BB86EA, 2.72:1, under the 3:1 floor for a control). So
   rather than chase individual `color` declarations through MudBlazor's (often !important) rules,
   the card REDEFINES the palette variables those rules read, back to their light-mode values from
   Theme/MateenTheme.cs:
     --mud-palette-text-primary    -> #2A2740 (LightForeground)      14.36:1 on #FFFFFF
     --mud-palette-text-secondary  -> #6B667F (LightMutedForeground)  5.74:1 on #FFFFFF
     --mud-palette-primary         -> #471671 (LightPrimary)         12.95:1 on #FFFFFF
     --mud-palette-lines-default   -> #E2DFEE (LightBorder) - so the hairline reads the same in both
                                      modes; the dark token is #BB86EA38, which composites on white
                                      to ~rgb(240,228,250), i.e. no visible edge at all
     --mud-palette-action-default / -hover -> MudBlazor's own light-mode values (radio hover/ripple)
   Custom properties inherit to every descendant regardless of CSS-isolation scope attributes, so
   the glyph, the hover tint and the ripple all follow with no ::deep rule and no !important of our
   own, and an !important MudBlazor rule still resolves through the pinned variable.

   WHAT VARIABLE PINNING CANNOT FIX (learned by measuring, not by reading)
   Pinning only affects declarations EVALUATED on a descendant of the card. Any text whose own rule
   is `color: inherit` - which is what MudText emits when no Color is set - inherits the colour
   already COMPUTED on an ancestor outside the card, i.e. the dark #E9EAEE, and no amount of
   variable pinning touches it. Both cards therefore re-declare `color` explicitly on their text
   (see the two `.mud-typography` rules below). Nothing outside the cards is touched either way.
   --mud-palette-secondary is deliberately NOT pinned: it is #9333EA in both modes already and
   lands at 5.38:1 on white, so the "Direction:" caption keeps exactly the colour it has today.
   =================================================================================== */
.plan-white-card[b-2xizucy91h] {
    background-color: #FFFFFF;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    --mud-palette-text-primary: #2A2740;
    --mud-palette-text-secondary: #6B667F;
    --mud-palette-primary: #471671;
    --mud-palette-lines-default: #E2DFEE;
    --mud-palette-action-default: rgba(0, 0, 0, 0.54);
    --mud-palette-action-default-hover: rgba(0, 0, 0, 0.04);
}

/* ===================================================================================
   DIRECTION OPTION CARDS (the two-option "Direction" radio group, create branch)
   =================================================================================== */
.plan-direction-cards[b-2xizucy91h]  .mud-radio-group {
    display: flex;
    /* wrap, not a media query: below Sm the drawer goes full-bleed (app.css's .mateen-drawer-dialog
       phone rule), and two 210px-minimum cards cannot fit a ~372px phone content width, so they
       stack themselves. At the drawer's normal 552px of content they sit side by side at ~271px
       each - which keeps this group the same ~1 row tall it was before the cards, in a drawer whose
       body already scrolls. */
    flex-wrap: wrap;
    gap: 10px;
}

/* Colour/border/radius and the dark-mode variable pins all come from .plan-white-card above; this
   adds only the layout. */
.plan-direction-card[b-2xizucy91h] {
    /* Equal halves of whatever width the row has, down to the wrap threshold above. */
    flex: 1 1 0;
    min-width: 210px;
    transition: border-color .15s ease, box-shadow .15s ease;
}

    /* Same hover feedback as .mateen-home-feature-card (border only - no translate: a form control
       that jumps under the pointer is worse than one that doesn't). */
    .plan-direction-card:hover[b-2xizucy91h] {
        border-color: color-mix(in srgb, var(--mud-palette-primary) 50%, transparent);
    }

    /* SELECTED STATE. Two near-identical white cards distinguished only by a small dot is weak
       feedback, so the chosen one takes a full primary-coloured border plus a faint primary ring.
       Matched on :has(.mud-checked) - the class MudBlazor puts on the checked radio's button span -
       rather than :has(input:checked), because MudRadio renders the selection as that class and the
       icon's own svg path; the input's checked IDL property is not what drives its appearance.
       No ::deep inside :has(): isolation appends this component's scope attribute to the compound
       selector itself (.plan-direction-card:has(...)[b-xxx]), which already matches, and :has() then
       looks at the child component's unscoped descendants anyway. */
    .plan-direction-card:has(.mud-checked)[b-2xizucy91h] {
        border-color: var(--mud-palette-primary);
        box-shadow: 0 0 0 1px color-mix(in srgb, var(--mud-palette-primary) 35%, transparent);
    }

    /* Stretch MudRadio's wrapper, its inner container and the <label> itself across the whole card,
       and move the card's padding onto that label, so clicking anywhere in the card selects the
       option (see the markup comment - the label is the native click target). */
    .plan-direction-card[b-2xizucy91h]  .mud-input-control,
    .plan-direction-card[b-2xizucy91h]  .mud-input-control-input-container {
        width: 100%;
    }

    .plan-direction-card[b-2xizucy91h]  .mud-radio {
        width: 100%;
        padding: 4px 10px;
        /* The two labels are long and differ only in word order ("Al-Baqarah -> An-Nas" /
           "An-Nas -> Al-Baqarah"); if the drawer is ever narrower than they are, wrap the text inside
           the card instead of pushing a scrollbar onto the dialog. */
        min-width: 0;
    }

        .plan-direction-card[b-2xizucy91h]  .mud-radio .mud-typography {
            /* NOT redundant with .plan-white-card's pinned --mud-palette-text-primary, and the one
               thing that actually fixes the dark-mode trap for the TEXT - see "WHAT VARIABLE PINNING
               CANNOT FIX" in the header comment. Measured before adding this line: 1.20:1 on the white
               card in dark mode (invisible); after: 14.36:1 in both modes. */
            color: var(--mud-palette-text-primary);
            min-width: 0;
            overflow-wrap: anywhere;
        }

/* ===================================================================================
   PLAN SUMMARY CARD (edit branch)
   ===================================================================================
   The read-only plan and its details - "<Rewayah>: <From> -> <To>" plus the "Direction:" line - in
   the same white card as the Direction options above. Padding is a little roomier than the radio
   cards' because this is a text block rather than a 48px control, and matches the 12-14px the
   dialog's own fields sit at.

   The "range can't be changed" caption is deliberately left OUTSIDE this card: it is guidance about
   what this form will and will not let you edit, not a detail of the plan, and keeping it on the
   drawer background means it also keeps the theme's own muted colour in dark mode.
   =================================================================================== */
.plan-summary-card[b-2xizucy91h] {
    padding: 12px 14px;
}

    /* Same reason as the radio label above: MudText's subtitle2 is `color: inherit`, so on a white
       card in dark mode it would arrive as the already-computed #E9EAEE (1.20:1). The "Direction:"
       caption carries MudBlazor's own .mud-secondary-text (--mud-palette-secondary #9333EA, !important
       in MudBlazor.css and identical in both modes - 5.38:1 on white), so it keeps its current colour
       and is intentionally not overridden here. */
    .plan-summary-card[b-2xizucy91h]  .mud-typography {
        color: var(--mud-palette-text-primary);
    }

/* Scoped to PlanFormDialog.razor (Blazor CSS isolation). The rules below exist for exactly one
   thing: making app.css's verse-text class usable as a LABEL inside this dialog's two Sura picker
   inputs when the user has chosen Arabic sura names.

   NO FONT FAMILY IS NAMED HERE, ON PURPOSE
   'QPC Hafs V22' (with V18 and a generic Arabic serif behind it) reaches those inputs only by their
   carrying app.css's .mateen-ayah class via MudAutocomplete's InputClass - that class is the single
   documented route for a Mushaf family to reach the DOM, and nothing in the app may hardcode the
   family. These rules override the size (a name is a short label, not a 2rem verse) and the two
   properties of that block that are authored for a centred verse paragraph and are actively wrong in
   a single-line text field.

   TWO SELECTORS
   MudAutocomplete 9.10.0 exposes InputClass but no InputStyle, and does not document whether the
   class lands on the <input> element itself or on the input wrapper around it. The first rule covers
   the former; the second lets the inherited face through to the control in the latter case, since
   form controls do not inherit font-family by default. `font: inherit` rather than a family, so the
   face still comes from .mateen-ayah alone. */

.plan-sura-pickers[b-2xizucy91h]  .mateen-ayah {
    --mateen-ayah-size: 1rem;
    line-height: normal;
    /* .mateen-ayah centres verse text; text-align does apply inside an input, and a centred picker
       value would be the only one on the form. */
    text-align: start;
}

    .plan-sura-pickers[b-2xizucy91h]  .mateen-ayah input {
        font: inherit;
    }

/* Body of the selected plan type (Whole Suras / Pages) - indented under its radio. Colours come from the
   active theme (MudBlazor palette variables), nothing hard-coded. */
.plan-type-section[b-2xizucy91h] {
    padding-left: 1.75rem;
    margin-bottom: 0.25rem;
}
/* /Components/Dialogs/SuggestionFormDialog.razor.rz.scp.css */
/* Scoped to SuggestionFormDialog only (Blazor CSS isolation) rather than added to app.css, since
   nothing outside this one form has a pending-attachment strip. */

/* The attachments block reads as its own field group, separated from the Title/Feedback pair above
   by the same hairline MudBlazor uses between input rows rather than by a heading alone. */
.attachments[b-xs1kssjeh3] {
    border-top: 1px solid var(--mud-palette-lines-default);
    padding-top: 12px;
}

/* Wraps, so any number of staged images stays inside the 600px drawer instead of scrolling
   sideways. */
.thumb-strip[b-xs1kssjeh3] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.thumb[b-xs1kssjeh3] {
    position: relative;
    width: 96px;
    height: 96px;
    border-radius: 8px;
    border: 1px solid var(--mud-palette-lines-inputs, #c4c4c4);
    background-color: var(--mud-palette-background-grey, #f5f5f5);
    overflow: hidden;
}

    /* contain, not cover: this is a preview of a file the user is about to send, so showing the whole
       frame matters more than filling the square neatly. */
    .thumb img[b-xs1kssjeh3] {
        width: 100%;
        height: 100%;
        object-fit: contain;
    }

/* The remove X sits on the thumbnail's top-right corner. Always visible rather than hover-only: on a
   touch screen there is no hover, and removing a wrongly-picked attachment has to be reachable. The
   dark scrim behind it is what keeps a white X legible over a pale photo.

   ::deep is required here and not optional: .thumb-remove is on a MudIconButton, and Blazor's CSS
   isolation only stamps its scope attribute onto elements THIS component renders - a child
   component's own root element never gets it, so a bare .thumb-remove rule would compile to
   .thumb-remove[b-xxx] and match nothing. Anchoring it to .thumb (which is this component's div)
   and reaching in with ::deep is what makes it apply. */
.thumb[b-xs1kssjeh3]  .thumb-remove {
    position: absolute;
    top: 2px;
    right: 2px;
    padding: 2px;
    color: #fff;
    background-color: rgba(0, 0, 0, 0.55);
}

    .thumb[b-xs1kssjeh3]  .thumb-remove:hover {
        background-color: rgba(0, 0, 0, 0.75);
    }
/* /Components/Dialogs/SuraTicketsDialog.razor.rz.scp.css */
/* Scoped to SuraTicketsDialog (Blazor CSS isolation). Only the plain elements this dialog declares
   itself are styled here - the MudPaper/MudStack/MudChip parts it composes carry no scope attribute
   and are left to MudBlazor and the palette, which is why nothing below needs ::deep. */

/* Scope line under the title: which Sura, which ayah window, which plan. Sits above the list as a
   quiet caption rather than a second heading - the title bar already names the Sura. */
.sura-tickets-scope[b-tk0tqdy8f6] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 16px;
}

.sura-tickets-scope__arabic[b-tk0tqdy8f6] {
    font-size: 1.0625rem;
    line-height: 1.6;
    color: var(--mud-palette-text-primary);
}

.sura-tickets-scope__meta[b-tk0tqdy8f6] {
    font-size: .75rem;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
    /* Ayah numbers line up between tickets. */
    font-variant-numeric: tabular-nums;
}

.sura-tickets-scope__sep[b-tk0tqdy8f6] {
    margin: 0 6px;
    opacity: .6;
}

/* The right-hand column of a ticket's header row: the type chip, with the mistake flag stacked under
   it. A column so the flag reads as belonging to that chip's ticket rather than to the row as a
   whole, end-aligned so both stay flush with the card edge the chip already sits on. */
.sura-tickets-type[b-tk0tqdy8f6] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    /* No gap of our own: MudBlazor gives .mud-chip a 4px margin on all sides, which already separates
       the two and is also what the warning below has to be indented by to line up with the chip. */
    gap: 0;
    /* The chip must not be squeezed by a long "Ayat 100-286" on the left. */
    flex: 0 0 auto;
}

/* The "this ticket has mistakes" flag. Orange comes from the theme's own warning tokens rather than a
   hex, so it follows the palette, but WHICH warning token depends on the mode: the plain
   --mud-palette-warning (#FF9800 light) manages only 2.2:1 on the white card, under the 3:1 WCAG
   1.4.11 asks of a meaningful graphic, while its -darken sibling (#D68100) clears it at 3.0:1 and is
   still unmistakably orange, not brown. In dark mode the opposite holds: the card is #121A3F, so the
   plain dark-mode warning (#FFA800) sits at roughly 7.8:1 and is the brighter, more legible of the
   two. light-dark() picks per mode off the color-scheme app.css already puts on :root - the same
   mechanism the landing and login blocks there use.

   The colour is set here on the span rather than as Color.Warning on the MudIcon precisely so it can
   differ per mode; MudIcon defaults to Color.Inherit and its SVG fills with currentColor, so it
   simply takes this. The span is also the flag's accessible name (role="img" + aria-label in the
   markup), and lines up its own icon. */
.sura-tickets-type__warning[b-tk0tqdy8f6] {
    display: inline-flex;
    align-items: center;
    /* The mode signal light-dark() below resolves against, declared HERE and not assumed: MudBlazor
       9.10.0 emits --mud-native-html-color-scheme on :root but only feeds it into the real
       `color-scheme` property on .mud-input, so anything outside an input that wants light-dark() has
       to do this for itself - exactly what app.css's .mateen-landing / .mateen-login /
       .mateen-person-card blocks each do, and why they document it. Without this line light-dark()
       sees color-scheme:normal and silently always returns the LIGHT value. */
    color-scheme: var(--mud-native-html-color-scheme);
    color: light-dark(var(--mud-palette-warning-darken), var(--mud-palette-warning));
    /* Matches .mud-chip's own 4px margin so the icon sits under the chip's right edge rather than 4px
       past it - the flag has to read as belonging to the chip above it. */
    margin-inline-end: 4px;
}

/* Grade + score on one baseline. The chip carries the band colour; the score stays neutral so the
   colour reads as the verdict rather than as two competing signals. */
.sura-tickets-grade[b-tk0tqdy8f6] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 6px 0 8px;
}

.sura-tickets-grade__score[b-tk0tqdy8f6] {
    font-size: .8125rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* One mistake per row, wrapping rather than scrolling: the drawer is 600px at most and a mistake
   line is type + count + ayah + cost + a free-text note. */
.sura-tickets-mistake[b-tk0tqdy8f6] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    font-size: .8125rem;
    line-height: 1.6;
    color: var(--mud-palette-text-secondary);
}

.sura-tickets-mistake__type[b-tk0tqdy8f6] {
    color: var(--mud-palette-text-primary);
    font-weight: 600;
}

.sura-tickets-mistake__ayah[b-tk0tqdy8f6] {
    font-variant-numeric: tabular-nums;
}

/* The points this mistake cost - error-coloured because it is a deduction, and kept from wrapping
   away from its own row. */
.sura-tickets-mistake__score[b-tk0tqdy8f6] {
    color: var(--mud-palette-error);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The ayah's Arabic text, under the mistake line it belongs to. flex-basis:100% is what puts it on
   its own line: .sura-tickets-mistake is a wrapping flex row, so a full-width item is forced to break,
   which is why the markup renders it last. Nothing about the font is set here - family, size, RTL,
   line-height and the centred setting all come from the global .mateen-ayah class plus the inline
   --mateen-ayah-size the markup passes, which is app.css's single-place contract for Mushaf text;
   adding a font-family or font-size here would quietly fork it.

   The top margin is negative-free and small on purpose: .mateen-ayah's 2.2 line-height already leaves
   air above the glyphs (it has to, for the tall stacked diacritics), so anything more would open a
   visible gap between the number and its own verse. */
.sura-tickets-mistake__text[b-tk0tqdy8f6] {
    flex: 1 1 100%;
    margin-top: 2px;
    /* Reads as the detail line it is rather than as a heading competing with the ticket above it. */
    color: var(--mud-palette-text-primary);
    opacity: .9;
}

/* Notes run to 500 characters; clipped to the remaining width on one line, with the full text in
   the tooltip the markup wraps it in. min-width:0 is what actually lets a flex item shrink below
   its content's width so the ellipsis can happen at all. */
.sura-tickets-mistake__note[b-tk0tqdy8f6] {
    flex: 1 1 120px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-style: italic;
    opacity: .85;
}
/* /Components/Dialogs/TicketFormDialog.razor.rz.scp.css */
/* Scoped to TicketFormDialog.razor (Blazor CSS isolation). */

/* ===================================================================================
   PLAN CARDS (New: one selectable white card per plan; Edit: one read-only summary card)
   ===================================================================================
   DELIBERATELY A MINIMAL COPY of PlanFormDialog.razor.css's .plan-white-card / .plan-direction-card /
   .plan-summary-card, not a shared class: that file is scoped and was finished and verified today, and
   hoisting it into app.css would have meant editing the working Add/Edit Plan styles. The full
   rationale (WHY it is white in both modes, why the palette variables are re-pinned, why the text
   colour must ALSO be re-declared explicitly because MudText emits `color: inherit`) is in the header of
   that file - read it before changing anything here. If the white-vs-surface decision flips, change
   BOTH files' .xxx-white-card background (and drop the pins).
   =================================================================================== */
.ticket-white-card[b-kmapwgpcob] {
    background-color: #FFFFFF;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    --mud-palette-text-primary: #2A2740;
    --mud-palette-text-secondary: #6B667F;
    --mud-palette-primary: #471671;
    --mud-palette-lines-default: #E2DFEE;
    --mud-palette-action-default: rgba(0, 0, 0, 0.54);
    --mud-palette-action-default-hover: rgba(0, 0, 0, 0.04);
}

    .ticket-white-card[b-kmapwgpcob]  .mud-typography,
    .ticket-white-card .ticket-plan-title[b-kmapwgpcob] {
        color: var(--mud-palette-text-primary);
    }

    /* Muted detail line (the plan's period). Explicit colour for the same inherit-trap reason. */
    .ticket-white-card .ticket-plan-detail[b-kmapwgpcob],
    .ticket-white-card[b-kmapwgpcob]  .mud-typography.ticket-plan-detail {
        color: var(--mud-palette-text-secondary);
    }

.ticket-plan-summary[b-kmapwgpcob] {
    padding: 12px 14px;
}

/* Stack of cards. Plans are long ("Rewayah: Sura a -> Sura b (dd-MM-yyyy - dd-MM-yyyy)"), so one
   column; capped in height and scrolled so a student with many plans doesn't push the form away.
   The 2px padding keeps the selected ring (box-shadow) from being clipped by the overflow. */
.ticket-plan-cards[b-kmapwgpcob]  .mud-radio-group {
    display: flex;
    flex-direction: column;
    /* MudBlazor's own group rule centres items; without this the cards shrink-wrap and float. */
    align-items: stretch;
    gap: 10px;
    max-height: 296px;
    overflow-y: auto;
    padding: 2px;
}

.ticket-plan-card[b-kmapwgpcob] {
    flex: 0 0 auto;
    transition: border-color .15s ease, box-shadow .15s ease;
}

    .ticket-plan-card:hover[b-kmapwgpcob] {
        border-color: color-mix(in srgb, var(--mud-palette-primary) 50%, transparent);
    }

    .ticket-plan-card:has(.mud-checked)[b-kmapwgpcob] {
        border-color: var(--mud-palette-primary);
        box-shadow: 0 0 0 1px color-mix(in srgb, var(--mud-palette-primary) 35%, transparent);
    }

    .ticket-plan-card[b-kmapwgpcob]  .mud-input-control,
    .ticket-plan-card[b-kmapwgpcob]  .mud-input-control-input-container {
        width: 100%;
    }

    .ticket-plan-card[b-kmapwgpcob]  .mud-radio {
        width: 100%;
        padding: 6px 10px;
        min-width: 0;
        align-items: flex-start;
    }

    .ticket-plan-card[b-kmapwgpcob]  .mud-radio .mud-typography {
        color: var(--mud-palette-text-primary);
        min-width: 0;
        overflow-wrap: anywhere;
    }

.ticket-plan-title[b-kmapwgpcob] {
    display: block;
    font-weight: 600;
}

.ticket-plan-detail[b-kmapwgpcob] {
    display: block;
    font-size: 0.75rem;
    line-height: 1.3;
}

/* ===================================================================================
   The "Ayat" field - the row's ayah range, which opens AyahRangePickerDialog.

   It is a div wrapping a MudField, not an input, because the range is picked in a dialog (see the
   markup's own comment). That div is the flex item on the Sura row, so the flex basis belongs here
   and not on the MudField: it replaced two .mateen-ticket-row-ayah numeric fields (70px each), and
   150px is what a "123-456 (334)" value needs next to its label without the field looking padded.

   Class-based, like every other field on that row, for the reason app.css's .mateen-ticket-row-*
   block documents at length: MudBlazor routes Style and Class to different elements per component,
   and only Class reliably lands on the outer MudInputControl. Here the basis is on our own div, so
   that hazard does not apply - but staying consistent with the neighbouring fields does.
   =================================================================================== */
.ticket-ayah-range[b-kmapwgpcob] {
    flex: 1 1 150px;
    cursor: pointer;
    /* The field is keyboard-focusable (role=button + tabindex), so it must show focus - MudField
       cannot, since the focus lands on this wrapper instead of on an input. */
    border-radius: 4px;
}

    .ticket-ayah-range:focus-visible[b-kmapwgpcob] {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: 2px;
    }

    /* No Sura chosen yet, or the row is already created: MudField is drawing itself disabled, so this
       only has to stop the pointer promising a click that OpenAyahPickerAsync would refuse. */
    .ticket-ayah-range--locked[b-kmapwgpcob] {
        cursor: default;
    }

.ticket-ayah-range__value[b-kmapwgpcob] {
    font-weight: 600;
    /* The range is digits that are read as a pair, so they line up column-wise as they change. */
    font-variant-numeric: tabular-nums;
}

/* ===================================================================================
   The staged mistake's ayah text - a read-only label, not a field.

   FAMILY AND SIZE
   Nothing here names a Mushaf family: the span carries app.css's .mateen-ayah class, which is that
   file's single sanctioned route for one, and the SIZE alone is overridden inline from the markup
   (TicketFormDialog.MistakeAyahStyle) exactly as SuraTicketsDialog does it. The rules below only
   undo the parts of .mateen-ayah that are authored for a centred verse paragraph on the Rewayah
   page and are wrong for a label inside a form.

   NO LONGER width:100%/margin-top (2026-09-29) - this used to sit on its own row below the entry
   form, hence a full-width block with room above it. It now has two different callers in this file:
   the entry row's ayah-text item (a flex child of the MudStack Row, sized 50% by app.css's own
   .mateen-mistake-ayah-text, which this class is combined with there) and each staged mistake card's
   own ayah slot (sized by app.css's .mateen-mistake-card__ayah). Both already own their outer sizing
   and spacing, so this block now does only the one thing it does in both places: lay the "Ayah ..."
   caption and the Mushaf text out on one baseline-aligned line, at whatever width its caller gives
   it. Kept here rather than folded into app.css alongside the row/card classes that DID move there
   (see that file's .mateen-mistake-ayah-text and .mateen-mistake-card comments) because this small a
   rule is still cheaper to keep duplicated between the two dialogs than to add another layer of
   indirection for. */
.mistake-ayah[b-kmapwgpcob] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

/* A caption where the MudTextField's floating label used to be, so the line is still self-describing
   now that it is no longer a labelled field. Kept small and secondary: the verse is the content. */
.mistake-ayah__label[b-kmapwgpcob] {
    flex: 0 0 auto;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.mistake-ayah__text[b-kmapwgpcob] {
    /* Takes everything left over, which is what pushes the verse out to the right. */
    flex: 1 1 auto;
    /* .mateen-ayah centres verse text for the Mushaf page; as a label on a form row it has to start at
       the reading edge, which in this RTL span is the right one - so the text ends up hugging the
       right edge of the drawer, where the request was for it to have more room. */
    text-align: start;
    /* The verse is the only RTL run in the block; isolation keeps the latin caption beside it from
       being reordered by the bidi algorithm. */
    unicode-bidi: isolate;
    /* A long ayah wraps rather than stretching the drawer; .mateen-ayah's generous line-height keeps
       the stacked diacritics clear of the line below. */
    overflow-wrap: anywhere;
}

/* The Sura/Ayat/Grade row (create mode's trailing "already created" check / "remove this Sura"
   button) switched from AlignItems.Center to AlignItems.Start on its MudStack, to fix Grade's own
   input box no longer lining up with Sura's and Ayat's - Grade is the only field on that row with
   HelperText, so Center was centring the shorter fields against a box tall enough to include a
   helper-text line that only Grade has. Start fixes the three inputs but would otherwise pin this
   icon to the top of the row alongside the labels, since it has no label/helper text of its own to
   push it down. align-self overrides just this one item back to centring against the row's full
   height (Grade's, helper text included), which is where it sat before and still belongs. */
.mateen-ticket-row-action[b-kmapwgpcob] {
    align-self: center;
}

/* No text imported for this rewayah - the ordinary case, so it reads as a quiet note in the app's own
   UI font (NOT .mateen-ayah: there is no Arabic here to set in a Mushaf face). */
.mistake-ayah__missing[b-kmapwgpcob] {
    font-size: 0.8125rem;
    font-style: italic;
    color: var(--mud-palette-text-secondary);
}
/* /Components/Dialogs/UserFormDialog.razor.rz.scp.css */
/* Increment 17 - real photo-upload feature. Scoped to UserFormDialog only (Blazor CSS isolation). */

.photo-upload-square[b-5l1eci29jy] {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 200px;
    height: 200px;
    border-radius: 12px;
    border: 1px dashed var(--mud-palette-lines-inputs, #c4c4c4);
    background-color: var(--mud-palette-background-grey, #f5f5f5);
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
}

.photo-upload-img[b-5l1eci29jy] {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Hover/focus overlay - makes "click here to replace the photo" discoverable both when the square
   is still showing the empty-state placeholder and when it's already showing a real photo (edit
   mode), so swapping an existing photo is exactly as smooth/obvious as setting one for the first
   time. */
.photo-upload-overlay[b-5l1eci29jy] {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    background-color: rgba(0, 0, 0, 0.55);
    color: #fff;
    opacity: 0;
    transition: opacity 0.15s ease-in-out;
    text-align: center;
    padding: 4px;
    pointer-events: none;
}

.photo-upload-square:hover .photo-upload-overlay[b-5l1eci29jy],
.photo-upload-square:focus .photo-upload-overlay[b-5l1eci29jy] {
    opacity: 1;
}

.photo-upload-overlay-text[b-5l1eci29jy] {
    font-size: 0.7rem;
    line-height: 1;
}

.photo-upload-square:focus-visible[b-5l1eci29jy] {
    outline: 2px solid var(--mud-palette-primary, #594ae2);
    outline-offset: 2px;
}

/* Remove-photo badge - always visible (not gated behind the hover overlay like the camera icon),
   since it is its own standalone action rather than a hint about what clicking the square does.
   Sits above both the image and the overlay (z-index) so it stays clickable through either state.
   .photo-upload-remove is the plain stopPropagation wrapper div (positioning only, see the markup's
   own comment on why the modifier lands on a div and not the MudIconButton directly) - the visual
   styling targets the button MudIconButton actually renders, inside it. ::deep is required here:
   CSS isolation never stamps this file's scope attribute onto markup a CHILD component renders,
   and MudIconButton is exactly that. */
.photo-upload-remove[b-5l1eci29jy] {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 2;
}

    .photo-upload-remove[b-5l1eci29jy]  .mud-icon-button {
        background-color: rgba(0, 0, 0, 0.55);
        color: #fff;
    }

    .photo-upload-remove[b-5l1eci29jy]  .mud-icon-button:hover {
        background-color: rgba(0, 0, 0, 0.75);
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
/* Pins the footer nav section (School Configuration) to the bottom of MudDrawer regardless of how
   long the main nav list above grows - MudDrawer itself is already a flex column filling the
   viewport height, so this wrapper just needs to stretch to fill the remaining space and push its
   last child down with margin-top:auto. */

.mateen-nav-menu-wrapper[b-vp2ryaash5] {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    /* padding-inline-start, not padding-left: the drawer's "start" edge is the right edge in an
       RTL layout, and this wrapper has no other horizontal padding of its own to conflict with. */
    padding-inline-start: 10px;
}

.mateen-nav-menu-footer[b-vp2ryaash5] {
    margin-top: auto;
}

/* Section header labels (MAIN / QURAN LEARNING / ADMINISTRATION / INSIGHTS) per the design - plain
   small-caps text ahead of a cluster of links, not an interactive MudNavGroup (see the long comment
   at the top of NavMenu.razor for why). Muted/secondary colour and letter-spacing so it reads as a
   label rather than another nav link; the surrounding MudNavLinks already carry their own left
   padding, so this is indented to match rather than starting flush with the drawer edge. */
.mateen-nav-section-header[b-vp2ryaash5] {
    display: block;
    padding: 12px 16px 4px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    opacity: 0.6;
}

/* Leave Requests' pending-count badge (see NavMenu.razor's @code block) - a small inline pill next
   to the label rather than a dot stuck on the icon, matching the design's "3" badge. */
.mateen-nav-badge[b-vp2ryaash5] {
    margin-right: 8px;
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-uq1lh2rudl],
.components-reconnect-repeated-attempt-visible[b-uq1lh2rudl],
.components-reconnect-failed-visible[b-uq1lh2rudl],
.components-pause-visible[b-uq1lh2rudl],
.components-resume-failed-visible[b-uq1lh2rudl],
.components-rejoining-animation[b-uq1lh2rudl] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-retrying[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-failed[b-uq1lh2rudl],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-uq1lh2rudl] {
    display: block;
}


#components-reconnect-modal[b-uq1lh2rudl] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-uq1lh2rudl 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-uq1lh2rudl 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-uq1lh2rudl 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-uq1lh2rudl]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-uq1lh2rudl 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-uq1lh2rudl {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-uq1lh2rudl {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-uq1lh2rudl {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-uq1lh2rudl] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-uq1lh2rudl] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-uq1lh2rudl] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-uq1lh2rudl] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-uq1lh2rudl] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-uq1lh2rudl] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-uq1lh2rudl] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-uq1lh2rudl 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-uq1lh2rudl] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-uq1lh2rudl {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/Account/Profile.razor.rz.scp.css */
/* Layout for the "My details" tab of the shared profile page (Account/Profile.razor - it moved here
   from Pages/Student/ when the page was opened to Admin and Educator; nothing in it is role-specific,
   the role differences live in the markup). Scoped rather than added to app.css
   because nothing else in the app renders a record this way - app.css is for idioms shared across
   pages, and the shared pieces this tab uses (.mateen-accent-card, .mateen-pill, and the whole
   .mateen-person-card__* family PersonCard itself renders) already live there and are only composed
   here, never redefined.

   Every colour comes from MudBlazor's palette variables, so light and dark mode both work without a
   second rule set.

   NO MORE "identity band" RULES HERE (2026-09-29): the hand-rolled .profile-identity* block that used
   to live in this section is gone along with the markup it styled - the identity card is now
   Components/Shared/PersonCard.razor itself (see the "IDENTITY BAND" comment at the top of
   Profile.razor), which brings its own styling from app.css and needs nothing scoped to this page.
   .profile-pill / .profile-pill--empty survive below because Profile.razor still uses them directly,
   for the one thing PersonCard doesn't draw on its own: the "no languages recorded" empty state. */

/* Border, radius and fill come from .mateen-pill, which every one of these also carries - only the
   typography is set here, matching the scaled-down person-card language pills. */
.profile-pill[b-mn8qknys6z] {
    font-size: .78rem;
    padding: 2px 10px;
    line-height: 1.7;
    color: var(--mud-palette-text-primary);
}

/* "Nothing recorded" reads as absence, not as a value. */
.profile-pill--empty[b-mn8qknys6z] {
    color: var(--mud-palette-text-secondary);
    font-style: italic;
}

/* --- grouped field cards --------------------------------------------------------------------- */

/* Equal height side by side: the two cards hold a different number of rows, and a short card next to
   a tall one is exactly what made the old tab look unfinished. */
.profile-card[b-mn8qknys6z] {
    height: 100%;
}

.profile-card__title[b-mn8qknys6z] {
    font-size: .78rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* icon | label over value. The label above the value (rather than beside it) keeps the values on one
   left edge, which is what makes a column of them scannable. */
.profile-field[b-mn8qknys6z] {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 8px 0;
}

    .profile-field + .profile-field[b-mn8qknys6z] {
        border-top: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 55%, transparent);
    }

/* Same ::deep reason as above - this class is put on a MudIcon, not on one of our own elements. */
.profile-field[b-mn8qknys6z]  .profile-field__icon {
    color: var(--mud-palette-text-secondary);
    margin-top: 2px;
}

.profile-field__text[b-mn8qknys6z] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.profile-field__label[b-mn8qknys6z] {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

/* break-word so a long email wraps inside the card instead of widening it. */
.profile-field__value[b-mn8qknys6z] {
    font-size: .95rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    overflow-wrap: anywhere;
}

/* --- read-only note -------------------------------------------------------------------------- */

.profile-note[b-mn8qknys6z] {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 16px;
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
}

    .profile-note[b-mn8qknys6z]  .mud-icon-root {
        font-size: 1rem;
        color: var(--mud-palette-text-secondary);
    }
/* /Components/Pages/Admin/SchoolConfiguration.razor.rz.scp.css */
/* School logo upload square - mirrors UserFormDialog.razor.css exactly (Blazor CSS isolation means
   that file's classes don't reach this page, so this is its own scoped copy, not a duplicate of
   logic that could otherwise be shared). */

.photo-upload-square[b-v353ofn2hd] {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 200px;
    height: 200px;
    border-radius: 12px;
    border: 1px dashed var(--mud-palette-lines-inputs, #c4c4c4);
    background-color: var(--mud-palette-background-grey, #f5f5f5);
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
}

.photo-upload-img[b-v353ofn2hd] {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.photo-upload-overlay[b-v353ofn2hd] {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    background-color: rgba(0, 0, 0, 0.55);
    color: #fff;
    opacity: 0;
    transition: opacity 0.15s ease-in-out;
    text-align: center;
    padding: 4px;
    pointer-events: none;
}

.photo-upload-square:hover .photo-upload-overlay[b-v353ofn2hd],
.photo-upload-square:focus .photo-upload-overlay[b-v353ofn2hd] {
    opacity: 1;
}

.photo-upload-overlay-text[b-v353ofn2hd] {
    font-size: 0.7rem;
    line-height: 1;
}

.photo-upload-square:focus-visible[b-v353ofn2hd] {
    outline: 2px solid var(--mud-palette-primary, #594ae2);
    outline-offset: 2px;
}
/* /Components/Pages/Attendance/AttendanceRecord.razor.rz.scp.css */
/* ===================================================================================
   ATTENDANCE RECORD - PER-CARD HIFD / MORAJAAH INDICATOR
   ===================================================================================
   The two rows sitting directly under a student's name on an "already recorded" card, listing the
   suras that student already has a Hifd / Morajaah ticket for on THIS session's date. Scoped to this
   page rather than added to wwwroot/app.css because it is a one-page idiom; the colours are taken
   from the theme palette (not literal hex) so the app-wide Hifd = Primary / Morajaah = Secondary
   pairing - the same one the dual progress ring's arcs and the ticket type chips use - keeps holding
   in both light and dark mode.
   =================================================================================== */
.mateen-day-records[b-g83ih2d0f3] {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    margin-top: .375rem;
}

/* Label and chips share one line and wrap as a block, with the label top-aligned so a student with
   many suras reads as "label + a paragraph of chips" instead of a vertically centred label floating
   beside them. */
.mateen-day-records__row[b-g83ih2d0f3] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: .25rem .375rem;
    min-height: 1.5rem;
    font-size: .8125rem;
    line-height: 1.5rem;
}

/* The label is the bold coloured part the educator scans for; min-width keeps "Hifd:" and
   "Morajaah:" starting their chips at the same x, so the two rows line up as a small table. */
.mateen-day-records__label[b-g83ih2d0f3] {
    font-weight: 700;
    min-width: 4.75rem;
    flex: 0 0 auto;
}

.mateen-day-records__label--hifd[b-g83ih2d0f3] {
    color: var(--mud-palette-primary);
}

.mateen-day-records__label--morajaah[b-g83ih2d0f3] {
    color: var(--mud-palette-secondary);
}

/* Dark mode: Secondary (#9333EA) on the #121A3F card is only 3.13:1, under AA for this small bold
   label. Lifted to #B565F7 (4.95:1) here, scoped to this label - the shared Secondary token is left
   alone. Still a more saturated purple than Hifd's #BB86EA, so the pair stays distinguishable. */
@container style(--mud-native-html-color-scheme: dark) {
    .mateen-day-records__label--morajaah[b-g83ih2d0f3] {
        color: #B565F7;
    }
}

/* "nothing registered yet" / "checking…" / "couldn't load" - deliberately muted and un-chip-like so
   it can never be mistaken for a registered record, while still occupying the row. */
.mateen-day-records__note[b-g83ih2d0f3] {
    color: var(--mud-palette-text-secondary);
    font-style: italic;
}

.mateen-day-records__note--empty[b-g83ih2d0f3] {
    color: var(--mud-palette-text-disabled);
}

/* The count itself: book icon, the number, and (only when there is something to list) the info icon
   whose tooltip carries the sura names that used to be a wrap of chips here. */
.mateen-day-records__count[b-g83ih2d0f3] {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
}

.mateen-day-records__number[b-g83ih2d0f3] {
    font-weight: 700;
    /* Tabular figures so a 1 and a 10 keep the info icon in the same place down a column of cards. */
    font-variant-numeric: tabular-nums;
}

/* A zero is "nothing registered yet" said in one character - muted to the same disabled tone the old
   "— nothing registered yet" note used, so it still reads as an absence rather than as data. */
.mateen-day-records__number--empty[b-g83ih2d0f3] {
    color: var(--mud-palette-text-disabled);
}

/* MudIcon renders its own element, which CSS isolation does not stamp with this page's scope
   attribute - hence ::deep (same reason the chips needed it before). Size.Small's 1.25rem is sized
   for a button, not for a .8125rem data row, so both icons are pulled down to the row's own scale
   and muted: neither is coloured per type, see the component's remarks. cursor:inherit keeps the
   card's own pointer, since clicking either icon still falls through to the card's navigation. */
.mateen-day-records__count[b-g83ih2d0f3]  .mud-icon-root {
    font-size: 1rem;
    color: var(--mud-palette-text-secondary);
    cursor: inherit;
}

/* One sura per line inside the tooltip. The tooltip surface is MudBlazor's own, so only the line
   rhythm is set here. */
.mateen-day-records__tooltip-line[b-g83ih2d0f3] {
    white-space: nowrap;
    line-height: 1.5;
}

/* ===================================================================================
   ALREADY RECORDED - GROUP HEADINGS AND THE CARD'S NAME + PHOTO ROW
   =================================================================================== */

/* The "Hifd/Morajaah done" / "… not yet done" subheadings. They are Typo.subtitle1 (one step under
   the section's own h6) and only the WEIGHT is set here, so they stay on MudBlazor's type scale
   instead of becoming a fourth heading size. ::deep because the weight has to land on MudText's own
   element, which CSS isolation does not stamp - the wrapper div exists purely to anchor that. */
.mateen-attendance-group-heading[b-g83ih2d0f3] {
    margin-bottom: .5rem;
    /* Theme surface, not a literal #fff: the plate was white in dark mode while MudText's text colour
       flipped to light, leaving pale text on white. LightCard is #FFFFFF so light mode is unchanged. */
    background-color: var(--mud-palette-surface);
    padding: 10px 12px;
    border-radius: 25px;
}

    .mateen-attendance-group-heading[b-g83ih2d0f3]  .mud-typography {
        font-weight: 700;
    }

/* A card's first row: name + today's recitation on the left, the student's photo hard against the
   card's right edge. flex-start, not center, so the photo sits level with the name rather than
   drifting down the middle of a card whose chip rows made it tall. */
.mateen-attendance-card__head[b-g83ih2d0f3] {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
}

    /* min-width:0 is what lets a long name ellipsise/wrap inside the flex item instead of pushing the
       photo past the card's padding. */
    .mateen-attendance-card__head-body[b-g83ih2d0f3] {
        flex: 1 1 auto;
        min-width: 0;
    }

/* Deliberately the same 40px plain circle (no ring, no shadow) as the dashboard's list rows
   (.mateen-dashboard-list-item__avatar in app.css) rather than PersonCard's 72px ringed avatar,
   which is sized for a centred card stack - this is a dense grid card, so the small treatment is the
   consistent one. The grey fill is the theme's, so the silhouette placeholder sits on a neutral
   backing in both modes. */
.mateen-attendance-card__avatar[b-g83ih2d0f3] {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    overflow: hidden;
    background-color: var(--mud-palette-background-gray);
}

    .mateen-attendance-card__avatar img[b-g83ih2d0f3] {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
/* /Components/Pages/Preferences/UserPreferences.razor.rz.scp.css */
/* Scoped to UserPreferences.razor (Blazor CSS isolation). Nothing here is reusable - it is the
   preview strip and the Save bar of one settings page - so it deliberately does not go anywhere
   global. app.css is also off limits for additions by convention in this repo.

   THE MUSHAF FONT IS NOT RE-DECLARED HERE, ON PURPOSE
   Arabic sura names get 'QPC Hafs V22' by carrying app.css's .mateen-ayah class (the single
   documented route by which a Mushaf family may reach the DOM - see the Mushaf block in app.css).
   The rules below therefore never mention a font FAMILY: they only override --mateen-ayah-size,
   because that block's 2rem default is sized for verse text and every Arabic name on this page is a
   short label sitting in a sentence-sized UI. Everything else .mateen-ayah brings along is either
   wanted (direction: rtl, the generous line-height's protection for stacked diacritics, the ligature
   settings) or inert on an inline element (its text-align/text-justify apply to block containers,
   and every element that carries the class here is a span). */

/* Sura names in the preview strip. Slightly larger than body text because the Uthmanic faces run
   visually smaller than Inter at the same px, so matching the size numerically would make the
   preview look smaller than what it is previewing. */
.preferences-preview[b-7hk3ki88a0] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
    margin-top: 4px;
}

.preferences-preview__item[b-7hk3ki88a0] {
    /* Read by .mateen-ayah's own font-size: var(--mateen-ayah-size) when the item is an Arabic name;
       simply unused when it is an English one, which keeps one rule for both languages. */
    --mateen-ayah-size: 1.25rem;
    font-size: 1rem;
    line-height: 1.8;
    font-weight: 600;
}

/* The Arabic word on the "Arabic" radio label - the option reads in the script it selects. Sized to
   the radio's own label text rather than to the preview, so the row keeps the height MudBlazor gives
   every other radio on the page. */
.preferences-option-sample[b-7hk3ki88a0] {
    --mateen-ayah-size: 1.15rem;
    margin-inline-start: 6px;
}

/* 10px gap between the tab strip and the panel body beneath it (explicit request) - MudTabs'
   TabPanelsClass hook, see that element's own comment for why this isn't an mt-* utility. */
.preferences-tab-panels[b-7hk3ki88a0] {
    margin-top: 10px;
}

/* ---- Default User Avatar tab's preview strip --------------------------------------------------
   A row of sample people, each rendered through the real UserAvatar component so the preview cannot
   drift from what the app will draw (the same principle as the sura preview above). */
.preferences-avatar-preview[b-7hk3ki88a0] {
    display: flex;
    flex-wrap: wrap;
    gap: 16px 24px;
    margin-top: 8px;
}

.preferences-avatar-preview__person[b-7hk3ki88a0] {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

/* The circular slot UserAvatar fills - the same plain 48px circle treatment as the app's list rows
   (.mateen-dashboard-list-item__avatar, app.css), restated locally because 40px is too small to
   judge a letter's legibility by and this is the one screen whose job is judging exactly that. */
.preferences-avatar-preview__avatar[b-7hk3ki88a0] {
    flex: 0 0 auto;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    overflow: hidden;
    background-color: var(--mud-palette-background-gray);
}

/* Sample names are Arabic as well as Latin, and an Arabic name set in the app's Latin face would
   fall through to whatever Arabic font the OS ships - so the label carries the app's own Tajawal
   text role (wwwroot/tajawal-typography.css); only its size is trimmed to this strip's scale. */
.preferences-avatar-preview__name.Tajawal-Text[b-7hk3ki88a0] {
    font-size: .9rem;
    white-space: nowrap;
}

/* Save bar: right-aligned under the tabs, the same gap the app's dialog action rows use, and it
   wraps rather than squeezing the buttons on a narrow phone. */
.preferences-actions[b-7hk3ki88a0] {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
}
/* /Components/Pages/Reports/LearningPlans.razor.rz.scp.css */
/* ===================================================================================
   Learning Plans overview (Components/Pages/Reports/LearningPlans.razor)

   Each plan card is reused verbatim from StudentPlansPanel.razor/app.css (.mateen-plan-card and
   friends, which stay global). This file adds the one genuinely new piece of markup the task calls
   for: a left-hand "owner" rail carrying the plan's student avatar and name, living INSIDE
   .mateen-plan-card__layout as a mirror of .mateen-plan-card__actions' right-hand action rail (same
   general technique: a flex child behind the card's own left accent bar, not a second box outside
   the card). Content classes mateen-owner-plan-row__avatar/__name are kept from the previous
   two-box layout - only their containing wrapper changed.
   =================================================================================== */

/* Spacing between cards - previously carried by the now-removed .mateen-owner-plan-row wrapper. */
.mateen-owner-plan-card[b-l9bof345ro] {
    margin-bottom: 20px;
}

.mateen-plan-card__owner[b-l9bof345ro] {
    flex: 0 0 96px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    cursor: pointer;
    /* Left padding clears the card's own 7px accent bar (.mateen-plan-card::before in app.css) now
       that this rail, not .mateen-plan-card__body, is .mateen-plan-card__layout's first child - see
       the matching .mateen-plan-card__body override below. Right padding plus the hairline mirrors
       .mateen-plan-card__actions on the opposite edge. */
    padding: 12px 10px 12px 20px;
    border-inline-end: 1px solid var(--mud-palette-lines-default);
    transition: background-color .15s ease;
}

.mateen-plan-card__owner:hover[b-l9bof345ro] {
    background-color: light-dark(color-mix(in srgb, var(--mud-palette-text-primary) 5%, transparent), color-mix(in srgb, #FFFFFF 8%, transparent));
}

/* Now a CONTAINER, not an <img> rule: the plan's owner avatar is the shared UserAvatar component
   (real photo, or whatever the viewer's Preferences > Default User Avatar picked - silhouette or
   initials plate), which renders its own <img>/initials span at 100%/100% of whatever box it is
   given, the same drop-in contract every other avatar slot in this app follows
   (.mateen-person-card__avatar, .mateen-dashboard-list-item__avatar). overflow:hidden is what clips
   either an image or an initials plate to this circle. */
.mateen-owner-plan-row__avatar[b-l9bof345ro] {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid var(--mud-palette-lines-default);
}

.mateen-owner-plan-row__name[b-l9bof345ro] {
    font-weight: 600;
    font-size: .8125rem;
    line-height: 1.3;
    /* Clamped rather than truncated to one line - a two-word name has room to wrap in this narrow
       rail instead of ellipsizing on a column only ~96px wide. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}

/* .mateen-plan-card__body no longer leads .mateen-plan-card__layout (the owner rail above does, and
   now carries its own accent-bar-clearing padding), so its left padding reverts to the card's plain
   default (16px, same as .mud-card-content-padding) instead of app.css's shared +7px rule, which is
   still correct for StudentPlansPanel's own cards where __body IS the first/only child. Scoped to
   this component only - app.css's global rule is untouched. */
.mateen-plan-card__body[b-l9bof345ro] {
    padding-left: 16px !important;
}

@media (max-width: 599.98px) {
    .mateen-plan-card__owner[b-l9bof345ro] {
        flex: 0 0 72px;
        padding: 10px 6px 10px 16px;
    }

    .mateen-owner-plan-row__avatar[b-l9bof345ro] {
        width: 44px;
        height: 44px;
    }

    .mateen-owner-plan-row__name[b-l9bof345ro] {
        -webkit-line-clamp: 1;
    }
}
/* /Components/Pages/Suggestions/Feedback.razor.rz.scp.css */
/* Scoped to Feedback.razor only (Blazor CSS isolation) rather than added to app.css, since nothing
   else in the app shows a suggestion card. Every selector here is on an element this page renders
   itself - see the razor's comments on why the text classes sit on wrapping divs rather than on the
   MudText components. */

/* Title on the left, status chip on the right, top-aligned so a title that wraps to two lines does
   not drag the chip down with it. overflow-wrap is inherited by the MudText inside, which is what
   stops a single long unbroken word from pushing the chip off the card. */
.suggestion-head[b-xi9bc79nzd] {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
    overflow-wrap: anywhere;
}

/* pre-wrap is what preserves the line breaks a user typed into their 500-character message (and a
   replier typed into their answer) WITHOUT converting them to <br /> - see the razor's comment: this
   is user-authored text and no HTML may ever be built from it. Inherited, so it reaches the <p> that
   MudText renders inside this wrapper. */
.suggestion-text[b-xi9bc79nzd] {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* Attachment thumbnails, wrapping so a suggestion with several screenshots stays inside the card. */
.suggestion-thumbs[b-xi9bc79nzd] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.suggestion-thumb[b-xi9bc79nzd] {
    display: block;
    width: 84px;
    height: 84px;
    border-radius: 8px;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-background-grey);
    overflow: hidden;
    transition: border-color .15s ease;
}

    .suggestion-thumb:hover[b-xi9bc79nzd] {
        border-color: var(--mud-palette-primary);
    }

    /* contain rather than cover: these are usually screenshots, where cropping to fill the square
       would hide the very thing the user attached. */
    .suggestion-thumb img[b-xi9bc79nzd] {
        width: 100%;
        height: 100%;
        object-fit: contain;
    }

/* THE REPLY. This is the answer the user opened the page for, so it is deliberately not styled like
   another paragraph of their own text: a tinted inset panel behind a 3px primary left rule, which is
   the cheapest treatment that reads unmistakably as "someone else is speaking". color-mix off the
   palette primary rather than a literal tint, so it follows the app's own dark/light mode and any
   future palette change exactly as the landing page's ornament does. */
.suggestion-reply[b-xi9bc79nzd] {
    border-left: 3px solid var(--mud-palette-primary);
    border-radius: 0 8px 8px 0;
    padding: 10px 14px;
    background-color: color-mix(in srgb, var(--mud-palette-primary) 7%, transparent);
}

/* The icon and the "Reply from Mateen" label on one line above the answer itself. */
.suggestion-reply-head[b-xi9bc79nzd] {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 4px;
}
/* /Components/Pages/Teacher/Students.razor.rz.scp.css */
/* ===================================================================================
   STUDENTS PAGE - GROUP SECTION SEPARATOR
   ===================================================================================
   The page reuses the generic .mateen-section-separator from wwwroot/app.css for its group heading,
   so this file only carries the one difference that is specific to THIS page: the label is dialled
   down a step (1rem, slightly relaxed letter-spacing) because the cards underneath it are the actual
   content and the group name is only a signpost to them. The count bubble and the fading rule are
   deliberately left exactly as the shared block defines them, so this page and GroupDetail.razor
   still read as the same idiom.

   Historical note, because the reason for the smaller label has changed: this separator used to
   repeat once per group down a single long page, and at its full 1.125rem/600 a stack of repeated
   labels competed with the cards. Since the page became server-paged it shows one group at a time
   and the separator appears once, so that specific argument is gone - but the quieter label is kept
   on purpose. GroupDetail.razor's separator introduces the page's subject; this one only names which
   bucket of students the grid below is currently paging through, which is a smaller claim and should
   look like one.
   =================================================================================== */
.mateen-section-separator--group .mateen-section-separator__label[b-542msj885v] {
    font-size: 1rem;
    letter-spacing: .01em;
}
/* /Components/Shared/NextSessionTasksPanel.razor.rz.scp.css */
/* Scoped to NextSessionTasksPanel. Visual language matches TicketsPanel's record cards (14px radius,
   soft shadow + 2px lift on hover, bottom accent bar Hifd = primary / Morajaah = secondary, surah pill
   as a plain span). Everything colour-related goes through --mud-palette-* / light-dark() / color-mix,
   nothing is a literal hex, so both themes resolve through the same rules. */

.nst-card[b-wcjzsr3hng] {
    /* The mode signal every light-dark() below resolves against. */
    color-scheme: var(--mud-native-html-color-scheme);
    --nst-accent: var(--mud-palette-primary);
    --nst-shadow: light-dark(rgba(42, 39, 64, .10), rgba(0, 0, 0, .45));
    --nst-shadow-hover: light-dark(rgba(42, 39, 64, .18), rgba(0, 0, 0, .60));
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    height: 100%;
    box-sizing: border-box;
    padding: 8px 10px 11px;
    overflow: hidden;
    border-radius: 14px;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    box-shadow: 0 6px 18px var(--nst-shadow);
    transition: box-shadow 200ms cubic-bezier(.4, 0, .2, 1), border-color 200ms cubic-bezier(.4, 0, .2, 1), transform 200ms cubic-bezier(.4, 0, .2, 1);
}

.nst-card--morajaah[b-wcjzsr3hng] {
    --nst-accent: var(--mud-palette-secondary);
}

.nst-card[b-wcjzsr3hng]::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 5px;
    background-color: var(--nst-accent);
    pointer-events: none;
}

.nst-card--clickable:hover[b-wcjzsr3hng] {
    border-color: color-mix(in srgb, var(--nst-accent) 45%, transparent);
    box-shadow: 0 10px 24px var(--nst-shadow-hover);
    transform: translateY(-2px);
}

/* Stretched edit target (Pending + CanManage only), under the round buttons (z-index 2). */
.nst-card__open[b-wcjzsr3hng] {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: inherit;
    background: transparent;
    cursor: pointer;
}

    .nst-card__open:focus-visible[b-wcjzsr3hng] {
        outline: 3px solid var(--nst-accent);
        outline-offset: -3px;
    }

.nst-card__head[b-wcjzsr3hng] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    margin-bottom: 10px;
}

.nst-card__id[b-wcjzsr3hng] {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    min-width: 0;
}

.nst-card__side[b-wcjzsr3hng] {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
}

/* Icon + pill on one row; the icon never shrinks, the pill ellipsises beside it. */
.nst-card__sura-row[b-wcjzsr3hng] {
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 100%;
    min-width: 0;
}

    .nst-card__sura-row[b-wcjzsr3hng]  .mateen-sura-icon {
        --sura-icon-size: 32px;
    }

/* Plain span, not a MudChip - same pill as TicketsPanel's .mateen-ticket-card__sura. */
.nst-card__sura[b-wcjzsr3hng] {
    box-sizing: border-box;
    min-width: 0;
    max-width: 100%;
    padding: 5px 10px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    unicode-bidi: isolate;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--nst-accent) 35%, transparent);
    background-color: color-mix(in srgb, var(--nst-accent) 14%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--nst-accent) 45%, var(--mud-palette-text-primary));
    font-size: .8125rem;
    line-height: 1.45;
    font-weight: 700;
}

.nst-card__range[b-wcjzsr3hng] {
    font-size: .8125rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

    .nst-card__range b[b-wcjzsr3hng] {
        color: var(--mud-palette-text-primary);
        font-weight: 700;
    }

.nst-card__type[b-wcjzsr3hng] {
    font-size: .75rem;
    font-weight: 700;
    line-height: 1.2;
    color: color-mix(in srgb, var(--nst-accent) 45%, var(--mud-palette-text-primary));
}

/* Status badge: plain span, tinted by status with the text mixed toward the primary text colour so it
   stays legible on its own tint in both modes. */
.nst-badge[b-wcjzsr3hng] {
    --nst-badge: var(--mud-palette-warning);
    display: inline-block;
    padding: 2px 9px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--nst-badge) 45%, transparent);
    background-color: color-mix(in srgb, var(--nst-badge) 16%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--nst-badge) 40%, var(--mud-palette-text-primary));
    font-size: .75rem;
    line-height: 1.4;
    font-weight: 700;
}

.nst-badge--approved[b-wcjzsr3hng] {
    --nst-badge: var(--mud-palette-success);
}

.nst-badge--rejected[b-wcjzsr3hng] {
    --nst-badge: var(--mud-palette-error);
}

.nst-card__divider[b-wcjzsr3hng] {
    width: 100%;
    height: 0;
    margin: auto 0 0;
    padding: 0;
    border: 0;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.nst-card__footer[b-wcjzsr3hng] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 28px;
    margin-top: 6px;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

.nst-card__meta[b-wcjzsr3hng] {
    white-space: normal;
    line-height: 1.25;
    min-width: 0;
    overflow-wrap: anywhere;
}

.nst-card__ticket[b-wcjzsr3hng] {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    color: color-mix(in srgb, var(--mud-palette-success) 55%, var(--mud-palette-text-primary));
    font-weight: 600;
}

.nst-card__ticket[b-wcjzsr3hng]  .nst-card__meta-icon {
    font-size: .95rem;
}

.nst-card__actions[b-wcjzsr3hng] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
}

/* Small round buttons above the stretched edit target. 28px is the tap-target floor. */
.nst-card__actions[b-wcjzsr3hng]  .nst-card__action {
    position: relative;
    z-index: 2;
    width: 28px;
    height: 28px;
    margin-block: -2px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 6%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
}

    .nst-card__actions[b-wcjzsr3hng]  .nst-card__action .mud-icon-root {
        font-size: 1rem;
    }

    .nst-card__actions[b-wcjzsr3hng]  .nst-card__action--approve {
        color: color-mix(in srgb, var(--mud-palette-success) 55%, var(--mud-palette-text-primary));
    }

        .nst-card__actions[b-wcjzsr3hng]  .nst-card__action--approve:hover {
            background-color: color-mix(in srgb, var(--mud-palette-success) 16%, var(--mud-palette-surface));
        }

    .nst-card__actions[b-wcjzsr3hng]  .nst-card__action--danger {
        color: color-mix(in srgb, var(--mud-palette-error) 55%, var(--mud-palette-text-primary));
    }

        .nst-card__actions[b-wcjzsr3hng]  .nst-card__action--danger:hover {
            background-color: color-mix(in srgb, var(--mud-palette-error) 16%, var(--mud-palette-surface));
        }

.nst-grid--loading[b-wcjzsr3hng] {
    opacity: .6;
    transition: opacity 150ms;
}

@media (prefers-reduced-motion: reduce) {
    .nst-card[b-wcjzsr3hng],
    .nst-card--clickable:hover[b-wcjzsr3hng] {
        transition: none;
        transform: none;
    }
}

.nst-filter[b-wcjzsr3hng] {
    flex: 0 1 220px;
    min-width: 160px;
}
/* /Components/Shared/PageLoadingOverlay.razor.rz.scp.css */
/* Scoped to this component, so none of it can collide with app.css's shared rules. MudOverlay
   already centres its ChildContent in the viewport (.mud-overlay is a fixed, full-screen flex box
   with align-items/justify-content: center), so this only has to shape the panel inside it. */

/* A real surface rather than bare content on the scrim: --mud-palette-overlay-dark is a dark wash
   over a LIGHT page in light mode and over a dark page in dark mode, so anything drawn straight onto
   it has a different backdrop per mode and no single colour reads well on both. Sitting the spinner
   and its label on the theme's own surface/text variables makes both modes correct by construction -
   white card + #471671 spinner in light, #121A3F card + #BB86EA spinner in dark (MateenTheme) - and
   dark mode here follows the app's mateen-theme choice, not the OS prefers-color-scheme flag. */
.mateen-page-loader[b-x4ha44xfat] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 1.75rem 2.25rem;
    border-radius: var(--mud-default-borderradius, 8px);
    background-color: var(--mud-palette-surface);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
}

.mateen-page-loader__label[b-x4ha44xfat] {
    color: var(--mud-palette-text-primary);
    font-size: 0.875rem;
    font-weight: 500;
    letter-spacing: 0.02em;
}
/* /Components/Shared/RoleShowcase.razor.rz.scp.css */
.role-showcase[b-2m1cm2otyx] {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px;
    max-width: 1120px; margin: 0 auto; align-items: start;
}

.role-card[b-2m1cm2otyx] { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

.role-chip[b-2m1cm2otyx] {
    align-self: flex-start; padding: 4px 14px; border-radius: 999px;
    font-size: .78rem; font-weight: 600; letter-spacing: .04em;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 35%, transparent);
}

.role-frame[b-2m1cm2otyx] {
    overflow: hidden;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mateen-landing-line);
    border-radius: 14px;
    box-shadow: 0 18px 44px -18px var(--mateen-landing-shadow-color);
    transition: transform .25s ease, box-shadow .25s ease;
}
.role-card:hover .role-frame[b-2m1cm2otyx] { transform: translateY(-4px); box-shadow: 0 26px 56px -18px var(--mateen-landing-shadow-color); }

.role-chrome[b-2m1cm2otyx] {
    display: flex; align-items: center; gap: 6px; padding: 9px 14px;
    background: var(--mateen-landing-card-2);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    direction: ltr;
}
.role-chrome span[b-2m1cm2otyx] { width: 9px; height: 9px; border-radius: 50%; background: var(--mateen-landing-line); }
.role-chrome em[b-2m1cm2otyx] { margin-inline-start: 12px; font-style: normal; font-size: .7rem; letter-spacing: .08em; color: var(--mud-palette-text-secondary); }

.role-frame img[b-2m1cm2otyx] { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; object-position: top left; }

.role-card h3[b-2m1cm2otyx] { margin: 0; font-size: 1.15rem; font-weight: 600; color: var(--mud-palette-text-primary); }

.role-card ul[b-2m1cm2otyx] { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.role-card li[b-2m1cm2otyx] {
    position: relative; padding-inline-start: 22px;
    font-size: .92rem; line-height: 1.55; color: var(--mud-palette-text-secondary);
}
.role-card li[b-2m1cm2otyx]::before {
    content: ""; position: absolute; inset-inline-start: 2px; top: .55em;
    width: 8px; height: 8px; border-radius: 50%; background: var(--mud-palette-primary);
}

@media (max-width: 860px) {
    .role-showcase[b-2m1cm2otyx] { grid-template-columns: 1fr; gap: 40px; }
}

@media (prefers-reduced-motion: reduce) {
    .role-frame[b-2m1cm2otyx] { transition: none; }
    .role-card:hover .role-frame[b-2m1cm2otyx] { transform: none; }
}

/* ---- enlarge on hover / focus (touch: tap) ------------------------------------------------- */
.role-frame[b-2m1cm2otyx] { cursor: zoom-in; }
.role-frame:focus-visible[b-2m1cm2otyx] { outline: 2px solid var(--mud-palette-primary); outline-offset: 3px; }

/* Fixed + centred: no layout shift. Sibling of .role-frame (not a child) so the frame's own hover
   transform cannot become its containing block. Width also capped so height always fits the viewport. */
.role-zoom[b-2m1cm2otyx] {
    position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center;
    pointer-events: none; opacity: 0; visibility: hidden;
    transition: opacity .25s ease, visibility .25s;
}
.role-zoom-frame[b-2m1cm2otyx] {
    width: min(90vw, 1440px, calc((100vh - 120px) * 1.6));
    overflow: hidden; background: var(--mud-palette-surface);
    border: 1px solid var(--mateen-landing-line); border-radius: 14px;
    box-shadow: 0 40px 100px -20px rgba(0, 0, 0, .55);
    transform: scale(.94); transition: transform .25s ease;
}
.role-zoom-frame img[b-2m1cm2otyx] { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; object-position: top left; }

.role-frame:hover ~ .role-zoom[b-2m1cm2otyx],
.role-frame:focus-visible ~ .role-zoom[b-2m1cm2otyx] { opacity: 1; visibility: visible; }
.role-frame:hover ~ .role-zoom .role-zoom-frame[b-2m1cm2otyx],
.role-frame:focus-visible ~ .role-zoom .role-zoom-frame[b-2m1cm2otyx] { transform: none; }
.role-card.is-dismissed .role-zoom[b-2m1cm2otyx] { opacity: 0; visibility: hidden; }

.role-zoom-close[b-2m1cm2otyx] { display: none; }

/* Touch / small screens: tap toggles. Dimmed, tappable backdrop closes; close button always visible. */
@media (hover: none), (max-width: 860px) {
    .role-frame:hover ~ .role-zoom[b-2m1cm2otyx] { opacity: 0; visibility: hidden; }
    .role-card.is-zoomed .role-zoom[b-2m1cm2otyx],
    .role-card.is-zoomed .role-frame:hover ~ .role-zoom[b-2m1cm2otyx] {
        opacity: 1; visibility: visible; pointer-events: auto;
        background: color-mix(in srgb, #000 62%, transparent);
    }
    .role-card.is-zoomed .role-zoom-frame[b-2m1cm2otyx] { transform: none; width: min(94vw, calc((100vh - 120px) * 1.6)); }
    .role-card.is-zoomed .role-zoom-close[b-2m1cm2otyx] {
        display: grid; place-items: center; position: fixed; z-index: 1001;
        inset-block-start: 12px; inset-inline-end: 12px; width: 44px; height: 44px; padding: 0; cursor: pointer;
        color: var(--mud-palette-text-primary); background: var(--mud-palette-surface);
        border: 1px solid var(--mateen-landing-line); border-radius: 50%;
    }
    .role-zoom-close:focus-visible[b-2m1cm2otyx] { outline: 2px solid var(--mud-palette-primary); outline-offset: 2px; }
}

@media (prefers-reduced-motion: reduce) {
    .role-zoom[b-2m1cm2otyx], .role-zoom-frame[b-2m1cm2otyx] { transition: none; }
    .role-zoom-frame[b-2m1cm2otyx] { transform: none; }
}
/* /Components/Shared/ScreenshotShowcase.razor.rz.scp.css */
.shot-showcase[b-w3zhgzttcl] {
    max-width: 1120px; margin: 0 auto;
    --dir: 1;
}
.shot-showcase:dir(rtl)[b-w3zhgzttcl] { --dir: -1; }
[dir="rtl"] .shot-showcase[b-w3zhgzttcl] { --dir: -1; }

.shot-carousel[b-w3zhgzttcl] { position: relative; outline: none; border-radius: 16px; }
.shot-carousel:focus-visible[b-w3zhgzttcl] { outline: 2px solid var(--mud-palette-primary); outline-offset: 4px; }

/* Fixed-height stage: no layout shift whichever slide is active. */
.shot-stage[b-w3zhgzttcl] {
    position: relative; overflow: hidden; contain: layout paint;
    aspect-ratio: 2.2 / 1;
    touch-action: pan-y; user-select: none; -webkit-user-select: none;
}

.shot-slide[b-w3zhgzttcl] {
    --w: 58%; --x: 0%; --s: 1; --blur: 0px; --dim: 1; --op: 1; --z: 10;
    position: absolute; top: 50%; inset-inline-start: calc(50% - var(--w) / 2);
    width: var(--w);
    transform: translateY(-50%) translateX(calc(var(--dir) * var(--o) * var(--x))) scale(var(--s));
    opacity: var(--op);
    filter: blur(var(--blur)) brightness(var(--dim));
    z-index: var(--z);
    transition: transform .5s ease, opacity .5s ease, filter .5s ease, visibility .5s;
}
/* inset-inline-start is mirrored in RTL, so centring stays correct; only translateX uses --dir. */
.shot-slide.pos-0[b-w3zhgzttcl] { --s: 1.04; --z: 10; }
.shot-slide.pos-1[b-w3zhgzttcl] { --x: 36%; --s: .84; --blur: 1.5px; --dim: .82; --op: .92; --z: 8; }
.shot-slide.pos-2[b-w3zhgzttcl] { --x: 29%; --s: .7;  --blur: 3px;   --dim: .68; --op: .7;  --z: 6; }
.shot-slide.pos-3[b-w3zhgzttcl] { --x: 29%; --s: .6;  --blur: 4px;   --dim: .6;  --op: 0;   --z: 1; visibility: hidden; pointer-events: none; }

.shot-frame[b-w3zhgzttcl] {
    position: relative; overflow: hidden;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mateen-landing-line);
    border-radius: 14px;
    box-shadow: 0 10px 24px -12px var(--mateen-landing-shadow-color);
    transition: box-shadow .5s ease;
}
.shot-slide.is-active .shot-frame[b-w3zhgzttcl] { box-shadow: 0 34px 70px -18px var(--mateen-landing-shadow-color), 0 8px 20px -10px var(--mateen-landing-shadow-color); }

.shot-chrome[b-w3zhgzttcl] {
    display: flex; align-items: center; gap: 6px; padding: 9px 14px;
    background: var(--mateen-landing-card-2);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    direction: ltr;
}
.shot-chrome span[b-w3zhgzttcl] { width: 9px; height: 9px; border-radius: 50%; background: var(--mateen-landing-line); }
.shot-chrome em[b-w3zhgzttcl] { margin-inline-start: 12px; font-style: normal; font-size: .7rem; letter-spacing: .08em; color: var(--mud-palette-text-secondary); }

.shot-frame img[b-w3zhgzttcl] { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; object-position: top left; pointer-events: none; }

.shot-badge[b-w3zhgzttcl] {
    position: absolute; inset-block-end: 10px; inset-inline-end: 10px;
    padding: 3px 10px; font-size: .7rem; border-radius: 999px;
    color: var(--mud-palette-text-secondary);
    background: color-mix(in srgb, var(--mud-palette-surface) 88%, transparent);
    border: 1px solid var(--mateen-landing-line);
}

/* Click target over inactive slides. */
.shot-hit[b-w3zhgzttcl] {
    position: absolute; inset: 0; z-index: 2; padding: 0; border: 0; background: transparent;
    border-radius: 14px; cursor: pointer;
}
.shot-hit:focus-visible[b-w3zhgzttcl] { outline: 3px solid var(--mud-palette-primary); outline-offset: 3px; }
.shot-slide.pos-1:hover[b-w3zhgzttcl] { --dim: .95; --blur: 0px; }

.shot-arrow[b-w3zhgzttcl] {
    position: absolute; top: 50%; z-index: 20; transform: translateY(-50%);
    display: grid; place-items: center; width: 44px; height: 44px; padding: 0; cursor: pointer;
    color: var(--mud-palette-text-primary);
    background: color-mix(in srgb, var(--mud-palette-surface) 90%, transparent);
    border: 1px solid var(--mateen-landing-line); border-radius: 50%;
    box-shadow: 0 6px 18px -8px var(--mateen-landing-shadow-color);
    transition: border-color .2s ease, color .2s ease, transform .2s ease;
}
.shot-arrow:hover[b-w3zhgzttcl] { color: var(--mud-palette-primary); border-color: var(--mud-palette-primary); transform: translateY(-50%) scale(1.06); }
.shot-arrow:focus-visible[b-w3zhgzttcl] { outline: 2px solid var(--mud-palette-primary); outline-offset: 2px; }
.shot-prev[b-w3zhgzttcl] { inset-inline-start: 4px; }
.shot-next[b-w3zhgzttcl] { inset-inline-end: 4px; }
.shot-showcase:dir(rtl) .shot-arrow svg[b-w3zhgzttcl] { transform: scaleX(-1); }
[dir="rtl"] .shot-showcase .shot-arrow svg[b-w3zhgzttcl] { transform: scaleX(-1); }

.shot-caption[b-w3zhgzttcl] {
    margin: 18px auto 0; min-height: 3.2em; max-width: 640px; text-align: center;
    font-size: .92rem; line-height: 1.6; color: var(--mud-palette-text-secondary);
}
.shot-caption strong[b-w3zhgzttcl] { color: var(--mud-palette-text-primary); font-weight: 600; }

.shot-dots[b-w3zhgzttcl] { display: flex; justify-content: center; gap: 4px; margin-top: 6px; }
.shot-dot[b-w3zhgzttcl] {
    position: relative; width: 24px; height: 24px; padding: 0; border: 0; background: transparent; cursor: pointer; border-radius: 50%;
}
.shot-dot[b-w3zhgzttcl]::after {
    content: ""; position: absolute; inset: 8px; border-radius: 999px;
    background: var(--mateen-landing-line); transition: background .3s ease, inset .3s ease;
}
.shot-dot:hover[b-w3zhgzttcl]::after { background: var(--mud-palette-text-secondary); }
.shot-dot.is-active[b-w3zhgzttcl]::after { background: var(--mud-palette-primary); inset: 7px 3px; }
.shot-dot:focus-visible[b-w3zhgzttcl] { outline: 2px solid var(--mud-palette-primary); outline-offset: 1px; }

@media (max-width: 860px) {
    .shot-stage[b-w3zhgzttcl] { aspect-ratio: 1.7 / 1; }
    .shot-slide[b-w3zhgzttcl] { --w: 72%; }
    .shot-slide.pos-1[b-w3zhgzttcl] { --x: 40%; --s: .86; --blur: 1px; }
    .shot-slide.pos-2[b-w3zhgzttcl], .shot-slide.pos-3[b-w3zhgzttcl] { --x: 40%; --op: 0; visibility: hidden; pointer-events: none; }
    .shot-arrow[b-w3zhgzttcl] { width: 38px; height: 38px; }
    .shot-chrome[b-w3zhgzttcl] { padding: 6px 10px; }
}

@media (prefers-reduced-motion: reduce) {
    .shot-slide[b-w3zhgzttcl], .shot-frame[b-w3zhgzttcl], .shot-arrow[b-w3zhgzttcl], .shot-dot[b-w3zhgzttcl]::after { transition: none; }
}
/* /Components/Shared/StudentSummaryCard.razor.rz.scp.css */
/* Scoped to StudentSummaryCard (Blazor CSS isolation). Only the student GRID card's Hifd ring's
   decile-band colour lives here - everything else about .mateen-dual-ring is shared, unscoped CSS
   in app.css, and the grid/detail markup itself lives in the .razor file next to this one.

   WHY SCOPED AND NOT app.css
   Mirrors Components/Shared/StudentSuraProgressPanel.razor.css's own reasoning for the Progress
   tab's per-Sura rings, copied here rather than reinvented: DualProgressRing is ALSO this very
   component's detail (horizontal) card's headline Aside dial, which the user has never asked to be
   banded and which must stay the plain brand palette. A global rule on
   .mateen-dual-ring__arc--outer would repaint that dial too. CSS isolation stamps its scope
   attribute onto .mateen-student-summary-card__ring (written directly in this component's markup,
   in the GRID branch only), and ::deep hangs off that to reach the arc inside the child
   DualProgressRing's own rendered markup - so the override is confined to this one ring by
   construction, not by naming discipline, and outranks app.css on specificity without needing
   !important (an attribute plus two classes against app.css's plain class rule, and this scoped
   bundle links after app.css in App.razor). */

/* Only the OUTER arc: single-ring mode never renders an inner arc/track at all (ShowInnerRing
   ="false"), so there is nothing else here to band - unlike the Sura panel's dial, this one has no
   legend dot to repaint either, since single-ring mode drops the whole legend block. */
.mateen-student-summary-card__ring[b-slumvotw2f]  .mateen-dual-ring__arc--outer {
    stroke: var(--mateen-progress-band, var(--mud-palette-primary));
}

/* The track behind the arc follows the same band, tinted the same 16%-into-surface way the Sura
   panel's own track override is, so a card at 15% does not read as an orange sliver dropped onto an
   unrelated violet ring. */
.mateen-student-summary-card__ring[b-slumvotw2f]  .mateen-dual-ring__track--outer {
    stroke: color-mix(in srgb, var(--mateen-progress-band, var(--mud-palette-primary)) 16%, var(--mud-palette-surface));
}

/* The ring's own wrapper becomes a small column (dial, then its figures row) instead of holding
   just the dial, so the figures row below can spread edge to edge under it. */
.mateen-student-summary-card__ring[b-slumvotw2f] {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}

/* Pushes the sura figure to the ring's bottom-left and the ayah figure to its bottom-right - see
   the markup's own comment for why these exist and where their numbers come from.
   .mateen-student-progress__bar-note (app.css) still supplies the figure/unit colour+weight split
   and the tabular numerals; this only adds the row layout spreading its two spans to the row's ends. */
.mateen-student-summary-card__ring-figures[b-slumvotw2f] {
    display: flex;
    justify-content: space-between;
    width: 100%;
    margin-top: 2px;
}

/* No plan yet: one dash, not two blank corners - space-between would otherwise pin a single child to
   the row's start rather than its centre. */
.mateen-student-summary-card__ring-figures--empty[b-slumvotw2f] {
    justify-content: center;
}
/* /Components/Shared/StudentSuraProgressPanel.razor.rz.scp.css */
/* Scoped to StudentSuraProgressPanel (Blazor CSS isolation). Everything the Progress tab's cards
   share with the rest of the app - the grid, the card body, the metric rows, the compact ring -
   still lives in app.css; only what is specific to these cards being CLICKABLE and to their ring
   carrying a per-percentage colour is here.

   WHY SCOPED AND NOT app.css
   The arc colour must not leak. DualProgressRing is also the student summary card's headline dial,
   where it has to stay in the brand palette - a global rule on .mateen-dual-ring__arc--outer would
   repaint that one too. CSS isolation stamps its scope attribute onto the elements this component
   declares (.mateen-sura-card-shell below), and ::deep hangs off that to reach the arc inside the
   child component's own markup, so the override is confined to this panel by construction rather
   than by naming discipline. It also outranks app.css on specificity (an attribute plus two
   classes against one), and the scoped bundle is linked after app.css in App.razor, so nothing
   here depends on !important. */

/* The wrapper is the grid item now, so it has to do what .mateen-sura-card used to do on its own:
   fill the cell top to bottom, with the card stretched inside it, or cards in a row stop matching
   heights the moment one Sura name wraps. */
.mateen-sura-card-shell[b-dselv853xt] {
    display: flex;
    height: 100%;
    border-radius: var(--mud-default-borderradius);
    transition: box-shadow 200ms cubic-bezier(.4, 0, .2, 1), transform 200ms cubic-bezier(.4, 0, .2, 1);
    cursor: pointer;
}

    .mateen-sura-card-shell[b-dselv853xt]  .mateen-sura-card {
        flex: 1 1 auto;
        /* Without this the card shrink-wraps its content inside the stretched shell. */
        width: 100%;
    }

/* Hover affordance in the same language as the app's other clickable cards
   (.mateen-person-card--clickable, .mateen-group-card--clickable): a small lift plus a deeper
   shadow, no colour change, so the accent bar and the ring stay the only coloured things on the
   card. The shadow lands on the shell rather than the card because the shell is what is being
   raised - the card's own MudBlazor elevation stays untouched. */
.mateen-sura-card-shell:hover[b-dselv853xt] {
    transform: translateY(-2px);
    /* The mode signal light-dark() below resolves against, declared here rather than assumed:
       MudBlazor 9.10.0 puts --mud-native-html-color-scheme on :root but only feeds it into the real
       `color-scheme` property on .mud-input, so anything outside an input silently sees
       color-scheme:normal and light-dark() always returns its LIGHT value. Without this line the
       dark shadow below never applied. Same guard app.css's .mateen-landing / .mateen-login /
       .mateen-person-card blocks each carry, and the drawer's warning icon too. */
    color-scheme: var(--mud-native-html-color-scheme);
    box-shadow: 0 10px 26px light-dark(rgba(42, 39, 64, .16), rgba(0, 0, 0, .5));
}

/* Keyboard users get the same discoverability as the pointer, plus a real focus ring - the shell
   is role="button" tabindex="0", so it is reachable by Tab and must say where focus is. */
.mateen-sura-card-shell:focus-visible[b-dselv853xt] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 3px;
    transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
    .mateen-sura-card-shell[b-dselv853xt],
    .mateen-sura-card-shell:hover[b-dselv853xt],
    .mateen-sura-card-shell:focus-visible[b-dselv853xt] {
        transition: none;
        transform: none;
    }
}

/* The completion colour from Design/progress.jpg, by way of Models/Plans/ProgressBands - the one
   shared scale, so these rings and the Hifd completion bars in app.css can never drift apart. The
   value is an inline custom property on the shell (set per card by ProgressBands.StyleFor in the
   .razor, which also omits it at a flat 0%), so one rule serves every band; the fallback is
   the palette primary the ring has everywhere else, which is what would show if the property ever
   went missing. Only the OUTER arc is repainted: it is the Hifd series, and Hifd is the completion
   metric the bands actually describe. The inner Morajaah arc keeps the brand secondary on purpose -
   Morajaah never counts toward completion in this app, so putting it on the same red-to-blue scale
   would claim a meaning it does not have, and two independently-coloured concentric arcs stop
   reading as one dial. */
.mateen-sura-card-shell[b-dselv853xt]  .mateen-dual-ring__arc--outer {
    stroke: var(--mateen-progress-band, var(--mud-palette-primary));
}

/* The legend dot below the dial has to follow its own arc, or the card ends up with a violet "Hifd"
   dot next to an orange arc and the legend stops explaining anything. */
.mateen-sura-card-shell[b-dselv853xt]  .mateen-dual-ring__dot--outer {
    background-color: var(--mateen-progress-band, var(--mud-palette-primary));
}

/* The track behind the arc is tinted from the same colour, so a card at 15% does not read as an
   orange sliver dropped onto an unrelated violet ring. Kept very light - it is a track, not a
   second figure. */
.mateen-sura-card-shell[b-dselv853xt]  .mateen-dual-ring__track--outer {
    stroke: color-mix(in srgb, var(--mateen-progress-band, var(--mud-palette-primary)) 16%, var(--mud-palette-surface));
}

/* ===================================================================================
   ARABIC SURA NAMES (per-user preference)
   -----------------------------------------------------------------------------------
   When the user has chosen Arabic sura names, the name elements in this component carry app.css's
   .mateen-ayah class, which is the ONLY sanctioned route by which a Mushaf family ('QPC Hafs V22',
   with V18 and a generic Arabic serif behind it) may reach the DOM - see the Mushaf block in
   app.css. Nothing below therefore names a font family: these rules override only
   --mateen-ayah-size, because that block's 2rem default is sized for a verse and every name here is
   a short label inside sentence-sized UI.

   What .mateen-ayah brings along is either wanted or inert on these elements: direction: rtl is
   correct for the name, the generous line-height keeps stacked diacritics from clipping, and its
   text-align/text-justify do nothing on an inline <span>.
   =================================================================================== */

/* The card's heading name. The card's own id prefix stays in the UI font (it is outside this span),
   so only the Arabic run switches face. */
.mateen-sura-card__name[b-dselv853xt] {
    --mateen-ayah-size: 1.15rem;
    min-width: 0;
    overflow-wrap: anywhere;
    /* .mateen-ayah centres its text; a wrapped long Arabic name should hug the icon instead. */
    text-align: start;
}

/* Icon + name on one row; the icon keeps its size (flex: none in SuraIcon) and a long name wraps
   beside it instead of pushing it away. The ordering follows the document direction. */
.mateen-sura-card__heading[b-dselv853xt] {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    max-width: 100%;
    vertical-align: middle;
}

/* The Sura picker's own input. Two selectors because MudAutocomplete exposes only InputClass (no
   InputStyle in 9.10.0) and does not document whether that class lands on the <input> itself or on
   the input wrapper around it - the first covers the former, the second lets the family through to
   the control in the latter case (form controls do not inherit font-family by default). `font:
   inherit` is used rather than a family, so the Mushaf face still comes from .mateen-ayah alone.

   The overrides are what makes a verse-text class usable in a single-line input: label-sized text,
   normal leading instead of 2.2, and start-aligned instead of the block's centring (text-align DOES
   apply inside an input, unlike on the spans above). */
.mateen-sura-progress-filters[b-dselv853xt]  .mateen-ayah {
    --mateen-ayah-size: 1rem;
    line-height: normal;
    text-align: start;
}

    .mateen-sura-progress-filters[b-dselv853xt]  .mateen-ayah input {
        font: inherit;
    }

/* Direction/adornment placement of this input (InputClass lands on the .mud-input root) is handled once
   in app.css by `.mud-input.mateen-ayah`, which also covers the plan and ticket dialog pickers. */
/* /Components/Shared/SuraAyahSelector.razor.rz.scp.css */
/* SuraAyahSelector. Palette variables only (no hex) so light and dark follow the theme. No Mushaf font
   family is named: Arabic text carries app.css's .mateen-ayah class and only the size is overridden inline. */

.sas[b-jtf2y58nkr] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    gap: 12px;
    height: min(66vh, 640px);
    min-height: 360px;
}

.sas__pane[b-jtf2y58nkr] {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    overflow: hidden;
}

.sas__title[b-jtf2y58nkr] { font-weight: 700; line-height: 1.2; }
.sas__sub[b-jtf2y58nkr] { font-size: .75rem; color: var(--mud-palette-text-secondary); }

/* ---- left pane ---- */
.sas__suras-head[b-jtf2y58nkr] { display: flex; align-items: center; gap: 10px; padding: 12px 14px 4px; }

.sas__head-icon[b-jtf2y58nkr] {
    padding: 6px;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.sas__search[b-jtf2y58nkr] { padding: 6px 10px; }

.sas__suras-list[b-jtf2y58nkr] { flex: 1 1 auto; overflow-y: auto; padding: 4px 8px 8px; }

.sas__sura[b-jtf2y58nkr] {
    all: unset;
    box-sizing: border-box;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    margin-bottom: 4px;
    border: 1px solid transparent;
    border-radius: 12px;
    cursor: pointer;
}

    .sas__sura:hover[b-jtf2y58nkr] { background: var(--mud-palette-action-default-hover); }
    .sas__sura:focus-visible[b-jtf2y58nkr], .sas__ayah:focus-visible[b-jtf2y58nkr] { outline: 2px solid var(--mud-palette-primary); outline-offset: -2px; }

.sas__sura--on[b-jtf2y58nkr],
.sas__sura--on:hover[b-jtf2y58nkr] {
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    border-color: color-mix(in srgb, var(--mud-palette-primary) 55%, transparent);
}

.sas__sura-names[b-jtf2y58nkr] { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.sas__sura-name[b-jtf2y58nkr] { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sas__sura-count[b-jtf2y58nkr] { font-size: .75rem; color: var(--mud-palette-text-secondary); }
.sas__sura--on .sas__sura-name[b-jtf2y58nkr] { color: var(--mud-palette-primary); }
.sas__sura-ar[b-jtf2y58nkr] { flex: 0 0 auto; }

.sas__dot[b-jtf2y58nkr] {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--mud-palette-primary);
    flex: 0 0 auto;
}

/* ---- right pane ---- */
.sas__ayahs-head[b-jtf2y58nkr] {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 14px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.sas__ayahs-title[b-jtf2y58nkr] { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.sas__ayahs-ar[b-jtf2y58nkr] { line-height: 1.5; }
.sas__tools[b-jtf2y58nkr] { display: flex; align-items: center; gap: 4px; }

.sas__ayah-scroll[b-jtf2y58nkr] { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 10px 12px; }

.sas__ayah[b-jtf2y58nkr] {
    all: unset;
    box-sizing: border-box;
    width: 100%;
    min-height: 80px;
    margin-bottom: 12px;
    padding: 10px 14px;
    display: flex;
    align-items: center;
    gap: 14px;
    cursor: pointer;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    user-select: none;
}

    .sas__ayah:hover[b-jtf2y58nkr] { background: var(--mud-palette-action-default-hover); }

.sas__ayah--on[b-jtf2y58nkr],
.sas__ayah--on:hover[b-jtf2y58nkr] {
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    border-color: var(--mud-palette-primary);
}

.sas__ayah-no[b-jtf2y58nkr] { flex: 0 0 auto; }
.sas__ayah-text[b-jtf2y58nkr] { flex: 1 1 auto; text-align: right; line-height: 2.2; }
.sas__ayah-missing[b-jtf2y58nkr] { flex: 1 1 auto; text-align: right; font-style: italic; color: var(--mud-palette-text-secondary); }
.sas__ayah-check[b-jtf2y58nkr] { flex: 0 0 24px; height: 24px; }

.sas__summary[b-jtf2y58nkr] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 8px 14px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.sas__summary-count[b-jtf2y58nkr] { display: inline-flex; align-items: center; gap: 6px; font-size: .85rem; font-weight: 600; }
.sas__chips[b-jtf2y58nkr] { flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }

.sas__empty[b-jtf2y58nkr] {
    flex: 1 1 auto;
    display: grid;
    place-content: center;
    justify-items: center;
    gap: 8px;
    color: var(--mud-palette-text-secondary);
}

@media (max-width: 760px) {
    .sas[b-jtf2y58nkr] { grid-template-columns: 1fr; grid-template-rows: minmax(140px, 30%) minmax(0, 1fr); height: 74vh; }
}

/* ---- per-ayah mistake (triangle) button ---- */
.sas__warn[b-jtf2y58nkr] {
    all: unset;
    box-sizing: border-box;
    position: relative;
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    cursor: pointer;
    color: var(--mud-palette-text-secondary);
}

    .sas__warn:hover[b-jtf2y58nkr] { background: var(--mud-palette-action-default-hover); }
    .sas__warn:focus-visible[b-jtf2y58nkr] { outline: 2px solid var(--mud-palette-primary); outline-offset: 1px; }

.sas__warn--has[b-jtf2y58nkr] { color: var(--mud-palette-warning); }

.sas__warn-badge[b-jtf2y58nkr] {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    font-size: .68rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    background: var(--mud-palette-warning);
    color: var(--mud-palette-warning-text);
}

/* ---- already added to the session: light success tint + green tick ---- */
.sas__sura--added[b-jtf2y58nkr],
.sas__ayah--added[b-jtf2y58nkr] {
    background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent);
    border-color: color-mix(in srgb, var(--mud-palette-success) 45%, transparent);
}

    .sas__sura--added:hover[b-jtf2y58nkr],
    .sas__ayah--added:hover[b-jtf2y58nkr] {
        background: color-mix(in srgb, var(--mud-palette-success) 20%, transparent);
    }

/* Selected wins the background/border (primary), the green tick on the number badge keeps showing it is added. */
.sas__sura--on.sas__sura--added[b-jtf2y58nkr],
.sas__ayah--on.sas__ayah--added[b-jtf2y58nkr] {
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, color-mix(in srgb, var(--mud-palette-success) 10%, transparent));
    border-color: var(--mud-palette-primary);
}

/* The tick sits on the number badge's corner; the selection check stays in its own slot at the card's far end. */
.sas__ayah-no[b-jtf2y58nkr] { position: relative; }

.sas__ayah-added[b-jtf2y58nkr] {
    position: absolute;
    top: -8px;
    right: -8px;
    display: grid;
    border-radius: 50%;
    background: var(--mud-palette-surface);
    line-height: 0;
}
/* /Components/Shared/SuraIcon.razor.rz.scp.css */
/* SuraIcon: ayah count inside an outline ornament. Everything is a palette variable or derived from
   one, nothing is a literal hex, so both modes follow the theme.

   color-scheme is declared on the root because MudBlazor 9.10.0 only feeds
   --mud-native-html-color-scheme into real `color-scheme` on inputs - outside one, light-dark()
   would always return its light value. Set here so the icon works under any ancestor. */
.mateen-sura-icon[b-5d3sr1lqn9] {
    color-scheme: var(--mud-native-html-color-scheme);
    --sura-icon-size: 36px;
    --sura-icon-ink: var(--mud-palette-primary);
    position: relative;
    display: inline-grid;
    place-items: center;
    flex: 0 0 auto;
    width: var(--sura-icon-size);
    height: var(--sura-icon-size);
    vertical-align: middle;
    color: var(--sura-icon-ink);
    line-height: 1;
    /* A count never reads right-to-left, even inside an Arabic .mateen-ayah/dir=rtl run. */
    direction: ltr;
    unicode-bidi: isolate;
}

/* Morajaah ink. Bare --mud-palette-secondary (#9333EA) is only 3.13:1 on the dark card, so lift it
   toward white in dark mode and deepen it slightly in light. */
.mateen-sura-icon--secondary[b-5d3sr1lqn9] {
    --sura-icon-ink: light-dark(
        color-mix(in srgb, var(--mud-palette-secondary) 85%, black),
        color-mix(in srgb, var(--mud-palette-secondary) 55%, white));
}

.mateen-sura-icon__shape[b-5d3sr1lqn9] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}

    .mateen-sura-icon__shape polygon[b-5d3sr1lqn9] {
        fill: color-mix(in srgb, var(--sura-icon-ink) 12%, transparent);
        stroke: var(--sura-icon-ink);
        stroke-width: 2;
        stroke-linejoin: miter;
        stroke-miterlimit: 4;
    }

.mateen-sura-icon__count[b-5d3sr1lqn9] {
    position: relative;
    font-size: 13px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -.02em;
    color: var(--sura-icon-ink);
}

/* Three digits (100-286): still >= 11px, and inside the star's inner circle. */
.mateen-sura-icon__count--long[b-5d3sr1lqn9] {
    font-size: 11px;
    letter-spacing: -.04em;
}
/* /Components/Shared/TicketsPanel.razor.rz.scp.css */
/* Scoped to TicketsPanel (Blazor CSS isolation): the record cards. Only what is specific to these
   cards lives here; the ring itself is the shared .mateen-dual-ring in app.css, reached through
   ::deep because DualProgressRing renders its own markup (the scope attribute is never stamped onto
   a child component's elements).

   Visual language matches the student grid card (PersonCard / StudentSummaryCard): 18px radius,
   the same soft shadow + 2px lift on hover, a 7px accent bar along the bottom edge, and the compact
   single-ring dial. The accent is the app-wide pairing - Hifd = primary, Morajaah = secondary.
   Everything colour-related goes through --mud-palette-* / light-dark(), nothing is a literal hex,
   so both themes resolve through the same rules. */

.mateen-ticket-card[b-zypvgx9s94] {
    /* The mode signal every light-dark() below resolves against. */
    color-scheme: var(--mud-native-html-color-scheme);
    --ticket-accent: var(--mud-palette-primary);
    --ticket-shadow: light-dark(rgba(42, 39, 64, .10), rgba(0, 0, 0, .45));
    --ticket-shadow-hover: light-dark(rgba(42, 39, 64, .18), rgba(0, 0, 0, .60));
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    height: 100%;
    box-sizing: border-box;
    /* Bottom padding clears the 5px accent bar. */
    padding: 8px 10px 11px;
    overflow: hidden;
    border-radius: 14px;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    box-shadow: 0 6px 18px var(--ticket-shadow);
    transition: box-shadow 200ms cubic-bezier(.4, 0, .2, 1), border-color 200ms cubic-bezier(.4, 0, .2, 1), transform 200ms cubic-bezier(.4, 0, .2, 1);
}

.mateen-ticket-card--morajaah[b-zypvgx9s94] {
    --ticket-accent: var(--mud-palette-secondary);
}

.mateen-ticket-card[b-zypvgx9s94]::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 5px;
    background-color: var(--ticket-accent);
    pointer-events: none;
}

.mateen-ticket-card--clickable:hover[b-zypvgx9s94] {
    border-color: color-mix(in srgb, var(--ticket-accent) 45%, transparent);
    box-shadow: 0 10px 24px var(--ticket-shadow-hover);
    transform: translateY(-2px);
}

/* The stretched edit target: invisible, covers the whole card, under the controls. The keyboard
   focus ring is drawn on the button itself (it IS the card's extent), inset so overflow:hidden on
   the card cannot clip it. */
.mateen-ticket-card__open[b-zypvgx9s94] {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: inherit;
    background: transparent;
    cursor: pointer;
}

    .mateen-ticket-card__open:focus-visible[b-zypvgx9s94] {
        outline: 3px solid var(--ticket-accent);
        outline-offset: -3px;
    }

/* Top row: identity cluster left, ring right, vertically centred so a read-only card (no buttons, a
   shorter cluster) leaves no gap under the pill. */
.mateen-ticket-card__head[b-zypvgx9s94] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    /* 10px between the body and the divider/footer block (the divider's auto top margin only adds to this when the row is taller). */
    margin-bottom: 10px;
}

/* Right column: ring over grade, pinned far right. */
.mateen-ticket-card__side[b-zypvgx9s94] {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin-inline-start: auto;
}

.mateen-ticket-card__grade[b-zypvgx9s94] {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    max-width: 96px;
}

/* flex 1 1 0 + min-width 0: this column takes whatever the ring leaves and is the one that gives
   (the pill ellipsises); the ring is flex 0 0 auto so it can never be squeezed or pushed out. */
.mateen-ticket-card__id[b-zypvgx9s94] {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 15px;
    min-width: 0;
}

/* Chip-like, but a plain span on purpose (not a MudChip): tinted by the card type, text mixed
   toward the primary text colour so it stays legible on its own tint in both modes. Long names
   ellipsise (full name in the title attribute). unicode-bidi: isolate keeps an Arabic name's own
   direction contained to the pill - the row and the card stay LTR. */
.mateen-ticket-card__sura[b-zypvgx9s94] {
    box-sizing: border-box;
    min-width: 0;
    max-width: 100%;
    padding: 5px 10px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    unicode-bidi: isolate;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--ticket-accent) 35%, transparent);
    background-color: color-mix(in srgb, var(--ticket-accent) 14%, var(--mud-palette-surface));
    color: color-mix(in srgb, var(--ticket-accent) 45%, var(--mud-palette-text-primary));
    font-size: .8125rem;
    line-height: 1.45;
    font-weight: 700;
}

/* Icon OUTSIDE the pill, beside it (same arrangement and size as Next session tasks): the icon is
   flex none, the pill is the part that shrinks and ellipsises. */
.mateen-ticket-card__sura-row[b-zypvgx9s94] {
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 100%;
    min-width: 0;
}

    .mateen-ticket-card__sura-row[b-zypvgx9s94]  .mateen-sura-icon {
        --sura-icon-size: 32px;
    }

.mateen-ticket-card__ring[b-zypvgx9s94] {
    flex: 0 0 auto;
}

/* Panel-scoped smaller dial: the shared compact ring is 104px (92px on phones); here it is 68px.
   class + attribute + class outranks app.css's phone media rule, so 68 holds at every width without
   touching the component or its other users. */
.mateen-ticket-card__ring[b-zypvgx9s94]  .mateen-dual-ring--compact {
    gap: 0;
}

.mateen-ticket-card__ring[b-zypvgx9s94]  .mateen-dual-ring__dial {
    width: 68px;
    height: 68px;
}

.mateen-ticket-card__ring[b-zypvgx9s94]  .mateen-dual-ring__value {
    font-size: .875rem;
}

.mateen-ticket-card__ring[b-zypvgx9s94]  .mateen-dual-ring__arc--outer {
    stroke: var(--mateen-progress-band, var(--ticket-accent));
}

.mateen-ticket-card__ring[b-zypvgx9s94]  .mateen-dual-ring__track--outer {
    stroke: color-mix(in srgb, var(--mateen-progress-band, var(--ticket-accent)) 16%, var(--mud-palette-surface));
}

/* Small round buttons, above the stretched edit target. 28px is the tap-target floor. */
.mateen-ticket-card__end[b-zypvgx9s94]  .mateen-ticket-card__action {
    position: relative;
    z-index: 2;
    width: 28px;
    height: 28px;
    margin-block: -2px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 6%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
}

    .mateen-ticket-card__end[b-zypvgx9s94]  .mateen-ticket-card__action .mud-icon-root {
        font-size: 1rem;
    }

    .mateen-ticket-card__end[b-zypvgx9s94]  .mateen-ticket-card__action:hover {
        background-color: color-mix(in srgb, var(--ticket-accent) 16%, var(--mud-palette-surface));
    }

    .mateen-ticket-card__end[b-zypvgx9s94]  .mateen-ticket-card__action--danger {
        color: color-mix(in srgb, var(--mud-palette-error) 55%, var(--mud-palette-text-primary));
    }

        .mateen-ticket-card__end[b-zypvgx9s94]  .mateen-ticket-card__action--danger:hover {
            background-color: color-mix(in srgb, var(--mud-palette-error) 16%, var(--mud-palette-surface));
        }

/* One row per stat: icon, label, value. */
.mateen-ticket-card__stat[b-zypvgx9s94] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    max-width: 100%;
    min-width: 0;
    padding: 1px 4px;
    margin-inline-start: -4px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: inherit;
    font: inherit;
}

/* The mistakes stat is a real button (opens Edit Mistakes) above the stretched edit target. */
.mateen-ticket-card__stat--button[b-zypvgx9s94] {
    position: relative;
    z-index: 2;
    cursor: pointer;
}

    .mateen-ticket-card__stat--button:hover[b-zypvgx9s94] {
        background-color: color-mix(in srgb, var(--mud-palette-text-primary) 8%, transparent);
    }

    .mateen-ticket-card__stat--button:focus-visible[b-zypvgx9s94] {
        outline: 2px solid var(--ticket-accent);
        outline-offset: 1px;
    }

.mateen-ticket-card[b-zypvgx9s94]  .mateen-ticket-card__stat-icon {
    font-size: 1rem;
    color: var(--mud-palette-text-secondary);
}

/* The bare palette success/warning/info colours are 2.2:1 against a white card - under the 3:1 a
   meaningful icon needs - so each is mixed toward the text colour. The same mix lifts them in dark
   mode (text is light there), so one rule serves both themes. */
/* Grade icon follows the same banding as SuraTicketsDialog.GradeColor. */
.mateen-ticket-card[b-zypvgx9s94]  .mateen-ticket-card__grade--excellent,
.mateen-ticket-card[b-zypvgx9s94]  .mateen-ticket-card__grade--verygood {
    color: color-mix(in srgb, var(--mud-palette-success) 55%, var(--mud-palette-text-primary));
}

.mateen-ticket-card[b-zypvgx9s94]  .mateen-ticket-card__grade--good {
    color: color-mix(in srgb, var(--mud-palette-info) 55%, var(--mud-palette-text-primary));
}

.mateen-ticket-card[b-zypvgx9s94]  .mateen-ticket-card__grade--fair {
    color: color-mix(in srgb, var(--mud-palette-warning) 55%, var(--mud-palette-text-primary));
}

.mateen-ticket-card[b-zypvgx9s94]  .mateen-ticket-card__grade--poor {
    color: color-mix(in srgb, var(--mud-palette-error) 55%, var(--mud-palette-text-primary));
}

.mateen-ticket-card[b-zypvgx9s94]  .mateen-ticket-card__stat-icon--warn {
    color: light-dark(#E06A00, var(--mud-palette-warning));
}

.mateen-ticket-card__stat-value[b-zypvgx9s94] {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .8125rem;
    line-height: 1.25;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

.mateen-ticket-card__stat-label[b-zypvgx9s94] {
    font-size: .75rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
}

.mateen-ticket-card__divider[b-zypvgx9s94] {
    width: 100%;
    height: 0;
    /* auto top margin pushes divider + footer to the card bottom so a grid row of cards lines up. */
    margin: auto 0 0;
    padding: 0;
    border: 0;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.mateen-ticket-card__footer[b-zypvgx9s94] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 8px;
    width: 100%;
    margin-top: 6px;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

    .mateen-ticket-card__footer b[b-zypvgx9s94] {
        color: var(--mud-palette-text-primary);
        font-weight: 700;
    }

.mateen-ticket-card__end[b-zypvgx9s94] {
    margin-inline-start: auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.mateen-ticket-card__date[b-zypvgx9s94] {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    white-space: nowrap;
}

.mateen-ticket-card__ayahs[b-zypvgx9s94] {
    white-space: nowrap;
}

.mateen-ticket-card__date[b-zypvgx9s94]  .mateen-ticket-card__date-icon {
    font-size: .875rem;
    color: var(--mud-palette-text-secondary);
}

/* A reload keeps the previous cards on screen; dimmed so it reads as "updating", not stale. */
.mateen-ticket-grid--loading[b-zypvgx9s94] {
    opacity: .6;
    transition: opacity 150ms;
}

@media (prefers-reduced-motion: reduce) {
    .mateen-ticket-card[b-zypvgx9s94],
    .mateen-ticket-card--clickable:hover[b-zypvgx9s94] {
        transition: none;
        transform: none;
    }
}

/* The grid cell is a size container: the card adapts to the width it is actually given (the requested
   lg=2 / md=3 / sm=4 / xs=6 spans produce ~145-250px cards at different viewports), not to the viewport. */
.mateen-ticket-grid[b-zypvgx9s94]  .mateen-ticket-cell {
    container-type: inline-size;
}

/* Narrow card: the 68px ring no longer leaves room for the stats beside it, so the head stacks -
   Surah / Mistakes / Score full width, then Grade (left) and the ring (right) on a row of their own.
   The footer already wraps (ayahs, then date + Delete) via flex-wrap above. */
@container (max-width: 205px) {
    .mateen-ticket-card__head[b-zypvgx9s94] {
        flex-wrap: wrap;
        gap: 10px 8px;
    }

    .mateen-ticket-card__id[b-zypvgx9s94] {
        flex: 1 1 100%;
    }

    .mateen-ticket-card__side[b-zypvgx9s94] {
        flex: 1 1 100%;
        flex-direction: row-reverse;
        justify-content: space-between;
        align-items: center;
    }

    .mateen-ticket-card__grade[b-zypvgx9s94] {
        max-width: none;
    }
}

/* Narrowest cards (xs=6 on phones, md=3 around 960px): ring + a long Grade word ("Excellent") no
   longer fit side by side, so Grade drops under the ring (the original arrangement), pinned right. */
@container (max-width: 172px) {
    .mateen-ticket-card__side[b-zypvgx9s94] {
        flex: 0 0 auto;
        flex-direction: column;
        justify-content: flex-start;
        margin-inline-start: auto;
        gap: 2px;
    }

    /* Date + Delete need ~124px; trim the card's side padding and the date/Delete gap so they fit at ~146px. */
    .mateen-ticket-card[b-zypvgx9s94] {
        padding-inline: 7px;
    }

    .mateen-ticket-card__end[b-zypvgx9s94] {
        gap: 3px;
    }
}

/* Fixed-ish filter width: a bare MudSelect stretches to fill its flex cell and strands the second
   filter at the far edge. */
.mateen-ticket-filter[b-zypvgx9s94] {
    flex: 0 1 280px;
    min-width: 200px;
}
/* /Components/Shared/UserAvatar.razor.rz.scp.css */
/* ===================================================================================
   UserAvatar.razor - the photo / silhouette / initials-plate avatar.

   SCOPED, NOT app.css, ON PURPOSE: everything here styles elements this component itself renders,
   so it needs no global reach, and keeping it out of app.css keeps the avatar's own rules
   discoverable next to the markup that produces them.

   WHY THE PLATE COLOURS ARE light-dark() PAIRS
   MudBlazor 9.10.0 emits no dark-mode class, but its ThemeProvider does emit the custom property
   --mud-native-html-color-scheme: light | dark on :root and re-emits it the instant the mode flips.
   .mateen-avatar below feeds that into the real `color-scheme` property, and because color-scheme
   inherits, every light-dark(<light>, <dark>) here resolves against the app's current mode with no
   JS and no wrapper class. This is the same mechanism app.css's .mateen-person-card and
   .mateen-landing blocks use - see app.css's own long note on it.

   A plate colour that did NOT flip would be the bug this app has already had once: a deep violet
   that reads beautifully on a white card is near-invisible on the dark navy one, and vice versa.
   =================================================================================== */

/* Fills whatever fixed-size circular container the call site already has
   (.mateen-person-card__avatar / .mateen-dashboard-list-item__avatar /
   .mateen-attendance-card__avatar - all of them width/height + border-radius:50% + overflow:hidden),
   so dropping this component in moved no layout.

   container-type: size is what lets the initials size themselves off the container instead of
   needing a Size parameter kept in sync with the CSS: the parent's width/height are definite, this
   span is 100% of them, so cq* units below resolve against the real avatar diameter - 40px in a list
   row, 72px on a person card. */
.mateen-avatar[b-8mybvmxcxv] {
    display: flex;
    width: 100%;
    height: 100%;
    container-type: size;
    /* The mode signal every light-dark() below is resolved against - see the block comment. */
    color-scheme: var(--mud-native-html-color-scheme);
}

/* Restated here rather than relied upon: every current call site has an equivalent
   "<container> img" rule of its own (which still matches - those are descendant selectors and the
   img is simply one level deeper now), but a future call site should not have to supply one. */
.mateen-avatar img[b-8mybvmxcxv] {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.mateen-avatar__initials[b-8mybvmxcxv] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    /* The plate itself is square; the container's own border-radius:50% + overflow:hidden clips it
       to the same circle the photo gets, so the two styles are interchangeable in every slot. */
    background-color: var(--mateen-avatar-plate-bg);
    color: var(--mateen-avatar-plate-fg);
    font-weight: 700;
    line-height: 1;
    /* No text cursor over what is effectively a picture, and a double-click on a card must not
       select the letters. */
    user-select: none;

    /* 1rem first as the floor for an engine without container query units; 38cqmin is the real
       value - 38% of the avatar's shorter side, i.e. 15.2px at 40px and 27.4px at 72px, which fits
       two Latin letters inside the circle at both sizes with the margin a round plate needs (the
       usable width across a circle at the text's own height is well under the diameter). */
    font-size: 1rem;
    font-size: 38cqmin;
}

/* ---- The six plates ---------------------------------------------------------------------------
   Each is a brand colour this app already owns, stated as a light/dark pair with the foreground the
   theme already pairs with it. Measured contrast of the INITIALS against their own plate (the ratio
   that decides legibility) is quoted per plate for light / dark; every one clears WCAG AA 4.5:1 for
   normal-size text, which is the stricter bar - the initials render bold at 15px+ and would only
   need 3:1 as large text at the bigger sizes.

   Deep in light mode with near-white letters, lifted in dark mode with near-black letters: the same
   construction Theme/MateenTheme.cs uses for Primary/PrimaryContrastText, and the reason a single
   fixed plate colour was not an option.

   Six rather than more: the set has to stay six clearly DIFFERENT hues, so that two people side by
   side look different rather than like two shades of the same colour. AvatarPlatePalette.PlateCount
   must match this count. */

/* Violet - MateenTheme LightPrimary/LightPrimaryForeground and DarkPrimary/DarkPrimaryForeground,
   verbatim. 11.65:1 / 6.54:1. */
.mateen-avatar__initials--p0[b-8mybvmxcxv] {
    --mateen-avatar-plate-bg: light-dark(#471671, #BB86EA);
    --mateen-avatar-plate-fg: light-dark(#F6F1FB, #1A1330);
}

/* Purple - MateenTheme BrandPurple + SecondaryContrastText. The one plate that does NOT flip, and
   deliberately so: the theme itself uses this exact pair in both palettes, and it is a mid-tone that
   genuinely works on either surface (3.13:1 against the dark card, 5.38:1 against the light one). It
   also has to stay saturated in dark mode to read as a different colour from p0's pale lilac. 5.38:1
   in both modes. */
.mateen-avatar__initials--p1[b-8mybvmxcxv] {
    --mateen-avatar-plate-bg: #9333EA;
    --mateen-avatar-plate-fg: #FFFFFF;
}

/* Periwinkle - MateenTheme LightPeriwinkleDarken / DarkPeriwinkleLighten, verbatim (the Tertiary
   role's own darken/lighten variants). 4.63:1 / 8.75:1. */
.mateen-avatar__initials--p2[b-8mybvmxcxv] {
    --mateen-avatar-plate-bg: light-dark(#4A5DED, #A7B1FB);
    --mateen-avatar-plate-fg: light-dark(#F6F1FB, #1A1330);
}

/* Mauve - MateenTheme LightMauve verbatim; the dark side is DarkMauve #7E77A8 lifted from
   hsl(249,19%,56%) to hsl(249,19%,62%), the only derived value in this set. DarkMauve itself gives
   4.32:1 against the near-black foreground, just under AA, and this is the smallest step that clears
   it while staying recognisably the same desaturated mauve (it is still clearly distinct from p0's
   saturated violet). 9.39:1 / 5.59:1. */
.mateen-avatar__initials--p3[b-8mybvmxcxv] {
    --mateen-avatar-plate-bg: light-dark(#413C58, #918CB1);
    --mateen-avatar-plate-fg: light-dark(#F6F1FB, #1A1330);
}

/* Teal - app.css's own --mateen-member-accent / .mateen-person-card--educator accent pair,
   verbatim. The app's established non-violet accent, so an avatar using it reads as in-family.
   5.21:1 / 7.75:1. */
.mateen-avatar__initials--p4[b-8mybvmxcxv] {
    --mateen-avatar-plate-bg: light-dark(#0F6E8C, #4FB8D4);
    --mateen-avatar-plate-fg: light-dark(#F6F1FB, #1A1330);
}

/* Bronze - app.css's --mateen-landing-title-1 pair, verbatim: the identity's gold, which the brand
   kept after the primary moved to violet. The set's only warm hue, which is what earns it a slot.
   4.86:1 / 7.27:1. */
.mateen-avatar__initials--p5[b-8mybvmxcxv] {
    --mateen-avatar-plate-bg: light-dark(#8A6320, #BEA088);
    --mateen-avatar-plate-fg: light-dark(#F6F1FB, #1A1330);
}

/* Arabic initials carry .Tajawal-Text-Bold (wwwroot/tajawal-typography.css) for the family and
   weight 700. Its 1rem font-size is wrong here - the letter has to scale with the avatar - so this
   overrides only that, the same way UserPreferences.razor.css overrides only --mateen-ayah-size on
   .mateen-ayah. Scoped CSS adds this component's own attribute selector, which outweighs the
   single-class rule in the global stylesheet.

   The Arabic letter is drawn one step larger than a Latin pair: it is a single glyph with no
   neighbour to make room for, and Tajawal's x-height sits lower in the em box than Inter's, so at
   the same font-size it reads noticeably smaller on the plate. */
.mateen-avatar__initials.Tajawal-Text-Bold[b-8mybvmxcxv] {
    font-size: 1.25rem;
    font-size: 46cqmin;
}
