/* ============================================
   Redirect Chain Checker - Styles

   Design tokens, reset, header, grid, field,
   button, card, badge and finding styles are
   taken 1:1 from the hreflang Validator, which
   took them from the UTM Builder, which took
   them from the SERP Simulator
   (serp-simulator.xtraz-labs.com). All four
   tools stay visually identical.

   Anything added for this tool is marked
   "Checker addition" and is derived from the
   existing tokens only. No new colour and no
   new font is introduced here.
   ============================================ */

/* --- Reset & Basis --- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* The hidden attribute only sets display:none at low priority, so any
   element given display:flex below would ignore it. Several elements
   here are toggled that way, so make hidden win outright. */
[hidden] {
  display: none !important;
}

:root {
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-bg: #f8fafc;
  --color-surface: #ffffff;
  --color-border: #e2e8f0;   /* 1.23:1 on white -- below the 3:1 WCAG 1.4.11
                                asks for on a control boundary. Inherited from
                                the SERP Simulator; changing it would make the
                                three tools diverge, so it is a shared decision. */
  --color-text: #1e293b;
  --color-text-secondary: #64748b;
  --color-success: #16a34a;
  --color-warning: #ea580c;
  --color-danger: #dc2626;
  --radius: 8px;
  --radius-sm: 4px;
  --shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.1);

  /* Carried over from the UTM Builder, unchanged. A URL is read character
     by character, so it needs fixed-width digits and an unambiguous l/1/I. */
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
  --tint-primary: rgba(37, 99, 235, 0.08);   /* --color-primary  @ 8%  */
  --tint-warning: rgba(234, 88, 12, 0.08);   /* --color-warning  @ 8%  */
  --tint-success: rgba(22, 163, 74, 0.10);   /* --color-success  @ 10% */
  --focus-ring: 0 0 0 3px rgba(37, 99, 235, 0.1);

  /* Validator addition: this tool reports errors, which the other two do
     not, so it needs the danger tint the same way. Same formula. */
  --tint-danger: rgba(220, 38, 38, 0.08);    /* --color-danger   @ 8%  */
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--color-bg);
  color: var(--color-text);
  line-height: 1.5;
  min-height: 100vh;
}

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Header --- */
.header {
  display: flex;
  align-items: center;
  padding: 24px 32px;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.header-logo-link,
.header-spacer {
  flex: 0 0 auto;
  width: 120px;
}

.header-text {
  flex: 1;
  text-align: center;
}

.header-title {
  font-size: 22px;
  font-weight: 700;
  color: var(--color-text);
}

.header-subtitle {
  font-size: 14px;
  color: var(--color-text-secondary);
  margin-top: 2px;
}

.header-logo {
  height: 32px;
  width: auto;
}

.noscript-note {
  padding: 20px 32px 0;
  max-width: 1400px;
  margin: 0 auto;
}

/* --- Container / Layout --- */
.container {
  display: grid;
  grid-template-columns: 420px 1fr;
  gap: 0;
  max-width: 1400px;
  margin: 0 auto;
  min-height: calc(100vh - 85px);
}

.input-panel {
  padding: 24px;
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  overflow-y: auto;
}

.field-group {
  margin-bottom: 20px;
}

.field-group label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.field-group input[type="text"],
.field-group input[type="url"],
.field-group textarea {
  width: 100%;
  padding: 10px 12px;
  font-size: 14px;
  font-family: inherit;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  transition: border-color 0.15s, box-shadow 0.15s;
  outline: none;
}

.field-group input:focus,
.field-group textarea:focus {
  border-color: var(--color-primary);
  box-shadow: var(--focus-ring);
}

.field-flag {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.field-flag.required {
  color: var(--color-primary);
}

.field-hint {
  font-size: 12px;
  color: var(--color-text-secondary);
  margin-top: 5px;
}

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color 0.15s, transform 0.1s;
  white-space: nowrap;
}

.btn:active {
  transform: scale(0.98);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn:disabled:active {
  transform: none;
}

.btn-small {
  padding: 5px 12px;
  font-size: 12px;
  background: var(--color-bg);
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
}

.btn-small:hover:not(:disabled) {
  background: var(--color-border);
  color: var(--color-text);
}

.btn-outline {
  background: transparent;
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
}

.btn-outline:hover:not(:disabled) {
  background: var(--color-bg);
  color: var(--color-text);
}

.btn-primary {
  background: var(--color-primary);
  color: #fff;
  min-height: 40px;
  padding: 8px 20px;
  font-size: 14px;
}

.btn-primary:hover:not(:disabled) {
  background: var(--color-primary-hover);
}

.action-buttons {
  display: flex;
  gap: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--color-border);
  margin-top: 8px;
}

/* --- Rechtes Panel: Ergebnis --- */
.preview-panel {
  padding: 24px 32px;
  background: var(--color-bg);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
}

.card[hidden] {
  display: none;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.card-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.card-note {
  font-size: 12px;
  color: var(--color-text-secondary);
}

.card-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
  flex-wrap: wrap;
}

.copy-feedback {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
  opacity: 0;
  transition: opacity 0.15s;
}

.copy-feedback::before {
  content: '\2713\00a0';
  color: var(--color-success);
}

.copy-feedback.visible {
  opacity: 1;
}

.copy-feedback.error {
  color: var(--color-danger);   /* 4.83:1 on white, passes */
}

.copy-feedback.error::before {
  content: '';
}

/* --- Befunde (aus .warning des UTM Builders, um "error" erweitert) --- */
.warnings {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.warnings:empty {
  display: none;
}

.warning {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13px;
  line-height: 1.5;
  padding: 12px 14px;
  border-radius: var(--radius);
  color: var(--color-text);
}

/* Validator addition: the error level. The other two tools never had one
   because neither can tell a user something is broken. */
.warning-error {
  background: var(--tint-danger);
  border: 1px solid var(--color-danger);
}

.warning-warning {
  background: var(--tint-warning);
  border: 1px solid var(--color-warning);
}

.warning-info {
  background: var(--tint-primary);
  border: 1px solid var(--color-border);
}

.warning-success {
  background: var(--tint-success);
  border: 1px solid var(--color-success);
}

.warning-icon {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
}

.warning-error .warning-icon {
  background: var(--color-danger);
}

.warning-warning .warning-icon {
  background: var(--color-warning);
}

.warning-info .warning-icon {
  background: var(--color-primary);
}

.warning-success .warning-icon {
  background: var(--color-success);
}

.warning-body {
  min-width: 0;
  flex: 1;
}

.warning-body strong {
  font-weight: 600;
}

/* --- Footer --- */
.footer {
  padding: 20px 32px 32px;
  text-align: center;
  font-size: 12px;
  color: var(--color-text-secondary);
}

.footer a {
  color: var(--color-text-secondary);
}

/* ============================================
   Validator additions from here on.
   ============================================ */

/* Status while a run is in flight. A run takes seconds, so the button
   alone is not enough feedback. */
.status {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--color-text-secondary);
  margin-top: 12px;
}

.spinner {
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  border: 2px solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 3s; }
}

/* Empty state, so the right-hand panel is never a blank rectangle. */
.placeholder {
  border: 1px dashed var(--color-border);
  border-radius: var(--radius);
  padding: 40px 24px;
  text-align: center;
  color: var(--color-text-secondary);
  font-size: 14px;
  background: var(--color-surface);
}

.placeholder-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 8px;
}

/* Summary line above the results: counts plus where the markup came from. */
.summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  overflow-wrap: anywhere;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text-secondary);
}

.badge-error {
  background: var(--tint-danger);
  border-color: var(--color-danger);
  color: var(--color-danger);
}

.badge-warning {
  background: var(--tint-warning);
  border-color: var(--color-warning);
  color: var(--color-warning);
}

.badge-success {
  background: var(--tint-success);
  border-color: var(--color-success);
  color: #15803d;   /* --color-success darkened for text contrast on the tint */
}

/* The hint line: where the markup was found, cluster size, languages. */
.meta-line {
  font-size: 12px;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

.meta-line strong {
  color: var(--color-text);
  font-weight: 600;
}

/* --- Befundliste --- */
.finding-url {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-text-secondary);
  word-break: break-all;
  display: block;
  margin-bottom: 4px;
}

.finding-recommendation {
  margin-top: 6px;
  font-size: 13px;
}

.finding-recommendation strong {
  font-weight: 600;
}

.finding-explanation {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--color-border);
  font-size: 12px;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

.finding-source {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
  margin-left: 6px;
  vertical-align: 1px;
}

/* --- Responsive --- */
@media (max-width: 900px) {
  .container {
    grid-template-columns: 1fr;
    /* Stacked, the container's min-height would hand the leftover space
       to the input panel and push the result a screen further down. */
    min-height: 0;
  }

  .input-panel {
    border-right: none;
    border-bottom: 1px solid var(--color-border);
  }

  .preview-panel {
    padding: 24px 16px;
  }
}

@media (max-width: 500px) {
  /* Same deviation the UTM Builder made: the SERP Simulator's two fixed
     120px header columns collide with the logo below ~520px. */
  .header {
    padding: 16px;
    gap: 12px;
  }

  .header-spacer {
    display: none;
  }

  .header-logo-link {
    width: auto;
  }

  .header-logo {
    height: 26px;
  }

  .header-text {
    text-align: left;
    min-width: 0;
  }

  .header-title {
    font-size: 18px;
  }

  .header-subtitle {
    font-size: 12px;
  }

  .input-panel {
    padding: 16px;
  }

  .card {
    padding: 16px;
  }

  .footer {
    padding: 16px;
  }
}

/* --- Checker addition: Geräteprofil-Umschalter ---
   A segmented control rather than a select, because there are exactly two
   options and both should be readable without opening anything. Built from
   the existing button tokens. */
.segmented {
  display: flex;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.segmented input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.segmented label {
  flex: 1;
  text-align: center;
  padding: 9px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text-secondary);
  background: var(--color-surface);
  cursor: pointer;
  user-select: none;
  text-transform: none;
  letter-spacing: 0;
  margin: 0;
  display: block;
}

.segmented label + label {
  border-left: 1px solid var(--color-border);
}

.segmented input:checked + label {
  background: var(--tint-primary);
  color: var(--color-primary);
}

.segmented input:focus-visible + label {
  box-shadow: inset var(--focus-ring);
}

/* --- Checker addition: die Kette ---
   Read top to bottom, one row per hop, with the connector carrying the
   status of the step that produced the next row. */
.chain {
  list-style: none;
  margin: 0;
  padding: 0;
}

.hop {
  position: relative;
  padding: 0 0 0 30px;
}

.hop:not(:last-child) {
  padding-bottom: 22px;
}

/* The vertical line and the dot are drawn rather than imaged so they inherit
   the token colours in every state. */
.hop::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 6px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--color-text-secondary);
}

.hop:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 9px;
  top: 17px;
  bottom: 2px;
  width: 1px;
  background: var(--color-border);
}

.hop-final::before { background: var(--color-success); }
.hop-problem::before { background: var(--color-danger); }

.hop-url {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.45;
  word-break: break-all;
  color: var(--color-text);
}

.hop-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--color-text-secondary);
}

.hop-status {
  font-family: var(--font-mono);
  font-weight: 700;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  background: var(--tint-primary);
  color: var(--color-primary);
}

.hop-status-ok { background: var(--tint-success); color: var(--color-success); }
.hop-status-temporary { background: var(--tint-warning); color: var(--color-warning); }
.hop-status-bad { background: var(--tint-danger); color: var(--color-danger); }

/* --- Checker addition: Kennzahlen über der Kette --- */
.figures {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 18px;
}

.figure {
  flex: 1 1 110px;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.figure-value {
  font-size: 20px;
  font-weight: 700;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

.figure-label {
  font-size: 11px;
  color: var(--color-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-top: 2px;
}

.figure-good .figure-value { color: var(--color-success); }
.figure-bad .figure-value { color: var(--color-danger); }
.figure-warn .figure-value { color: var(--color-warning); }

/* --- Checker addition: Standort- und Identitätshinweis ---
   Deliberately always visible, never behind a toggle. A finding that was only
   a location difference is an argument nobody wins, so the answer says where
   it was measured before anyone has to ask. */
.provenance {
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-bg);
  font-size: 12px;
  line-height: 1.55;
  color: var(--color-text-secondary);
}

.provenance strong {
  color: var(--color-text);
  font-weight: 600;
}

.provenance code {
  font-family: var(--font-mono);
  font-size: 11px;
  word-break: break-all;
}

@media (max-width: 700px) {
  .figure { flex: 1 1 calc(50% - 5px); }
}

/* --- Checker addition: Modus 2 --- */
.field-group textarea {
  width: 100%;
  padding: 10px 12px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.5;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  resize: vertical;
  white-space: pre;
  overflow-wrap: normal;
  overflow-x: auto;
}

.field-group textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: var(--focus-ring);
}

.file-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
}

/* The native control is unusable and unstyleable; the label above it is the
   button. It stays focusable and keyboard-operable through the label. */
.file-row input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.file-row input[type="file"]:focus-visible + #fileName,
.file-row label.btn:hover {
  text-decoration: none;
}

/* The preview before anything is fetched. Guessing the delimiter silently is
   how a list gets checked against the wrong column, so the guess is shown. */
.preview {
  margin-bottom: 20px;
  padding: 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-bg);
  font-size: 12px;
  line-height: 1.6;
}

.preview-headline {
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 6px;
}

.preview table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
}

.preview th,
.preview td {
  text-align: left;
  padding: 3px 6px;
  border-bottom: 1px solid var(--color-border);
  word-break: break-all;
  vertical-align: top;
}

.preview th {
  color: var(--color-text-secondary);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: 10px;
}

.preview-problem { color: var(--color-warning); }

/* --- Checker addition: Ergebnistabelle --- */
.card-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.filter-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--color-text-secondary);
  cursor: pointer;
  user-select: none;
}

.table-scroll {
  overflow-x: auto;
  /* The first column is the row's identity; scrolling it out of view leaves a
     grid of numbers nobody can attribute. */
  position: relative;
}

table.results {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

table.results th,
table.results td {
  text-align: left;
  padding: 7px 10px;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}

table.results th {
  position: sticky;
  top: 0;
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font-weight: 600;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
  z-index: 2;
}

table.results td:first-child,
table.results th:first-child {
  position: sticky;
  left: 0;
  background: var(--color-surface);
  z-index: 1;
  max-width: 260px;
}

table.results th:first-child { z-index: 3; }

table.results td:nth-child(2),
table.results td:nth-child(3) {
  max-width: 220px;
}

table.results .cell-url {
  font-family: var(--font-mono);
  font-size: 11.5px;
  word-break: break-all;
}

table.results tr.row-problem td:first-child {
  box-shadow: inset 3px 0 0 var(--color-danger);
}

table.results tr.row-spelling td:first-child {
  box-shadow: inset 3px 0 0 var(--color-warning);
}

table.results tr.row-pending td {
  color: var(--color-text-secondary);
  font-style: italic;
}

.cell-findings {
  font-size: 11.5px;
  line-height: 1.5;
}

.cell-findings span { display: block; }

/* --- Checker addition: Kartendarstellung für kleine Bildschirme ---
   Below the breakpoint a seven-column table cannot be read however it is
   scrolled, so the same rows render as cards. Both are in the DOM; only which
   one is shown changes. */
.result-cards { display: none; }

.result-card {
  padding: 12px 0;
  border-bottom: 1px solid var(--color-border);
}

.result-card-url {
  font-family: var(--font-mono);
  font-size: 12px;
  word-break: break-all;
  font-weight: 600;
}

.result-card dl {
  display: grid;
  grid-template-columns: 88px 1fr;
  gap: 2px 10px;
  margin-top: 6px;
  font-size: 12px;
}

.result-card dt { color: var(--color-text-secondary); }
.result-card dd { margin: 0; font-family: var(--font-mono); font-size: 11.5px; word-break: break-all; }

/* --- Checker addition: Fortschritt --- */
.progress {
  height: 4px;
  border-radius: 2px;
  background: var(--color-border);
  overflow: hidden;
  margin-top: 10px;
}

.progress-bar {
  height: 100%;
  width: 0;
  background: var(--color-primary);
  transition: width 200ms ease;
}

@media (max-width: 820px) {
  .table-scroll { display: none; }
  .result-cards { display: block; }
}
