/* Professional Components Styling - Signatures, Variants, and Modals
   Uses CSS variables from DaisyUI theme for dark/light mode compatibility */

/* =============================================================================
   SIGNATURES STYLING
============================================================================= */

.signatures-table {
  font-size: 13px;
  border-collapse: collapse;
  width: 100%;
  background: var(--color-base-200);
}

.signatures-table thead th {
  background: var(--color-base-200);
  border-bottom: 1px solid var(--color-base-300);
  padding: 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-base-content);
  text-align: left;
}

.signatures-table tbody td {
  border-bottom: 1px solid var(--color-base-300);
  padding: 12px;
  font-size: 13px;
  color: var(--color-base-content);
  vertical-align: middle;
}

.signatures-table tbody tr:hover {
  background-color: var(--color-base-200);
}

.status-signed {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--color-success);
  font-weight: 600;
}

.status-pending {
  display: inline-block;
  padding: 4px 12px;
  background-color: color-mix(in srgb, var(--color-warning) 15%, transparent);
  color: var(--color-warning);
  border: 1px solid color-mix(in srgb, var(--color-warning) 30%, transparent);
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
}

.status-not-signed {
  display: inline-block;
  padding: 4px 12px;
  background-color: color-mix(in srgb, var(--color-error) 15%, transparent);
  color: var(--color-error);
  border: 1px solid color-mix(in srgb, var(--color-error) 30%, transparent);
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
}

.section-header {
  font-size: 18px;
  font-weight: 600;
  color: var(--color-base-content);
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--color-primary);
}

.table-container {
  background: var(--color-base-200);
  border: 1px solid var(--color-base-300);
  border-radius: 8px;
  margin-bottom: 24px;
  overflow: hidden;
}

.btn-primary-custom {
  background-color: var(--color-primary);
  color: var(--color-primary-content);
  padding: 6px 12px;
  border: 1px solid var(--color-primary);
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}

.btn-outline-custom {
  background-color: transparent;
  color: var(--color-primary);
  padding: 6px 12px;
  border: 1px solid var(--color-primary);
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  margin-right: 8px;
}

.btn-primary-custom:hover {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
}

.btn-outline-custom:hover {
  background-color: var(--color-primary);
  color: var(--color-primary-content);
}

.technology-badge {
  display: inline-block;
  padding: 4px 10px;
  background-color: color-mix(in srgb, var(--color-primary) 10%, transparent);
  color: var(--color-primary);
  border: 1px solid color-mix(in srgb, var(--color-primary) 20%, transparent);
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
}

/* Cryptographic-details panel inside the signature details modal.
   Deliberately dark with a subtle rose tint so the audit-only data
   reads as a "vault" and visually separates from the data summary
   above. Theme-independent: dictates its own colours rather than
   inheriting from the active daisyUI theme. */
.crypto-panel {
  background-color: oklch(0.25 0 0);
  color: oklch(0.9 0.01 327.68);
}

.crypto-panel-label {
  color: oklch(0.7 0.01 327.68);
}

.crypto-panel-helper {
  color: oklch(0.6 0.01 327.68);
}

.crypto-panel-code {
  background-color: oklch(0.3 0 0);
  color: oklch(0.92 0.01 327.68);
}

/* "Permission to sign" row inside the signing modal. The actual permission
   check happened server-side at modal-render time (the refusal partial
   would have been returned if the user lacked permission), so this is
   pure UX theatre — a brief spinner that cross-fades into a confirmed
   "Authorised" state, to make the verification feel substantial rather
   than instantaneous. */
.permission-verify-cell,
.permission-verify-inline {
  position: relative;
  display: inline-block;
  min-height: 1rem;
  min-width: 11rem;
  text-align: right;
}

.permission-state-verifying,
.permission-state-authorised {
  position: absolute;
  right: 0;
  top: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  white-space: nowrap;
}

.permission-state-verifying {
  color: var(--color-base-content);
  opacity: 0.7;
  animation: permission-verify-fade-out 1.5s forwards;
}

.permission-state-authorised {
  color: var(--color-success);
  font-weight: 600;
  opacity: 0;
  animation: permission-verify-fade-in 1.5s forwards;
}

@keyframes permission-verify-fade-out {
  0%   { opacity: 0.7; }
  80%  { opacity: 0.7; }
  100% { opacity: 0; }
}

@keyframes permission-verify-fade-in {
  0%, 80% { opacity: 0; transform: scale(0.96); }
  100%    { opacity: 1; transform: scale(1); }
}

/* =============================================================================
   VARIANTS TABLE STYLING
============================================================================= */

#variantsTableHtml {
  font-size: 13px;
  border-collapse: collapse;
  width: 100% !important;
  background: var(--color-base-200);
  table-layout: fixed !important;
}

#variantsTableHtml thead th {
  background: var(--color-base-300) !important;
  border: 1px solid var(--color-base-300) !important;
  padding: 8px 10px !important;
  font-size: 13px !important;
  font-weight: 600 !important;
  color: var(--color-base-content) !important;
  white-space: nowrap !important;
  vertical-align: middle !important;
  box-sizing: border-box !important;
}

#variantsTableHtml tbody td {
  border: 1px solid var(--color-base-300) !important;
  padding: 8px 10px !important;
  font-size: 13px !important;
  color: var(--color-base-content) !important;
  vertical-align: middle !important;
  box-sizing: border-box !important;
}

#variantsTableHtml tbody tr:nth-child(even) {
  background-color: var(--color-base-100);
}

#variantsTableHtml tbody tr:hover {
  background-color: var(--color-base-300);
  cursor: pointer;
}

/* Monospace for sequence data */
#variantsTableHtml .sequence-data {
  font-family: 'Courier New', monospace;
  font-size: 12px;
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Column widths and alignment */
#variantsTableHtml th:nth-child(1), #variantsTableHtml td:nth-child(1) { width: 70px !important; text-align: center; }
#variantsTableHtml th:nth-child(2), #variantsTableHtml td:nth-child(2) { width: 90px !important; text-align: center; }
#variantsTableHtml th:nth-child(3), #variantsTableHtml td:nth-child(3) { width: 80px !important; text-align: right; }
#variantsTableHtml th:nth-child(4), #variantsTableHtml td:nth-child(4) { width: 80px !important; text-align: center; }
#variantsTableHtml th:nth-child(5), #variantsTableHtml td:nth-child(5) { width: 80px !important; text-align: center; }
#variantsTableHtml th:nth-child(6), #variantsTableHtml td:nth-child(6) { width: 80px !important; text-align: right; }
#variantsTableHtml th:nth-child(7), #variantsTableHtml td:nth-child(7) { width: 90px !important; text-align: center; }
#variantsTableHtml th:nth-child(8), #variantsTableHtml td:nth-child(8) { width: 180px !important; text-align: left; }
#variantsTableHtml th:nth-child(9), #variantsTableHtml td:nth-child(9) { width: 120px !important; text-align: left; }
#variantsTableHtml th:nth-child(10), #variantsTableHtml td:nth-child(10) { width: 100px !important; text-align: center; }
#variantsTableHtml th:nth-child(11), #variantsTableHtml td:nth-child(11) { width: 100px !important; text-align: center; }

#variantsTableHtml .gene-name {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* DataTables control styling */
.dataTables_wrapper {
  font-size: 13px;
  padding: 0;
}

.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
  margin: 0 0 16px 0;
}

.dataTables_wrapper .dataTables_length { margin-bottom: 16px; }
.dataTables_wrapper .dataTables_filter { margin-bottom: 16px; }

table.dataTable { margin: 16px 0 !important; }

.dataTables_filter input {
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid var(--color-base-300);
  border-radius: 4px;
  background: var(--color-base-200);
  color: var(--color-base-content);
}

.dataTables_length select {
  font-size: 13px;
  padding: 4px 8px;
  border: 1px solid var(--color-base-300);
  border-radius: 4px;
  background: var(--color-base-200);
  color: var(--color-base-content);
}

.dataTables_info, .dataTables_paginate {
  font-size: 13px;
  color: var(--color-neutral-content);
}

.paginate_button {
  font-size: 13px !important;
  padding: 6px 12px !important;
  margin: 0 2px !important;
  border: 1px solid var(--color-base-300) !important;
  background: var(--color-base-200) !important;
  color: var(--color-base-content) !important;
}

.paginate_button.current {
  background: var(--color-primary) !important;
  color: var(--color-primary-content) !important;
  border-color: var(--color-primary) !important;
}

/* Variant type indicators */
.variant-type-snp { color: var(--color-success); font-weight: 600; }
.variant-type-ins { color: var(--color-primary); font-weight: 600; }
.variant-type-del { color: var(--color-error); font-weight: 600; }

/* Variant stats cards */
.variant-stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 24px;
  padding: 16px;
}

.variant-stat-card {
  background: var(--color-base-200);
  border: 1px solid var(--color-base-300);
  border-radius: 8px;
  padding: 16px;
  text-align: center;
}

.variant-stat-card.snp-card { border-left: 4px solid var(--color-success); }
.variant-stat-card.ins-card { border-left: 4px solid var(--color-primary); }
.variant-stat-card.del-card { border-left: 4px solid var(--color-error); }
.variant-stat-card.total-card { border-left: 4px solid var(--color-neutral-content); }
.variant-stat-card.high-impact-card { border-left: 4px solid var(--color-error); }
.variant-stat-card.moderate-impact-card { border-left: 4px solid var(--color-warning); }
.variant-stat-card.low-impact-card { border-left: 4px solid var(--color-success); }
.variant-stat-card.modifier-impact-card { border-left: 4px solid var(--color-neutral-content); }

.variant-stat-number { font-size: 24px; font-weight: 700; margin-bottom: 4px; }
.variant-stat-number.snp-number { color: var(--color-success); }
.variant-stat-number.ins-number { color: var(--color-primary); }
.variant-stat-number.del-number { color: var(--color-error); }
.variant-stat-number.total-number { color: var(--color-neutral-content); }
.variant-stat-number.high-impact-number { color: var(--color-error); }
.variant-stat-number.moderate-impact-number { color: var(--color-warning); }
.variant-stat-number.low-impact-number { color: var(--color-success); }
.variant-stat-number.modifier-impact-number { color: var(--color-neutral-content); }

.variant-stat-label {
  font-size: 12px;
  color: var(--color-neutral-content);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.variant-stat-description {
  font-size: 11px;
  color: var(--color-neutral-content);
  margin-top: 4px;
}

/* Impact and frequency cell colouring — plain coloured text, no boxes. */
.impact-badge {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.impact-badge.high { color: var(--color-error); }
.impact-badge.moderate { color: var(--color-warning); }
.impact-badge.low { color: var(--color-info); }
.impact-badge.modifier { color: var(--color-base-content); opacity: 0.6; }

.impact-cell { text-align: center; }

.freq-badge {
  font-weight: 600;
  font-family: 'Courier New', monospace;
}

.freq-badge.very-low { color: var(--color-success); }
.freq-badge.low { color: var(--color-info); }
.freq-badge.medium { color: var(--color-warning); }
.freq-badge.high { color: var(--color-error); }
.freq-badge.very-high { color: var(--color-error); font-weight: 700; }

.freq-cell { text-align: center; }

/* =============================================================================
   VARIANT MODAL STYLING
============================================================================= */

#variantModal .modal-box {
  background: var(--color-base-200);
  border: 1px solid var(--color-base-300);
  border-radius: 8px;
}

#variantModal .variant-header {
  border-bottom: 1px solid var(--color-base-300);
  padding-bottom: 16px;
  margin-bottom: 24px;
}

#variantModal .variant-badge {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
}

#variantModal .variant-badge.snp {
  background-color: color-mix(in srgb, var(--color-success) 15%, transparent);
  color: var(--color-success);
  border: 1px solid color-mix(in srgb, var(--color-success) 30%, transparent);
}

#variantModal .variant-badge.ins {
  background-color: color-mix(in srgb, var(--color-primary) 10%, transparent);
  color: var(--color-primary);
  border: 1px solid color-mix(in srgb, var(--color-primary) 20%, transparent);
}

#variantModal .variant-badge.del {
  background-color: color-mix(in srgb, var(--color-error) 15%, transparent);
  color: var(--color-error);
  border: 1px solid color-mix(in srgb, var(--color-error) 30%, transparent);
}

#variantModal .info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  margin-bottom: 24px;
}

#variantModal .info-item {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-base-300);
}

#variantModal .info-label {
  font-weight: 600;
  color: var(--color-base-content);
  font-size: 13px;
}

#variantModal .info-value {
  color: var(--color-base-content);
  font-family: 'Courier New', monospace;
  font-size: 13px;
}

#variantModal .aa-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

#variantModal .aa-table th {
  background: var(--color-base-300);
  border: 1px solid var(--color-base-300);
  padding: 10px;
  text-align: left;
  font-weight: 600;
  color: var(--color-base-content);
}

#variantModal .aa-table td {
  border: 1px solid var(--color-base-300);
  padding: 10px;
  color: var(--color-base-content);
}

#variantModal .aa-table .ref-row {
  background-color: color-mix(in srgb, var(--color-error) 8%, transparent);
}

#variantModal .aa-table .alt-row {
  background-color: color-mix(in srgb, var(--color-success) 8%, transparent);
}

#variantModal .section-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--color-base-content);
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--color-primary);
}

/* =============================================================================
   AUTH SURFACE BACKGROUND
   ============================================================================= */

/* Applied to the body of every page that extends base_minimal.html
   (login, signup, password reset, sign-out confirmation, 4xx/5xx error
   pages). A solid base-100 with a single muted primary radial accent
   in the top-right, overlaid with a slowly drifting hexagonal pattern
   reminiscent of icosahedral phage capsids viewed top-down. Branded
   without competing with the centered card. The pattern uses CSS mask
   + a primary-tinted fill so the colour follows the active DaisyUI
   theme. */
.auth-surface {
  background:
    radial-gradient(
      ellipse 90% 70% at 0% 0%,
      color-mix(in srgb, var(--color-primary) 85%, white),
      var(--color-primary) 55%,
      color-mix(in srgb, var(--color-primary) 80%, black) 100%
    );
}

/* Common pattern overlay properties. The actual pattern (hexagons,
   bubbles, concentric circles) is selected by a sibling modifier class
   on the body that sets mask-image. Swap modifiers to try variants. */
.auth-surface::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* White-ish pattern over the primary-coloured base; opacity gives
     the "faint symbols" feel without losing visibility against the
     purple. Theme-aware via primary-content (the contrast colour
     DaisyUI pairs with primary). */
  background-color: var(--color-primary-content, white);
  opacity: 0.18;
  -webkit-mask-repeat: repeat;
          mask-repeat: repeat;
  animation: auth-surface-drift 90s linear infinite;
}

@keyframes auth-surface-drift {
  from { -webkit-mask-position: 0 0; mask-position: 0 0; }
  to   { -webkit-mask-position: var(--auth-pattern-tile-w, 200px) var(--auth-pattern-tile-h, 232px);
              mask-position: var(--auth-pattern-tile-w, 200px) var(--auth-pattern-tile-h, 232px); }
}

/* Variant 1 — rounded phage-capsid hexagons (single layer, no inset).
   Slightly softer than the original sharp hex. Default. */
.auth-pattern-rounded-hex {
  --auth-pattern-tile-w: 200px;
  --auth-pattern-tile-h: 232px;
}
.auth-pattern-rounded-hex::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 232' width='200' height='232'><g fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round' stroke-linecap='round'><polygon points='100,12 181,57 181,151 100,196 19,151 19,57'/><polygon points='0,127 28,144 28,177 0,194 -28,177 -28,144'/><polygon points='200,127 228,144 228,177 200,194 172,177 172,144'/></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 232' width='200' height='232'><g fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round' stroke-linecap='round'><polygon points='100,12 181,57 181,151 100,196 19,151 19,57'/><polygon points='0,127 28,144 28,177 0,194 -28,177 -28,144'/><polygon points='200,127 228,144 228,177 200,194 172,177 172,144'/></g></svg>");
  -webkit-mask-size: 200px 232px;
          mask-size: 200px 232px;
}

/* Variant 2 — bubbles (scattered circles of varying sizes). Most
   rounded, suggests microbial colonies / phage particles. */
.auth-pattern-bubbles {
  --auth-pattern-tile-w: 240px;
  --auth-pattern-tile-h: 240px;
}
.auth-pattern-bubbles::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 240' width='240' height='240'><g fill='none' stroke='black' stroke-width='1.6'><circle cx='40' cy='40' r='28'/><circle cx='160' cy='60' r='44'/><circle cx='90' cy='150' r='36'/><circle cx='200' cy='180' r='24'/><circle cx='30' cy='200' r='18'/></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 240' width='240' height='240'><g fill='none' stroke='black' stroke-width='1.6'><circle cx='40' cy='40' r='28'/><circle cx='160' cy='60' r='44'/><circle cx='90' cy='150' r='36'/><circle cx='200' cy='180' r='24'/><circle cx='30' cy='200' r='18'/></g></svg>");
  -webkit-mask-size: 240px 240px;
          mask-size: 240px 240px;
}

/* Variant 3 — concentric cells (bacterial-colony / petri-dish feel).
   Soft, biology-flavoured, no straight edges anywhere. */
.auth-pattern-cells {
  --auth-pattern-tile-w: 220px;
  --auth-pattern-tile-h: 220px;
}
.auth-pattern-cells::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 220 220' width='220' height='220'><g fill='none' stroke='black' stroke-width='1.4'><circle cx='55' cy='55' r='34'/><circle cx='55' cy='55' r='22'/><circle cx='55' cy='55' r='10'/><circle cx='160' cy='110' r='42'/><circle cx='160' cy='110' r='28'/><circle cx='160' cy='110' r='14'/><circle cx='80' cy='180' r='28'/><circle cx='80' cy='180' r='16'/></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 220 220' width='220' height='220'><g fill='none' stroke='black' stroke-width='1.4'><circle cx='55' cy='55' r='34'/><circle cx='55' cy='55' r='22'/><circle cx='55' cy='55' r='10'/><circle cx='160' cy='110' r='42'/><circle cx='160' cy='110' r='28'/><circle cx='160' cy='110' r='14'/><circle cx='80' cy='180' r='28'/><circle cx='80' cy='180' r='16'/></g></svg>");
  -webkit-mask-size: 220px 220px;
          mask-size: 220px 220px;
}

/* Variant 4 — DNA double helix. Two intertwined strands with rungs at
   regular intervals; tile width = one full period so it loops
   seamlessly. Most genomics-flavoured of the lot. */
.auth-pattern-dna {
  --auth-pattern-tile-w: 240px;
  --auth-pattern-tile-h: 100px;
}
.auth-pattern-dna::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 100' width='240' height='100'><g fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round'><path d='M 0,50 C 20,50 40,15 60,15 C 80,15 100,50 120,50 C 140,50 160,85 180,85 C 200,85 220,50 240,50'/><path d='M 0,50 C 20,50 40,85 60,85 C 80,85 100,50 120,50 C 140,50 160,15 180,15 C 200,15 220,50 240,50'/><line x1='30' y1='32' x2='30' y2='68'/><line x1='60' y1='15' x2='60' y2='85'/><line x1='90' y1='32' x2='90' y2='68'/><line x1='150' y1='32' x2='150' y2='68'/><line x1='180' y1='15' x2='180' y2='85'/><line x1='210' y1='32' x2='210' y2='68'/></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 100' width='240' height='100'><g fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round'><path d='M 0,50 C 20,50 40,15 60,15 C 80,15 100,50 120,50 C 140,50 160,85 180,85 C 200,85 220,50 240,50'/><path d='M 0,50 C 20,50 40,85 60,85 C 80,85 100,50 120,50 C 140,50 160,15 180,15 C 200,15 220,50 240,50'/><line x1='30' y1='32' x2='30' y2='68'/><line x1='60' y1='15' x2='60' y2='85'/><line x1='90' y1='32' x2='90' y2='68'/><line x1='150' y1='32' x2='150' y2='68'/><line x1='180' y1='15' x2='180' y2='85'/><line x1='210' y1='32' x2='210' y2='68'/></g></svg>");
  -webkit-mask-size: 240px 100px;
          mask-size: 240px 100px;
}

/* Variant 5 — zoomed-in phage capsids, scattered. Three solid filled
   hexagons of varying sizes and slight rotations within a large tile,
   so the eye reads "two or three capsids drifting in solution"
   rather than a regular honeycomb grid. No internal lines — the
   solid fill against the primary background carries the shape. */
.auth-pattern-capsid-close {
  --auth-pattern-tile-w: 1100px;
  --auth-pattern-tile-h: 1100px;
}
.auth-pattern-capsid-close::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1100 1100' width='1100' height='1100'><g fill='black'><g transform='rotate(8 300 320)'><polygon points='300,60 525,190 525,450 300,580 75,450 75,190'/></g><g transform='rotate(-12 770 700)'><polygon points='770,400 1030,550 1030,850 770,1000 510,850 510,550'/></g><g transform='rotate(20 190 920)'><polygon points='190,780 311,850 311,990 190,1060 69,990 69,850'/></g></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1100 1100' width='1100' height='1100'><g fill='black'><g transform='rotate(8 300 320)'><polygon points='300,60 525,190 525,450 300,580 75,450 75,190'/></g><g transform='rotate(-12 770 700)'><polygon points='770,400 1030,550 1030,850 770,1000 510,850 510,550'/></g><g transform='rotate(20 190 920)'><polygon points='190,780 311,850 311,990 190,1060 69,990 69,850'/></g></g></svg>");
  -webkit-mask-size: 1100px 1100px;
          mask-size: 1100px 1100px;
}

/* Variant 6 — Illumina read pileup with coverage track on top. Mimics
   the IGV alignment view: a continuous coverage curve along the top,
   with several rows of staggered short-read rectangles below.
   Strongly genomics-flavoured — reads as "we work with sequencing
   data" without needing a label. */
.auth-pattern-reads {
  --auth-pattern-tile-w: 240px;
  --auth-pattern-tile-h: 90px;
}
.auth-pattern-reads::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 90' width='240' height='90'><g><path d='M 0,22 C 30,22 30,8 60,8 C 90,8 90,20 120,20 C 150,20 150,10 180,10 C 210,10 210,26 240,26' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round'/><g fill='black'><rect x='2' y='34' width='30' height='5' rx='1.5'/><rect x='42' y='34' width='38' height='5' rx='1.5'/><rect x='92' y='34' width='28' height='5' rx='1.5'/><rect x='130' y='34' width='44' height='5' rx='1.5'/><rect x='184' y='34' width='28' height='5' rx='1.5'/><rect x='220' y='34' width='30' height='5' rx='1.5'/><rect x='12' y='44' width='34' height='5' rx='1.5'/><rect x='58' y='44' width='28' height='5' rx='1.5'/><rect x='100' y='44' width='38' height='5' rx='1.5'/><rect x='150' y='44' width='30' height='5' rx='1.5'/><rect x='192' y='44' width='38' height='5' rx='1.5'/><rect x='4' y='54' width='28' height='5' rx='1.5'/><rect x='44' y='54' width='40' height='5' rx='1.5'/><rect x='96' y='54' width='30' height='5' rx='1.5'/><rect x='138' y='54' width='34' height='5' rx='1.5'/><rect x='184' y='54' width='30' height='5' rx='1.5'/><rect x='222' y='54' width='28' height='5' rx='1.5'/><rect x='20' y='64' width='34' height='5' rx='1.5'/><rect x='66' y='64' width='28' height='5' rx='1.5'/><rect x='106' y='64' width='32' height='5' rx='1.5'/><rect x='150' y='64' width='42' height='5' rx='1.5'/><rect x='200' y='64' width='30' height='5' rx='1.5'/><rect x='8' y='74' width='30' height='5' rx='1.5'/><rect x='50' y='74' width='30' height='5' rx='1.5'/><rect x='90' y='74' width='38' height='5' rx='1.5'/><rect x='140' y='74' width='32' height='5' rx='1.5'/><rect x='184' y='74' width='34' height='5' rx='1.5'/></g></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 90' width='240' height='90'><g><path d='M 0,22 C 30,22 30,8 60,8 C 90,8 90,20 120,20 C 150,20 150,10 180,10 C 210,10 210,26 240,26' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round'/><g fill='black'><rect x='2' y='34' width='30' height='5' rx='1.5'/><rect x='42' y='34' width='38' height='5' rx='1.5'/><rect x='92' y='34' width='28' height='5' rx='1.5'/><rect x='130' y='34' width='44' height='5' rx='1.5'/><rect x='184' y='34' width='28' height='5' rx='1.5'/><rect x='220' y='34' width='30' height='5' rx='1.5'/><rect x='12' y='44' width='34' height='5' rx='1.5'/><rect x='58' y='44' width='28' height='5' rx='1.5'/><rect x='100' y='44' width='38' height='5' rx='1.5'/><rect x='150' y='44' width='30' height='5' rx='1.5'/><rect x='192' y='44' width='38' height='5' rx='1.5'/><rect x='4' y='54' width='28' height='5' rx='1.5'/><rect x='44' y='54' width='40' height='5' rx='1.5'/><rect x='96' y='54' width='30' height='5' rx='1.5'/><rect x='138' y='54' width='34' height='5' rx='1.5'/><rect x='184' y='54' width='30' height='5' rx='1.5'/><rect x='222' y='54' width='28' height='5' rx='1.5'/><rect x='20' y='64' width='34' height='5' rx='1.5'/><rect x='66' y='64' width='28' height='5' rx='1.5'/><rect x='106' y='64' width='32' height='5' rx='1.5'/><rect x='150' y='64' width='42' height='5' rx='1.5'/><rect x='200' y='64' width='30' height='5' rx='1.5'/><rect x='8' y='74' width='30' height='5' rx='1.5'/><rect x='50' y='74' width='30' height='5' rx='1.5'/><rect x='90' y='74' width='38' height='5' rx='1.5'/><rect x='140' y='74' width='32' height='5' rx='1.5'/><rect x='184' y='74' width='34' height='5' rx='1.5'/></g></g></svg>");
  -webkit-mask-size: 240px 90px;
          mask-size: 240px 90px;
}

/* Variant 7 — sequencing chromatogram. Series of overlapping Gaussian
   peaks at varying heights, like a Sanger trace (but single colour).
   Reads as quality-control / sequencing data without being literal. */
.auth-pattern-trace {
  --auth-pattern-tile-w: 240px;
  --auth-pattern-tile-h: 80px;
}
.auth-pattern-trace::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 80' width='240' height='80'><g fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round'><path d='M 0,60 L 12,60 C 20,60 20,30 30,30 C 40,30 40,60 48,60 L 60,60 C 68,60 68,15 78,15 C 88,15 88,60 96,60 L 118,60 C 124,60 124,40 132,40 C 140,40 140,60 146,60 L 168,60 C 174,60 174,20 184,20 C 194,20 194,60 200,60 L 218,60 C 224,60 224,38 230,38 C 236,38 236,60 240,60'/></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 80' width='240' height='80'><g fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round'><path d='M 0,60 L 12,60 C 20,60 20,30 30,30 C 40,30 40,60 48,60 L 60,60 C 68,60 68,15 78,15 C 88,15 88,60 96,60 L 118,60 C 124,60 124,40 132,40 C 140,40 140,60 146,60 L 168,60 C 174,60 174,20 184,20 C 194,20 194,60 200,60 L 218,60 C 224,60 224,38 230,38 C 236,38 236,60 240,60'/></g></svg>");
  -webkit-mask-size: 240px 80px;
          mask-size: 240px 80px;
}

/* Variant 8 — tight hex lattice. Small precise hexagons in a dense
   regular grid. Static (no drift animation), low opacity. Reads as
   "icosahedral capsid symmetry as a design system" rather than
   illustration — pharma-grade rather than playful. */
.auth-pattern-hex-grid {
  --auth-pattern-tile-w: 24.249px;
  --auth-pattern-tile-h: 42px;
}
.auth-pattern-hex-grid::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24.249 42' width='24.249' height='42'><g fill='none' stroke='black' stroke-width='0.7'><polygon points='12.124,0 24.249,7 24.249,21 12.124,28 0,21 0,7'/><polygon points='0,21 12.124,28 12.124,42 0,49 -12.124,42 -12.124,28'/><polygon points='24.249,21 36.373,28 36.373,42 24.249,49 12.124,42 12.124,28'/></g></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24.249 42' width='24.249' height='42'><g fill='none' stroke='black' stroke-width='0.7'><polygon points='12.124,0 24.249,7 24.249,21 12.124,28 0,21 0,7'/><polygon points='0,21 12.124,28 12.124,42 0,49 -12.124,42 -12.124,28'/><polygon points='24.249,21 36.373,28 36.373,42 24.249,49 12.124,42 12.124,28'/></g></svg>");
  -webkit-mask-size: 24.249px 42px;
          mask-size: 24.249px 42px;
  opacity: 0.09;
  animation: none;
}

/* Variant 9 — single large outlined capsid behind the card. One big
   faint hexagonal outline centred on the viewport, no tiling, no
   motion. Says "scientific" once and stops. */
.auth-pattern-capsid-mark::before {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 692' width='600' height='692'><polygon points='300,20 580,180 580,512 300,672 20,512 20,180' fill='none' stroke='black' stroke-width='2.5' stroke-linejoin='round'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 692' width='600' height='692'><polygon points='300,20 580,180 580,512 300,672 20,512 20,180' fill='none' stroke='black' stroke-width='2.5' stroke-linejoin='round'/></svg>");
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: min(640px, 78vw) auto;
          mask-size: min(640px, 78vw) auto;
  opacity: 0.16;
  animation: none;
}

/* Glassmorphism card sitting on top of .auth-surface. Semi-transparent
   white background + backdrop blur lets the hex lattice show through
   without competing with the form. The 1px inner highlight gives the
   "frosted pane" edge. */
.auth-card {
  background-color: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
          backdrop-filter: blur(20px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.45);
  box-shadow:
    0 12px 40px -8px rgba(0, 0, 0, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

/* Inputs inside the auth-card render as solid white tiles with a
   primary-tinted border, so they read as crisp foreground rather than
   picking up the lavender backdrop tint of the glass pane. */
.auth-card .input {
  background-color: #ffffff;
  border-color: color-mix(in srgb, var(--color-primary) 25%, transparent);
  color: var(--color-base-content);
}
.auth-card .input:focus,
.auth-card .input:focus-within {
  border-color: var(--color-primary);
  outline: 2px solid color-mix(in srgb, var(--color-primary) 30%, transparent);
  outline-offset: 0;
}

/* Respect reduced-motion preferences. */
@media (prefers-reduced-motion: reduce) {
  .auth-surface::before {
    animation: none;
  }
}

/* Permissions matrix column-hover highlight (driven by
   js/users/permission_matrix_hover.js). */
#permissions-matrix-table .col-hover {
  background-color: var(--color-base-200);
}
