/* ══ erp-tip.css — the one tooltip bubble for the whole admin ═════════════════
   Pairs with dashboard/js/erp-tip.js. Linked ONCE, from
   admin/layouts/common/header_script.blade.php, AFTER style.css — the kill
   switch below has to win the ::after fight with it.

   PORTED FROM THE ERP PROJECT (dashboard/css/pages/erp-admin.css), 2026-09-23.
   One difference: the ERP has a shared erp-admin.css where the --ui-* tokens
   are declared for every page. Here those tokens are declared per page
   (access-centre.css, admission-decisions.css, exam-desk.css,
   notification-access.css, seat-reconciliation.css, system-tasks.css), so a
   global stylesheet cannot rely on them being defined. Every var() below
   therefore carries a literal fallback, and the bubble looks the same on a
   page that declares no tokens at all.
   ═════════════════════════════════════════════════════════════════════════ */

/* ⚠️ THE OLD CSS TOOLTIP STANDS DOWN.
   style.css (~lines 79–130) drew a bubble for EVERY button[title] and
   a[title] with a ::after and a ::before arrow, INSIDE the element. Put one in
   a card or a scrolling table and it is clipped at that ancestor's edge — the
   "cut off at the left/right border" — and its z-index of 1000 loses to the
   header and sidebar (1027–1099) and to a full-screen card (99999), so it
   hides behind them too.

   erp-tip.js adds html.has-erp-tip as its first act, so the moment the engine
   is present those rules are switched off and the engine's own body-level
   bubble is the only one drawn. The style.css rules are left in place for a
   page that somehow renders without the script (a print, a mail preview);
   they are never the plan. */
html.has-erp-tip button[title]::after,
html.has-erp-tip a[title]::after,
html.has-erp-tip button[title]::before,
html.has-erp-tip a[title]::before { content: none; }

/* ── .ui-tip — an HTML tooltip that survives a scrolling container ─────────
   A ::after bubble is drawn INSIDE its element. Put that in a table wrapper
   with overflow-x: auto and the bubble is clipped at the wrapper's edge: it
   never appears at all, with no error and nothing to see.

   This is the other answer. ONE element lives at the end of <body>; it is
   refilled and re-placed from whichever target is hovered rather than
   duplicated per target. position: fixed takes it out of every overflow and
   every positioned ancestor, so the same markup works in a table cell, a card
   or a modal. pointer-events: none means it can never sit between the cursor
   and the thing underneath it.

   To use: put data-uitip="…" (and optionally data-uitip-note="…" for a quieter
   second line) on any element. title="…" on a button or a link is adopted
   automatically. Give the element an aria-label too — a tooltip is not an
   accessible name. */
.ui-tip {
    /* FIXED, not absolute. An absolutely-positioned tooltip is placed against
       its nearest POSITIONED ancestor, not the document — and an admin page
       has several. Fixed + viewport coordinates has no such dependency. */
    position: fixed;
    /* Above EVERY layout layer, by a margin. This portal's layers run to 1099
       (header, sidebar), select2's open dropdown is 5000 and a full-screen
       card is 99999 — a tooltip inside any of them was hidden at 1000. Only
       Toastr (999999) stays above, and a toast over a tooltip is the right
       order. Swal (1060) sits below but carries its own backdrop, so nothing
       under it can be hovered in the first place. */
    z-index: 100000;
    top: 0; left: 0;
    width: max-content;
    max-width: min(19rem, calc(100vw - 24px));
    padding: 8px 11px 9px;
    border-radius: 9px;
    background: var(--ui-ink, #2b2521);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.55;
    text-align: left;
    /* A tip written with a line break keeps it; one without wraps normally. */
    white-space: pre-line;
    overflow-wrap: anywhere;
    box-shadow: 0 8px 22px rgba(30, 35, 50, .22);
    opacity: 0;
    visibility: hidden;
    transform: translateY(3px);
    transition: opacity .12s ease, transform .12s ease, visibility .12s;
    pointer-events: none;
}
.ui-tip.is-on { opacity: 1; visibility: visible; transform: translateY(0); }

/* The quieter second line: a qualification, not a second sentence of equal
   weight. Hidden outright when the target carries no note, so the bubble
   never keeps an empty line from the last thing hovered. */
.ui-tip-note {
    display: block;
    margin-top: 3px;
    font-size: 10px;
    font-weight: 500;
    color: rgba(255, 255, 255, .72);
}
.ui-tip-note:empty { display: none; }

/* The arrow tracks the target even when the bubble has been clamped to the
   viewport edge, so it never points at the wrong thing. */
.ui-tip::after {
    content: '';
    position: absolute;
    left: var(--arrow, 50%);
    margin-left: -5px;
    border: 5px solid transparent;
    border-top-color: var(--ui-ink, #2b2521);
}
.ui-tip::after { bottom: -10px; }
.ui-tip.is-below::after { bottom: auto; top: -10px;
                          border-top-color: transparent; border-bottom-color: var(--ui-ink, #2b2521); }

/* A target that carries a tooltip is focusable, so it must show focus. */
[data-uitip]:focus-visible { outline: 2px solid var(--ui-maroon, #a6303a); outline-offset: 2px; }

/* ⚠️ THE HELP CURSOR IS FOR THINGS THAT ONLY EXPLAIN. A chip or an info dot
   that does nothing but carry a tooltip gets the question-mark cursor — that
   is what it means. A button, a link, a label or a form control that ALSO
   carries a tooltip is still a button: it keeps the hand. The engine adopts
   every .ui-act's title into data-uitip on first hover, so without this
   exclusion every icon button in the admin turned into a question mark the
   moment it was hovered (reported in the ERP, 2026-09-23). */
[data-uitip]:not(a):not(button):not(label):not(input):not(select):not(textarea):not([role="button"]):not(.ui-act):not(.ui-btn):not(.btn) { cursor: help; }

@media (prefers-reduced-motion: reduce) {
    .ui-tip { transition: none; transform: none; }
    .ui-tip.is-on { transform: none; }
}
