/* Administrace webhostingu.

   BARVA JE ROZLIŠOVACÍ ZNAK, NE OZDOBA. Postmaster je zelený, tohle modré —
   obě administrace bývají otevřené vedle sebe a mají společné účty i vzhled,
   takže bez toho by nebylo poznat, ve které z nich člověk zrovna maže.
   Mění se jen odstín akcentu; zbytek palety je stejný, ať se opravy dají
   přenášet mezi oběma. */
/* Administrace mailserveru. Bez frameworku a bez buildu — jeden soubor, který
   se dá přečíst celý.

   Motiv: výchozí je světlý, tmavý se bere z nastavení systému. Přepínač v hlavičce
   navíc umí volbu vynutit — pak je na <html> atribut data-theme a ten má přednost
   před systémem v obou směrech. */

:root {
	color-scheme: light;

	--bg: #f5f6f8;
	--surface: #fff;
	--surface-2: #f0f2f5;
	--border: #e0e4ea;
	--border-strong: #c9cfd8;
	--text: #171a1f;
	--muted: #626a76;
	--accent: #2f5f8f;
	--accent-text: #fff;
	--accent-soft: #e7eef6;
	--ok: #2c7a4d;
	--warn: #9a6206;
	--bad: #b3261e;

	/* Druhý faktor se pozná barvou dřív, než se přečte. Vlastní trojice, ne
	   --ok/--warn/--bad: zelená a červená tu znamenají „v pořádku" a „problém"
	   a u výčtu možností by lhaly. */
	--factor-sms: #2f5f8f;
	--factor-email: #6b4fa0;
	--factor-totp: #1f6f75;

	--danger-bg: #fdf4f3;
	--code-bg: #eef0f4;
	--shadow: 0 1px 2px rgb(16 22 32 / 6%);
	--radius: 10px;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme='light']) {
		color-scheme: dark;

		--bg: #101216;
		--surface: #181b21;
		--surface-2: #1e222a;
		--border: #292e37;
		--border-strong: #3a414d;
		--text: #e6e9ee;
		--muted: #98a1ae;
		--accent: #5f95d0;
		--accent-text: #0c0f13;
		--accent-soft: #172230;
		--ok: #5cb287;
		--warn: #d09a45;
		--bad: #e0736a;
		--factor-sms: #5f95d0;
		--factor-email: #a68bd8;
		--factor-totp: #62b6bd;
		--danger-bg: #241a1a;
		--code-bg: #21252d;
		--shadow: none;
	}
}

/* Vynucený tmavý — musí platit i ve světlém systému, proto zvlášť. */
:root[data-theme='dark'] {
	color-scheme: dark;

	--bg: #101216;
	--surface: #181b21;
	--surface-2: #1e222a;
	--border: #292e37;
	--border-strong: #3a414d;
	--text: #e6e9ee;
	--muted: #98a1ae;
	--accent: #5f95d0;
	--accent-text: #0c0f13;
	--accent-soft: #172230;
	--ok: #5cb287;
	--warn: #d09a45;
	--bad: #e0736a;
	--factor-sms: #5f95d0;
	--factor-email: #a68bd8;
	--factor-totp: #62b6bd;
	--danger-bg: #241a1a;
	--code-bg: #21252d;
	--shadow: none;
}

* { box-sizing: border-box; }

body {
	margin: 0;
	font: 15px/1.55 system-ui, -apple-system, 'Segoe UI', sans-serif;
	background: var(--bg);
	color: var(--text);
}

h1 { font-size: 1.4rem; margin: 0 0 1rem; letter-spacing: -0.01em; }
h2 { font-size: 1rem; margin: 0 0 .75rem; }
h3 { font-size: .9rem; margin: 1.1rem 0 .35rem; }
p { margin: 0 0 .7rem; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }

.muted { color: var(--muted); font-size: .85rem; }
.break { word-break: break-all; }
.block { display: block; }

code {
	font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
	font-size: .85em;
	background: var(--code-bg);
	padding: .05em .3em;
	border-radius: 4px;
}

/* --- rozvržení ----------------------------------------------------------- */

.layout { display: flex; min-height: 100vh; align-items: stretch; }

.sidebar {
	width: 14.5rem;
	flex: 0 0 14.5rem;
	background: var(--surface);
	border-right: 1px solid var(--border);
	padding: 1.15rem .85rem;
	display: flex;
	flex-direction: column;
	gap: 1.25rem;
	position: sticky;
	top: 0;
	height: 100vh;
}

/* Dlaždice a dvojřádek vedle ní mají lícovat hranami: vršek dlaždice s vrškem
   názvu, spodek s účařím adresy.

   Dělá se to dopočtem, ne roztahováním. `align-self: stretch` s `aspect-ratio`
   tu bylo a byla to chyba — obrázek se roztáhl přes celý panel, protože SVG bez
   pevných rozměrů si přirozenou velikost bere z kontejneru. Dlaždice má proto
   pevných 1.9rem a text se skládá tak, aby měl tutéž výšku:

       název   .95rem × line-height 1  = 15.2 px
       mezera  .3rem                   =  4.8 px
       adresa  .72rem × line-height 1  = 11.5 px
                                         ───────
                                         31.5 px  ≈ 1.9rem (30.4 px)

   `line-height: 1` je tu podstatné: výchozích 1.55 by k oběma řádkům přidalo
   prázdný prostor pro dotažnice, které v „Webhosting" ani v adrese nejsou. */
.brand { display: flex; align-items: center; gap: .55rem; padding: 0 .35rem; }

.brand-text {
	display: flex;
	flex-direction: column;
	gap: .3rem;
}

.brand strong { display: block; font-size: .95rem; line-height: 1; }
.brand small { display: block; color: var(--muted); font-size: .72rem; line-height: 1; }

/* Značka je obrázek, ne písmeno v barevném boxu — viz komentář v @layout.latte.
   Pozadí i zaoblení si nese SVG, tady zbývá jen velikost. */
.brand-mark {
	width: 1.9rem;
	height: 1.9rem;
	flex: 0 0 auto;
	display: block;
}

.sidebar nav { display: flex; flex-direction: column; gap: .1rem; }

.sidebar nav a {
	padding: .4rem .6rem;
	border-radius: 7px;
	color: var(--text);
	text-decoration: none;
	font-size: .92rem;
}

.sidebar nav a:hover { background: var(--surface-2); }
.sidebar nav a.active { background: var(--accent); color: var(--accent-text); }

/* Odkazy pod nadpisem skupiny jsou odsazené, aby bylo na první pohled vidět,
   kam který patří. Sourozenecký selektor bere všechno za prvním nadpisem —
   „Přehled" stojí před ním, a tak zůstává zarovnaný nalevo jako nadpisy. */
.sidebar nav .nav-group ~ a { padding-left: 1.35rem; }

/* Nadpis skupiny v nabídce. Administrace spravuje weby i poštu a bez rozdělení
   by devět odkazů pod sebou splývalo do jednoho seznamu. První skupina nemá
   odsazení nahoře — je hned pod Přehledem. */
.sidebar nav .nav-group {
	padding: .55rem .6rem .2rem;
	font-size: .72rem;
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--muted);
}

.sidebar-foot {
	margin-top: auto;
	display: flex;
	flex-direction: column;
	gap: .5rem;
	font-size: .8rem;
	color: var(--muted);
	border-top: 1px solid var(--border);
	padding: .75rem .35rem 0;
}

.sidebar-user { display: flex; justify-content: space-between; align-items: center; gap: .5rem; }

.content {
	flex: 1;
	min-width: 0;
	padding: 1.4rem 1.75rem 3rem;
	max-width: 72rem;
}

.toolbar { display: flex; justify-content: flex-end; margin-bottom: .5rem; }

/* Přihlašovací stránka nemá postranní panel, takže obsah nemá proti čemu držet
   šířku — bez tohohle by karta seděla nalevo od středu obrazovky. */
.content.full { max-width: none; }

.grid-2 {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
	gap: 1rem;
	align-items: start;
	margin-bottom: 1rem;
}

/* Uvnitř .grid-2 dělají mezery gapy, ne okraje karet — jinak by se odstup pod
   gridem řídil tím, který sloupec je delší, a někdy by chyběl úplně.
   Odstup k následující sekci má proto samotný grid. */
.grid-2 > .card, .grid-2 > .column > .card { margin-bottom: 0; }
.grid-2 > .column { display: flex; flex-direction: column; gap: 1rem; }

/* Varianta, která drží poloviny i tehdy, když je karta v mřížce jen jedna:
   `auto-fit` prázdný sloupec sbalí a karta by se roztáhla přes celou šířku.
   U mazání, kde se „Smazat web" u nepřipravené domény vůbec nevypíše, by se
   tak zbylá karta nafoukla na celou stránku. Zalomení řeší .card.half níž. */
.grid-2.halves { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
	gap: .75rem;
	margin-bottom: 1rem;
}

/* --- karty --------------------------------------------------------------- */

.card {
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	box-shadow: var(--shadow);
	padding: 1rem 1.1rem;
	margin-bottom: 1rem;
}

.card > :last-child { margin-bottom: 0; }
.card.danger { border-color: var(--bad); background: var(--danger-bg); }

/* Karta, ve které je jen formulář — bez omezení by se roztáhla přes celou šířku
   obsahu a pole v ní by plavala v prázdnu. */
.card.narrow { max-width: 34rem; }

.stat { display: flex; flex-direction: column; gap: .1rem; padding: .85rem 1rem; margin: 0; }
.stat-label { font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.stat-value { font-size: 1.7rem; font-weight: 600; line-height: 1.25; }
.stat-note { font-size: .78rem; color: var(--muted); }

/* --- tabulky ------------------------------------------------------------- */

.table { width: 100%; border-collapse: collapse; font-size: .92rem; }

.table th {
	text-align: left;
	font-size: .7rem;
	text-transform: uppercase;
	letter-spacing: .05em;
	color: var(--muted);
	font-weight: 600;
	padding: .3rem .55rem;
	border-bottom: 1px solid var(--border);
	white-space: nowrap;
}

.table td { padding: .45rem .55rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover td { background: var(--surface-2); }

/* První sloupec nese jméno a bere zbývající místo, ostatní se smrští na obsah —
   bez toho se tabulka na širokém monitoru roztáhne a čísla odplavou od popisků. */
.table td:first-child, .table th:first-child { width: 100%; }
.table td:not(:first-child), .table th:not(:first-child) { white-space: nowrap; width: 1%; }
.table .num { text-align: right; }
.table td.wrap { white-space: normal; width: auto; }

/* Formulář navazující na tabulku ve stejné kartě — bez odsazení se lepí na
   poslední řádek. */
.table + form, .table + p + form { margin-top: 1.1rem; }

/* Doména jako mezinadpis nad skupinou adres. */
.group-label {
	margin: 1rem 0 .1rem;
	font-size: .78rem;
	text-transform: uppercase;
	letter-spacing: .05em;
	color: var(--muted);
}

.group-label:first-of-type { margin-top: 0; }

/* Za tabulkou ale mezera potřeba je. Pravidlo výš ji ruší proto, že první
   skupina obvykle navazuje rovnou na nadpis karty — jenže když je nad
   popiskem tabulka, sedne si na její poslední řádek a čte se jako jeho
   pokračování. Musí být až za :first-of-type, obě mají stejnou váhu. */
.table + .group-label { margin-top: 1.4rem; }

/* --- strom domén ---------------------------------------------------------- */

/* Subdomén je na stroji víc než domén a většina je technická (mta-sts.*, mail.*),
   takže ve výpisu visí pod svou doménou a rozbalují se šipkou.

   PŘEPÍNAČ SE UKAZUJE, AŽ HO JE ČÍM OBSLOUŽIT. Řádky jsou v HTML všechny a schová
   je JavaScript; bez něj je vidět celý seznam a tlačítko, které nic nedělá, by
   jen mátlo. Proto se obojí zapíná až třídou, kterou skript doplní. */
.tree-toggle, .tree-space { display: none; }
.tree-ready .tree-space { display: inline-block; width: 1.9rem; }

.tree-ready .tree-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .1rem;
	min-width: 1.9rem;
	padding: .05rem .3rem;
	border: 1px solid var(--border);
	border-radius: 999px;
	background: var(--surface-2);
	color: var(--muted);
	font: inherit;
	font-size: .72rem;
	line-height: 1.4;
	cursor: pointer;
}

.tree-ready .tree-toggle:hover { color: var(--text); border-color: var(--border-strong); }
.tree-toggle svg { width: .7rem; height: .7rem; transition: transform .15s ease; }
.tree-toggle[aria-expanded='true'] svg { transform: rotate(90deg); }

.tree-name { display: flex; align-items: center; gap: .4rem; min-width: 0; }

/* Vypnutá doména zůstává ve výpisu, ale nemá poutat pozornost. */
.table tr.is-inactive td { opacity: .55; }

.actions { text-align: right; }
.actions a { margin-left: .5rem; font-size: .85rem; text-decoration: none; }
.actions a:hover { text-decoration: underline; }
/* Tlačítko v buňce s akcemi si drží svůj vzhled. Bez tohohle by mu pravidlo
   výš přidalo při najetí podtržení, což na tlačítku vypadá jako závada. */
.actions a.btn:hover { text-decoration: none; }

/* --- drobnosti ----------------------------------------------------------- */

.dot {
	display: inline-block;
	width: .5rem; height: .5rem;
	border-radius: 50%;
	background: var(--muted);
	margin-right: .4rem;
	vertical-align: baseline;
}

.dot.ok { background: var(--ok); }
.dot.warn { background: var(--warn); }
.dot.bad { background: var(--bad); }

.badge {
	display: inline-block;
	padding: .05rem .45rem;
	border-radius: 999px;
	border: 1px solid var(--border-strong);
	font-size: .72rem;
	color: var(--muted);
	white-space: nowrap;
}

.badge.ok { color: var(--ok); border-color: var(--ok); }
.badge.warn { color: var(--warn); border-color: var(--warn); }
.badge.bad { color: var(--bad); border-color: var(--bad); }

.states { list-style: none; margin: 0 0 .75rem; padding: 0; }
.states li { display: flex; align-items: center; gap: .4rem; padding: .18rem 0; font-size: .92rem; }
.states-name { flex: 1; }

.meter {
	height: .55rem;
	background: var(--surface-2);
	border: 1px solid var(--border);
	border-radius: 999px;
	overflow: hidden;
	margin: .3rem 0 .5rem;
	max-width: 22rem;
}

/* Pruh je vidět i při zanedbatelném podílu — proto min-width. */
.meter span { display: block; height: 100%; min-width: 2px; background: var(--accent); }
.meter span.warn { background: var(--warn); }
.meter span.bad { background: var(--bad); }

/* Skládaný pruh: schránka, ostatní data a zbytek, kterým prosvítá pozadí. */
.meter.stacked { display: flex; }
.meter span.mine { background: var(--accent); }
.meter span.others { background: var(--border-strong); }

.legend { list-style: none; margin: 0 0 .7rem; padding: 0; font-size: .82rem; }
.legend li { display: flex; align-items: center; gap: .4rem; padding: .1rem 0; }

.swatch {
	width: .7rem;
	height: .7rem;
	border-radius: 3px;
	flex: 0 0 auto;
	background: var(--surface-2);
	border: 1px solid var(--border);
}

.swatch.mine { background: var(--accent); border-color: var(--accent); }
.swatch.others { background: var(--border-strong); border-color: var(--border-strong); }

.record { margin: .75rem 0; display: grid; gap: .3rem; max-width: 46rem; }
.record-row { display: grid; grid-template-columns: 8.5rem 1fr; gap: .5rem; align-items: start; }
.record-label { color: var(--muted); font-size: .78rem; padding-top: .15rem; }
.record-value { background: var(--code-bg); padding: .25rem .4rem; border-radius: 6px; }

.code-block {
	background: var(--code-bg);
	padding: .7rem .8rem;
	border-radius: 8px;
	font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
	font-size: .78rem;
	line-height: 1.5;
	white-space: pre-wrap;
	margin: 0 0 .5rem;
}

.code-block.scroll { max-height: 32rem; overflow: auto; white-space: pre; }
.code-block.log { font-size: .74rem; }

/* --- flash zprávy -------------------------------------------------------- */

.flash {
	padding: .65rem .85rem;
	border-radius: var(--radius);
	border: 1px solid var(--border);
	border-left-width: 3px;
	margin-bottom: .85rem;
	background: var(--surface);
	font-size: .92rem;
}

.flash-success { border-left-color: var(--ok); }
.flash-warning { border-left-color: var(--warn); }
.flash-error { border-left-color: var(--bad); }
.flash span { display: block; }

/* --- formuláře ----------------------------------------------------------- */

/* Odstup zespodu: odstavce mají margin jen dole, takže text hned za
   formulářem se lepil na odesílací tlačítko. */
form { max-width: 30rem; margin: 0 0 .9rem; }
form.wide, .card.danger form { max-width: none; }

.field { margin-bottom: .8rem; }
.field label { display: block; font-size: .78rem; color: var(--muted); margin-bottom: .2rem; }
.field-check label { display: inline; font-size: .92rem; color: var(--text); }
.field-check input { margin: 0 .4rem 0 0; vertical-align: -1px; }
.field small { display: block; margin-top: .2rem; }

/* Typy se sem musí dopisovat - input[type='tel'] tu chyběl a telefon pak
   vypadal jako neostylované pole uprostřed formuláře. */
input[type='text'], input[type='email'], input[type='password'], input[type='number'],
input[type='tel'], input[type='search'], select, textarea {
	width: 100%;
	max-width: 24rem;
	padding: .4rem .55rem;
	border: 1px solid var(--border-strong);
	border-radius: 7px;
	background: var(--surface);
	color: var(--text);
	font: inherit;
}

textarea { max-width: none; }
textarea.code { font-family: ui-monospace, 'Cascadia Code', Consolas, monospace; font-size: .8rem; }
input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible, a:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 1px;
}
input[disabled] { color: var(--muted); background: var(--surface-2); }

.form-inline { display: flex; gap: .7rem; align-items: flex-end; flex-wrap: wrap; max-width: none; }
.form-inline .field { margin-bottom: 0; }
.form-inline input, .form-inline select { max-width: 14rem; }

/* Listování ve výpisu, kde se řádky nevejdou na jednu stránku. */
.pager { display: flex; align-items: center; gap: .7rem; margin: .8rem 0; }

/* Pravidlo pro tlačítka níž je silnější než [hidden] z prohlížeče — bez tohohle
   by schované tlačítko (třeba odesílací u filtru, který se uplatní sám) zůstalo
   vidět. Platí na cokoliv, ne jen na tlačítka: skrytý prvek má být skrytý. */
[hidden] { display: none !important; }

.btn, input[type='submit'], button {
	display: inline-block;
	padding: .35rem .75rem;
	border: 1px solid var(--border-strong);
	border-radius: 7px;
	background: var(--surface);
	color: var(--text);
	font: inherit;
	font-size: .9rem;
	text-decoration: none;
	cursor: pointer;
}

.btn:hover, input[type='submit']:hover, button:hover { border-color: var(--accent); }
.btn-primary, input[type='submit'] { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }
.btn-small { padding: .22rem .55rem; font-size: .82rem; }
.btn.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.btn-danger, .card.danger input[type='submit'] { background: var(--bad); border-color: var(--bad); color: #fff; }

/* Zamčené tlačítko u nevratné akce — dokud se neopíše jméno, nemá vypadat
   jako by stačilo kliknout. */
.btn:disabled, button:disabled, input[type='submit']:disabled {
	opacity: .45;
	cursor: not-allowed;
}
.link-danger { color: var(--bad); }

.buttons { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: 1rem; align-items: center; }

.error { color: var(--bad); font-size: .8rem; display: block; margin-top: .2rem; }

/* --- přepínač motivu ------------------------------------------------------ */

.theme-switch {
	display: inline-flex;
	border: 1px solid var(--border);
	background: var(--surface);
	border-radius: 999px;
	padding: 2px;
	gap: 2px;
}

.theme-switch button {
	border: 0;
	background: transparent;
	color: var(--muted);
	border-radius: 999px;
	padding: .2rem .6rem;
	font-size: .78rem;
	line-height: 1.4;
}

.theme-switch button:hover { color: var(--text); }
.theme-switch button[aria-pressed='true'] { background: var(--accent); color: var(--accent-text); }

/* --- přihlášení ---------------------------------------------------------- */

.signin { min-height: 80vh; display: grid; place-items: center; padding: 1rem; }
.signin .card { width: min(23rem, 100%); }
.signin form { max-width: none; }
.signin h1 { margin-bottom: .2rem; }
.signin input { max-width: none; }

@media (max-width: 52rem) {
	.layout { flex-direction: column; }
	.sidebar { width: auto; flex: none; position: static; height: auto; }
	.sidebar nav { flex-direction: row; flex-wrap: wrap; }
	.sidebar-foot { flex-direction: row; justify-content: space-between; align-items: center; }
	.content { padding: 1rem; }
	.record-row { grid-template-columns: 1fr; }
}


/* DNS potřebuje PEVNÉ rozvržení tabulky.
   Při automatickém je `width` jen návrh a hodnota s `break-all` se umí zmenšit
   skoro na nulu — prohlížeč jí pak místo sebral a dal ho sloupci s tříznakovou
   zkratkou. S `table-layout: fixed` platí šířky tak, jak jsou napsané.
   Vyšší specificita (.table.table-dns) je tu schválně: obecné pravidlo
   `.table td:first-child { width: 100% }` má stejnou váhu a přebilo by to. */
.table-dns { table-layout: fixed; }
.table.table-dns td:first-child, .table.table-dns th:first-child { width: 5rem; white-space: nowrap; }
.table.table-dns td:nth-child(2), .table.table-dns th:nth-child(2) { width: 6.5rem; white-space: nowrap; }
.table.table-dns td:last-child, .table.table-dns th:last-child { width: auto; white-space: normal; }

/* Seznam záznamů pro zónu má dva dlouhé sloupce (jméno a hodnota) a jeden úzký
   se stavem. Pevné rozvržení ze stejného důvodu jako u .table-dns výš; navíc
   zarovnání nahoru, protože pod jménem stojí ještě věta, proč záznam je. */
.table-zone { table-layout: fixed; }
.table.table-zone td { vertical-align: top; }
.table.table-zone td:first-child, .table.table-zone th:first-child { width: 34%; white-space: normal; }
.table.table-zone td:nth-child(2), .table.table-zone th:nth-child(2) { width: auto; white-space: normal; }
.table.table-zone td:last-child, .table.table-zone th:last-child { width: 7rem; white-space: nowrap; }
.table.table-zone small { margin-top: .15rem; }

/* Přehled nastavení klienta je dvojice popisek/hodnota, ne seznam záznamů.
   Výchozí pravidlo dává první sloupec roztáhnout na všechno místo — tady je
   v něm jednoslovný popisek a roztáhnout se má naopak hodnota vedle něj. */
.table.table-setup th:first-child { width: 1%; vertical-align: top; padding-top: .5rem; }
.table.table-setup td:not(:first-child) { white-space: normal; width: auto; }

/* Popisek je tu <th> uvnitř <tbody>, ne v hlavičce — pravidla psaná pro <td>
   by ho jinak minula a poslední řádek by měl čáru jen pod půlkou. */
.table.table-setup tr:last-child th { border-bottom: 0; }
.table.table-setup tbody tr:hover th { background: var(--surface-2); }

/* Hodnota a tlačítko vedle sebe; tlačítko se nesmí zmenšovat, hodnota ano. */
.record-row { display: flex; align-items: flex-start; gap: .4rem; margin-bottom: .25rem; }
.record-row:last-child { margin-bottom: 0; }
.record-row code { flex: 1 1 auto; min-width: 0; }

/* Ikona místo slova — u čtyř řádků pod sebou zabíral text víc místa než
   hodnota, kvůli které tam tlačítko je. */
.copy {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.75rem;
	height: 1.75rem;
	padding: 0;
	border: 1px solid var(--border);
	border-radius: 4px;
	background: var(--surface-2);
	color: var(--muted);
	cursor: pointer;
}

.copy:hover { color: var(--text); }
.copy svg { width: .9rem; height: .9rem; }
.copy .hotovo { display: none; }
.copy[data-done] { color: #4ade80; border-color: currentColor; }
.copy[data-done] .ikona { display: none; }
.copy[data-done] .hotovo { display: block; }


/* Přidělené schránky se nevybírají ze seznamu stovek položek, ale přidávají
   po jedné s našeptáváním. */
.grant-list { list-style: none; padding: 0; margin: 0 0 .7rem; }
.grant-list li { display: flex; align-items: center; justify-content: space-between; gap: .6rem; padding: .3rem 0; border-bottom: 1px solid var(--border); }
.grant-list li:last-child { border-bottom: 0; }


/* --- formulář jako tabulka ----------------------------------------------- */

/* Nette vykresluje formulář do tabulky, takže popisek je v <th>. Výchozí svislé
   zarovnání je na střed a u víceřádkových prvků - zaškrtávátek nebo pole
   s vysvětlivkou - pak popisek plave uprostřed místo u prvního řádku.
   Odsazení shora dorovnává vnitřní odsazení vstupního pole, aby text popisku
   seděl na stejné účaří jako první řádek prvku. */
form table th {
	vertical-align: top;
	padding-top: .45rem;
	font-weight: 400;
	color: var(--muted);
	font-size: .82rem;
}

form table td { vertical-align: top; }

/* Vysvětlivka patří pod prvek, ne za něj. Bez tohohle se u seznamu zaškrtávátek
   nalepí za poslední položku a vypadá jako její součást. */
form table td small,
form table td .description { display: block; margin-top: .3rem; color: var(--muted); font-size: .78rem; }


/* --- přepínače ------------------------------------------------------------ */

/* Zaškrtávátko nese v administraci vždycky stav „zapnuto / vypnuto", ne výběr
   z možností - přepínač to řekne na první pohled a barva odpoví na otázku
   „je to aktivní?" dřív, než člověk přečte popisek.
   Červená u vypnutého je záměr: většina těch přepínačů něco povoluje, takže
   vypnutý stav je ten, který stojí za povšimnutí. */
input[type='checkbox'] {
	appearance: none;
	-webkit-appearance: none;
	flex: 0 0 auto;
	width: 2.2rem;
	height: 1.2rem;
	margin: 0 .45rem 0 0;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: var(--bad);
	position: relative;
	cursor: pointer;
	vertical-align: -.28rem;
	transition: background .15s ease;
}

input[type='checkbox']::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 2px;
	width: .9rem;
	height: .9rem;
	border-radius: 50%;
	background: #fff;
	transform: translateY(-50%);
	transition: left .15s ease;
}

input[type='checkbox']:checked { background: var(--ok); }
input[type='checkbox']:checked::after { left: calc(100% - .9rem - 2px); }
input[type='checkbox'][disabled] { opacity: .5; cursor: default; }

/* Týž přepínač jako odkaz. Ve výpisu schránek není formulář, do kterého by
   zaškrtávátko patřilo, a odkaz na signál funguje i bez JavaScriptu. Vypadat
   musí stejně jako přepínače ve formulářích, aby se nemusel učit podruhé:
   dráha je ::before, kolečko ::after a stav řídí aria-checked — tedy právě
   ten atribut, který stav hlásí i čtečkám, ne třída vedle něj. */
.switch {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
	position: relative;
	text-decoration: none;
	color: var(--muted);
	font-size: .82rem;
}

.switch:hover { text-decoration: none; }

.switch::before {
	content: '';
	flex: 0 0 auto;
	width: 2.2rem;
	height: 1.2rem;
	border-radius: 999px;
	background: var(--bad);
	transition: background .15s ease;
}

.switch::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 2px;
	width: .9rem;
	height: .9rem;
	border-radius: 50%;
	background: #fff;
	transform: translateY(-50%);
	transition: left .15s ease;
}

.switch[aria-checked='true']::before { background: var(--ok); }
.switch[aria-checked='true']::after { left: calc(2.2rem - .9rem - 2px); }

/* --- dlaždice s podrobnostmi ---------------------------------------------- */

/* Seznam, kde má každá položka víc údajů, než se vejde do řádku tabulky —
   FTP účet má jméno, poznámku, cestu, stav, poslední přihlášení a tři akce.
   V tabulce by se cesta zalomila a akce slepily k sobě. */
.tiles { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }

.tile {
	padding: .7rem .8rem;
	border: 1px solid var(--border);
	border-radius: 9px;
	background: var(--surface-2);
}

.tile.is-inactive { opacity: .7; }

.tile-head { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.tile p { margin: .3rem 0 0; }

/* Popisek a hodnota vedle sebe. Sloupec s popisky je úzký a pevný, ať se
   hodnoty pod sebou dají číst jedním pohledem. */
.tile-facts { display: grid; grid-template-columns: 6rem 1fr; gap: .2rem .6rem; margin: .45rem 0 0; }
.tile-facts dt { color: var(--muted); font-size: .8rem; padding-top: .1rem; }

/* Hodnota a tlačítko na zkopírování na jednom řádku. `flex` kvůli tomu, aby
   tlačítko zůstalo u konce hodnoty i tam, kde se hodnota zalomí. */
.tile-facts dd {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: .1rem .35rem;
	margin: 0;
	min-width: 0;
	font-size: .88rem;
}

.tile .buttons { margin: .6rem 0 0; }

/* --- dialog --------------------------------------------------------------- */

/* Ze serveru chodí otevřený, aby formulář uvnitř fungoval i bez JavaScriptu —
   do té doby vypadá jako obyčejný blok v dlaždici, ne jako okno. Teprve
   `showModal()` z něj udělá okno; `::backdrop` platí jen na modální dialog. */
.modal {
	width: 100%;
	max-width: 26rem;
	margin: .6rem 0 0;
	padding: 1rem;
	border: 1px solid var(--border);
	border-radius: 10px;
	background: var(--surface);
	color: var(--text);
}

.modal[open] { display: block; }
.modal h3 { margin: 0 0 .35rem; }
.modal form { max-width: none; margin: 0; }
.modal .buttons { margin: .9rem 0 0; }

/* Okno uprostřed obrazovky. `:modal` chytne jen dialog otevřený přes
   showModal(), takže tenhle blok se netýká toho, co drží šablona otevřené. */
.modal:modal {
	margin: auto;
	box-shadow: 0 12px 40px rgb(0 0 0 / .35);
}

.modal::backdrop { background: rgb(0 0 0 / .5); }

/* --- výběr složek pro zálohu ---------------------------------------------- */

/* Strom složek projektu, u každé přepínač „zálohovat / nezálohovat".

   ODSAZENÍ NESE PROMĚNNÁ --level PŘÍMO NA ŘÁDKU. Hloubka je vlastnost dat,
   ne pár tříd pro každou úroveň zvlášť — a hlubší výpis si o nové pravidlo
   v CSS neřekne.

   VÝPIS SE NEROLUJE. Je to celý výběr toho, co se zálohuje, takže se v něm
   hledá očima po stránce, ne v okénku s vlastním posuvníkem — a při hledání
   se posuvník uvnitř karty plete s tím od stránky. Že je seznam dlouhý, je
   rozhodnutí člověka: základní výpis jde do tří úrovní a hlubší se vyžádá
   odkazem pod ním. */
.dirtree {
	list-style: none;
	margin: 0 0 .9rem;
	padding: .35rem 0;
	border: 1px solid var(--border);
	border-radius: 8px;
	background: var(--surface-2);
}

.dirtree li {
	display: flex;
	align-items: center;
	gap: .4rem;
	padding: .12rem .7rem .12rem calc(.7rem + var(--level, 0) * 1.3rem);
	font-size: .9rem;
}

.dirtree input[type='checkbox'] { margin-right: 0; }
.dirtree label { display: inline-flex; align-items: center; min-width: 0; margin: 0; }
/* Dlouhé jméno složky se zalomí. Ve výpisu bez posuvníku není kam ho odsunout
   a vodorovný posuvník uvnitř karty je totéž, čemu se výpis vyhýbá svisle. */
.dirtree code { background: none; padding: 0; overflow-wrap: anywhere; }
.dirtree-size { margin-left: auto; color: var(--muted); font-size: .78rem; white-space: nowrap; }

/* Cesta, která v seznamu je, ale na disku už ne. Přeškrtnutí to řekne dřív,
   než člověk dočte odznak vedle. */
.dirtree li.is-missing code { color: var(--bad); text-decoration: line-through; }
.dirtree li.is-excluded code, .dirtree li.is-blocked code { color: var(--muted); }

/* Odznaky o vynechání jsou v HTML pořád a ukazuje je až třída na řádku:
   přepínáním se mění a dopisovat je v JavaScriptu by znamenalo držet tytéž
   texty na dvou místech. */
.dirtree .badge-excluded, .dirtree .badge-blocked { display: none; }
.dirtree li.is-excluded .badge-excluded { display: inline-block; }
.dirtree li.is-blocked .badge-blocked { display: inline-block; }


/* --- zálohy na NASu -------------------------------------------------------- */

/* Seznam snapshotů, ze kterých jde obnovovat. Vypadá jako strom složek vedle
   něj schválně: je to zase výběr jednoho řádku v ohraničeném seznamu, jen
   místo přepínačů má přepínač jediné volby. */
.snapshots {
	list-style: none;
	margin: 0 0 .9rem;
	padding: .35rem 0;
	border: 1px solid var(--border);
	border-radius: 8px;
	background: var(--surface-2);
}

.snapshots li {
	display: flex;
	align-items: center;
	gap: .5rem;
	padding: .25rem .7rem;
	font-size: .9rem;
}

/* Kolečko v hodnotě, jakou má výběr na přihlašovací obrazovce (.choice) —
   výchozí velikost prohlížeče je vedle přepínačů ve stromu složek drobek
   a míří se na ni myší. */
.snapshots input[type='radio'] {
	flex: 0 0 auto;
	width: 1.15rem;
	height: 1.15rem;
	margin: 0;
	accent-color: var(--accent);
	cursor: pointer;
}

.snapshots label { display: inline-flex; align-items: center; min-width: 0; margin: 0; cursor: pointer; }

.snapshot-time { white-space: nowrap; }
.snapshot-id { background: none; padding: 0; color: var(--muted); font-size: .78rem; }

/* Co v záloze je. Bývá to ve všech řádcích totéž, takže se vejde vpravo
   nadrobno — a když se seznam cest za ta léta měnil, je rozdíl vidět. Celý
   výčet drží title, do řádku se vejde zkrácený. */
.snapshot-paths {
	margin-left: auto;
	overflow: hidden;
	color: var(--muted);
	font-size: .78rem;
	text-overflow: ellipsis;
	white-space: nowrap;
}


/* Adresa je jeden údaj ve dvou prvcích, tak ať tak i vypadá: bez mezery,
   se zaoblením jen na krajích a jedinou dělicí čárou uprostřed.
   `width: auto` je nutné - obecné pravidlo dává poli i nabídce `width: 100 %`
   a bez přepsání by se každý postavil na vlastní řádek i uvnitř flexu. */
.addr-input { display: flex; align-items: stretch; max-width: 26rem; }

.addr-input input[type='text'] {
	flex: 1 1 9rem;
	width: auto;
	min-width: 0;
	max-width: none;
	border-radius: 7px 0 0 7px;
	border-right: 0;
}

.addr-input select {
	flex: 1 1 11rem;
	width: auto;
	min-width: 0;
	max-width: none;
	border-radius: 0 7px 7px 0;
}

/* Obrys při zaostření musí být nad sousedem, jinak ho druhý prvek překryje. */
.addr-input input:focus-visible, .addr-input select:focus-visible { position: relative; z-index: 1; }


/* QR kód pro Authenticator. Knihovna ho kreslí černě na průhledném pozadí,
   takže i v tmavém motivu musí mít světlý podklad — na tmavém by ho čtečka
   v telefonu nenašla. */
.qr { background: #fff; padding: .6rem; border-radius: 8px; width: max-content; margin: 0 0 .9rem; }
.qr svg { display: block; }

/* Stav ověřování v přehledu účtu. */
.mfa-state { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .8rem; }


/* Výběr způsobu ověřování.

   Terčem je celá karta, ne kolečko vedle textu: vybírá se to skoro vždycky na
   telefonu, jednou rukou. Minimální výška 3.25rem drží plochu nad hranicí, na
   kterou se dá trefit palcem, a `label` obalující `input` znamená, že kliknutí
   kamkoliv do karty volbu přepne — i bez JavaScriptu.

   Vybraná karta se pozná i bez kolečka (rámeček a podbarvení), protože na
   malém displeji je stav prvku to první, co zanikne. */
.choices { display: flex; flex-direction: column; gap: .5rem; margin-bottom: 1rem; }

.choice {
	display: flex;
	align-items: center;
	gap: .75rem;
	min-height: 3.25rem;
	padding: .7rem .85rem;
	border: 1px solid var(--border-strong);
	border-radius: 10px;
	background: var(--surface-2);
	cursor: pointer;
	/* Bez tohohle čeká prohlížeč na dvojité ťuknutí a volba se přepne se zpožděním. */
	touch-action: manipulation;
	transition: border-color .15s ease, background .15s ease;
}

.choice:hover { border-color: var(--accent); }

.choice input[type='radio'] {
	flex: none;
	width: 1.25rem;
	height: 1.25rem;
	margin: 0;
	accent-color: var(--accent);
	/* Kliká se na kartu, ne na kolečko — samo o sobě je jen ukazatel stavu. */
	pointer-events: none;
}

.choice-body { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.choice-title { font-weight: 600; line-height: 1.25; }
.choice-note { font-size: .82rem; color: var(--muted); line-height: 1.3; }

/* :has() umí všechny prohlížeče, ve kterých tahle administrace běží; kdyby ne,
   výběr funguje dál, jen se karta nezvýrazní. */
.choice:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.choice:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Potvrzovací tlačítko pod výběrem má být stejně dobře trefitelné jako volby. */
.btn-wide {
	display: block;
	width: 100%;
	min-height: 2.9rem;
	font-size: .95rem;
}

/* Hláška u tlačítka pro otisk. Chyba z dialogu prohlížeče se nesmí ztratit
   v konzoli — člověk musí vědět, jestli se čeká na jeho prst, nebo to selhalo. */
.passkey-stav { margin: .5rem 0 0; font-size: .85rem; }
.passkey-stav.bad { color: var(--bad); }

/* Dělítko mezi přihlášením otiskem a heslem. */
.delic { display: flex; align-items: center; gap: .6rem; margin: .9rem 0; font-size: .8rem; }
.delic::before, .delic::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* Rám s výpisem phpinfo. Je to cizí dokument s vlastními styly, takže jde do
   iframu — ale nemá vypadat jako vložený rám: bez rámečku a s pozadím, které si
   dokument uvnitř sladí s kartou (styl mu dopisuje PhpInfoPresenter).

   Výšku dorovnává app.js podle obsahu, aby v rámu nebyl vlastní posuvník uvnitř
   stránky, která se posouvá taky. Hodnota tady je jen pro případ, že JavaScript
   neběží — pak zůstane posuvník, ale výpis je vidět celý. */
.phpinfo {
	display: block;
	width: 100%;
	height: 75vh;
	border: 0;
	background: transparent;
}

/* Blok na polovinu šířky, přesně jako jeden sloupec v .grid-2 — pro sekce,
   které vedle sebe nikoho nemají a přes celou stránku by jen zbytečně roztahovaly
   krátký formulář nebo úzkou tabulku.

   Pod hranicí, kde se mřížka láme do jednoho sloupce, se roztáhne taky; jinak
   by na telefonu zůstal proužek vedle prázdna. */
.card.half { width: calc(50% - .5rem); }

@media (max-width: 42rem) {
	.card.half { width: 100%; }
	.grid-2.halves { grid-template-columns: 1fr; }
}

/* --- seznam databází ------------------------------------------------------ */

/* Základní .table dává první sloupec „na zbytek šířky" — u domén to sedí, protože
   za jménem je jen pár krátkých odznaků. Tady mají sloupce podobně dlouhý obsah,
   takže by jméno viselo uprostřed prázdna a zbytek by se mačkal u pravého okraje.
   Rozdělují se proto pevně.

   Jméno má nejvíc, je to identita řádku a klika, na kterou se míří; čísla vpravo
   naopak jen tolik, kolik potřebují. Šířky platí z hlavičky (table-layout: fixed),
   takže stačí popsat th — a když sloupec „Založil" chybí, protože se nedívá správce,
   zbylé se roztáhnou samy. */
.table-databases { table-layout: fixed; }
.table-databases th:nth-child(1) { width: 30%; }
.table-databases th:nth-child(2) { width: 22%; }
.table-databases th:nth-child(3) { width: 22%; }
.table-databases th:nth-child(4) { width: 12%; }
.table-databases th:nth-child(5) { width: 14%; }

/* --- obsazenost schránek -------------------------------------------------- */

/* Pruh má vlastní sloupec bez popisku — co znamená, říkají procenta nad ním.
   Šířku nestačí držet na buňce: tabulka se rozvrhuje automaticky, `width` je pro
   ni jen přání a sloupec, ve kterém není žádný text, smačkne na nulu. Pevnou
   šířku má proto sám pruh — ta se počítá do minimální šířky sloupce a tabulka
   ji dodržet musí. */
.table td.usage, .table th.usage { width: 7rem; }
.table td.usage .meter { width: 7rem; height: .4rem; margin: .15rem 0 0; max-width: none; }

/* Procenta stojí uprostřed nad pruhem — patří k němu, ne k číslu v sousedním
   sloupci. Blok má stejnou šířku jako pruh, takže střed sedí na jeho střed. */
.usage-value { display: block; width: 7rem; text-align: center; font-size: .6rem; line-height: 1.1; }
.usage-value.warn { color: var(--warn); }
.usage-value.bad { color: var(--bad); }

/* --- proxy ---------------------------------------------------------------- */

/* Záložky uvnitř sekce. Nabídka v postranním panelu ukazuje na jednu položku
   „Proxy" a rozpad na routery, služby a middlewary patří až dovnitř — v panelu
   by ze čtyř řádků udělal skupinu velkou jako pošta. */
.tabs { display: flex; flex-wrap: wrap; gap: .3rem; margin: 0 0 1rem; border-bottom: 1px solid var(--border); }

.tabs a {
	padding: .4rem .8rem;
	border: 1px solid transparent;
	border-bottom: 0;
	border-radius: 6px 6px 0 0;
	color: var(--muted);
	font-size: .9rem;
	text-decoration: none;
	margin-bottom: -1px;
}

.tabs a:hover { color: var(--text); background: var(--surface-2); }

.tabs a.active {
	color: var(--text);
	background: var(--surface);
	border-color: var(--border);
	border-bottom-color: var(--surface);
}

/* Výběr typu middlewaru. Je jich přes dvacet a v rozbalovátku by z nich byl
   jen seznam zkratek — jako dlaždice se vejde i věta o tom, k čemu typ je. */
.cards-types { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }

.type-card { display: flex; flex-direction: column; gap: .15rem; text-decoration: none; color: inherit; }
.type-card:hover { border-color: var(--accent); }
.type-card code { align-self: flex-start; font-size: .75rem; }

/* Tabulky v sekci Proxy mají pevné rozvržení a sloupce s odkazy jako pilulky.

   Obecné pravidlo výš dává prvnímu sloupci `width: 100%` a ostatním `nowrap`.
   Tady to nefunguje: middleware `allow-lan` používá jedenáct routerů, ten
   sloupec se nezalomil, roztáhl tabulku a jméno v prvním sloupci se pak lámalo
   po slabikách. Pevné šířky drží rozvržení bez ohledu na to, kolik odkazů kde
   je, a pilulky se zalomí do dalšího řádku. */
.table-proxy { table-layout: fixed; }
.table-proxy td, .table-proxy th { white-space: normal; width: auto; }
.table-proxy td:first-child, .table-proxy th:first-child { width: auto; }
.table-proxy th:last-child, .table-proxy td:last-child { text-align: right; }

.table-routers th:nth-child(1) { width: 26%; }
.table-routers th:nth-child(2) { width: 17%; }
.table-routers th:nth-child(3) { width: 7%; }
.table-routers th:nth-child(4) { width: 9%; }
.table-routers th:nth-child(5) { width: 28%; }
.table-routers th:nth-child(6) { width: 13%; }

.table-services th:nth-child(1) { width: 24%; }
.table-services th:nth-child(2) { width: 44%; }
.table-services th:nth-child(3) { width: 18%; }
.table-services th:nth-child(4) { width: 14%; }

.table-middlewares th:nth-child(1) { width: 26%; }
.table-middlewares th:nth-child(2) { width: 19%; }
.table-middlewares th:nth-child(3) { width: 42%; }
.table-middlewares th:nth-child(4) { width: 13%; }

.table-transports th:nth-child(1) { width: 26%; }
.table-transports th:nth-child(2) { width: 61%; }
.table-transports th:nth-child(3) { width: 13%; }

/* Jména routerů a služeb v buňce. Je jich klidně dvanáct, takže se musí zalomit
   jako celá slova — uvnitř jedné pilulky se ale lámat nesmí, jinak z ní není
   poznat, kde jméno začíná a končí. */
.pills { display: flex; flex-wrap: wrap; gap: .25rem; }

.pill {
	display: inline-block;
	max-width: 100%;
	padding: .08rem .45rem;
	border-radius: 999px;
	background: var(--surface-2);
	border: 1px solid var(--border);
	font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
	font-size: .74rem;
	line-height: 1.5;
	color: var(--text);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Adresa serveru se do pilulky nevejde a zkrátit se nesmí — je to jediné místo,
   kde je vidět port. Zalomí se proto uvnitř. */
.pill-wide { white-space: normal; word-break: break-all; text-align: left; }

/* Pilulka pro doplňkovou hodnotu — vstupní body vedle služby. Stejný tvar, aby
   spolu v jedné buňce ladily, ale bez výplně: služba je to podstatné, entrypoint
   jen upřesňuje, kudy se tam chodí. */
.pill-soft { background: none; color: var(--muted); font-size: .7rem; }

/* Jméno položky a popisek pod ním. Popisek je delší věta, takže se láme; jméno
   ne — rozlámané jméno v úzkém sloupci je nečitelné. */
.cell-name strong, .cell-name a { display: block; word-break: break-word; }

/* Popisek nad jménem položky.

   Nahoře je schválně: při hledání v seznamu je první otázka „k čemu to je", ne
   „jak se to jmenuje" — jméno je technický klíč, který se hodí až potom. Musí
   být taky na vlastním řádku; jako inline `.muted` splýval s pravidlem pod sebou
   v jeden šedý odstavec a vypadal jako pokračování jména. */
.cell-name .note {
	display: block;
	margin-bottom: .15rem;
	font-size: .82rem;
	line-height: 1.35;
	color: var(--text);
}

/* Pravidlo routeru je technická hodnota, ne věta — monospace ji odliší od
   popisku nad ním a dlouhý výraz se zalomí, místo aby roztáhl sloupec. */
.cell-name .rule {
	display: block;
	margin-top: .15rem;
	font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
	font-size: .74rem;
	line-height: 1.4;
	color: var(--muted);
	word-break: break-word;
}

/* Definiční tabulka: popisek v <th> vlevo, hodnota v <td> vpravo, bez hlavičky.

   Obecné pravidlo pro tabulky výš platí pro seznamy — první sloupec nese jméno
   a bere zbývající místo, ostatní se smrští na obsah a nezalomí se. V definiční
   tabulce je to přesně obráceně: popisek je krátký a pevný, hodnota může být celý
   odstavec. Bez tohohle dostal popisek `width: 100%`, hodnota `nowrap` a dlouhý
   text přetekl z karty ven (vysvětlivka u otisku zařízení).

   Pozná se podle toho, že <th> je v tbody, ne v thead — seznamy mají hlavičku,
   definiční tabulky ne. Platí to tedy i pro ty, které teprve vzniknou. */
.table tbody > tr > th:first-child {
	width: 1%;
	white-space: nowrap;
	vertical-align: top;
	padding: .45rem .55rem;
}

.table tbody > tr > th:first-child ~ td {
	width: auto;
	white-space: normal;
	vertical-align: top;
}

/* --- seznam uživatelů ------------------------------------------------------ */

/* Účet má vedle jména ještě čtyři výčty: druhý faktor, spravované domény,
   přidělené schránky a e-mail. Obecné pravidlo drží všechny sloupce kromě
   prvního na jednom řádku, takže se tabulka roztahovala tak dlouho, dokud se
   nejdelší výčet nevešel — u účtu se třemi faktory přetekla z karty ven.

   Rozvržení je proto pevné a výčty se zalomí. Šířky platí z hlavičky
   (table-layout: fixed), takže stačí popsat th. Nejvíc má účet a druhý faktor:
   účet je identita řádku a klika, na kterou se míří, faktory jsou nejdelší text.

   Vyšší specificita (.table.table-users) je tu schválně, stejně jako u tabulek
   výš: obecná pravidla mají stejnou váhu a přebila by to. */
.table-users { table-layout: fixed; }
.table.table-users th, .table.table-users td { white-space: normal; overflow-wrap: anywhere; }
.table.table-users th:nth-child(1) { width: 17%; }
.table.table-users th:nth-child(2) { width: 15%; }
.table.table-users th:nth-child(3) { width: 14%; }
.table.table-users th:nth-child(4) { width: 16%; }
.table.table-users th:nth-child(5) { width: 15%; }
.table.table-users th:nth-child(6) { width: 14%; }
.table.table-users th:nth-child(7) { width: 9%; }

/* Řádek je vysoký podle nejdelšího výčtu; na střed zarovnaný účet by se pak
   vznášel uprostřed prázdna vedle něj. */
.table.table-users td { vertical-align: top; }

/* Buňka účtu má tři patra: přihlašovací jméno, pod ním celé jméno a teprve pak
   odznaky. Odkaz je blokem už z .cell-name, blokem musí být i jméno — odznak
   vedle něj se čte jako přípona jména, přitom mluví o stavu účtu. */
.table.table-users .cell-name .muted { display: block; }

/* Pilulka si tu nechává tvar, ale ne strojové písmo: jinde je v ní jméno routeru
   nebo služby, tady věta pro člověka. A dlouhý název se radši zalomí, než aby
   zmizel pod výpustkou — jméno faktoru je celé, nebo k ničemu. */
.table.table-users .pill { font-family: inherit; font-size: .78rem; white-space: normal; }

/* Barva odliší faktory od sebe na první pohled — ve výpisu se pak dá porovnávat
   po sloupci, aniž by se každý řádek četl. Rámeček i text, výplň ne: pilulka je
   štítek, ne tlačítko. */
.pill-sms { color: var(--factor-sms); border-color: var(--factor-sms); }
.pill-email { color: var(--factor-email); border-color: var(--factor-email); }
.pill-totp { color: var(--factor-totp); border-color: var(--factor-totp); }

/* Telefon je jedno číslo a rozlomit se nesmí — předvolba na samostatném řádku
   vypadá jako dvě čísla. Když se do sloupce přesto nevejde (úzké okno, delší
   předvolba), utne ho výpustka: nezalomené číslo jinak vyteče přes sousední
   sloupec a překryje ho. */
.table.table-users td:nth-child(3) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Akce se pod sebe zalomit můžou, jméno akce ne: „nové“ a „heslo“ na dvou
   řádcích už není odkaz, ale hádanka. */
.table.table-users td:last-child a { white-space: nowrap; }
