/*
 * SfButton — portable button family CSS, extracted from app.css for use
 * across portals (admin, applicant, student, etc.).
 *
 * Drop into any Blazor portal that references GlobalEdTech.Sis.WebApp.Shared
 * (which provides the SfButton razor components). Include via:
 *
 *     <link rel="stylesheet"
 *           href="_content/GlobalEdTech.Web.Shared/css/sf-tokens.css" />
 *     <link rel="stylesheet"
 *           href="_content/GlobalEdTech.Web.Shared/css/sf-buttons.css" />
 *
 * sf-tokens.css ships the design-token system (colors, focus rings,
 * shadow, button family colors / sizes, etc.). It must be loaded
 * alongside this file — every var() reference here resolves to a token
 * declared there. See sf-tokens.css for token catalog and rationale.
 *
 * See docs/ui/sf-button-design.md and docs/ui/sf-button-group-design.md.
 *
 * ── SfButton class-name reference ──────────────────────────────────────
 *   Component name          CSS class(es) used
 *   ─────────────────────   ─────────────────────────────────────────
 *   SfButton.Primary        .sf-btn-save
 *   SfButton.Accent         .sf-btn-accent
 *   SfButton.Secondary      .sf-btn-cancel
 *   SfButton.Ghost          .sf-btn-secondary    ← misleading; means "ghost"
 *   SfButton.Destructive    .sf-btn-delete
 *   SfButton.Cautionary     .sf-btn-cautionary
 *   SfButton.Warning        .sf-btn-warning
 *   SfButton.Link           .btn-plain
 *   SfButton.Close          .btn-plain (icon-only with fa-window-close)
 *   SfButton.Grid.*         .sf-btn-grid (sizing) + role class
 *   SfButton.Grid.Custom    .sf-btn-grid-aligned + role class
 *   SfButton.Grid.ChevronToggle  .sf-btn-grid + .sf-btn-secondary + .sf-chevron-toggle
 *   SfButton.ButtonGroup.*  .sf-btn-group (parent only)
 *
 * Don't try to "fix" .sf-btn-secondary by changing it to mean Secondary —
 * ~250 existing call sites use it for the Ghost treatment. The component
 * names are the source of truth for new code; class names are legacy.
 */

/* ════════════════════════════════════════════════════════════════════
   Standalone role buttons (Primary / Accent / Secondary / Ghost /
   Destructive / Cautionary). Each rule applies to a TelerikButton with
   the corresponding sf-btn-* class — automatically merged by the
   SfButton.* wrapper components.
   ════════════════════════════════════════════════════════════════════ */

/* ── SfButton.Primary  →  .sf-btn-save ────────────────────────────── */
.sf-btn-save.k-button {
    background-color: var(--sf-primary-button-bg) !important;
    border-color: var(--sf-primary-button-bg) !important;
    color: #ffffff !important;
    border-radius: 8px !important;
    height: var(--sf-btn-size);
    padding: 4px 16px !important;
    min-width: 64px;
    box-shadow: var(--sf-shadow-md);
    transition: all 200ms ease;
}

.sf-btn-save.k-button:hover:not(.k-disabled) {
    background-color: var(--sf-primary-button-hover) !important;
    border-color: var(--sf-primary-button-hover) !important;
}

.sf-btn-save.k-button.k-disabled {
    opacity: 0.6;
}

.sf-btn-save.k-button:focus-visible {
    outline: 2px solid var(--sf-primary-button-bg);
    outline-offset: 2px;
    box-shadow: none;
}

/* ── SfButton.Accent  →  .sf-btn-accent ───────────────────────────── */
.sf-btn-accent.k-button {
    background-color: var(--sf-accent-button-bg) !important;
    border-color: var(--sf-accent-button-bg) !important;
    color: #ffffff !important;
    border-radius: 8px !important;
    height: var(--sf-btn-size);
    padding: 4px 16px !important;
    min-width: 64px;
    box-shadow: var(--sf-shadow-md);
    transition: all 200ms ease;
}

.sf-btn-accent.k-button:hover:not(.k-disabled) {
    background-color: var(--sf-accent-button-hover) !important;
    border-color: var(--sf-accent-button-hover) !important;
}

.sf-btn-accent.k-button.k-disabled { opacity: 0.6; }

.sf-btn-accent.k-button:focus-visible {
    outline: 2px solid var(--sf-accent-button-bg);
    outline-offset: 2px;
    box-shadow: none;
}

/* ── SfButton.Secondary  →  .sf-btn-cancel ────────────────────────── */
/* Border is --sf-secondary-text by design, NOT --sf-border-subtle. Keeping
   cancel darker than form-input borders preserves the visual hierarchy of
   toolbar (subtle) < cancel (strong) < primary actions. */
.sf-btn-cancel.k-button {
    background-color: var(--sf-bg-white) !important;
    border: 1px solid var(--sf-secondary-text) !important;
    color: var(--sf-secondary-text) !important;
    border-radius: 8px !important;
    height: var(--sf-btn-size);
    padding: 4px 16px !important;
    min-width: 64px;
    box-shadow: var(--sf-shadow-md);
    transition: all 200ms ease;
}

.sf-btn-cancel.k-button:hover:not(.k-disabled) {
    background-color: #f8f9fa !important;
}

.sf-btn-cancel.k-button:focus-visible {
    outline: 2px solid var(--sf-secondary-text);
    outline-offset: 2px;
    box-shadow: none;
}

/* ── SfButton.Ghost  →  .sf-btn-secondary ─────────────────────────── */
/* Low emphasis actions (Password Recovery, Preview, More Options, etc.).
   slate-500 (--sf-border-subtle, #64748b) — 4.1:1 against gray-100 fill,
   passes WCAG 2.2 non-text contrast (3:1). Lighter than Secondary's
   slate-600 border so the two roles read as distinct. */
.sf-btn-secondary.k-button {
    background-color: var(--sf-secondary-button-bg) !important;
    border: 1px solid var(--sf-border-subtle) !important;
    color: var(--sf-secondary-button-text) !important;
    border-radius: 8px !important;
    height: var(--sf-btn-size);
    padding: 4px 16px !important;
    min-width: 64px;
    box-shadow: var(--sf-shadow-md);
    transition: all 200ms ease;
}

.sf-btn-secondary.k-button:hover:not(.k-disabled) {
    background-color: var(--sf-secondary-button-hover) !important;
}

.sf-btn-secondary.k-button:focus-visible {
    outline: 2px solid var(--sf-secondary-button-text);
    outline-offset: 2px;
    box-shadow: none;
}

.sf-btn-secondary.k-button.k-disabled {
    background-color: var(--sf-secondary-button-disabled-bg) !important;
    color: var(--sf-secondary-button-disabled-text) !important;
    cursor: not-allowed;
    opacity: 1;
}

/* Inside an input wrapper (e.g. Telerik search/combo group), tighten the secondary button */
.k-input .sf-btn-secondary.k-button {
    min-width: unset !important;
    padding: 4px 4px !important;
}

/* ── Ghost/icon buttons inside a combo/input prefix or suffix ─────────
   Buttons authored into a Telerik input prefix/suffix (e.g. the Code/Name
   swap and Refresh actions in the Term/Course/Reference combo boxes via a
   MultiColumnComboBoxSuffixTemplate / ComboBoxSuffixTemplate /
   TextBoxSuffixTemplate) must read as borderless, muted affordances that
   sit alongside the native clear (×) / dropdown (▾) icons — NOT as solid,
   boxed standalone buttons. The secondary role's fill/border/shadow
   (above) otherwise wins, so strip it here and tighten to an icon
   footprint. The native Telerik dropdown/clear buttons render OUTSIDE
   .k-input-prefix / .k-input-suffix (as siblings), so they are never
   matched, and SfButton.Link/Close (.btn-plain, not .k-button) is already
   borderless. This is host-agnostic; the per-host .sf-combo-swap rule
   still owns the swap button's hide-until-hover reveal behavior. */
.k-input-prefix .sf-btn-secondary.k-button,
.k-input-prefix .sf-btn-icon.k-button,
.k-input-suffix .sf-btn-secondary.k-button,
.k-input-suffix .sf-btn-icon.k-button {
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
    min-width: 0 !important;
    height: auto;
    padding: 4px 6px !important;
}

.k-input-prefix .sf-btn-secondary.k-button:hover:not(.k-disabled),
.k-input-prefix .sf-btn-icon.k-button:hover:not(.k-disabled),
.k-input-suffix .sf-btn-secondary.k-button:hover:not(.k-disabled),
.k-input-suffix .sf-btn-icon.k-button:hover:not(.k-disabled) {
    background-color: var(--kendo-color-base-hover, #ebebeb) !important;
}

/* ── SfButton.Destructive  →  .sf-btn-delete ──────────────────────── */
.sf-btn-delete.k-button {
    background-color: var(--sf-delete-button-bg) !important;
    /* Darker red border (red-700) for visual weight against the red-600 fill */
    border-color: var(--sf-delete-button-hover) !important;
    color: #ffffff !important;
    border-radius: 8px !important;
    height: var(--sf-btn-size);
    padding: 4px 16px !important;
    min-width: 64px;
    box-shadow: var(--sf-shadow-md);
    transition: all 200ms ease;
}

.sf-btn-delete.k-button:hover:not(.k-disabled) {
    background-color: var(--sf-delete-button-hover) !important;
    border-color: var(--sf-delete-button-hover) !important;
}

.sf-btn-delete.k-button.k-disabled {
    background-color: var(--sf-disabled-button-bg) !important;
    border-color: var(--sf-disabled-button-bg) !important;
    color: var(--sf-disabled-button-text) !important;
    cursor: not-allowed;
    opacity: 1;
}

.sf-btn-delete.k-button:focus-visible {
    outline: 2px solid var(--sf-delete-button-bg);
    outline-offset: 2px;
    box-shadow: none;
}

/* ── SfButton.Cautionary  →  .sf-btn-cautionary ───────────────────── */
/* Cautionary actions that need attention but are less severe than delete —
   e.g. Reset Password, Suspend, Lock. White ground with red border + text;
   hover tints to red-50. */
.sf-btn-cautionary.k-button {
    background-color: var(--sf-bg-white) !important;
    border: 1px solid var(--sf-delete-button-bg) !important;
    color: var(--sf-delete-button-bg) !important;
    border-radius: 8px !important;
    height: var(--sf-btn-size);
    padding: 4px 16px !important;
    min-width: 64px;
    box-shadow: var(--sf-shadow-md);
    transition: all 200ms ease;
}

.sf-btn-cautionary.k-button:hover:not(.k-disabled) {
    background-color: #fef2f2 !important; /* tailwind red-50 */
}

.sf-btn-cautionary.k-button.k-disabled {
    background-color: var(--sf-disabled-button-bg) !important;
    border-color: var(--sf-disabled-button-bg) !important;
    color: var(--sf-disabled-button-text) !important;
    cursor: not-allowed;
    opacity: 1;
}

.sf-btn-cautionary.k-button:focus-visible {
    outline: 2px solid var(--sf-delete-button-bg);
    outline-offset: 2px;
    box-shadow: none;
}

/* ── SfButton.Warning  →  .sf-btn-warning ─────────────────────────── */
/* Amber filled. Less severe than Destructive — use for "active filter",
   "unsaved changes", "pending review" affordances where the user needs
   attention drawn to a non-irreversible state. White text on amber-600
   meets WCAG 2.2 AA non-text contrast (4.66:1). */
.sf-btn-warning.k-button {
    background-color: var(--sf-warning-button-bg) !important;
    /* Darker amber border (amber-700) for visual weight against the amber-600 fill */
    border-color: var(--sf-warning-button-hover) !important;
    color: #ffffff !important;
    border-radius: 8px !important;
    height: var(--sf-btn-size);
    padding: 4px 16px !important;
    min-width: 64px;
    box-shadow: var(--sf-shadow-md);
    transition: all 200ms ease;
}

.sf-btn-warning.k-button:hover:not(.k-disabled) {
    background-color: var(--sf-warning-button-hover) !important;
    border-color: var(--sf-warning-button-hover) !important;
}

.sf-btn-warning.k-button.k-disabled {
    background-color: var(--sf-disabled-button-bg) !important;
    border-color: var(--sf-disabled-button-bg) !important;
    color: var(--sf-disabled-button-text) !important;
    cursor: not-allowed;
    opacity: 1;
}

.sf-btn-warning.k-button:focus-visible {
    outline: 2px solid var(--sf-warning-button-bg);
    outline-offset: 2px;
    box-shadow: none;
}

/* ════════════════════════════════════════════════════════════════════
   SfButton.Link / SfButton.Close  →  .btn-plain
   Plain <button> styled as inline text — no Telerik chrome, no role
   color. Used by SfButton.Link (text affordance) and SfButton.Close
   (icon-only close X).
   ════════════════════════════════════════════════════════════════════ */

.btn-plain {
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    line-height: inherit;
    text-align: inherit;
    text-decoration: none;
    vertical-align: baseline;
    cursor: pointer;
}

.btn-plain:hover,
.btn-plain:focus {
    color: inherit;
    text-decoration: none;
}

.btn-plain:focus:not(:focus-visible) {
    outline: none;
}

.btn-plain:focus-visible {
    outline: var(--sf-focus-inner-width) solid var(--sf-focus-ring-inner);
    outline-offset: var(--sf-focus-offset);
    box-shadow: 0 0 0 var(--sf-focus-width) var(--sf-focus-ring-outer);
}

/* Disabled visual for plain link-style buttons. Browsers' default
   disabled treatment for unstyled buttons is barely visible, so authors
   expect a muted-text + not-allowed cue when Enabled="false" propagates
   to the disabled attribute. */
.btn-plain:disabled,
.btn-plain[disabled] {
    color: var(--sf-text-muted);
    cursor: not-allowed;
    opacity: 0.6;
}

/* SfButton.Link rendered inside a Telerik grid — restore the
   Bootstrap-link-style blue color + hover underline that callers had
   before migrating to <SfButton.Link>. .btn-plain otherwise inherits the
   surrounding text color, which makes a clickable row affordance read as
   plain text. Scoped to .k-grid so SfButton.Link in other contexts
   (modals, sidebars, inline help) keeps the plain inheriting treatment.
   :not(:disabled) keeps the disabled-muted rule above winning for
   Enabled="false" — selector specificity (0,3,0) beats the disabled rule
   (0,2,0) so non-disabled grid links pick up the blue.

   :not(.sf-link) added for bug32138: SfButton.Link now carries its own blue
   via .sf-link below, at a specificity a caller can override. This rule sits
   at (0,4,0) and would still out-rank a caller's scoped colour for any Link
   inside a grid, so Links are excluded here and it now covers only the other
   .btn-plain consumers (SfButton.Close / SfButton.ChevronToggle), whose
   in-grid appearance is unchanged. */
.k-grid .btn-plain:not(.sf-link):not(:disabled):not([disabled]) {
    color: var(--sf-focus-ring-inner);
}
.k-grid .btn-plain:not(.sf-link):not(:disabled):not([disabled]):hover {
    text-decoration: underline;
}

/* .sf-link — emitted by SfButton.Link on every instance, so a Link reads as
   a hyperlink everywhere, not only inside a grid.

   Before bug32138 the blue lived only on the .k-grid rule, so the ~80 Links
   that happen to sit in a grid looked right while the ~16 outside one (list
   views, cards, student tiles) inherited body text colour and read as plain
   text — the Global Search results being the reported case.

   SPECIFICITY IS LOAD-BEARING. These selectors are deliberately (0,1,0) /
   (0,2,0) — the same weight as the .btn-plain rules above, which they beat
   on source order alone. That makes the blue a *default* that any
   caller-supplied colour overrides, rather than an override that silently
   wins. Do not add :not(:disabled) guards or extra compound classes to
   "make it stick": at (0,4,0) this rule clobbers
     • scoped .razor.css colours — .scheduled-course-section[b-xxx] is (0,2,0)
       and needs white-on-blue in StudentCourseRegistrationForm; losing it
       leaves blue text on a blue chip
     • descendant rules in app.css — .sf-student-account-header
       .sf-account-edit-icon (0,2,0) sets the accent tone on StudentAccount
   Keyed on .sf-link and NOT .btn-plain: SfButton.Close and
   SfButton.ChevronToggle share that foundation and must not turn blue. */
.sf-link {
    color: var(--sf-focus-ring-inner);
}
.sf-link:hover {
    color: var(--sf-focus-ring-inner);
    text-decoration: underline;
}

/* The pop-out (ShowPopout) is the only part of SfButton.Link that renders as
   an <a>, and the Kendo theme in studentfirst.css sets

       .k-grid a { color: inherit; text-decoration: none }        (0,1,1)

   That file loads AFTER this one, so it out-ranks the .sf-link default (0,1,0)
   and the pop-out icon rendered black in every grid cell while the label
   <button> beside it stayed blue — visible on /main/studentlist and
   /main/studentholdslist, which use <StudentLinkButton>. The theme has the
   same rule for .k-messagebox / .k-bubble / .k-chat-bubble anchors.

   (0,2,0) clears all of them. Safe at this weight because no caller class ever
   lands on this element: Link.razor builds the pop-out's class from its own
   tokens plus sf-link-popout and never splats the caller's Class onto it, so
   this cannot clobber a caller colour the way a broad rule would.

   :not(.sf-link--inherit) keeps InheritColor="true" working: that modifier is
   part of linkTokens, so it reaches the pop-out too, and without the guard this
   rule (declared later, same weight) would silently override the opt-out. */
.sf-link.sf-link-popout:not(.sf-link--inherit),
.sf-link.sf-link-popout:not(.sf-link--inherit):hover {
    color: var(--sf-focus-ring-inner);
}

/* .sf-link--inherit — emitted when a call site passes InheritColor="true".
   Cancels the blue so the link takes the colour of whatever it sits in, for a
   Link that reads as a heading or as part of already-coloured chrome (the
   student-name <h2> header). (0,2,0) beats the .sf-link default above while
   still losing to a caller's own scoped colour. */
.sf-link.sf-link--inherit,
.sf-link.sf-link--inherit:hover {
    color: inherit;
}

/* Disabled links stay muted. .btn-plain:disabled (0,2,0) above already beats
   the .sf-link default, but not .sf-link:hover — declared last so a disabled
   link stays muted even while hovered. */
.sf-link:disabled,
.sf-link[disabled],
.sf-link:disabled:hover,
.sf-link[disabled]:hover {
    color: var(--sf-text-muted);
    text-decoration: none;
}

/* SfButton.Link pop-out (ShowPopout) — a leading "open in new tab" anchor
   next to the label link. Absorbs the legacy LinkButton layout: the flex
   wrapper lets the label shrink and ellipsize inside a grid cell while the
   pop-out icon keeps its intrinsic size, and align-items:baseline lines the
   icon up with the text baseline. */
.sf-link-popout-wrap {
    display: inline-flex;
    align-items: baseline;
    max-width: 100%;
    min-width: 0;
}

.sf-link-popout {
    padding-right: 4px;
    flex-shrink: 0;
}

/* The label button (the <button>, distinct from the pop-out <a>) truncates
   with an ellipsis instead of forcing the wrapper wider than its cell. */
.sf-link-popout-wrap > button {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
}

/* ════════════════════════════════════════════════════════════════════
   SfButton.Grid.* — uniform 28×28 command-column buttons, plus the
   adjacent grid-cell padding and toolbar overflow tweaks they need.
   ════════════════════════════════════════════════════════════════════ */

/* Show button drop-shadows and focus rings inside grid toolbars.
   Telerik's default `.k-toolbar-items` overflow clips sf-btn-* shadows
   and the focus-clearance margin, so SfButton.Grid.* render flat and
   lose their focus indicator when keyboard-navigated. Scoped to
   .k-grid-toolbar so stand-alone Telerik toolbars elsewhere keep their
   default scroll-button affordance for overflowing content. */
.k-grid .k-grid-toolbar,
.k-grid .k-grid-toolbar .k-toolbar-items,
.k-grid .k-grid-toolbar .k-toolbar-items-scroll {
    overflow: visible !important;
}

/* Tighten command-cell horizontal padding when SfButton.Grid.* buttons
   are present. The buttons' own 4px focus-clearance margin already
   provides the visual breathing room that Telerik's default ~14px cell
   padding was supplying, so we can reclaim ~20px of column width and
   let narrower locked columns (e.g. 100px Actions) keep their buttons
   horizontal without wrapping. Scoped via :has() so command cells
   without our buttons keep Telerik's default padding. */
.k-grid .k-command-cell:has(.sf-btn-grid),
.k-grid .k-command-cell:has(.sf-btn-grid-aligned) {
    padding-inline: 10px !important;
    text-align: center !important;
}

/* Lighter sibling of sf-btn-grid for buttons that share the focus-
   clearance margin and the double-ring focus indicator but DON'T want
   the 28×28 icon-only footprint. SfButton.Grid.Custom uses this so it
   can render text + icon at the role class's natural sizing while
   still aligning vertically with the action-bound grid buttons
   (Save / Edit / Delete / etc.). */
.sf-btn-grid-aligned.k-button {
    margin: calc(var(--sf-focus-offset) + var(--sf-focus-inner-width)) !important;
}

.sf-btn-grid-aligned.sf-btn-grid-aligned.k-button:focus,
.sf-btn-grid-aligned.sf-btn-grid-aligned.k-button:focus-visible {
    outline: var(--sf-focus-inner-width) solid var(--sf-focus-ring-inner) !important;
    outline-offset: var(--sf-focus-offset) !important;
    box-shadow: 0 0 0 var(--sf-focus-width) var(--sf-focus-ring-outer) !important;
}

/* Restores the universal double-ring focus indicator (blue inner +
   white outer) on grid command buttons, overriding the role rules'
   colored single-ring treatment. Two reasons grid buttons need this:

     1. The 28×28 icon-only footprint is too small for a colored single
        ring to read well; the bright blue+white double ring is much
        more visible against any role color (red Delete, slate Save,
        gray Edit) and against any row background.

     2. Telerik renders grid command-column buttons with tabindex="-1"
        (Tab key skips them — keyboard nav goes through the grid's own
        cell traversal). Mouse clicks don't reliably trigger
        :focus-visible across browsers, so we match :focus too — that
        way the ring shows up on click, on keyboard arrow-nav, and on
        programmatic focus uniformly.

   Chained `.sf-btn-grid` for (0,3,1) specificity to beat role
   :focus-visible rules at (0,2,1). !important guards against Telerik's
   internal focus styling. */
.sf-btn-grid.sf-btn-grid.k-button:focus,
.sf-btn-grid.sf-btn-grid.k-button:focus-visible {
    outline: var(--sf-focus-inner-width) solid var(--sf-focus-ring-inner) !important;
    outline-offset: var(--sf-focus-offset) !important;
    box-shadow: 0 0 0 var(--sf-focus-width) var(--sf-focus-ring-outer) !important;
}

/* Selector chains `.sf-btn-grid` twice on purpose: when this class is
   composed alongside a role class (sf-btn-save, sf-btn-delete, etc.) the
   role rules also have specificity (0,2,0) and !important. Repeating the
   class here bumps us to (0,3,0) so sf-btn-grid's sizing always wins
   regardless of where the role rules sit in the cascade. */
.sf-btn-grid.sf-btn-grid.k-button {
    width: var(--sf-btn-size) !important;
    height: var(--sf-btn-size) !important;
    min-width: var(--sf-btn-size) !important;
    padding: 0 !important;
    /* Reserve space for the focus outline so it isn't clipped by parents
       with overflow: hidden (Telerik grid command cells). The outline
       extends `outline-offset + outline-width` = 2px + 2px = 4px outside
       the button edge; the box-shadow's 3px spread is smaller and within
       this margin. Computed via the focus-ring vars so future tweaks
       there propagate here automatically. */
    margin: calc(var(--sf-focus-offset) + var(--sf-focus-inner-width)) !important;
    /* IMPORTANT: do NOT add !important to `display`. Telerik hides
       grid command buttons by setting inline `style="display: none"`
       based on the row's edit state + ShowInEdit. An !important here
       wins over Telerik's inline style and forces every button to
       render in every mode. */
    display: inline-flex;
    align-items: center !important;
    justify-content: center !important;
    border-radius: 6px !important;
    flex-shrink: 0;
}

/* TelerikButton with Icon and no child text renders only the icon span and
   centers cleanly inside the 28×28 flex box. TelerikDropDownButton, however,
   still renders an empty .k-button-text span when DropDownButtonContent is
   omitted — that empty span eats flex space and pushes the icon off-center.
   Hide it so icon-only DropDownButtons match the SfButton.Grid family. */
.sf-btn-grid.k-button > .k-button-text:empty {
    display: none;
}

/* Margin spacer between adjacent buttons inside a grid toolbar. */
.k-grid .k-grid-toolbar .k-button + .k-button {
    margin-left: 4px;
}

/* SfButton.DropDown popup — double-hover fix (bug24030 item 10).
   Telerik leaves the .k-focus highlight on the last-interacted popup item, so
   mousing from item 1 to item 2 leaves BOTH looking active (1 keeps .k-focus,
   2 gets :hover). The popup is portaled to <body>, so this can't be scoped to
   the button's wrapper — instead it's conditioned tightly: it fires ONLY while
   the menu group is being hovered, and clears the stale focus paint from the
   item that is NOT the one under the cursor. Keyboard navigation (no :hover on
   the group) is untouched, so the .k-focus ring still shows for keyboard users.
   Both the .k-menu-item and .k-item spellings are covered so it holds across
   Telerik popup markup variants; if neither matches it is a harmless no-op. */
.k-popup .k-menu-group:hover .k-menu-item.k-focus:not(:hover),
.k-popup .k-menu-group:hover .k-item.k-focus:not(:hover) {
    background-color: transparent;
    box-shadow: none;
}

/* ════════════════════════════════════════════════════════════════════
   SfButton.Grid.ChevronToggle  →  .sf-chevron-toggle (+ .is-expanded)
   Composes onto sf-btn-grid + sf-btn-secondary; mirrors the
   .sf-nav__chevron treatment used by the main nav and the
   .k-panelbar-toggle::before rotation on the student enrollment
   header.

   Why the rotation targets the ::before pseudo-element (not the icon
   span): FontAwesome renders its glyph via .fa-chevron-right::before
   { content: "\f054" }, sitting baseline-aligned inside the span. The
   span itself is sized to the button's line box, not to the glyph —
   so the span's geometric center is several pixels off from the
   glyph's visual center. Rotating the span drags the offset glyph
   around in an arc and the chevron drifts up/right depending on
   angle. Rotating the ::before instead pivots the glyph in place,
   which is what .k-panelbar-toggle does and the same fix here.
   ════════════════════════════════════════════════════════════════════ */
.sf-chevron-toggle .k-button-icon::before,
.sf-chevron-toggle .k-icon::before {
    font-size: 1rem;
    display: inline-block;
    transition: transform 200ms ease;
}

.sf-chevron-toggle.is-expanded .k-button-icon::before,
.sf-chevron-toggle.is-expanded .k-icon::before {
    transform: rotate(90deg);
}

/* Standalone SfButton.ChevronToggle renders a raw <i class="sf-chevron-toggle__icon">
   (not Telerik's .k-button-icon). Rotate its ::before glyph the same way — see the
   note above on why the ::before, not the <i>, is the rotation target. */
.sf-chevron-toggle .sf-chevron-toggle__icon::before {
    display: inline-block;
    transition: transform 200ms ease;
}

.sf-chevron-toggle.is-expanded .sf-chevron-toggle__icon::before {
    transform: rotate(90deg);
}

.sf-chevron-toggle .sf-chevron-toggle__label {
    margin-left: 0.4rem;
}

/* ════════════════════════════════════════════════════════════════════
   SfButton.ButtonGroup  →  .sf-btn-group (parent only)
   Auto-applied by <SfButton.ButtonGroup.Group> via OnParametersSet.
   Children are <SfButton.ButtonGroup.Button> / .Toggle (rendered by
   Telerik as .k-buttons inside the group). Parent-driven descendant
   selectors so children stay free of role classes — no specificity
   fights between role rules and segmented-control rules.
   ════════════════════════════════════════════════════════════════════ */

/* Drop shadow on the parent so it traces the outer perimeter of the
   whole segmented control rather than each child individually (which
   would put the right-edge shadow of child N on top of child N+1).
   border-radius matches Telerik's default for .k-button-group .k-button
   (4px from the Kendo theme) so the shadow's rounded corners line up
   with the children's outer corners. */
.sf-btn-group {
    border-radius: 4px;
    box-shadow: var(--sf-shadow-md);
}

.sf-btn-group .k-button {
    /* Ghost baseline — matches the sf-btn-secondary palette */
    background-color: var(--sf-secondary-button-bg) !important;
    border-color: var(--sf-border-subtle) !important;
    color: var(--sf-secondary-button-text) !important;
    /* 20056 REQ-028: the style guide specifies DM Sans 600 for button labels;
       Telerik's theme leaves segmented-control children at the inherited 400,
       so text-bearing toggles read lighter than every other button. Scoped to
       the group rather than the whole SfButton family so this does not restyle
       every button in the portal. */
    font-weight: 600 !important;
    /* Use the WCAG-aligned interactive-target token (32px) rather than the
       compact --sf-btn-size — button groups appear most often inline with
       form fields, where the 32px height matches the surrounding text
       inputs and reads as a peer of those controls rather than a denser
       toolbar control. Icon-only toggles render as 32×32 squares; text
       and icon+text toggles grow horizontally with their content. */
    min-width: var(--sf-interactive-min) !important;
    min-height: var(--sf-interactive-min) !important;
    transition: background-color 200ms ease, color 200ms ease;
}

.sf-btn-group .k-button:hover:not(.k-disabled):not(.k-selected) {
    background-color: var(--sf-secondary-button-hover) !important;
}

.sf-btn-group .k-button.k-selected {
    /* Filled treatment one step up — slate-700 fill, white text — so the
       active toggle reads as the chosen segment. Border stays slate-500
       to keep the segmented-control gestalt. */
    background-color: var(--sf-color-dark) !important;
    border-color: var(--sf-border-subtle) !important;
    color: var(--sf-color-white) !important;
}

.sf-btn-group .k-button.k-disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Universal blue+white double-ring on focus — matches the rest of the
   SfButton family. Selector chained twice for (0,3,1) specificity to beat
   role rules that some legacy markup still carries on individual children. */
.sf-btn-group .k-button.k-button:focus,
.sf-btn-group .k-button.k-button:focus-visible {
    outline: var(--sf-focus-inner-width) solid var(--sf-focus-ring-inner) !important;
    outline-offset: var(--sf-focus-offset) !important;
    box-shadow: 0 0 0 var(--sf-focus-width) var(--sf-focus-ring-outer) !important;
}

/* ════════════════════════════════════════════════════════════════════
   Icon-tone helpers — apply alongside any role class to tint just the
   rendered icon span (.k-button-icon). Use sparingly; the role class
   still wins for text/border/background.
       <SfButton.Grid.Custom Class="sf-icon-tone-success" …>
   !important is required because role rules set color: … !important on
   the button, and the icon span inherits that color by default.
   ════════════════════════════════════════════════════════════════════ */

.sf-icon-tone-success.k-button .k-button-icon  { color: var(--sf-color-success) !important; }
.sf-icon-tone-danger.k-button   .k-button-icon { color: var(--sf-color-destructive) !important; }
.sf-icon-tone-warning.k-button  .k-button-icon { color: var(--sf-color-warning) !important; }
.sf-icon-tone-info.k-button     .k-button-icon { color: #1d4ed8 !important; } /* blue-700 */
.sf-icon-tone-darkblue.k-button .k-button-icon { color: darkblue !important; }
.sf-icon-tone-purple.k-button   .k-button-icon { color: #7c3aed !important; } /* violet-600 — CSV export, distinct from green Excel / red PDF */

/* SfButton.DropDownItem Tone=… — the same tones on a dropdown MENU ITEM
   (bug24030 item 10). The tone class lands on the item; its leading glyph is
   not a .k-button .k-button-icon but a menu-link icon, so target that. Covers
   the icon element across Telerik popup markup variants (.k-menu-link-icon /
   .k-icon / a bare FontAwesome <span>/<i>); non-matching selectors no-op. */
.sf-icon-tone-success .k-menu-link-icon,
.sf-icon-tone-success .k-icon,
.sf-icon-tone-success .k-menu-link > [class*="fa-"]  { color: var(--sf-color-success) !important; }
.sf-icon-tone-danger .k-menu-link-icon,
.sf-icon-tone-danger .k-icon,
.sf-icon-tone-danger .k-menu-link > [class*="fa-"]   { color: var(--sf-color-destructive) !important; }
.sf-icon-tone-warning .k-menu-link-icon,
.sf-icon-tone-warning .k-icon,
.sf-icon-tone-warning .k-menu-link > [class*="fa-"]  { color: var(--sf-color-warning) !important; }
.sf-icon-tone-info .k-menu-link-icon,
.sf-icon-tone-info .k-icon,
.sf-icon-tone-info .k-menu-link > [class*="fa-"]     { color: #1d4ed8 !important; }
.sf-icon-tone-darkblue .k-menu-link-icon,
.sf-icon-tone-darkblue .k-icon,
.sf-icon-tone-darkblue .k-menu-link > [class*="fa-"] { color: darkblue !important; }
.sf-icon-tone-purple .k-menu-link-icon,
.sf-icon-tone-purple .k-icon,
.sf-icon-tone-purple .k-menu-link > [class*="fa-"]   { color: #7c3aed !important; }

/* ════════════════════════════════════════════════════════════════════
   Help-icon tooltip trigger — bare <button> wrapping a fa-question-circle
   icon, anchored by a <TelerikTooltip TargetSelector=".tooltip-target" />.
   Strips all default <button> chrome so only the icon shows; cursor: help
   signals it's informational, not actionable.
   ════════════════════════════════════════════════════════════════════ */

.sf-tooltip-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    color: inherit;
    font: inherit;
    cursor: help;
    line-height: 1;
    vertical-align: middle;
    border-radius: 50%;
}
.sf-tooltip-btn:focus-visible {
    outline: var(--sf-focus-inner-width) solid var(--sf-focus-ring-inner);
    outline-offset: var(--sf-focus-offset);
    box-shadow: 0 0 0 var(--sf-focus-width) var(--sf-focus-ring-outer);
}

/* ════════════════════════════════════════════════════════════════════
   Course-category filter popup (StudentCourseRegistrationForm)
   ────────────────────────────────────────────────────────────────────
   TelerikPopup portals its content into a global k-animation-container
   at document root, so we can't scope these rules to the .razor.css
   bundle. The .course-cat-filter-popup class flows through Telerik's
   Class parameter onto the portaled wrapper.
   ════════════════════════════════════════════════════════════════════ */

.course-cat-filter-popup {
    background-color: var(--sf-bg-card);
    border: 1px solid var(--sf-border-subtle);
    border-radius: 6px;
    box-shadow: var(--sf-shadow-md);
    min-width: 220px;
}

.course-cat-filter-menu {
    display: flex;
    flex-direction: column;
    gap: 2px;
    outline: none;
}

.course-cat-filter-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 6px 10px;
    border-radius: 4px;
    margin: 0;
    cursor: pointer;
    color: var(--sf-text-primary);
    font-size: var(--sf-font-size-md);
    font-weight: 500;
    transition: background-color 120ms ease;
}

.course-cat-filter-item:hover {
    background-color: var(--sf-secondary-button-bg);
}

.course-cat-filter-icon {
    width: 18px;
    text-align: center;
    font-size: 14px;
}

.course-cat-filter-icon.cat-planned     { color: #1B696F; }
.course-cat-filter-icon.cat-required    { color: #b0493e; }
.course-cat-filter-icon.cat-recommended { color: #7fba00; }
.course-cat-filter-icon.cat-outside     { color: #F8C0B0; }

.course-cat-filter-label {
    flex: 1;
}

/* ════════════════════════════════════════════════════════════════════
   MultiColumnComboBox dropdown — horizontal scroll on narrow layouts
   ────────────────────────────────────────────────────────────────────
   A MultiColumnComboBox popup is sized to its input, so when the fixed
   column widths total more than the input the Code/Name columns get
   clipped with no way to scroll across. Two callers hit this:
     • the term picker (StudentCourseRegistrationForm), columns ~600px,
       only clipped once the layout goes narrow → applied when _isMobile;
     • the course search (CourseSelectorComponent), columns ~580px in a
       min(360px,100%) input → always clipped, so applied unconditionally.
   Applied via MultiColumnComboBoxPopupSettings.Class, which lands on the
   portaled .k-popup wrapper — hence here, not in scoped css.

   overflow-x on the popup root scrolls the column header and the rows as
   one unit (both are children of the popup, sized to the columns). If a
   future Telerik version gives the inner list its own horizontal scroller
   and the header stops tracking the rows, target that inner scroll element
   (.k-list-content / .k-table-list) here instead.
   ════════════════════════════════════════════════════════════════════ */

.sf-multicol-combo-popup-scroll {
    max-width: 95vw;
    overflow-x: auto;
}

/* ════════════════════════════════════════════════════════════════════
   Unsaved-changes prompt — dialog surface treatment
   ────────────────────────────────────────────────────────────────────
   SfConfirmDialog carries `sf-confirm-dialog` on every instance and adds
   whatever its caller passes as Class; SfUnsavedChangesGuard passes
   `sf-unsaved-changes-dialog`. The rule below is deliberately scoped to that
   second class rather than to every confirmation in the portal.

   The destructive button is NOT restyled here. It was briefly outlined rather
   than filled, on the reasoning that this prompt - unlike a delete - offers a
   safer answer, so a filled red "Leave without saving" would dress the lossy
   choice up as the recommended one. Ami's call on 9/10 (QA task 27979) is that
   it should read as the same red-filled button as every other destructive
   action in the portal, minus the trash icon, so the override is gone and
   SfConfirmDialog's SfButton.Destructive renders in the standard .sf-btn-delete
   treatment. The safe answer is still the one the dialog opens focused on -
   see the note in SfUnsavedChangesGuard - so the affordance survives the
   colour change. Only the surface radius is scoped here now.

   Not scoped to all dialogs: the radius belongs in the style guide for every
   dialog surface, but changing it here would restyle every confirmation and
   window in three portals, which is a separate decision.

   !important, matching the rest of this file — the Telerik theme ships its own
   .k-dialog rules and its load order relative to this stylesheet is not
   guaranteed across the three hosts.
   ════════════════════════════════════════════════════════════════════ */

/* Both forms of each selector on purpose: Telerik's Class lands on the dialog root
   for Dialog but on an inner element for some component versions, and which one it is
   here is not worth depending on. The :has() arm matches when the marker turns up
   inside instead; only one arm can match, so the pair is not double-applied. */

.k-dialog.sf-unsaved-changes-dialog,
.k-dialog:has(.sf-unsaved-changes-dialog) {
    border-radius: var(--sf-radius-md) !important;
    overflow: hidden !important; /* keeps the titlebar's square corners inside the rounded surface */
}

/* ── In-grid linked cell: value + pop-out on one line ──────────────────────
   A linked grid cell (REQ-006) renders two siblings - the value as a link,
   then the pop-out that opens the record in a new tab. Left as plain inline
   elements they break between each other, so in a 130px Student Number column
   the number fitted but the pop-out dropped onto a second line and doubled the
   row height. The Student Enrollment grid, which QA compared against, keeps
   both on one line (QA task 27979).

   A flex row instead: the value takes the space that is left and truncates
   with an ellipsis, and the pop-out never shrinks and never wraps. Truncating
   the value is what QA asked for - the column heading is untouched, and the
   full value stays available through the link's own title/aria text. */
.sf-grid-link-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.125rem;
    /* min-width: 0 on both the row and the value is what actually lets the
       value shrink - a flex item defaults to min-width: auto and refuses to go
       below its content width, which is how the pop-out got pushed out. */
    min-width: 0;
    max-width: 100%;
    vertical-align: middle;
}

.sf-grid-link-cell > .btn-plain,
.sf-grid-link-cell > .btn-link,
.sf-grid-link-cell > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sf-grid-link-cell > .sf-popout-link {
    flex: 0 0 auto;
}
