/* The management dashboard. Desktop-first, the mirror image of the field screens:
   a wide table beats a stack of cards when the job is scanning twenty rows for the
   one that is wrong. */

.page-head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--s-3);
	margin-bottom: var(--s-5);
}

.page-head h1 {
	font-size: var(--fs-2xl);
}

/* Let the heading block shrink instead of pushing the action onto its own line: a
   long subtitle otherwise sets the minimum width of the whole row. */
.page-head > div {
	min-width: 0;
}

/* A table is the one thing that genuinely cannot reflow to 375px. Let it scroll
   inside its own box rather than pushing the whole page sideways. */
.table-scroll {
	overflow-x: auto;
	margin-bottom: var(--s-5);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-lg);
	background: var(--c-surface);
}

.table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--fs-sm);
}

.table th,
.table td {
	padding: var(--s-2) var(--s-3);
	text-align: left;
	vertical-align: middle;
	border-bottom: 1px solid var(--c-border);
	white-space: nowrap;
}

.table thead th {
	white-space: normal;
	vertical-align: bottom;
	position: sticky;
	top: 0;
	z-index: 1;
	background: var(--c-surface-sunken);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--c-text-muted);
}

.table tbody tr:last-child td {
	border-bottom: 0;
}

.table tbody tr:hover {
	background: var(--c-primary-subtle);
}

/* `th.`/`td.` rather than the bare class: `.table th, .table td` above sets
   `text-align: left` at specificity (0,1,1), which beat a lone `.table__number` at
   (0,1,0) — so every numeric column in the app has been left-aligned since the class
   was written. alpdest spotted it on the Monteure times; it was also the position
   counts, the resort breakdown, the surface list and the import preview
   (26 Aug 2026). */
th.table__number,
td.table__number {
	text-align: right;
}

/* Deactivated rows stay visible — they answer "who was on the team in February?" —
   but recede, so a scan for a live account does not stop on them. */
.table__row--muted td {
	color: var(--c-text-muted);
}

.table__actions {
	display: flex;
	gap: var(--s-2);
	justify-content: flex-end;
}

/* A secondary action next to a primary one: same size and hit area, less shouting. */
.btn--quiet {
	background: transparent;
	border: 1px solid var(--c-border-strong);
	color: var(--c-primary);
	font-weight: 600;
}

.btn--quiet:hover {
	background: var(--c-surface-sunken);
	color: var(--c-primary-hover);
}


/* --- Filters ------------------------------------------------------------- */

/* Tabs in all but name. Which set you are looking at has to be readable without
   reading — a manager lands here dozens of times a week. */
/* No rule underneath. The table below starts with its own header band, so the line
   sat two pixels above another line and read as a mistake (20 Aug 2026). */
.filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--s-1);
	margin-bottom: var(--s-3);
}

/* The search box that sits in front of the tabs. Narrow: it is a filter like the
   others, not the main control of the page. */
.filters__search {
	display: flex;
	align-items: center;
	margin-right: var(--s-2);
}

.filters__search input {
	width: 11rem;
	height: 2rem;
	padding: var(--s-1) var(--s-2);
	font-size: var(--fs-sm);
}

/* Between groups of tabs, so five in a row do not read as one list of eight. */
.filters__rule {
	width: 1px;
	align-self: stretch;
	margin: var(--s-1) var(--s-2);
	background: var(--c-border);
}

.filters__item {
	display: inline-flex;
	align-items: center;
	gap: var(--s-2);
	padding: var(--s-2);
	white-space: nowrap;
	margin-bottom: -1px;
	border: 1px solid transparent;
	border-bottom: 2px solid transparent;
	color: var(--c-text-muted);
	font-size: var(--fs-sm);
	font-weight: 600;
	text-decoration: none;
}

.filters__item:hover {
	color: var(--c-text);
	text-decoration: none;
}

.filters__item--on {
	border-bottom-color: var(--c-primary);
	border-radius: var(--radius);
	background: var(--c-primary-subtle);
	color: var(--c-primary);
}

.filters__count {
	padding: 0 var(--s-2);
	border-radius: 999px;
	background: var(--c-surface-sunken);
	font-size: 0.75rem;
	font-weight: 700;
}

.filters__item--on .filters__count {
	background: var(--c-primary-subtle);
	color: var(--c-primary);
}

/* --- Desktop tables ------------------------------------------------------ */

/* Proportional columns rather than content-width ones: the header row should not
   jump sideways when a long email address arrives. */
.table--fixed {
	table-layout: fixed;
}

.table--fixed th:nth-child(1) { width: 18%; }
.table--fixed th:nth-child(2) { width: 22%; }
.table--fixed th:nth-child(3) { width: 8%; }
.table--fixed th:nth-child(4) { width: 12%; }
.table--fixed th:nth-child(5) { width: 12%; }
.table--fixed th:nth-child(6) { width: 8%; }
/* The rest goes to the actions column — enough for both buttons at their widest.
   A flex row with justify-content:flex-end overflows *leftwards* when it runs out of
   room, straight over the status badge, which is how this was first noticed. */

.table--fixed td:nth-child(1),
.table--fixed td:nth-child(2) {
	overflow: hidden;
	text-overflow: ellipsis;
}

.table__actions-head {
	text-align: right;
}

.table__empty {
	padding: var(--s-6);
	text-align: center;
	color: var(--c-text-muted);
}

/* Every row carries the same two buttons, so they are quiet and small — a wall of
   blue down the right-hand side would compete with the data. */
.row-actions {
	display: flex;
	gap: var(--s-2);
	justify-content: flex-end;
}

.btn--sm {
	min-height: 2rem;
	padding: 0 var(--s-3);
	font-size: var(--fs-sm);
}

/* --- Forms --------------------------------------------------------------- */

/* A form does not want the full width of a laptop: the eye should not have to travel
   across empty space between a label and its input. */
.form-page {
	max-width: 34rem;
}

.form-page .card {
	margin-bottom: var(--s-4);
}

/* Two fields that belong together, side by side above 40rem. */
.field-grid {
	display: grid;
	gap: var(--s-3);
}

@media (min-width: 40rem) {
	.field-grid {
		grid-template-columns: 1fr 1fr;
	}
}

/* Facts about an existing person: read-only, quiet, and not pretending to be a form. */
.meta-list {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: var(--s-1) var(--s-4);
	margin-bottom: var(--s-4);
	padding: var(--s-3) var(--s-4);
	background: var(--c-surface-sunken);
	border-radius: var(--radius-lg);
	font-size: var(--fs-sm);
}

.meta-list dt {
	color: var(--c-text-muted);
}

.meta-list dd {
	margin: 0;
	font-variant-numeric: tabular-nums;
}

/* The role radios read as a list of sentences, not a row of dots. */
.field--radio ul,
.form-page ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.form-page li label {
	display: flex;
	align-items: baseline;
	gap: var(--s-2);
	padding: var(--s-1) 0;
	font-weight: 400;
}


/* --- Reference data hub --------------------------------------------------- */

.cards {
	display: grid;
	gap: var(--s-3);
	grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
}

.card--link {
	display: block;
	color: inherit;
	text-decoration: none;
	transition: border-color 120ms, box-shadow 120ms;
}

.card--link:hover {
	color: inherit;
	border-color: var(--c-primary);
	box-shadow: var(--shadow-lg);
	text-decoration: none;
}

.card__count {
	margin-top: var(--s-3);
	font-weight: 700;
}

/* A path back up, for screens two levels deep. The dashboard nav only reaches the
   hub, and a list of resorts is one further in. */
.crumbs {
	display: flex;
	align-items: center;
	gap: var(--s-2);
	margin-bottom: var(--s-3);
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}


/* --- Position list -------------------------------------------------------- */

/* Filters wrap rather than scroll: on a laptop they fill one line, on a narrow
   window they stack, and nothing is ever hidden behind a horizontal scrollbar. */
/* No card around it. It is a row of controls, not a panel — and a white box on a
   white-ish page mostly announced its own edges (20 Aug 2026). Same treatment as the
   tabs on Personen. */
.filter-bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--s-2);
	margin-bottom: var(--s-3);
}

/* One line, and the same height throughout. A select sized to its longest option —
   "DOOH Switzerland Country Packages" — is a control four times the width of the one
   beside it, and eight of them wrapped onto three rows (alpdest, 20 Aug 2026).

   `text-overflow: ellipsis` cuts the *closed* control only; the open dropdown is
   drawn by the operating system and shows every option in full, so nothing is
   actually hidden from the reader. */
.filter-bar select,
.filter-bar input[type="search"],
.filter-bar input[type="text"] {
	height: 2.5rem;
	min-height: 0;
	padding: var(--s-1) var(--s-2);
	font-size: var(--fs-sm);
}

.filter-bar select {
	flex: 0 1 auto;
	width: auto;
	max-width: 7.75rem;
	text-overflow: ellipsis;
}

/* The labels are visually hidden but still flex items, so each one was contributing
   its own gap: eight of them cost 70px of the line and pushed the last two controls
   onto a second row. Taking them out of the flow costs nothing — a screen reader
   finds them through `for`, not through where they sit. */
.filter-bar .visually-hidden {
	position: absolute;
}

/* The search box gets whatever the selects leave. It shrinks before they do, because
   a search box is still usable narrow and a truncated dropdown is not. */
.filter-bar__search {
	flex: 1 1 9rem;
	min-width: 7rem;
}

.filter-bar__search input {
	width: 100%;
}

/* Push the reset to the end of the line, whatever is in front of it, and match the
   height of the controls it sits beside — a shorter button on the same row reads as
   a different kind of thing. */
.filter-bar > .btn:last-child {
	margin-left: auto;
	height: 2.5rem;
	min-height: 0;
	white-space: nowrap;
}

/* Sits above the table so the count and the action are where the eye already is
   after ticking a row. */
.bulk-bar {
	display: flex;
	align-items: center;
	gap: var(--s-3);
	min-height: 2.5rem;
	margin-bottom: var(--s-2);
}

/* `.row-actions` is right-aligned because it lives in the last cell of a table row.
   In a card it should start where the heading above it does. */
.card > .row-actions {
	justify-content: flex-start;
}

/* A state as a word rather than a badge. In a table a badge sets the row height and
   makes every line taller than its text needs — and it is what pushed the action
   buttons out of line with their own header (20 Aug 2026). */
.state {
	font-weight: 600;
}

.state--on { color: var(--c-success); }
.state--off { color: var(--c-text-muted); }

/* Tighter rows on the people list. Seven columns of one short line each do not need
   the height a report row does. */
.table--tight th,
.table--tight td {
	padding-top: var(--s-1);
	padding-bottom: var(--s-1);
	white-space: nowrap;
}

.table--tight .row-actions {
	gap: var(--s-1);
}

/* An edit screen that also has something to read beside it: the form on the left, the
   account's own facts on the right, the same two-panel shape as the position detail.
   `.form-page` stays narrow for creating somebody, where there is nothing to show. */
.form-page--wide {
	max-width: none;
}

/* A form whose content is two boxes side by side. Wider than a single column of
   fields, narrower than the whole laptop — two small cards stretched across 1600px
   read as a page that lost its content. */
.form-page--pair {
	max-width: 58rem;
}

/* Every status the same width, so the column reads as a column rather than as ragged
   text of five different lengths. 7ch fits "Erledigt", the longest of them. */
.badge--block {
	display: inline-block;
	min-width: 7ch;
	text-align: center;
}

/* An <abbr> here is a code with its full name on the title. No dotted underline —
   there are three of them per row and the table would look ruled. */
.table abbr {
	text-decoration: none;
	border-bottom: none;
	cursor: help;
}

.table__pick {
	width: 2.5rem;
	text-align: center;
}

.table__pick input {
	width: 1.1rem;
	height: 1.1rem;
	min-height: 0;
}

.table__sortable a {
	display: inline-flex;
	align-items: center;
	gap: var(--s-1);
	color: inherit;
	text-decoration: none;
	white-space: nowrap;
}

.table__sortable a:hover {
	color: var(--c-primary);
}

.table__sortable--on {
	color: var(--c-primary);
}

.pagination {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--s-3);
	margin-bottom: var(--s-6);
}

.pagination__where {
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

/* --- Position detail ------------------------------------------------------ */

.detail-grid {
	display: grid;
	gap: var(--s-3);
	margin-bottom: var(--s-5);
	grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
}

.detail-grid .meta-list {
	background: transparent;
	padding: 0;
}

.reports h2 {
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--c-text-muted);
	margin-bottom: var(--s-3);
}

/* One card per report, newest first — the answer to "why is this still open?". */
.report-card {
	padding: var(--s-4);
	margin-bottom: var(--s-3);
	background: var(--c-surface);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-lg);
}

.report-card__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--s-3);
	margin-bottom: var(--s-2);
}

.photo-gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
	gap: var(--s-2);
	margin-top: var(--s-3);
	list-style: none;
	padding: 0;
}

.photo-gallery img {
	width: 100%;
	/* `height: auto` is load-bearing, not tidiness. The <img> carries width and
	   height attributes so the row does not jump while the photo loads, and those
	   map to CSS as presentational hints. A hint only loses to a real rule on the
	   same property — nothing here set `height`, so `height: 900px` survived and
	   `aspect-ratio` was ignored, because it applies only when height is auto. The
	   result was a 160×900 sliver of one photo. */
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--radius);
	background: var(--c-surface-sunken);
}

.plain-list {
	list-style: none;
	margin: var(--s-2) 0 0;
	padding: 0;
	font-size: var(--fs-sm);
}

.plain-list li {
	padding: var(--s-1) 0;
	border-bottom: 1px solid var(--c-border);
}

/* A cell of free text among columns of codes and numbers. Capped and clipped: a
   Standortdetail is a sentence, and one long one otherwise decides the width of the
   whole table. The full text is on the surface, one click away. */
.table__note {
	max-width: 18rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.text-danger {
	color: var(--c-danger);
	font-weight: 600;
}

/* Not an error — something the office still has to get to. A provisional ID and a
   board with no measurements are both work waiting, not faults. */
.text-warning {
	color: var(--c-warning);
	font-weight: 600;
}


/* --- Week dashboard ------------------------------------------------------- */

.counters {
	display: grid;
	gap: var(--s-3);
	margin-bottom: var(--s-5);
	grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}

/* A coloured edge rather than a coloured card: four saturated blocks across the top
   of a screen compete with the data underneath, and the point of the colour is only
   to say which number is the worrying one. */
.counter {
	position: relative;
	background: var(--c-surface);
	border: 1px solid var(--c-border);
	border-left: 4px solid var(--c-border-strong);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow);
}

.counter--danger { border-left-color: var(--c-danger); }
.counter--success { border-left-color: var(--c-success); }
.counter--warning { border-left-color: var(--c-warning); }
.counter--info { border-left-color: var(--c-primary); }
.counter--muted { border-left-color: var(--c-border-strong); }

.counter__peek {
	display: block;
	padding: var(--s-3) var(--s-4);
	color: inherit;
	text-decoration: none;
}

.counter__peek:hover {
	color: inherit;
	text-decoration: none;
	background: var(--c-primary-subtle);
	border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
}

.counter__label {
	display: block;
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--c-text-muted);
}

.counter__value {
	display: block;
	font-size: 2rem;
	font-weight: 700;
	line-height: 1.15;
}

.counter__note {
	display: block;
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

/* Its own target, in the corner, because it does something different from the card:
   the card peeks, this leaves. */
.counter__arrow {
	position: absolute;
	top: var(--s-2);
	right: var(--s-3);
	padding: 0 var(--s-1);
	color: var(--c-text-muted);
	text-decoration: none;
	font-size: var(--fs-lg);
	line-height: 1;
}

.counter__arrow:hover {
	color: var(--c-primary);
	text-decoration: none;
}

/* Two columns on a laptop, not three: these panels are lists of sentences, and a
   third column narrows each one to the point where every line wraps. */
.week-grid {
	display: grid;
	gap: var(--s-3);
	margin-bottom: var(--s-3);
	grid-template-columns: repeat(auto-fit, minmax(30rem, 1fr));
	/* Each panel is its own height. Stretching them to match the tallest in the row
	   left a short list sitting in an acre of white while the reader scrolled past
	   nothing. */
	align-items: start;
}

/* One under the other, full width. They were side by side for an afternoon and there
   was not room: a table of five status columns and a table of nine day columns each
   had about 40 characters to live in (20 Aug 2026). */
.week-stack {
	display: flex;
	flex-direction: column;
	gap: var(--s-3);
}

/* A card is a block with something after it. Without this the problems table sat flush
   against the panel below and the two read as one long table. */
.card {
	margin-bottom: var(--s-3);
}

/* The country a run of resorts belongs to, with its own totals. A row, so it scrolls
   with the table it labels — and deliberately quieter than the header above it: it is
   a divider inside the data, not a second set of column names. Styled the same, the
   table read as two tables (20 Aug 2026). */
.table__group td {
	padding-top: var(--s-2);
	padding-bottom: var(--s-2);
	background: var(--c-surface-sunken);
	border-bottom: 1px solid var(--c-border);
	font-weight: 600;
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

/* Assigning: the positions on the left, the people on the right. The question is
   "who goes to *these*", and it is easier to answer with both on screen. */
.assign-grid {
	display: grid;
	gap: var(--s-3);
	grid-template-columns: 1fr;
	align-items: start;
	margin-bottom: var(--s-3);
}

@media (min-width: 60rem) {
	.assign-grid {
		grid-template-columns: minmax(18rem, 1fr) 2fr;
	}
}

.assign-list {
	max-height: 22rem;
	overflow-y: auto;
}

.assign-list li {
	display: flex;
	flex-direction: column;
	padding: var(--s-1) 0;
	border-bottom: 1px solid var(--c-border);
	font-size: var(--fs-sm);
}

.assign-list li:last-child { border-bottom: none; }

/* Three columns of names. Five down one side of a wide card is a lot of scrolling
   past nothing, and the list only grows. */
/* Django wraps a CheckboxSelectMultiple in a plain <div> of <div>s — the grid goes
   on that wrapper. One column on a phone, three once there is room: this screen is
   the office's, but it has to survive being opened on a tablet. */
.assign-people > div {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--s-1) var(--s-4);
}

.assign-people label {
	display: flex;
	align-items: center;
	gap: var(--s-2);
	padding: var(--s-1) 0;
}

@media (min-width: 48rem) {
	.assign-people > div {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* A link that is not the point of the cell — the whole row already opens the thing,
   and an underline under every ID turns a table into a page of links. The colour
   still says it is clickable. */
.link-plain {
	text-decoration: none;
}

.link-plain:hover {
	text-decoration: underline;
}

/* A number in a table cell that opens the list filtered to it. Coloured by the status
   it counts, so the column reads as a status column and not as four columns of
   arithmetic. */
.cell-link {
	display: inline-block;
	min-width: 1.75rem;
	padding: 0 var(--s-1);
	border-radius: var(--radius);
	font-weight: 600;
	text-decoration: none;
}

.cell-link:hover { text-decoration: none; background: var(--c-surface-sunken); }

.cell-link--planned { color: var(--c-text-muted); }
.cell-link--open { color: var(--c-status-open); }
.cell-link--problem { color: var(--c-status-problem); }
.cell-link--done { color: var(--c-status-done); }

/* The sentence under a table that says what its numbers are and are not. */
.card__note {
	margin-top: var(--s-3);
	padding-top: var(--s-2);
	border-top: 1px solid var(--c-border);
}

/* A whole row that opens something. The cell that carries the real <a> is what makes
   it reachable by keyboard and by a middle click; this only widens the target for a
   mouse. */
.row-link { cursor: pointer; }
.row-link:hover { background: var(--c-primary-subtle); }

/* Compact enough to scan: a problem row is read to answer "is any of this mine?",
   and the sentence is the part that answers it. */
.problems td { vertical-align: top; }
.problems td:last-child { width: 40%; }

.monteur-table th,
.monteur-table td,
.resort-table th,
.resort-table td {
	padding-inline: var(--s-2);
	white-space: nowrap;
}

.week-grid .card__title,
.card__title {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--s-3);
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--c-text-muted);
	margin-bottom: var(--s-3);
}

/* A second heading inside a card — "Aktionen" under the account facts. Same
   voice as the card's own title, set off by a rule rather than by size, so it
   reads as part of the card and not as a card of its own. */
.card__subtitle {
	margin: var(--s-4) 0 var(--s-2);
	padding-top: var(--s-3);
	border-top: 1px solid var(--c-border);
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--c-text-muted);
}

.card__more {
	font-size: var(--fs-sm);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	white-space: nowrap;
}

/* One row in a panel: an id, a body that takes the slack, and a tail that does not
   wrap. Used by three of the four panels, so they line up with each other. */
.line {
	display: flex;
	align-items: baseline;
	gap: var(--s-3);
	padding: var(--s-2) 0;
	border-bottom: 1px solid var(--c-border);
	color: inherit;
	text-decoration: none;
}

.line:last-child {
	border-bottom: 0;
}

.line:hover {
	color: inherit;
	text-decoration: none;
	background: var(--c-primary-subtle);
}

.line__id {
	flex: none;
	font-weight: 700;
	font-size: var(--fs-sm);
}

.line__body {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.line__tail {
	flex: none;
	display: flex;
	align-items: center;
	gap: var(--s-2);
}

.bar-row {
	display: grid;
	grid-template-columns: 8rem 1fr 3.5rem;
	align-items: center;
	gap: var(--s-3);
	padding: var(--s-1) 0;
	font-size: var(--fs-sm);
}

.bar-row__track {
	height: 6px;
	border-radius: 999px;
	background: var(--c-surface-sunken);
	overflow: hidden;
}

.bar-row__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: var(--c-primary);
}

.bar-row__value {
	text-align: right;
	font-weight: 600;
}

/* --- Submit matrix -------------------------------------------------------- */

/* Seven columns per person: somebody who stopped submitting on Wednesday is a gap you
   see, rather than a number you have to work out. */
.submit-matrix__day {
	text-align: center;
	width: 4.5rem;
}

.submit-matrix__day span {
	display: block;
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
}

.submit-matrix__cell {
	text-align: center;
	font-size: var(--fs-lg);
	line-height: 1;
}

.submit-matrix__cell--submitted { color: var(--c-success); }
.submit-matrix__cell--reopened { color: var(--c-warning); }
.submit-matrix__cell--draft { color: var(--c-text-muted); }

/* --- Drill-down dialog ---------------------------------------------------- */

.drill {
	width: min(56rem, 92vw);
	max-height: 86vh;
	padding: 0;
	border: 0;
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lg);
	background: var(--c-surface);
	color: var(--c-text);
}

.drill::backdrop {
	background: rgb(20 24 28 / 0.45);
}

.drill__inner {
	position: relative;
	padding: var(--s-5);
	max-height: 86vh;
	overflow-y: auto;
}

.drill h2 {
	font-size: var(--fs-xl);
	margin-bottom: var(--s-4);
	padding-right: var(--s-6);
}

.drill__close {
	position: absolute;
	top: var(--s-3);
	right: var(--s-3);
	display: grid;
	place-items: center;
	width: var(--tap-min);
	height: var(--tap-min);
	border-radius: var(--radius);
	background: transparent;
	font-size: var(--fs-xl);
	line-height: 1;
	cursor: pointer;
}

.drill__close:hover {
	background: var(--c-surface-sunken);
}

/* No ring on the panel itself. Focus is moved here on open so that the close button
   is not what gets outlined, and the global ring would then frame the whole dialog. */
.drill:focus,
.drill:focus-visible {
	outline: none;
}

/* Says which slice of the data is on screen when somebody arrives from elsewhere. */
.scope-banner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--s-3);
	padding: var(--s-2) var(--s-3);
	margin-bottom: var(--s-3);
	background: var(--c-primary-subtle);
	border-radius: var(--radius);
	font-size: var(--fs-sm);
}


/* --- Reopening a Monteur's week ------------------------------------------- */

/* The hours on one side, the positions on the other. Both halves of the lock on
   screen at once, because the question is "which of these is wrong" and the answer
   is easier to see beside the week it sits in. */
.reopen-grid {
	display: grid;
	gap: var(--s-3);
	grid-template-columns: 1fr;
	margin-bottom: var(--s-3);
}

@media (min-width: 62rem) {
	.reopen-grid {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
		align-items: start;
	}
}

/* A checkbox and its label, aligned on the first line rather than centred: these
   labels run to three lines and a centred box floats away from the word it marks. */
.reopen-pick {
	display: flex;
	align-items: flex-start;
	gap: var(--s-3);
	padding: var(--s-2) 0;
	cursor: pointer;
}

.reopen-pick > span {
	display: flex;
	flex-direction: column;
	gap: var(--s-1);
	min-width: 0;
}

.reopen-pick input[type="checkbox"] {
	margin-top: 0.2rem;
	flex: none;
}

.reopen-list {
	display: flex;
	flex-direction: column;
	gap: 0;
}

.reopen-item {
	border-bottom: 1px solid var(--c-border);
}

.reopen-item:last-child {
	border-bottom: none;
}

.reopen-item--open {
	background: var(--c-warning-subtle);
}

.reopen-item__head {
	display: flex;
	align-items: center;
	gap: var(--s-2);
	flex-wrap: wrap;
}

/* What the Monteur wrote. Quoted rather than plain, so it reads as their sentence
   and not as the app's. */
.reopen-item__note {
	font-size: var(--fs-sm);
	border-left: 2px solid var(--c-border-strong);
	padding-left: var(--s-2);
	color: var(--c-text);
}

.reopen-item__warn {
	font-size: var(--fs-sm);
	color: var(--c-warning);
}


/* --- Importing a briefing ------------------------------------------------ */

/* A row the import cannot use. Tinted rather than outlined: several in a row would
   otherwise draw a ladder of boxes down the table. */
.import-row--error {
	background: var(--c-danger-subtle);
}

/* One reason, under the badge that summarises the row. Block-level so several stack
   rather than running together into a paragraph, and wrapping rather than clipped —
   "Ändert: location_note, map_url, photos_url, frame_width_mm, frame_heigh…" is the
   half of the sentence that says nothing. */
.import-problem {
	display: block;
	margin-top: var(--s-1);
	font-size: var(--fs-sm);
	line-height: 1.35;
	white-space: normal;
	overflow-wrap: anywhere;
	color: var(--c-warning);
}

/* The outcome column carries the reasons, so it gets the room. The two free-text
   columns beside it give it up: a location and an Auftrag are both readable
   truncated, and a reason is not. */
.import-outcome {
	min-width: 16rem;
}

.import-problem--error {
	color: var(--c-danger);
}

.import-blocked {
	border-left: 4px solid var(--c-danger);
}

/* The preview's counters are a summary above a table, not the week dashboard's row
   of cards — smaller, and without the arrow that opens something. */
.counters--compact {
	grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
	margin-bottom: var(--s-4);
}

.counters--compact .counter {
	padding: var(--s-3);
}

.counters--compact .counter__value {
	font-size: var(--fs-lg);
}

/* Scoped to the compact set. On the week dashboard a counter's tone colours its left
   stripe and nothing else — an unscoped rule here turned Probleme red and Offen gold
   on a screen nobody had asked to change (26 Aug 2026). */
.counters--compact .counter--danger .counter__value {
	color: var(--c-danger);
}


/* A file drop target that is also the picker: a <label> around a hidden input, so it
   works with no JavaScript at all and reads in the app's language rather than the
   browser's. */
.dropzone {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--s-1);
	padding: var(--s-5) var(--s-4);
	border: 2px dashed var(--c-border-strong);
	border-radius: var(--radius);
	background: var(--c-surface-sunken);
	text-align: center;
	cursor: pointer;
}

.dropzone:hover,
.dropzone:focus-within {
	border-color: var(--c-primary);
	background: var(--c-primary-subtle);
}

/* While a file is over it. Deliberately the same treatment as hover — the target is
   the whole box either way, and a second colour would be one distinction too many. */
.dropzone--over {
	border-color: var(--c-primary);
	background: var(--c-primary-subtle);
}

.dropzone--filled {
	border-style: solid;
	border-color: var(--c-success);
	background: var(--c-success-subtle);
}

.dropzone__icon {
	font-size: 1.5rem;
	line-height: 1;
	color: var(--c-text-muted);
}

.dropzone__title {
	font-weight: 600;
}

.dropzone__hint {
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

.dropzone__chosen {
	margin-top: var(--s-2);
	font-family: var(--font-mono, inherit);
	font-size: var(--fs-sm);
	color: var(--c-success);
	overflow-wrap: anywhere;
}

/* Changing the week from the preview, on one line above the table. */
.week-bar {
	display: flex;
	align-items: center;
	gap: var(--s-2);
	flex-wrap: wrap;
	margin-bottom: var(--s-3);
}

.week-bar__label {
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

.week-bar select {
	width: auto;
	min-height: 0;
	height: 2.5rem;
	padding: var(--s-1) var(--s-2);
	font-size: var(--fs-sm);
}

/* A row the import will skip — already planned in this week. Not a fault, so it is
   tinted rather than flagged, and warmer than the error rows above it. */
.import-row--skip {
	background: var(--c-warning-subtle);
}

.counters--compact .counter--warning .counter__value {
	color: var(--c-warning);
}


/* A checkbox list on a card that has the page's whole width. Three columns is right
   beside a second panel and leaves half the row empty on its own. */
@media (min-width: 62rem) {
	.assign-people--wide > div {
		grid-template-columns: repeat(5, minmax(0, 1fr));
	}
}

/* The file and the week, side by side: one decision in two boxes. */
.upload-grid {
	display: grid;
	gap: var(--s-3);
	grid-template-columns: 1fr;
	margin-bottom: var(--s-3);
}

@media (min-width: 48rem) {
	.upload-grid {
		grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
		align-items: start;
	}
}


/* --- Export --------------------------------------------------------------- */

.export-tile {
	display: flex;
	flex-direction: column;
	gap: var(--s-2);
}

.export-tile .form-actions {
	margin-top: auto;
}

/* The "only these Monteure" list, folded away: the common case is everybody, and
   forty checkboxes above the download button would bury it. */
.export-people {
	margin: var(--s-3) 0;
}

.export-people summary {
	cursor: pointer;
	font-weight: 600;
	padding: var(--s-2) 0;
}

/* Wider than the field app's 28rem info panel: a date range side by side and three
   columns of names do not fit in a phone-sized box. Set on the <dialog> itself —
   widening the *body* instead pushes it out of a panel that stays 28rem, which is
   what put half this form off the left edge (26 Aug 2026). */
#work-time-export,
#position-download {
	width: min(38rem, calc(100vw - 2 * var(--s-4)));
}

/* --- Benachrichtigungen ------------------------------------------------- */

/* The three explanations above the table. Wider than the default card grid: each
   one is a paragraph, and three narrow columns of prose is three columns nobody
   finishes reading. */
.cards--notify {
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	margin-bottom: var(--s-4);
}

/* One block per mail on the edit form. `fieldset` is reset to nothing globally
   (01-reset), so the card styling has to be asked for rather than inherited. */
.notify-group {
	margin-bottom: var(--s-3);
}

/* The people-list cell. A link wrapping badges, so the whole cell is the target
   rather than each badge separately — and an empty one still has something to
   click, which is the row that most needs it. */
.notify-cell {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s-1);
	align-items: center;
	text-decoration: none;
	color: inherit;
	min-height: 1.5rem;
}
.notify-cell:hover .badge--quiet {
	border-color: var(--c-primary);
	color: var(--c-primary);
}

/* A badge that names a thing rather than warning about one. The status badges are
   solid colour because a problem should catch the eye; these are three neutral
   labels in a dense table and would only add noise. */
.badge--quiet {
	background: transparent;
	color: var(--c-text-muted);
	border: 1px solid var(--c-border);
	font-weight: 500;
	white-space: nowrap;
	/* Tighter than a status badge: this is a scan column with up to three of them in
	   a cell, and at the normal size two would not sit on one line. */
	font-size: 0.72rem;
	padding: 0.05rem 0.3rem;
	line-height: 1.5;
}

.d-block {
	display: block;
}

/* --- Benachrichtigungen: Standard je Rolle ------------------------------ */

/* The role default lives in the card that explains the mail, so the switch and the
   sentence somebody needs in order to answer it are in one box. */
.notify-default {
	display: flex;
	flex-direction: column;
	gap: var(--s-2);
}
.notify-default__controls {
	margin-top: auto;
	padding-top: var(--s-3);
	border-top: 1px solid var(--c-border);
	display: flex;
	flex-direction: column;
	gap: var(--s-2);
	align-items: flex-start;
}
.notify-default__when {
	display: flex;
	gap: var(--s-2);
	width: 100%;
}
.notify-default__when > .field {
	flex: 1;
	min-width: 0;
}

/* --- Bulk selection ----------------------------------------------------- */

.bulk-bar {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s-2);
	align-items: center;
	padding: var(--s-2) var(--s-3);
	margin-bottom: var(--s-2);
	border: 1px solid var(--c-border);
	background: var(--c-surface-muted, #f4f6fa);
}
.bulk-bar__count {
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
	margin-right: auto;
}
/* Selects are full-width by default (05-forms), which turned a one-line bar into
   three stacked rows. They hold short labels and can size to them. */
.bulk-bar select {
	width: auto;
	min-width: 9rem;
	max-width: 100%;
}
/* Armed only once something is ticked, so the bar does not shout at an idle screen. */
.bulk-bar--armed .bulk-bar__count {
	color: var(--c-primary);
	font-weight: 600;
}

.table__check {
	width: 2.5rem;
	text-align: center;
}
.table__check input {
	margin: 0;
}

/* A value that came from the role, not from this person. Muted rather than a second
   colour: the column is scanned for the exceptions, so the rule should recede. */
.state--inherited {
	color: var(--c-text-muted);
	font-weight: 400;
}

/* The three-way radio, laid out as a row rather than a stack — it is one question
   with three short answers, and three lines for it reads as three questions. */
.field--choice ul,
.field--choice > div {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s-3);
	list-style: none;
	margin: 0;
	padding: 0;
}
.field--choice label {
	display: inline-flex;
	align-items: center;
	gap: var(--s-1);
	font-weight: 500;
}

/* --- Hinweise (Slice 13) ------------------------------------------------ */

/* The nav entry, red only while something is open. A permanent badge is furniture,
   and furniture is not noticed. */
.site-nav__alert {
	color: var(--c-danger-text, #ffd7d3) !important;
	font-weight: 600;
}
.site-nav__badge {
	display: inline-block;
	min-width: 1.25rem;
	padding: 0 0.3rem;
	margin-left: 0.3rem;
	border-radius: 999px;
	background: var(--c-danger, #99231f);
	color: #fff;
	font-size: 0.72rem;
	font-weight: 700;
	line-height: 1.25rem;
	text-align: center;
	font-variant-numeric: tabular-nums;
}

.all-clear {
	padding: var(--s-5) var(--s-4);
	text-align: center;
	border: 1px solid var(--c-border);
	background: var(--c-surface, #fff);
}
.all-clear__title {
	font-size: 1.15rem;
	font-weight: 600;
	color: var(--c-status-done, #1b6e45);
	margin: 0 0 var(--s-1);
}

.alert-group {
	margin-bottom: var(--s-5);
}
.alert-group__title {
	display: flex;
	align-items: baseline;
	gap: var(--s-2);
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--c-text-muted);
	margin: 0 0 var(--s-2);
}
.alert-group__count {
	font-variant-numeric: tabular-nums;
	font-weight: 400;
}

.alert-list {
	list-style: none;
	margin: 0;
	padding: 0;
	border: 1px solid var(--c-border);
	background: var(--c-surface, #fff);
}

/* The row: what is wrong on the left, what to do on the right. The severity stripe
   is on the left edge so a column of them can be scanned without reading. */
.alert-row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s-2) var(--s-3);
	align-items: center;
	justify-content: space-between;
	padding: var(--s-3);
	border-bottom: 1px solid var(--c-border);
	border-left: 3px solid transparent;
}
.alert-row:last-child {
	border-bottom: 0;
}
.alert-row--danger {
	border-left-color: var(--c-danger, #99231f);
}
.alert-row--warning {
	border-left-color: var(--c-warning, #9a5e00);
}

.alert-row__what {
	flex: 1 1 22rem;
	min-width: 0;
}
.alert-row__title {
	margin: 0;
	font-weight: 600;
}
.alert-row__detail {
	margin: 0.15rem 0 0;
	color: var(--c-text-muted);
	font-size: var(--fs-sm);
}
/* What to do when there is no button — the office cannot close somebody else's week. */
.alert-row__hint {
	margin: 0.25rem 0 0;
	font-size: var(--fs-sm);
	font-style: italic;
	color: var(--c-text-muted);
}

.alert-row__do {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s-2);
	align-items: center;
}

.dismissed {
	margin-top: var(--s-5);
	padding-top: var(--s-3);
	border-top: 1px solid var(--c-border);
}
.dismissed > summary {
	cursor: pointer;
	font-weight: 600;
	color: var(--c-text-muted);
}
.alert-list--quiet {
	margin-top: var(--s-2);
	opacity: 0.75;
}
