/* ==========================================================================
   Q88 Questionnaire Form Refresh — questionnaire.css
   Spec: docs/plans/2026-04-30-questionnaire-form-refresh-spec.md
   Figma: pdLLyUsUxvfLP19TYN3oqw node 72:8685

   Scope:
     - Rules apply only when body has `.page-questionnaire` AND when the
       questionnaire form panel `#pnlQuestionnaires` is in the DOM (View phase).
     - Selector phase (CreateQuestionnaire.ascx, scoped under #modQSelect_divMod)
       is left to createQuestionnaire.css.

   Rollback:
     Set `<add key="EnableRefreshedFrontend" value="false"/>` in Web.config.
     The body class drops, this stylesheet stops loading, page reverts to legacy.
   ========================================================================== */

/* Sentinel (Phase A) — assertable via getComputedStyle(document.body)
   .getPropertyValue('--q88-questionnaire-css-loaded'). */
body.page-questionnaire {
    --q88-questionnaire-css-loaded: 1;
}

/* --------------------------------------------------------------------------
   Phase B — Card chrome scoping
   The .q88-card rule from components.css already paints bg/border/shadow.
   Per-page tweaks: confirm the panel renders full-bleed and break the DNN
   ContentPane width constraint (mirror of createQuestionnaire.css technique).
   -------------------------------------------------------------------------- */
body.page-questionnaire #pnlQuestionnaires.q88-card {
    /* The Phase A sentinel guarantees `body.page-questionnaire`; combining with
       the panel id keeps these rules from touching anything else on the page. */
    width: calc(100% - 96px);
    max-width: none;
    display: block;
}

/* Break the DNN content-pane width clamp so the card fills the area next to
   the sidebar. Same selector pattern as createQuestionnaire.css for the
   selector page; scoped by `body.page-questionnaire` so only the form view
   phase is affected. */
body.page-questionnaire:has(#pnlQuestionnaires) .ContentPane,
body.page-questionnaire:has(#pnlQuestionnaires) .ContentPaneBody,
body.page-questionnaire:has(#pnlQuestionnaires) #ctl00_cphMiddle,
body.page-questionnaire:has(#pnlQuestionnaires) #cphMiddle_ctl00_divWrap {
    width: 100% !important;
    max-width: none !important;
}

/* The branded bathymetric pattern (.q88-content::before — bathymetric-pattern.png,
   absolute inset:0, z:0) is the intended app background. The legacy ModuleTemplateV2
   wrappers around the card are OPAQUE and full-width, so they paint over it:
   .modV2Main (white) and .modMain (slate-50 #f8fafc). That hides the pattern both
   behind the card and in the ~48px margins beside it. Make those wrappers transparent
   so the pattern shows around the floating .q88-card (the card keeps its own white
   surface + border + shadow). View flow only (scoped via :has(#pnlQuestionnaires));
   !important defeats the legacy/global module-chrome background. */
body.page-questionnaire:has(#pnlQuestionnaires) .modV2Main,
body.page-questionnaire:has(#pnlQuestionnaires) .modMain {
    background-color: transparent !important;
    background-image: none !important;
}

/* Create flow (CreateQuestionnaire.ascx) — outer margin per Figma 72:8685 (Card
   inside Frame 3 at x=48, y=48 of the 1680x2201 content area = 48px gap from
   sidebar AND from the app header). Combined with .q88-card's white bg + border +
   padding, the panel becomes the questionnaire-form card surface. pnlViewQuestionnaire
   is the asp:Panel host for the Create flow only; ViewQuestionnaire88.ascx uses
   a different id (#pnlQuestionnaires) handled by the .q88-card rule above. */
body.page-questionnaire [id$="pnlViewQuestionnaire"] {
    margin: 48px;
}

/* --------------------------------------------------------------------------
   Phase B — TopHeader (Figma node 72:8948)
   Stacked title + subtitle on the left; search + filter dropdown + ellipsis
   overflow placeholder on the right. Replaces the legacy heavy-blue
   `Questionnaire: Q88 V6 ...` strip and light-blue INTERTANKO substrip.
   -------------------------------------------------------------------------- */
body.page-questionnaire .q88-tophdr {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 0;                                      /* Deliberate deviation: Figma 72:8948 is `padding: 0 16px` (T/B 0, L/R 16); .q88-card already provides 28L/28R, so we drop the L/R and keep 16 T/B for vertical breathing room. See spec §9.2 + Phase B plan line 532. */
    gap: 16px;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

body.page-questionnaire .q88-tophdr__left {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;                                         /* allows ellipsis to fire on title */
}

body.page-questionnaire .q88-tophdr__title {
    margin: 0;                                            /* h2 default margin reset */
    font-size: 20px;
    font-weight: 600;                                     /* Semi Bold */
    line-height: 24px;
    color: var(--foreground, #0f172a);
    letter-spacing: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

body.page-questionnaire .q88-tophdr__subtitle {
    font-size: 11px;
    font-weight: 400;
    line-height: 13px;
    color: var(--muted-foreground, #757575);
}

/* The optional `(Edit)` link — keep visible but render in subtitle weight so
   it doesn't compete with the title. Inline `ForeColor="Blue"` on the
   <asp:HyperLink> renders as `style="color:Blue;"` on the <a>; class CSS
   needs !important to override it. */
body.page-questionnaire .q88-tophdr__edit {
    font-size: 11px;
    color: var(--muted-foreground, #757575);
    margin-left: 4px;
}
body.page-questionnaire .q88-tophdr__edit a {
    color: inherit !important;
    text-decoration: underline;
}

body.page-questionnaire .q88-tophdr__right {
    display: flex;
    align-items: center;
    gap: 8px;                                             /* Tighter than Figma's gap:16 — chrome controls (search + dropdown) read crowded at 16; revisit with design if requested. */
    flex: 0 0 auto;
    flex-wrap: nowrap;
}

/* Search field label — keep small/inline. Existing TextBox renders inline. */
body.page-questionnaire .q88-tophdr__right > label,
body.page-questionnaire .q88-tophdr__right > span {
    font-size: 13px;
    color: var(--muted-foreground, #757575);
}
body.page-questionnaire .q88-tophdr__right input[type="text"] {
    height: 32px;
    padding: 4px 12px;
    border: 1px solid var(--input, #e2e8f0);
    border-radius: 8px;
    font-size: 14px;
    line-height: 20px;
    color: var(--foreground, #1e293b);
    background: var(--input-background, #ffffff);
    box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   Phase B — Filter dropdown skin (Figma node 72:8953 DropdownMenu)
   ddlChangeLastDays renders as <select>. Skin applies only when ASP.NET
   decides to show the control (codebehind toggles Visible).
   -------------------------------------------------------------------------- */
body.page-questionnaire .q88-tophdr__filter {
    height: 36px;
    min-width: 145px;                                     /* matches Figma 145w; native select grows for content */
    padding: 8px 16px;
    border: 1px solid var(--input, #e2e8f0);
    border-radius: 8px;
    background: var(--input-background, #ffffff);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;                                     /* Medium */
    line-height: 20px;                                    /* no-op on <select>; documents Figma intent — height is controlled by `height: 36px` */
    color: var(--foreground, #0f172a);
    box-sizing: border-box;
    cursor: pointer;
    /* Keep the native chevron — full custom chevron is deferred to a later
       ticket. The native chevron sits inside this padding box, which is
       visually close enough for Phase B. */
    appearance: auto;
}

body.page-questionnaire .q88-tophdr__filter:focus {
    outline: 2px solid var(--primary, #0d9488);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   Phase C — Section bands (Figma node 72:8959, "1. SECTION")
   Replaces legacy heavy mid-blue .Header1 strip with a muted card-tone band.
   - bg: var(--accent, #f1f5f9)
   - text: Inter Semi Bold 16px / leading-none, #000000
   - padding: 16px all sides (Figma 16/16/16/16; row reads as 48h with 16-tall
     text sitting at y:16 inside the frame)
   Legacy `Q88.css` declares `color: #FFFFFF !important` — we need !important
   to compete. Specificity (0,1,2,1) beats legacy (0,0,2,0) for everything else.
   Skin variants (Q88Whiteout.css, Baltic99.css, jotun.css, heidenreich.css,
   MilbrosWhiteout.css) all carry the same legacy declaration; the body-class
   scope wins against all of them.
   -------------------------------------------------------------------------- */
body.page-questionnaire #pnlQuestionnaires .StdTable .Header1,
body.page-questionnaire #pnlQuestionnaires .StdTable td.Header1,
body.page-questionnaire #pnlQuestionnaires .StdTable .Header1 td,
body.page-questionnaire #pnlQuestionnaires td.Header1,
body.page-questionnaire #pnlQuestionnaires .Header1 {
    background-color: var(--accent, #f1f5f9);
    background-image: none;                              /* defensive: legacy variants may inherit a sprite */
    color: #000000 !important;                            /* legacy uses !important — required to override */
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 16px;
    font-weight: 600;                                     /* Semi Bold per Figma */
    line-height: 1;                                       /* leading-none */
    padding: 16px;                                        /* 16 T/R/B/L per spec §9.3 */
    letter-spacing: 0;
    text-transform: none;                                 /* legacy doesn't uppercase, but defend against skin variants */
}

/* Edit / hyperlink children inside section bands need readable color too.
   Legacy `Q88.css:5-6` declares `.StdTable .Header1 a { color: #FFFFFF }` —
   would render white-on-light without this override. */
body.page-questionnaire #pnlQuestionnaires .StdTable .Header1 a,
body.page-questionnaire #pnlQuestionnaires .StdTable .Header1 a:link,
body.page-questionnaire #pnlQuestionnaires .StdTable .Header1 a:visited,
body.page-questionnaire #pnlQuestionnaires .Header1 a {
    color: #000000;
    text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Create-parity — major chapter bands (QEN-8776, 2026-06-08)
   "the page needs ... similar looks as the create questionnaire page ... sections
    should be styled the same. It's like Create.aspx but in read only mode."

   ViewShip renders the questionnaire's major chapters ("1. General Information",
   "2. CERTIFICATES", ...) as bare <tr> rows whose first cell is
   <td class="GridHeader">N.</td> followed by a colspan title cell
   (Templates/0/WebService/GetQ88*_v6.htm). There is NO `.Header1` class in this
   flow — the .Header1 rule above never matches on ViewShip, so the chapter bands
   fell through to the legacy .GridHeader guard (navy #dae3f2 + ColumnHeader.gif).

   Mirror the Create-flow qTypeH treatment (see line ~411): flat #f1f5f9 band,
   16px Semi Bold title. Selector `tr:not(.SubHeader2):has(> td.GridHeader:first-child)`
   isolates exactly the 12 chapter rows (verified live) and excludes the 29
   SubHeader2 sub-sections + the 28 other GridHeader cells (inline column headers).
   -------------------------------------------------------------------------- */
body.page-questionnaire #pnlQuestionnaires tr:not(.SubHeader2):has(> td.GridHeader:first-child) > td.GridHeader {
    background-color: var(--surface-muted);                            /* flat band — matches Create qTypeH (line ~412) */
    background-image: none;                              /* kill legacy ColumnHeader.gif sprite */
    color: #000000 !important;                            /* beat the .GridHeader guard's #000 !important */
    line-height: 24px;                                   /* unified 24px line-height — matches Create qTypeH */
    padding: 12px;
    border: none;                                        /* Create qTypeH drops the noisy legacy borders */
}

/* Section title typography — 16px Semi Bold on the number ("1.") + the colspan
   title ("General Information") only. Sibling column-header cells in multi-column
   section rows (e.g. CERTIFICATES → Issued / Last Annual / Expires) keep their
   14px column-label size so they stay aligned with the grid below. */
body.page-questionnaire #pnlQuestionnaires tr:not(.SubHeader2):has(> td.GridHeader:first-child) > td.GridHeader:first-child,
body.page-questionnaire #pnlQuestionnaires tr:not(.SubHeader2):has(> td.GridHeader:first-child) > td.GridHeader:first-child + td.GridHeader[colspan] {
    font-size: 16px;                                     /* --font-size-base — Create qTypeH (line ~416) */
    font-weight: 600;                                    /* Semi Bold */
}

/* --------------------------------------------------------------------------
   Phase C — Sub-section table-title bands (Figma node 72:9032,
   "6.1  Cargo Tank Coating (7.1.1)")
   Replaces legacy light-blue .SubHeader2 strip + ColumnHeader.gif gradient
   with a flat muted card-tone band.
   - bg: #f1f5f9 (hardcoded — var(--accent) is overridden to navy #2D3663 inside #pnlQuestionnaires; see amendment 2026-04-30)
   - bg-image: none — kills the legacy /images/page/ColumnHeader.gif sprite
   - text: Inter Bold (700) 14px / leading-none, #111e40 (navy hardcoded — NOT a token)
   - padding: 8 T/B + 16 L/R per spec §9.4 (h ≈ 36–44 with 14-tall text + 8+8 padding)
   Note: deferral — §9.4.1 group-header variant (8.1 VECS, transparent bg, no
   pencil, child indent guides) shares the .SubHeader2 class in legacy markup
   and is NOT addressed here. See Deferral note at top of plan.
   -------------------------------------------------------------------------- */
body.page-questionnaire #pnlQuestionnaires .StdTable .SubHeader2,
body.page-questionnaire #pnlQuestionnaires .StdTable td.SubHeader2,
body.page-questionnaire #pnlQuestionnaires .StdTable .SubHeader2 td,
body.page-questionnaire #pnlQuestionnaires td.SubHeader2,
body.page-questionnaire #pnlQuestionnaires .SubHeader2,
body.page-questionnaire #pnlQuestionnaires .SubHeader2 td.GridHeader,
body.page-questionnaire #pnlQuestionnaires .SubHeader2 td.gridheader {
    background-color: #f1f5f9;                           /* hardcoded — legacy stylesheet overrides --accent to #2D3663 (navy) inside #pnlQuestionnaires scope, so var() falls through to the wrong value. See plan amendment 2026-04-30 (cell-targeting fix). */
    background-image: none;                              /* kill legacy ColumnHeader.gif sprite */
    color: #111e40 !important;                            /* legacy uses !important on #000000 */
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    font-weight: 700;                                     /* Bold per Figma 72:9033 */
    line-height: 1;                                       /* leading-none */
    padding: 8px 16px;                                    /* 8 T/B, 16 L/R per spec §9.4 */
    letter-spacing: 0;
}

/* Edit / hyperlink children inside sub-section bands. Legacy `Q88.css:5-6`
   applies to `.SubHeader1 a` only (not SubHeader2), so legacy doesn't fight
   us here — but we set explicit color so the visual outcome is deterministic
   across all 7 skin variants (Q88, Q88Whiteout, Baltic99, jotun, heidenreich,
   milbros, MilbrosWhiteout). */
body.page-questionnaire #pnlQuestionnaires .StdTable .SubHeader2 a,
body.page-questionnaire #pnlQuestionnaires .StdTable .SubHeader2 a:link,
body.page-questionnaire #pnlQuestionnaires .StdTable .SubHeader2 a:visited,
body.page-questionnaire #pnlQuestionnaires .SubHeader2 a {
    color: #111e40;
    text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Phase C.5 — Sub-section group-header variant (Figma node 72:8990,
   "8.1 Vapor Emission Control System (VECS)" and structurally identical
   sub-sections like "Ownership and Operation", "Insurance", etc.)

   Marker emitted in static templates (Templates/0/WebService/GetQ88*_v6.htm)
   on every <tr> whose only child is <td class="GridHeader" colspan="7">.
   Detection rule: sub-section is a group-header iff followed by sub-numbered
   question rows (1.10, 1.11, ...) — see plan amendment 2026-04-30.

   Differences from Phase C's table-title styling:
   - bg: transparent (card surface bleeds through; not the muted #f1f5f9 band)
   - text color: #1a1a1a (vs table-title's #111e40 navy) — !important to
     override Phase C's color: #111e40 !important on the same selector chain
   - padding: T:12 / R:12 / B:10 / L:12 (asymmetric — vs table-title 8 T/B + 16 L/R)
   - font-size + font-weight + font-family inherited from Phase C
     (Inter Bold 14, leading-none) — DO NOT change. Spec §9.4.1 corrected
     2026-04-30: Inter Bold 700, was wrongly Regular 400.

   Selectors target the <td.GridHeader> cell because <tr> background is
   invisible behind the cell — same lesson learned from Phase C cell-targeting
   amendment 2026-04-30. Specificity (0,1,3,1) beats Phase C (0,1,2,1).
   -------------------------------------------------------------------------- */
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.GridHeader,
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.gridheader {
    background-color: #f1f5f9;                            /* Create-parity (2026-06-08): qTypeN sits on a #f1f5f9 band (was transparent per old Figma 72:8990) */
    background-image: none;                              /* defensive: kill any inherited sprite */
    color: #334155 !important;                            /* slate-700 — one step below the #000 chapter title; matches Create qTypeN (line ~2179) */
    font-weight: 600 !important;                          /* Semi Bold — matches Create qTypeN (was rendering 400 via the .GridHeader guard) */
    line-height: 1;
    padding: 12px 12px 12px 40px;                        /* L:40 leaves room for the ↳ icon at x:12 (16w + 12 gap) — matches Create qTypeN (line ~2175) */
    border-bottom: 1px solid #e5e5e5;                    /* matches Create qTypeN base/border */
    position: relative;                                  /* anchor for the ::before ↳ icon */
    /* font-family, font-size (14) inherited from Phase C */
}

/* ↳ CornerDownRight glyph at x:12 — mirrors Create qTypeN (line ~2186). Painted via
   currentColor mask so it inherits the slate-700 sub-header text color. */
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.GridHeader::before {
    content: "";
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
    height: 16px;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg 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'><polyline points='15 10 20 15 15 20'/><path d='M4 4v7a4 4 0 0 0 4 4h12'/></svg>") no-repeat center / 16px;
            mask: url("data:image/svg+xml;utf8,<svg 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'><polyline points='15 10 20 15 15 20'/><path d='M4 4v7a4 4 0 0 0 4 4h12'/></svg>") no-repeat center / 16px;
    pointer-events: none;
}

/* Hyperlink children in group-header: Phase C paints `#111e40`; override to
   match the group-header text color across all interactive states. */
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.GridHeader a,
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.GridHeader a:link,
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.GridHeader a:visited,
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.GridHeader a:hover,
body.page-questionnaire #pnlQuestionnaires .SubHeader2[data-q88-subsection="group"] td.GridHeader a:focus {
    color: #334155;                                      /* slate-700 — match the group-header text color (Create parity 2026-06-08) */
    text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Phase C.5 — VECS child-row indent guide (Figma node 72:9001 et al.)

   A 52w x 1h connector at x:12 y:23.5 inside each child row of a
   group-header. Visually anchors the child to its group parent.

   Selector strategy: general sibling combinator (~) reaches every <tr> that
   follows a group-header in the same parent. We restrict matches to rows
   carrying the `rattr` attribute — every question/answer row in the
   questionnaire template has `rattr="<question-number>"` (e.g. rattr="1.10"
   on the Registered-owner row). Bare section-header rows (the 12 chapter
   bands "1. GENERAL INFORMATION", "2. CERTIFICATES", etc.) and spacer rows
   carry NO rattr, so the selector cleanly excludes them.

   The ~ reach is unbounded (extends past later group-headers), but every
   matching question row IS a child of some group-header in the row
   sequence, so the rule lands appropriately. Inline-table data rows nested
   inside a separate <table> are NOT siblings of the outer <tr>, so the ~
   combinator can't reach them — Phase E inline tables remain untouched.

   Anchor needs position:relative on the <td:first-child> so the ::before
   absolutely-positioned guide lands inside.
   -------------------------------------------------------------------------- */
/* Phase C.5 child-row connector guide REMOVED for Create-parity (2026-06-08).
   Create's qTypeN hierarchy reads via the ↳ icon on the sub-header itself, not
   per-child 52px connector lines. Keeping both clashed visually with the new ↳
   band treatment, so the connector (formerly `~ tr[rattr] > td:first-child::before`)
   is dropped. The question-number cell no longer needs position:relative for it. */

/* --------------------------------------------------------------------------
   Phase C — Defensive guard: do NOT restyle .GridHeader.
   Legacy Q88.css lumps .SubHeader2, .Header2, .ColHeader, .GridHeader, and
   .GridHeaderFixed into a single rule. Our override deliberately targets
   `.SubHeader2` only, but skin variants and edge-case markup may apply both
   `.SubHeader2` AND `.GridHeader` to the same cell. This guard re-asserts the
   legacy GridHeader appearance for any cell that carries .GridHeader, so
   Phase E (inline cargo/ballast tables) inherits a clean baseline.
   -------------------------------------------------------------------------- */
body.page-questionnaire #pnlQuestionnaires .StdTable .GridHeader,
body.page-questionnaire #pnlQuestionnaires .StdTable td.GridHeader,
body.page-questionnaire #pnlQuestionnaires .StdTable .GridHeader td,
body.page-questionnaire #pnlQuestionnaires .StdTable .GridHeaderFixed,
body.page-questionnaire #pnlQuestionnaires .StdTable td.GridHeaderFixed {
    background-color: #dae3f2;                            /* legacy value preserved verbatim */
    background-image: url("/images/page/ColumnHeader.gif");
    background-position: center;
    background-repeat: repeat-x;
    color: #000000 !important;
    font-weight: bold;
    /* font-size + family inherit from .StdTable / global — do not lock here so
       Phase E can re-skin without fighting Phase C. */
}

/* --------------------------------------------------------------------------
   Phase C (dual-flow extension) — Section bands on CreateQuestionnaire.ascx
   The Create.aspx?c=1 → "Create" flow renders the questionnaire form via
   CreateQuestionnaire.ascx (panel pnlViewQuestionnaire), NOT
   ViewQuestionnaire88.ascx. Both controls coexist on Create.aspx; only one
   panel is visible at a time (Default.Master.cs:415-421). Section header
   rows are emitted at CreateQuestionnaire.ascx.cs:2244-2248 with classes:
       <tr class="qTypeH darkBlueBackground whiteText textDecorationNone">
   So the rules above (targeting .Header1 / #pnlQuestionnaires) leave this
   flow untouched. This block mirrors the .Header1 visual treatment using
   the qTypeH selector inside #tblQuestionnaire (ClientIDMode="Static" on
   CreateQuestionnaire.ascx:760, so the id is stable across postbacks).

   Selector strategy:
   - Scope by #tblQuestionnaire (stable id) so we never touch other tables
     that might happen to use class="qTypeH".
   - Apply at td level — Main.css:1739 sets td-level background and padding,
     and the .darkBlueBackground utility paints at tr level. Painting at td
     level wins both visually and by specificity.
   - !important is required, not optional. .darkBlueBackground (Q88Whiteout.css:270)
     uses `background-color: var(--brand-accent) !important`, and .whiteText
     (MainWhiteout.css:3597) uses `color: var(--text-on-brand) !important`.
     Specificity alone cannot beat !important.

   Note: there is no SubHeader2 analogue in this flow. qTypeN is a regular
   question row, qTypeI is an info row — neither is a sub-section band.
   The Figma sub-section treatment is a ViewQuestionnaire88-only concern.
   -------------------------------------------------------------------------- */
/* Specificity note: the data-row rule `tr:has(.qN) > td` (line 539) ties on
   specificity with `tr.qTypeH td` and appears later in the file, so without
   help it wins for `font-size`/`padding`/`font-family`. qTypeH section bands
   *also* contain `.qN` (the section number), so they get pulled into the
   data-row scope too. We chain `.qTypeH.qTypeH` to bump specificity by one
   class (0,1,3,2 vs 0,1,2,2) and use `!important` on bg/color to defeat the
   `.darkBlueBackground` / `.whiteText` utility classes (Q88Whiteout/MainWhiteout). */
body.page-questionnaire #tblQuestionnaire tr.qTypeH.qTypeH > td {
    background-color: #f1f5f9 !important;                 /* hardcoded — `--accent` resolves to navy #2D3663; same trap as line 222 */
    background-image: none !important;                    /* override .darkBlueBackground gradient if any */
    color: #000000 !important;                            /* override .whiteText !important */
    font-family: var(--raw-font-family-modern);
    font-size: var(--font-size-base);                     /* Questionnaire section header — 16px Semi Bold */
    font-weight: var(--font-weight-semibold);
    line-height: var(--raw-space-12);                     /* unified 24px line-height across all td */
    letter-spacing: 0;
    text-transform: none;
    padding: var(--raw-space-6);                          /* unified 12px padding across all td */
    border-top: none;
    border-bottom: none;                                  /* Main.css:1739 1px e7e7e7 borders read noisy on the new band */
}

/* Hyperlink children inside qTypeH section bands. Legacy markup includes a
   `textDecorationNone` utility on the tr — our rule restores underline so
   links read as links, mirroring the .Header1 a treatment above. */
body.page-questionnaire #tblQuestionnaire tr.qTypeH.qTypeH a,
body.page-questionnaire #tblQuestionnaire tr.qTypeH.qTypeH a:link,
body.page-questionnaire #tblQuestionnaire tr.qTypeH.qTypeH a:visited {
    color: #000000 !important;                            /* defends against `.whiteText a` skin variants */
    text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Phase D — View-flow answer-cell lane (Figma node 72:8965)

   The View flow's static .htm template renders answers as text inside
   <td class="GridData Answer"> cells. There are no <input> / <select>
   / <textarea> elements — substitution is text-only via [D:ID]. So the
   "input lane" here is a visual treatment of the answer text cell:
   right-anchored, Inter 14 / leading-20 / #1e293b, padding L/R 12.

   We do NOT paint a white border or radius on these cells in View flow:
   they're text outputs, not editable inputs, and adding a "fake input"
   visual treatment would mislead users into thinking they can click to
   edit. The card-surface bg is enough.
   -------------------------------------------------------------------------- */
body.page-questionnaire #pnlQuestionnaires .StdTable td.GridData.Answer,
body.page-questionnaire #pnlQuestionnaires td.GridData.Answer {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    font-weight: 400;                                     /* Regular per Figma 72:8965 inner text */
    line-height: 20px;
    color: var(--foreground, #1e293b);                    /* base/accent-foreground per spec §9.5.1 */
    padding: 8px 12px;                                    /* matches Figma px:12, slight T/B compression for read-only */
    text-align: right;                                    /* right-anchored answer per Figma right-edge alignment */
    vertical-align: top;                                  /* QEN-8831: number/question/answer share the row's top edge (production parity, canvas F0BB0KDFG66) */
}

/* QEN-8831 cascade trap: on a published vessel the ENTIRE V6 grid renders
   inside one <table class="sTbl"> (not just the pre-publish basic-info card).
   The sTbl label-cell rule below — `table.sTbl td:not(.answer)` (spec 1,3,3) —
   matches the V6 answer cell too (it's uppercase `.Answer`, has no lowercase
   `.answer`), so it out-specifies the answer rule above (1,3,2) and forced the
   answer back to vertical-align:middle. The number (1,4,2) and question (1,5,2)
   cells already out-specify it; only the answer loses. Re-assert top with the
   sTbl scope (1,4,3) so all three columns share the row's top edge. */
body.page-questionnaire #pnlQuestionnaires table.sTbl td.GridData.Answer {
    vertical-align: top;
}

/* Question number cell (1st column) — 36px wide, muted gray text, regular
   weight per spec §9.5.1 ("number" Inter Regular 14, leading-none, #4d4d4d). */
body.page-questionnaire #pnlQuestionnaires .StdTable td.GridData.VBorderRight:first-child,
body.page-questionnaire #pnlQuestionnaires td.GridData.VBorderRight:first-child {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    font-weight: 400;
    line-height: 1;                                       /* leading-none per spec */
    color: var(--muted-foreground, #4d4d4d);
    padding: 12px;
    width: 48px;                                          /* approx Figma w:36 + breathing room */
    vertical-align: top;                                  /* QEN-8831: number sits at the row's top edge (production parity) */
    white-space: nowrap;
}

/* Question label cell (2nd column, the long colspan one) — flex-1
   equivalent: Inter Regular 14, leading-20, #262626 per spec §9.5.1
   "question" Inter Regular 14, leading-none, #262626. */
body.page-questionnaire #pnlQuestionnaires .StdTable td.GridData.VBorderRight:not(:first-child):not(.Answer),
body.page-questionnaire #pnlQuestionnaires td.GridData.VBorderRight:not(:first-child):not(.Answer) {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;                                    /* leading-normal — labels often wrap */
    color: var(--foreground, #262626);
    padding: 12px;
    vertical-align: top;                                  /* QEN-8831: question label sits at the row's top edge (production parity) */
}

/* Row separator: 1px var(--border) between rows. Legacy markup paints
   `border-bottom` via a per-cell rule (.GridData td bottom border) —
   we re-assert with token color so dark-mode picks up the swap. The
   last row drops the border to avoid doubling against the card edge. */
body.page-questionnaire #pnlQuestionnaires tr > td.GridData {
    border-bottom: 1px solid var(--border, #e2e8f0);
}
body.page-questionnaire #pnlQuestionnaires tr:last-child > td.GridData {
    border-bottom: none;
}

/* Phase D — View-flow basic-info card (table.sTbl, pre-publish state)

   Pre-publish, the View flow renders a vessel basic-info card using
   <table class="sTbl"> with label/value <td> pairs. The `.answer` cell
   (lowercase) holds the value; siblings hold the label. This is a
   different markup family from V6's td.GridData.Answer — left-aligned
   (label/value pairs read better that way), muted label color, same
   Inter 14 / leading-20 / padding 8/12 base typography. */
body.page-questionnaire #pnlQuestionnaires table.sTbl td.answer {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
    color: var(--foreground, #1e293b);
    padding: 8px 12px;
    text-align: left;                       /* basic-info is label/value pairs, NOT right-anchored */
    vertical-align: middle;
}
body.page-questionnaire #pnlQuestionnaires table.sTbl td:not(.answer) {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
    color: var(--muted-foreground, #4d4d4d); /* muted label color, matches Figma label/value treatment */
    padding: 8px 12px;
    vertical-align: middle;
}

/* Phase D — Create-flow row geometry (Task 3)

   Task 1 discovery (2026-04-30): the `qTypeN` class lands ONLY on section
   sub-header rows emitted by CreateQuestionnaire.ascx.cs (single
   <td colspan="5">). Question DATA rows come from the static .htm
   templates and have an EMPTY <tr> class — but they always carry a
   <span class="qN">N.N</span> in cell 1. We use `tr:has(.qN)` as the
   structural discriminator: it matches every data row and zero
   sub-headers, no codebehind change required (original plan's Step 3.4
   contingency is therefore unnecessary).

   Five-cell layout:
     cell 1 = number      (48w slot, .qN span lives inside)
     cell 2 = question    (auto-width label)
     cell 3 = status      (12w slot — hosts img.jqQS.qS* + Phase D
                           required-bar ::before in Task 5; position:relative)
     cell 4 = field       (580w lane — host for .qDiv + input/select;
                           textarea variant widens to 600 in Task 4)
     cell 5 = comment     (40w slot)

   Geometry only — form-control skin, required-bar, glyph, radio,
   and guards are Tasks 4-8.
   Row-level font-family is the Inter stack; no !important needed since
   MainWhiteout's `td { font-family: var(--font-family) }` also resolves to
   Inter on refresh pages (tokens.css --font-family rebind). */

/* Row-level typography on data rows only (rows containing .qN number span).
   Content text — 14px Regular. Unified 12px padding + 24px line-height. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td {
    font-family: var(--raw-font-family-modern);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-normal);
    line-height: var(--raw-space-12);
    vertical-align: middle;
    padding: var(--raw-space-6);
}

/* Cell 1 — number (.qN span lives inside).
   Color: hardcode #4d4d4d per Figma 72:8963 — `--muted-foreground` resolves to
   slate-600 (#475569) which reads blue-grey vs Figma's neutral warm grey. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(1) {
    width: 48px;
    color: #4d4d4d;
    white-space: nowrap;
}

/* qTypeN sub-section / question header row — single colspan=5 cell holding the
   sub-header text (e.g. "Ownership and Operation", "8.1 Vapor Emission Control
   System", "6.1 Cargo Tank Coating"). Question header font — 14px Semi Bold. */
body.page-questionnaire #tblQuestionnaire tr.qTypeN > td {
    font-family: var(--raw-font-family-modern);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--raw-space-12);
    padding: var(--raw-space-6);
    vertical-align: middle;
}
body.page-questionnaire #tblQuestionnaire tr.qTypeN:has(.qN) > td:nth-child(1) .qN {
    font-weight: var(--font-weight-semibold);
    color: var(--muted-foreground, #4d4d4d); /* qTypeN only: qTypeH section bands keep black on accent fill */
}

/* Cell 2 — question label */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(2) {
    color: var(--foreground, #262626);
    width: auto;
}

/* Cell 3 — status (12w slot, holds img.jqQS.qS* + Phase D ::before required-bar) */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(3) {
    width: var(--raw-space-6);
    padding: var(--raw-space-6);
    position: relative;
}

/* Hide legacy 9x21 sprite VISUALLY but keep the element in the DOM as a
   transparent overlay so its native `title="Expired/Missing/Updated/Answered"`
   attribute (emitted at GenerateQuestionnaire.cs:3064) still fires a browser
   tooltip when the user hovers the colored indicator bar. Match the bar's
   exact footprint (4w x 24h, right:0, vertically centred — mirrors the
   ::before block at line ~1320) so the tooltip only triggers on the bar,
   not on the surrounding empty cell area. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(3) img.jqQS {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 4px;
    height: 24px;
    opacity: 0;
    cursor: help;
}

/* Make the questionnaire table fill its panel. Without this, table-layout:auto
   sizes the table to intrinsic-content width (~1343px), leaving dead space on
   the right of the panel even though the panel itself fills ContentPane. */
body.page-questionnaire #tblQuestionnaire {
    width: 100%;
    box-sizing: border-box;
}

/* Cell 4 — field lane (fluid: ~38% of row width, Figma 72:8685 ratio).
   Was fixed 580px; on wide viewports that pushed inputs off the right edge,
   leaving a wide dead zone between question label and input. With width: 38%
   + min-width floor, the input lane scales with the form width and stays
   right-anchored. Children (.qDiv, input, select, textarea) keep width: 100%. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) {
    width: 38%;
    min-width: 280px;
    max-width: none;
    padding: var(--raw-space-6);
    text-align: left;
}

/* Cell 5 — comment (40w slot) */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(5) {
    width: 40px;
    padding: var(--raw-space-6);
    text-align: center;
}

/* Comment icon — replace legacy StdIcons.png sprite (.qImC at Main.css:1736
   uses background-position -96px -48px, a pencil/note glyph) with the
   MessageCircle outline per Figma node 72:8966 (16px chat-bubble outline).
   Render via -webkit-mask + currentColor so dark-mode flips with the row's
   foreground token. The legacy <img src='/cp.gif'> is a 1x1 transparent
   spacer; the visible glyph is a CSS background — overriding background to
   none and switching to mask preserves layout while swapping the icon. */
body.page-questionnaire #tblQuestionnaire .qImC {
    background-image: none !important;
    background-color: #000;                               /* Figma 72:8966 — solid black (was --muted-foreground) */
    visibility: visible;                                  /* Figma 72:8962 — always shown when present (Main.css:1736 hides until row hover/.rF) */
    display: inline-block;                                /* play nice with cell 5's text-align: center */
    width: 16px;
    height: 16px;
    margin: 0;
    vertical-align: middle;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg 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'><path d='M7.9 20A9 9 0 1 0 4 16.1L2 22Z'/></svg>") no-repeat center / 16px;
            mask: url("data:image/svg+xml;utf8,<svg 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'><path d='M7.9 20A9 9 0 1 0 4 16.1L2 22Z'/></svg>") no-repeat center / 16px;
    /* Natural flow inside cell 5 (40px slot, text-align: center). Previously
       absolute-positioned at right:100% which anchored the icon OUTSIDE cell 5,
       overlapping cell 4. With qDiv now full-width on every row (commented or
       not), an external anchor would collide with the qDiv right border — so
       the icon flows naturally inside its own cell. Result: unit labels
       (Metres / US$ / Knots) line up vertically across the form regardless of
       whether the row carries a comment. */
}

/* Row separator on data rows */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td {
    border-bottom: 1px solid var(--border, #e2e8f0);
}

/* --------------------------------------------------------------------------
   Group question styling — only underline the context section on sub-questions
   Figma: ZrCO5nudzyQMi1LXRzj4eW node 199:4131 ("4. Update group question
   styling"). Frame 199:4089 shows a parent question (8.1.1) with a full-width
   bottom border, followed by several conditional sub-questions ("If fitted,
   ...", "If ship possesses VEC Certification, ...") whose bottom border is
   collapsed to a short 42px stub in the LEFT context column only. Rectangle
   199:4052 in the last frame establishes the geometry: x=12, width=42,
   height=1, base/border (#e2e8f0).

   Markup: CreateQuestionnaire renders every data row with a `<span class="qN">`
   in cell 1. Parent rows hold a number ("8.11", "8.15.1"). Sub-questions —
   conditional follow-ups that share the parent's numbering — render the same
   span empty. So `tr:has(.qN:empty)` is the sub-question selector.

   Per-cell borders: defeat both questionnaire.css L670 (`tr:has(.qN) > td`
   border-bottom) and Main.css L1729 (`.qTbl td` border-top + border-bottom
   #f8f8f8) on every cell of a sub-question row. Then paint the 42px stub on
   cell 1 only as a background-image gradient — a per-cell `border-bottom`
   would span the full ~122px cell, but the gradient lets us pin width=42
   starting at the 12px x-inset, matching Figma rectangle 199:4052. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN:empty) > td {
    border-top: 0 !important;
    border-bottom: 0 !important;
}

/* Edit icon on variable-grid (vqatable) rows — swap legacy /images/icons/edit.png
   pencil for Lucide SquarePen per Figma 95:10652 (was Lucide Pen 72:9034). Size 16x16
   per Figma 62:10380 (the 24x24 from the prior Pen swap was oversized vs the design,
   which shows a 16px icon vertically centered in the 40px header-row slot). The PNG
   is rendered by the legacy `<a onclick="editQuestionnaire_window=...">` wrapper;
   we use CSS `content: url(...)` to replace the rendered image with an inline SVG.
   Only icons inside #tblQuestionnaire are swapped — the same PNG is used elsewhere
   (e.g. modal toolbars) and we don't want to broadcast. Stroke #000 per request. */
body.page-questionnaire #tblQuestionnaire img[src$="/images/icons/edit.png"] {
    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='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/><path d='M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z'/></svg>");
    width: 16px;
    height: 16px;
    vertical-align: middle;
}

/* Variable-grid row (vqatable) — collapse empty state.

   Markup (post CreateQuestionnaire.ascx.cs §"Variable-grid layout" refactor):
     TR1  tr:has(.qN)         qN + question text + status + edit pencil (cols 4-5)
     vgTr tr:not(:has(.qN))   single TD with colspan=5 containing the vqatable
                              (or an empty <span> placeholder when no rows saved)

   When the variable-grid is empty, drop the "Empty" italic hint and collapse
   vgTr's vertical footprint so the question reads as a single 48h row. */

body.page-questionnaire #tblQuestionnaire span[id^="lblVariableGrid_"]:empty::after {
    content: none;
}

body.sidebar-nav.page-questionnaire #tblQuestionnaire
    tr:not(:has(.qN)):has(span[id^="lblVariableGrid_"]:empty) > td {
    padding-top: 0;
    padding-bottom: 0;
    border: 0;
    line-height: 0;
    font-size: 0;
    height: 0;
}

/* Variable-grid edit pencil — sits on TR1's colspan=2 cell (cols 4-5) which
   IS the `td:nth-child(4)` slot. Block §"Cell 4 — input lane" at line 626
   sets that slot to `width: 38%; min-width: 280px; padding: 12px; text-align: left`
   for normal data rows; on a pencil-only cell those values keep the icon
   middle-of-row instead of right-pinned. Match the same selector shape and
   add a :has() filter to discriminate the pencil cell (it carries the legacy
   `/images/icons/edit.png` img which the data-row input lane never does), then
   override to a tight right-aligned cell so the pencil pins to the row's far
   right per Figma 260:8455 (label left, status + pencil right). */
body.page-questionnaire #tblQuestionnaire
    tr:has(.qN) > td:nth-child(4):has(> a > img[src$="/images/icons/edit.png"]) {
    text-align: right;
    width: auto;
    min-width: 0;
    padding: 0 var(--raw-space-6);
}

/* Question-hint icon — swap legacy /images/icons/alertInfoSmall.png background
   on .qRemark for Lucide Info (16px circle-with-i) per Figma 62:10359. The
   legacy MainWhiteout.css:3419 paints alertInfoSmall as background-image with
   padding-left:17px and italic text; the refresh wants a 16x16 outline icon,
   8px gap, normal-style text. Render via -webkit-mask + currentColor so the
   icon flips with --foreground in dark mode (same trick as .qImC). */
body.page-questionnaire #tblQuestionnaire .qRemark {
    background-image: none;                               /* clear legacy alertInfoSmall.png */
    font-style: italic;                                   /* keep legacy italic so the hint text reads distinct from the question label */
    padding-left: 24px;                                   /* 16 icon + 8 gap (Figma 62:10364 flex gap:8) */
    min-height: 16px;                                     /* match icon height */
    position: relative;                                   /* anchor for ::before */
    color: var(--foreground, #262626);
    font-size: 14px;
    line-height: 20px;
}

body.page-questionnaire #tblQuestionnaire .qRemark::before {
    content: "";
    position: absolute;
    left: 0;
    top: 2px;                                             /* aligns 16px glyph with cap height of 14/20 first line */
    width: 16px;
    height: 16px;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg 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'><circle cx='12' cy='12' r='10'/><path d='M12 16v-4'/><path d='M12 8h.01'/></svg>") no-repeat center / 16px;
            mask: url("data:image/svg+xml;utf8,<svg 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'><circle cx='12' cy='12' r='10'/><path d='M12 16v-4'/><path d='M12 8h.01'/></svg>") no-repeat center / 16px;
}

/* Rebind --text-link for the questionnaire page (which is NOT scoped to
   .q88-refresh) so in-row links resolve to teal-600 — same shade we use for
   the primary button. The refresh-scope binding is kept in tokens.css. */
body.page-questionnaire {
    --text-link: var(--primary);
}

/* In-row text links (HVPQ info link, .qConvertUnit unit-toggle, etc.) — recolor
   to var(--text-link) to match the primary button. Scope to text-only anchors
   inside the questionnaire table; image-only anchors (status icons, edit pen)
   are unaffected. Legacy `Main.css:1683 .qDiv .qConvertUnit { color:#1193d6
   !important }` carries !important, so we need !important to win.
   Exclude `.Img-Std-EditV2` (UDF edit-pencil anchors emitted by
   GenerateQuestionnaire.cs:3865 as LinkButton with <ins>&nbsp;</ins> spacer):
   `:not(:has(img))` matches them because they wrap <ins>, not <img>, which
   leaked teal into the pencil via currentColor on the components.css mask. */
body.page-questionnaire #tblQuestionnaire a:not(:has(img)):not(.Img-Std-EditV2),
body.page-questionnaire #tblQuestionnaire a:not(:has(img)):not(.Img-Std-EditV2):link,
body.page-questionnaire #tblQuestionnaire a:not(:has(img)):not(.Img-Std-EditV2):visited,
body.page-questionnaire #tblQuestionnaire .qDiv a.qConvertUnit,
body.page-questionnaire #tblQuestionnaire .qDiv a.qConvertUnit:link,
body.page-questionnaire #tblQuestionnaire .qDiv a.qConvertUnit:visited {
    color: var(--text-link) !important;
}
body.page-questionnaire #tblQuestionnaire a:not(:has(img)):not(.Img-Std-EditV2):hover,
body.page-questionnaire #tblQuestionnaire .qDiv a.qConvertUnit:hover {
    color: var(--link-hover, var(--primary)) !important;
}

/* ============================================================================
 * Phase D — Task 4: Form-control skin (input / select / textarea)
 * ----------------------------------------------------------------------------
 * Anchor strategy:
 *   - Text inputs (text/email/number/tel/url) anchor on `.qDiv input[type=...]`.
 *     `.qDiv` is unique to data-row field cells (template emitter), so it's the
 *     safest hook — no false positives on inputs elsewhere in the page.
 *   - `<select>` and `<textarea>` have no shared anchor class, so they anchor
 *     on `tr:has(.qN) > td:nth-child(4)` (the field cell of a data row).
 *
 * Cascade override (CRITICAL):
 *   MainWhiteout.css declares
 *     body, input, select, textarea, td, form { font-family: var(--font-family); }
 *   That `!important` beats any specificity. Phase D's `font-family` on
 *   inputs / selects / textareas MUST also be `!important` to win — this is
 *   the documented cascade-override pattern from the corrections doc.
 *   Other properties (font-size, color, border, padding, background) win on
 *   specificity alone — no `!important` needed.
 *
 * Out of scope (deferred):
 *   - Custom `<select>` chevron — keep native chevron per spec §9.5.4. Phase G
 *     can swap to a custom SVG chevron if/when desired.
 *   - Custom radio dot — `input[type="radio"]` is owned by Task 7.
 *   - Custom date picker — out of Phase D scope.
 *
 * Required-row visual (4w narrower variant): achieved at row level via Task 5's
 * amber bar painted into the status cell, NOT by a separate width here.
 * ============================================================================ */

/* A. Text inputs INSIDE .qDiv — transparent (the bordered frame is on .qDiv,
   block B). This preserves the legacy pattern where input + unit text/link
   sit in a single bordered control (Main.css:1643-1662 .qDiv + .qTxt + .qUnit).
   Phase D originally moved the border to <input> and unwound .qDiv, which
   pushed unit elements outside the visual control — restored 2026-05-07.
   Case-insensitive `i` flag matches HtmlBuilder.cs:418 emitted `type="Text"`
   (capital T) — without it, modern Chrome/Firefox honour the case strictly
   in some contexts and the input falls back to ~20-char default width
   ("some textboxes don't span to end of cell"). */
body.page-questionnaire #tblQuestionnaire .qDiv input[type="text" i],
body.page-questionnaire #tblQuestionnaire .qDiv input[type="email" i],
body.page-questionnaire #tblQuestionnaire .qDiv input[type="number" i],
body.page-questionnaire #tblQuestionnaire .qDiv input[type="tel" i],
body.page-questionnaire #tblQuestionnaire .qDiv input[type="url" i],
body.page-questionnaire #tblQuestionnaire .qDiv input.qTxt {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
    height: auto;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    line-height: 22px;
    color: var(--foreground, #1e293b);
    box-sizing: border-box;
    appearance: none;
    outline: 0;                         /* :focus ring is on .qDiv:focus-within, see block F */
}

/* A2. Select inside .qDiv — transparent (the bordered frame is on .qDiv,
   block B). Selects are wrapped in .qDiv just like text inputs (verified
   2026-05-07 via DOM probe), so giving the select its own border created
   the "dropdown nested inside a textbox" double-border look. Native
   chevron (appearance: auto) is preserved. The .qDdl class fallback
   covers the legacy pattern at Main.css:1670.
   `!important` on border/background is required: components.css declares
   `body.sidebar-nav select { border: 1px solid var(--input) !important }`
   and `!important` cannot be beaten by specificity alone. */
body.page-questionnaire #tblQuestionnaire .qDiv select,
body.page-questionnaire #tblQuestionnaire .qDiv .qDdl {
    flex: 1 1 auto;
    min-width: 0;
    width: 100% !important;
    height: auto !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    line-height: 22px;
    color: var(--foreground, #1e293b);
    box-sizing: border-box;
    appearance: auto;
    outline: 0;
}

/* A2-fallback. Bare select sitting directly in cell-4 (not wrapped in .qDiv).
   No false positives on the .qDiv-wrapped path because that has higher
   specificity (the selectors above include .qDiv). */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) > select {
    width: 100%;
    height: 32px;
    padding: 4px 12px;
    border: 1px solid var(--input, #e2e8f0);
    border-radius: 8px;
    background: var(--card, #ffffff);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    line-height: 20px;
    color: var(--foreground, #1e293b);
    box-sizing: border-box;
    appearance: auto;
}

/* B. .qDiv — the bordered frame. Flex row so input grows and the unit
   (.qUnit element or trailing text node) sits on the right edge. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv {
    width: 100%;
    min-height: 32px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 12px;
    border: 1px solid var(--input, #e2e8f0);
    border-radius: 8px;
    background: var(--card, #ffffff);
    box-sizing: border-box;
}

/* B0. Invalid-field state. Legacy validation adds `.qDivVal` to the field
   wrapper on a failed required/range check (Main.css:1695 painted it red:
   1px #f51919 border + #f8c5a3 salmon fill). The refresh .qDiv rule above is
   more specific than the single `.qDivVal` class, so it was silently
   overriding the invalid chrome — invalid fields no longer turned red on the
   refresh (QA #8: "input field is not red; it is on staging"). Re-assert the
   invalid state in the refresh palette (red-600 border + red-50 fill) at a
   specificity that beats the .qDiv rule (extra `.qDivVal` class). Shorthand
   `border` with a hardcoded hex (NOT var()) to avoid the longhand-vs-shorthand
   var() cascade loss documented in MEMORY. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv.qDivVal {
    border: 1px solid #dc2626;
    background: #fef2f2;
}

/* B1. Comment icon (.qImC) rendered in cell 5's natural 40px slot — the
   previous version narrowed .qDiv by 24px on commented rows to make room for
   an absolutely-positioned icon, which had the side-effect of shifting the
   unit text (Metres / US$ / Knots) 24px left compared to uncommented rows so
   the units never lined up across the form. .qDiv now stays full-width on
   every row, and the icon flows naturally inside cell 5 (see .qImC block
   below). Keeping a no-op rule here as documentation; remove if a future
   refactor consolidates this section. */

/* B2. Unit text inside .qDiv. Targets the legacy <a class="qUnit"> + a
   defensive last-child <a> fallback. The HtmlBuilder.cs:421 bare-text path
   produces a text node, which becomes an anonymous flex item here and
   inherits color from the next rule. Color: neutral foreground (slate-700)
   instead of --primary teal — the unit (US$, Knots, Metres) is a passive
   label, not an interactive link, so painting it teal misread as a clickable
   accent. .qConvertUnit (the only INTERACTIVE unit-toggle anchor, e.g.
   "Metres / Feet") keeps the teal link color via the rule at line 745. */
body.page-questionnaire #tblQuestionnaire .qDiv .qUnit,
body.page-questionnaire #tblQuestionnaire .qDiv > a:last-child {
    flex: 0 0 auto;
    color: var(--muted-foreground, #475569);
    font-size: 13px;
    line-height: 20px;
    text-decoration: none;
    white-space: nowrap;
}
body.page-questionnaire #tblQuestionnaire .qDiv .qUnit:hover,
body.page-questionnaire #tblQuestionnaire .qDiv > a:last-child:hover {
    text-decoration: underline;
}

/* C. Select — looser T/B padding per spec §9.5.2 */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) select {
    padding: 8px 12px;
}

/* D. Textarea cell — keep the same fluid lane (38%/min-280) as plain inputs;
   override only vertical alignment so a multi-line textarea anchors to the top
   of the row instead of vertically centering with the question label. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4):has(textarea) {
    vertical-align: top;
}

/* E. Textarea inside .qDiv — transparent (the bordered frame is on .qDiv,
   block B). Same nesting fix as Block A2 for select. */
body.page-questionnaire #tblQuestionnaire .qDiv textarea {
    flex: 1 1 auto;
    min-width: 0;
    width: 100% !important;
    min-height: 80px;
    padding: 8px 0 !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    line-height: 20px;
    color: var(--foreground, #1e293b);
    box-sizing: border-box;
    resize: vertical;
    outline: 0;
}

/* E-fallback. Bare textarea sitting directly in cell-4 (not in .qDiv).
   Keep the bordered styling so it matches the .qDiv-wrapped pattern. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) > textarea {
    width: 100%;
    min-height: 80px;
    padding: 8px 12px;
    border: 1px solid var(--input, #e2e8f0);
    border-radius: 8px;
    background: var(--card, #ffffff);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    line-height: 20px;
    color: var(--foreground, #1e293b);
    box-sizing: border-box;
    resize: vertical;
}

/* When the field cell contains a textarea, .qDiv needs to stretch vertically
   (top-aligned, multi-line content) instead of staying at the 32px row height. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(textarea) {
    align-items: stretch;
    min-height: 0;
    padding: 0 12px;
}

/* UDF rows (User Defined Fields, e.g. row 1.3 "Vessel's previous names").
   Markup (GenerateQuestionnaire.cs:3697-3743):
       <div class="qDiv">
         <span style="float:left;width:275px;">{value}</span>
         <input class="UDFFormControlForValidation" type="text">
         <a class="Img-Std-EditV2 jqUDF" style="float:right;">{edit pencil}</a>
       </div>
   The input is intentionally hidden via .UDFFormControlForValidation
   (left:-3000px) — it exists only for ASP.NET validation. The visible UI is
   the span (read-only value) + edit pencil. With flex on qDiv, the hidden
   input still occupies a 278px flex slot, leaving dead space mid-row. Fall
   back to display:block + flow-root so the legacy float:left/right pattern
   from Main.css renders correctly. The span's inline width:275px is dropped
   so the value can fill the lane. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input.UDFFormControlForValidation) {
    display: flow-root;                 /* contain floated children, modern clearfix */
    align-items: initial;
    gap: 0;
    padding: 4px 12px;
    min-height: 32px;
}

/* Inline-style overrides (`style="width:275px"` from codebehind) — neutralise
   so the value span flexes with the qDiv. The edit-pencil keeps its float
   right via inline style; nothing to override there. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input.UDFFormControlForValidation) > span[style*="float"] {
    width: auto !important;
    float: none !important;
    display: block;
    overflow: hidden;                   /* let the value sit next to the right-floated edit pencil */
    margin-right: 32px;                 /* leave room for the right-floated edit pencil (24px + 8px gap) */
    color: var(--foreground, #1e293b);
    font-size: 14px;
    line-height: 22px;
    padding-top: 4px;
    text-overflow: ellipsis;
    white-space: nowrap;                /* keep value on one line; long values truncate (matches legacy fixed-width behaviour) */
}

/* UDF row — switch the .qDiv to flex so the value label + edit pencil sit
   on the same row. The legacy flow-root + float:right pattern wraps the
   anchor to a new line because the value <span> renders as display:block
   (full-width line) BEFORE the float:right anchor in the DOM — the
   `overflow:hidden BFC` trick only works when the float comes first.
   Switching to flex puts both children side-by-side; the margin-right:32px
   reservation on the label collapses into the flex gap.
   `align-items: flex-end` pins the pencil to the bottom-right: when the
   value is single-line both rows are the same height (looks identical to
   center), when the value contains <br/> breaks the pencil stays at the
   bottom edge of the taller label box. */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input.UDFFormControlForValidation) {
    display: flex !important;
    align-items: flex-end;
    gap: 8px;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input.UDFFormControlForValidation) > span[style*="float"] {
    display: block;
    flex: 1 1 auto;
    min-width: 0;          /* allow shrink so the ellipsis fires before pushing the anchor out */
    margin-right: 0;       /* gap on parent handles spacing now */
    padding-top: 0;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input.UDFFormControlForValidation) > a {
    flex: 0 0 auto;
    float: none !important;
}

/* F. Focus ring — teal outline. For .qDiv-wrapped inputs, the ring sits on
   the wrapper via :focus-within so the whole control (input + unit) lights
   up as one unit. Plain selects/textareas keep the ring on themselves. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:focus-within,
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) select:focus,
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) textarea:focus {
    outline: 2px solid var(--primary, #0891b2);
    outline-offset: 2px;
    border-color: var(--primary, #0891b2);
}

/* G1. Disabled — fully inert. Apply to the .qDiv wrapper so the unit text
   also dims; raw select/textarea use their own disabled state. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input[disabled]),
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) select[disabled],
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) textarea[disabled] {
    background: var(--muted, #f1f5f9);
    color: var(--muted-foreground, #475569);
    cursor: not-allowed;
}

/* G2. Readonly — non-editable but text-selectable. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input[readonly]),
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) textarea[readonly] {
    background: var(--muted, #f1f5f9);
    color: var(--muted-foreground, #475569);
}

/* --------------------------------------------------------------------------
   Phase D Task 5 — Required-bar amber marker (Figma node 72:8970)

   Per spec §9.5.2 / DESIGN.md §9.5: a 4w x 30h amber #f59e0b rectangle is
   painted on the Status cell ::before of required rows. Height scales to
   80h for textarea (multi-line) rows so the marker spans the full input.

   Detection signal: the codebehind emits <img class="qImR"> for any
   question where IsQuestionRequired is true. Per Task 1 discovery,
   qImRCount was 0 on the audited Q88 record (IMO 1800251), so this rule
   is speculative for that record — it is harmless when no row matches
   :has(img.qImR), and verification on a record that emits qImR markers
   is deferred to Phase F (where the data-flow question — does the V6
   template path emit qImR the same way CreateQuestionnaire.ascx.cs does?
   — is investigated).

   Why ::before on cell 3 (status) and not cell 2 (label): cell 3 is the
   column-anchored slot in the existing 5-cell layout (Task 3 already set
   position: relative + 12w width on this cell). Painting the bar there
   places it between question text and input control, matching Figma's
   right-edge rail alignment.

   Why amber (#f59e0b) only here: spec §9.5 says required+answered renders
   green (#15803d). Phase D paints amber for ALL required rows; Phase F
   (status-toolbar restyle) overrides with green when the row also carries
   a qSA marker. Concerns split — Task 5 owns "this row is required",
   Phase F owns "this row is required AND answered".

   The status cell already shows img.jqQS.qSE/qSM/qSU/qSA when the question
   has a status (Phase F's domain). Our ::before sits behind/over those;
   Phase F will reconcile.

   Selector union covers both legacy <img class='qImR'> emission and the
   corrections-doc-suggested <span class='qImR'> fallback (in case Task 6's
   optional codebehind contingency fires later).

   Color is hardcoded raw hex (not tokenized) — state colors do not
   dark-mode flip per MEMORY.md Phase 4 notes. Height uses a CSS variable
   set at the row level so the textarea modifier flips it without
   duplicating the ::before block.
   -------------------------------------------------------------------------- */

body.page-questionnaire #tblQuestionnaire tr:has(.qN) {
    --q88-required-bar-h: 30px;
}
body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(textarea) {
    --q88-required-bar-h: 80px;
}

body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.qImR) > td:nth-child(3)::before,
body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(.qImR) > td:nth-child(3)::before {
    content: "";
    position: absolute;
    width: 4px;
    height: var(--q88-required-bar-h);
    background-color: #f59e0b;          /* tailwind amber/500 — hardcoded, not tokenized (state color, doesn't dark-mode flip) */
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    border-radius: 2px;
    pointer-events: none;
}

/* --------------------------------------------------------------------------
   Phase D Task 6 — Required-question glyph (replaces <img class='qImR' />)

   Legacy emission per CreateQuestionnaire.ascx.cs:2239:
       <img src='/cp.gif' class='qImR'
            style='display:inline-block; visibility:visible'/>
   emitted right after the question text on required questions.

   Phase D replaces the sprite image with a CSS '*' glyph in red #b91c1c
   (tailwind red/700) on the question label cell ::after.

   Why ::after on the parent <td>, not on <img>: replaced elements (img)
   have no pseudo-content. Attach to the cell.

   The :has(.qImR) fallback (in addition to :has(img.qImR)) covers the
   optional codebehind contingency where <img> is swapped for <span>.

   Verifiability gap (per Task 1 discovery): qImRCount = 0 on the audited
   Q88 record. Rule ships speculatively — harmless no-op when no row matches.

   - Cell 2 placement: our selector tr:has(.qN) > td:nth-child(2)
     scopes to DATA rows (rows with .qN number span). The qRemark
     <div class='qRemark'> hint emission at CreateQuestionnaire.ascx.cs:2241
     fires for qTypeN section sub-headers (NOT data rows, per Task 1
     discovery — data rows come from .htm templates). So the ::after
     glyph painting "below the hint" risk doesn't apply to Phase D's
     scope. If a future template path adds qRemark alongside qImR in
     a data-row cell 2, revisit this rule.

   The corresponding Phase D codebehind contingency (Step 6.4 in original
   plan) is NOT activated. CSS display:none is sufficient for the legacy
   <img>; see hide-rule comment below for the cascade rationale.
   -------------------------------------------------------------------------- */

/* Hide the legacy qImR <img> (or fallback span). Selector specificity
   (0,1,1,2 with #tblQuestionnaire ID) beats MainWhiteout.css:3377's
   `.qImR { display:inline-block; ... }` rule (0,0,1,0). Source order
   also favors us (questionnaire.css loads after MainWhiteout.css).
   No !important required. */
body.page-questionnaire #tblQuestionnaire img.qImR,
body.page-questionnaire #tblQuestionnaire .qImR {
    display: none;
}

/* Emit a red '*' glyph on the question label cell of rows that contain a
   qImR marker. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(2):has(img.qImR)::after,
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(2):has(.qImR)::after {
    content: "*";
    color: #b91c1c;                      /* tailwind red/700 — state color, hardcoded */
    font-weight: 700;
    margin-left: 4px;
    font-size: 14px;
    line-height: 1;
}

/* --------------------------------------------------------------------------
   Phase D Task 7 — Radio-pair row skin (Figma node 72:8993, "8.11 VRS fitted")

   - Targets tr:has(.qN) data rows whose field cell contains radios (e.g.
     row 1.2b "Is the vessel owner/manager a member of Intertanko? Yes/No").
   - Other RadioButton width variants per DESIGN.md §9.5.5 (table-affiliated
     294/202, Yes/No 146 header, dialog 202) are OUT OF SCOPE for Phase D.
   - Number-cell text muted to #595959 (vs plain row #4d4d4d) and 13px
     (vs 14px) per spec §9.5.4 — visual differentiator for radio rows.
   - Native accent-color paints cyan selected dot. Custom radio dot
     (bg/border/inner-circle per spec §9.5.4) is a separate ticket.

   MARKUP REALITIES (HtmlBuilder.cs:326 SetRadioButton):
   - Radio "labels" are bare text nodes between inputs, NOT <label>/<span>:
       <input type="radio">Yes&nbsp;&nbsp;&nbsp;<input type="radio">No
     We style at the <td> level so bare text inherits font-weight + color.
   - When ShowComments=true the same cell also receives <br><a>Comments:</a>
     <div>...</div> appended via SetComment. We therefore DO NOT use
     display:flex on cell 4 — flex would collapse the <br> and lay the
     Comments link/textarea horizontally with the radios.

   DEFERRED: a perfect 294 + 12 + 294 split per Figma 72:8993 is NOT
   achieved here because the legacy &nbsp;&nbsp;&nbsp; spacing dominates
   horizontal flow. A future ticket can wrap bare-text labels in
   <label class="qRadioLabel"> server-side to enable a clean flex split.
   -------------------------------------------------------------------------- */

/* Number cell text in radio rows: muted + smaller. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(input[type="radio"]) > td:nth-child(1) {
    color: #595959;
    font-size: 13px;
}

/* Field cell when it contains radios. Inherits the 38%/min-280 fluid lane
   from cell-4 base. Yes/No radios LEFT-align to the lane edge — revert to
   staging per QA #6/#7. The Figma right-anchor was rejected: it pushed the
   cluster to the card's right edge AND the clear-response X (right:-8px,
   below) then overflowed the cell boundary, reading as "misaligned".
   NOTE: no display:flex — bare text labels (Yes/No) and ShowComment
   <br>+links are emitted directly into this cell by
   HtmlBuilder.SetRadioButton. Flex would collapse the <br> and wrap
   Comments inline. Keep block-flow; rely on inline radios. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4):has(input[type="radio"]) {
    text-align: left;
}

/* Bare text labels (Yes/No) inherit Inter 14 from Task 3 row typography.
   Bump to Medium (500) and explicitly set foreground color for radio rows
   to match Figma 72:8993. The legacy markup at HtmlBuilder.cs:326 emits
   the labels as bare text nodes, NOT <label> elements — we style at cell
   level so the bare text inherits. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(input[type="radio"]) > td:nth-child(4) {
    font-weight: 500;
    color: var(--foreground, #0f172a);
}

/* Each radio button: native 16x16 with teal accent (matches link/button color).
   Spec §9.5.4: gap 12 between dot and its label. The sibling <label>
   (rendered by Custom.Web.UI.WebControls.RadioButtonList — see also note
   below about stale "bare text" comment above) is `<input>+<label>`, so a
   12px right-margin on the input opens the dot→label gap. Figma 62:10406. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) input[type="radio"] {
    width: 16px;
    height: 16px;
    margin: 0 12px 0 0;
    accent-color: var(--text-link);
    cursor: pointer;
    vertical-align: middle;
}

/* Radio rows: drop the bordered/white-background qDiv shell — Figma 62:10406 shows
   the radio cluster sitting transparently on the row, not inside an input box.
   LEFT-align the inner <span> (which wraps both radios) so Yes/No anchor to the
   lane's LEFT edge — revert to staging per QA #7. The qDiv inherits flex from the
   data-row base (line 839); justify-content:flex-start keeps the span at the left,
   which also lets the clear-X (.clearRadioBtn, right:-8px) sit just after "No"
   instead of overflowing the card edge. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv:has(input[type="radio"]) {
    justify-content: flex-start;
    border: 0;
    background: transparent;
    padding: 0;
    min-height: 0;
}

/* Inter-pair spacing — spec §9.5.4 RadioButton frame is `flex gap:12`.
   Without this rule the previous label sits flush against the next dot
   (probed: 0px), so "Yes No" reads as "YesNo". Right-margin on the label
   opens the label→next-dot gap to 12. The trailing label's margin is
   absorbed by the surrounding flow (next sibling is `<div.clearRadioBtn>`
   or `<br>` for Comments) — harmless. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) input[type="radio"] + label {
    margin-right: 12px;
    vertical-align: middle;
}

/* Clear-response X button (`.clearRadioBtn`) — appended by JS to each
   radio's parent the first time its .qDiv is hovered (CreateQuestionnaire.ascx).
   Legacy inline `float:right; display:none → block` reflows the layout when the
   X toggles on. Absolute-position it to its parent so the visibility flip
   doesn't move neighboring elements. */
body.sidebar-nav.page-questionnaire .radioButtonContainer > * {
    position: relative;
}
body.sidebar-nav.page-questionnaire .clearRadioBtn {
    position: absolute !important;
    top: 4px;
    right: -8px;
    float: none !important;
}
/* QEN-8831 — reveal the X on container hover via CSS, NOT a jQuery .hover()
   toggle. The btn is lazy-created on the first hover; binding a toggle at that
   moment misses the in-progress mouseenter and leaves the show/hide state
   permanently inverted (X showed only AFTER the mouse left). CSS :hover is
   evaluated continuously from pointer position, so it shows correctly even on
   the first (mid-init) hover. `!important` beats the btn's inline display:none. */
body.sidebar-nav.page-questionnaire .radioButtonContainer:hover .clearRadioBtn {
    display: block !important;
}

/* Textarea inside .qDiv — the wrapper already paints the focus outline via
   .qDiv:focus-within (block F). Suppress the textarea's own outline+border
   so we don't get a double-ring. Selector chained through the same scope
   as block F (line 1000) plus an extra `.qDiv` to beat it on specificity. */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv textarea:focus {
    outline: 0 !important;
    border: 0 !important;
}

/* Select inside .qDiv — same double-ring fix as textarea above. Block F
   paints the focus ring on .qDiv:focus-within, and components.css's
   `body.sidebar-nav select { border: 1px solid var(--input) !important }`
   keeps the select itself bordered, so on focus the select also paints
   its own outline → double ring. Suppress it. */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) .qDiv select:focus {
    outline: 0 !important;
    border: 0 !important;
}

/* Status indicators per DESIGN.md §9.9 — 4×24px colored bar at the right
   edge of cell 3 (= left edge of the input lane). Driven by the qS* class
   on the legacy img.jqQS marker, which is hidden by the line-609 rule but
   stays in the DOM so :has() can detect it.
     .qSE Expired → red    (#b91c1c)
     .qSM Missing  → amber  (#f59e0b)   ← yellow
     .qSU Updated  → green  (#16a34a)
     .qSA Answered → green  (#16a34a)   ← matches user mental model
   Cell 3 is `position: relative` (line 601) so the absolute ::before
   anchors to it. */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSE) > td:nth-child(3)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSM) > td:nth-child(3)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSU) > td:nth-child(3)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSA) > td:nth-child(3)::before {
    content: "";
    position: absolute;
    width: 4px;
    height: 24px;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    border-radius: 2px;
    pointer-events: none;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSE) > td:nth-child(3)::before {
    background-color: #b91c1c;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSM) > td:nth-child(3)::before {
    background-color: #f59e0b;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSU) > td:nth-child(3)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSA) > td:nth-child(3)::before {
    background-color: #16a34a;
}

/* Variable-grid (vqatable) rows — these have no .qN (the question label
   lives in a sibling row above), but their first cell holds an img.jqQS.qS*
   marker. The block above only paints the modern 4×24 bar on .qN cell 3,
   so vqatable rows still rendered the legacy 9×21 sprite. Mirror the same
   treatment: hide the sprite, paint a 4×24 colored bar with 2px radius via
   ::before on the indicator cell so vqatable rows match input-row chrome. */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)) > td:has(> img.jqQS) {
    position: relative;
}

/* Variable-grid indicator cell — same overlay trick as the .qN-row cell
   above so the native `title` tooltip remains hoverable on the colored
   indicator bar. Position matches the bar's ::before footprint below:
   4w x 24h, left:0, top:12 (anchored from the top, not centred — see the
   bar's own comment about not floating mid-grid on tall vqatable cells). */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)) > td > img.jqQS {
    position: absolute !important;
    left: 0;
    top: 12px;
    width: 4px;
    height: 24px;
    opacity: 0;
    cursor: help;
}

body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSE) > td:has(> img.jqQS)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSM) > td:has(> img.jqQS)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSU) > td:has(> img.jqQS)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSA) > td:has(> img.jqQS)::before {
    content: "";
    position: absolute;
    width: 4px;
    height: 24px;
    left: 0;
    /* Anchor to the TOP of the (often very tall) variable-grid cell, not its
       vertical centre. Centring put the bar at rowHeight/2 — e.g. ~230px down a
       463px Mooring 9.1 grid — so the colour bar floated mid-grid, detached from
       its "9.x" title in the row above (QEN-8704 "yellow blocks misaligned").
       12px mirrors the top offset a 24px bar gets when centred in a 48px
       question row, keeping vqatable + question-row bars visually consistent. */
    top: 12px;
    border-radius: 2px;
    pointer-events: none;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSE) > td:has(> img.jqQS)::before {
    background-color: #b91c1c;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSM) > td:has(> img.jqQS)::before {
    background-color: #f59e0b;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSU) > td:has(> img.jqQS)::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:not(:has(.qN)):has(img.jqQS.qSA) > td:has(> img.jqQS)::before {
    background-color: #16a34a;
}

/* --------------------------------------------------------------------------
   QEN-8831 — variable-grid status bar re-anchor (Mooring 8.1 "colored bar
   not lined up", Dev vs Stg).

   The block above (QEN-8704) painted the variable-grid bar at the grid cell's
   TOP-LEFT — but it targets `tr:not(:has(.qN))`, i.e. the layout where the
   status img.jqQS sat on the GRID row. The QEN-8776 restructure
   (CreateQuestionnaire.ascx.cs §"Variable-grid layout") moved the status img
   UP onto the question row (TR1, a .qN row) alongside the edit pencil, and made
   the grid full-width (colspan=5) on the row below. Consequences:
     • TR1 now matches the *normal-question* bar rule (line ~1459) → the bar
       paints at cell-3's right edge (= input-lane left), which on a full-width
       grid floats over the MIDDLE of the table, detached from it.
     • the grid row no longer carries img.jqQS, so the QEN-8704 rule above never
       fires.

   Repair (CSS-only, no further .cs change): for a variable-grid question's TR1
   — detected as a .qN row whose immediately-following sibling row contains a
   .vqatable — suppress the orphaned cell-3 bar and repaint the same 4×24 bar at
   the grid's left edge, vertically CENTRED on the column-header row, coloured by
   TR1's qS* class. The edit pencil stays on the question line (Eileen Wu's
   design directive, Slack 1779895739).
   -------------------------------------------------------------------------- */

/* 1. suppress the orphaned cell-3 bar on the variable-grid question's TR1
      (single :has — nested :has() is invalid; !important beats the more-specific
      qS*-class painting rule above) */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(+ tr .vqatable) > td:nth-child(3)::before {
    display: none !important;
}

/* 2. anchor = the grid's first column-header cell. Its left edge == the grid
      cell's left edge, and it spans the FULL header-row height, so the bar can
      centre on the headers no matter how many lines the column titles wrap to
      (on wide screens they wrap to 2-3 lines → a fixed top offset would float
      above them; the legacy layout sat the bar at the header level). */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child {
    position: relative;
}

/* 3. paint the 4×24 bar at the header cell's left edge, vertically centred on
      the column-header row, coloured by TR1's status class */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSE) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSM) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSU) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSA) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before {
    content: "";
    position: absolute;
    width: 4px;
    height: 24px;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    border-radius: 2px;
    pointer-events: none;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSE) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before {
    background-color: #b91c1c;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSM) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before {
    background-color: #f59e0b;
}
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSU) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before,
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN):has(img.jqQS.qSA) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child::before {
    background-color: #16a34a;
}

/* 4. script.js (PrepareCreateQStatusPopups) clones TR1's real img.jqQS into
   this header cell (.jqQSGridEcho) so the echoed bar has an actual element
   to click/hover, not just the decorative ::before. Same 4×24 footprint as
   the ::before it sits over, same invisible-overlay + cursor:help treatment
   as the qN-row marker (line ~669) — clicking/hovering the bar itself opens
   the popup / shows the native title tooltip, nothing outside it. */
body.sidebar-nav.page-questionnaire #tblQuestionnaire tr:has(.qN) + tr > td:has(.vqatable) .vqatable > thead > tr:first-child > th:first-child img.jqQSGridEcho {
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 4px;
    height: 24px;
    opacity: 0;
    cursor: help;
}

/* --------------------------------------------------------------------------
   Perf — content-visibility skip on off-screen rows.

   The questionnaire renders ~275 rows in #tblQuestionnaire. Only ~10 are above
   the fold on a typical viewport, but the browser still paints + lays out the
   other 265 on every render. `content-visibility: auto` tells the browser to
   skip layout/paint for any row whose box is off-screen until it scrolls into
   view (or close to it via the contain-intrinsic-size hint).

   contain-intrinsic-size gives the browser a placeholder height for off-screen
   rows so the scrollbar doesn't jump as rows resolve. 1px wide is a no-op for
   width (the cell math drives that); 48px height matches the typical row
   height (Inter 14/20 + 12px y-padding).

   Caveat: anchored fragment scroll (#row-12.3 links) and JS that probes
   row.offsetHeight on a not-yet-resolved row may read 0/wrong values. Both
   patterns aren't used in this form today. Modern browser only — Safari ≥18.
   -------------------------------------------------------------------------- */
body.page-questionnaire #tblQuestionnaire > tbody > tr {
    content-visibility: auto;
    contain-intrinsic-size: 1px 48px;
}

/* --------------------------------------------------------------------------
   Phase D Task 8 — Defensive guards (revert nested-table inputs)

   - Phase D's Task 4 / Task 7 rules target inputs/selects/textareas/radios
     inside the field cell of tr:has(.qN) data rows. When Phase E (inline
     tables: Cargo Tank, Ballast Tank, Pollution Incident — DESIGN.md §9.7)
     renders nested <table>s inside that cell with their own table-cell
     densities (36/40h per DESIGN.md §9.5.5), Phase D's 32h/8r/580w skin
     would clash.
   - This block uses `revert` to reset properties on descendants of any
     nested <table> inside the field cell, so Phase E can re-skin them
     freely. `revert` rolls back to the user-agent default — clean escape.
   - Purely defensive: the audited Q88 record (Task 1 discovery, IMO 1800251)
     contains zero nested <table> elements inside data-row field cells, so
     this block paints nothing today. It activates only when Phase E ships
     and starts nesting cargo/ballast/pollution-incident tables in cell 4.
   -------------------------------------------------------------------------- */

/* Inputs inside nested inline tables: reset Phase D Task 4 form-control skin. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) table input,
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) table select,
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) table textarea {
    width: auto;
    height: auto;
    padding: revert;
    border: revert;
    border-radius: revert;
    font-family: revert;
    font-size: revert;
    line-height: revert;
    color: revert;
}

/* Nested-table radios: reset Phase D Task 7 radio skin. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) table input[type="radio"] {
    width: revert;
    height: revert;
    margin: revert;
    accent-color: revert;
}

/* Nested-table radio labels: reset inter-pair margin so nested table flow
   (e.g. Phase E re-attempt cargo/ballast radios per DESIGN.md §9.5.5)
   isn't affected by the page-level Yes/No spacing rule. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) table input[type="radio"] + label {
    margin-right: revert;
    vertical-align: revert;
}

/* --------------------------------------------------------------------------
   Phase E (layout-safe re-attempt) — vqatable inline tables

   First Phase E attempt (commits c1bc1801 + d53bbc9c) was reverted
   (22fe1f85 + 4b713aeb) after shipping page-wide horizontal overflow on
   the questionnaire form. Root cause traced via in-browser bisect:

   1. `max-width: 1476px` on `table.vqatable` propagates UP the table-
      layout chain (vqatable nests 5 levels deep inside #tblQuestionnaire,
      itself a <table>). The nested `max-width` acts as a sizing hint and
      forced #tblQuestionnaire to grow from ~948px to 1764px — page
      overflowed by ~670px.
   2. `min-width: 85px` on heads adds 85*col_count to a table's minimum
      width — for the 11-col Cargo Tank Table that's 935px floor before
      content/padding.
   3. `padding: 8px` on every cell + `font-size: 14px` together push
      intrinsic cell widths past the parent cell's natural size, causing
      another ~210px of overflow even with #1 and #2 removed.

   This rewrite keeps the visual chrome users want (transparent bg,
   1px #e5e5e5 bottom border, Inter 14/20, dark text, 40h heads / 36h
   cells) but trades the Figma `padding: 8px` contract for `padding: 8px
   2px` (vertical 8, horizontal 2) so cells don't bloat horizontally.
   The Figma contract was designed for a 1476px-wide canvas; vqatable
   actually renders in a ~948px nested cell, so horizontal padding has
   to compress.

   Verified in browser (Edge via CDP):
     - widest vqatable: 1013px (vs legacy 883px, +130 acceptable)
     - page scrollWidth: 1513px (viewport 1528 → -15px buffer, clean)
     - chrome verified visually: transparent bg, 1px bottom border,
       Inter font, 14/20 sizing, dark text on light card.

   Branch B selectors (markup is `<table class="vqatable">` with
   `<thead class="vqath">`, `<tbody class="vqatbody">` + bare <th>/<td>):
   per Task 1 preflight, all 22 vqatable instances share this markup
   and live in unclassed rows under `#tblQuestionnaire`. Ancestor
   `tr:has(.qN) > td:nth-child(4)` from the original plan dropped
   because rows containing vqatable have no class.

   Specificity (0,1,3,3) beats both the legacy `.vqath` rule (0,0,1,0)
   and the per-table inline <style> `.vqatable th { border: 1px solid
   #E5E5E5 }` (0,0,1,1) injected by HtmlBuilder.cs:565. No `!important`
   needed.

   Rollback: single feature flag `EnableRefreshedFrontend = false`
   removes `body.page-questionnaire` body class → these rules go inert.
   -------------------------------------------------------------------------- */

/* Table header cells (column titles like "Tank ID", "Tank PSC") — 14px Medium.
   #pnlQuestionnaires duplicates target the View flow (ViewShip.aspx / DesktopDefault?i=),
   whose inline tables share the identical vqatable/vqath markup but live under a
   different container id than the Create flow's #tblQuestionnaire. Without these the
   View-flow column titles render the legacy navy `.vqath` colour (#003366). */
body.page-questionnaire #tblQuestionnaire table.vqatable thead.vqath th,
body.page-questionnaire #tblQuestionnaire table.vqatable thead.vqath td,
body.page-questionnaire #tblQuestionnaire table.vqatable > thead th,
body.page-questionnaire #tblQuestionnaire table.vqatable > thead td,
body.page-questionnaire #pnlQuestionnaires table.vqatable thead.vqath th,
body.page-questionnaire #pnlQuestionnaires table.vqatable thead.vqath td,
body.page-questionnaire #pnlQuestionnaires table.vqatable > thead th,
body.page-questionnaire #pnlQuestionnaires table.vqatable > thead td {
    background-image: none;
    background-color: transparent;
    border: none;
    border-bottom: 1px solid var(--border);
    color: var(--foreground);
    font-family: var(--raw-font-family-modern);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    line-height: var(--raw-space-12);
    padding: var(--raw-space-6);
    text-align: left;
    vertical-align: middle;
}

/* Table body cells — content text 14px Regular */
body.page-questionnaire #tblQuestionnaire table.vqatable tbody.vqatbody td,
body.page-questionnaire #tblQuestionnaire table.vqatable > tbody td,
body.page-questionnaire #pnlQuestionnaires table.vqatable tbody.vqatbody td,
body.page-questionnaire #pnlQuestionnaires table.vqatable > tbody td {
    background-color: transparent;
    border: none;
    border-bottom: 1px solid var(--border);
    color: var(--foreground);
    font-family: var(--raw-font-family-modern);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-normal);
    line-height: var(--raw-space-12);
    padding: var(--raw-space-6);
    vertical-align: middle;
    /* Left-align data rows to line up under the (already left-aligned)
       headers. Beats the per-table inline `<style>` rule
       `.vqatbody { text-align: center }` injected by HtmlBuilder.cs:565
       on specificity (0,1,3,3) > (0,1,0). */
    text-align: left;
}

body.page-questionnaire #tblQuestionnaire table.vqatable,
body.page-questionnaire #pnlQuestionnaires table.vqatable {
    border-collapse: collapse;
    background-color: transparent;
}

/* Drop the bottom border on the final body row so the inner vqatable doesn't
   render a hanging divider below its last cell. */
body.page-questionnaire #tblQuestionnaire table.vqatable tbody.vqatbody tr:last-child > td,
body.page-questionnaire #tblQuestionnaire table.vqatable > tbody tr:last-child > td,
body.page-questionnaire #pnlQuestionnaires table.vqatable tbody.vqatbody tr:last-child > td,
body.page-questionnaire #pnlQuestionnaires table.vqatable > tbody tr:last-child > td {
    border-bottom: none;
}

/* View flow only — contain inline tables within the card at any viewport width.
   1. table-layout:fixed + width:100% forces each inline table to fit its host
      cell rather than grow to its intrinsic (nowrap) width. The widest variant
      — the 15-column Mooring lines table — otherwise inflates to ~2344px and,
      via the DNN table-shrink-to-fit chain, pushes the whole page past the
      viewport on wide monitors (and overflows the card on narrow ones). A
      RELATIVE width:100% fills the host cell without the chain-widening that a
      fixed-px max-width caused — see the Phase E post-mortem above.
   2. white-space:normal lets column content wrap within its fixed share. The
      host is a first-child td.GridData.VBorderRight, which inherits
      `white-space: nowrap` from the question-number-cell rule (~L464); without
      this the columns can't wrap and content overflows the fixed cells.
   Scoped to #pnlQuestionnaires (read-only View). The Create flow
   (#tblQuestionnaire) hosts editable inputs in these cells and stays on auto
   layout — see the questionnaire page-width deferral. */
body.page-questionnaire #pnlQuestionnaires table.vqatable {
    table-layout: fixed;
    width: 100%;
}
body.page-questionnaire #pnlQuestionnaires table.vqatable th,
body.page-questionnaire #pnlQuestionnaires table.vqatable td {
    white-space: normal;
}

/* ============================================================
   Phase F — Bottom status toolbar
   Spec: docs/plans/2026-04-30-questionnaire-form-refresh-spec.md §9.7 (Frame 25)
   Scope: body.page-questionnaire .q88-status-toolbar
   Rollback: Set EnableRefreshedFrontend=false → body class drops
            → these rules stop matching → toolbar reverts to legacy
            <table> chrome (which now has no <img> swatches,
            so it renders as plain-text chips — see plan Risks #5).
   ============================================================ */

body.page-questionnaire .q88-status-toolbar {
    position: sticky;
    bottom: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: 48px;
    padding: 0 16px;
    margin: 0;
    background: var(--card, #ffffff);
    border-top: 1px solid var(--border, #e2e8f0);
    box-shadow: 0 -1px 2px 0 rgba(0, 0, 0, 0.05);
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
}

/* The Continue PopupMenu lives inside this sticky bottom toolbar. AjaxToolkit's
   PopupControlExtender positioned its panel OVERLAPPING the button (panel bottom
   fell ~34px into the button top), so a real click's mouseup landed on the panel
   instead of the button: no `click` fired and PopupControlBehavior's body-click
   handler hid the just-(focus-)shown panel. Net — the menu "needed multiple
   clicks" (QEN-8704 #5c) and visually covered the button (#5a). The toolbar is
   position:sticky (a positioning context), so anchor the panel FULLY ABOVE the
   button, right-aligned, overriding AjaxToolkit's inline top/left. */
body.page-questionnaire .q88-status-toolbar .popupMenuV2 {
    position: absolute !important;
    top: auto !important;
    left: auto !important;
    right: 16px !important;
    bottom: calc(100% + 8px) !important;
}

/* Strip default chrome from the legacy chip <table> directly inside the toolbar */
body.page-questionnaire .q88-status-toolbar > table {
    border-collapse: collapse;
    margin: 0;
    padding: 0;
    background: transparent;
}
body.page-questionnaire .q88-status-toolbar > table tr,
body.page-questionnaire .q88-status-toolbar > table td {
    padding: 0;
    border: none;
    background: transparent;
    vertical-align: middle;
}
body.page-questionnaire .q88-status-toolbar > table td {
    padding-right: 6px;
}
body.page-questionnaire .q88-status-toolbar > table td:last-child {
    padding-right: 0;
}

/* Chip labels never wrap mid-label — keeps "Required Field", "Officer Matrix" intact at narrow widths
   (replaces the legacy &nbsp; in <b>Required&nbsp;Field</b> that the markup rewrite dropped). */
body.page-questionnaire .q88-status-toolbar .q88-status-chip {
    white-space: nowrap;
}

/* ============================================================
   Phase F — Chip base + per-state colored bar ::before
   Spec: docs/plans/2026-04-30-questionnaire-form-refresh-spec.md §9.7
   Each chip is a flex row of [4w x 20h colored bar | 8px gap | label].
   ============================================================ */

/* Chip base — flex container holding the colored bar + label.
   Longhand font-* used for consistency with the rest of questionnaire.css
   (sibling rules use font-family/font-size/font-weight, not the `font:` shorthand). */
body.page-questionnaire .q88-status-toolbar .q88-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 36px;
    padding: 0 8px;
    border-radius: 8px;
    background: transparent;
    color: var(--foreground, #0f172a);
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    font-size: 14px;
    font-weight: 500;
    line-height: 20px;
    cursor: default;
    vertical-align: middle;
}

/* The 4w x 20h colored bar — pseudo-element so each state can swap color.
   Required chip's ::before content stays as the empty bar for now;
   Task 5 will overwrite it with "*". */
body.page-questionnaire .q88-status-toolbar .q88-status-chip::before {
    content: "";
    flex: 0 0 auto;
    width: 4px;
    height: 20px;
    border-radius: 2px;
    background: transparent;  /* default; per-state rules override */
}

/* Per-state bar colors — spec §9.7. Hard-coded literals (NOT tokenized)
   because state colors are universal across light/dark modes. */
body.page-questionnaire .q88-status-toolbar .q88-status-chip--expired::before  { background: #b91c1c; }   /* red/700 */
body.page-questionnaire .q88-status-toolbar .q88-status-chip--missing::before  { background: #ff991a; }   /* orange */
body.page-questionnaire .q88-status-toolbar .q88-status-chip--updated::before  { background: #16a34a; }   /* green/600 */
body.page-questionnaire .q88-status-toolbar .q88-status-chip--answered::before { background: #1d4ed8; }   /* blue/700 */

/* Required chip — no bar; render a red * glyph instead.
   Overrides the base ::before width/height/background from Task 4. */
body.page-questionnaire .q88-status-toolbar .q88-status-chip--required::before {
    content: "*";
    width: auto;
    height: auto;
    background: transparent;
    color: #b91c1c;            /* red/700 — same as Phase D row glyph */
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    font-size: 18px;
    font-weight: 700;
    line-height: 1;
    flex: 0 0 auto;
}

/* Icon chips (Officer Matrix / Loadline / Vetting) — render the legacy PNG icon
   in a 16x16 ::before. Same chip shell, but the bar pseudo-element becomes an icon.
   Lucide SVG upgrade with currentColor tinting deferred to a follow-up ticket. */
body.page-questionnaire .q88-status-toolbar .q88-status-chip--officer-matrix::before,
body.page-questionnaire .q88-status-toolbar .q88-status-chip--loadline::before,
body.page-questionnaire .q88-status-toolbar .q88-status-chip--vetting::before {
    width: 16px;
    height: 16px;
    background-color: transparent;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    border-radius: 0;
}

body.page-questionnaire .q88-status-toolbar .q88-status-chip--officer-matrix::before {
    background-image: url('/images/icons/officerMatrix2.png');
}
body.page-questionnaire .q88-status-toolbar .q88-status-chip--loadline::before {
    background-image: url('/images/icons/loadline.png');
}
body.page-questionnaire .q88-status-toolbar .q88-status-chip--vetting::before {
    background-image: url('/images/icons/vetting.png');
}

/* Refresh skin — swap the legacy PNG bitmaps for Lucide SVG masks per
   DESIGN.md §9.8 (Officer Matrix → User-star, Loadline → Ruler, Vetting →
   FileCheck). `background-color: currentColor` paints the mask with the
   chip's text color so all three icons read as a unified slate-900 stroke. */
body.sidebar-nav.page-questionnaire .q88-status-toolbar .q88-status-chip--officer-matrix::before,
body.sidebar-nav.page-questionnaire .q88-status-toolbar .q88-status-chip--loadline::before,
body.sidebar-nav.page-questionnaire .q88-status-toolbar .q88-status-chip--vetting::before {
    background-image: none;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: 16px 16px;
            mask-size: 16px 16px;
}

body.sidebar-nav.page-questionnaire .q88-status-toolbar .q88-status-chip--officer-matrix::before {
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M8 21v-1a4 4 0 0 1 4-4'/><path d='M17.8 22 16 20.5l-1.8 1.5.7-2.4-1.9-1.6h2.4l.8-2.3.8 2.3h2.4l-1.9 1.6Z'/><circle cx='10' cy='8' r='5'/></svg>");
            mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M8 21v-1a4 4 0 0 1 4-4'/><path d='M17.8 22 16 20.5l-1.8 1.5.7-2.4-1.9-1.6h2.4l.8-2.3.8 2.3h2.4l-1.9 1.6Z'/><circle cx='10' cy='8' r='5'/></svg>");
}

body.sidebar-nav.page-questionnaire .q88-status-toolbar .q88-status-chip--loadline::before {
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z'/><path d='m14.5 12.5 2-2'/><path d='m11.5 9.5 2-2'/><path d='m8.5 6.5 2-2'/><path d='m17.5 15.5 2-2'/></svg>");
            mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z'/><path d='m14.5 12.5 2-2'/><path d='m11.5 9.5 2-2'/><path d='m8.5 6.5 2-2'/><path d='m17.5 15.5 2-2'/></svg>");
}

body.sidebar-nav.page-questionnaire .q88-status-toolbar .q88-status-chip--vetting::before {
    -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5z'/><polyline points='14 2 14 8 20 8'/><path d='m9 15 2 2 4-4'/></svg>");
            mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5z'/><polyline points='14 2 14 8 20 8'/><path d='m9 15 2 2 4-4'/></svg>");
}

/* ============================================================
   Phase F — Continue button (teal pill).
   Re-skins the <uc:PopupMenu ID="popMenuContinue"> rendered
   <a class="LinkButton">. Scoped to the toolbar so other
   .LinkButton uses elsewhere on the page are unaffected.
   !important wins against legacy MainWhiteout.css/Main.css
   .LinkButton rules that already use !important on bg/color.
   ============================================================ */

/* Direct-child combinator only — the popup panel (.popupMenuV2) is rendered as
   a sibling of the trigger inside the toolbar; broader selectors leak teal-pill
   styling into the panel and the .LinkButton menu items it contains. */
body.page-questionnaire .q88-status-toolbar > a.LinkButton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    min-width: 93px;
    padding: 0 16px !important;
    border-radius: 8px;
    background-color: var(--primary) !important;
    color: #eff6ff !important;
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    font-size: 14px;
    font-weight: 500 !important;
    line-height: 20px;
    text-decoration: none !important;
    border: none;
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
    cursor: pointer;
}

body.page-questionnaire .q88-status-toolbar > a.LinkButton:hover {
    background-color: var(--button-primary-hover) !important;  /* slightly darker teal on hover */
    color: #eff6ff !important;
}

body.page-questionnaire .q88-status-toolbar > a.LinkButton:focus-visible {
    outline: 2px solid var(--button-primary-hover);
    outline-offset: 2px;
}

/* Hide the legacy <ins>&nbsp;</ins> leading spacer + trailing 1x1 clearpixel.gif —
   the Figma button has no leading icon. */
body.page-questionnaire .q88-status-toolbar > a.LinkButton ins,
body.page-questionnaire .q88-status-toolbar > a.LinkButton img {
    display: none;
}

/* Print — drop sticky positioning so the toolbar doesn't occlude content */
@media print {
    body.page-questionnaire .q88-status-toolbar {
        position: static;
        box-shadow: none;
        border-top: 1px solid #000;
    }
}

/* ==========================================================================
   EditQuestionAnswer modal chrome — Figma 62:15648
   The mpeUDF Modal on CreateQuestionnaire.ascx renders as #pnlModalPopup
   (ClientIdMode="Static") wrapping the legacy AjaxToolkit corner-image table.
   Default chrome = navy hdrTblBar with red close_red.gif + corner cells.
   Figma shows a flat white card: bold dark title left, plain X right, a clean
   border below, and the inner indigo strip directly underneath.

   Scoped tightly:
     - body.sidebar-nav.page-questionnaire — feature flag gate (matches the
       inner iframe's CSS gating in Blank.master.cs)
     - #pnlModalPopup — only mpeUDF gets the bare ID; every other Modal.ascx
       instance on this page renders with a ctl00_..._ prefix (verified live).
   ========================================================================== */
body.sidebar-nav.page-questionnaire #pnlModalPopup.modPopPnl {
    background: #ffffff;
    border: 1px solid var(--raw-slate-200, #e2e8f0);
    border-radius: 8px;
    box-shadow:
        0 10px 15px -3px rgba(0, 0, 0, 0.10),
        0 4px 6px -4px rgba(0, 0, 0, 0.10);
    overflow: hidden;
}

/* Strip legacy corner-image chrome (`<td class="modPopContentTop">`,
   `.leftCornerIcon`, `.rightCornerIcon`) and the outer table padding. */
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopupTbl {
    width: 100% !important;
    border-collapse: collapse;
    background: transparent !important;
}
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopupTbl > tbody > tr:first-child,
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopupTbl .leftCornerIcon,
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopupTbl .rightCornerIcon,
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopupTbl .modPopContentTop {
    display: none !important;
}

/* Header row — `.hdrTblBar` is the drag handle. Keep the inner table layout
   (title cell + close cell) so AjaxToolkit's drag math still latches onto
   `#pnlPopHdrbar` (`.modPopTitlePnl`). */
body.sidebar-nav.page-questionnaire #pnlModalPopup .hdrTblBar {
    background: #ffffff !important;
    background-image: none !important;
    color: var(--raw-slate-900, #0f172a) !important;
    border-bottom: 1px solid var(--raw-slate-200, #e2e8f0) !important;
    padding: 16px 20px !important;
    height: auto !important;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 16px !important;
    line-height: 24px !important;
    font-weight: 700 !important;
    cursor: move;
}
body.sidebar-nav.page-questionnaire #pnlModalPopup .hdrTblBar > table {
    background: transparent !important;
    width: 100% !important;
}
body.sidebar-nav.page-questionnaire #pnlModalPopup .hdrTblBar > table td {
    background: transparent !important;
    padding: 0 !important;
    border: 0 !important;
    vertical-align: middle;
}

/* Title text — Inter 16/24/700 slate-900 */
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopTitlePnl,
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopTitlePnl span,
body.sidebar-nav.page-questionnaire #pnlModalPopup .popupTitleSub {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    color: var(--raw-slate-900, #0f172a) !important;
    font-size: 16px !important;
    line-height: 24px !important;
    font-weight: 700 !important;
    background: transparent !important;
    text-shadow: none !important;
}

/* Close button — replace `<img src="close_red.gif">` with a Lucide X mask.
   Anchor stays interactive (Modal.ascx wires `onClick="ShowModal(...)"`). */
body.sidebar-nav.page-questionnaire #pnlModalPopup #lnkClose {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 4px;
    color: var(--raw-slate-600, #475569);
    text-decoration: none;
    cursor: pointer;
}
body.sidebar-nav.page-questionnaire #pnlModalPopup #lnkClose:hover {
    color: var(--raw-slate-900, #0f172a);
    background: var(--raw-slate-100, #f1f5f9);
}
body.sidebar-nav.page-questionnaire #pnlModalPopup #lnkClose img {
    display: none !important;
}
body.sidebar-nav.page-questionnaire #pnlModalPopup #lnkClose::before {
    content: "";
    display: block;
    width: 18px;
    height: 18px;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>") no-repeat center / 18px;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>") no-repeat center / 18px;
}

/* Questionnaire table wrapper — replaces the legacy inline
   `style="background-color:#f8f8f8; border:1px solid #adadad;"` on
   CreateQuestionnaire.ascx:760. Per re-skin: data rows render on a clean
   white card surface; only section headers carry the light-blue band
   (qTypeH at #f1f5f9). var(--card) lets dark mode flip the surface. */
body.page-questionnaire .qTblWrap {
    background-color: var(--card, #ffffff);
}

/* Content cell + iframe wrapper — strip the .mainBG cell padding so the
   indigo strip inside the iframe sits flush below the new header. */
body.sidebar-nav.page-questionnaire #pnlModalPopup .mainBG {
    background: #ffffff !important;
    padding: 0 !important;
    border: 0 !important;
}
body.sidebar-nav.page-questionnaire #pnlModalPopup .modPopContent {
    padding: 0 !important;
    background: transparent !important;
}

/* ==========================================================================
   modVetting modal chrome — QEN-8656 Frontend refresh
   The Vetting Details modal is the second <uc:Modal> instance on this page
   (CreateQuestionnaire.ascx:571, opened from the 3-dot Actions menu via
   showVettings() → ShowModal('modVetting', true)). Unlike mpeUDF — which has
   ClientIdMode="Static" so its inner panel renders as the bare #pnlModalPopup
   matched by the block above — modVetting has no static ClientIdMode, so its
   inner <asp:Panel id="pnlModalPopup"> renders as
   `<naming-prefix>_modVetting_pnlModalPopup`. Mirror the chrome rules using
   a [id$="_modVetting_pnlModalPopup"] suffix-match (per memory
   feedback_aspnet-naming-container-id-selectors: substring match overshoots
   into nested children sharing the naming-container prefix).
   ========================================================================== */
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"].modPopPnl {
    background: #ffffff;
    border: 1px solid var(--raw-slate-200, #e2e8f0);
    border-radius: 8px;
    box-shadow:
        0 10px 15px -3px rgba(0, 0, 0, 0.10),
        0 4px 6px -4px rgba(0, 0, 0, 0.10);
    overflow: hidden;
}

body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopupTbl {
    width: 100% !important;
    border-collapse: collapse;
    background: transparent !important;
}
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopupTbl > tbody > tr:first-child,
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopupTbl .leftCornerIcon,
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopupTbl .rightCornerIcon,
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopupTbl .modPopContentTop {
    display: none !important;
}

body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .hdrTblBar {
    background: #ffffff !important;
    background-image: none !important;
    color: var(--raw-slate-900, #0f172a) !important;
    border-bottom: 1px solid var(--raw-slate-200, #e2e8f0) !important;
    padding: 16px 20px !important;
    height: auto !important;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 16px !important;
    line-height: 24px !important;
    font-weight: 700 !important;
    cursor: move;
}
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .hdrTblBar > table {
    background: transparent !important;
    width: 100% !important;
}
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .hdrTblBar > table td {
    background: transparent !important;
    padding: 0 !important;
    border: 0 !important;
    vertical-align: middle;
}

body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopTitlePnl,
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopTitlePnl span,
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .popupTitleSub {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    color: var(--raw-slate-900, #0f172a) !important;
    font-size: 16px !important;
    line-height: 24px !important;
    font-weight: 700 !important;
    background: transparent !important;
    text-shadow: none !important;
}

/* Close anchor — Modal.ascx hard-codes id="lnkClose" on the runat="server" <a>,
   so the rendered id is `<naming-prefix>_modVetting_lnkClose`. */
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] a[id$="_lnkClose"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 4px;
    color: var(--raw-slate-600, #475569);
    text-decoration: none;
    cursor: pointer;
}
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] a[id$="_lnkClose"]:hover {
    color: var(--raw-slate-900, #0f172a);
    background: var(--raw-slate-100, #f1f5f9);
}
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] a[id$="_lnkClose"] img {
    display: none !important;
}
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] a[id$="_lnkClose"]::before {
    content: "";
    display: block;
    width: 18px;
    height: 18px;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>") no-repeat center / 18px;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>") no-repeat center / 18px;
}

body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .mainBG {
    background: #ffffff !important;
    padding: 0 !important;
    border: 0 !important;
}
body.sidebar-nav.page-questionnaire [id$="_modVetting_pnlModalPopup"] .modPopContent {
    padding: 0 !important;
    background: transparent !important;
}

/* ==========================================================================
   Phase H — Header re-skin (QEN-8776, Headers/Subheaders Fixes)
   Figma: ZrCO5nudzyQMi1LXRzj4eW node 197:3974
   --------------------------------------------------------------------------
   1. The first qTypeN row in #tblQuestionnaire (full questionnaire name —
      "INTERTANKO CHARTERING QUESTIONNAIRE 88 - Oil (Version 6)") is moved
      into the title-block subtitle and tagged with .q88-tophdr-source by JS
      in CreateQuestionnaire.ascx. Hide that flagged row here.
   2. All other qTypeN rows are inline group sub-headers ("Ownership and
      Operation", "Vapor Emission Control System (VECS)", etc.). Paint a 16px
      Lucide CornerDownRight glyph at x=12 of the cell, with text pushed to
      x=60 to match Figma node 197:3972 / 197:3973 (icon@x=12, text@x=60).
   ========================================================================== */

/* Pure-CSS replacement for the previous JS `addClass('q88-tophdr-source')`
   approach: hide the FIRST qTypeN row from the first paint so the page never
   visibly shifts up when the header re-skin runs. The general-sibling combinator
   `tr.qTypeN ~ tr.qTypeN` matches every qTypeN that's preceded by another
   qTypeN (i.e. second + later) — anything NOT matched is the first qTypeN, so
   the default `display: none` lands on exactly the row that holds the full
   questionnaire name. */
body.page-questionnaire #tblQuestionnaire tr.qTypeN {
    display: none;
}
body.page-questionnaire #tblQuestionnaire tr.qTypeN ~ tr.qTypeN {
    display: table-row;
}
/* Legacy class kept for backward compat with any code/markup that still adds it. */
body.page-questionnaire #tblQuestionnaire tr.qTypeN.q88-tophdr-source {
    display: none;
}

/* Single-cell sub-headers ("Ownership and Operation", etc. — colspan=5 with no .qN).
   Scoped via :not(:has(.qN)) so the numbered variant ("8.6 Max loading rate...")
   keeps its native two-cell layout (its .qN cell already aligns with the question-
   number column and cell 2 already aligns with the question-text column). */
body.page-questionnaire #tblQuestionnaire tr.qTypeN:not(.q88-tophdr-source):not(:has(.qN)) > td {
    padding-left: 40px;                                     /* left-align text next to its ::before ↳ icon (icon left 12px + 16px wide + gap) instead of floating at the question-text column */
    position: relative;
    background-color: var(--surface-muted);                              /* Figma 197:2995 bg: base/accent → #f1f5f9 */
    border-bottom: 1px solid #e5e5e5;                       /* Figma 197:2995 border-b: base/border → #e5e5e5 */
    color: var(--text-secondary);                                         /* slate-700 — darker so sub-headers stand out (one step below the slate-900 section bands) */
}
/* Tame the legacy <b> wrap inside sub-headers — browser default boosts to 700/900
   and clashes with the Figma "semi-bold" intent. */
body.page-questionnaire #tblQuestionnaire tr.qTypeN b {
    font-weight: var(--font-weight-semibold);
}
body.page-questionnaire #tblQuestionnaire tr.qTypeN:not(.q88-tophdr-source):not(:has(.qN)) > td::before {
    content: "";
    position: absolute;
    left: 12px;                                             /* icon x=12 per Figma 197:3972 */
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
    height: 16px;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg 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'><polyline points='15 10 20 15 15 20'/><path d='M4 4v7a4 4 0 0 0 4 4h12'/></svg>") no-repeat center / 16px;
            mask: url("data:image/svg+xml;utf8,<svg 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'><polyline points='15 10 20 15 15 20'/><path d='M4 4v7a4 4 0 0 0 4 4h12'/></svg>") no-repeat center / 16px;
    pointer-events: none;
}

/* Title block typography — match Figma 197:2947 (title) + 197:2948 (subtitle).
   Phase B set 20/24 + 11/13 which predates this design pass. Figma reads:
     title  = text-base/leading-none/semibold → 16/1/600, color base/foreground #0f0f0f
     subtitle = ~13px / leading-none / normal, color base/muted-foreground #757575

   The legacy DNN/ASP `<td>` ancestor of `.q88-card` carries `text-align: center`
   (resolves to `-webkit-center` and propagates through inheritance), which
   centers the h2 / span TEXT inside their flex item even though the flex layout
   itself is left-anchored. Re-assert `text-align: left` on the tophdr column
   and its children. */
body.page-questionnaire .q88-tophdr__left,
body.page-questionnaire .q88-tophdr__title,
body.page-questionnaire .q88-tophdr__subtitle {
    text-align: left;
}
body.page-questionnaire .q88-tophdr__title {
    font-size: 16px;
    line-height: 24px;                                      /* Figma title box = 24h; visual breathing kept */
    color: #0f0f0f;                                         /* base/foreground per tokens.json */
}
body.page-questionnaire .q88-tophdr__subtitle {
    font-size: 13px;
    line-height: 1;
    color: #757575;                                         /* base/muted-foreground per tokens.json */
}

/* --------------------------------------------------------------------------
   Phase I — Question-number font-size + single-line row-height alignment
   (QEN-8776 Headers/Subheaders follow-up)

   1. Question-number font-size: standardize to 14px. Phase D Task 7 (L1211)
      sets 13px on radio rows as a "visual differentiator" per spec §9.5.4 —
      user feedback overrides: numbers must read at 14px everywhere.
   2. Single-line row height: collapse 50/58/60/62 variants to a uniform 48px.
      Measured cause of variance:
        - data row TD vertical padding = 12+12 (24)
        - qDiv min-height = 32 for inputs/selects (yields 56 → 58 visual)
        - .qCal date-picker input = 24px (vs 22px text input) bloats qDiv to 36
        - radio rows clear min-height to 0, settling at 24+24 = 50
      Fix: TD padding 8+8 (16) + qDiv pinned 32 + .qCal 22 → 16+32 = 48 for
      input/select/date; radio rows lifted by explicit TD height: 48.
      Excludes textarea + .UDFFormControlForValidation (multi-input chip)
      so those keep growing.
   -------------------------------------------------------------------------- */

/* (1) Question-number font-size — override Phase D Task 7's 13px on radio rows. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(input[type="radio"]) > td:nth-child(1) {
    font-size: 14px;
}

/* (2a) Data-row TD: border-box sizing so 48 is the total cell height (the row
   has 1px top + 1px bottom borders per Phase D row-divider chrome — 2px is
   eaten by border alone). Padding 6+6 (12 total) + border 2 = 14 chrome,
   leaving 34px content area for the qDiv (qDiv pinned to 32 in 2c — fits with
   2px spare for vertical alignment).
   Scoped to data rows only — qTypeH section bands + qTypeN sub-sections keep
   their existing geometry. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN):not(.qTypeH):not(.qTypeN) > td {
    box-sizing: border-box;
    padding-top: 6px;
    padding-bottom: 6px;
}

/* (2b) Single-line rows: TD `min-height: 48px` floor (border-box, so 48 is
   total cell height). For radio rows (qDiv collapses to 24) this forces 48;
   for control rows the 12 TD pad + 2 border + 32 qDiv = 46 → floor lifts to
   48. Multi-line rows (textarea, UDF, multi-input chips, ASP CheckBoxList)
   can still grow above 48 because it's min, not max.

   Exclude rows whose answer is an ASP CheckBoxList (`span.qCblRequired` /
   `qCblOptional` wrapper inside .qDiv). The cbl span renders checkboxes on
   multiple lines separated by `<br>`, so the TD needs to grow with content. */
body.page-questionnaire #tblQuestionnaire
  tr:has(.qN):not(.qTypeH):not(.qTypeN):not(:has(textarea)):not(:has(.UDFFormControlForValidation)):not(:has([class*="qCbl"])) > td {
    height: 48px;
}

/* (2c) qDiv: pin to 32px on single-control rows so .qCal date-pickers (24h input)
   stop bloating to 36. Exclude qDivs containing textarea (multi-line),
   multiple input siblings (1.10 / 1.11 / 1.12 multi-input chips), or an ASP
   CheckBoxList wrapper (`span[class*="qCbl"]` — inputs nested under the span
   so the `> input ~ input` exclusion misses them). For the CBL case the qDiv
   needs to grow with content and align children to the top instead of center. */
body.page-questionnaire #tblQuestionnaire
  tr:has(.qN):not(:has(textarea)):not(:has(.UDFFormControlForValidation)) > td:nth-child(4) > .qDiv:not(:has(textarea)):not(:has(> input ~ input)):not(:has([class*="qCbl"])) {
    height: 32px;
    min-height: 32px;
}

/* (2c.cbl) ASP CheckBoxList answer (e.g. 10.12 NOx Tier III equipment list):
   the qDiv must grow to fit the multi-row checkbox span. Override the flex
   default (`align-items: center` from block B) so checkboxes stack from the
   top, and add vertical padding so the frame looks balanced. */
body.page-questionnaire #tblQuestionnaire
  tr:has(.qN) > td:nth-child(4) > .qDiv:has([class*="qCbl"]) {
    height: auto;
    min-height: 32px;
    align-items: flex-start;
    padding-top: 6px;
    padding-bottom: 6px;
}

/* (2d) Date-picker input height: 22px (was 24px) so it fits the 32 qDiv frame
   identically to plain text inputs (.qTxt is 22px). */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) input.qCal {
    height: 22px;
}

/* --------------------------------------------------------------------------
   Phase J — Larger-question alignment + comment-icon gap
   (QEN-8776 follow-up: 2026-05-28 user feedback on Figma node 198:3975
   "Improve alignment for larger questions")

   1. Top-align cells 1-4 in multi-line rows (textarea + UDF) so the row
      number, question label, status icon, and input field all share the
      same top edge instead of vertically centering against a tall input.
      Cell 5 (comment icon) keeps vertical-align: middle per Figma 198:3991
      (icon vertically centered in multi-line row).
   2. Reduce the gap between cell 4 (input/answer field) right edge and the
      comment icon to 8px (was 24px+ depending on table-auto-layout width
      distribution). Matches Figma 198:3987 InputGroup-end-to-icon-start gap
      (input ends x=944, icon at x=952). Done by zeroing cell 4 padding-right
      and switching cell 5 to text-align: left + padding-left: 8px so the
      icon left-anchors regardless of how table-auto-layout sizes cell 5.
   -------------------------------------------------------------------------- */

/* (J1) Top-align cells 1-4 in multi-line rows. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(textarea) > td:not(:nth-child(5)),
body.page-questionnaire #tblQuestionnaire tr:has(.qN):has(.UDFFormControlForValidation) > td:not(:nth-child(5)) {
    vertical-align: top;
}

/* (J2) Tighten cell 4 → cell 5 gap to 8px (Figma 198:3987 / 198:3990).
   Cell 4 padding-right: 0 lets the input/qDiv extend to cell 4 right edge.
   Cell 5 text-align: left + padding-left: 8px anchors the icon 8px from cell 5
   left edge regardless of cell 5's auto-sized width. */
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(4) {
    padding-right: 0;
}
body.page-questionnaire #tblQuestionnaire tr:has(.qN) > td:nth-child(5) {
    text-align: left;
    padding-left: 8px;
}
