/* HAREC - dense, data-entry-first internal tool. Desktop-first (see UI_guideline.md). */

:root {
  --color-border: #d0d5dd;
  --color-muted: #667085;
  --color-bg: #f9fafb;
  --color-header-bg: #eef1f5;
  --color-accent: #2b5797;
  --color-primary: #007aff;
  --color-primary-hover: #0071eb;
  --color-primary-active: #0064d1;
  --color-text: #1d2939;
  --color-high: #f8d7da;
  --color-high-text: #842029;
  --color-high-hover: #f5c2c7;
  --color-medium: #fff3cd;
  --color-medium-text: #664d03;
  --color-low: #d1e7dd;
  --color-low-text: #0f5132;
  --row-height: 28px;
  --radius-md: 8px;
  --radius-sm: 6px;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.08);
  --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.10);
  --shadow-focus: 0 0 0 3px rgba(0, 122, 255, 0.35);
  --transition-btn: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Arial, sans-serif;
  font-size: 14px;
  color: var(--color-text);
  background: var(--color-bg);
}

a { color: var(--color-accent); }

/* Global scrollbar/selection -- same muted/bg palette as .grid-wrapper's
   own styled scrollbar (below), just thinner, so the rest of the app
   doesn't fall back to a mismatched OS-default scrollbar right next to the
   grid's styled one. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-muted) var(--color-bg);
}
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track {
  background: var(--color-bg);
}
::-webkit-scrollbar-thumb {
  background: var(--color-muted);
  border-radius: 6px;
  border: 2px solid var(--color-bg);
}
::-webkit-scrollbar-thumb:hover {
  background: var(--color-accent);
}
::selection {
  background: rgba(0, 122, 255, 0.2);
}

.topnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #fff;
  border-bottom: 1px solid var(--color-border);
  padding: 8px 16px;
  box-shadow: var(--shadow-sm);
}

.topnav-brand { display: flex; align-items: center; gap: 8px; font-weight: 700; }
.topnav-logo { width: 24px; height: 24px; }

.topnav-links a {
  margin-right: 4px;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--color-text);
  font-weight: 500;
  transition: var(--transition-btn);
}
.topnav-links a:hover {
  background: #f0f7ff;
  color: var(--color-primary-hover);
}
.topnav-links a.current {
  background: var(--color-primary);
  color: #fff;
  font-weight: 600;
}
.topnav-links a.current:hover {
  background: var(--color-primary-hover);
}

.topnav-user {
  display: flex;
  align-items: center;
  gap: 8px;
}

.page {
  padding: 16px;
  max-width: 1400px;
  margin: 0 auto;
}

/* Login page: centers the otherwise plain top-left-floating form in a
   raised card, matching the Apple-style depth used elsewhere (buttons,
   context menu, sheet-tabs) instead of leaving auth as the one bare page
   in the app. Column direction (not row) so the flash-list -- a sibling
   rendered before {% block content %} in base.html, e.g. "Please log in
   to access this page." -- stacks directly above the card instead of
   floating beside it. */
.page.page-auth {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 8vh;
}
.page-auth .flash-list {
  width: 100%;
  max-width: 360px;
}
.auth-card {
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 32px;
  width: 100%;
  max-width: 360px;
}
.auth-card h1 { margin-top: 0; }
.auth-logo { display: block; width: 48px; height: 48px; margin: 0 auto 16px; }
.auth-card form.stacked-form { max-width: none; }
/* The Google link sits outside the flex form above, so it doesn't inherit
   that form's full-width stretch -- as a plain inline <a> it hugged the
   card's left edge while the "Log in" button spanned the full width
   directly above it, which read as misaligned. Centering it (and its
   helper line) puts it back on the card's vertical axis, the same one the
   logo already uses. Not stretched full-width on purpose: the primary
   action stays the widest element, so the alternative doesn't compete
   with it. */
.auth-alt { margin-top: 16px; text-align: center; }
.auth-alt p { margin: 8px 0 0; }

/* Worksheet pages (HAZID/HAZOP/LOPA grids) drop the shared page's 1400px
   reading-width cap and tighten the heading/description spacing above the
   grid -- unlike a form or a list, this page's whole point is the grid
   itself, so the more of the viewport it can use (width and height both),
   the less scrolling a dense HAZID/HAZOP/LOPA worksheet needs. Other pages
   (forms, lists) keep the narrower, centered `.page` default -- a wide
   line length is bad for reading prose, but doesn't matter for a fixed-
   column grid that already manages its own internal scrolling. */
.page.page-worksheet {
  max-width: none;
}
.page-worksheet h1 {
  margin: 6px 0 4px;
}
#worksheet-chrome > p {
  margin: 2px 0;
}

/* BOW-TIE diagram page: same "let it use the viewport" reasoning as
   .page-worksheet above -- the diagram is the whole point of this page,
   not supporting prose, so drop the shared 1400px reading-width cap. The
   canvas's own height is computed in JS (frontend/bowtie-diagram/src/
   main.jsx), not CSS, since it depends on this page's own variable-height
   heading content above it (Top Event name/MAH text can each wrap to a
   different number of lines). */
.page.page-bowtie-diagram {
  max-width: none;
}
.page-bowtie-diagram h1 {
  margin: 6px 0 4px;
}

/* Hide/show toggle for everything above the grid (back-link, sheet tabs,
   heading, description) -- the zoom-controls row (with the toggle button
   itself) stays visible either way, so the grid can take over the rest of
   the page when the user wants maximum working space. Persisted per
   browser (see worksheet.js/lopa_worksheet.js), like zoom/column widths. */
#worksheet-chrome.chrome-hidden {
  display: none;
}

/* Project-detail action buttons -- a div, not a <p>, since a <form> (block
   content) isn't valid inside <p> and browsers silently close the <p>
   around it, splitting the row onto two lines. */
.actions-row { margin: 1em 0; }

.flash-list { list-style: none; padding: 0; margin: 0 0 12px; }
.flash {
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  margin-bottom: 6px;
  box-shadow: var(--shadow-sm);
}
.flash-error { background: var(--color-high); color: var(--color-high-text); }
.flash-success { background: var(--color-low); color: var(--color-low-text); }
.flash-warning { background: var(--color-medium); color: var(--color-medium-text); }
.flash-message { background: #eaf4ff; color: var(--color-accent); }

/* Worksheet sheet-tab navigation (jump between a project's other nodes) --
   always a single row; on a project with many nodes it scrolls
   horizontally instead of wrapping, same reasoning as the grid's own
   horizontal scrollbar (UI_guideline.md). */
.sheet-nav {
  display: flex;
  flex-wrap: nowrap;
  gap: 4px;
  overflow-x: auto;
  white-space: nowrap;
  margin: 4px 0 12px;
  padding-bottom: 4px;
}
.sheet-nav .sheet-tab {
  flex: 0 0 auto;
  padding: 4px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  text-decoration: none;
  color: var(--color-primary);
  background: #fff;
  font-weight: 500;
  transition: var(--transition-btn);
}
.sheet-nav .sheet-tab:hover {
  background: #f0f7ff;
  border-color: var(--color-primary-hover);
  box-shadow: var(--shadow-sm);
}
.sheet-nav .sheet-tab:active { transform: scale(0.97); }
.sheet-nav .sheet-tab:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.sheet-nav .sheet-tab.current {
  background: var(--color-primary);
  color: #fff;
  font-weight: 600;
  border-color: var(--color-primary);
}
.sheet-nav .sheet-tab.current:hover {
  background: var(--color-primary-hover);
  border-color: var(--color-primary-hover);
}

form.stacked-form { display: flex; flex-direction: column; gap: 10px; max-width: 420px; }
form.stacked-form.wide { max-width: 700px; }
form.stacked-form table.plain-list input { width: 100%; }
form.stacked-form label { display: flex; flex-direction: column; gap: 4px; font-weight: 600; }
form.stacked-form input, form.stacked-form textarea {
  font: inherit;
  padding: 6px 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
form.inline-form { display: inline; }

/* Generic form controls app-wide (login, project create/load, admin
   forms, node/attendee edit forms, etc.). Deliberately a plain low-
   specificity selector (element only, no class/ancestor) -- every
   worksheet-grid-specific control rule (e.g. `table.lopa-worksheet-grid td
   select`, `.zoom-controls #worksheet-find-input`, `.context-menu select`)
   already has higher specificity via its class/ancestor chain, so those
   keep winning over this without needing an explicit exclusion here. */
input, select, textarea {
  font: inherit;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  transition: var(--transition-btn);
}
input:hover, select:hover, textarea:hover {
  border-color: var(--color-muted);
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: var(--shadow-focus);
}
input[type="checkbox"], input[type="radio"] {
  accent-color: var(--color-primary);
}

button, .btn {
  font: inherit;
  font-weight: 600;
  padding: 6px 14px;
  border: 1px solid var(--color-primary);
  background: var(--color-primary);
  color: #fff;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: var(--transition-btn);
}
button:hover, .btn:hover {
  background: var(--color-primary-hover);
  border-color: var(--color-primary-hover);
  box-shadow: var(--shadow-md);
}
button:active, .btn:active {
  background: var(--color-primary-active);
  border-color: var(--color-primary-active);
  box-shadow: var(--shadow-sm);
  transform: scale(0.97);
}
button:focus-visible, .btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-sm), var(--shadow-focus);
}
button.secondary, .btn.secondary {
  background: #fff;
  color: var(--color-primary);
  border-color: var(--color-primary);
}
button.secondary:hover, .btn.secondary:hover {
  background: #f0f7ff;
  border-color: var(--color-primary-hover);
  color: var(--color-primary-hover);
}
button.secondary:active, .btn.secondary:active {
  background: #e1efff;
  border-color: var(--color-primary-active);
  color: var(--color-primary-active);
}
button.danger, .btn.danger {
  background: var(--color-high);
  color: var(--color-high-text);
  border-color: var(--color-high-text);
}
button.danger:hover, .btn.danger:hover {
  background: var(--color-high-hover);
  box-shadow: var(--shadow-md);
}
button.danger:active, .btn.danger:active {
  background: var(--color-high);
  box-shadow: var(--shadow-sm);
  transform: scale(0.97);
}
button.danger:focus-visible, .btn.danger:focus-visible {
  outline: none;
  box-shadow: var(--shadow-sm), 0 0 0 3px rgba(132, 32, 41, 0.35);
}

/* Per-row reset-password reveal on the admin Users page (a plain <details>
   disclosure, no JS needed). */
table.plain-list details summary { cursor: pointer; color: var(--color-accent); }
table.plain-list details form {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
table.plain-list details label { display: flex; align-items: center; gap: 4px; font-weight: 600; }

table.plain-list {
  border-collapse: collapse;
  width: 100%;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}
table.plain-list th, table.plain-list td {
  border: 1px solid var(--color-border);
  padding: 6px 8px;
  text-align: left;
}
table.plain-list th { background: var(--color-header-bg); }
table.plain-list tbody tr:hover td { background: var(--color-bg); }

/* Worksheet zoom controls -- scales the whole grid (table.worksheet-grid /
   table.lopa-worksheet-grid, via the CSS `zoom` property applied in JS, not
   .grid-wrapper itself -- see worksheet.js/lopa_worksheet.js's comments for
   why the table is the right element to zoom). */
.zoom-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 4px 0 8px;
}
.zoom-controls button {
  padding: 2px 10px;
  line-height: 1.4;
  border-radius: var(--radius-sm);
}
.zoom-controls #zoom-level {
  min-width: 3.5em;
  text-align: center;
  color: var(--color-muted);
}

/* Worksheet find (HAZID/HAZOP grid only -- see worksheet.js's matching
   comment) -- lives in the same always-visible zoom-controls row, pushed
   to the row's right edge so it doesn't crowd the zoom/chrome-toggle
   buttons on a narrow window. */
.zoom-controls #worksheet-find-input {
  margin-left: auto;
  font: inherit;
  padding: 2px 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  width: 200px;
}
.zoom-controls #worksheet-find-status {
  min-width: 6em;
  color: var(--color-muted);
}

/* Worksheet grid */
.grid-wrapper {
  overflow: auto;
  max-height: 80vh;
  border: 1px solid var(--color-border);
  /* Force a visible, always-there scrollbar (not the OS's auto-hiding
     overlay style) so a wide grid's horizontal scrollbar is obvious. */
  scrollbar-width: auto;
  scrollbar-color: var(--color-muted) var(--color-bg);
}
.grid-wrapper::-webkit-scrollbar {
  height: 14px;
  width: 14px;
}
.grid-wrapper::-webkit-scrollbar-track {
  background: var(--color-bg);
}
.grid-wrapper::-webkit-scrollbar-thumb {
  background: var(--color-muted);
  border-radius: 7px;
  border: 3px solid var(--color-bg);
}
.grid-wrapper::-webkit-scrollbar-thumb:hover {
  background: var(--color-accent);
}

/* The chrome above the grid is now tighter (see .page-worksheet above), so
   there's a bit more viewport left to give back to the grid itself. */
.page-worksheet .grid-wrapper {
  max-height: 85vh;
}

table.worksheet-grid {
  border-collapse: collapse;
  table-layout: fixed;
  /* table-layout: fixed with an "auto" table width doesn't reliably use
     the columns' declared px widths in every browser -- some shrink the
     whole table to fit its container instead, silently ignoring them.
     Setting the table's own width to the columns' exact sum forces every
     browser to honor each column's declared width, and lets that width
     overflow .grid-wrapper (triggering its horizontal scrollbar) instead
     of squeezing every column to fit 100% of the page. Keep this in sync
     with the sum of the col widths below if any of them change. */
  width: 1610px;
}

table.worksheet-grid th, table.worksheet-grid td,
table.lopa-worksheet-grid th, table.lopa-worksheet-grid td {
  border: 1px solid var(--color-border);
  padding: 3px 6px;
  vertical-align: top;
  height: var(--row-height);
  overflow: hidden;
  word-wrap: break-word;
  white-space: normal;
}

table.worksheet-grid thead th,
table.lopa-worksheet-grid thead th {
  position: sticky;
  top: 0;
  background: var(--color-header-bg);
  z-index: 1;
}

/* HAZID/HAZOP header, tinted by column importance -- Apple-style
   restraint (a soft tint + a colored underline + accent-colored bold
   text), not a saturated fill: the header stays airy, per Apple's HIG,
   with color reserved for signal rather than decoration. Four tiers,
   picked from the analysis's own logic rather than arbitrarily:
   - Consequence (systemRed) -- the hazard outcome itself; the single
     thing a HAZID/HAZOP exists to surface, so it reads as the most
     "alarming" column, intentionally.
   - Safeguard (systemGreen) -- what protects against that consequence;
     equally central, colored as the counterpart to Consequence's red
     (danger vs. protection), not as a lesser tier.
   - Recommendation (systemBlue) -- the resulting action item; reuses
     `--color-primary`, the same blue already used for every button in
     the app, so "blue = actionable" reads consistently everywhere.
   - Cause (systemOrange) -- supporting context that leads to the
     consequence; important but one step removed from it, so a softer
     accent than red/green.
   Guide word/Actionee/Remark are deliberately left neutral (structural
   categorization / administrative tracking, not analytical content).
   Ranking is also left neutral here on purpose: its body cells already
   auto-color by high/medium/low severity (see td.ranking-high/medium/low
   below) -- a second, static header tint would compete with that
   existing per-row signal rather than reinforce it. */
table.worksheet-grid thead th[data-col="consequence"] {
  background: #fff1f0;
  color: #d70015;
  border-bottom: 3px solid #ff3b30;
}
table.worksheet-grid thead th[data-col="safeguard"] {
  background: #eafbf0;
  color: #248a3d;
  border-bottom: 3px solid #34c759;
}
table.worksheet-grid thead th[data-col="recommendation"] {
  background: #eaf4ff;
  color: var(--color-primary);
  border-bottom: 3px solid var(--color-primary);
}
table.worksheet-grid thead th[data-col="cause"] {
  background: #fff6e9;
  color: #c46a00;
  border-bottom: 3px solid #ff9500;
}

table.worksheet-grid col[data-col="guide_word"] { width: 220px; }
table.worksheet-grid col[data-col="cause"] { width: 220px; }
table.worksheet-grid col[data-col="consequence"] { width: 220px; }
table.worksheet-grid col[data-col="safeguard"] { width: 220px; }
table.worksheet-grid col[data-col="recommendation"] { width: 240px; }
table.worksheet-grid col[data-col="ranking"] { width: 110px; }
table.worksheet-grid col[data-col="actionee"] { width: 160px; }
table.worksheet-grid col[data-col="remark"] { width: 220px; }

/* Column width / row height resize handles (drag on a header's right edge
   to resize its column; drag on a row's bottom edge to resize that row). */
table.worksheet-grid th,
table.lopa-worksheet-grid th { position: relative; }
table.worksheet-grid .col-resize-handle,
table.lopa-worksheet-grid .col-resize-handle {
  position: absolute;
  top: 0;
  right: -3px;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 2;
}
table.worksheet-grid td.row-resize-cell,
table.lopa-worksheet-grid td.row-resize-cell { position: relative; }
table.worksheet-grid .row-resize-handle,
table.lopa-worksheet-grid .row-resize-handle {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 6px;
  cursor: row-resize;
  z-index: 2;
}

table.worksheet-grid .cell-number,
table.lopa-worksheet-grid .cell-number {
  display: inline-block;
  color: var(--color-muted);
  font-weight: 700;
  margin-right: 6px;
  user-select: none;
}

table.worksheet-grid .cell-text,
table.lopa-worksheet-grid .cell-text {
  display: inline;
}

table.worksheet-grid [contenteditable="true"],
table.lopa-worksheet-grid [contenteditable="true"] {
  cursor: text;
  white-space: pre-wrap;
}
table.worksheet-grid [contenteditable="true"]:focus,
table.lopa-worksheet-grid [contenteditable="true"]:focus {
  outline: none;
}

table.worksheet-grid td.upstream-cell,
table.lopa-worksheet-grid td.upstream-cell {
  background: #fbfbfd;
}

/* LOPA worksheet grid -- see app/templates/lopa_worksheet/grid.html and
   app/static/js/lopa_worksheet.js. Column widths are deliberately narrow
   across the board (matching the user-supplied reference header layout)
   so all 20 columns fit on one screen without horizontal scrolling --
   narrow letter/number/select columns get just enough room to not clip,
   prose-heavy columns (Consequence/Initiating Events/Enabling Conditions/
   IPL Description/Recommendations) get a bit more; everything wraps
   (white-space: normal, set generically above) rather than being widened
   to fit its label. */
table.lopa-worksheet-grid {
  border-collapse: collapse;
  table-layout: fixed;
  /* Keep in sync with the sum of the col widths below if any change --
     see table.worksheet-grid's identical comment above for why this
     explicit width (rather than "auto") is required. */
  width: 1870px;
}

table.lopa-worksheet-grid col[data-col="lopa_consequence"] { width: 130px; }
table.lopa-worksheet-grid col[data-col="lopa_consequence_category"] { width: 60px; }
table.lopa-worksheet-grid col[data-col="lopa_s"] { width: 120px; }
table.lopa-worksheet-grid col[data-col="lopa_tmel"] { width: 75px; }
table.lopa-worksheet-grid col[data-col="lopa_initiating_event"] { width: 130px; }
table.lopa-worksheet-grid col[data-col="lopa_frequency"] { width: 65px; }
table.lopa-worksheet-grid col[data-col="lopa_enabling_conditions"] { width: 160px; }
table.lopa-worksheet-grid col[data-col="lopa_probability"] { width: 65px; }
table.lopa-worksheet-grid col[data-col="lopa_product_ec_cm"] { width: 75px; }
table.lopa-worksheet-grid col[data-col="lopa_ipl"] { width: 130px; }
table.lopa-worksheet-grid col[data-col="lopa_ipl_category"] { width: 80px; }
table.lopa-worksheet-grid col[data-col="lopa_ipl_pfd"] { width: 60px; }
table.lopa-worksheet-grid col[data-col="lopa_total_pfd"] { width: 85px; }
table.lopa-worksheet-grid col[data-col="lopa_risk_reduction_factor"] { width: 85px; }
table.lopa-worksheet-grid col[data-col="lopa_calc_pfd"] { width: 60px; }
table.lopa-worksheet-grid col[data-col="lopa_rrf"] { width: 60px; }
table.lopa-worksheet-grid col[data-col="lopa_sil"] { width: 70px; }
table.lopa-worksheet-grid col[data-col="lopa_recommendation"] { width: 140px; }
table.lopa-worksheet-grid col[data-col="lopa_responsibility"] { width: 100px; }
table.lopa-worksheet-grid col[data-col="lopa_comments"] { width: 120px; }

/* Header cells need to grow to fit their wrapped multi-line label (e.g.
   "Enabling Conditions/Conditional Modifiers" in a 160px column), so
   they're exempted from the generic fixed-height/overflow-hidden rule
   above. */
table.lopa-worksheet-grid thead th {
  height: auto;
  overflow: visible;
  /* Overrides the generic vertical-align: top (set above for every grid
     cell) -- row 1 mixes tall rowspan="2" labels (e.g. "Enabling
     Conditions/Conditional Modifiers", wraps to 3 lines) with short
     single-line colspan group labels ("Independent Protection Layers",
     "Comments"), so row 1's height is set by the tallest one. Top-aligned,
     the short labels looked pinned to the top with an ugly dead gap below;
     centered, they just use the available height evenly. */
  vertical-align: middle;
}

/* Header row background/text distinct from the plain HAZID/HAZOP grid
   header, matching the reference layout. */
table.lopa-worksheet-grid thead th {
  background: #cfeaf3;
}

/* "Total PFD for all IPLs" is the one column-group total the reference
   layout calls out -- a green header accent, independent of the orange
   .lopa-col-total-pfd body-cell highlight below. */
th.lopa-total-pfd-header {
  background: #37b24d !important;
  color: #fff;
}

/* The 2-row column-group header (Independent Protection Layers/LOPA
   Calculation/LOPA Recommendations) -- row 1's rowspan="2" cells stick at
   the very top; row 2's own cells must stick exactly at row 1's own
   rendered height, not a moment sooner or later -- position: sticky's
   `top` is a *minimum* distance from the scroll container's top, so if
   this value is even a few px taller than row 1 actually is, row 2 gets
   pushed down past its natural position, opening a gap that row 2's own
   background can't cover -- through which the first tbody row shows
   (a real bug this exact rule caused once already: a stale hardcoded
   58px, from before the header redesign narrowed every column, briefly
   became a wrong 74px guess that never matched real content). Row 1's own
   height depends on whether the "Independent Protection Layers"/"LOPA
   Calculation"/"LOPA Recommendations" labels (the only cells confined to
   row 1 -- see .lopa-group-header) wrap to more than one line, which
   varies with their sub-columns' widths -- user-resizable -- so a fixed
   number can't be trusted. lopa_worksheet.js's syncGroupHeaderStickyOffset
   measures the real rendered height of a .lopa-group-header cell and
   writes it into --lopa-header-row1-height on load and after every column
   resize; the 29px fallback below only covers the instant before that
   JS runs. */
table.lopa-worksheet-grid thead tr:nth-child(2) th {
  top: var(--lopa-header-row1-height, 29px);
}

/* Locked/computed cells -- never contenteditable, always show a muted,
   visually "computed" look distinct from both a normal editable cell and a
   not-yet-created placeholder. */
td.cell-locked {
  background: #f1f3f5;
  color: var(--color-muted);
  font-style: italic;
}

/* Default per-column background accents on the LOPA grid's data rows,
   matching the user-supplied reference worksheet -- a visual grouping cue
   (TMEL/Freq. as the "given" inputs, the IPL-tier safeguard columns,
   Total PFD as the standout aggregate, then the 3 LOPA Calculation
   outputs each getting their own tint). None of these use `!important`:
   an explicit user-picked Fill color (right-click "Fill color...") is an
   inline `style="background-color:..."` on the cell itself, which always
   wins over an external class/attribute selector on plain CSS specificity
   grounds -- same "the user's explicit choice wins" precedent as Ranking's
   automatic high/medium/low color-coding (see docs/UI_guideline.md).
   Locked/computed columns among these (TMEL, Risk Reduction Factor, PFD,
   RRF) still need their color/font-style set explicitly here to override
   .cell-locked's muted/italic look, same as Total PFD below always has. */
table.lopa-worksheet-grid tbody td[data-col="lopa_tmel"],
table.lopa-worksheet-grid tbody td[data-col="lopa_frequency"] {
  background: #d0ebff;
  color: #1864ab;
  font-weight: 700;
  font-style: normal;
}
table.lopa-worksheet-grid tbody td[data-col="lopa_ipl_category"],
table.lopa-worksheet-grid tbody td[data-col="lopa_ipl_pfd"] {
  background: #d3f9d8;
}
table.lopa-worksheet-grid tbody td[data-col="lopa_risk_reduction_factor"] {
  background: #ffe3e3;
  color: var(--color-text);
  font-style: normal;
}
table.lopa-worksheet-grid tbody td[data-col="lopa_calc_pfd"] {
  background: #e5dbff;
  color: var(--color-text);
  font-style: normal;
}
table.lopa-worksheet-grid tbody td[data-col="lopa_rrf"] {
  background: #d0ebff;
  color: var(--color-text);
  font-style: normal;
}

/* Total PFD is locked/computed (.cell-locked, above), so this overrides
   its muted/italic look back to the required bold text color -- there's
   no format/fill menu path that could ever fight this (a locked cell
   never reaches one). */
td.lopa-col-total-pfd {
  font-weight: 700;
  font-style: normal;
  color: #1971c2;
  background: #51cf66;
}

/* Con.Catg/S comboboxes -- plain native <select>, sized to fill their
   (now narrow) cell rather than overflowing it. */
table.lopa-worksheet-grid td select {
  width: 100%;
  font: inherit;
  border: 1px solid var(--color-border);
  border-radius: 3px;
  background: #fff;
}

td.ranking-high { background: var(--color-high); color: var(--color-high-text); font-weight: 600; }
td.ranking-medium { background: var(--color-medium); color: var(--color-medium-text); font-weight: 600; }
td.ranking-low { background: var(--color-low); color: var(--color-low-text); font-weight: 600; }

/* Copy/paste selection range (click/shift-click/drag/shift-arrow) */
td.cell-selected {
  background: #d6e4ff;
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}
/* No solid boundary while actively editing a cell -- the blue background
   is enough to show it's still the selected/anchor cell. */
td.cell-selected:focus,
td.cell-selected:focus-within {
  outline: none;
}

/* Right-click context menu */
.context-menu {
  position: fixed;
  z-index: 100;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: 4px 0;
  min-width: 160px;
  display: none;
}
.context-menu.open { display: block; }
.context-menu button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--color-text);
  padding: 6px 12px;
  border-radius: 0;
  box-shadow: none;
  transform: none;
  transition: background-color 0.1s ease;
}
.context-menu button:hover { background: var(--color-header-bg); }
.context-menu button:active { transform: none; box-shadow: none; }
.context-menu button:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--color-primary);
}
.context-menu select { margin: 4px 12px; width: calc(100% - 24px); }

/* Cell formatting: color-swatch picker shown in place of the menu's
   buttons after "Format text.../Fill color..." (see worksheet.js's
   renderColorPicker/renderFormatPicker). */
.color-picker { padding: 4px 12px; }
.color-swatch-row { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
.color-picker .color-swatch {
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  box-shadow: none;
  transition: border-color 0.1s ease, transform 0.05s ease;
}
.color-picker .color-swatch:hover { border-color: var(--color-muted); }
.color-picker .color-swatch:active { transform: scale(0.9); }
.color-picker .color-swatch:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-primary);
}
.color-swatch-custom { width: 100%; margin-bottom: 6px; }
.color-picker button:not(.color-swatch) {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--color-text);
  padding: 4px 0;
  box-shadow: none;
  transform: none;
}
.color-picker button:not(.color-swatch):hover { background: var(--color-header-bg); }
.color-picker button:not(.color-swatch):focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--color-primary);
}
