/* Matrix Server List — Material 3-inspired, dependency-free.
   Design tokens live in :root; a [data-theme] attribute or the OS preference
   selects light/dark. Components: buttons, cards, chips, text fields, app bar. */

:root {
  /* Brand: Quassel green accent over neutral surfaces (palette from quassel.io). */
  --primary: #1f6644;
  --on-primary: #ffffff;
  --primary-container: #d7e9dd;
  --on-primary-container: #07301c;
  --secondary-container: #cfe7d7;
  --on-secondary-container: #0d3a24;
  --tertiary: #3d8a5e;

  --surface: #ffffff;
  --surface-1: #ffffff;
  --surface-2: #f1f5f2;
  --surface-3: #e9efea;
  --on-surface: #172019;
  --on-surface-variant: #4d5d50;
  --outline: rgba(0, 0, 0, 0.28);
  --outline-variant: rgba(0, 0, 0, 0.10);
  --bg: #f4f7f5;

  --success: #2e7d32;
  --success-container: #c8e6c9;
  --warning: #b26a00;
  --error: #ba1a1a;
  --error-container: #ffdad6;
  --on-error-container: #410002;

  --radius-sm: 8px;
  --radius: 16px;
  --radius-lg: 24px;
  --radius-full: 999px;
  --shadow-1: 0 1px 3px rgba(0,0,0,.12), 0 1px 2px rgba(0,0,0,.06);
  --shadow-2: 0 4px 12px rgba(0,0,0,.10);
  --maxw: 1120px;
  --ff: "Segoe UI", Roboto, system-ui, -apple-system, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --primary: #4cb87f;
    --on-primary: #052312;
    --primary-container: #1b3d2a;
    --on-primary-container: #b9ecca;
    --secondary-container: #26302a;
    --on-secondary-container: #d7e9dd;
    --surface: #161616;
    --surface-1: #161616;
    --surface-2: #1e1e1e;
    --surface-3: #252525;
    --on-surface: #ededed;
    --on-surface-variant: #b0b6b1;
    --outline: rgba(255, 255, 255, 0.28);
    --outline-variant: rgba(255, 255, 255, 0.10);
    --bg: #0e0e0e;
    --success: #7dd39a;
    --success-container: #143018;
    --error-container: #93000a;
    --on-error-container: #ffdad6;
  }
}
:root[data-theme="dark"] {
  --primary: #4cb87f; --on-primary: #052312; --primary-container: #1b3d2a;
  --on-primary-container: #b9ecca; --secondary-container: #26302a;
  --on-secondary-container: #d7e9dd; --surface: #161616; --surface-1: #161616;
  --surface-2: #1e1e1e; --surface-3: #252525; --on-surface: #ededed;
  --on-surface-variant: #b0b6b1; --outline: rgba(255, 255, 255, 0.28); --outline-variant: rgba(255, 255, 255, 0.10);
  --bg: #0e0e0e; --success: #7dd39a; --success-container: #143018; --error-container: #93000a;
  --on-error-container: #ffdad6;
}

* { box-sizing: border-box; }
/* The scrollbar gutter is intentionally NOT reserved: reserving it leaves an
   empty strip beside the app bar/footer on pages that don't scroll. The trade-off
   is a small horizontal recentre (~half the scrollbar width) when navigating
   between a scrolling and a non-scrolling page on classic (non-overlay)
   scrollbars; overlay-scrollbar platforms (macOS, mobile) see neither effect. */
html { scroll-behavior: smooth; }
body {
  margin: 0; font-family: var(--ff); background: var(--bg); color: var(--on-surface);
  line-height: 1.55; -webkit-font-smoothing: antialiased;
  /* Sticky footer: column layout so the footer is pinned to the bottom even on
     short pages. */
  min-height: 100vh; display: flex; flex-direction: column;
}
body > main { flex: 1 0 auto; }
a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }
.container { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }
.muted { color: var(--on-surface-variant); }
.center { text-align: center; }
h1, h2, h3 { line-height: 1.2; }
h1 { font-size: clamp(1.8rem, 4vw, 2.6rem); margin: 0 0 8px; }
code { font-family: ui-monospace, "Cascadia Code", monospace; font-size: .9em; }

/* --- App bar --- */
.appbar {
  position: sticky; top: 0; z-index: 50; background: color-mix(in srgb, var(--surface) 85%, transparent);
  backdrop-filter: saturate(180%) blur(12px); border-bottom: 1px solid var(--outline-variant);
}
.appbar-inner { display: flex; align-items: center; gap: 16px; height: 64px; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 1.15rem; color: var(--on-surface); }
.brand:hover { text-decoration: none; }
.brand .logo {
  width: 34px; height: 34px; border-radius: 50%; object-fit: cover; display: block; flex: none;
}
.appbar .spacer { flex: 1; }
.nav { display: flex; align-items: center; gap: 4px; }
.nav a { padding: 8px 14px; border-radius: var(--radius-full); color: var(--on-surface-variant); font-weight: 500; }
.nav a:hover { background: var(--surface-2); text-decoration: none; color: var(--on-surface); }
.nav a.active { color: var(--primary); background: var(--primary-container); }

/* Higher specificity than .icon-btn so the burger stays hidden on desktop. */
.appbar .menu-toggle { display: none; }

/* --- Buttons (Material 3 styles) --- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: inherit; font-size: .94rem; font-weight: 600; line-height: 1;
  min-height: 44px; padding: 0 24px; border-radius: var(--radius-full); border: none; cursor: pointer;
  transition: box-shadow .2s, background .2s, transform .05s; text-decoration: none;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn-filled { background: var(--primary); color: var(--on-primary); }
.btn-filled:hover { box-shadow: var(--shadow-2); text-decoration: none; }
.btn-tonal { background: var(--surface-3); color: var(--on-surface); }
.btn-tonal:hover { background: color-mix(in srgb, var(--on-surface) 10%, var(--surface-3)); box-shadow: var(--shadow-1); text-decoration: none; }
.btn-outlined { background: transparent; color: var(--primary); border: 1px solid var(--outline); }
.btn-outlined:hover { background: color-mix(in srgb, var(--primary) 8%, transparent); text-decoration: none; }
.btn-text { background: transparent; color: var(--primary); padding: 10px 14px; }
.btn-text:hover { background: color-mix(in srgb, var(--primary) 8%, transparent); text-decoration: none; }
.btn-danger { background: var(--error); color: #fff; }
.btn-sm { min-height: 34px; padding: 0 16px; font-size: .85rem; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn-block { width: 100%; }

.icon-btn {
  width: 40px; height: 40px; border-radius: var(--radius-full); border: none; cursor: pointer;
  background: transparent; color: var(--on-surface-variant); display: grid; place-items: center;
}
.icon-btn:hover { background: var(--surface-2); color: var(--on-surface); }

/* --- Cards --- */
.card {
  background: var(--surface-1); border: 1px solid var(--outline-variant);
  border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-1);
}
.card + .card { margin-top: 20px; }

/* --- Chips --- */
.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; font-size: .8rem;
  font-weight: 600; border-radius: var(--radius-full); border: 1px solid var(--outline-variant);
  color: var(--on-surface-variant); background: var(--surface);
}
.chip.on {
  background: color-mix(in srgb, var(--primary) 12%, var(--surface));
  color: var(--primary);
  border-color: color-mix(in srgb, var(--primary) 24%, transparent);
}
.chip-link { cursor: pointer; }
.chip-good { background: var(--success-container); color: var(--success); border-color: transparent; }
.chip-bad { background: var(--error-container); color: var(--on-error-container); border-color: transparent; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* Group the fact chips and the category chips into two clearly separated rows. */
.chip-groups { display: flex; flex-direction: column; gap: 8px; }
.chips-cats { padding-top: 2px; }
.chip-cat { background: var(--surface-2); border-color: transparent; color: var(--on-surface-variant); font-weight: 500; }
/* Registration status: a distinct icon + text line, not a chip. */
.reg { display: inline-flex; align-items: center; gap: 6px; font-size: .82rem; font-weight: 600; line-height: 1.2; }
.reg svg { flex: none; }
.reg-open { color: #2e9e44; }
.reg-closed { color: var(--on-surface-variant); }

/* --- Forms --- */
.field { margin-bottom: 18px; }
.field label { display: block; font-weight: 600; margin-bottom: 6px; font-size: .9rem; }
.field .hint { font-size: .82rem; color: var(--on-surface-variant); margin-top: 6px; }
.field label.checkbox { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.field label.checkbox input[type=checkbox] { width: 18px; height: 18px; flex: none; accent-color: var(--primary); cursor: pointer; }
.char-counter { font-size: .78rem; color: var(--on-surface-variant); margin-top: 4px; text-align: right; }
.char-counter-warn { color: var(--warning); font-weight: 600; }
input[type=text], input[type=email], input[type=password], input[type=url], textarea, select {
  width: 100%; font-family: inherit; font-size: .96rem; color: var(--on-surface);
  background: var(--surface); border: 1px solid var(--outline); border-radius: var(--radius-sm);
  padding: 13px 15px; transition: border-color .15s, box-shadow .15s;
}
textarea { resize: vertical; min-height: 90px; }
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 30%, transparent);
}
/* Custom select: drop the native control and draw our own chevron. */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  cursor: pointer; padding-right: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2379747e' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
}
select:hover { border-color: var(--on-surface-variant); }
select::-ms-expand { display: none; }

/* --- Alerts / flashes --- */
.flash-stack { margin-top: 24px; }
/* High contrast: a tinted background + a coloured left bar, but the message text
   itself uses the normal text colour so it stays legible in both themes. */
.alert { padding: 14px 18px; border-radius: var(--radius); margin-bottom: 16px; font-size: .92rem;
  color: var(--on-surface); border-left: 4px solid var(--outline); }
.alert-success { background: color-mix(in srgb, var(--success) 14%, var(--surface)); border-left-color: var(--success); }
.alert-error { background: color-mix(in srgb, var(--error) 14%, var(--surface)); border-left-color: var(--error); }
.alert-info { background: color-mix(in srgb, var(--primary) 12%, var(--surface)); border-left-color: var(--primary); }
.alert ul { margin: 6px 0 0; padding-left: 18px; }
/* Flash messages get a close button laid out beside the text. */
.flash-stack .alert { display: flex; align-items: flex-start; gap: 12px; }
.flash-stack .alert > span { flex: 1; min-width: 0; }
.alert-close { flex: none; border: none; background: transparent; color: inherit; cursor: pointer;
  font-size: 1.3rem; line-height: 1; opacity: .55; padding: 0 2px; }
.alert-close:hover { opacity: 1; }

/* --- Category picker (searchable multi-select) --- */
.cat-box { position: relative; display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  border: 1px solid var(--outline); border-radius: var(--radius-sm); padding: 7px 8px; background: var(--surface); }
.cat-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 30%, transparent); }
.cat-input { flex: 1; min-width: 140px; border: none; outline: none; background: transparent;
  font-family: inherit; font-size: .92rem; color: var(--on-surface); padding: 5px 4px; }
.cat-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 6px 5px 12px;
  font-size: .82rem; font-weight: 600; border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--primary) 12%, var(--surface)); color: var(--primary);
  border: 1px solid color-mix(in srgb, var(--primary) 24%, transparent); }
.cat-chip-x { border: none; background: transparent; color: inherit; cursor: pointer;
  font-size: 1rem; line-height: 1; padding: 0 2px; }
.cat-menu { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 40;
  max-height: 248px; overflow-y: auto; background: var(--surface);
  border: 1px solid var(--outline-variant); border-radius: var(--radius-sm); box-shadow: var(--shadow-2); }
.cat-menu[hidden] { display: none; }
.cat-menu-item { display: block; width: 100%; text-align: left; border: none; background: transparent;
  padding: 10px 14px; cursor: pointer; font-size: .9rem; color: var(--on-surface); }
.cat-menu-item:hover { background: var(--surface-2); }
.cat-menu-note { padding: 10px 14px; color: var(--on-surface-variant); font-size: .85rem; }
.cat-native { width: 100%; }

/* --- Hero --- */
.hero { padding: 32px 0 24px; }
.hero p.lead { font-size: 1.15rem; max-width: 640px; }
.hero .actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 24px; }
.stats { display: flex; gap: 28px; flex-wrap: wrap; margin-top: 28px; }
.stat .n { font-size: 1.8rem; font-weight: 800; color: var(--primary); }
.stat .l { font-size: .85rem; color: var(--on-surface-variant); }

/* --- Toolbar / filters (compact, single row, same height as a button) --- */
.toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 6px 0 18px; }
.toolbar .search { flex: 1 1 220px; min-width: 160px; }
.toolbar input, .toolbar select {
  height: 44px; padding-top: 0; padding-bottom: 0; font-size: .88rem; border-radius: var(--radius-full);
}
.toolbar select { width: auto; min-width: 132px; flex: 0 0 auto; padding-left: 16px; padding-right: 38px;
  background-position: right 14px center; }
.toolbar .btn { font-size: .88rem; }
.toolbar .search input { padding-left: 40px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2379747e' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: 14px center; }

/* --- Server grid --- */
/* Fixed column counts (not auto-fill/auto-fit) so cards keep a consistent slot
   width: capped at 3 per row on large screens, stepping down to 2 then 1. A
   lone card then occupies a single slot instead of stretching across the row. */
.grid { display: grid; grid-template-columns: 1fr; gap: 16px; align-items: stretch; }
@media (min-width: 640px)  { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .grid { grid-template-columns: repeat(3, 1fr); } }
.grid > * { height: 100%; }
/* The stacked-card spacing (.card + .card) must not leak into the grid, or every
   card after the first gets pushed down inside its cell. */
.grid .card + .card { margin-top: 0; }
.server-card {
  position: relative; display: flex; flex-direction: column; gap: 10px; min-height: 188px;
  padding: 18px 20px; transition: box-shadow .18s ease, transform .12s ease, border-color .18s ease;
}
.server-card:hover { border-color: var(--primary); box-shadow: var(--shadow-2); transform: translateY(-2px); }
.server-card .top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.server-card h3 { margin: 0; font-size: 1.12rem; }
/* The whole card is clickable via a stretched overlay on the title link, so we
   can keep real links (uptime) inside without nesting <a> elements. */
.card-link { color: var(--on-surface); }
.card-link:hover { text-decoration: none; }
.card-link::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.server-card .domain { font-family: ui-monospace, monospace; font-size: .82rem; color: var(--on-surface-variant); }
.server-card .desc { font-size: .9rem; color: var(--on-surface-variant); flex: 1;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.card-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: auto; padding-top: 4px; }
.card-foot .uptime-link { position: relative; z-index: 2; font-size: .82rem; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
.card-foot .uptime { font-size: .8rem; color: var(--on-surface-variant); }
.card-foot .uptime-num { color: var(--on-surface); font-weight: 600; }
.dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none; }
.dot-up { background: #2e9e44; box-shadow: 0 0 0 3px color-mix(in srgb, #2e9e44 25%, transparent); }
.dot-down { background: var(--error); box-shadow: 0 0 0 3px color-mix(in srgb, var(--error) 25%, transparent); }
.dot-degraded { background: #e0a400; box-shadow: 0 0 0 3px color-mix(in srgb, #e0a400 25%, transparent); }
.dot-unknown { background: var(--outline); }
.statusline { display: flex; align-items: center; gap: 8px; font-size: .85rem; font-weight: 600; }

.kv { display: grid; grid-template-columns: minmax(120px, max-content) 1fr; gap: 8px 18px; font-size: .92rem; }
.kv dt { color: var(--on-surface-variant); }
.kv dd { margin: 0; }

/* --- Server detail --- */
.detail-head { margin: 0 0 22px; }
.detail-title { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.detail-head h1 { margin: 0 0 4px; }
.detail-head .lead { margin: 12px 0 0; max-width: 640px; font-size: 1.05rem; }
.detail-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
details.tech { margin-top: 18px; border-top: 1px solid var(--outline-variant); padding-top: 14px; }
details.tech summary { cursor: pointer; font-weight: 600; color: var(--on-surface-variant);
  list-style: none; display: inline-flex; align-items: center; gap: 8px; user-select: none; }
details.tech summary::-webkit-details-marker { display: none; }
details.tech summary::before { content: "›"; font-size: 1.1rem; line-height: 1;
  transition: transform .15s ease; display: inline-block; }
details.tech[open] summary::before { transform: rotate(90deg); }

/* --- TXT record / copy box --- */
.copybox { display: flex; gap: 8px; align-items: stretch; }
.copybox code { flex: 1; background: var(--surface-2); padding: 12px 14px; border-radius: var(--radius-sm);
  overflow-x: auto; white-space: nowrap; border: 1px solid var(--outline-variant); }

.load-more-wrap { display: flex; justify-content: center; margin: 28px 0 8px; }

.section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 32px 0 14px; }
.empty { text-align: center; padding: 56px 20px; color: var(--on-surface-variant); }

/* --- Steps --- */
.steps { counter-reset: step; display: grid; gap: 14px; }
.step { display: flex; gap: 14px; }
.step .num { counter-increment: step; flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: var(--primary-container); color: var(--on-primary-container); display: grid; place-items: center; font-weight: 700; }
.step .num::before { content: counter(step); }

/* --- Table --- */
table.data { width: 100%; border-collapse: collapse; font-size: .9rem; }
table.data th, table.data td { text-align: left; padding: 12px 10px; border-bottom: 1px solid var(--outline-variant); vertical-align: top; }
table.data th { color: var(--on-surface-variant); font-weight: 600; }

/* --- Footer (compact, centered, single line) --- */
.footer { margin-top: 48px; border-top: 1px solid var(--outline-variant); background: var(--surface-1); }
.footer-inner { display: flex; flex-wrap: wrap; gap: 6px 12px; justify-content: center; align-items: center;
  padding: 16px 0; font-size: .85rem; color: var(--on-surface-variant); }
.footer .links { display: flex; flex-wrap: wrap; gap: 6px 14px; justify-content: center; }
.footer .links a { color: var(--on-surface-variant); }
.footer .sep { color: var(--outline-variant); }

/* --- Unmanaged notice banner --- */
.notice { display: flex; align-items: flex-start; gap: 10px; padding: 12px 16px; margin: 0 0 8px;
  border: 1px solid var(--outline-variant); border-radius: var(--radius); background: var(--surface-2);
  color: var(--on-surface-variant); font-size: .86rem; }
.notice svg { flex: none; margin-top: 1px; color: var(--warning); }

/* --- Cookie notice --- */
.cookie {
  position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 100; max-width: 560px; margin: 0 auto;
  background: var(--surface-3); border: 1px solid var(--outline-variant); border-radius: var(--radius);
  padding: 16px 18px; box-shadow: var(--shadow-2); display: flex; gap: 14px; align-items: center;
  font-size: .88rem;
}
.cookie[hidden] { display: none; }
.cookie span { flex: 1; }
.cookie .btn { flex: none; }

.auth-wrap { max-width: 440px; margin: 48px auto; }
.badge-pending { color: var(--warning); }
.badge-approved { color: var(--success); }
.badge-rejected { color: var(--error); }

/* Stack the dashboard "My servers" table into per-row blocks on small screens.
   A normal table forces a min content width (the nowrap actions column alone is
   ~220px) wider than a phone, which expands the mobile layout viewport and
   breaks the whole page; stacking keeps every row within the viewport. */
@media (max-width: 640px) {
  .servers-table, .servers-table tbody, .servers-table tr, .servers-table td { display: block; }
  .servers-table thead { display: none; }
  .servers-table tr { padding: 12px 0; border-bottom: 1px solid var(--outline-variant); }
  .servers-table tr:last-child { border-bottom: none; }
  .servers-table td { border: none; padding: 3px 0; }
  .servers-table td:last-child { white-space: normal; margin-top: 8px; }
  .servers-table td:last-child .btn { padding-left: 0; }
}

/* --- Responsive --- */
@media (max-width: 860px) {
  .nav { position: fixed; inset: 64px 0 auto 0; flex-direction: column; align-items: stretch;
    background: var(--surface-1); border-bottom: 1px solid var(--outline-variant); padding: 8px;
    gap: 4px; display: none; box-shadow: var(--shadow-2); }
  .nav.open { display: flex; }
  .nav a { padding: 12px 16px; }
  .appbar .menu-toggle { display: grid; }
  .stats { gap: 18px; }
}
.theme-toggle .moon { display: none; }
:root[data-theme="dark"] .theme-toggle .sun { display: none; }
:root[data-theme="dark"] .theme-toggle .moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .sun { display: none; }
  :root:not([data-theme="light"]) .theme-toggle .moon { display: block; }
}
