/* ==========================================================================
   Terminal Vetting page (TerminalVetting.aspx → TerminalVettingReports.ascx)
   ----------------------------------------------------------------------------
   Scoped via `body.page-terminal-vetting`. The .ascx wraps every <asp:View>
   in a legacy <uc:ModuleTemplate> (modContainerStd / modInnerContainer /
   modTLeft / modTRight / modSub1 / modMain / modFooter2), and bodies are
   asp:Repeater / DataList rendering classic <table class="StdTable">,
   class="GridHeader", class="GridData" / "GridDataAlt", class="ColHeader",
   class="GridTable" — same family as vessel-management.css. We re-implement
   the modern visual language (white card, soft shadow, 12px radius,
   teal #0d9488 primary CTA, light grid header, hover rows) directly against
   those legacy class names. Tokens mirror grid.css so the page sits next to
   Inspections / Vessel Mgmt at a glance.

   The page exposes 5 multiview states which all reuse the same wrapper:
     viewReport1            — list + filter (default)
     viewPendingReport      — pending grid (StdTable + ColHeader)
     viewAddEditReport      — paired left/right form + category ratings repeater
     viewReportSearch       — search form + DataList results
     viewHelp               — read-only help text

   Rules are organised top-down through that wrapper, then per-view tweaks.
   ========================================================================== */

body.page-terminal-vetting {
    /* Tokens re-derived from Figma file oM4wJDLxiHlaKMCy6GvTXs (Q88 Account/Tools)
       node 24:7375 + 150:8392 via get_variable_defs, 2026-05-21.
       Source for each value annotated inline. */
    --q88-grid-fg: #000000;                /* tailwind-colors/base/black (title text) */
    --q88-grid-body-fg: var(--text-primary);           /* base/foreground (body text) */
    --q88-grid-muted: var(--surface-muted);             /* base/muted */
    --q88-grid-muted-fg: var(--text-muted);          /* base/muted-foreground */
    --q88-grid-placeholder: #737373;       /* placeholder text; no Figma token, kept from prior */
    --q88-grid-border: var(--border-default);            /* base/border + base/input + base/sidebar-border */
    --q88-grid-card: #ffffff;              /* base/card / base/background */
    --q88-grid-primary: var(--primary);           /* base/primary */
    --q88-grid-primary-hover: var(--button-primary-hover);     /* darker teal — no Figma token, conventional 1-step */
    --q88-grid-primary-fg: #eff6ff;        /* base/primary-foreground */
    --q88-grid-row-hover: var(--surface-card);         /* base/sidebar (lighter than base/muted) */
    --q88-grid-header-bg: var(--surface-muted);         /* base/muted — matches Column Header in grid */
    --q88-grid-content-band-bg: var(--surface-card);   /* matches Card Content body bg; lightest tier */
    --q88-grid-shadow-xs: 0 1px 2px 0 rgba(0,0,0,0.05);   /* shadow/xs */
    --q88-grid-shadow-sm: 0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px -1px rgba(0,0,0,0.1); /* shadow/sm */
    --q88-grid-radius: 12px;               /* border-radius/rounded-xl (card) */
    --q88-grid-radius-md: 8px;             /* border-radius/rounded-md (combobox/button) */
    --q88-grid-radius-sm: 6px;             /* border-radius/rounded-sm (content band) */
    --q88-grid-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* ==========================================================================
   1a. Card chrome override — re-derive every value from Figma node 150:8392
       (Card 📍). Phase 2 components.css applies default .q88-card chrome
       (radius 8, border #e5e5e5 0.8px, no shadow, padding 24 28). This file
       wraps in `<div class="q88-card tv-card-wrap">` so the `.tv-card-wrap`
       suffix lets us narrow-scope the override without touching the global
       Phase 2 token. Source: get_design_context for node 150:8392 returned
       `rounded-xl(12) + border 1px #e2e8f0 + shadow/sm + py-6 px-0`.
       To preserve the Figma "py-24 px-0 on card + px-24 inside each slot"
       inset model with minimal markup changes, we set 24px symmetric padding
       on the card itself (functionally equivalent — content lands at 24px
       from the card border either way). 1px border + #e2e8f0 + shadow/sm
       + 12px radius are the visible deltas. */
body.page-terminal-vetting .q88-card.tv-card-wrap {
    /* Figma card spec: rounded-xl (12) + 1px base/border + shadow/sm + py-6 (24)
       px-3-5 (14). Card horizontal padding is 14 (not 24 symmetric — that was a
       prior-pass simplification). Sections inside (header, Frame 37) carry
       their own px-6 (24) so visible content lands at card.left + 14 + 24 = 38.
       The 38-from-card-edge nesting is what positions title at 38 and the icon
       cluster's right edge at card.right - 38, both per Figma. */
    border: 1px solid var(--q88-grid-border) !important;
    border-radius: var(--q88-grid-radius) !important;
    box-shadow: var(--q88-grid-shadow-sm) !important;
    padding: 24px 14px !important;
    background-color: var(--q88-grid-card) !important;
}

/* ==========================================================================
   1. Module wrapper — flatten legacy ModuleTemplate chrome into a clean card.
   ========================================================================== */

body.page-terminal-vetting table.modContainerStd,
body.page-terminal-vetting table.modContainerLarge {
    /* Card chrome (bg / border / radius / shadow / margin) is supplied by
       the outer `<div class="q88-card tv-card-wrap">` wrapper in
       TerminalVettingReports.ascx. ModuleTemplate's Page_PreRender hardcodes
       `class="modContainerStd"` on its `<table id="divMod">`, so we can't
       attach .q88-card directly to the table — the wrapper div is the
       only safe insertion point. We retain table-specific declarations the
       inner layout depends on: fill the wrapper (width: 100%) and clamp
       intrinsic min-width so a wide descendant can't auto-grow past it. */
    font-family: var(--q88-grid-font);
    color: var(--q88-grid-fg);
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    min-width: 0;
    border-collapse: separate;
    border-spacing: 0;
    overflow: hidden;
}

body.page-terminal-vetting .modInnerContainer,
body.page-terminal-vetting .modInnerContainerIsAlert {
    /* Card now supplies 24px padding all around (see §1a) — modInnerContainer
       must therefore add ZERO extra inset, otherwise content lands at 44px
       from the card border instead of Figma's 24. Caught 2026-05-21 horizontal
       anchor probe: `title.left - card.left` = 45 (target 24). The prior
       `padding: 16px 20px 20px` was inherited brownfield from the legacy
       ModuleTemplate's chrome — incompatible with the new card model. */
    border: 0 !important;
    background: transparent;
    padding: 0;
}

body.page-terminal-vetting .modAboveLeft,
body.page-terminal-vetting .modAboveRight,
body.page-terminal-vetting .modBelowLeft,
body.page-terminal-vetting .modBelowRight {
    display: none;
}

/* ==========================================================================
   2. Title bar — navy strip out, single flex row with title + action pills.
   ========================================================================== */

body.page-terminal-vetting .modTitle {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: 24px;          /* icons are 24h; title text 18; min-height matches icon */
    width: 100%;
    box-sizing: border-box;    /* keep padding 0 24px inside the 100% width — don't overflow */
    background: transparent !important;
    background-image: none !important;
    overflow: visible;
    /* Header carries section padding px-6 (24) per Figma + pb-5 (20) bottom.
       Then gap-3-5 (14) separates Header from Frame 37 — we express that as
       margin-bottom 14. Total height = 24 (icon row) + 20 (pb-5) = 44 ✓ matches
       Figma header height. The 14 margin-bottom yields the gap to modSub1. */
    margin: 0 0 14px 0;
    padding: 0 24px 20px 24px;
    font-size: inherit;
    font-weight: inherit;
    color: var(--q88-grid-fg);
}

body.page-terminal-vetting .modTLeft,
body.page-terminal-vetting .modTRight {
    float: none !important;
    padding: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    background: transparent !important;
    color: var(--q88-grid-fg);
}

body.page-terminal-vetting .modTLeft {
    font-family: var(--q88-grid-font);
    font-size: 18px;
    font-weight: 600;
    color: var(--q88-grid-fg);   /* base/black #000 per text-[color:tailwind-colors/base/black] */
    line-height: 1;              /* Figma `leading-none` on 18px = 18px line-height */
    letter-spacing: 0;
    text-transform: none;
    /* The .ascx uses non-breaking spaces ("Terminal&nbsp;Vetting&nbsp;Reports")
       — that's fine inside a single line; we just keep it on the baseline. */
    white-space: nowrap;
}

body.page-terminal-vetting .modTRight {
    margin-left: auto;
    /* QEN-8704: TitleRight markup converted from 4 ghost-pill LinkButtons to
       Figma's icon header (CirclePlus + EllipsisVertical kebab) via .tv-actions
       wrapper. The wrapper handles flex layout + gap (spacing/3 = 12px between
       icons per get_design_context node 26:7456). Outer .modTRight just
       provides margin-left:auto to push the cluster to the card's right edge. */
}

/* MainWhiteout paints `.modTitle a` white. Repaint to page-content fg. */
body.page-terminal-vetting .modTRight a,
body.page-terminal-vetting .modTRight a:link,
body.page-terminal-vetting .modTRight a:visited,
body.page-terminal-vetting .modTRight a:hover {
    color: var(--q88-grid-fg);
    text-decoration: none;
}

/* Note (QEN-8704): the prior `.modTRight img { display: none }` and
   `.modTRight a > ins { display: none }` defensive rules were removed in
   this pass. Q88:LinkButton with `CssClass="tv-action-icon ..."` or
   `CssClass="tv-kebab-item"` no longer emits the legacy `<img class="clearpixel">`
   or `<ins>&nbsp;</ins>` siblings inside its rendered `<a>` — the rendered
   markup is bare `<a>Text</a>`. Inverse-coverage probe (Step 9) flagged
   both selectors as matching 0 elements after the markup conversion. */

/* ==========================================================================
   QEN-8704 / Figma node 26:7456 (Frame 45) — 60×24 cluster, gap-3 (12).
   Two icons per get_design_context: CirclePlus 24×24 + EllipsisVertical 24×24.
   Markup wraps Q88:LinkButton#lnkAddReport with `.tv-action-icon-add` (clipped
   text + mask-painted icon) and Search / Blank TVR / Pending Reports inside
   `.tv-kebab-menu` opened by an EllipsisVertical anchor. Postback handlers on
   the inner LinkButtons are unchanged.

   `.modTRight a` ghost-pill rule was removed in this commit — the new
   markup uses `.tv-action-icon` + `.tv-kebab-item` class hooks instead, and
   any direct `<a>` in `.modTRight` outside those two classes is no longer
   produced by the .ascx. The `.modTRight img` + `.modTRight a > ins` hide
   rules above (L184, L230) still apply — they strip the clearpixel `<img>`
   and `<ins>&nbsp;</ins>` that Q88:LinkButton renders inside its `<a>`. */

body.page-terminal-vetting .modTRight .tv-actions {
    display: inline-flex;
    align-items: center;
    gap: 12px;  /* spacing/3 — between CirclePlus and the kebab wrap */
}

/* Icon button base — used for both CirclePlus and EllipsisVertical.
   24×24 mask-painted glyph, no chrome. The Q88:LinkButton renders
   <a><img class="clearpixel"/><ins>&nbsp;</ins>Text</a>; the inner img/ins
   are hidden by .modTRight rules above, and Text is clipped via
   text-indent + overflow hidden + font-size:0. */
body.page-terminal-vetting .tv-action-icon {
    display: inline-block !important;
    width: 24px !important;
    height: 24px !important;
    padding: 0 !important;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background-color: var(--q88-grid-body-fg) !important;  /* base/foreground #0f172a */
    background-image: none !important;
    box-shadow: none !important;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 24px 24px;
    mask-size: 24px 24px;
    overflow: hidden;
    text-indent: -9999px;
    white-space: nowrap;
    text-decoration: none !important;
    cursor: pointer;
    line-height: 24px;
    font-size: 0;
    vertical-align: middle;
    transition: background-color 120ms ease;
}

body.page-terminal-vetting .tv-action-icon:hover,
body.page-terminal-vetting .tv-action-icon:focus-visible {
    background-color: var(--q88-grid-primary) !important;  /* teal #0d9488 */
    outline: none;
}

/* Lucide CirclePlus — node 51:20985.
   Inline SVG mask: circle + horizontal stroke + vertical stroke, stroke-width 2. */
body.page-terminal-vetting .tv-action-icon-add {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M8 12h8'/%3E%3Cpath d='M12 8v8'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M8 12h8'/%3E%3Cpath d='M12 8v8'/%3E%3C/svg%3E");
}

/* Lucide EllipsisVertical — node 47:20981. Three vertical dots. */
body.page-terminal-vetting .tv-action-icon-kebab {
    -webkit-mask-image: var(--icon-ellipsis-vertical);
    mask-image: var(--icon-ellipsis-vertical);
}

/* Kebab dropdown — Lucide-style menu. Card chrome, soft shadow, 8px radius. */
body.page-terminal-vetting .tv-kebab-wrap {
    position: relative;
    display: inline-block;
    line-height: 0;
}

body.page-terminal-vetting .tv-kebab-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 180px;
    padding: 4px 0;
    background: var(--q88-grid-card);
    border: 1px solid var(--q88-grid-border);
    border-radius: 8px;  /* rounded-md */
    box-shadow: var(--q88-grid-shadow-sm);
    z-index: 50;
    display: none;
}

body.page-terminal-vetting .tv-kebab-wrap.tv-kebab-open .tv-kebab-menu {
    display: block;
}

/* Menu items: text rows with hover state. They are Q88:LinkButton anchors so
   they post back to the original lnkEmailTVR_Click / lnkSearch_Click /
   lnkPendingReports_Click handlers unchanged. */
body.page-terminal-vetting .tv-kebab-menu a.tv-kebab-item {
    display: block !important;
    box-sizing: border-box;
    padding: 8px 14px !important;
    margin: 0 !important;
    width: 100%;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    background-image: none !important;
    box-shadow: none !important;
    font-family: var(--q88-grid-font);
    font-size: 14px !important;
    line-height: 20px !important;
    font-weight: 500 !important;
    color: var(--q88-grid-body-fg) !important;
    text-decoration: none !important;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}

body.page-terminal-vetting .tv-kebab-menu a.tv-kebab-item:hover,
body.page-terminal-vetting .tv-kebab-menu a.tv-kebab-item:focus-visible {
    background: var(--q88-grid-row-hover) !important;
    color: var(--q88-grid-body-fg) !important;
    outline: none;
}

/* ==========================================================================
   3. SubHeader1 (filter row) — modSub1 carries `background: #f8f8f8` by
      default. Strip the panel chrome and re-skin the inner StdTable.NoBorder
      as a flat filter row with 32px pills.

   trMembers (filter row) and trIntro (INTERTANKO welcome/agreement panel,
   §8) are SIBLING <tr>s of the SAME table.StdTable.NoBorder (.ascx SubHeader1
   markup) and trIntro's rows also collapse to a single td, so every rule
   below MUST scope through `tr[id$='_trMembers']` — bare `tr`/`td:nth-of-type`
   paths match trIntro's identically-shaped single-td rows too. Missing this
   scoping flexed the 10 <p> welcome paragraphs into a horizontal row (each
   became a flex item) and stripped the centered padding off the Proceed/
   checkbox row — reported as "the agreement page is broken" (QEN-8865).
   ========================================================================== */

body.page-terminal-vetting .modSub1 {
    /* Frame 37 (Card Content section per Figma). Carries section padding
       px-6 (24) L/R so its inner content lands at card.left + 14 + 24 = 38.
       position:relative anchors the absolutely-positioned btnShow (see below). */
    background: transparent !important;
    background-image: none !important;
    border: 0 !important;
    box-sizing: border-box;
    padding: 0 24px;
    margin: 0;
    position: relative;
}

/* Filter-row layout — the markup is a 1-row StdTable with 3 TDs (filter
   content / btnShow / hidden Download). Table auto-layout pushes btnShow far
   to the right when TD1 absorbs all available space. To match Figma's spec
   (button 8px after the 3rd combobox, then a flex-spacer absorbing the rest),
   we absolute-position btnShow inside modSub1 and collapse TD2/TD3 in the
   flow. TD1 fills the row. */

body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(1) {
    width: 100% !important;
    padding-top: 0 !important;
    padding-left: 0 !important;     /* Country: table sits flush with modSub1 contentBox.left */
    vertical-align: top !important;
}

body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(2) {
    /* TD2 holds btnShow. TD1 is width:100% so the table squeezes TD2 down to the
       button's natural width, parking Show at the row's right edge — aligned with
       Download and the right content edge. vertical-align:bottom drops it onto the
       dropdown line (TD1 stacks the View radios above the dropdowns). 12px gap from
       the 3rd dropdown. */
    width: 1% !important;
    padding: 0 0 0 12px !important;
    border: 0;
    vertical-align: bottom !important;
    white-space: nowrap;
    font-size: 0 !important;  /* collapse the trailing "&nbsp;&nbsp;" after btnShow (markup) so Show's right edge reaches the 1434 content edge; the button keeps its own 14px */
}

body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(3) {
    /* TD3 holds lbDownloadPDF. The code-behind makes that link Visible=true on
       the Summary / Low Rating views (TerminalVettingReports.ascx.cs:686,708),
       so DON'T hide the cell — that silently dropped the Download link in the
       refresh. Like TD2/btnShow, the link itself is absolute-positioned (see the
       §3 Download rule below), so collapse the cell to keep it out of the flow. */
    width: 0 !important;
    padding: 0 !important;
    border: 0;
}

/* btnShow flows in TD2 now (normal table flow, bottom-aligned to the dropdown
   line — see the TD2 rule above). The old `position:absolute; left:1023px` hack
   pinned the button to a fixed x that only lined up with the dropdowns + grid at
   ~1858px; at every narrower width it floated mid-row, short of the right edge
   (e.g. at 1536px it ended 46px before the card edge). Flowing it keeps it glued
   to the right of the (now full-width) dropdowns at any width. */
body.page-terminal-vetting .modSub1 a[id$='_btnShow'].LinkButton {
    position: static;
}

body.page-terminal-vetting .modSub1 table.StdTable.NoBorder {
    width: 100%;
    border: 0;
    border-collapse: separate;
    border-spacing: 0;
    background: transparent;
    table-layout: auto;
}

body.page-terminal-vetting .modSub1 table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] td {
    /* QEN-8704: "View:" + "Country:" labels — Figma uses Inter Medium 14/20
       color #1a1a1a (literal hex from get_design_context p#26:7463 and p#26:7467).
       Zero vertical padding — the filter-row inner controls (radio 16h, select
       36h) define the row height. Inline `padding: 3px` on the markup td would
       win on specificity, so `!important` here. */
    background: transparent !important;
    border: 0 !important;
    padding: 0 8px !important;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    font-weight: 500;
    color: #1a1a1a;
    vertical-align: middle;
    line-height: 20px;
}

/* Nested table TDs (Country: label + 3-select host) — zero padding so the
   row hits Figma's 36h target (was 48h with 6px vertical padding). Width
   collapses to natural so the 3 selects can be 300w each. */
body.page-terminal-vetting .modSub1 table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td > table td {
    padding: 0 !important;
    padding-right: 8px !important;  /* spacing/2 between Country: label and first select, and between selects */
    line-height: 36px;              /* selects 36h — vertical-align middle inside */
}

body.page-terminal-vetting .modSub1 table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td > table td:last-child {
    padding-right: 0 !important;
}

/* Stretch the 3 filter dropdowns to fill the row so the filter line spans the
   full card width (like the grid below) instead of three fixed 300px boxes that
   left Show floating with dead space on the right. CountryPortTerminal renders
   [Country: label | one cell holding all 3 selects inline w/ "*" validators]. */
body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(1) > table {
    width: 100%;
    table-layout: fixed;   /* breaks the auto-layout circular dep so the % selects below can actually expand */
}
body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(1) > table > tbody > tr > td:first-child {
    width: 72px;           /* "Country:" label column — shrink so the select cell gets all the rest */
    vertical-align: middle;
}
/* The select cell holds all 3 selects inline. Flex it so they fill the cell
   evenly at any width (table-layout:fixed above already fixed the column width,
   so flexing the cell is safe). */
body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(1) > table > tbody > tr > td:last-child {
    display: flex;
    align-items: center;
    gap: 11px;
    width: auto;
}
body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(1) > table select.NormalTextBox {
    flex: 1 1 0 !important;
    width: auto !important;
    min-width: 0 !important;
}
/* "*" required validators sit between the selects (ASP.NET RequiredFieldValidator,
   color:Red; visibility:hidden until a failed submit). Give them zero flex width
   so they don't add stray gaps between the dropdowns, but keep overflow visible
   so the red "*" can still render (overflowing) when validation fails. */
body.page-terminal-vetting .modSub1 > table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td:nth-of-type(1) > table > tbody > tr > td:last-child > span.Val {
    flex: 0 0 0;
    width: 0;
    overflow: visible;
    white-space: nowrap;
}

/* Vertically centre every child of the filter row inside the 32px line box. */
body.page-terminal-vetting .modSub1 select,
body.page-terminal-vetting .modSub1 input[type='text'],
body.page-terminal-vetting .modSub1 input[type='radio'],
body.page-terminal-vetting .modSub1 input[type='checkbox'],
body.page-terminal-vetting .modSub1 a.LinkButton,
body.page-terminal-vetting .modSub1 label,
body.page-terminal-vetting .modSub1 .FleetVessel {
    vertical-align: middle;
}

/* RadioButtonList — Figma renders each radio as a custom 16×16 circle: 1px
   #e2e8f0 border, white bg, full radius, 8×8 teal inner dot when checked.
   Source: get_design_context node 26:7464 (selected) + 26:7465 (unselected)
   + tokens (width/w-2 = 8 for dot size). Native browser radios are too small
   (13×13 default on Chrome/Windows) and accent-color doesn't change the chassis
   size or border — restyle from scratch via appearance:none.

   TWO radio groups share this skin:
     • rbType (All Reports / Own Fleet Only) — lives in the .modSub1 filter row.
     • rbView (Summary / Detail / Low Rating / Graph / Fleet) — the view switcher
       rendered INSIDE .modMain (id …_rbView_N, host …_div_AvgRatingViewLabel).
   The rbView set was previously uncovered (scope was .modSub1 only) so it fell
   back to the 13×13 native chassis on the text baseline — smaller and visibly
   lower than rbType. Both groups are now matched (QEN-8801).

   MEMORY: input[type="radio"]:checked + label is the correct selected-state
   selector for ASP RadioButtonList Flow layout. :has() does NOT work here
   because every input + label are siblings inside ONE outer span. */
body.page-terminal-vetting .modSub1 input[type='radio'] + label,
body.page-terminal-vetting .modMain input[type='radio'][id*='_rbView'] + label {
    color: var(--q88-grid-body-fg);  /* base/foreground #0f172a (NOT muted) */
    font-family: var(--q88-grid-font);
    font-size: 14px;
    font-weight: 500;
    line-height: 16px;  /* leading-none — radio label sits in a 16px line box */
    margin: 0 24px 0 12px;  /* spacing/3 (12) between circle and label; 24 between adjacent radios */
    vertical-align: middle;
}

/* Last label in the row doesn't need right-margin */
body.page-terminal-vetting .modSub1 #rbType label:last-of-type,
body.page-terminal-vetting .modSub1 [id$='_rbType'] label:last-of-type,
body.page-terminal-vetting .modMain [id$='_rbView'] label:last-of-type {
    margin-right: 0;
}

body.page-terminal-vetting .modSub1 input[type='radio'],
body.page-terminal-vetting .modMain input[type='radio'][id*='_rbView'] {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    width: 16px;
    height: 16px;
    margin: 0 0 0 4px;  /* 4px gap from preceding text (the "View:" word) */
    padding: 0;
    border: 1px solid var(--q88-grid-border);  /* #e2e8f0 */
    border-radius: 50%;
    background-color: var(--q88-grid-card);    /* #ffffff */
    box-shadow: var(--q88-grid-shadow-xs);     /* shadow/xs — matches unselected radio in design */
    cursor: pointer;
    vertical-align: middle;
    box-sizing: border-box;
    transition: border-color 120ms ease;
}

body.page-terminal-vetting .modSub1 input[type='radio']:checked,
body.page-terminal-vetting .modMain input[type='radio'][id*='_rbView']:checked {
    /* 8×8 (w-2) inner dot, base/primary teal #0d9488 — radial-gradient hard stop at 4px radius */
    background-image: radial-gradient(circle, var(--q88-grid-primary) 0 4px, transparent 4px);
    box-shadow: none;  /* selected variant in design has no extra shadow */
}

body.page-terminal-vetting .modSub1 input[type='radio']:focus-visible,
body.page-terminal-vetting .modMain input[type='radio'][id*='_rbView']:focus-visible {
    outline: 2px solid var(--q88-grid-primary);
    outline-offset: 2px;
}

/* All <select> elements in the filter row — 36px pill matching Figma's
   Combobox/Trigger spec (h-9 = 36px, gap-2 = 8px, px-4 py-2 = 16/8, rounded-md = 8,
   shadow/xs). Source: get_design_context for I150:8392;25831:122460;150:8387;150:8253
   (Combobox instance) — `h-[36px] px-[var(--spacing/4,16px)] py-[var(--spacing/2,8px)]
   rounded-[var(--border-radius/rounded-md,8px)] shadow-[var(--shadow/xs,...)]`. */
body.page-terminal-vetting .modSub1 select {
    /* Combobox per Figma node 26:7468 / 26:7469 / 26:7470 — get_design_context:
       h-9 (36) px-4 (16) py-2 (8) rounded-md (8) bg base/card + border 1px
       base/input + shadow/xs. Text Inter Medium 14/20 color base/foreground
       #0f172a. Chevron is `Icon / 24px / ChevronsUpDown` rendered at 16×16
       with opacity-50 (15:6997 documented as "vertical bidirectional up down
       double arrows"). Two-arrow glyph — single down-chevron was a prior-pass
       miss caught in this Figma re-derivation.

       `!important` on height/padding/shadow beats components.css Phase 2
       default `body.sidebar-nav select { height: 32px !important }`. */
    height: 36px !important;
    width: 300px;                /* Figma combobox spec: w-[300px] per node 26:7468/9/70 */
    min-width: 220px;            /* graceful fallback if viewport too narrow */
    max-width: 300px;
    /* Vertical padding trimmed 8→4: with box-sizing:border-box the 36px height
       minus 8/8 padding minus 1/1 border left only 18px content for a 20px
       line-height, clipping the option text (browsers top-bias select text, so
       it cut off at the bottom). 4/4 padding gives 26px content — text clears. */
    padding: 4px 36px 4px 16px !important;
    background-color: var(--q88-grid-card);
    border: 1px solid var(--q88-grid-border);
    border-radius: 8px;
    color: var(--q88-grid-body-fg);  /* base/foreground #0f172a (NOT #000) */
    font-family: var(--q88-grid-font);
    font-size: 14px;
    line-height: 20px;
    font-weight: 500;  /* Inter Medium per Figma */
    box-sizing: border-box;
    box-shadow: var(--q88-grid-shadow-xs);  /* shadow/xs — 0 1px 2px rgba(0,0,0,0.05) */
    outline: none;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    /* Lucide ChevronsUpDown — stroke #0f172a with alpha 80 (50%, 8-digit hex).
       Rendered at 16×16. `!important` required to beat components.css Phase 2
       `body.sidebar-nav select { background-image: ... }` which paints a
       single down-chevron in slate-600. Without !important, components.css
       wins despite our higher specificity (theirs is !important). */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230f172a' stroke-opacity='0.5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: calc(100% - 12px) 50% !important;
    background-size: 16px 16px !important;
    cursor: pointer;
}

body.page-terminal-vetting .modSub1 select:focus,
body.page-terminal-vetting .modSub1 input[type='text']:focus {
    border-color: var(--q88-grid-primary);
    outline: 2px solid var(--q88-grid-primary);
    outline-offset: -1px;
}

/* QEN-8704 / Figma Frame 37 (node 26:7461) — root frame is `flex-col
   gap-6 (24)` between view-row and filter-row. The markup separates them
   with a single `<br />` (~16px), leaving the actual gap at ~9px in the
   prior pass. Hide the <br /> (its only role is to start a new line) and
   set explicit margin-top on the CountryPortTerminal's outer table to
   land exactly at 24px. Source: figma-tree.md root gap declaration. */
body.page-terminal-vetting .modSub1 table.StdTable.NoBorder > tbody > tr > td > br {
    display: none;
}

body.page-terminal-vetting .modSub1 table.StdTable.NoBorder > tbody > tr[id$='_trMembers'] > td > table {
    margin-top: 24px;
}

/* "Show" LinkButton — the page's primary CTA. Figma "Default" button is
   `h-9 (36) + px-4 (16) + py-2 (8) + rounded-md (8) + gap-2 (8)` filled with
   base/primary teal, text Inter Medium 14/20 base/primary-foreground (#eff6ff).
   Source: get_design_context for I150:8392;25831:122460;150:8387;150:8256
   (Button instance) — `h-[36px] px-[16px] rounded-[8px] bg-base/primary`. */
body.page-terminal-vetting .modSub1 a[id$='_btnShow'].LinkButton {
    /* "Show" primary CTA per Figma node 26:7471 (Button) — bg base/primary
       teal, rounded-md (8), padding px-4 (16) py-2 (8), gap-2 (8), height 36,
       NO BORDER (background fill only — color-pick of pill edges in
       header.png shows uniform teal interior, no darker stripe at corner).
       Text Inter Medium 14/20 color base/primary-foreground #eff6ff. */
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: 8px;
    box-sizing: border-box;
    height: 36px;
    padding: 8px 16px !important;
    border-radius: 8px;
    background: var(--q88-grid-primary) !important;
    color: var(--q88-grid-primary-fg) !important;
    border: 0 !important;            /* no border per Figma */
    font-family: var(--q88-grid-font);
    font-size: 14px;
    font-weight: 500 !important;
    line-height: 20px;
    text-decoration: none !important;
    background-image: none !important;
    box-shadow: none !important;
    cursor: pointer;
    transition: background-color 120ms ease;
}

body.page-terminal-vetting .modSub1 a[id$='_btnShow'].LinkButton:hover,
body.page-terminal-vetting .modSub1 a[id$='_btnShow'].LinkButton:focus {
    background: var(--q88-grid-primary-hover) !important;
    color: var(--q88-grid-primary-fg) !important;
}

/* asp:LinkButton renders <ins>&nbsp;</ins> as a sibling before the visible
   text. In the inline-flex button with gap-2, the <ins> becomes a flex item
   plus the gap, shifting "Show" right of center. Hide the <ins> so the text
   centers correctly. */
body.page-terminal-vetting .modSub1 a[id$='_btnShow'].LinkButton > ins {
    display: none !important;
}

/* "Download" link (Font-Underline=true, lbDownloadPDF) — rendered by the
   code-behind on the Summary / Low Rating views. It can't share the dropdown row:
   the 3 fixed-300px filter selects + the pinned btnShow (left:1023) fill the row
   at common laptop widths (≤1536px → Show ends ~46px from the card edge), so a
   far-right Download on that line overlaps Show. Instead drop it onto its own line
   directly below the dropdown row (btnShow row bottom = top46 + 36 = 82), right-
   aligned. right:24px puts its right edge on modSub1's content edge (mirrors the
   24px left padding). Robust at every width. */
body.page-terminal-vetting .modSub1 a[id$='_lbDownloadPDF'] {
    position: absolute;
    top: 102px;   /* was 90: dropped 12px to give the shared radios+Download line top breathing room (see the rbView lift rule) */
    right: 24px;
    z-index: 1;
    color: var(--q88-grid-primary);
    font-size: 13px;
    font-weight: 500;
    text-decoration: underline;
}

/* Reserve room for that Download line so the absolutely-positioned link doesn't
   overlap the section below (Ports band). :has() scopes the extra bottom padding
   to the Summary / Low Rating views — the other views set lbDownloadPDF
   Visible=false, so ASP.NET renders no <a> and :has() won't match (no dead gap). */
body.page-terminal-vetting .modSub1:has(a[id$='_lbDownloadPDF']) {
    padding-bottom: 32px;
}

/* The narrative-row table inside trIntroButton (Proceed button + checkbox)
   needs its own pill treatment — see §8. */

/* "View: Summary / Detail / Low Rating / Graph / Fleet" view-switcher
   (div_AvgRatingViewLabel) is the first block of trAvgRating, which the
   code-behind renders BELOW trReportDetails (Ports) + trReportCount (the
   "# Reports / Loading / Discharging" stats band) whenever a search returns
   results.

   A prior pass (QEN-8801) lifted this row up by margin-top:-35px so it would
   sit level with the absolutely-positioned Download link on the filter line.
   That premise was wrong: Download (lbDownloadPDF) renders ONLY on the Summary /
   Low Rating views (ascx.cs:704,726) — and those are exactly the views where
   trReportCount is ALSO shown, so the stats band always sits directly above
   these radios. The -35px lift therefore dragged the radios ~11px UP INTO the
   stats band, colliding the "View:" row with the "# Reports…" line. (QEN-8865)

   The Detail / Fleet views never got the lift and already laid out correctly —
   the outer StdTable's 24px border-spacing opens a clean gap above the radios.
   Removing the lift makes Summary / Low Rating match them. Download stays on the
   filter line, right-aligned; it was never meant to share this row. No lift
   rule is emitted — the natural table flow is correct for all views. */

/* ==========================================================================
   4. Main panel — modMain hosts all the grids / repeaters / forms.
   ========================================================================== */

body.page-terminal-vetting .modMain {
    /* Match modSub1's 24px L/R inset so the grid band + rows share the same
       left/right verticals as the filter (was padding:0 → grid sat flush at the
       card edge 319-1458 while the filter was inset to 343-1434, so the grid read
       as "wider than everything else"). Now everything lives in one 343-1434 box. */
    padding: 0 24px !important;  /* !important: MainWhiteout forces .modMain padding:0 via ~17 !important rules */
    background: transparent;
}

/* First column carries the standard 16px cell inset like every other column
   (design.md §5.3/§5.4/§5.9 — header caption + data cell cellHorizontalPadding
   = 16). The earlier QEN-8704 `padding-left: 0` (flush at 343 to align with the
   filter labels) was dropped in QEN-8801 so the grid reads as a uniform inset
   grid; the 16px now comes from the base tr.Header / tr.GridData cell rules
   below. (Inner stats sub-tables keep their own 6px 12px padding via §5.) */

/* The Main of viewReport1 wraps the per-view repeaters in another
   table.StdTable.NoBorder — neutralise its borders / cellpadding. */
body.page-terminal-vetting .modMain > table.StdTable.NoBorder {
    width: 100%;
    border: 0;
    border-collapse: separate;
    border-spacing: 0;
    background: transparent;
}

body.page-terminal-vetting .modMain > table.StdTable.NoBorder > tbody > tr > td:not(.Header):not(.GridHeader):not(.ColHeader) {
    /* `:not(.Header)` etc. is required — without it, this selector's
       (0,3,6) specificity + !important beats every later .Header rule and
       silently wipes the muted band from trReportCount / trReportDetails /
       trAvgRating header cells. Caught 2026-05-21 during measurement pass
       on QEN-8704 — td.Header bg probed `rgba(0,0,0,0)` despite three
       later rules with !important explicitly setting it. */
    background: transparent !important;
    border: 0 !important;
    padding: 0;
}

/* ==========================================================================
   5. Repeater grids — class="GridTable" used by the category-rating /
      pending-report / low-rating / fleet repeaters. The Header rows carry
      class="Header" or class="GridHeader", and data rows class="GridData".
   ========================================================================== */

body.page-terminal-vetting table.GridTable {
    width: 100%;
    border: 0 !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
    background: transparent !important;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    color: var(--q88-grid-fg);
    margin: 4px 0 16px 0;
    border-radius: 8px;
    overflow: hidden;
}

body.page-terminal-vetting tr.Header > td,
body.page-terminal-vetting tr.GridHeader > td,
body.page-terminal-vetting tr.GridHeaderLight > td,
body.page-terminal-vetting tr.ColHeader > td,
body.page-terminal-vetting td.Header,
body.page-terminal-vetting td.GridHeader {
    /* MainWhiteout's `.Header` rule paints navy + white text. It targets the
       class as a stand-alone selector (no element prefix), so it matches BOTH
       `<tr class="Header">` (via the AvgRating repeater's <tr class="Header">)
       AND `<td class="Header">` (via trReportCount/trReportDetails which put
       the class directly on the td). We need both selectors here or the latter
       silently keeps MainWhiteout's navy chrome. Caught by visual probe on
       QEN-8704 baseline 2026-05-21 — the stats line read as a dark navy bar. */
    background-color: var(--q88-grid-header-bg) !important;
    background-image: none !important;
    color: var(--q88-grid-muted-fg) !important;
    font-family: var(--q88-grid-font);
    font-size: 12px !important;
    font-weight: 600 !important;
    line-height: 16px !important;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    text-align: left;
    padding: 16px !important;   /* design.md §5.3 — header row height 48 (12px font + 16px line-height + 16px×2 = 48; was 12px → 41) */
    border: 0 !important;
    border-bottom: 1px solid var(--q88-grid-border) !important;
    white-space: nowrap;
}

/* (Section-header first column — "EQUIPMENT", "TERMINAL PERSONNEL", … — now
   inherits the standard 16px left inset from the tr.Header cell rule above,
   per design.md §5.9 header caption indent. The QEN-8704 flush-left override
   was removed in QEN-8801; see the §4 note above.) */

/* The Header td hosts an INNER GridTable in some views (trReportCount /
   trReportDetails / trAvgRating). That inner table inherits MainWhiteout's
   class/font selectors. Reset cells so the inner stats grid reads as a
   muted band, not a navy strip. Source: bilateral inventory 2026-05-21 —
   Figma stats row Body uses bg #f8fafc, p-12, rounded-sm. */
body.page-terminal-vetting td.Header > table.GridTable,
body.page-terminal-vetting td.Header > table {
    background-color: transparent !important;
    border: 0 !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
}

body.page-terminal-vetting td.Header > table > tbody > tr > td,
body.page-terminal-vetting td.Header > table > tr > td {
    /* Lift the inner stats cells off MainWhiteout's `.Header td` cascade so
       they sit on the parent's lighter band, not a separate navy chrome. */
    background-color: transparent !important;
    background-image: none !important;
    color: var(--q88-grid-fg) !important;
    font-family: var(--q88-grid-font);
    font-size: 13px !important;
    font-weight: 500 !important;
    line-height: 20px !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
    padding: 6px 12px !important;
    border: 0 !important;
    white-space: nowrap;
}

/* trReportCount itself — the stats row in Figma sits on the muted band
   (bg #f8fafc, p-12, rounded-sm). Tie that look to the td.Header host. */
body.page-terminal-vetting [id$='_trReportCount'] > td.Header {
    background-color: var(--q88-grid-content-band-bg) !important;
    padding: 12px !important;
    border-radius: var(--q88-grid-radius-sm) !important;
    border: 0 !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    font-size: 14px !important;
}

/* Inter-section gaps inside modMain — Figma root frame is `flex-col gap-6`
   (24px) between Card Header / Card Content / Card Footer. trReportDetails
   sits at the bottom of Card Header (the filter "Terminals" header), so the
   24px gap belongs BELOW it. trReportCount maps to Card Content. trAvgRating
   maps to Card Footer. Caught 2026-05-21 vertical anchor pass — all three
   blocks rendered flush (0px gap) where Figma's root gap-6 token says 24.
   `padding-bottom` on the OUTER td so the gap sits between TRs without
   reflowing the inner grid's first-row spacing. */
body.page-terminal-vetting [id$='_trReportDetails'] > td,
body.page-terminal-vetting [id$='_trReportCount'] > td.Header {
    margin-bottom: 24px;
}

/* The above margin-bottom doesn't work on td (table-cell can't take margin).
   Use border-spacing on the parent table OR add a spacer. Cleanest: target
   the parent StdTable.NoBorder inside modMain with border-spacing: 0 24px,
   then strip the outer cellspacing. */
body.page-terminal-vetting .modMain > table.StdTable.NoBorder {
    border-spacing: 0 24px !important;
    border-collapse: separate !important;
}

/* Restore zero spacing for the innermost grids (Repeater HeaderTemplate
   produces nested tables that should NOT inherit the 24px row gap). */
body.page-terminal-vetting .modMain > table.StdTable.NoBorder table {
    border-spacing: 0 !important;
}

/* GridHeaderAlt — the "All ratings on a scale of 1-5" caption cell uses
   this class on the Add/Edit view. Keep it on-brand but understated. */
body.page-terminal-vetting tr > td.GridHeaderAlt,
body.page-terminal-vetting td.GridHeaderAlt {
    background-color: var(--q88-grid-header-bg) !important;
    background-image: none !important;
    color: var(--q88-grid-muted-fg) !important;
    font-family: var(--q88-grid-font);
    font-size: 12px !important;
    font-weight: 600 !important;
    line-height: 16px !important;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    padding: 10px 16px !important;
    border: 0 !important;
    border-top: 1px solid var(--q88-grid-border) !important;
    border-bottom: 1px solid var(--q88-grid-border) !important;
}

/* Category header rows on the Add/Edit view explicitly use the GridHeader
   class on a <tr>, but the inner repeater header in the list view is
   class="Header" — same rule via the selector above. The header cell needs
   to sit flush against the grid below so we strip the StdTable's default
   3px cellpadding. */
body.page-terminal-vetting tr.Header > td .GridTable,
body.page-terminal-vetting tr.GridHeader > td .GridTable {
    margin-top: 0;
}

/* Data rows — uniform white surface, hover highlight, 14px font. */
body.page-terminal-vetting tr.GridData,
body.page-terminal-vetting tr.GridDataAlt {
    background: var(--q88-grid-card) !important;
    transition: background-color 120ms ease;
}

body.page-terminal-vetting tr.GridData:hover,
body.page-terminal-vetting tr.GridDataAlt:hover {
    /* author !important beats the inline `onmouseover="HighLight(this,'')"`
       style.backgroundColor injection from /Scripts/Script.js. */
    background: var(--q88-grid-row-hover) !important;
}

body.page-terminal-vetting tr.GridData > td,
body.page-terminal-vetting tr.GridDataAlt > td {
    background: transparent;
    color: var(--q88-grid-fg);
    border: 0;
    border-bottom: 1px solid var(--q88-grid-border);
    padding: 8px 16px !important;   /* design.md §5.4 — data row 36 (8px×2 + 20px line-height; was 12px → 48, taller than the header) */
    vertical-align: top;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    line-height: 20px;
}

/* Last row in a repeater — drop the bottom border so it doesn't double up
   with the card's outer stroke. */
body.page-terminal-vetting table.GridTable > tbody > tr.GridData:last-child > td,
body.page-terminal-vetting table.GridTable > tbody > tr.GridDataAlt:last-child > td {
    border-bottom: 0;
}

/* ==========================================================================
   6. Pending Reports view — uses StdTable + ColHeader instead of GridTable.
   ========================================================================== */

body.page-terminal-vetting .modMain table.StdTable {
    width: 100%;
    border: 0;
    border-collapse: separate;
    border-spacing: 0;
    background: transparent;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    color: var(--q88-grid-fg);
}

body.page-terminal-vetting .modMain table.StdTable tr.ColHeader > td:first-child {
    padding-left: 16px !important;   /* design.md §5.3 — standard 16px cell inset (QEN-8801; was 0 to align with the filter labels) */
    border-top-left-radius: 8px;
}

body.page-terminal-vetting .modMain table.StdTable tr.ColHeader > td:last-child {
    padding-right: 20px !important;
    border-top-right-radius: 8px;
    text-align: center;
}

body.page-terminal-vetting .modMain table.StdTable tr.GridData > td:first-child,
body.page-terminal-vetting .modMain table.StdTable tr.GridDataAlt > td:first-child {
    padding-left: 16px !important;   /* design.md §5.4 — standard 16px cell inset (QEN-8801; was 0 to align with the filter labels) */
}

body.page-terminal-vetting .modMain table.StdTable tr.GridData > td:last-child,
body.page-terminal-vetting .modMain table.StdTable tr.GridDataAlt > td:last-child {
    padding-right: 20px !important;
}

/* ==========================================================================
   7. Add/Edit Report view (viewAddEditReport) — paired left/right tables
      hosting the report meta fields. We don't want a grid look here; treat
      these as light forms with proper label/control spacing.
   ========================================================================== */

body.page-terminal-vetting [id$='_viewAddEditReportLeftTable'],
body.page-terminal-vetting [id$='_viewAddEditReportRightTable'] {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0 8px;
    background: transparent;
}

body.page-terminal-vetting [id$='_viewAddEditReportLeftTable'] > tbody > tr > td:first-child,
body.page-terminal-vetting [id$='_viewAddEditReportRightTable'] > tbody > tr > td:first-child {
    color: var(--q88-grid-muted-fg);
    font-family: var(--q88-grid-font);
    font-size: 13px;
    font-weight: 500;
    width: 110px;
    padding: 0 12px 0 0;
    white-space: nowrap;
    vertical-align: middle;
    background: transparent !important;
}

body.page-terminal-vetting [id$='_viewAddEditReportLeftTable'] > tbody > tr > td,
body.page-terminal-vetting [id$='_viewAddEditReportRightTable'] > tbody > tr > td {
    background: transparent !important;
    border: 0 !important;
    padding: 0;
    font-family: var(--q88-grid-font);
    color: var(--q88-grid-fg);
    vertical-align: middle;
}

/* Form controls inside the Add/Edit pane — 32px pills like the filter row. */
body.page-terminal-vetting .modMain input[type='text']:not(.search-q88-quick),
body.page-terminal-vetting .modMain select,
body.page-terminal-vetting .modMain textarea {
    background-color: var(--q88-grid-card);
    border: 1px solid var(--q88-grid-border);
    border-radius: 8px;
    color: var(--q88-grid-fg);
    font-family: var(--q88-grid-font);
    font-size: 14px;
    line-height: 20px;
    font-weight: 400;
    box-sizing: border-box;
    box-shadow: none;
    outline: none;
}

body.page-terminal-vetting .modMain input[type='text']:not(.search-q88-quick),
body.page-terminal-vetting .modMain select {
    height: 32px;
    padding: 6px 12px;
}

body.page-terminal-vetting .modMain select {
    padding-right: 32px;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'><path d='M3 4.5L6 7.5L9 4.5' stroke='%23737373' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat;
    background-position: calc(100% - 12px) 50%;
    background-size: 12px 12px;
    cursor: pointer;
}

body.page-terminal-vetting .modMain textarea {
    padding: 8px 12px;
    min-height: 56px;
    resize: vertical;
}

body.page-terminal-vetting .modMain input[type='text']:focus,
body.page-terminal-vetting .modMain select:focus,
body.page-terminal-vetting .modMain textarea:focus {
    border-color: var(--q88-grid-primary);
    outline: 2px solid var(--q88-grid-primary);
    outline-offset: -1px;
}

/* Category rating sub-rows use inline bgcolor="#FFFFC0" on the terminal-
   comment row — that's the "yellow note" semantic. Tone it down so it
   reads as a soft callout rather than highlighter ink. */
body.page-terminal-vetting tr[bgcolor='#FFFFC0'],
body.page-terminal-vetting tr[bgcolor='#FFFFC0'] > td {
    background-color: #fefce8 !important;     /* tailwind yellow-50 */
}

/* The rating sub-grid uses a bgcolor="#C0C0C0" border-collapse table.
   Strip the grey background. */
body.page-terminal-vetting table[bgcolor='#C0C0C0'] {
    background-color: transparent !important;
    border-collapse: separate;
    border-spacing: 0;
}

/* ==========================================================================
   8. Intro / help narrative (viewReport1 trIntro + viewHelp) — long-form
      text needs comfortable reading width and proper paragraph rhythm.
   ========================================================================== */

body.page-terminal-vetting [id$='_trIntro'] > td,
body.page-terminal-vetting [id$='_viewHelp'] .modMain {
    font-family: var(--q88-grid-font);
    font-size: 14px;
    line-height: 22px;
    color: var(--q88-grid-fg);
    max-width: 920px;
    text-align: justify;
}

body.page-terminal-vetting [id$='_trIntro'] p,
body.page-terminal-vetting [id$='_viewHelp'] p {
    margin: 0 0 12px 0;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    line-height: 22px;
    text-align: justify;
}

body.page-terminal-vetting [id$='_trIntro'] ul,
body.page-terminal-vetting [id$='_viewHelp'] ul {
    margin: 8px 0 14px 22px;
    padding: 0;
}

body.page-terminal-vetting [id$='_trIntro'] li,
body.page-terminal-vetting [id$='_viewHelp'] li {
    margin: 0 0 6px 0;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    line-height: 22px;
}

/* Proceed CTA at the bottom of the intro — boxed teal pill. */
body.page-terminal-vetting [id$='_btnGoToTVR'].LinkButton {
    display: inline-flex !important;
    align-items: center;
    gap: 6px;
    box-sizing: border-box;
    height: 36px;
    padding: 0 16px !important;
    border-radius: 8px;
    background: var(--q88-grid-primary) !important;
    color: var(--q88-grid-primary-fg) !important;
    border: 1px solid var(--q88-grid-primary) !important;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    font-weight: 500 !important;
    line-height: 20px;
    text-decoration: none !important;
    background-image: none !important;
    box-shadow: none !important;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease;
}

body.page-terminal-vetting [id$='_btnGoToTVR'].LinkButton:hover {
    background: var(--q88-grid-primary-hover) !important;
    border-color: var(--q88-grid-primary-hover) !important;
}

/* ==========================================================================
   9. DataList of port/terminal tiles (viewReport1 trReportDetails) — the
      4-column repeater rendering port links with the green status sprite.
   ========================================================================== */

body.page-terminal-vetting [id$='_dlPortTerminalBerth'] > tbody > tr > td,
body.page-terminal-vetting [id$='_dlSearchResult'] > tbody > tr > td {
    padding: 6px 12px !important;
    border: 0 !important;
    background: transparent !important;
    vertical-align: top;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    line-height: 20px;
}

body.page-terminal-vetting [id$='_dlPortTerminalBerth'] a,
body.page-terminal-vetting [id$='_dlSearchResult'] a {
    color: var(--q88-grid-primary);
    text-decoration: none;
    font-weight: 500;
}

body.page-terminal-vetting [id$='_dlPortTerminalBerth'] a:hover,
body.page-terminal-vetting [id$='_dlSearchResult'] a:hover {
    text-decoration: underline;
    color: var(--q88-grid-primary-hover);
}

/* ==========================================================================
   10. Footer / action buttons (viewAddEditReport modFooter2) — Save / Cancel /
       Delete row. Same ghost-outline language as the title-bar pills, plus a
       primary teal pill for Save.
   ========================================================================== */

body.page-terminal-vetting .modFooter2 {
    background: transparent;
    border-top: 1px solid var(--q88-grid-border);
    margin-top: 16px;
    padding: 14px 4px 0;
    color: var(--q88-grid-muted-fg);
    font-family: var(--q88-grid-font);
    font-size: 13px;
    text-align: right;
}

body.page-terminal-vetting .modFooter2 a.LinkButton {
    display: inline-flex !important;
    align-items: center;
    gap: 4px;
    box-sizing: border-box;
    height: 32px;
    padding: 0 14px !important;
    border-radius: 8px;
    background: var(--q88-grid-card) !important;
    color: var(--q88-grid-fg) !important;
    border: 1px solid var(--q88-grid-border) !important;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    font-weight: 500 !important;
    line-height: 20px;
    text-decoration: none !important;
    background-image: none !important;
    box-shadow: none !important;
    cursor: pointer;
    margin-left: 6px;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

body.page-terminal-vetting .modFooter2 a.LinkButton:hover {
    background: var(--q88-grid-row-hover) !important;
    border-color: var(--q88-grid-primary) !important;
    color: var(--q88-grid-primary) !important;
}

/* Save = primary CTA. lnkSaveRating sits inside spanTVAdmin. */
body.page-terminal-vetting .modFooter2 a[id$='_lnkSaveRating'].LinkButton {
    background: var(--q88-grid-primary) !important;
    color: var(--q88-grid-primary-fg) !important;
    border-color: var(--q88-grid-primary) !important;
}

body.page-terminal-vetting .modFooter2 a[id$='_lnkSaveRating'].LinkButton:hover {
    background: var(--q88-grid-primary-hover) !important;
    border-color: var(--q88-grid-primary-hover) !important;
    color: var(--q88-grid-primary-fg) !important;
}

/* Delete = destructive ghost (red). */
body.page-terminal-vetting .modFooter2 a[id$='_lnkDeleteReport'].LinkButton:hover {
    background: rgba(220, 38, 38, 0.06) !important;
    border-color: var(--red-600) !important;
    color: var(--red-600) !important;
}

/* ==========================================================================
   11. Status icon sprite next to port links (.statusIcon / .statusIconGreen).
       Existing sprite stays — just give it a touch of breathing room.
   ========================================================================== */

body.page-terminal-vetting .statusIcon {
    margin-right: 6px;
    vertical-align: -2px;
}

/* ==========================================================================
   12. Search view (viewReportSearch) — the search filter strip on top.
   ========================================================================== */

body.page-terminal-vetting [id$='_cpViewReportSearch'] .modSub1 table {
    background: transparent;
}

body.page-terminal-vetting [id$='_cpViewReportSearch'] input[type='submit'].LinkButton,
body.page-terminal-vetting [id$='_cpViewReportSearch'] input[type='button'].LinkButton,
body.page-terminal-vetting [id$='_cpViewReportSearch'] button.LinkButton {
    display: inline-flex !important;
    align-items: center;
    box-sizing: border-box;
    height: 32px;
    padding: 0 14px !important;
    border-radius: 8px;
    background: var(--q88-grid-card) !important;
    color: var(--q88-grid-fg) !important;
    border: 1px solid var(--q88-grid-border) !important;
    font-family: var(--q88-grid-font);
    font-size: 14px;
    font-weight: 500 !important;
    line-height: 20px;
    text-decoration: none !important;
    background-image: none !important;
    box-shadow: none !important;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

body.page-terminal-vetting [id$='_btnReportSearch'] {
    background: var(--q88-grid-primary) !important;
    color: var(--q88-grid-primary-fg) !important;
    border-color: var(--q88-grid-primary) !important;
}

body.page-terminal-vetting [id$='_btnReportSearch']:hover {
    background: var(--q88-grid-primary-hover) !important;
    border-color: var(--q88-grid-primary-hover) !important;
}

/* ==========================================================================
   13. Pending count label (TitleRight on viewPendingReport) — keep it red
       semantic (q88-text-error class is already applied) but tighten line
       height so it sits next to the help icon cleanly.
   ========================================================================== */

body.page-terminal-vetting [id$='_lblPendingReportCount'] {
    font-size: 14px;
    font-weight: 600;
    line-height: 32px;
    padding: 0 6px;
}

/* ==========================================================================
   Refresh skin (body.sidebar-nav) — top section of Add/Edit Report.
   Give every input/select/calendar in BOTH the left and right tables a
   uniform width so each column reads as a clean stack. The calendar widget
   (`.qDiv:has(> input.qCal)`) is the visual reference; selects + text
   inputs match it. Right table contains CountryPortTerminal's 4 selects
   (Country / Port / Terminal / Berth). */
body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportLeftTable'],
body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportRightTable'] {
    --tv-input-width: 240px;
}

body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportLeftTable'] input[type='text']:not(.qCal),
body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportLeftTable'] select,
body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportLeftTable'] .qDiv:has(> input.qCal),
body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportRightTable'] input[type='text']:not(.qCal),
body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportRightTable'] select,
body.sidebar-nav.page-terminal-vetting [id$='_viewAddEditReportRightTable'] .qDiv:has(> input.qCal) {
    width: var(--tv-input-width);
    box-sizing: border-box;
}

/* Category-rating pair — the yellow "Terminal:" row has only one td (col 3)
   and no .GridData class, so the §"Data rows" rule (line 824) doesn't paint
   its bottom border. Question + Rating cells (rowspan=2) already carry
   border-bottom that lands at the bottom of the pair; add the same border
   to the yellow td so the right column aligns visually. */
body.sidebar-nav.page-terminal-vetting tr[bgcolor='#FFFFC0'] > td {
    border-bottom: 1px solid var(--q88-grid-border);
}

/* Drop the border-bottom on the User Comment cell (col 3 of the white row)
   — it sits mid-pair, between user + terminal comments. The bottom-of-pair
   line now comes from the yellow td above. Covers both .GridData AND
   .GridDataAlt — `rptRatings_ItemDataBound` (TerminalVettingReports.ascx.cs
   line 1578) swaps the class on alternating rows, so without GridDataAlt
   the fix only matched every other pair. */
body.sidebar-nav.page-terminal-vetting tr.GridData:has(+ tr[bgcolor='#FFFFC0']) > td:not([rowspan]),
body.sidebar-nav.page-terminal-vetting tr.GridDataAlt:has(+ tr[bgcolor='#FFFFC0']) > td:not([rowspan]) {
    border-bottom: 0;
}

/* Yellow "Terminal:" row bg — show ONLY when the textarea has rendered
   content. Otherwise the row stays transparent. The border-bottom from the
   rule above still applies regardless, so the row pair keeps its bottom
   stroke whether or not a terminal comment exists.
   `:empty` matches an empty textarea (no text-node child); the legacy
   §"Category rating sub-rows" rule at line 969 paints the bg unconditionally
   — these two rules below override it. */
body.sidebar-nav.page-terminal-vetting tr[bgcolor='#FFFFC0'],
body.sidebar-nav.page-terminal-vetting tr[bgcolor='#FFFFC0'] > td {
    background-color: transparent !important;
}
body.sidebar-nav.page-terminal-vetting tr[bgcolor='#FFFFC0']:has(textarea:not(:empty)),
body.sidebar-nav.page-terminal-vetting tr[bgcolor='#FFFFC0']:has(textarea:not(:empty)) > td {
    background-color: #fefce8 !important;
}
