/**
 * Upendo Hostel — management application design system.
 *
 * WHY THE HOSTEL HAS ITS OWN STYLESHEET
 * -------------------------------------
 * It had none. Every `lshostel-` class the views emitted styled nothing, so
 * the hostel's screens rendered as bare wp-admin markup: unstyled headings,
 * default tables, cards that were not cards. The system worked and looked
 * broken, which for the person using it is indistinguishable from broken.
 *
 * It is a separate file from the lodge's rather than a section inside it,
 * because the two businesses are separate and the interface should say so
 * before anybody reads a word. Same standard of work, different identity: the
 * lodge is teal, the hostel is indigo-slate. An administrator who runs both on
 * one login can tell from across the room which one they are looking at.
 *
 * THREE RULES, THE SAME THREE THE LODGE KEEPS
 * -------------------------------------------
 *   1. Status is never carried by colour alone. Every badge and every alert
 *      carries a word as well as a hue, because roughly one man in twelve
 *      cannot reliably separate the red from the amber, and this is an
 *      operations tool where getting that wrong means a bed double-booked.
 *
 *   2. Density over decoration. A warden reads this standing at a desk with a
 *      student waiting.
 *
 *   3. It lives inside wp-admin, so it must out-specify wp-admin without
 *      reaching for !important. The .lshostel-app scope does that.
 *
 * @package LodgeStay_PMS
 */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

.lshostel-app {
	/*
	 * THE SCALES ARE THE PLATFORM'S; ONLY THE COLOUR IS THE HOSTEL'S.
	 *
	 * These used to be twelve neutrals, seven spacing steps in PIXELS, two radii
	 * and two shadows, all written out here with their own values. The lodge had
	 * its own set with different steps in different units, and the two drifted
	 * exactly as you would expect: the same card had a 6px corner in one system
	 * and an 8px corner in the other, and nobody could have told you why.
	 *
	 * They are now aliases onto toplife.css, so there is one value behind each
	 * and changing it changes all three systems together. Every alias below
	 * preserves the pixel value the hostel had, so this is a change of
	 * PLUMBING and not of appearance — with two exceptions, both noted where
	 * they occur.
	 */
	--hs-neutral-0:   var(--tl-neutral-0);
	--hs-neutral-25:  var(--tl-neutral-25);
	--hs-neutral-50:  var(--tl-neutral-50);
	--hs-neutral-100: var(--tl-neutral-100);
	--hs-neutral-200: var(--tl-neutral-200);
	--hs-neutral-300: var(--tl-neutral-300);
	--hs-neutral-400: var(--tl-neutral-400);
	--hs-neutral-500: var(--tl-neutral-500);

	/*
	 * EXCEPTION ONE, AND IT WAS A BUG.
	 *
	 * This read `#4c536616` — eight hex digits where six were meant, which CSS
	 * reads as a colour at 9% opacity. Anywhere it was used as text the text was
	 * all but invisible; anywhere it was used as a border the border was not
	 * there. The sibling token `--hs-neutral-650` was `#4c5366`, opaque, and was
	 * almost certainly added because somebody hit this and worked around it
	 * rather than finding it.
	 *
	 * Both now point at the shared neutral, which is what they were both
	 * reaching for.
	 */
	--hs-neutral-600: var(--tl-neutral-600);
	--hs-neutral-650: var(--tl-neutral-600);

	--hs-neutral-700: var(--tl-neutral-700);
	--hs-neutral-800: var(--tl-neutral-800);
	--hs-neutral-900: var(--tl-neutral-900);

	/*
	 * Indigo-slate. Deliberately not the lodge's teal and deliberately not a
	 * bright SaaS purple: this is a student hostel's back office, and the
	 * palette is calm because most of what appears on these screens is routine.
	 *
	 * This is the hostel's identity and the only block in this file that is not
	 * an alias. It is also published as --tl-primary-* so the shared rules in
	 * toplife.css — the focus ring, chiefly — pick up the hostel's colour rather
	 * than the lodge's.
	 */
	--hs-primary-50:  #eef1f9;
	--hs-primary-100: #d8def2;
	--hs-primary-200: #b3bfe4;
	--hs-primary-300: #8496d1;
	--hs-primary-400: #5c72bd;
	--hs-primary-500: #4257a5;
	--hs-primary-600: #354688;
	--hs-primary-700: #2b396e;
	--hs-primary-800: #222d57;
	--hs-primary-900: #1a2242;

	--tl-primary-50:  var(--hs-primary-50);
	--tl-primary-100: var(--hs-primary-100);
	--tl-primary-500: var(--hs-primary-500);
	--tl-primary-700: var(--hs-primary-700);

	/*
	 * Status. Each of these is paired with a WORD everywhere it is used.
	 *
	 * EXCEPTION TWO: these now resolve to the platform's semantic ramp rather
	 * than the hostel's own slightly different greens and reds. The hostel's
	 * success green was #2e7d4f and the lodge's #1e874b — near enough that
	 * nobody would notice them side by side, and far enough that they were two
	 * decisions where there should have been one.
	 */
	--hs-good-50:    var(--tl-success-50);
	--hs-good-500:   var(--tl-success-500);
	--hs-good-700:   var(--tl-success-700);

	--hs-notice-50:  var(--tl-notice-50);
	--hs-notice-500: var(--tl-notice-500);
	--hs-notice-700: var(--tl-notice-700);

	--hs-warning-50:  var(--tl-warning-50);
	--hs-warning-500: var(--tl-warning-500);
	--hs-warning-700: var(--tl-warning-700);

	--hs-urgent-50:  var(--tl-danger-50);
	--hs-urgent-500: var(--tl-danger-500);
	--hs-urgent-700: var(--tl-danger-700);

	--hs-info-50:    var(--tl-info-50);
	--hs-info-500:   var(--tl-info-500);
	--hs-info-700:   var(--tl-info-700);

	/*
	 * Spacing. The hostel's seven px steps map onto the platform's rem scale
	 * with every value preserved exactly: 4, 8, 12, 16, 24, 32, 48. The gaps in
	 * the mapping (--tl-space-5, -10) are steps the hostel never had and can now
	 * reach for.
	 */
	--hs-space-1: var(--tl-space-1);  /*  4 */
	--hs-space-2: var(--tl-space-2);  /*  8 */
	--hs-space-3: var(--tl-space-3);  /* 12 */
	--hs-space-4: var(--tl-space-4);  /* 16 */
	--hs-space-5: var(--tl-space-6);  /* 24 */
	--hs-space-6: var(--tl-space-8);  /* 32 */
	--hs-space-7: var(--tl-space-12); /* 48 */

	--hs-radius:    var(--tl-radius);
	--hs-radius-lg: var(--tl-radius-lg);

	--hs-shadow-sm: var(--tl-shadow-sm);
	--hs-shadow:    var(--tl-shadow-md);

	--hs-border: 1px solid var(--tl-border);

	color: var(--hs-neutral-800);
}

/* ==========================================================================
   2. PAGE SHELL
   ========================================================================== */

.lshostel-app {
	/*
	 * A little air on the right. wp-admin's .wrap runs content to the edge of
	 * the viewport, which on a 1920px monitor puts the end of a wide table
	 * against the window frame.
	 */
	padding-right: var(--hs-space-4);
	max-width: 1600px;
}

.lshostel-masthead {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--hs-space-3);
	padding: var(--hs-space-4) 0 var(--hs-space-3);
	border-bottom: 2px solid var(--hs-primary-600);
	margin-bottom: var(--hs-space-4);
}

.lshostel-masthead__title {
	margin: 0;
	padding: 0;
	font-size: 1.5rem;
	line-height: 1.2;
	font-weight: 650;
	color: var(--hs-primary-800);
}

.lshostel-masthead__where {
	margin: 0;
	font-size: 0.9rem;
	color: var(--hs-neutral-500);
}

/*
 * The navigation and the content sit side by side on a wide screen and stack
 * on a narrow one. Grid rather than float, so the sidebar cannot end up taller
 * than the content and leave a hole under it.
 */
.lshostel-app {
	display: grid;
	grid-template-columns: 220px minmax(0, 1fr);
	grid-template-areas:
		"masthead masthead"
		"nav      main";
	gap: 0 var(--hs-space-5);
	align-items: start;
}

.lshostel-masthead { grid-area: masthead; }
.lshostel-nav      { grid-area: nav; }
.lshostel-main     { grid-area: main; min-width: 0; }

/*
 * minmax(0, 1fr) above and min-width: 0 here are the pair that stops a wide
 * table stretching the grid column and pushing the whole page sideways. A grid
 * item's default min-width is auto, which means "as wide as my content", which
 * for a table of thirty payments means the page scrolls horizontally.
 */

/* ==========================================================================
   3. SIDEBAR
   ========================================================================== */

.lshostel-nav {
	position: sticky;
	top: 46px;
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	padding: var(--hs-space-3) 0;
	box-shadow: var(--hs-shadow-sm);
}

.lshostel-nav-group {
	margin: var(--hs-space-4) var(--hs-space-4) var(--hs-space-2);
	padding: 0;
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--hs-neutral-400);
}

.lshostel-nav-group:first-child { margin-top: var(--hs-space-1); }

.lshostel-nav ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.lshostel-nav li { margin: 0; }

.lshostel-nav a {
	display: flex;
	align-items: center;
	gap: var(--hs-space-2);
	padding: var(--hs-space-2) var(--hs-space-4);
	color: var(--hs-neutral-700);
	text-decoration: none;
	font-size: 0.9rem;
	border-left: 3px solid transparent;
}

.lshostel-nav a:hover,
.lshostel-nav a:focus {
	background: var(--hs-primary-50);
	color: var(--hs-primary-700);
}

.lshostel-nav a:focus-visible {
	outline: 2px solid var(--hs-primary-500);
	outline-offset: -2px;
}

.lshostel-nav a.current {
	background: var(--hs-primary-50);
	border-left-color: var(--hs-primary-600);
	color: var(--hs-primary-800);
	font-weight: 600;
}

.lshostel-nav .dashicons {
	font-size: 17px;
	width: 17px;
	height: 17px;
	color: var(--hs-neutral-400);
	flex: none;
}

.lshostel-nav a.current .dashicons { color: var(--hs-primary-600); }

/* ==========================================================================
   4. BREADCRUMBS
   ========================================================================== */

.lshostel-crumbs {
	margin: 0 0 var(--hs-space-4);
	font-size: 0.82rem;
	color: var(--hs-neutral-500);
}

.lshostel-crumbs ol {
	display: flex;
	flex-wrap: wrap;
	gap: var(--hs-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.lshostel-crumbs li { margin: 0; }

/* The separator is generated, so it is never read aloud as a list item. */
.lshostel-crumbs li + li::before {
	content: "\203A";
	margin-right: var(--hs-space-2);
	color: var(--hs-neutral-300);
}

.lshostel-crumbs [aria-current="page"] {
	color: var(--hs-neutral-800);
	font-weight: 600;
}

/* ==========================================================================
   5. SECTIONS AND HEADINGS
   ========================================================================== */

.lshostel-section { margin: 0 0 var(--hs-space-6); }

.lshostel-h2 {
	margin: 0 0 var(--hs-space-3);
	padding: 0;
	font-size: 1.05rem;
	font-weight: 650;
	color: var(--hs-neutral-800);
}

.lshostel-h3 {
	margin: var(--hs-space-5) 0 var(--hs-space-3);
	font-size: 1rem;
	font-weight: 600;
	color: var(--hs-neutral-700);
}

.lshostel-lead {
	margin: 0 0 var(--hs-space-4);
	max-width: 74ch;
	color: var(--hs-neutral-650);
	font-size: 0.92rem;
	line-height: 1.6;
}

/* ==========================================================================
   6. BRIEFING
   ========================================================================== */

.lshostel-briefing {
	background: linear-gradient(135deg, var(--hs-primary-700), var(--hs-primary-500));
	color: var(--hs-neutral-0);
	border-radius: var(--hs-radius-lg);
	padding: var(--hs-space-5);
	margin-bottom: var(--hs-space-5);
}

.lshostel-briefing__greeting {
	margin: 0 0 var(--hs-space-1);
	padding: 0;
	font-size: 1.35rem;
	font-weight: 650;
	/*
	 * White on the gradient's lightest stop is 4.9:1. Stated because it is the
	 * one place in this file where text sits on a coloured field rather than on
	 * a neutral, and it is the first thing that would break if the gradient
	 * were lightened for looks.
	 */
	color: var(--hs-neutral-0);
}

.lshostel-briefing__lead {
	margin: 0 0 var(--hs-space-3);
	font-size: 0.95rem;
	color: rgba(255, 255, 255, 0.92);
}

.lshostel-briefing__body {
	margin: 0 0 var(--hs-space-2);
	font-size: 1rem;
	line-height: 1.55;
	max-width: 70ch;
	color: var(--hs-neutral-0);
}

.lshostel-briefing__stamp {
	margin: 0;
	font-size: 0.8rem;
	color: rgba(255, 255, 255, 0.78);
}

/* ==========================================================================
   7. KPI CARDS
   ========================================================================== */

.lshostel-kpis {
	display: grid;
	/*
	 * auto-fill with a minimum, so the row reflows instead of squashing. 210px
	 * is the width at which "TZS 1,250,000" still fits on one line at the value
	 * font size; below that the number wraps and a KPI card whose number wraps
	 * is unreadable.
	 */
	grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
	gap: var(--hs-space-3);
	margin-bottom: var(--hs-space-4);
}

.lshostel-kpi {
	position: relative;
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	padding: var(--hs-space-4);
	box-shadow: var(--hs-shadow-sm);
	min-width: 0;
}

.lshostel-kpi__icon {
	position: absolute;
	top: var(--hs-space-4);
	right: var(--hs-space-4);
	font-size: 18px;
	width: 18px;
	height: 18px;
	color: var(--hs-neutral-300);
}

.lshostel-kpi__label {
	margin: 0 var(--hs-space-6) var(--hs-space-2) 0;
	padding: 0;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--hs-neutral-500);
}

.lshostel-kpi__value {
	margin: 0 0 var(--hs-space-2);
	font-size: 1.6rem;
	line-height: 1.15;
	font-weight: 650;
	color: var(--hs-neutral-900);
	font-variant-numeric: tabular-nums;
	/*
	 * A long amount shrinks the gap between digits rather than wrapping. The
	 * non-breaking space in "TZS 150,000" keeps the code with the number; this
	 * keeps the number itself on one line down to about 320px.
	 */
	overflow-wrap: break-word;
	word-break: normal;
}

.lshostel-kpi__description {
	margin: 0;
	font-size: 0.8rem;
	line-height: 1.45;
	color: var(--hs-neutral-500);
}

/* ==========================================================================
   8. ALERTS
   ========================================================================== */

.lshostel-alerts {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: var(--hs-space-2);
}

.lshostel-alert {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--hs-space-3);
	margin: 0;
	padding: var(--hs-space-3) var(--hs-space-4);
	border-radius: var(--hs-radius);
	border: 1px solid transparent;
	/* The left rule is a second, non-colour signal of severity: thicker for
	   the ones that matter more. */
	border-left-width: 4px;
	background: var(--hs-neutral-50);
	font-size: 0.9rem;
}

.lshostel-alert__level {
	flex: none;
	font-size: 0.68rem;
	font-weight: 750;
	letter-spacing: 0.08em;
	padding: 2px var(--hs-space-2);
	border-radius: 3px;
}

.lshostel-alert__message {
	flex: 1 1 240px;
	min-width: 0;
	line-height: 1.5;
}

.lshostel-alert__action {
	flex: none;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}

.lshostel-alert--urgent {
	background: var(--hs-urgent-50);
	border-color: var(--hs-urgent-500);
}
.lshostel-alert--urgent .lshostel-alert__level {
	background: var(--hs-urgent-500);
	color: #fff;
}
.lshostel-alert--urgent .lshostel-alert__action { color: var(--hs-urgent-700); }

.lshostel-alert--warning {
	background: var(--hs-warning-50);
	border-color: var(--hs-warning-500);
}
.lshostel-alert--warning .lshostel-alert__level {
	background: var(--hs-warning-500);
	color: #fff;
}
.lshostel-alert--warning .lshostel-alert__action { color: var(--hs-warning-700); }

.lshostel-alert--notice {
	background: var(--hs-notice-50);
	border-color: var(--hs-notice-500);
}
.lshostel-alert--notice .lshostel-alert__level {
	background: var(--hs-notice-500);
	color: #fff;
}
.lshostel-alert--notice .lshostel-alert__action { color: var(--hs-notice-700); }

.lshostel-alert--info {
	background: var(--hs-info-50);
	border-color: var(--hs-info-500);
}
.lshostel-alert--info .lshostel-alert__level {
	background: var(--hs-info-500);
	color: #fff;
}
.lshostel-alert--info .lshostel-alert__action { color: var(--hs-info-700); }

/* ==========================================================================
   9. BADGES
   ========================================================================== */

.lshostel-badge {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 2px var(--hs-space-2);
	border-radius: 3px;
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.03em;
	white-space: nowrap;
}

/*
 * The hostel colours its badges by TONE, and pending, cancelled and refunded
 * all resolve to `notice` — three states a bookkeeper has to tell apart,
 * printed in one colour. The colour was not merely insufficient there, it was
 * saying they were the same. The mark is per state, so they stop matching.
 */
.lshostel-badge__mark {
	font-size: 12px;
	width: 12px;
	height: 12px;
	line-height: 12px;
	flex: 0 0 12px;
}

.lshostel-badge__label { display: inline; }

.lshostel-badge--good    { background: var(--hs-good-50);    color: var(--hs-good-700); }
.lshostel-badge--notice  { background: var(--hs-notice-50);  color: var(--hs-notice-700); }
.lshostel-badge--warning { background: var(--hs-warning-50); color: var(--hs-warning-700); }
.lshostel-badge--urgent  { background: var(--hs-urgent-50);  color: var(--hs-urgent-700); }
.lshostel-badge--info    { background: var(--hs-info-50);    color: var(--hs-info-700); }

/* ==========================================================================
   10. QUICK ACTIONS
   ========================================================================== */

.lshostel-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--hs-space-2);
}

.lshostel-action {
	display: inline-flex;
	align-items: center;
	gap: var(--hs-space-2);
	/* 40px tall, which is a comfortable target with a thumb. */
	min-height: 40px;
	padding: var(--hs-space-2) var(--hs-space-4);
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius);
	color: var(--hs-neutral-700);
	text-decoration: none;
	font-size: 0.88rem;
	font-weight: 500;
	box-shadow: var(--hs-shadow-sm);
}

.lshostel-action:hover,
.lshostel-action:focus {
	border-color: var(--hs-primary-400);
	color: var(--hs-primary-700);
	background: var(--hs-primary-50);
}

.lshostel-action:focus-visible {
	outline: 2px solid var(--hs-primary-500);
	outline-offset: 1px;
}

.lshostel-action .dashicons {
	font-size: 16px;
	width: 16px;
	height: 16px;
	color: var(--hs-primary-500);
}

/* ==========================================================================
   11. TODAY'S OPERATIONS
   ========================================================================== */

.lshostel-ops {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: var(--hs-space-3);
}

.lshostel-op {
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	padding: var(--hs-space-4);
	min-width: 0;
}

.lshostel-op__title {
	margin: 0 0 var(--hs-space-2);
	padding: 0;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--hs-neutral-500);
}

.lshostel-op__count {
	margin: 0 0 var(--hs-space-1);
	font-size: 1.7rem;
	font-weight: 650;
	line-height: 1.1;
	color: var(--hs-neutral-900);
	font-variant-numeric: tabular-nums;
}

.lshostel-op__note {
	margin: 0;
	font-size: 0.8rem;
	line-height: 1.4;
	color: var(--hs-neutral-500);
}

/* An empty note leaves no ghost gap under the number. */
.lshostel-op__note:empty { display: none; }

/* ==========================================================================
   12. EMPTY STATES
   ========================================================================== */

/*
 * An empty state has to look INTENDED. The failure it guards against is a
 * screen that has nothing on it because there is nothing to show, being read
 * as a screen that has nothing on it because it broke. So: a bordered panel
 * with two sentences, not a bare line of grey text.
 */
.lshostel-empty-state {
	background: var(--hs-neutral-25);
	border: 1px dashed var(--hs-neutral-300);
	border-radius: var(--hs-radius-lg);
	padding: var(--hs-space-5);
	text-align: center;
	margin: 0 0 var(--hs-space-4);
}

.lshostel-empty-state__heading {
	margin: 0 0 var(--hs-space-2);
	font-size: 0.98rem;
	font-weight: 600;
	color: var(--hs-neutral-700);
}

.lshostel-empty-state__body {
	margin: 0 auto;
	max-width: 62ch;
	font-size: 0.87rem;
	line-height: 1.55;
	color: var(--hs-neutral-500);
}

/* ==========================================================================
   13. TABLES
   ========================================================================== */

/*
 * The wrapper scrolls, not the page. A payments table with seven columns is
 * wider than a phone; without this the whole document scrolls sideways and the
 * navigation goes with it.
 */
.lshostel-tablewrap {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	background: var(--hs-neutral-0);
	margin-bottom: var(--hs-space-4);
}

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

/* A table that is its own wrapper still needs the frame. */
.lshostel-table:not(.lshostel-tablewrap > .lshostel-table) {
	background: var(--hs-neutral-0);
}

.lshostel-table th,
.lshostel-table td {
	padding: var(--hs-space-3) var(--hs-space-4);
	text-align: left;
	border-bottom: 1px solid var(--hs-neutral-100);
	vertical-align: top;
}

.lshostel-table thead th {
	background: var(--hs-neutral-50);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--hs-neutral-500);
	white-space: nowrap;
	border-bottom: 1px solid var(--hs-neutral-200);
}

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

.lshostel-table tbody tr:hover { background: var(--hs-neutral-25); }

.lshostel-table--compact th,
.lshostel-table--compact td {
	padding: var(--hs-space-2) var(--hs-space-3);
}

.lshostel-unset {
	color: var(--hs-neutral-400);
	font-style: italic;
}

/*
 * A sentence explaining what a control will do, sitting under it. Quieter than
 * the surrounding text but not as quiet as `.lshostel-unset`, which means
 * "nobody has filled this in" — this means "read this before you press it".
 */
.lshostel-hint {
	color: var(--hs-neutral-500);
	font-size: 13px;
	margin: 4px 0 12px;
	max-width: 60ch;
}

/*
 * A form's fields, two or three across depending on the width available. auto-fit
 * rather than a fixed column count, so the registration form is one column on a
 * phone at the reception desk without a media query saying where the break is.
 */
.lshostel-formgrid {
	display: grid;
	gap: 0 16px;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.lshostel-field {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin: 0 0 12px;
	max-width: 640px;
}

.lshostel-field label {
	color: var(--hs-neutral-600);
	font-size: 13px;
	font-weight: 600;
}

.lshostel-field input,
.lshostel-field select,
.lshostel-field textarea {
	max-width: 100%;
	width: 100%;
}

/* ==========================================================================
   14. OCCUPANCY BAR
   ========================================================================== */

.lshostel-bar {
	display: flex;
	height: 26px;
	border-radius: var(--hs-radius);
	overflow: hidden;
	background: var(--hs-neutral-100);
	margin-bottom: var(--hs-space-3);
}

.lshostel-bar__part { display: block; height: 100%; }

/*
 * Each segment carries a texture as well as a colour: solid, diagonal hatch,
 * dense hatch. In greyscale, in a printout, or to a reader who cannot separate
 * the hues, the three are still three different things. The accessible reading
 * is the table below it, which is always present and never behind a toggle.
 */
.lshostel-bar__part--occupied {
	background: var(--hs-primary-500);
}

.lshostel-bar__part--available {
	background: var(--hs-good-500);
	background-image: repeating-linear-gradient(
		45deg,
		rgba(255, 255, 255, 0.28) 0,
		rgba(255, 255, 255, 0.28) 3px,
		transparent 3px,
		transparent 7px
	);
}

/*
 * Reserved: amber, and with its own texture direction. Every segment here is
 * distinguishable without colour, because roughly one man in twelve cannot
 * separate the amber from the green and a bed board that speaks only in hue
 * tells him nothing.
 */
.lshostel-bar__part--reserved {
	background: var(--hs-warning-500);
	background-image: repeating-linear-gradient(
		90deg,
		rgba(255, 255, 255, 0.35) 0,
		rgba(255, 255, 255, 0.35) 2px,
		transparent 2px,
		transparent 6px
	);
}

.lshostel-bar__part--maintenance {
	background: var(--hs-neutral-400);
	background-image: repeating-linear-gradient(
		-45deg,
		rgba(255, 255, 255, 0.42) 0,
		rgba(255, 255, 255, 0.42) 2px,
		transparent 2px,
		transparent 5px
	);
}

/* ==========================================================================
   15. NOTICES AND ANNOUNCEMENTS
   ========================================================================== */

.lshostel-notices {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: var(--hs-space-3);
}

.lshostel-notice {
	margin: 0;
	padding: var(--hs-space-4);
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
}

.lshostel-notice__title {
	margin: var(--hs-space-2) 0 var(--hs-space-1);
	padding: 0;
	font-size: 0.98rem;
	font-weight: 650;
	color: var(--hs-neutral-800);
}

.lshostel-notice__body {
	margin: 0;
	font-size: 0.88rem;
	line-height: 1.55;
	max-width: 74ch;
	color: var(--hs-neutral-650);
}

/* ==========================================================================
   16. GATEWAY STATE
   ========================================================================== */

.lshostel-gateway {
	padding: var(--hs-space-4);
	border-radius: var(--hs-radius-lg);
	border: 1px solid transparent;
	border-left-width: 4px;
	margin-bottom: var(--hs-space-5);
}

.lshostel-gateway p { margin: 0; }
.lshostel-gateway p + p { margin-top: var(--hs-space-2); }

.lshostel-gateway__state {
	font-size: 0.72rem;
	font-weight: 750;
	letter-spacing: 0.09em;
}

.lshostel-gateway--good    { background: var(--hs-good-50);    border-color: var(--hs-good-500);    color: var(--hs-good-700); }
.lshostel-gateway--warning { background: var(--hs-warning-50); border-color: var(--hs-warning-500); color: var(--hs-warning-700); }
.lshostel-gateway--urgent  { background: var(--hs-urgent-50);  border-color: var(--hs-urgent-500);  color: var(--hs-urgent-700); }

/* ==========================================================================
   17. REPORTS
   ========================================================================== */

.lshostel-report-list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
	gap: var(--hs-space-3);
	margin-bottom: var(--hs-space-5);
}

.lshostel-report-card {
	display: block;
	padding: var(--hs-space-4);
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	text-decoration: none;
	color: inherit;
	min-width: 0;
}

.lshostel-report-card:hover,
.lshostel-report-card:focus {
	border-color: var(--hs-primary-400);
	background: var(--hs-primary-50);
}

.lshostel-report-card:focus-visible {
	outline: 2px solid var(--hs-primary-500);
	outline-offset: 1px;
}

/*
 * The chosen report is marked with a thickened left edge as well as a tint,
 * so "which one am I looking at" does not depend on distinguishing a pale
 * blue panel from a white one.
 */
.lshostel-report-card.is-current {
	border-color: var(--hs-primary-600);
	border-left-width: 4px;
	background: var(--hs-primary-50);
}

.lshostel-report-card h3 {
	margin: 0 0 var(--hs-space-2);
	padding: 0;
	font-size: 0.92rem;
	font-weight: 650;
	color: var(--hs-primary-800);
}

.lshostel-report-card p {
	margin: 0;
	font-size: 0.82rem;
	line-height: 1.5;
	color: var(--hs-neutral-500);
}

.lshostel-ranges ul {
	display: flex;
	flex-wrap: wrap;
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-4);
	padding: 0;
	list-style: none;
}

.lshostel-ranges li { margin: 0; }

.lshostel-ranges a {
	display: inline-block;
	min-height: 34px;
	padding: var(--hs-space-2) var(--hs-space-3);
	border: var(--hs-border);
	border-radius: var(--hs-radius);
	background: var(--hs-neutral-0);
	color: var(--hs-neutral-650);
	text-decoration: none;
	font-size: 0.85rem;
}

.lshostel-ranges a:hover,
.lshostel-ranges a:focus { border-color: var(--hs-primary-400); color: var(--hs-primary-700); }

.lshostel-ranges a:focus-visible {
	outline: 2px solid var(--hs-primary-500);
	outline-offset: 1px;
}

.lshostel-ranges a.is-current {
	background: var(--hs-primary-600);
	border-color: var(--hs-primary-600);
	color: #fff;
	font-weight: 600;
}

.lshostel-report-period {
	margin: 0 0 var(--hs-space-4);
	font-size: 0.85rem;
	color: var(--hs-neutral-500);
}

/* ==========================================================================
   18. FORMS
   ========================================================================== */

.lshostel-form {
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	padding: var(--hs-space-2) var(--hs-space-4) var(--hs-space-4);
	margin-bottom: var(--hs-space-5);
}

.lshostel-form .form-table th {
	padding-left: 0;
	color: var(--hs-neutral-700);
}

.lshostel-form input[type="text"]:focus-visible,
.lshostel-form input[type="password"]:focus-visible,
.lshostel-form input[type="number"]:focus-visible,
.lshostel-form select:focus-visible,
.lshostel-form textarea:focus-visible {
	outline: 2px solid var(--hs-primary-500);
	outline-offset: 1px;
	border-color: var(--hs-primary-500);
}

/* ==========================================================================
   19. RESPONSIVE
   ========================================================================== */

/*
 * wp-admin folds its own sidebar at 960px, which is where the hostel's
 * two-column grid also stops earning its keep.
 */
@media screen and (max-width: 960px) {
	.lshostel-app {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"masthead"
			"nav"
			"main";
		padding-right: 0;
	}

	.lshostel-nav {
		position: static;
		margin-bottom: var(--hs-space-4);
	}

	/* The sidebar becomes a wrapped row of links rather than a tall column
	   that pushes the content off the first screen. */
	.lshostel-nav ul {
		display: flex;
		flex-wrap: wrap;
		gap: var(--hs-space-1);
		padding: 0 var(--hs-space-3);
	}

	.lshostel-nav a {
		border-left: 0;
		border-radius: var(--hs-radius);
		padding: var(--hs-space-2) var(--hs-space-3);
	}

	.lshostel-nav a.current { border-left: 0; }
}

@media screen and (max-width: 600px) {
	.lshostel-kpis { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
	.lshostel-ops  { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }

	.lshostel-kpi__value { font-size: 1.35rem; }
	.lshostel-op__count  { font-size: 1.45rem; }

	.lshostel-briefing { padding: var(--hs-space-4); }
	.lshostel-briefing__greeting { font-size: 1.15rem; }

	/* An action that fills the row is easier to hit than one that shares it. */
	.lshostel-action { flex: 1 1 100%; justify-content: center; }
}

/* ==========================================================================
   20. PRINT
   ========================================================================== */

/*
 * A report printed from the browser must contain the report and nothing else.
 * The navigation, the masthead, the quick actions and wp-admin's own furniture
 * are all removed, so what comes out of the printer is what was asked for.
 */
@media print {
	#adminmenumain,
	#wpadminbar,
	#wpfooter,
	.lshostel-nav,
	.lshostel-actions,
	.lshostel-crumbs,
	.lshostel-form,
	.notice {
		display: none !important;
	}

	.lshostel-app {
		display: block;
		padding: 0;
		max-width: none;
	}

	#wpcontent,
	#wpbody-content {
		padding-left: 0 !important;
		margin-left: 0 !important;
	}

	.lshostel-masthead {
		border-bottom: 1px solid #000;
		margin-bottom: 12pt;
	}

	.lshostel-kpi,
	.lshostel-table,
	.lshostel-tablewrap {
		border-color: #999;
		box-shadow: none;
	}

	.lshostel-briefing {
		background: none;
		color: #000;
		border: 1px solid #999;
	}

	.lshostel-briefing__greeting,
	.lshostel-briefing__body { color: #000; }
	.lshostel-briefing__lead,
	.lshostel-briefing__stamp { color: #444; }

	/* A table split across a page break loses its heading row otherwise. */
	.lshostel-table thead { display: table-header-group; }
	.lshostel-table tr { page-break-inside: avoid; }

	.lshostel-tablewrap { overflow: visible; }
}

/* ==========================================================================
   21. REDUCED MOTION AND FORCED COLOURS
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	.lshostel-app * {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
	}
}

/*
 * In Windows high-contrast mode every background is replaced, so the alert
 * severities would become indistinguishable. The left rule and the level word
 * are what carry the meaning there, and both survive.
 */
@media (forced-colors: active) {
	.lshostel-alert,
	.lshostel-gateway,
	.lshostel-kpi,
	.lshostel-op,
	.lshostel-empty-state {
		border: 1px solid CanvasText;
	}

	.lshostel-alert { border-left-width: 4px; }

	.lshostel-bar__part { forced-color-adjust: none; }
}

/* ==========================================================================
   22. ROOMS AND BEDS
   ========================================================================== */

.lshostel-rooms {
	display: grid;
	/*
	 * 300px is the width at which room 07's fourteen bed chips still form a
	 * readable block rather than a single column. Narrower and the biggest room
	 * becomes a list; wider and a 1280px screen fits only three rooms.
	 *
	 * The floor is capped at the container's own width, so the rule holds at
	 * every width rather than only at the ones somebody remembered to test. It
	 * measures clean today; the clamp is what keeps it clean when the layout
	 * around it changes.
	 */
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
	gap: var(--hs-space-4);
}

.lshostel-room {
	background: var(--hs-neutral-0);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	padding: var(--hs-space-4);
	box-shadow: var(--hs-shadow-sm);
	min-width: 0;
}

.lshostel-room__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--hs-space-2);
	padding-bottom: var(--hs-space-3);
	border-bottom: var(--hs-border);
	margin-bottom: var(--hs-space-3);
}

.lshostel-room__code {
	margin: 0;
	padding: 0;
	font-size: 1.05rem;
	font-weight: 650;
	color: var(--hs-primary-800);
}

.lshostel-room__beds {
	margin: 0;
	font-size: 0.8rem;
	color: var(--hs-neutral-500);
	white-space: nowrap;
}

.lshostel-room__stats {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-3);
}

.lshostel-room__stat { min-width: 0; }

.lshostel-room__stat dt {
	margin: 0 0 2px;
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--hs-neutral-400);
	/* Four labels across a 300px card: "Out of service" has to wrap rather
	   than push the fourth column off the edge. */
	overflow-wrap: break-word;
}

.lshostel-room__stat dd {
	margin: 0;
	font-size: 1.1rem;
	font-weight: 650;
	color: var(--hs-neutral-900);
	font-variant-numeric: tabular-nums;
}

.lshostel-room__rate {
	margin: 0 0 var(--hs-space-1);
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--hs-neutral-800);
}

.lshostel-room__rate span {
	font-size: 0.78rem;
	font-weight: 400;
	color: var(--hs-neutral-500);
}

.lshostel-room__potential {
	margin: 0 0 var(--hs-space-3);
	font-size: 0.78rem;
	color: var(--hs-neutral-500);
}

.lshostel-room__actions {
	margin: var(--hs-space-3) 0 0;
	font-size: 0.85rem;
}

/* --------------------------------------------------------------- bed chips

   A chip carries its state as a WORD as well as a colour and a left rule.
   This is the screen a warden reads at a glance from across a desk to answer
   "what have I got free", and it is exactly where colour-only status fails:
   the consequence is a student sent to a bed that is already taken.
*/
.lshostel-bedgrid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
	gap: var(--hs-space-1);
	margin: 0;
	padding: 0;
	list-style: none;
}

.lshostel-bedchip {
	display: flex;
	flex-direction: column;
	gap: 1px;
	margin: 0;
	padding: var(--hs-space-1) var(--hs-space-2);
	border: 1px solid var(--hs-neutral-200);
	border-left-width: 3px;
	border-radius: var(--hs-radius);
	background: var(--hs-neutral-25);
	min-width: 0;
}

.lshostel-bedchip__code {
	font-size: 0.8rem;
	font-weight: 700;
	color: var(--hs-neutral-800);
	font-variant-numeric: tabular-nums;
}

.lshostel-bedchip__state {
	font-size: 0.6rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	/* "Out of service" is the longest and must wrap inside the chip rather
	   than widen it and break the grid. */
	overflow-wrap: break-word;
	hyphens: auto;
}

.lshostel-bedchip--available {
	border-left-color: var(--hs-good-500);
	background: var(--hs-good-50);
}
.lshostel-bedchip--available .lshostel-bedchip__state { color: var(--hs-good-700); }

.lshostel-bedchip--occupied {
	border-left-color: var(--hs-primary-500);
	background: var(--hs-primary-50);
}
.lshostel-bedchip--occupied .lshostel-bedchip__state { color: var(--hs-primary-700); }

.lshostel-bedchip--reserved {
	border-left-color: var(--hs-warning-500);
	background: var(--hs-warning-50);
}
.lshostel-bedchip--reserved .lshostel-bedchip__state { color: var(--hs-warning-700); }

.lshostel-bedchip--broken {
	border-left-color: var(--hs-urgent-500);
	background: var(--hs-urgent-50);
}
.lshostel-bedchip--broken .lshostel-bedchip__state { color: var(--hs-urgent-700); }

@media screen and (max-width: 600px) {
	.lshostel-rooms { grid-template-columns: minmax(0, 1fr); }

	/*
	 * Two stats per row rather than four. Four columns of 0.62rem uppercase
	 * inside a 343px card is unreadable, and "Out of service" wraps to three
	 * lines.
	 */
	.lshostel-room__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (forced-colors: active) {
	.lshostel-bedchip { border: 1px solid CanvasText; border-left-width: 3px; }
	.lshostel-room { border: 1px solid CanvasText; }
}

/* ---------------------------------------------------------------- wizard
 *
 * Seven steps across the top and one decision underneath. Everything here is
 * sized for a warden standing at a desk with somebody waiting: the choices are
 * large targets, the blocked ones stay visible with their reason attached
 * rather than disappearing, and the figure on the rate step is big enough to
 * read from arm's length before it is agreed to.
 * ---------------------------------------------------------------------- */

.lshostel-wizard__steps {
	display: flex;
	flex-wrap: wrap;
	gap: var(--hs-space-1);
	margin: 0 0 var(--hs-space-5);
	padding: 0;
	list-style: none;
	counter-reset: none;
}

.lshostel-wizard__stepitem {
	flex: 1 1 auto;
	min-width: 0;
}

.lshostel-wizard__stepitem > a,
.lshostel-wizard__stepitem > span {
	display: block;
	padding: var(--hs-space-2) var(--hs-space-3);
	border-bottom: 3px solid var(--hs-neutral-200);
	font-size: 0.8rem;
	line-height: 1.3;
	text-decoration: none;
	color: var(--hs-neutral-600);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.lshostel-wizard__stepitem.is-done > a { color: var(--hs-primary-700); border-bottom-color: var(--hs-primary-300); }

.lshostel-wizard__stepitem.is-current > a,
.lshostel-wizard__stepitem.is-current > span {
	color: var(--hs-primary-700);
	border-bottom-color: var(--hs-primary-600);
	font-weight: 600;
}

/*
 * A step that cannot be reached yet is dimmed but still readable, because it
 * tells the warden what is coming. It is never a link: a stepper that offers a
 * shortcut the wizard refuses is a stepper that lies.
 */
.lshostel-wizard__stepitem.is-locked > span { color: var(--hs-neutral-400); }

.lshostel-wizard__step { max-width: 62rem; }

.lshostel-picklist {
	display: grid;
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-5);
	padding: 0;
	list-style: none;
}

.lshostel-picklist--grid { grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); }

.lshostel-picklist__item > a,
.lshostel-picklist__item.is-blocked {
	display: flex;
	flex-direction: column;
	gap: var(--hs-space-1);
	padding: var(--hs-space-3) var(--hs-space-4);
	border: var(--hs-border);
	border-left: 3px solid var(--hs-primary-500);
	border-radius: var(--hs-radius);
	background: #fff;
	text-decoration: none;
	color: var(--hs-neutral-800);
	box-shadow: var(--hs-shadow-sm);
}

.lshostel-picklist__item > a:hover,
.lshostel-picklist__item > a:focus {
	border-left-color: var(--hs-primary-700);
	background: var(--hs-primary-50);
	box-shadow: var(--hs-shadow);
}

/*
 * Blocked choices are shown, not hidden. A bed board that quietly omits 3B
 * leaves the warden looking for it; one that shows it greyed with "Occupied"
 * beside it has answered the question.
 */
.lshostel-picklist__item.is-blocked {
	border-left-color: var(--hs-neutral-300);
	background: var(--hs-neutral-50);
	color: var(--hs-neutral-500);
}

.lshostel-picklist__name { font-weight: 600; font-size: 1rem; }
.lshostel-picklist__why  { font-size: 0.8rem; color: var(--hs-neutral-600); }
.lshostel-picklist__item.is-blocked .lshostel-picklist__why { color: var(--hs-neutral-500); }

.lshostel-wizard__figure {
	display: flex;
	flex-direction: column;
	gap: var(--hs-space-1);
	padding: var(--hs-space-5);
	margin: 0 0 var(--hs-space-4);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	background: var(--hs-primary-50);
}

.lshostel-wizard__amount {
	font-size: 2rem;
	font-weight: 700;
	line-height: 1.1;
	color: var(--hs-primary-800);
}

.lshostel-wizard__amountnote { font-size: 0.85rem; color: var(--hs-neutral-600); }

.lshostel-wizard__facts {
	display: grid;
	grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr);
	gap: var(--hs-space-2) var(--hs-space-4);
	margin: 0 0 var(--hs-space-5);
	padding: var(--hs-space-4);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	background: #fff;
}

.lshostel-wizard__facts dt { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--hs-neutral-600); }
.lshostel-wizard__facts dd { margin: 0; font-weight: 600; }

.lshostel-wizard__months {
	display: flex;
	flex-wrap: wrap;
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-4);
	padding: 0;
	border: 0;
}

.lshostel-wizard__months legend {
	padding: 0 0 var(--hs-space-2);
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--hs-neutral-600);
}

.lshostel-wizard__month {
	display: flex;
	align-items: center;
	gap: var(--hs-space-2);
	padding: var(--hs-space-2) var(--hs-space-3);
	border: var(--hs-border);
	border-radius: var(--hs-radius);
	background: #fff;
	cursor: pointer;
}

.lshostel-wizard__month:hover { background: var(--hs-primary-50); }

@media screen and (max-width: 782px) {
	/*
	 * The stepper stacks rather than scrolling sideways. Seven labels do not
	 * fit across a phone, and a horizontally scrolling progress indicator hides
	 * the very steps it exists to show.
	 */
	.lshostel-wizard__steps { flex-direction: column; gap: 0; }

	.lshostel-wizard__stepitem > a,
	.lshostel-wizard__stepitem > span {
		border-bottom: 0;
		border-left: 3px solid var(--hs-neutral-200);
		white-space: normal;
	}

	.lshostel-wizard__stepitem.is-done > a { border-left-color: var(--hs-primary-300); }

	.lshostel-wizard__stepitem.is-current > a,
	.lshostel-wizard__stepitem.is-current > span { border-left-color: var(--hs-primary-600); }

	.lshostel-picklist--grid { grid-template-columns: minmax(0, 1fr); }

	.lshostel-wizard__facts { grid-template-columns: minmax(0, 1fr); gap: var(--hs-space-1) 0; }
	.lshostel-wizard__facts dd { margin-bottom: var(--hs-space-3); }
}

@media (forced-colors: active) {
	.lshostel-picklist__item > a,
	.lshostel-picklist__item.is-blocked { border: 1px solid CanvasText; border-left-width: 3px; }
	.lshostel-wizard__facts,
	.lshostel-wizard__figure { border: 1px solid CanvasText; }
}

/* -------------------------------------------------- dashboard preferences
 *
 * At the foot of the dashboard, closed. Somebody sets this once and then wants
 * it out of the way, so it is a disclosure rather than a panel competing with
 * the figures above it.
 * ---------------------------------------------------------------------- */

.lshostel-dashsettings {
	margin: var(--hs-space-6) 0 0;
	padding: var(--hs-space-4);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	background: var(--hs-neutral-50);
}

.lshostel-dashsettings > summary {
	cursor: pointer;
	font-weight: 600;
	color: var(--hs-primary-700);
}

.lshostel-dashsettings > summary:focus-visible {
	outline: 2px solid var(--hs-primary-600);
	outline-offset: 2px;
}

.lshostel-dashsettings__list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
	gap: var(--hs-space-2);
	margin: var(--hs-space-3) 0;
}

.lshostel-dashsettings__item {
	display: flex;
	align-items: center;
	gap: var(--hs-space-2);
	padding: var(--hs-space-2) var(--hs-space-3);
	border: var(--hs-border);
	border-radius: var(--hs-radius);
	background: #fff;
	cursor: pointer;
}

.lshostel-dashsettings__item:hover { background: var(--hs-primary-50); }

@media screen and (max-width: 782px) {
	.lshostel-dashsettings__list { grid-template-columns: minmax(0, 1fr); }
}

@media (forced-colors: active) {
	.lshostel-dashsettings,
	.lshostel-dashsettings__item { border: 1px solid CanvasText; }
}

/* An inline form, so a Download PDF button sits on its own line without the
   block margin a full form carries. */
.lshostel-form--inline { display: inline-block; margin: 0 0 var(--hs-space-4); }

/* A settings form drawn as a table. The label column is fixed so the controls
   line up down the page, and the value column takes what is left. */
.lshostel-formtable th {
	width: 16rem;
	vertical-align: top;
	font-weight: 600;
}

.lshostel-formtable td { vertical-align: top; }

.lshostel-formtable input[type="text"],
.lshostel-formtable input[type="email"],
.lshostel-formtable input[type="tel"],
.lshostel-formtable input[type="url"],
.lshostel-formtable input[type="number"],
.lshostel-formtable textarea,
.lshostel-formtable select { max-width: 100%; }

@media screen and (max-width: 782px) {
	/*
	 * Label above control rather than beside it. A 16rem label column inside a
	 * 343px screen leaves 5rem for the input.
	 */
	.lshostel-formtable th,
	.lshostel-formtable td { display: block; width: auto; }
	.lshostel-formtable th { border-bottom: 0; padding-bottom: 0; }
}

/* ------------------------------------------------------- figure cards
 *
 * A row of small totals: charged, paid, discounted, refunded, balance. These
 * were emitted with no rules behind them at all, so the Money screen showed
 * five stacked divs of unstyled text where five cards were intended. Found by
 * pms-test/stylesheet-scope-check.py, which asks whether every class a screen
 * emits has a rule in the stylesheet that screen actually loads.
 * ------------------------------------------------------------------------ */

.lshostel-cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
	gap: var(--hs-space-3);
	margin: 0 0 var(--hs-space-5);
}

.lshostel-card {
	display: flex;
	flex-direction: column;
	gap: var(--hs-space-1);
	padding: var(--hs-space-3) var(--hs-space-4);
	border: var(--hs-border);
	border-left: 3px solid var(--hs-primary-500);
	border-radius: var(--hs-radius);
	background: #fff;
	box-shadow: var(--hs-shadow-sm);
}

.lshostel-card-label {
	font-size: 0.75rem;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--hs-neutral-600);
}

.lshostel-card-value {
	font-size: 1.15rem;
	font-weight: 700;
	color: var(--hs-neutral-800);
	/* Figures line up down the column, so two amounts can be compared at a
	   glance rather than read digit by digit. */
	font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------- screen receipt
 *
 * The on-screen version of what the PDF prints. Bounded rather than full
 * width, because a receipt read across 1920 pixels is a receipt nobody can
 * check against the paper one.
 * ------------------------------------------------------------------------ */

.lshostel-receipt {
	max-width: 44rem;
	padding: var(--hs-space-5);
	border: var(--hs-border);
	border-radius: var(--hs-radius-lg);
	background: #fff;
	box-shadow: var(--hs-shadow-sm);
}

.lshostel-receipt h2 { margin: 0 0 var(--hs-space-1); font-size: 1.25rem; }
.lshostel-receipt > p { margin: 0 0 var(--hs-space-4); color: var(--hs-neutral-600); }

@media (forced-colors: active) {
	.lshostel-card,
	.lshostel-receipt { border: 1px solid CanvasText; }
	.lshostel-card { border-left-width: 3px; }
}

/* ------------------------------------------------------- recommended method
 *
 * The method, its standing and its readiness on one line and visibly three
 * things. A warden who reads "Online Payment, recommended" and then hands the
 * resident nothing to pay into has been told two facts at once and only one of
 * them was true.
 * ---------------------------------------------------------------------- */

.lshostel-method {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-3);
}

.lshostel-method__name {
	font-size: 1.15rem;
	font-weight: 700;
	color: var(--hs-neutral-800);
}

/* The hostel's own sentence about paying, set apart from the surrounding
   explanation because it is the part a warden reads out loud. */
.lshostel-instructions {
	padding: var(--hs-space-3) var(--hs-space-4);
	border-left: 3px solid var(--hs-primary-500);
	border-radius: var(--hs-radius);
	background: var(--hs-primary-50);
	font-weight: 600;
	color: var(--hs-neutral-800);
}

@media (forced-colors: active) {
	.lshostel-instructions { border-left: 3px solid CanvasText; }
}

/* ------------------------------------------------------------- masthead now
 *
 * The date, the hostel's clock and whose clock it is. The timezone is named
 * rather than assumed: a hostel in Dar es Salaam may be administered from
 * anywhere, and a bare time is whichever clock the reader happens to guess.
 * ---------------------------------------------------------------------- */

.lshostel-masthead {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--hs-space-4);
}

.lshostel-masthead__identity { min-width: 0; }

.lshostel-masthead__now {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 2px;
	margin-left: auto;
	text-align: right;
}

.lshostel-masthead__date {
	font-size: 0.85rem;
	color: var(--hs-neutral-600);
}

.lshostel-masthead__time {
	font-size: 1.35rem;
	font-weight: 700;
	line-height: 1;
	color: var(--hs-primary-700);
	/* Digits keep their column as the minute changes, so the clock does not
	   shuffle the text beside it once a minute. */
	font-variant-numeric: tabular-nums;
}

.lshostel-masthead__zone {
	font-size: 0.72rem;
	letter-spacing: 0.03em;
	color: var(--hs-neutral-500);
}

.lshostel-masthead__user {
	display: flex;
	align-items: center;
	gap: var(--hs-space-3);
}

.lshostel-masthead__alerts {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: var(--hs-space-1);
	padding: var(--hs-space-1) var(--hs-space-2);
	border-radius: var(--hs-radius);
	color: var(--hs-neutral-600);
	text-decoration: none;
}

.lshostel-masthead__alerts:hover,
.lshostel-masthead__alerts:focus-visible { background: var(--hs-neutral-50); color: var(--hs-primary-700); }

.lshostel-masthead__count {
	min-width: 1.5rem;
	padding: 0 var(--hs-space-1);
	border-radius: 999px;
	background: var(--hs-neutral-200);
	color: var(--hs-neutral-700);
	font-size: 0.75rem;
	font-weight: 700;
	text-align: center;
}

/* Amber only when there is actually something in it. A permanently coloured
   badge is furniture; one that changes is a signal. */
.lshostel-masthead__count.is-active { background: var(--hs-warning-500); color: #fff; }

.lshostel-masthead__who {
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--hs-neutral-700);
}

@media screen and (max-width: 782px) {
	.lshostel-masthead { flex-direction: column; align-items: stretch; }
	.lshostel-masthead__now { align-items: flex-start; margin-left: 0; text-align: left; }
	.lshostel-masthead__user { justify-content: flex-start; }
}

@media (forced-colors: active) {
	.lshostel-masthead__count { border: 1px solid CanvasText; }
}

/* ------------------------------------------------------ occupancy by room
 *
 * A hostel average hides the thing a warden needs. "40% occupied" across
 * fourteen rooms is consistent with four full rooms and ten empty ones, and
 * with every room being a little under half. Those are different hostels to
 * run, so each room gets its own line.
 *
 * Every room is listed, including the empty ones: a chart showing only rooms
 * with residents in them would be a chart of where people are, under a heading
 * about where beds are.
 * ---------------------------------------------------------------------- */


.lshostel-roombars {
	display: grid;
	gap: var(--hs-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.lshostel-roombar {
	display: grid;
	grid-template-columns: 3.5rem minmax(0, 1fr) 4.5rem;
	align-items: center;
	gap: var(--hs-space-3);
}

.lshostel-roombar__code {
	font-weight: 700;
	font-size: 0.9rem;
	color: var(--hs-neutral-700);
}

.lshostel-roombar__track {
	position: relative;
	display: block;
	height: 14px;
	border-radius: 999px;
	background: var(--hs-neutral-100);
	overflow: hidden;
}

.lshostel-roombar__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: var(--hs-primary-500);
	/* A room with nobody in it draws nothing rather than a sliver, so an empty
	   room is visibly empty instead of looking like a rounding error. */
	min-width: 0;
}

.lshostel-roombar__figure {
	font-size: 0.85rem;
	color: var(--hs-neutral-600);
	font-variant-numeric: tabular-nums;
	text-align: right;
}

@media screen and (max-width: 600px) {
	.lshostel-roombar { grid-template-columns: 3rem minmax(0, 1fr) 4rem; gap: var(--hs-space-2); }
}

@media (forced-colors: active) {
	.lshostel-roombar__track { border: 1px solid CanvasText; }
	.lshostel-roombar__fill { background: Highlight; }
}

/* A sentence under a chart that qualifies what the chart does not show —
   money that belongs to no room, a range that excludes something. It is not a
   caption: the chart is complete without it and wrong without it being said. */
/* ------------------------------------------------------ room intelligence
 *
 * A card per room rather than eleven columns against fourteen rows. The
 * questions asked here are about ONE room at a time — how full is 07, what does
 * 03 owe — and a table wide enough to answer them has to scroll sideways on
 * anything smaller than a laptop.
 */
.lshostel-roomcards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
	gap: var(--hs-space-3);
	margin: 0 0 var(--hs-space-4);
}

.lshostel-roomcard {
	border: 1px solid var(--hs-neutral-200);
	border-radius: var(--hs-radius-lg);
	background: #fff;
	padding: var(--hs-space-4);
	/* Stops a long figure forcing the column wider than its grid track. */
	min-width: 0;
}

.lshostel-roomcard__code {
	margin: 0 0 var(--hs-space-3);
	font-size: 0.95rem;
	font-weight: 700;
	color: var(--hs-neutral-800);
}

.lshostel-roomcard__beds,
.lshostel-roomcard__money {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(76px, 1fr));
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-3);
}

.lshostel-roomcard__stat { min-width: 0; }

.lshostel-roomcard__stat dt {
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--hs-neutral-500);
}

.lshostel-roomcard__stat dd {
	margin: 2px 0 0;
	font-size: 1rem;
	font-weight: 700;
	color: var(--hs-neutral-800);
	font-variant-numeric: tabular-nums;
	/* A money figure wraps rather than widening the card. */
	overflow-wrap: anywhere;
}

.lshostel-roomcard__label {
	margin: 0 0 4px;
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--hs-neutral-500);
}

.lshostel-roomcard__meter {
	height: 8px;
	border-radius: 999px;
	background: var(--hs-neutral-100);
	overflow: hidden;
}

.lshostel-roomcard__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: var(--hs-primary-500);
}

.lshostel-roomcard__reading {
	margin: 4px 0 var(--hs-space-3);
	font-size: 0.78rem;
	line-height: 1.5;
	color: var(--hs-neutral-600);
}

/*
 * The sentence that replaces a meter when there is nothing to measure. It is
 * deliberately NOT a bar at nought: a bar at nought for a room with no lettable
 * bed looks exactly like a bar at nought for a room that is empty, and those
 * are different facts.
 */
.lshostel-roomcard__none {
	margin: 0 0 var(--hs-space-3);
	font-size: 0.78rem;
	line-height: 1.5;
	color: var(--hs-neutral-500);
	font-style: italic;
}

@media (forced-colors: active) {
	.lshostel-roomcard__meter { border: 1px solid CanvasText; }
	.lshostel-roomcard__fill { background: Highlight; }
}

/* --------------------------------------------------------- a custom range
 *
 * Two dates and a button, on one line where there is room and stacked where
 * there is not. A hostel bills by the month and its terms do not begin on the
 * first, so the named periods above cannot express the range a warden most
 * often wants.
 */
.lshostel-rangeform {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-4);
}

.lshostel-rangeform label {
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--hs-neutral-600);
}

.lshostel-rangeform input[type="date"] {
	min-height: var(--tl-touch, 44px);
	padding: 0 var(--hs-space-2);
	border: 1px solid var(--hs-neutral-300);
	border-radius: var(--hs-radius);
	background: #fff;
	color: var(--hs-neutral-800);
	font-size: 0.9rem;
	/* So a narrow phone stacks the fields instead of pushing the page sideways. */
	min-width: 0;
	max-width: 100%;
}

.lshostel-note {
	margin: var(--hs-space-3) 0 0;
	max-width: 74ch;
	font-size: 0.85rem;
	line-height: 1.55;
	color: var(--hs-neutral-600);
}

/* --------------------------------------------------------- bed actions
 *
 * What can be done to one bed, laid out as a row of controls rather than a
 * menu. The list depends on the bed's state, because a row of buttons that
 * mostly produce refusals teaches a warden to ignore the row.
 * ---------------------------------------------------------------------- */

.lshostel-bedactions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--hs-space-2);
	margin: 0 0 var(--hs-space-5);
}

.lshostel-bedactions .lshostel-form--inline { margin: 0; }

.lshostel-room__more {
	margin: var(--hs-space-3) 0 0;
	padding-top: var(--hs-space-3);
	border-top: var(--hs-border);
	font-size: 0.9rem;
}

@media screen and (max-width: 600px) {
	/* Full-width controls on a phone: a row of small buttons at 343px puts two
	   words on each and wraps the third onto its own line anyway. */
	.lshostel-bedactions { flex-direction: column; align-items: stretch; }
	.lshostel-bedactions .button { width: 100%; text-align: center; }
	.lshostel-bedactions .lshostel-form--inline { display: block; }
}
