/* The Monteur PWA. Phone-first: this file assumes a 360–430px screen held at arm's
   length, outdoors, possibly through gloves. */

/* --- Account menu -------------------------------------------------------- */

.account {
	position: relative;
}

.account__button {
	display: flex;
	align-items: center;
	gap: var(--s-2);
	min-height: var(--tap-min);
	padding: var(--s-1) var(--s-2) var(--s-1) var(--s-1);
	border-radius: 999px;
	background: rgb(255 255 255 / 0.14);
	color: var(--c-text-inverse);
	cursor: pointer;
	list-style: none;
}

/* Safari draws its own triangle on <summary> unless told otherwise. */
.account__button::-webkit-details-marker {
	display: none;
}

.account__avatar {
	display: grid;
	place-items: center;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	background: var(--c-surface);
	color: var(--c-primary);
	font-size: var(--fs-sm);
	font-weight: 700;
}

.account__name {
	font-size: var(--fs-sm);
	font-weight: 600;
}

.account__chevron {
	font-size: 0.75rem;
	opacity: 0.8;
}

.account__menu {
	position: absolute;
	right: 0;
	top: calc(100% + var(--s-2));
	z-index: 50;
	min-width: 12rem;
	padding: var(--s-1);
	background: var(--c-surface);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lg);
}

/* Scoped to .account__menu on purpose: `.site-header a` paints links white for the
   dark header bar, and on this white dropdown that made "Passwort ändern" invisible.
   Two classes beat one class plus one element, so this wins. */
.account__menu .account__item {
	display: flex;
	align-items: center;
	width: 100%;
	min-height: var(--tap-min);
	padding: 0 var(--s-3);
	border-radius: var(--radius);
	color: var(--c-text);
	font-size: var(--fs-base);
	text-align: left;
	text-decoration: none;
	cursor: pointer;
}

.account__menu .account__item:hover {
	background: var(--c-surface-sunken);
	color: var(--c-text);
	text-decoration: none;
}

.account__menu .account__item--danger {
	color: var(--c-danger);
}

/* --- Day header ---------------------------------------------------------- */

.day-head {
	margin-bottom: var(--s-4);
}

.day-head__nav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--s-2);
}

.day-head__title {
	text-align: center;
	flex: 1;
	min-width: 0;
}

.day-head__title h1 {
	font-size: var(--fs-2xl);
	text-transform: capitalize;
}

.day-head__meta {
	color: var(--c-text-muted);
	font-size: var(--fs-sm);
	font-variant-numeric: tabular-nums;
}

.day-nav {
	display: grid;
	place-items: center;
	flex: none;
	width: var(--tap-min);
	height: var(--tap-min);
	border: 1px solid var(--c-border-strong);
	border-radius: var(--radius);
	background: var(--c-surface);
	color: var(--c-primary);
	font-size: var(--fs-xl);
	line-height: 1;
	text-decoration: none;
}

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

/* Inline on the meta line, so it occupies no row of its own. */
.day-head__today {
	font-weight: 600;
	white-space: nowrap;
}

/* --- Hours panel --------------------------------------------------------- */

.hours {
	padding: var(--s-3);
	margin-bottom: var(--s-5);
	background: var(--c-surface-sunken);
	border-radius: var(--radius-lg);
}

.hours__fields {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--s-2);
}

.hours__field {
	display: flex;
	flex-direction: column;
	gap: var(--s-1);
	padding: var(--s-2);
	background: var(--c-surface);
	border: 2px solid var(--c-border);
	border-radius: var(--radius);
	text-align: center;
}

/* Green means stored. It is a state rather than a flash, and it survives closing the
   app: a Monteur who entered a start at 07:30 can open the day at midday and see at a
   glance that the start is safe and the other two are still to come. Changing a value
   returns the cell to white until the save comes back. */
.hours__field--saved {
	border-color: var(--c-success);
	background: var(--c-success-subtle);
}

.hours__value {
	width: 100%;
	min-height: 2.25rem;
	background: transparent;
	font-size: var(--fs-lg);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	text-align: center;
	cursor: pointer;
}

.hours__field--saved .hours__value {
	color: var(--c-success);
}

/* A submitted day. The cells stay green and fully legible — the Monteur still needs
   to read back what they sent — but they are no longer controls. Browsers grey a
   disabled button out by default, which here would read as "not entered" and mean
   the opposite of the truth. */
.hours__value:disabled {
	cursor: default;
	opacity: 1;
	color: inherit;
	-webkit-text-fill-color: currentColor;
}

.hours__field--saved .hours__value:disabled {
	color: var(--c-success);
	-webkit-text-fill-color: var(--c-success);
}

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

/* Always present, fixed height. The total used to appear only once there were hours
   to show, which pushed the position list down the moment a day was completed. */
.hours__footer {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: var(--s-2);
	min-height: 1.75rem;
	margin-top: var(--s-3);
}

.hours__footer-label {
	margin-right: auto;
	font-size: var(--fs-sm);
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--c-text-muted);
}

.hours__total {
	font-weight: 700;
}

.hours__total--pending {
	color: var(--c-text-muted);
	font-weight: 600;
}

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

.positions__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--s-3);
	margin-bottom: var(--s-3);
}

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

.positions__count {
	font-size: var(--fs-sm);
	font-weight: 600;
	padding: var(--s-1) var(--s-3);
	border-radius: 999px;
	background: var(--c-surface-sunken);
	color: var(--c-text-muted);
}

.position {
	position: relative;
	padding: var(--s-3) var(--s-4);
	margin-bottom: var(--s-3);
	background: var(--c-surface);
	border: 1px solid var(--c-border);
	/* The status stripe down the left edge, as in the mockup. */
	border-left: 4px solid var(--c-status-planned);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow);
}

.position--open {
	border-left-color: var(--c-status-open);
}
.position--done {
	border-left-color: var(--c-status-done);
}
.position--postponed {
	border-left-color: var(--c-status-moved);
}
.position--problem {
	border-left-color: var(--c-status-problem);
}
.position--cancelled {
	border-left-color: var(--c-status-cancelled);
}

.position__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--s-3);
}

.position__id {
	font-weight: 700;
	letter-spacing: 0.03em;
}

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

/* The card's children are spans inside a <button>, so they need telling to stack —
   a <button> lays its contents out inline however they are marked up. */
.position__head {
	width: 100%;
}

.position__note {
	display: block;
}

.position__note {
	margin-top: var(--s-2);
	padding-top: var(--s-2);
	border-top: 1px dashed var(--c-border);
	font-size: var(--fs-sm);
}

/* The category, or the date it moved to: the fact, ahead of the sentence explaining
   it. Bold rather than a badge — the card already carries one, and a second would
   compete with the status for the same glance. */
.position__note-label {
	font-weight: 600;
}

.position__note--problem .position__note-label {
	color: var(--c-danger);
}

.badge--done {
	background: var(--c-status-done);
}
.badge--postponed {
	background: var(--c-status-moved);
}
.badge--problem {
	background: var(--c-status-problem);
}
.badge--cancelled {
	background: var(--c-status-cancelled);
}
.badge--open {
	background: var(--c-status-open);
}
.badge--planned {
	background: var(--c-status-planned);
}

/* --- Bottom-sheet wheel picker ------------------------------------------- */

/* A <dialog>, so the browser owns the modal semantics, focus trap and Escape.
   Pinned to the bottom because that is where an iOS action sheet lives — Safari's own
   <input type="time"> puts a box in the middle of the screen instead, which reads as
   a web page rather than an app. */
.sheet {
	position: fixed;
	inset: auto 0 0 0;
	width: 100%;
	max-width: 32rem;
	margin: 0 auto;
	padding: 0;
	border: none;
	border-radius: var(--radius-lg) var(--radius-lg) 0 0;
	background: var(--c-surface);
	box-shadow: 0 -8px 32px rgb(20 24 28 / 0.25);
}

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

.sheet[open] {
	animation: sheet-up 0.22s ease-out;
}

@keyframes sheet-up {
	from {
		transform: translateY(100%);
	}
}

/* Buttons above the wheels: cancel left, confirm right.
   A three-column grid with equal outer tracks, not space-between: "Abbrechen" is far
   wider than "OK", so space-between pushed the title off centre. */
.sheet__bar {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: var(--s-2);
	padding: var(--s-2);
	border-bottom: 1px solid var(--c-border);
}

.sheet__title {
	font-weight: 700;
	font-size: var(--fs-sm);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--c-text-muted);
	text-align: center;
}

.sheet__action {
	justify-self: start;
	min-height: var(--tap-min);
	padding: 0 var(--s-3);
	border-radius: var(--radius);
	background: none;
	color: var(--c-text-muted);
	font-size: var(--fs-base);
	cursor: pointer;
}

.sheet__action--primary {
	justify-self: end;
}

.sheet__action--primary {
	color: var(--c-primary);
	font-weight: 700;
}

/* The panel takes focus when the sheet opens (see the template) and must not draw a
   ring for it — it is a container, not something anybody chose. Every control inside
   still shows one. */
.sheet__inner:focus,
.sheet__inner:focus-visible {
	outline: none;
}

.sheet__wheels {
	position: relative;
	display: flex;
	justify-content: center;
	gap: var(--s-4);
	/* Room for the home-bar on a modern iPhone. */
	padding: var(--s-3) var(--s-4) calc(var(--s-4) + env(safe-area-inset-bottom));
}

/* The selection is a fixed band behind the numbers, not a style on the chosen row.
   Styling the row meant its size changed as the wheel scrolled, which reflowed the
   column mid-gesture and made the whole thing feel like it was fighting the thumb.
   Every row is now identical and nothing moves but the scroll. */
.sheet__band {
	position: absolute;
	left: var(--s-3);
	right: var(--s-3);
	top: 50%;
	height: 2.5rem;
	transform: translateY(-50%);
	border-radius: var(--radius);
	background: var(--c-surface-sunken);
	pointer-events: none;
	z-index: 0;
}

.sheet__wheels .wheel {
	position: relative;
	z-index: 1;
}

/* The wheel. Scroll-snap does the physics: momentum, deceleration and snapping are
   the browser's, and we only read back which option ended up centred. */
.wheel {
	position: relative;
	min-width: 3.5rem;
	height: 11rem;
	overflow-y: auto;
	scroll-snap-type: y mandatory;
	scrollbar-width: none;
	text-align: center;
	/* Fade the ends so the centre reads as the selection, without an overlay that
	   would swallow taps. */
	mask-image: linear-gradient(
		to bottom,
		transparent,
		#000 25%,
		#000 75%,
		transparent
	);
}

.wheel::-webkit-scrollbar {
	display: none;
}

.wheel:focus-visible {
	outline: 3px solid var(--c-focus);
	outline-offset: 2px;
	border-radius: var(--radius);
}

/* Half the wheel's height above and below, so the first and last options can reach
   the middle. */
.wheel__list {
	padding-block: 4.25rem;
}

/* Every row identical — same size, same weight. The mask fades the ends and the band
   marks the middle, so nothing needs to change as the wheel moves. */
.wheel__option {
	display: block;
	width: 100%;
	height: 2.5rem;
	scroll-snap-align: center;
	background: none;
	color: var(--c-text);
	font-size: var(--fs-xl);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	cursor: pointer;
}

/* Sits beside the column, level with the selection band. */
.sheet__suffix {
	position: relative;
	z-index: 1;
	align-self: center;
	font-size: var(--fs-base);
	color: var(--c-text-muted);
	pointer-events: none;
}

/* --- What the board is --------------------------------------------------- */

/* The "i" beside the Alpdest-ID. Deliberately quiet: it is a way in to reference
   material, not an action, and the actions on this page are the status buttons. */
.sheet-head__info {
	display: inline-grid;
	place-items: center;
	width: 1.75rem;
	height: 1.75rem;
	margin-left: var(--s-2);
	vertical-align: middle;
	border: 1px solid var(--c-border-strong);
	border-radius: 50%;
	background: var(--c-surface);
	color: var(--c-text-muted);
	font-family: var(--font-body);
	font-size: var(--fs-sm);
	font-weight: 700;
	font-style: italic;
	line-height: 1;
	cursor: pointer;
}

.sheet-head__info:hover {
	background: var(--c-surface-sunken);
	color: var(--c-text);
}

/* A panel, not a page. It holds four measurements and two links, so it is sized by
   its contents and sits in the middle of the screen rather than filling it. */
.info-dialog {
	width: min(28rem, calc(100vw - 2 * var(--s-4)));
	padding: 0;
	border: none;
	border-radius: var(--radius-lg);
	background: var(--c-surface);
	color: var(--c-text);
}

.info-dialog::backdrop {
	background: rgb(0 0 0 / 0.45);
}

.info-dialog__body {
	padding: var(--s-4);
}

.info-dialog__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--s-3);
}

.info-dialog__head h2 {
	font-size: var(--fs-xl);
	letter-spacing: 0.03em;
}

.info-dialog__close {
	display: grid;
	place-items: center;
	flex: none;
	width: var(--tap-min);
	height: var(--tap-min);
	margin: calc(var(--s-2) * -1) calc(var(--s-2) * -1) 0 0;
	border-radius: var(--radius);
	background: none;
	color: var(--c-text-muted);
	font-size: var(--fs-2xl);
	line-height: 1;
	cursor: pointer;
}

.info-dialog__where {
	margin: var(--s-1) 0 var(--s-4);
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}


/* Full-height tap targets: these are the two things a Monteur reaches for with one
   hand while holding something in the other. */
.surface__links {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	gap: var(--s-2);
	margin-bottom: var(--s-3);
}

.surface__link {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--s-2);
	min-height: var(--tap-min);
	padding: 0 var(--s-3);
	background: var(--c-surface);
	border: 1px solid var(--c-border-strong);
	border-radius: var(--radius);
	font-weight: 600;
	text-decoration: none;
}

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

/* Label above value, two or three across. A definition list because that is what it
   is, and because a screen reader then reads "Gerüst, 400 × 300 cm" rather than four
   numbers in a row. */
.surface__facts {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s-3) var(--s-5);
	margin: 0;
}

.surface__facts dt {
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--c-text-muted);
}

.surface__facts dd {
	margin: 0;
	font-weight: 600;
}

.surface__status {
	margin: var(--s-3) 0 0;
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

/* --- Report sheet -------------------------------------------------------- */

.sheet-head {
	display: flex;
	flex-direction: column;
	gap: var(--s-2);
	margin-bottom: var(--s-4);
}

.sheet-head__back {
	font-size: var(--fs-sm);
	font-weight: 600;
	text-decoration: none;
}

.sheet-head h1 {
	font-size: var(--fs-xl);
	letter-spacing: 0.03em;
	font-variant-numeric: tabular-nums;
	/* The date wraps under the ID on a narrow phone rather than shrinking it — the
	   ID is the thing being checked against a surface in the snow. */
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--s-2);
}

/* Inside the h1, so screen readers still announce one heading, but weighted as the
   supporting detail it is. */
.sheet-head__day {
	font-size: var(--fs-sm);
	font-weight: 400;
	letter-spacing: normal;
	color: var(--c-text-muted);
}

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

.report {
	margin-bottom: var(--s-5);
}

.report__locked {
	padding: var(--s-3);
	margin-bottom: var(--s-4);
	background: var(--c-warning-subtle);
	border: 1px solid var(--c-warning);
	border-radius: var(--radius);
	font-size: var(--fs-sm);
}

/* Information, not a warning: somebody else filled this in, which is the normal way
   a two-person job gets reported. Quieter than the lock banner above deliberately. */
.report__filed-by {
	padding: var(--s-3);
	margin-bottom: var(--s-4);
	background: var(--c-surface-sunken);
	border-left: 3px solid var(--c-border);
	border-radius: var(--radius);
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

.report fieldset {
	border: none;
	padding: 0;
	margin: 0 0 var(--s-4);
}

/* Status: the mockup's 2x2 grid of large targets. */
.report__statuses {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--s-2);
}

.report__statuses legend {
	margin-bottom: var(--s-2);
}

.status-choice {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 3.5rem;
	padding: var(--s-2);
	background: var(--c-surface);
	border: 2px solid var(--c-border);
	border-radius: var(--radius-lg);
	font-weight: 600;
	text-align: center;
	cursor: pointer;
}

/* The radio itself is invisible but still focusable and still the thing screen
   readers announce — the label is only paint. */
.status-choice input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
}

.status-choice:has(input:focus-visible) {
	outline: 3px solid var(--c-focus);
	outline-offset: 2px;
}

.status-choice:has(input:checked) {
	border-color: var(--c-primary);
	background: var(--c-primary-subtle);
}

.status-choice--done:has(input:checked) {
	border-color: var(--c-status-done);
	background: var(--c-success-subtle);
}
.status-choice--problem:has(input:checked) {
	border-color: var(--c-status-problem);
	background: var(--c-danger-subtle);
}
.status-choice--postponed:has(input:checked) {
	border-color: var(--c-status-moved);
	background: var(--c-warning-subtle);
}

/* Team chips. */
.chips {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s-2);
}

.chip {
	display: inline-flex;
	align-items: center;
	min-height: var(--tap-min);
	padding: 0 var(--s-4);
	border: 1px solid var(--c-border-strong);
	border-radius: 999px;
	background: var(--c-surface);
	font-size: var(--fs-sm);
	font-weight: 600;
	cursor: pointer;
}

.chip input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
}

.chip:has(input:checked) {
	background: var(--c-primary);
	border-color: var(--c-primary);
	color: var(--c-text-inverse);
}

.chip:has(input:focus-visible) {
	outline: 3px solid var(--c-focus);
	outline-offset: 2px;
}

/* Conditional fields, shown by the chosen status alone — no JavaScript, and no
   request. Which status needs what is decided server-side by
   positions.services.report_requirements; this only mirrors it. */
.report__conditional {
	display: none;
}

.report:has(input[name="status"][value="PROBLEM"]:checked) .report__conditional--problem,
.report:has(input[name="status"][value="POSTPONED"]:checked) .report__conditional--postponed,
.report:has(input[name="status"][value="PROBLEM"]:checked) .report__conditional--explained,
.report:has(input[name="status"][value="POSTPONED"]:checked) .report__conditional--explained {
	display: block;
}

/* A field with a server-side error is always shown, whatever the status says —
   otherwise the message would be invisible and the form would look simply broken. */
.report__conditional:has(.field--error) {
	display: block;
}

.report__saved {
	margin-top: var(--s-2);
	font-size: var(--fs-sm);
	color: var(--c-success);
}

/* --- Photos -------------------------------------------------------------- */

/* Only for "Erledigt": a photo is the evidence a surface went up, and there is
   nothing to photograph for a problem or a postponement. Reaches across from the
   radio in the report form because both live inside .sheet-page. */
.photos {
	display: none;
	margin-bottom: var(--s-6);
}

.sheet-page:has(input[name="status"][value="DONE"]:checked) .photos,
.sheet-page:has(input[name="status"][value="PROBLEM"]:checked) .photos {
	display: block;
}

.photos__actions {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--s-2);
	margin-top: var(--s-3);
}

/* Each button is wrapped in its own form (one upload per request), and a form is a
   block that shrinks to its label. Stretching both means the two boxes stay the same
   height even if one label wraps and the other does not. */
.photos__actions form {
	display: grid;
}

/* Hidden by default; the chosen status reveals exactly one. */
.photos__note {
	display: none;
	margin-left: var(--s-2);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
}

.sheet-page:has(input[name="status"][value="DONE"]:checked) .photos__note--required {
	display: inline;
	color: var(--c-danger);
}

.sheet-page:has(input[name="status"][value="PROBLEM"]:checked) .photos__note--optional {
	display: inline;
	color: var(--c-text-muted);
}

.photos__list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
	gap: var(--s-2);
	margin: var(--s-3) 0;
}

.photos__item {
	position: relative;
	aspect-ratio: 4 / 3;
	overflow: hidden;
	border-radius: var(--radius);
	background: var(--c-surface-sunken);
}

.photos__item img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.photos__remove {
	position: absolute;
	top: var(--s-1);
	right: var(--s-1);
	display: grid;
	place-items: center;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	background: rgb(20 24 28 / 0.65);
	color: var(--c-text-inverse);
	font-size: var(--fs-lg);
	line-height: 1;
	cursor: pointer;
}

.photos__add--library {
	border-style: solid;
	border-color: var(--c-border);
}

.photos__add {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--s-2);
	min-height: var(--tap-min);
	padding: var(--s-3);
	border: 2px dashed var(--c-border-strong);
	border-radius: var(--radius-lg);
	color: var(--c-primary);
	font-weight: 600;
	cursor: pointer;
}

/* --- Submit the day ------------------------------------------------------ */

.day-submit {
	margin: var(--s-6) 0 var(--s-4);
}

.day-submit .btn {
	background: var(--c-focus);
	font-size: var(--fs-lg);
	min-height: 3.5rem;
}

.day-submit .btn:hover {
	background: #8f3f08;
}

.day-submit__hint {
	margin-top: var(--s-2);
	text-align: center;
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

.day-submitted {
	margin: var(--s-6) 0 var(--s-4);
	padding: var(--s-3) var(--s-4);
	background: var(--c-success-subtle);
	border: 1px solid var(--c-success);
	border-radius: var(--radius-lg);
	text-align: center;
	font-weight: 600;
}

/* The card is a link, so it needs the link colours undone. */
a.position {
	display: block;
	color: inherit;
	text-decoration: none;
}

a.position:hover {
	color: inherit;
	border-color: var(--c-border-strong);
	box-shadow: var(--shadow-lg);
}


/* --- Saving a report ----------------------------------------------------- */

/* Below the photos, because that is the last thing a Monteur does. Disabled until
   the form is genuinely complete — see app.js, which reads the same rule the server
   enforces rather than restating it. */
/* Not sticky any more. Pinning it to the bottom of the viewport made it a composited
   layer, and iOS painted stale copies of that layer whenever the hint underneath
   changed — the reason the message came out clipped. It sits at the end of the sheet,
   after the photos, which is where a Monteur is looking when they have finished
   filling it in and is what the button was asked to do in the first place. */
.sheet-save {
	padding: var(--s-3) 0 var(--s-4);
	border-top: 1px solid var(--c-border);
}

/* Two lines' worth, always, whatever the message is. The longest of them wrap to two
   lines on a narrow phone and the shortest need one, so without this the bar changed
   height as the Monteur filled the form in — the page jumping under their thumb, and
   a sticky element resizing itself, which is what iOS mispainted. */
.sheet-save__hint {
	margin-top: var(--s-2);
	text-align: center;
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
	min-height: 2.75rem;
}

/* --- Submitting the day -------------------------------------------------- */


/* --- Week view (M6) ------------------------------------------------------ */

/* Seven rows, one per day, always present. Four columns on one line: the day, how
   many positions are done, the hours, and a state marker. It has to survive a 320px
   phone, so the columns are fixed where they can be and the day name is abbreviated
   by Django's `D` format rather than by CSS truncation. */
.week {
	display: grid;
	gap: var(--s-2);
	margin-bottom: var(--s-5);
}

.week-day {
	display: grid;
	grid-template-columns: minmax(4.5rem, auto) 1fr auto 2rem;
	align-items: center;
	gap: var(--s-2);
	min-height: var(--tap-min);
	padding: var(--s-3);
	background: var(--c-surface);
	border: 1px solid var(--c-border);
	border-left: 4px solid var(--c-border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow);
	color: inherit;
	text-decoration: none;
}

.week-day:hover {
	color: inherit;
	border-color: var(--c-border-strong);
	box-shadow: var(--shadow-lg);
}

/* Today keeps its stripe, so the eye lands on the right row without reading dates. */
.week-day--today {
	border-left-color: var(--c-primary);
	background: var(--c-primary-subtle);
}

/* A day with nothing planned and nothing entered recedes rather than disappears —
   still tappable, because that is how a Monteur adds hours to a day off. */
.week-day--empty {
	box-shadow: none;
	background: transparent;
}

.week-day__name {
	display: flex;
	flex-direction: column;
	font-weight: 700;
	line-height: var(--lh-tight);
}

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

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

.week-day__hours {
	font-weight: 600;
}

/* Always rendered, empty or not, so the hours column stays in one line down the
   seven rows instead of jumping left whenever a day has no marker. */
.week-day__state {
	display: grid;
	place-items: center;
	min-width: 2rem;
}

.week-day__state .badge {
	padding: 0 var(--s-2);
	min-width: 1.75rem;
	text-align: center;
}

.week-total {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: baseline;
	gap: var(--s-2);
	padding: var(--s-3) var(--s-4);
	margin-bottom: var(--s-5);
	background: var(--c-surface-sunken);
	border-radius: var(--radius-lg);
}

.week-total__label {
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--c-text-muted);
}

.week-total__value {
	font-size: var(--fs-lg);
	font-weight: 700;
}

.week-total__meta {
	grid-column: 1 / -1;
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

/* --- Create a position on site (M7) -------------------------------------- */

/* Dashed, quiet, and below the list: it is the exception, not the task. Same shape
   as the photo buttons, which are the other "add something" control in the app. */
.create-position {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--s-2);
	min-height: var(--tap-min);
	padding: var(--s-3);
	margin-bottom: var(--s-5);
	border: 2px dashed var(--c-border-strong);
	border-radius: var(--radius-lg);
	color: var(--c-primary);
	font-weight: 600;
	text-decoration: none;
}

.create-position:hover {
	border-color: var(--c-primary);
	background: var(--c-primary-subtle);
}

.form-note {
	margin-bottom: var(--s-4);
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
}

.day-head__week {
	color: inherit;
}

/* --- The week of positions ------------------------------------------------ */
/* Added 14 Aug 2026 when the day view became a week view. */

.week-head {
	margin-bottom: var(--s-4);
}

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

.week-head__title {
	flex: 1;
	text-align: center;
}

.week-head__title h1 {
	font-size: var(--fs-xl);
	line-height: 1.1;
}

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

/* The one link out of this screen, and it has to be findable with a glance and a
   thumb — underlined rather than styled as a button so it does not compete with
   "Woche abschliessen" below. */
.week-head__hours {
	margin-left: var(--s-2);
	font-weight: 600;
}

.week-status {
	padding: var(--s-3);
	margin-bottom: var(--s-4);
	background: var(--c-surface-sunken);
	border-radius: var(--radius);
}

.week-status__counts {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--s-2);
	margin-bottom: var(--s-3);
	list-style: none;
	padding: 0;
	text-align: center;
}

/* The counters are buttons now, so they have to stop looking like the browser's.
   The tap target spans the whole tile and nothing else says "button" — they are
   still meant to read as four numbers, and only turn out to be pressable. */
.week-count {
	display: block;
	width: 100%;
	padding: var(--s-2) var(--s-1);
	border: 1px solid transparent;
	border-radius: var(--radius);
	background: none;
	font: inherit;
	text-align: center;
	cursor: pointer;
}

.week-count:hover {
	background: var(--c-surface);
}

.week-count__value {
	display: block;
	font-size: var(--fs-lg);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.week-count__label {
	display: block;
	font-size: 0.6875rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--c-text-muted);
}

/* The counter colours are the badge colours, so a number and the cards it counts
   read as the same thing. */
.week-count--problem .week-count__value { color: var(--c-status-problem); }
.week-count--done .week-count__value { color: var(--c-status-done); }

.week-status__hint {
	margin-top: var(--s-2);
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
	text-align: center;
}

.week-closed {
	padding: var(--s-3);
	background: var(--c-success-subtle);
	border: 1px solid var(--c-success);
	border-radius: var(--radius);
	font-size: var(--fs-sm);
}

.week-group {
	margin-bottom: var(--s-3);
}

.week-group__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--s-2);
	padding: var(--s-2) var(--s-3);
	background: var(--c-surface);
	border-radius: var(--radius);
	font-weight: 600;
	cursor: pointer;
	/* The whole row is the target. A summary marker sized for a mouse is not sized
	   for a glove. */
	min-height: 2.75rem;
}

.week-group__count {
	font-variant-numeric: tabular-nums;
	color: var(--c-text-muted);
}

.week-group__empty {
	padding: var(--s-3);
	font-size: var(--fs-sm);
}

/* A card is a button now, not a link: it opens the sheet in place rather than
   navigating. Everything else about it is unchanged, so the reset here is only
   undoing what the browser does to <button>. */
button.position {
	display: block;
	width: 100%;
	text-align: left;
	font: inherit;
	color: inherit;
	background: var(--c-surface);
	cursor: pointer;
}

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

.position__work {
	display: block;
	margin-top: var(--s-1);
	font-weight: 600;
}

/* --- The sheet dialog ----------------------------------------------------- */

.sheet-dialog {
	width: min(100%, 34rem);
	max-height: 92vh;
	margin: auto auto 0;
	padding: var(--s-4);
	border: none;
	border-radius: var(--radius) var(--radius) 0 0;
	background: var(--c-bg);
	overflow-y: auto;
}

/* The dialog takes focus when it opens (see app.js) so no control inside arrives
   ringed. It is a container, not something anybody chose. */
.sheet-dialog:focus,
.sheet-dialog:focus-visible {
	outline: none;
}

.sheet-dialog::backdrop {
	background: rgb(0 0 0 / 0.45);
}

.sheet-head__close {
	position: absolute;
	top: var(--s-3);
	right: var(--s-3);
	width: 2.5rem;
	height: 2.5rem;
	font-size: var(--fs-lg);
	line-height: 1;
	background: transparent;
	color: var(--c-text-muted);
	cursor: pointer;
}

.sheet-head__work {
	margin-top: var(--s-1);
	font-weight: 600;
}

/* --- Closing the week ----------------------------------------------------- */

.confirm__days {
	list-style: none;
	padding: 0;
	margin: var(--s-3) 0;
}

.confirm__day {
	display: grid;
	grid-template-columns: 4.5rem 1fr auto;
	gap: var(--s-2);
	align-items: baseline;
	padding: var(--s-2) 0;
	border-bottom: 1px solid var(--c-border);
	font-size: var(--fs-sm);
}

.confirm__day--empty {
	color: var(--c-text-muted);
}

.confirm__total {
	display: flex;
	justify-content: space-between;
	padding: var(--s-2) 0;
	font-size: var(--fs-lg);
}

.confirm__blockers {
	padding: var(--s-3);
	margin-bottom: var(--s-3);
	background: var(--c-warning-subtle);
	border: 1px solid var(--c-warning);
	border-radius: var(--radius);
	font-size: var(--fs-sm);
}

.confirm__actions {
	display: grid;
	gap: var(--s-2);
}

/* --- Zeiterfassung -------------------------------------------------------- */

.hours-row {
	display: grid;
	grid-template-columns: 3.5rem 1fr 3.5rem;
	gap: var(--s-2);
	align-items: center;
	padding: var(--s-2);
	margin-bottom: var(--s-2);
	background: var(--c-surface);
	border-radius: var(--radius);
}

.hours-row--today {
	outline: 2px solid var(--c-primary);
}

.hours-row__weekday {
	display: block;
	font-weight: 700;
}

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

.hours-row__fields {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--s-1);
}

.hours-row__total {
	text-align: right;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.hours-week__total {
	display: flex;
	justify-content: space-between;
	padding: var(--s-3);
	background: var(--c-surface-sunken);
	border-radius: var(--radius);
	font-size: var(--fs-lg);
}

/* Seven of these stack on a 375px screen, so the cells are tighter than the day
   view's were: "– min" wrapping onto a second line made every row 40px taller and
   pushed Sunday off the bottom. */
.hours-row .hours__field {
	padding: var(--s-1);
}

.hours-row .hours__value {
	min-height: 1.75rem;
	font-size: var(--fs-base);
	white-space: nowrap;
}

.hours-row .hours__label {
	font-size: 0.625rem;
}

/* --- Week screens, second pass (14 Aug 2026) ------------------------------ */

/* The arrows match the height of the three lines beside them and are square, so the
   header reads as one block rather than two small buttons floating beside a title. */
/* As tall as the title and the date range together — not the link below them, which
   made the arrows enormous and the header look like three buttons. Square, with an
   explicit size: `aspect-ratio` with `width: auto` on a flex item resolves the width
   from the content, which had them eleven pixels wide. */
.week-head__nav .day-nav {
	flex: none;
	width: 3rem;
	height: 3rem;
}

/* Aligned with the top two lines rather than centred against the whole block, so the
   arrows sit beside the week number and not beside the link. */
.week-head__nav {
	align-items: flex-start;
}

.week-head__hours {
	display: inline-block;
	font-weight: 600;
	font-size: var(--fs-sm);
}

/* Each group is one block: a coloured header with its positions inside a matching
   border, so a red section is visibly a red section rather than a red word above
   some white cards. */
.week-group {
	border: 1px solid var(--c-border);
	border-radius: var(--radius-lg);
	overflow: hidden;
}

.week-group__head {
	background: var(--c-surface-sunken);
	border-radius: 0;
}

.week-group__body {
	padding: var(--s-3) var(--s-3) var(--s-1);
}

/* Our own disclosure marker, rotating on open. The browser's default is a few pixels
   wide and sits at the very edge, which is not a target for a gloved thumb. */
.week-group__head::-webkit-details-marker,
.week-group__head::marker {
	display: none;
	content: "";
}

.week-group__marker {
	display: inline-block;
	margin-right: var(--s-2);
	transition: transform 120ms ease;
	color: var(--c-text-muted);
}

.week-group[open] .week-group__marker {
	transform: rotate(90deg);
}

.week-group__label {
	margin-right: auto;
}

/* Status colour on the header and the border, from the same tokens the badges and
   the card stripes use — one status, one colour, wherever it appears. */
.week-group--planned { border-color: var(--c-status-planned); }
.week-group--planned .week-group__head { background: var(--c-surface-sunken); }

.week-group--open { border-color: var(--c-status-open); }
.week-group--open .week-group__head {
	background: var(--c-status-open);
	color: var(--c-text-inverse);
}

.week-group--problem { border-color: var(--c-status-problem); }
.week-group--problem .week-group__head {
	background: var(--c-status-problem);
	color: var(--c-text-inverse);
}

.week-group--done { border-color: var(--c-status-done); }
.week-group--done .week-group__head {
	background: var(--c-status-done);
	color: var(--c-text-inverse);
}

/* The count and the marker inherit the header's colour rather than staying grey on
   a coloured bar, where they would be close to unreadable. */
.week-group__head .week-group__count,
.week-group__head .week-group__marker {
	color: inherit;
	opacity: 0.85;
}

/* A wider stripe. It is the fastest thing to read on the card and was competing with
   the card's own border for four pixels. */
.position {
	border-left-width: 8px;
}

/* --- The sheet, second pass ----------------------------------------------- */

/* The dialog now holds only the close-week confirmation, which is short and sizes
   itself. The fixed-height geometry the report sheet needed went with it when the
   sheet became a page again. */

/* Three across rather than two-plus-one. Losing "Verschoben" made the fourth cell
   empty and the grid ragged, and one row instead of two is a whole status button's
   worth of height back. */
.report__statuses {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--s-2);
}

.status-choice {
	font-size: var(--fs-base);
}

/* --- Zeiterfassung, second pass ------------------------------------------- */

/* "10:00 h" broke after the number, which put the unit on its own line and made the
   row taller than the six around it. */
.hours-row__total,
.hours-week__total strong {
	white-space: nowrap;
}

/* Enough height back for the week total to clear the bottom of a 6.1" phone: the
   rows lose a little padding each, which is seven times over. */
.hours-row {
	margin-bottom: var(--s-1);
	padding: var(--s-1) var(--s-2);
}

.hours-week__total {
	padding: var(--s-2) var(--s-3);
	margin-bottom: var(--s-3);
}


/* --- Closing the week, at the bottom -------------------------------------- */

/* Its own block after "Neue Position", separated so it does not read as part of the
   last status group. */
.week-close {
	padding: var(--s-3);
	margin-top: var(--s-4);
	background: var(--c-surface-sunken);
	border-radius: var(--radius);
}

/* An empty group is one line of text, not a panel. It was inheriting the body's
   padding on top of its own and stood as tall as a position card. */
.week-group__empty {
	padding: 0;
	margin: 0;
	font-size: var(--fs-sm);
}

.week-group__body:has(.week-group__empty) {
	padding: var(--s-2) var(--s-3);
}

/* Beside the date range, not under it — the header already has three lines. */
.week-head__today {
	margin-left: var(--s-2);
	font-weight: 600;
	white-space: nowrap;
}

/* The padlock beside an Alpdest-ID, with the name of whoever sent it. Small and
   grey: a statement of fact, not a warning — the card is still worth opening to
   read. "Locked" and "locked by Markus" are different pieces of news, and only the
   second one says who to ask about reopening it (18 Aug 2026). */
.position__lock {
	font-size: var(--fs-sm);
	color: var(--c-text-muted);
	white-space: nowrap;
}
