/* ==========================================================================
   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 a global icon swap left in that file never
   reaches an iframe. The help/info family lives here for that reason, and the
   Edit pencil was moved here from components.css for it too (QEN-8937, see the
   section at the end of this file). Still in components.css and therefore
   still NOT reaching iframes: the calendar trigger and the star marker.

   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;
}

/* ==========================================================================
   Edit pencil — global swap, MOVED HERE FROM components.css (QEN-8937)
   --------------------------------------------------------------------------
   Both the class-based (Img-Std-EditV2 / Img-Std-Edit + Disabled) and the
   src-based (edit.gif / edit.png) swaps. They were in components.css, which
   Blank.master never loads, so every iframe popup kept the legacy 15x15
   StdIcons.png pencil — reported on the Fleet List tab of CompanyInfoPopup.aspx
   (<asp:ImageButton ImageUrl="clearpixel.gif" class="Img-Std Img-Std-EditV2">),
   and the src-based comment below already listed CompanyLicense, another tab of
   that same popup. Moved rather than duplicated so there is one source of
   truth; Default.master.cs loads this file immediately after components.css,
   and the per-page `body.page-X` rules referenced below are more specific, so
   the cascade is unchanged for top-level pages.
   ========================================================================== */
/* ==========================================================================
   Edit-pencil icon — global Img-Std-EditV2 swap (refresh, all pages)
   --------------------------------------------------------------------------
   Main.css/MainWhiteout.css paint `.Img-Std-EditV2` with a 15×15 bitmap
   pencil from `/images/icons/StdIcons.png`. Inspections grid (grid.css §7),
   FleetManagement (fleet-management.css §6), Q88 Status (q88status.css §4a)
   and Officer Matrix Vessel (officer-matrix-vessel.css) already replace it
   per-page with a Lucide pencil glyph painted via CSS mask + currentColor.

   This rule applies the same swap globally under the refresh feature flag
   (`body.sidebar-nav`) so every remaining `Img-Std-EditV2` instance — admin
   pages, MooringArrangements, Milbros lists, InspectionContainer,
   ManageEmailPackage, UploadHVPQ, etc. — renders the modern pencil instead
   of the legacy sprite. The per-page rules above are more specific (scoped
   to body.page-X) and continue to win where they exist; this is the
   catch-all for everywhere else.

   Element forms covered:
     • <input type="image">           — asp:ImageButton + clearpixel.gif src
     • <img>                          — direct or rendered inside <a>
     • <a>:empty                      — HyperLink with no Text/children;
                                        sprite paints the anchor itself
     • <a>:has(> ins:only-child)      — LinkButton with empty <ins> spacer
     • <a>:has(> img:only-child)      — asp:HyperLink with ImageUrl set;
                                        renders <a><img src="clearpixel"/></a>;
                                        inner img is hidden below
   Anchors with content (LinkButton wrapping ImageManager etc.) are
   intentionally excluded — masking would hide their children. Those keep
   the legacy sprite until their host page gets a dedicated rule.
   ========================================================================== */
body.sidebar-nav input[type='image'].Img-Std-EditV2,
body.sidebar-nav img.Img-Std-EditV2,
body.sidebar-nav a.Img-Std-EditV2:empty,
body.sidebar-nav a.Img-Std-EditV2:has(> ins:only-child),
body.sidebar-nav a.Img-Std-EditV2:has(> img:only-child),
body.sidebar-nav input[type='image'].Img-Std-Edit,
body.sidebar-nav img.Img-Std-Edit,
body.sidebar-nav a.Img-Std-Edit:empty,
body.sidebar-nav a.Img-Std-Edit:has(> ins:only-child),
body.sidebar-nav a.Img-Std-Edit:has(> img:only-child) {
    width: 24px;
    height: 24px;
    padding: 4px;
    box-sizing: border-box;
    border: 1px solid transparent;
    border-radius: 6px;
    background-image: none !important;
    color: var(--q88-grid-muted-fg, #64748b);
    cursor: pointer;
    vertical-align: middle;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
    -webkit-mask: var(--icon-square-pen) no-repeat center / 16px 16px;
            mask: var(--icon-square-pen) no-repeat center / 16px 16px;
    background-color: currentColor;
}

/* `<asp:LinkButton>` controls (e.g. UDF edit pencil emitted by
   GenerateQuestionnaire.cs:3865 as `<a class="Img-Std Img-Std-EditV2 jqUDF">
   <ins>&nbsp;</ins></a>`) render an empty <ins> spacer so :empty doesn't
   match; the :has(> ins:only-child) branch above catches them, then this
   rule hides the spacer so the mask glyph isn't pushed off-center.
   `<asp:HyperLink ImageUrl="...">` controls (e.g. hlkViewComments in
   TerminalVettingReports.ascx) render `<a><img src="clearpixel.gif"/></a>`;
   hide the inner clearpixel for the same reason. */
body.sidebar-nav a.Img-Std-EditV2 > ins,
body.sidebar-nav a.Img-Std-EditV2 > img,
body.sidebar-nav a.Img-Std-Edit > ins,
body.sidebar-nav a.Img-Std-Edit > img {
    display: none !important;
}

body.sidebar-nav input[type='image'].Img-Std-EditV2:hover,
body.sidebar-nav img.Img-Std-EditV2:hover,
body.sidebar-nav a.Img-Std-EditV2:empty:hover,
body.sidebar-nav a.Img-Std-EditV2:has(> ins:only-child):hover,
body.sidebar-nav a.Img-Std-EditV2:has(> img:only-child):hover,
body.sidebar-nav input[type='image'].Img-Std-Edit:hover,
body.sidebar-nav img.Img-Std-Edit:hover,
body.sidebar-nav a.Img-Std-Edit:empty:hover,
body.sidebar-nav a.Img-Std-Edit:has(> ins:only-child):hover,
body.sidebar-nav a.Img-Std-Edit:has(> img:only-child):hover {
    color: var(--q88-grid-primary);
    border-color: var(--q88-grid-primary);
}

/* Disabled / read-only variants — same Lucide pencil glyph, dimmer, no
   pointer affordance. Covers `Img-Std-EditV2Disabled` (Milbros heavy
   user: LibraryNoteList, DocumentNoteList, CommodityContainerPriorCargo,
   CommodityContainerCoating) plus the older `Img-Std-EditDisabled`
   token (CertificateDocumentList, FleetReportList). Without this rule
   these still painted the 15×15 grayscale bitmap from StdIcons.png. */
body.sidebar-nav input[type='image'].Img-Std-EditV2Disabled,
body.sidebar-nav img.Img-Std-EditV2Disabled,
body.sidebar-nav a.Img-Std-EditV2Disabled:empty,
body.sidebar-nav a.Img-Std-EditV2Disabled:has(> ins:only-child),
body.sidebar-nav input[type='image'].Img-Std-EditDisabled,
body.sidebar-nav img.Img-Std-EditDisabled,
body.sidebar-nav a.Img-Std-EditDisabled:empty,
body.sidebar-nav a.Img-Std-EditDisabled:has(> ins:only-child) {
    width: 24px;
    height: 24px;
    padding: 4px;
    box-sizing: border-box;
    border: 1px solid transparent;
    border-radius: 6px;
    background-image: none !important;
    color: var(--q88-grid-muted-fg, #64748b);
    cursor: default;
    vertical-align: middle;
    opacity: 0.45;
    -webkit-mask: var(--icon-square-pen) no-repeat center / 16px 16px;
            mask: var(--icon-square-pen) no-repeat center / 16px 16px;
    background-color: currentColor;
}

body.sidebar-nav a.Img-Std-EditV2Disabled > ins,
body.sidebar-nav a.Img-Std-EditDisabled > ins {
    display: none !important;
}

/* ==========================================================================
   Edit-pencil icon — global src-based swap (refresh, all pages)
   --------------------------------------------------------------------------
   Catch-all for legacy edit icons emitted WITHOUT the `Img-Std-EditV2`
   class. ~30 ASCX/ASPX files plus codebehind sites still build
   `<asp:Image/ImageButton/HyperLink ImageUrl="~/images/edit.gif">`, raw
   `<img src="/images/icons/edit.png">`, etc. The V2 class rule above only
   matches markup that opted in via `CssClass`; this rule matches the
   legacy `src` URL directly so admin (Tabs, TabLayout, CompanyLicense),
   DesktopModules (Announcements, Contacts, Document, Events, QuickLinks,
   Links), Jotun (PRLSearch, EditPRLNotes), TerminalVetting reports,
   MessageReport, UserManagement, Approvals, ImageManager, ForumList,
   VariableGridQuestion and codebehind-built tank-plan / generated-
   questionnaire / question-settings pencils all render the modern
   Lucide pencil without per-control markup churn.

   Per-page rules with id/class selectors (e.g. questionnaire.css
   `body.page-questionnaire #tblQuestionnaire img[src$="…edit.png"]`)
   remain more specific and continue to win where they exist.

   Composite branded icons (`notes-Edit.gif`, `TVR-Edit.gif`) are
   intentionally excluded — they're not the bare-pencil glyph.
   ========================================================================== */
body.sidebar-nav img[src*='/edit.gif'],
body.sidebar-nav img[src*='/images/icons/edit.png'],
body.sidebar-nav img[src*='/images/icons/editDisabled.png'],
body.sidebar-nav input[type='image'][src*='/edit.gif'],
body.sidebar-nav input[type='image'][src*='/images/icons/edit.png'] {
    width: 24px;
    height: 24px;
    padding: 4px;
    box-sizing: border-box;
    border: 1px solid transparent;
    border-radius: 6px;
    background-image: none !important;
    color: var(--q88-grid-muted-fg, #64748b);
    cursor: pointer;
    vertical-align: middle;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
    -webkit-mask: var(--icon-square-pen) no-repeat center / 16px 16px;
            mask: var(--icon-square-pen) no-repeat center / 16px 16px;
    background-color: currentColor;
}

/* Disabled state — same glyph, dimmer, no pointer affordance. */
body.sidebar-nav img[src*='/images/icons/editDisabled.png'] {
    opacity: 0.45;
    cursor: default;
}

body.sidebar-nav img[src*='/edit.gif']:hover,
body.sidebar-nav img[src*='/images/icons/edit.png']:hover,
body.sidebar-nav input[type='image'][src*='/edit.gif']:hover,
body.sidebar-nav input[type='image'][src*='/images/icons/edit.png']:hover {
    color: var(--q88-grid-primary);
    border-color: var(--q88-grid-primary);
}
