/* ==========================================================================
   icon-swaps.css — cross-context legacy → Lucide icon swaps
   --------------------------------------------------------------------------
   Loaded by BOTH Default.master.cs (top-level pages) AND Blank.master.cs
   (iframe popups), gated on EnableRefreshedFrontend + PortalId 0/1/2. This is
   the one place these swaps live, because the icons appear on iframe popups
   (EditQuestionAnswer, TerminalVettingReports, …) too, and Blank.master does
   NOT load components.css — so the other global icon swaps (Edit, calendar,
   star, in components.css) never reach iframes. The help/info family does,
   via this file.

   tokens.css (the --icon-* glyphs) and MainWhiteout.css (the legacy sprites)
   both load before this file in either master, so var(--icon-*) resolves and
   the !important declarations beat the single-class legacy rules.

   Two source shapes, two mechanisms:
     • transparent clearpixel sprite (Img-Std-Help/HelpSmall) → mask + token
       (recolourable; background-color supplies slate-500).
     • opaque raster gif (help.gif, info.gif) → `content: url(<inline SVG>)`
       — masking an opaque raster leaks its pixmap through (the edit.gif trap,
       DESIGN.md §32.5), so the image is REPLACED outright. A content-replaced
       image can't be recoloured by background-color, so slate #64748b is baked
       into the inline SVG (the one place the token isn't reused).
   ========================================================================== */

/* --- Help "?" sprite (Img-Std-Help 16 / Img-Std-HelpSmall 14) ------------- */
body.sidebar-nav img.Img-Std-Help,
body.sidebar-nav img.Img-Std-HelpSmall {
    background-image: none !important;     /* kill the StdIcons sprite */
    background-color: #64748b !important;  /* slate-500 */
    vertical-align: middle;
}
body.sidebar-nav img.Img-Std-Help {
    width: 16px !important;
    height: 16px !important;
    -webkit-mask: var(--icon-circle-help) no-repeat center / 16px 16px;
            mask: var(--icon-circle-help) no-repeat center / 16px 16px;
}
body.sidebar-nav img.Img-Std-HelpSmall {
    width: 14px !important;
    height: 14px !important;
    -webkit-mask: var(--icon-circle-help) no-repeat center / 14px 14px;
            mask: var(--icon-circle-help) no-repeat center / 14px 14px;
}

/* --- Raw help.gif raster (Approvals, Forum, ViewPositionList, Registration,
   TerminalVettingReports iframe, …) → slate-500 CircleHelp. Not gated on
   body.sidebar-nav — help.gif also renders on pre-auth / legacy pages that
   never get that class; the file's own load gate already bounds the match. --- */
img[src$='/help.gif'] {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'/><path d='M12 17h.01'/></svg>") !important;
    width: 16px !important;
    height: 16px !important;
    vertical-align: middle;
}

/* --- Raw info.gif raster (Milbros "Preview Commodity Summary", Jotun
   registration, VesselManagement) → slate-500 Lucide Info ("i" in a circle,
   = var(--icon-info)). Same content:url mechanism as help.gif (opaque raster).
   Native markup sizes it 13×13; render at 14px to match the HelpSmall family. */
img[src$='/info.gif'] {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='M12 16v-4'/><path d='M12 8h.01'/></svg>") !important;
    width: 14px !important;
    height: 14px !important;
    vertical-align: middle;
}

/* --- Legacy validation / warning triangle (alertVal.png / .gif + the sibling
   ValInvalid.png raster, opaque) → red Lucide TriangleAlert ------------------
   The dominant use is ASP.NET field validators
   (`<img class="ValImage" src="…/alertVal.png">` — "Required" / "Invalid"),
   so the error-red #dc2626 of the validation convention is baked in.
   ValInvalid.png is the same validator-error raster emitted as an `<img>` by
   the FileUploader invalid-file alert (fileuploader.js), InspectionVIQGroups
   "already exists", CustomFilter invalid, and the Officer Matrix Compliance
   Voyage-date "on or after" warning (OfficerMatrixCompliance.ascx) — it gets
   the identical red swap. NOTE: the `.ValTipInvalid span` RangeValidator sprite
   paints ValInvalid.png as a CSS *background* (not an `<img>`), so it is NOT
   matched here — officer-matrix-person.css keeps that one amber on purpose.
   `content:url` REPLACES the raster outright (masking an opaque raster leaks
   its pixmap — DESIGN.md §32.5); the underlying src/title is left intact so
   legacy validator tooltips still work. Not gated on body.sidebar-nav:
   alertVal also renders pre-auth (admin Signin IMO error) and on legacy admin
   pages that never get that class — the file's own load gate (refresh +
   PortalId 0/1/2) already bounds the match, same as the help/info rasters.

   ADVISORY-WARNING exceptions stay AMBER via more-specific page rules that win
   over this one: the Officer Matrix "officers updated" banner + "Missing Data"
   row (officer-matrix-vessel.css §6) and the OCIMF `statusIconAlertVal` dot
   (Q88Whiteout.css). createQuestionnaire / vesselCompare keep their red
   AlertCircle variant; inspection-container / customfilter already match this
   red TriangleAlert (their rules are now redundant but harmless). --- */
img[src*="alertVal" i],
img[src*="ValInvalid" i] {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23dc2626' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3'/><path d='M12 9v4'/><path d='M12 17h.01'/></svg>") !important;
    width: 16px !important;
    height: 16px !important;
    /* strip the deprecated yellow .ValImage box when the class sits on the img */
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
    vertical-align: middle !important;
}

/* When the yellow .ValImage box sits on a HOST (validator span) wrapping the
   alertVal img rather than on the img itself, neutralize the box too so the
   swapped Lucide icon stands alone. Scoped with :has() to hosts that actually
   contain an alertVal img — text-only .ValImage messages are untouched. */
.ValImage:has(img[src*="alertVal" i]),
.ValImage:has(img[src*="ValInvalid" i]) {
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
    text-transform: none !important;
}

/* --- Loading spinner raster (loading_small.gif, 30x30 — a spinning ship's
   helm/captain's-wheel icon, opaque raster) → Lucide LoaderCircle, spinning.
   Shared by every disconnected in-flight "loading…" placeholder still on the
   legacy gif: the generic "8th popup mechanism" placeholder
   (PopupGenerateGenericLoadingPopup, Scripts/script.js — covers every popup
   built on that mechanism: Milbros CommodityDetail attribute popups,
   BookingDetail Tank Information, Officer Matrix Rank History, Prior Cargo
   List, Cleaning Chemical Type, Coating Producer Notes, Company Comment,
   questionnaire status popup), plus standalone thumbnail/callback loaders
   (CertificateDocumentDetail.ascx/.js, LoadLineDetails.ascx,
   FromToCleaning.ascx, GridFilterMenu.ascx DevExpress popup). One global
   content:url() swap (opaque raster — masking would leak the pixmap, same
   reasoning as help.gif/info.gif/alertVal above) using the same glyph +
   spin animation already used for LoadingModal.ascx's #loadingIMG
   (loading-modal.css). @keyframes re-declared here rather than shared:
   Default.master.cs loads icon-swaps.css BEFORE loading-modal.css while
   Blank.master.cs loads them in the opposite order, so this file can't
   assume the other's keyframe is registered first (harmless if duplicated
   — last declaration of a given @keyframes name wins, same animation either
   way). Not gated on body.sidebar-nav: several of the above render inside
   iframes / pre-full-chrome contexts; the file's own load gate already
   bounds the match. --- */
@keyframes q88-spin {
    to { transform: rotate(360deg); }
}
img[src$="loading_small.gif" i] {
    content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%230f172a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 12a9 9 0 1 1-6.219-8.56'/></svg>") !important;
    width: 24px !important;
    height: 24px !important;
    vertical-align: middle;
    animation: q88-spin 0.8s linear infinite;
}
