/**
 * Console-only styles, split out of profile.css.
 *
 * profile.css is enqueued on public pages too - the practice profile, the
 * booking confirmation, the complaint form, the ROI calculator - and 43% of
 * it was rules only the practice console and the signed-in account can ever
 * match. That was 47KB of render-blocking CSS on the site's most-linked page
 * type, for selectors those pages carry no elements for.
 *
 * What stayed behind, deliberately: everything scoped to .vb-account,
 * .vb-callback, .vb-otp and the profile/booking/review components. The
 * SIGNED-OUT account page carries the .vb-account wrapper, so those rules
 * are public rules whatever their name suggests.
 *
 * This file loads AFTER profile.css wherever the console renders, so within
 * the console the cascade order is unchanged relative to itself; console
 * rules only move later relative to public ones, which raises them where
 * they tie. That was checked against a 103-element computed-style
 * fingerprint taken across 24 page/width combinations before the split.
 *
 * @package VetBook
 */

/* Subscription panel (P5). */
.vb-subscription__payment {
	margin: 14px 0;
	padding: 16px 18px;
	background: var(--vb-base, #fbf7f2);
	border: 1px dashed var(--vb-primary, #b66a80);
	border-radius: var(--vb-radius-sm, 11px);
}


.vb-subscription__bank {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 6px 16px;
	margin: 0;
}


.vb-subscription__bank dt {
	font-weight: 600;
	color: var(--vb-muted, #6b5b60);
}


.vb-subscription__bank dd {
	margin: 0;
}


.vb-subscription__reference {
	font-size: 1.1rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	user-select: all;
}


.vb-subscription__note {
	margin: 12px 0 0;
	font-size: var(--vb-text-label, 0.9rem);
	color: var(--vb-muted, #6b5b60);
}


.vb-subscription__op {
	margin-top: 12px;
}


.vb-subscription__opbtn {
	padding: 9px 18px;
	font: inherit;
	font-weight: 600;
	color: var(--vb-accent-text, #68192e);
	background: transparent;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-sm, 11px);
	cursor: pointer;
}


.vb-subscription__opbtn:hover {
	background: var(--vb-primary-soft, #f3e2e7);
	border-color: var(--vb-primary, #b66a80);
}


/* AFTER the base on purpose: same 0-1-0 specificity, so source order is the
   whole mechanism. Written before the base, this red family was silently
   clobbered by the base's `color` and `border:` shorthand - the css hook
   caught exactly that. */
.vb-subscription__opbtn--withdraw,
.vb-subscription__opbtn--cancel {
	color: var(--vb-danger-text-strong, #b52216);
	border-color: rgba( 207, 34, 46, 0.7 );
}


.vb-subscription__opbtn--withdraw:hover,
.vb-subscription__opbtn--cancel:hover {
	color: #fff;
	background: #cf222e;
	border-color: var(--vb-danger-text-strong, #b52216);
}


/* ===== Dashboard tabs + cards (shared: practice console + account) ========= */
/* The console carries 22 sections. As one wrapping row of pills that is four
   rows of undifferentiated ovals, and the reader has to read all 22 to find
   one. Grouped into three labelled blocks it is three short scans, and the
   label can no longer be separated from the tabs it belongs to. */
@media ( min-width: 67.5rem ) {
	/* Side by side once all three groups fit: Daily work is the one used all
	   day, so it gets the room and the others sit beside it. */
}






/* No-JS fallback: every panel shows, separated by a labelled heading. */
/* Focused panel keeps a visible indicator (WCAG 2.4.7); :focus-visible
   spares mouse users the ring while keeping it for keyboard activation. */
/* ==========================================================================
   Day view (Task 20) — practice console agenda for one local day.
   ========================================================================== */
.vb-day__nav {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0 0 0.75rem;
}

.vb-day__nav-btn {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
	padding: 0.4rem 0.85rem;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-surface, #f2e7df);
	color: var(--vb-ink, #30272b);
	text-decoration: none;
	font-size: var(--vb-text-label, 0.9rem);
	line-height: 1.2;
}

.vb-day__nav-btn:hover {
	border-color: var(--vb-accent-text, #68192e);
	color: var(--vb-accent-text, #68192e);
}

.vb-day__nav-today {
	background: var(--vb-primary-soft, #f3e2e7);
	border-color: var(--vb-accent-text, #68192e);
	color: var(--vb-accent-text, #68192e);
}

.vb-day__heading {
	margin: 0 0 0.85rem;
	font-weight: 600;
	color: var(--vb-ink, #30272b);
	text-transform: capitalize;
}

.vb-day__jump {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin: 0 0 1rem;
}

.vb-day__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

/* Inline status ops (console-live.js): confirm flash, blocker exit. */
@keyframes vb-row-updated {
	0% { background: var(--vb-success-soft, #e6f3ea); }
	100% { background: transparent; }
}


.vb-day__item.is-updated {
	animation: vb-row-updated 0.9s ease-out;
}


.vb-day__item.is-leaving {
	opacity: 0;
	transform: translateX(8px);
	transition: opacity 0.3s ease, transform 0.3s ease;
}


.vb-day__inline-error {
	font-size: var(--vb-text-small, 0.85rem);
	color: var(--vb-danger-text, #b52216);
	font-weight: 600;
}


@media (prefers-reduced-motion: reduce) {
	.vb-day__item.is-updated {
		animation: none;
	}

	.vb-day__item.is-leaving {
		transition: none;
	}
}


.vb-day__item {
	display: flex;
	align-items: flex-start;
	gap: 0.85rem;
	padding: 0.7rem 0.85rem;
	border: 1px solid var(--vb-line, #d9c7c1);
	border-left: 4px solid var(--vb-primary, #b66a80);
	border-radius: var(--vb-radius-sm, 11px);
	background: var(--vb-surface, #f2e7df);
}

/* The status bar colour travels as a custom property rather than as
   border-left-color directly. Three separate rules in this file set that
   border - the base row, a transparent 1px frame and a later rewrite - and
   whichever landed last silently switched the colour coding off. A variable
   has exactly one consumer, so there is nothing left to win the argument. */
 /* De-emphasis used to be `opacity` on the whole row, and opacity does not
   discriminate: it faded the status chip along with everything else. The
   chip's own #c0392b on #fbeae7 measures 4.67:1 standing alone and 2.93:1
   seen through opacity 0.7 - the token promised a pass and the container
   quietly spent it. What marks a cancelled row is the left bar, the chip
   and the struck-through time; none of that needs the text dimmed.
   The bars take the status roles, so they turn with the scheme and keep
   3:1 on every row ground (#408, review of #409). */
.vb-day__item--cancelled {
	--vb-day-bar: var(--vb-danger-text-strong, #b52216);
}

.vb-day__item--cancelled .vb-day__time,
.vb-day__item--cancelled .vb-day__who {
	color: var( --vb-muted, #6b5b60 );
	text-decoration: line-through;
}

.vb-day__item--noshow {
	--vb-day-bar: var(--vb-muted, #6b5b60);
}

.vb-day__item--noshow .vb-day__time,
.vb-day__item--noshow .vb-day__who {
	color: var( --vb-muted, #6b5b60 );
}

.vb-day__item--done {
	--vb-day-bar: var(--vb-success, #176849);
}

.vb-day__item--pending {
	--vb-day-bar: var(--vb-warn-text, #86520a);
}

.vb-day__time {
	flex: 0 0 auto;
	min-width: 5.5ch;
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	color: var(--vb-ink, #30272b);
}

.vb-day__body {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	flex: 1 1 auto;
	min-width: 0;
}

.vb-day__who {
	font-weight: 600;
}

.vb-day__meta,
.vb-day__note {
	font-size: var(--vb-text-label, 0.9rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-day__note {
	font-style: italic;
}

.vb-day__status {
	flex: 0 0 auto;
	align-self: center;
	padding: 0.15rem 0.6rem;
	border-radius: var(--vb-radius-pill, 999px);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	background: var(--vb-primary-soft, #f3e2e7);
	color: var(--vb-accent-text, #68192e);
	white-space: nowrap;
}

.vb-day__status--cancelled {
	background: var(--vb-danger-soft, #ffece6);
	color: var(--vb-danger-text, #b52216);
}

.vb-day__status--pending {
	background: var(--vb-warn-soft, #fff0d8);
	color: var(--vb-warn-text, #86520a);
}

.vb-day__status--noshow {
	background: var(--vb-neutral-soft, #efe9e6);
	color: var(--vb-neutral-ink, #6b5f4e);
}

.vb-day__status--done {
	background: var(--vb-neutral-soft, #efe9e6);
	color: var(--vb-muted, #6b5b60);
}

.vb-day__deposit {
	flex: 0 0 auto;
	align-self: center;
	padding: 0.15rem 0.6rem;
	border-radius: var(--vb-radius-pill, 999px);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	white-space: nowrap;
	background: var(--vb-warn-soft, #fff0d8);
	color: #b7791f;
}

.vb-day__deposit--completed {
	background: var(--vb-success-soft, #e6f3ea);
	color: var(--vb-success, #176849);
}

.vb-day__deposit--refunded {
	background: #eef1f0;
	color: var(--vb-muted, #6b5b60);
}

/* Day-view visit-reason answers (Task 32). */
.vb-day__answers {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	margin-top: 0.15rem;
}

.vb-day__qa {
	font-size: var(--vb-text-small, 0.85rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-day__q {
	font-weight: 600;
	color: var(--vb-ink, #30272b);
}


/* Day-view status actions (Task 35). */
.vb-day__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
	align-self: center;
}

.vb-day__action {
	padding: 0.3rem 0.7rem;
	font-size: var(--vb-text-small, 0.85rem);
	border-radius: var(--vb-radius-pill, 999px);
	border: 1px solid var(--vb-line, #d9c7c1);
	background: var(--vb-surface, #f2e7df);
	color: var(--vb-ink, #30272b);
	cursor: pointer;
	line-height: 1.2;
}

.vb-day__action:hover {
	border-color: var(--vb-primary, #b66a80);
}

/* (The one-class --cancelled:hover that used to sit here was dead: beaten
   by the two-class quiet rule at any hover, and superseded by the two-class
   red hover further down.) */

@media (max-width: 30rem) {
	.vb-day__actions {
		align-self: flex-start;
		width: 100%;
	}
}


/* Practice settings: opening-hours grid + badges (SUB-1). */
.vb-hours {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	margin: 0.25rem 0 0.5rem;
}

.vb-hours__row {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-wrap: wrap;
}

.vb-hours__day {
	flex: 0 0 8rem;
	font-weight: 600;
}

.vb-hours__row input[type="time"] {
	/* flex: 0 0 auto resolves its basis from the width property, and the
	   generic console rule sets width: 100% - with flex-shrink: 0 on top,
	   each of the fourteen time fields claimed a whole row and the opening
	   hours editor broke into three lines per day. Same trap already patched
	   by hand for the day view's date and delay controls; this one was
	   missed. An explicit width is the fix, not a bigger selector. */
	flex: 0 0 auto;
	width: auto;
	min-width: 7.5rem;
	max-width: 100%;
}

.vb-settings__badges {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 1.25rem;
}

@media (max-width: 30rem) {
	.vb-hours__day {
		flex-basis: 100%;
	}
}

@media print {
	.vb-week__grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
	.vb-week__col { border: 1px solid #ccc; }
}


/* ===== 1:1 messages (account tab + practice console) ====================== */















/* ===== Day-view move mode (drag & drop reschedule) ========================= */
.vb-day__item[draggable="true"] {
	cursor: grab;
}

.vb-day__item.is-moving {
	outline: 2px solid var(--vb-accent-text, #68192e);
	outline-offset: 2px;
	border-radius: var(--vb-radius-sm, 11px);
}

.vb-day__movebtn {
	font: inherit;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	padding: 4px 10px;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-xs, 6px);
	background: var(--vb-base, #fbf7f2);
	cursor: pointer;
	margin-right: 8px;
}

.vb-day__movebtn:hover {
	border-color: var(--vb-primary, #b66a80);
	color: var(--vb-accent-text, #68192e);
}

.vb-day__movepanel {
	margin: 14px 0;
	padding: 16px;
	border: 1.5px dashed var(--vb-primary, #b66a80);
	border-radius: var(--vb-radius, 16px);
	background: rgba(104, 25, 46, 0.06);
}

.vb-day__movehint {
	margin: 0 0 10px;
	font-weight: 600;
}

.vb-day__movegroup {
	margin-bottom: 10px;
}

.vb-day__movedate {
	margin: 0 0 6px;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	color: var(--vb-muted, #6b5b60);
}

.vb-day__moveslot {
	font: inherit;
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
	font-feature-settings: "tnum";
	margin: 0 6px 6px 0;
	padding: 7px 12px;
	border: 1.5px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-sm, 11px);
	background: var(--vb-base, #fbf7f2);
	cursor: pointer;
	transition: 0.15s;
}

.vb-day__moveslot:hover,
.vb-day__moveslot.is-over {
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
	color: #fff;
	transform: translateY(-1px);
}

.vb-day__movecancel {
	font: inherit;
	font-size: var(--vb-text-small, 0.85rem);
	background: none;
	border: 0;
	color: var(--vb-muted, #6b5b60);
	text-decoration: underline;
	cursor: pointer;
}


/* ----- Patients tab: search + pager ---------------------------------------- */
.vb-patients__search {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0 0 10px;
}


.vb-patients__search input[type="search"] {
	flex: 1 1 240px;
	padding: 0.55rem 0.8rem;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-sm, 11px);
	font: inherit;
}


.vb-patients__search button {
	padding: 0.55rem 1.1rem;
	border: 0;
	border-radius: var(--vb-radius-sm, 11px);
	background: var(--vb-primary-dark, #68192e);
	color: #fff;
	font-weight: 600;
	cursor: pointer;
}


.vb-patients__reset {
	font-size: var(--vb-text-label, 0.9rem);
}


.vb-patients__pager {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-top: 14px;
}


/* ----- Tab group labels (console IA: daily / setup / business) -------------- */
/* ----- Refill requests ------------------------------------------------------ */
.vb-refills {
	list-style: none;
	margin: 12px 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 10px;
}


.vb-refills__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 14px;
	padding: 12px 14px;
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius, 16px);
	background: var(--vb-base, #fbf7f2);
}


.vb-refills__item {
	flex: 1 1 240px;
}


.vb-refills__status {
	flex: 0 0 auto;
	padding: 0.2rem 0.7rem;
	border-radius: var(--vb-radius-pill, 999px);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	background: #eef1f0;
	color: var(--vb-muted, #6b5b60);
}


.vb-refills__status--requested {
	background: var(--vb-warn-soft, #fff0d8);
	color: var(--vb-warn-text, #86520a);
}


.vb-refills__status--approved {
	background: var(--vb-success-soft, #e6f3ea);
	color: var(--vb-success, #176849);
}


.vb-refills__status--ready {
	background: var(--vb-success-fill, #176849);
	color: #fff;
}


.vb-refills__status--declined {
	background: var(--vb-danger-soft, #ffece6);
	color: var(--vb-danger-text, #b52216);
}


.vb-refills__actions {
	display: flex;
	gap: 6px;
}


/* Same chip language as the day-view actions: a quiet row of equals, colour
   only when you point at one. Three permanently coloured chips per request
   row were louder than the panel's actual primary. */
.vb-refills__action {
	padding: 0.4rem 0.8rem;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-sm, 11px);
	background: var(--vb-base, #fbf7f2);
	color: var(--vb-ink, #30272b);
	font-weight: 600;
	cursor: pointer;
}


.vb-refills__action--approved:hover,
.vb-refills__action--ready:hover {
	color: #fff;
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
}


/* Declining is the red family - it must never green up on hover. */
.vb-refills__action--declined:hover {
	color: #fff;
	background: #c0392b;
	border-color: var(--vb-danger-text, #b52216);
}


/* ----- Day view: check-in badge + delay broadcast ---------------------------- */
.vb-day__checkin {
	flex: 0 0 auto;
	align-self: center;
	padding: 0.15rem 0.6rem;
	border-radius: var(--vb-radius-pill, 999px);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	/* Checked in and not yet waiting long: a good state, so green (#408) -
	   the longer waits take the warning and error roles below. */
	background: var(--vb-success-fill, #176849);
	color: #fff;
	white-space: nowrap;
}


.vb-day__delay {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0 0 12px;
	padding: 8px 12px;
	border: 1px dashed var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius, 16px);
	font-size: var(--vb-text-label, 0.9rem);
}


.vb-day__delay select {
	padding: 0.3rem 0.5rem;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-sm, 11px);
}


.vb-day__delay button {
	padding: 0.4rem 0.9rem;
	border: 1px solid #96620a;
	border-radius: var(--vb-radius-sm, 11px);
	background: var(--vb-base, #fbf7f2);
	color: var(--vb-warn-text, #86520a);
	font-weight: 600;
	cursor: pointer;
}


.vb-day__delay button:hover {
	background: #96620a;
	color: #fff;
}


/* ----- Team logins ------------------------------------------------------------ */
.vb-teamaccess {
	list-style: none;
	margin: 12px 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}


.vb-teamaccess__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 14px;
	padding: 10px 14px;
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius, 16px);
	background: var(--vb-base, #fbf7f2);
}


.vb-teamaccess__who {
	flex: 1 1 240px;
}


.vb-teamaccess__role {
	padding: 0.2rem 0.7rem;
	border-radius: var(--vb-radius-pill, 999px);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
}


/* A role label is information, not an action - the owner badge in filled
   green outshone the panel's actual controls. Same chip family as --team,
   one step darker so the two roles still read apart at a glance. */
.vb-teamaccess__role--owner {
	background: var(--vb-primary-soft, #f3e2e7);
	color: var(--vb-primary-darker, #300b17);
}


.vb-teamaccess__role--team {
	background: #eef1f0;
	color: var(--vb-muted, #6b5b60);
}


.vb-teamaccess__remove {
	background: transparent;
	border: 1px solid var(--vb-danger-text, #b52216);
	color: var(--vb-danger-text, #b52216);
	padding: 0.35rem 0.8rem;
	border-radius: var(--vb-radius-sm, 11px);
	font-weight: 600;
	cursor: pointer;
}


.vb-teamaccess__remove:hover {
	background: #c0392b;
	color: #fff;
}


.vb-teamaccess__cred code {
	user-select: all;
	font-size: 1.02em;
}


/* Practice console — Statistics panel (audit 6.8) */
.vb-stats__kpis {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
	gap: 12px;
	margin: 16px 0 24px;
}

.vb-stats__kpi {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 14px 16px;
	background: var(--vb-surface, #f2e7df);
	border: 1px solid var(--vb-border, #d9c7c1);
	border-radius: var(--vb-radius-sm, 11px);
}

.vb-stats__kpi-label {
	font-size: var(--vb-text-small, 0.85rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-stats__kpi-value {
	font-size: 1.5rem;
	font-weight: 700;
	color: var(--vb-ink, #30272b);
	line-height: 1.1;
}

.vb-stats__table-wrap {
	overflow-x: auto;
	margin-bottom: 24px;
}

.vb-stats__table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--vb-text-label, 0.9rem);
}

.vb-stats__table th,
.vb-stats__table td {
	padding: 8px 10px;
	text-align: right;
	border-bottom: 1px solid var(--vb-border, #d9c7c1);
	white-space: nowrap;
}

.vb-stats__table th:first-child,
.vb-stats__table td:first-child {
	text-align: left;
}

.vb-stats__table thead th {
	color: var(--vb-muted, #6b5b60);
	font-weight: 600;
}

.vb-stats__bars {
	list-style: none;
	margin: 8px 0 24px;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.vb-stats__bar-row {
	display: grid;
	grid-template-columns: minmax(120px, 1fr) 2fr auto;
	align-items: center;
	gap: 12px;
}

.vb-stats__bar-label {
	font-size: var(--vb-text-label, 0.9rem);
	color: var(--vb-ink, #30272b);
}

.vb-stats__bar-track {
	position: relative;
	height: 10px;
	background: var(--vb-border, #d9c7c1);
	border-radius: var(--vb-radius-pill, 999px);
	overflow: hidden;
}

.vb-stats__bar-fill {
	position: absolute;
	inset: 0 auto 0 0;
	/* Die Balkenlänge IST die Aussage - Bedeutung ohne Text, also 3:1. */
	background: var(--vb-accent-text, #68192e);
	border-radius: var(--vb-radius-pill, 999px);
}

.vb-stats__bar-value {
	font-variant-numeric: tabular-nums;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-label, 0.9rem);
}


/* ATTR-1 — per-channel booking links */
.vb-embed__srclinks { list-style: none; padding: 0; margin: 8px 0 16px; display: flex; flex-direction: column; gap: 6px; }

.vb-embed__srclinks li { display: grid; grid-template-columns: minmax(140px, auto) 1fr; align-items: center; gap: 10px; }

.vb-embed__srclabel { font-size: var(--vb-text-label, 0.9rem); color: var(--vb-muted, #6b5b60); }

.vb-embed__srcinput { width: 100%; padding: 7px 10px; border: 1px solid var(--vb-field-line, #8c716e); border-radius: var(--vb-radius-xs, 6px); font-size: var(--vb-text-small, 0.85rem); font-family: ui-monospace, monospace; background: var(--vb-surface, #f2e7df); }


/* NOSHOW-1 — confirmation + risk badges */
.vb-day__unconfirmed { display: inline-block; margin-left: 6px; padding: 2px 7px; border-radius: var(--vb-radius-pill, 999px); font-size: var(--vb-text-caption, 0.78rem); font-weight: 700; background: #fff4e5; color: #8a5a00; border: 1px solid #f0c88a; }

.vb-day__noshowrisk { display: inline-block; margin-left: 6px; padding: 2px 7px; border-radius: var(--vb-radius-pill, 999px); font-size: var(--vb-text-caption, 0.78rem); font-weight: 700; border: 1px solid currentColor; }

.vb-day__noshowrisk--medium { background: #fff4e5; color: #8a5a00; }

.vb-day__noshowrisk--high { background: #fdecea; color: #a32116; }


/* --- Overview boards (practice console) ------------------------------- */
.vb-board__title {
	margin: 0 0 14px;
	font-family: var(--vb-display, inherit);
	font-size: 1.2rem;
}

.vb-board__switch {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0 0 18px;
	padding-bottom: 10px;
	border-bottom: 1px solid var(--vb-line, #d9c7c1);
}

.vb-board__tab {
	padding: 7px 15px;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-base, #fbf7f2);
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
	line-height: 1.3;
	text-decoration: none;
	cursor: pointer;
}

.vb-board__tab:hover,
.vb-board__tab:focus-visible {
	border-color: var(--vb-accent-text, #68192e);
	color: var(--vb-ink, #30272b);
}

.vb-board__tab.is-active {
	background: var(--vb-primary-soft, #f3e2e7);
	border-color: var(--vb-primary, #b66a80);
	color: var(--vb-accent-text, #68192e);
}

.vb-board__tab--add {
	border-style: dashed;
}

.vb-board__op {
	display: inline;
}

/* Inbox-zero: a queue at zero is a confirmation, not a card. The slim row
   hands its height back to the window budget; the grip stays for sorting. */
.vb-board__tile--leer {
	flex-direction: row;
	align-items: baseline;
	gap: 8px;
	grid-column: 1 / -1;
	padding: 5px 12px;
}

.vb-board__tile--leer .vb-board__value {
	font-size: var(--vb-text-body, 1rem);
}

.vb-board__tile--leer .vb-board__hint {
	margin-left: auto;
}

.vb-board__tile--leer a:last-child::after {
	border-radius: inherit;
}


/* Peak-time heatmap: single-hue density, no text in the cells (the number
   sits in the title), no second green scale. Length/position stay the
   quantitative channels elsewhere; here density IS the datum. */
.vb-peak {
	margin-top: 18px;
}

.vb-peak__grid {
	display: grid;
	grid-template-columns: auto repeat(7, minmax(0, 1fr));
	gap: 3px;
	align-items: center;
	max-width: 460px;
}

.vb-peak__dow,
.vb-peak__part {
	font-size: var(--vb-text-caption, 0.78rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-peak__dow {
	text-align: center;
}

.vb-peak__part {
	padding-right: 6px;
}

.vb-peak__cell {
	height: 18px;
	border-radius: var(--vb-radius-xs, 6px);
	background: color-mix( in srgb, var(--vb-accent-text, #68192e) calc( var(--vb-peak, 0) * 100% ), var(--vb-surface, #f2e7df) );
}


/* Waiting colour steps (the day-list pattern): the chip ages with
   the wait, in the same tinted-pill families the status chips use. */
.vb-day__checkin--amber {
	background: var(--vb-warn-soft, #fff0d8);
	color: var(--vb-warn-text, #86520a);
}

.vb-day__checkin--rot {
	background: var(--vb-danger-soft, #ffece6);
	color: #a32619;
}


.vb-board__notice--warn {
	border-left-color: #96620a;
	background: var(--vb-warn-soft, #fff0d8);
	color: #6b4d08;
}


/* Callback queue + waitlist: quiet worklists in the tabs they belong to. */
.vb-callbacks__list,
.vb-waitlist__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.vb-callbacks__item,
.vb-waitlist__list li {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 10px;
	padding: 6px 10px;
	border-top: 1px solid var(--vb-line, #d9c7c1);
}

.vb-callbacks__item:first-child,
.vb-waitlist__list li:first-child {
	border-top: 0;
}

.vb-callbacks__who,
.vb-waitlist__who {
	font-weight: 600;
}

.vb-callbacks__phone {
	color: var(--vb-accent-text, #68192e);
	text-decoration: none;
	font-variant-numeric: tabular-nums;
}

.vb-callbacks__note {
	flex: 1 1 100%;
	font-size: var(--vb-text-small, 0.85rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-callbacks__age {
	font-size: var(--vb-text-caption, 0.78rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-callbacks__item form {
	margin-left: auto;
}

.vb-callbacks__item button {
	padding: 4px 12px;
	font-size: var(--vb-text-small, 0.85rem);
}


/* Quiet fact lines above the board (on-call duty, absences): information
   the practice should not have to go looking for. Rendered only while the
   fact holds, so most days they are simply absent. */
.vb-board__notice {
	margin: 0 0 8px;
	padding: 6px 12px;
	font-size: var(--vb-text-small, 0.85rem);
	color: var(--vb-muted, #6b5b60);
	background: var(--vb-surface, #f2e7df);
	border-left: 3px solid var(--vb-field-line, #8c716e);
	border-radius: 0 var(--vb-radius-xs, 6px) var(--vb-radius-xs, 6px) 0;
}


.vb-board__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 12px;
}

.vb-board__tile {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 4px;
	/* Dichte-Entscheid (Superdesign "Dichtes Raster", 25.08.2026): 10/12
	   statt 14/16 - zwoelf Kacheln plus Umschalter bleiben weit unter einem
	   749px-Fenster, ohne dass eine Kachel eng wirkt. */
	padding: 12px 14px;
	/* Widgets on a canvas, not cards in a list: the tinted ground moved to
	   the grid (below) and the tile is the light thing floating on it. A
	   hairline border plus a shadow reads as two separations for one edge,
	   so the border is gone and the shadow does the work alone. */
	background: var(--vb-base, #fbf7f2);
	border: 0;
	border-radius: var(--vb-radius, 16px);
	box-shadow:
		0 1px 2px rgba(48, 39, 43, 0.06 ),
		0 6px 16px -10px rgba(48, 39, 43, 0.22 );
}

.vb-board__label {
	margin: 0;
	padding-right: 22px;
	font-size: var(--vb-text-caption, 0.78rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-board__value {
	margin: 0;
	font-family: var(--vb-display, inherit);
	font-size: 1.25rem;
	font-weight: 700;
	line-height: 1.1;
	color: var(--vb-ink, #30272b);
	/* A leading service name can be long; it wraps rather than overflowing. */
	overflow-wrap: anywhere;
}

.vb-board__hint {
	margin: 0;
	font-size: var(--vb-text-caption, 0.78rem);
	color: var(--vb-muted, #6b5b60);
}

/* One quiet inline line instead of stacked hairline sub-rows: the same
   markup (<li>Abgeschlossen: 8</li> ...) rendered as "Abgeschlossen: 8 ·
   Storniert: 1 · ..." - a third of the height, and the list semantics stay
   intact for screen readers. */
.vb-board__lines {
	margin: 2px 0 0;
	padding: 0;
	list-style: none;
	font-size: var(--vb-text-caption, 0.78rem);
	line-height: 1.45;
	color: var(--vb-muted, #6b5b60);
}

.vb-board__lines li {
	display: inline;
}

.vb-board__lines li + li::before {
	content: " \00b7  ";
}

.vb-board__spark {
	display: block;
	width: 100%;
	height: 26px;
	margin-top: 8px;
	color: var(--vb-accent-text, #68192e);
	/* The line is drawn in a 100x20 box and stretched, so the stroke would
	   thin out horizontally without this. */
	vector-effect: non-scaling-stroke;
}

.vb-board__more {
	margin-top: auto;
	padding-top: 6px;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	color: var(--vb-accent-text, #68192e);
}

/* Above the stretched link, or the drag handle would be unclickable. */
.vb-board__grip {
	position: absolute;
	z-index: 1;
	top: 8px;
	right: 8px;
	width: 28px;
	height: 28px;
	padding: 0;
	border: 0;
	border-radius: var(--vb-radius-xs, 6px);
	background: transparent;
	color: var(--vb-line-strong, #c7b1aa);
	font-size: var(--vb-text-label, 0.9rem);
	line-height: 1;
	cursor: grab;
	/* Without this a touch drag scrolls the page instead of moving the tile. */
	touch-action: none;
}

.vb-board__grip:hover,
.vb-board__grip:focus-visible {
	background: var(--vb-base, #fbf7f2);
	color: var(--vb-accent-text, #68192e);
}


/* Pointer devices only: eight permanent '::' glyphs are chrome, so the grip
   appears when the tile is pointed at or reached by keyboard. On touch there
   is no hover and the grip is the only drag entry - it stays visible. It
   also stays while a keyboard sort is in progress. */
@media (hover: hover) {
	.vb-board__tile .vb-board__grip {
		opacity: 0;
		transition: opacity 0.12s ease;
	}

	.vb-board__tile:hover .vb-board__grip,
	.vb-board__grip:focus-visible,
	.vb-board__grid.is-sorting .vb-board__grip {
		opacity: 1;
	}
}

.vb-board__grid.is-sorting .vb-board__tile {
	transition: transform 120ms ease;
}

.vb-board__tile.is-dragging {
	/* Dropped out of hit testing so elementFromPoint sees the tile beneath. */
	pointer-events: none;
	opacity: 0.9;
	box-shadow: var(--vb-shadow, 0 2px 6px -2px rgba(48, 39, 43, 0.10), 0 18px 40px -26px rgba(48, 39, 43, 0.40));
	transform: scale(1.03);
}

.vb-board__reports {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 12px;
	margin: 16px 0 0;
	font-size: var(--vb-text-small, 0.85rem);
}

.vb-board__reports > span {
	font-weight: 600;
	color: var(--vb-muted, #6b5b60);
}

.vb-board__reports a {
	color: var(--vb-accent-text, #68192e);
	font-weight: 600;
}

.vb-board__csv {
	padding: 2px 9px;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
	font-size: var(--vb-text-caption, 0.78rem);
	text-decoration: none;
}

.vb-board__status {
	margin: 12px 0 0;
	font-size: var(--vb-text-caption, 0.78rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-board__settings {
	margin-top: 18px;
	padding: 14px 16px;
	background: var(--vb-base, #fbf7f2);
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius-sm, 11px);
}

.vb-board__settings > summary {
	font-weight: 600;
	cursor: pointer;
}

.vb-board__field {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 14px 0 0;
}

.vb-board__field input {
	flex: 1 1 200px;
	/* 16px keeps iOS Safari from zooming when the field takes focus. */
	font-size: 16px;
}

.vb-board__choices {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: 6px 18px;
	margin: 12px 0 16px;
	padding: 0;
	list-style: none;
}

.vb-board__choices li {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
}

.vb-board__pos {
	width: 4.5rem;
	font-size: 16px;
}

.vb-board__delete {
	margin-top: 12px;
	border: 0;
	background: none;
	padding: 0;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-small, 0.85rem);
	text-decoration: underline;
	cursor: pointer;
}

@media ( prefers-reduced-motion: reduce ) {
	.vb-board__grid.is-sorting .vb-board__tile { transition: none; }
	.vb-board__tile.is-dragging { transform: none; }
}


/* --- Invite a colleague ------------------------------------------------ */
.vb-refer__field {
	display: flex;
	flex-direction: column;
	gap: 6px;
	margin: 16px 0 0;
}

.vb-refer__field label {
	font-weight: 600;
	font-size: var(--vb-text-label, 0.9rem);
}

.vb-refer__field input,
.vb-refer__field textarea {
	width: 100%;
	/* 16px keeps iOS Safari from zooming when the field takes focus. */
	font-size: 16px;
	font-family: inherit;
}

.vb-refer__field textarea {
	resize: vertical;
}

.vb-refer__stat {
	margin: 20px 0 8px;
	font-weight: 600;
}

.vb-refer__table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--vb-text-label, 0.9rem);
}

.vb-refer__table th,
.vb-refer__table td {
	text-align: left;
	padding: 6px 8px;
	border-bottom: 1px solid var(--vb-line, #d9c7c1);
	vertical-align: top;
}

.vb-refer__table th {
	font-size: var(--vb-text-caption, 0.78rem);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--vb-muted, #6b5b60);
}


/* --- Promoted placement panel ------------------------------------------ */
.vb-sponsor__note {
	font-size: var(--vb-text-label, 0.9rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-sponsor__state {
	margin: 12px 0 0;
	padding: 12px 14px;
	border-radius: var(--vb-radius, 16px);
	border: 1px solid var(--vb-line, #d9c7c1);
	border-left-width: 4px;
}

.vb-sponsor__state.is-on {
	background: linear-gradient(135deg, var(--vb-primary-soft, #f3e2e7), var(--vb-base, #fbf7f2));
	border-color: var(--vb-accent-text, #68192e);
}

/* Paused reads as a warning rather than an error: nothing is broken and the
   practice fixes it by opening a slot, which is what the link goes to. */
.vb-sponsor__state.is-paused {
	background: linear-gradient(135deg, var(--vb-warning-soft, #fff0d8), var(--vb-base, #fbf7f2));
	border-color: var(--vb-gold, #e0a82e);
}

.vb-sponsor__state.is-paused a {
	white-space: nowrap;
}


.vb-sponsor__done {
	margin: 12px 0 0;
	padding: 12px 14px;
	font-weight: 600;
	background: linear-gradient(135deg, var(--vb-primary-soft, #f3e2e7), var(--vb-base, #fbf7f2));
	border: 1px solid var(--vb-accent-text, #68192e);
	border-left-width: 4px;
	border-radius: var(--vb-radius-sm, 11px);
}


/* The attachment block is a quiet footer to the card, not a second form
   competing with it. */
.vb-bdocs {
	margin-top: 4px;
	padding-top: 10px;
	border-top: 1px solid var(--vb-line, #d9c7c1);
	min-width: 0;
}


.vb-bdocs__upload > label {
	flex: 1 0 100%;
	font-size: var(--vb-text-small, 0.85rem);
	font-weight: 400;
}


.vb-bdocs__upload {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 6px 0 0;
	min-width: 0;
}


.vb-bdocs__upload input[type="file"] {
	flex: 1 1 160px;
	min-width: 0;
	font-size: var(--vb-text-small, 0.85rem);
}


.vb-bdocs__upload button {
	flex: 0 0 auto;
	padding: 8px 15px;
	font-size: var(--vb-text-label, 0.9rem);
}


.vb-bdocs__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 6px;
}


.vb-bdocs__list li {
	display: flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
	font-size: var(--vb-text-label, 0.9rem);
}


.vb-bdocs__list a {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
}


/* Arriving from the week view: say which appointment was meant, then let the
   highlight fade so it does not sit there colouring the list forever. */
.vb-day__item:target {
	animation: vb-day-arrive 2.4s ease-out both;
	/* Air only: html's scroll-padding-top keeps the header clear. */
	scroll-margin-top: 12px;
}


.vb-day__item:focus-visible {
	outline: 2px solid transparent;
	box-shadow: var(--vb-focus, 0 0 0 2px var(--vb-raised, #fffcf8), 0 0 0 5px var(--vb-focus-color, #205f9c));
}


@media (prefers-reduced-motion: reduce) {
	.vb-day__item:target {
		animation: none;
		box-shadow: inset 0 0 0 2px var(--vb-accent-text, #68192e);
	}
}


/* ----- Message thread: read it as a conversation -------------------------- */

/* A day marker turns a stack of identically-stamped boxes back into
   something that happened over time. */
/* Consecutive messages from one side are a single turn: tighten them up and
   let only the last of them carry a timestamp. */



.vb-msg__kbd {
	margin: 4px 0 0;
	font-size: var(--vb-text-caption, 0.78rem);
	color: var(--vb-muted, #6b5b60);
}


/* ==========================================================================
   Practice console: density

   This is a tool somebody sits in front of all day, often mid-phone-call. It
   had been dressed as a landing page - large pills, generous padding, a
   filled green button on every action - which cost roughly 450px of screen
   before the first appointment and made everything shout at the same volume.

   The direction here is a quiet worklist: type carries the meaning, chrome
   almost disappears, and green appears on exactly ONE thing per context (the
   section you are in, the action you most likely want). Everything else is
   ink and hairline.
   ========================================================================== */

/* ----- Navigation: quieter and half the height ---------------------------- */



/* Text first, container second. A pill outline around every one of twenty
   sections is twenty boxes to look past. */

/* The one green thing: where you are. */
/* ----- Day view: a worklist, not a stack of cards ------------------------- */

.vb-day__nav,
.vb-dashboard .vb-day__jump,
.vb-dashboard .vb-day__delay {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 8px 10px;
}


.vb-dashboard .vb-day__jump,
.vb-dashboard .vb-day__delay {
	margin: 10px 0 0;
	padding: 0;
	border: 0;
	background: none;
}


.vb-day__jump label,
.vb-day__delay label {
	flex: 0 1 auto;
}


/* A date field is a date wide, and a delay picker is shorter than that.
   Left to flex them out, the date input resolved to 520px and the toolbar
   read as a form. */
.vb-day__jump input[type="date"] {
	flex: 0 0 auto;
	width: 11rem;
	min-width: 0;
	max-width: 100%;
}


.vb-day__delay select {
	flex: 0 0 auto;
	width: auto;
	min-width: 8rem;
	max-width: 100%;
}


.vb-day__heading {
	margin: 14px 0 2px;
	font-size: var(--vb-text-lead, 1.0625rem);
}


.vb-day__list {
	display: grid;
	gap: 4px;
	margin: 12px 0 0;
	padding: 0;
	list-style: none;
}


/* One line per appointment: time, who, what, state, actions. At ~52px a
   full clinic day is one screen instead of five. */
/* Flex, not a fixed three-column grid: a row has either three children
   (time, who, state) or five (a move button before them and an action form
   after), and the fixed grid pushed the extra two onto implicit rows - which
   is why an actionable booking rendered three times the height of a settled
   one, with its own name stranded in the right-hand column. */
.vb-day__item {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 12px;
	padding: 6px 10px;
	/* Three sides only. `border: 1px solid transparent` would also set
	   border-left-color, and so would the `border-left: 3px solid <col>`
	   shorthand - either one resets the status colours declared ~2470 lines
	   above (cancelled red, no-show brown, done grey, pending amber) and
	   every row draws the same bar. That is the one glanceable signal in the
	   list, so the left edge is left alone here and coloured below. */
	border-top: 1px solid transparent;
	border-right: 1px solid transparent;
	border-bottom: 1px solid transparent;
	border-left-width: 3px;
	border-left-style: solid;
	border-left-color: var( --vb-day-bar, var( --vb-accent-text, #68192e ) );
	border-radius: var(--vb-radius-sm, 11px);
	background: var(--vb-surface, #f2e7df);
}


.vb-day__item:nth-child(odd) {
	background: color-mix( in srgb, var(--vb-surface, #f2e7df) 55%, #fff );
}


/* The scan anchor. Tabular numerals so the column stays a column. */
.vb-day__time {
	font-family: var(--vb-display, inherit);
	font-size: var(--vb-text-body, 1rem);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	color: var(--vb-ink, #30272b);
}


.vb-day__body {
	display: flex;
	/* row, explicitly: the original rule ~2470 lines above sets
	   flex-direction: column, and it was never reset here - so the "one line
	   per appointment" this block describes never actually happened. Name,
	   chips and service stacked, and a row was as tall as it had children. */
	flex-direction: row;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 2px 9px;
	/* Takes the middle and pushes state and actions to the right edge, so no
	   auto margins are needed and both row shapes line up the same way. */
	flex: 1 1 240px;
	min-width: 0;
}


.vb-day__time,
.vb-dashboard .vb-day__movebtn {
	flex: 0 0 auto;
}


.vb-day__who {
	font-weight: 600;
	font-size: var(--vb-text-label, 0.9rem);
}


.vb-day__meta,
.vb-day__phone,
.vb-day__note {
	font-size: var(--vb-text-small, 0.85rem);
	color: var(--vb-muted, #6b5b60);
	min-width: 0;
}


/* Chips are chips: they wrap to their content and never stretch into bars.
   Stretched full-width they read as alert banners, so a routine "unconfirmed"
   looked as loud as a real warning. */
.vb-day__status,
.vb-day__unconfirmed,
.vb-day__noshowrisk,
.vb-day__deposit,
.vb-day__checkin {
	flex: 0 0 auto;
	align-self: center;
	width: auto;
	max-width: max-content;
	padding: 2px 8px;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	line-height: 1.5;
	border-radius: var(--vb-radius-pill, 999px);
	white-space: nowrap;
}


/* This one is a <form>, so it has to outrank the generic .vb-dashboard form
   rule rather than merely follow it. */
.vb-dashboard .vb-day__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	align-items: center;
	gap: 4px;
	align-self: center;
	margin: 0;
}


/* Quiet by default. A row of filled buttons makes every option look equally
   urgent, so nothing guides the eye. */
.vb-dashboard .vb-day__action,
.vb-dashboard .vb-day__movebtn {
	padding: 4px 10px;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	line-height: 1.35;
	/* Ink, not green: fifteen rows of green-lettered chips still add up to a
	   green wall. The chips answer with colour on hover; at rest they are
	   labels in a quiet row. */
	color: var(--vb-ink, #30272b);
	background: transparent;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
	transform: none;
	box-shadow: none;
}


.vb-dashboard .vb-day__action:hover,
.vb-dashboard .vb-day__movebtn:hover {
	color: #fff;
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
	transform: none;
	box-shadow: none;
}


/* The destructive one keeps its own hover. At one class the --cancelled rule
   further up could never beat the two-class quiet rule, so Cancel hovered to
   the same filled green as Confirm - the two opposite actions became
   identical at the moment of pointing at one of them. */
.vb-dashboard .vb-day__action--cancelled:hover {
	color: #fff;
	background: #c0392b;
	border-color: var(--vb-danger-text, #b52216);
}


/* Confirm used to be the one filled chip in the row. With the panel's single
   green now living on the promoted "Block slot" button, a green fill per
   pending row would put N green things where the rule allows one - the amber
   status chip already flags the row, the labels say what to do, and the
   generic hover above still answers with green when you point at it. */


/* Below the row: the panels that only appear when asked for. */
.vb-day__movepanel,
.vb-day__qa,
.vb-day__docs {
	flex: 1 1 100%;
	margin-top: 6px;
	padding-top: 8px;
	border-top: 1px dashed var(--vb-line, #d9c7c1);
}


@media ( max-width: 45rem ) {
	.vb-dashboard .vb-day__actions {
		flex: 1 1 100%;
		justify-content: flex-start;
		margin-top: 2px;
	}
}


/* ----- Board: the grips were mine, and they were shouting ---------------- */

/* .vb-board__grip is declared transparent further up; the generic console
   button rule was overriding it into a filled dark-green lozenge on every
   tile - six of the loudest elements on the screen, all of them for a
   secondary affordance. The generic rules are :where()-wrapped now, so the
   component's own declaration wins again. This only tightens the target. */
:where(.vb-dashboard) .vb-board__grip {
	min-height: 0;
	padding: 0;
}


/* A 2.59:1 border does not mark anything for anyone with reduced vision;
   1.4.11 wants 3:1 for the boundary of a control. */
.vb-board__tab.is-active {
	border-color: var(--vb-accent-text, #68192e);
}


/* ----- Board: an even row, a calmer surface, and some life ---------------- */

/* Fixed five-across left six tiles as 5 + 1, which reads as a mistake. Let
   the row fill itself and the remainder distributes instead of dangling. */
.vb-board__grid {
	/* Four columns, not three. In an 840px content column three columns put
	   eight tiles on three rows at 662px, which does not fit a 749px window
	   with the switcher above it; four puts them on two rows at about 420px.
	   The tiles are narrower for it and a long label takes two lines - a fair
	   trade for seeing the whole board without scrolling. */
	grid-template-columns: repeat( auto-fill, minmax( 200px, 1fr ) );
	gap: 10px;
	/* The canvas the widgets sit on. Without it white tiles on a white page
	   would need their border back to be findable at all. */
	padding: 12px;
	background: var(--vb-surface, #f2e7df);
	border-radius: var(--vb-radius-lg, 22px);
}


/* The phone half of the approved density direction: auto-fill with a 200px
   floor collapses a 370px column to ONE tile per row - a tall single-file
   scroll. Two columns hold the density promise; values shrink a step so
   the narrower tiles stay calm rather than cramped. */
@media (max-width: 40rem) {
	.vb-board__grid {
		grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
		gap: 8px;
	}

	.vb-board__grid {
		padding: 8px;
		border-radius: var(--vb-radius, 16px);
	}

	.vb-board__tile {
		padding: 10px 11px;
		border-radius: var(--vb-radius, 16px);
	}

	.vb-board__label {
		font-size: var(--vb-text-caption, 0.78rem);
	}

	.vb-board__value {
		font-size: 1.1rem;
	}

	.vb-board__lines,
	.vb-board__hint {
		/* One breakdown line may truncate on a 180px tile; the full line
		   lives one tap away inside the panel the tile opens. */
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}
}


/* The whole tile IS the link now (stretched-link overlay on the existing
   anchor - no new markup, no JS). The visible "Öffnen" line under every
   tile was eight links doing one link's job; its text now appears only for
   keyboard users, on focus, as a labelled pill. */
.vb-board__tile a:last-child {
	position: static;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	color: var(--vb-accent-text, #68192e);
	text-decoration: none;
}


.vb-board__tile a:last-child::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
}


/* Clip the label, not the anchor: the overlay must keep its full size. */
.vb-board__tile a:last-child span,
.vb-board__tile a:last-child {
	line-height: 1.2;
}


.vb-board__tile a:last-child:not(:focus-visible) {
	/* visually hidden, still focusable - the classic clip pattern, applied
	   to the anchor's inline box while ::after keeps covering the tile. */
	clip-path: inset(50%);
	height: 1px;
	overflow: hidden;
	white-space: nowrap;
}


.vb-board__tile a:last-child:focus-visible {
	clip-path: none;
	height: auto;
	align-self: flex-start;
	padding: 1px 8px;
	background: var(--vb-base, #fbf7f2);
	border-radius: var(--vb-radius-pill, 999px);
}


.vb-board__tile {
	position: relative;
	transition: transform 0.16s ease, box-shadow 0.16s ease;
}


/* Lift, not outline: with the border gone there is no border-color left to
   change, and a deeper shadow is what a raised widget actually looks like. */
.vb-board__tile:hover {
	transform: translateY(-2px);
	box-shadow:
		0 2px 4px rgba(48, 39, 43, 0.08 ),
		0 14px 28px -14px rgba(48, 39, 43, 0.32 );
}


/* The number is the point of the tile: give it the display face and let the
   label above it recede. */
.vb-board__tile strong,
.vb-board__tile b {
	font-family: var(--vb-display, inherit);
	font-variant-numeric: tabular-nums;
	letter-spacing: -0.01em;
}


/* ----- The panel's focus ring is a ring, not a container ----------------- */

/* Focus lands here when a section is opened from the list, which is right -
   but the full double ring drew a heavy box around the whole panel and read
   as chrome. A single hairline says the same thing quietly. */

/* ----- Small screens: the section list folds away --------------------------
   Wrapped, all twenty sections took 396px on a 402px-wide phone - half the
   screen before the first line of work. Collapsed behind a trigger it is one
   row, and opening it shows every section in full: nothing clipped, nothing
   scrolling sideways. */

/* Clipped, not display:none - the control has to stay focusable and stay in
   the accessibility tree, or the picker below has no keyboard path at all.
   It carries the state for the CSS, so it cannot simply be removed. */

@media ( max-width: 67.99rem ) {


	/* Closed by default: the panel heading below already says where you are. */

	/* The focus sits on the clipped checkbox, so the ring has to be drawn on
	   the label that stands in for it - otherwise a keyboard user tabs onto
	   an invisible control. :focus (not only :focus-visible) because the
	   checkbox is reached by Tab, never by pointer. */
}


/* ----- Board: aligned rows, four across -----------------------------------
   The overview used to overflow: three columns put eight tiles on three rows
   at 671px in a 749px window, and grid rows stretch every tile to the
   tallest in the row - 219px of measured emptiness across eight tiles, 107
   of it in one. The first attempt was to stop the stretching, which turned
   out to be the wrong lever: it only moved the gap from inside the tile to
   underneath it, because the row height still follows the tallest tile.

   The column count was the lever. Four across makes it two rows, and with
   four the spread within a row is small enough that aligning the bottoms
   costs almost nothing - so the stretch stays and each row's links share a
   baseline. Compactness came from the columns, not from ragged edges. */
.vb-board__grid {
	align-items: stretch;
}


/* The link sits on the bottom edge again, so a row of tiles shares one
   baseline for its call to action. */
.vb-board__tile > :last-child {
	margin-top: auto;
	padding-top: 6px;
}


.vb-board__tile {
	min-height: 0;
	padding: 12px 14px;
	gap: 3px;
}



/* The number carries the tile; the label above it and the note below can
   both step back a little. */
.vb-board__tile strong,
.vb-board__tile b {
	line-height: 1.1;
}


/* The breakdown rows inside a tile (completed / cancelled / no-show) were
   set at body size, which made a three-row tile twice the height of its
   neighbours for information that is secondary by definition. */
.vb-board__tile dl,
.vb-board__tile ul,
.vb-board__tile .vb-board__rows {
	margin: 4px 0 0;
	font-size: var(--vb-text-caption, 0.78rem);
	line-height: 1.5;
}


/* Third attempt, and the arithmetic is written down this time. The grip
   began as a filled green lozenge (too loud), went to the line colour
   (1.41:1, invisible), then to --vb-muted at opacity 0.55 - and the comment
   claimed 5.8:1 while the opacity actually blended it to #98a59e over the
   tile, i.e. 2.32:1, still under the 3:1 that 1.4.11 asks of a control.
   Opacity is the trap: it silently rewrites the contrast the colour token
   promises. No opacity now, and a colour picked against the tile ground:
   #6b7d74 on #eef6f0 measures 3.97:1. */
.vb-board__grip {
	color: #6b7d74;
	transition: color 0.14s ease;
}


.vb-board__tile:hover .vb-board__grip,
.vb-board__grip:hover,
.vb-board__grip:focus-visible {
	color: var(--vb-accent-text, #68192e);
}


/* ---------------------------------------------------------------------------
   Overview agenda: mini calendar + next appointments (the overview's working
   half). Quiet worklist: the count pills are neutral - a month of green dots
   would be a green wall; the one green in this context is today's ring. */

.vb-agenda {
	margin: 0 0 18px;
}

.vb-agenda__grid {
	display: grid;
	grid-template-columns: 288px minmax(0, 1fr);
	gap: 14px;
	align-items: start;
}

.vb-agenda__cal,
.vb-agenda__list {
	padding: 14px 16px;
	background: var(--vb-base, #fbf7f2);
	border: 0;
	border-radius: var(--vb-radius, 16px);
	box-shadow:
		0 1px 2px rgba(48, 39, 43, 0.06 ),
		0 6px 16px -10px rgba(48, 39, 43, 0.22 );
}

.vb-agenda__calhead {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-bottom: 8px;
}

.vb-agenda__month {
	font-size: var(--vb-text-body, 1rem);
}

.vb-agenda__nav {
	padding: 2px 10px;
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
	line-height: 1.4;
	color: var(--vb-ink, #30272b);
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
	text-decoration: none;
}

.vb-agenda__nav:hover {
	color: #fff;
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
}

.vb-agenda__dows {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	margin-bottom: 2px;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	text-align: center;
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.vb-agenda__cells {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	gap: 2px;
}

.vb-agenda__cell {
	display: flex;
	flex-direction: column;
	align-items: center;
	min-height: 2.5rem;
	padding: 4px 2px 3px;
	border-radius: var(--vb-radius-xs, 6px);
	color: var(--vb-ink, #30272b);
	text-decoration: none;
}

.vb-agenda__cell:hover {
	background: var(--vb-surface, #f2e7df);
}

.vb-agenda__cell.is-today {
	box-shadow: inset 0 0 0 2px var(--vb-accent-text, #68192e);
}

.vb-agenda__cell.is-outside .vb-agenda__daynum {
	color: var(--vb-muted, #6b5b60);
	font-weight: 400;
}

.vb-agenda__daynum {
	font-size: var(--vb-text-small, 0.85rem);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.vb-agenda__count {
	margin-top: 2px;
	padding: 1px 5px;
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-surface, #f2e7df);
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	line-height: 1.3;
	font-variant-numeric: tabular-nums;
}

.vb-agenda__monthlink {
	display: inline-block;
	margin-top: 8px;
	font-size: var(--vb-text-caption, 0.78rem);
}

.vb-agenda__title {
	margin: 0 0 8px;
	font-size: var(--vb-text-body, 1rem);
}

.vb-agenda__rows {
	margin: 0;
	padding: 0;
	list-style: none;
}

.vb-agenda__row {
	display: flex;
	/* One line per appointment. With wrap the row prefers to break rather
	   than shrink the name column, which put every action chip on its own
	   line and doubled the row height. */
	flex-wrap: nowrap;
	align-items: center;
	gap: 8px;
	padding: 6px 8px;
	border-top: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius-xs, 6px);
}


/* Zebra: on a phone every appointment wraps onto three lines, and eight of
   them run together into one wall of text - the hairline alone stops
   carrying the boundary. A faint alternating ground does, and it costs no
   height. Token-based, so it holds in both schemes. */
.vb-agenda__row:nth-child(even) {
	background: var(--vb-zebra, rgba(48, 39, 43, 0.035));
}


/* The list is a scan target, not a form: the action chips stay on the row's
   line. Wrapping them doubled every row's height and pushed the KPI board
   a full screen down. */
.vb-dashboard .vb-agenda__row .vb-day__actions {
	flex: 0 0 auto;
	flex-wrap: nowrap;
	margin-top: 0;
}


.vb-agenda__row .vb-day__status {
	flex: 0 0 auto;
}

.vb-agenda__row:first-child {
	padding-top: 2px;
	border-top: 0;
}

.vb-agenda__when {
	display: flex;
	flex: 0 0 auto;
	flex-direction: column;
	align-items: center;
	min-width: 3.6rem;
	color: var(--vb-ink, #30272b);
	text-decoration: none;
}

.vb-agenda__daychip {
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	white-space: nowrap;
}

.vb-agenda__time {
	font-size: var(--vb-text-body, 1rem);
	font-variant-numeric: tabular-nums;
}

.vb-agenda__who {
	display: flex;
	/* Zero basis: the name column is what gives way, not the row. */
	flex: 1 1 0;
	flex-direction: column;
	min-width: 0;
}

.vb-agenda__names,
.vb-agenda__meta {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.vb-agenda__names {
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
}

.vb-agenda__meta {
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
}

@media ( max-width: 56rem ) {
	.vb-agenda__grid {
		grid-template-columns: 1fr;
	}
}


@media ( max-width: 45rem ) {
	.vb-agenda__row {
		flex-wrap: wrap;
		row-gap: 4px;
	}

	.vb-dashboard .vb-agenda__row .vb-day__actions {
		flex: 1 1 100%;
		flex-wrap: wrap;
		justify-content: flex-start;
	}
}


/* Booking funnel: reuses the stats bar rows; the only addition is the quiet
   conversion note per step. */

.vb-funnel {
	margin-top: 18px;
}

.vb-funnel__step {
	/* The bar row is a three-column grid, so the note takes its own line
	   underneath rather than squeezing a fourth column in. */
	grid-column: 1 / -1;
	margin-top: 2px;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	font-variant-numeric: tabular-nums;
}


/* ---------------------------------------------------------------------------
   Roadmap board: practices propose, practices vote. Quiet by default — the
   one coloured thing per row is a vote this practice has actually cast. */

.vb-roadmap__form {
	display: flex;
	flex-direction: column;
	/* The shared console form rule sets align-items: flex-end for its
	   horizontal layouts. Turning the direction to column without restating
	   this pushed every label and field to the right edge of an otherwise
	   empty box. */
	align-items: stretch;
	gap: 8px;
	max-width: 46rem;
	margin: 12px 0 20px;
	padding: 12px 14px;
	background: var(--vb-base, #fbf7f2);
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius, 16px);
}

.vb-roadmap__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: var(--vb-text-small, 0.85rem);
	font-weight: 600;
}

.vb-roadmap__field input,
.vb-roadmap__field textarea {
	font-weight: 400;
}

.vb-roadmap__submit {
	align-self: flex-start;
}

.vb-roadmap__list {
	display: flex;
	flex-direction: column;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.vb-roadmap__item {
	display: flex;
	gap: 12px;
	padding: 12px 14px;
	background: var(--vb-base, #fbf7f2);
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius, 16px);
}

.vb-roadmap__voteform {
	flex: 0 0 auto;
	margin: 0;
}

.vb-dashboard .vb-roadmap__vote {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0;
	min-width: 3rem;
	padding: 6px 8px;
	color: var(--vb-ink, #30272b);
	background: transparent;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-sm, 11px);
	line-height: 1.2;
	transform: none;
	box-shadow: none;
}

.vb-dashboard .vb-roadmap__vote:hover {
	background: var(--vb-surface, #f2e7df);
	transform: none;
	box-shadow: none;
}

/* A vote this practice has cast is the one filled thing in the row. */
.vb-dashboard .vb-roadmap__vote.is-voted {
	color: #fff;
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
}

.vb-roadmap__arrow {
	font-size: var(--vb-text-caption, 0.78rem);
}

.vb-roadmap__count {
	font-size: var(--vb-text-body, 1rem);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.vb-roadmap__body {
	flex: 1 1 auto;
	min-width: 0;
}

.vb-roadmap__title {
	display: block;
	font-size: var(--vb-text-body, 1rem);
}

.vb-roadmap__text {
	margin: 4px 0 6px;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-label, 0.9rem);
}

.vb-roadmap__meta {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0;
}

.vb-roadmap__status {
	padding: 0.12rem 0.55rem;
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-surface, #f2e7df);
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
}

.vb-roadmap__status--planned {
	background: #e7eefb;
	color: #24508f;
}

.vb-roadmap__status--shipped {
	background: var(--vb-primary-soft, #f3e2e7);
	color: var(--vb-accent-text, #68192e);
}

.vb-roadmap__status--declined {
	background: #f0ece6;
	color: #6b5f4e;
}

.vb-roadmap__own {
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
}

.vb-roadmap__answer {
	margin: 8px 0 0;
	padding-left: 10px;
	border-left: 2px solid var(--vb-field-line, #8c716e);
	font-size: var(--vb-text-label, 0.9rem);
}

.vb-roadmap__answer span {
	font-weight: 700;
}

.vb-roadmap__delform {
	margin: 6px 0 0;
}

.vb-dashboard .vb-roadmap__delete {
	padding: 2px 10px;
	color: var(--vb-muted, #6b5b60);
	background: transparent;
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius-pill, 999px);
	font-size: var(--vb-text-caption, 0.78rem);
	transform: none;
	box-shadow: none;
}

.vb-dashboard .vb-roadmap__delete:hover {
	color: #fff;
	background: #c0392b;
	border-color: var(--vb-danger-text, #b52216);
}


/* ---------------------------------------------------------------------------
   Sidebar regressions from the profile.css/console.css split (26.08.2026).

   The sidebar shape lives in profile.css inside 


/* ---------------------------------------------------------------------------
   Console shell: eight sections beside the work.

   The old shell (.vb-tabs) rendered every panel and switched them with JS.
   This one renders the section that was asked for, so the navigation is a
   list of links — the browser's own current-page mechanics, no tablist. */

.vb-console {
	display: grid;
	grid-template-columns: 210px minmax(0, 1fr);
	gap: 0 30px;
	align-items: start;
}

.vb-console__nav {
	position: sticky;
	/* Clears the sticky site header; the admin bar sits above that again. */
	top: 90px;
	max-height: calc( 100vh - 120px );
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 0 10px 0 0;
	border-right: 1px solid var(--vb-line, #d9c7c1);
}

.vb-console__list {
	display: grid;
	gap: 1px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The foot pair sits apart: reachable, not competing with the day's work. */
.vb-console__list--foot {
	margin-top: 14px;
	padding-top: 12px;
	border-top: 1px solid var(--vb-line, #d9c7c1);
}

.vb-console__link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	padding: 7px 10px 7px 13px;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 500;
	text-decoration: none;
	border-radius: var(--vb-radius-sm, 11px);
}

.vb-console__link:hover {
	color: var(--vb-ink, #30272b);
	background: var(--vb-surface, #f2e7df);
}

/* The one green thing in the sidebar: where you are. A bar rather than a
   filled block — a filled row turns a quarter of the column into a slab. */
.vb-console__link.is-active {
	position: relative;
	color: var(--vb-accent-text, #68192e);
	font-weight: 700;
	background: var(--vb-primary-soft, #f3e2e7);
}

.vb-console__link.is-active::before {
	content: "";
	position: absolute;
	left: 0;
	top: 5px;
	bottom: 5px;
	width: 3px;
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-accent-text, #68192e);
}

.vb-console__badge {
	flex: 0 0 auto;
	min-width: 1.35rem;
	padding: 0 6px;
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-primary-dark, #68192e);
	color: #fff;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	line-height: 1.5rem;
	text-align: center;
	font-variant-numeric: tabular-nums;
}

.vb-console__title {
	margin: 0 0 14px;
	font-size: 1.35rem;
	line-height: 1.2;
}


/* Level two: the segmented row inside a section. */
.vb-console__sub {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0 0 16px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--vb-line, #d9c7c1);
}

.vb-console__subtab {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 12px;
	color: var(--vb-ink, #30272b);
	font-size: var(--vb-text-small, 0.85rem);
	font-weight: 600;
	text-decoration: none;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
}

.vb-console__subtab:hover {
	color: #fff;
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
}

.vb-console__subtab.is-active {
	color: #fff;
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
}

.vb-console__subtab.is-active .vb-console__badge {
	background: var(--vb-base, #fbf7f2);
	color: var(--vb-accent-text, #68192e);
}


/* The switch is desktop-irrelevant: the sidebar is always there. */
.vb-console__switch,
.vb-console__trigger {
	display: none;
}


@media ( max-width: 67.99rem ) {
	/* One column, and the section list collapsed behind a single 44px row —
	   eight links stacked above the work would be half a phone screen
	   before anything happens. */
	.vb-console {
		display: block;
		/* Explicit: a left-over 210px track with display:block is inert,
		   but the next person reading it should not have to know that. */
		grid-template-columns: none;
	}

	.vb-console__nav {
		position: static;
		max-height: none;
		overflow: visible;
		margin: 0 0 16px;
		padding: 0;
		border-right: 0;
	}

	.vb-console__trigger {
		display: block;
		margin: 0 0 10px;
		padding: 10px 14px;
		background: var(--vb-surface, #f2e7df);
		border-radius: var(--vb-radius, 16px);
		font-weight: 600;
		cursor: pointer;
	}

	.vb-console__switch:not(:checked) ~ .vb-console__nav {
		display: none;
	}

	.vb-console__list {
		gap: 2px;
	}
}


/* ---------------------------------------------------------------------------
   Chat (practice console + customer account — one renderer, one look).

   The feel of a native messenger in the site's own design language: brand
   green for own bubbles, surface tone for theirs, tails only at a group's
   end, a docked round composer. Deliberately NOT an iMessage clone — no
   #007AFF, no Apple assets; the physics, not the trade dress. */

.vb-chat__layout {
	display: grid;
	grid-template-columns: 280px minmax(0, 1fr);
	gap: 0 18px;
	align-items: start;
}

/* ----- Thread list ----- */

.vb-chat__list {
	border-right: 1px solid var(--vb-line, #d9c7c1);
	padding-right: 12px;
}

.vb-chat__new {
	margin: 0 0 12px;
}

.vb-chat__threads {
	display: grid;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.vb-chat__threaditem a {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 10px;
	border-radius: var(--vb-radius-sm, 11px);
	color: inherit;
	text-decoration: none;
}

.vb-chat__threaditem a:hover {
	background: var(--vb-surface, #f2e7df);
}

.vb-chat__threaditem.is-active a {
	background: var(--vb-primary-soft, #f3e2e7);
}

.vb-chat__avatar {
	display: inline-grid;
	place-items: center;
	flex: 0 0 auto;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	/* 42%/38% put white on 3.66:1 at the yellow end of the hue circle -
	   measured 4.26:1 and 4.27:1 on two real correspondents in the inbox,
	   and 12.5px bold is small text, so 4.5:1 is the bar. Darker and more
	   saturated together: every hue now clears 4.74:1 and the circles keep
	   their colour instead of turning to mud. */
	background: hsl(var(--vb-avatar-h, 150) 50% 31%);
	color: #fff;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	letter-spacing: 0.02em;
}

.vb-chat__threadbody {
	display: grid;
	flex: 1 1 auto;
	min-width: 0;
	gap: 1px;
}

.vb-chat__threadtop {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px;
}

.vb-chat__name {
	overflow: hidden;
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.vb-chat__when {
	flex: 0 0 auto;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	white-space: nowrap;
}

.vb-chat__preview {
	overflow: hidden;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.vb-chat__unread {
	display: inline-grid;
	place-items: center;
	flex: 0 0 auto;
	min-width: 20px;
	height: 20px;
	padding: 0 6px;
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-primary-dark, #68192e);
	color: #fff;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
}

/* ----- Conversation pane ----- */

.vb-chat__head {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 0 0 10px;
	margin: 0 0 10px;
	border-bottom: 1px solid var(--vb-line, #d9c7c1);
}

.vb-chat__back {
	display: none; /* desktop shows the list beside it */
	color: var(--vb-ink, #30272b);
	font-size: 1.1rem;
	text-decoration: none;
}

.vb-chat__headbody {
	display: grid;
	gap: 0;
	min-width: 0;
}

.vb-chat__headname {
	font-size: var(--vb-text-body, 1rem);
}

.vb-chat__context {
	font-size: var(--vb-text-caption, 0.78rem);
}

.vb-chat__thread {
	display: grid;
	gap: 2px;
	align-content: start;
	max-height: min(58vh, 540px);
	margin-bottom: 12px;
	overflow-y: auto;
	overscroll-behavior: contain;
	scroll-behavior: smooth;
	padding: 2px 2px 6px;
}

@media (prefers-reduced-motion: reduce) {
	.vb-chat__thread {
		scroll-behavior: auto;
	}
}

.vb-chat__day {
	position: sticky;
	top: 0;
	z-index: 1;
	justify-self: center;
	margin: 8px 0 4px;
	padding: 3px 12px;
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-surface, #f2e7df);
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	letter-spacing: 0.04em;
}

/* Bubbles: springy arrival, tight groups, a tail only at the group's end. */

@keyframes vb-chat-in {
	from {
		opacity: 0;
		transform: translateY(6px) scale(0.97);
	}
	60% {
		transform: translateY(-1px) scale(1.005);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

.vb-chat__bubble {
	position: relative;
	max-width: 76%;
	padding: 8px 12px;
	border-radius: var(--vb-radius, 16px);
	animation: vb-chat-in 220ms ease-out both;
}

@media (prefers-reduced-motion: reduce) {
	.vb-chat__bubble {
		animation: none;
	}
}

.vb-chat__bubble p {
	margin: 0;
	overflow-wrap: anywhere;
}

.vb-chat__bubble--mine {
	justify-self: end;
	background: var(--vb-primary-dark, #68192e);
	color: #fff;
}

.vb-chat__bubble--theirs {
	justify-self: start;
	background: var(--vb-surface, #f2e7df);
	color: var(--vb-ink, #30272b);
}

.vb-chat__bubble.is-continued {
	margin-top: 0;
}

.vb-chat__bubble--mine.is-continued {
	border-top-right-radius: 6px;
}

.vb-chat__bubble--theirs.is-continued {
	border-top-left-radius: 6px;
}

.vb-chat__bubble--mine:not(.is-groupend) {
	border-bottom-right-radius: 6px;
}

.vb-chat__bubble--theirs:not(.is-groupend) {
	border-bottom-left-radius: 6px;
}

/* The tail: a small curve at the group's last bubble, drawn with a
   pseudo-element so it inherits the bubble colour. */
.vb-chat__bubble.is-groupend::after {
	content: "";
	position: absolute;
	bottom: 0;
	width: 10px;
	height: 12px;
	background: inherit;
}

.vb-chat__bubble--mine.is-groupend::after {
	right: -5px;
	border-bottom-left-radius: 12px;
	clip-path: path( "M0 12 C4 12 8 8 10 0 L10 12 Z" );
}

.vb-chat__bubble--theirs.is-groupend::after {
	left: -5px;
	border-bottom-right-radius: 12px;
	clip-path: path( "M10 12 C6 12 2 8 0 0 L0 12 Z" );
}

.vb-chat__meta {
	display: none;
	margin-top: 3px;
	font-size: var(--vb-text-caption, 0.78rem);
}

.vb-chat__bubble.is-groupend .vb-chat__meta {
	display: block;
}

.vb-chat__bubble--mine .vb-chat__meta {
	color: rgba(255, 255, 255, 0.75);
	text-align: right;
}

.vb-chat__bubble--theirs .vb-chat__meta {
	color: var(--vb-muted, #6b5b60);
}

.vb-chat__bubble.is-pending {
	opacity: 0.75;
}

/* Idle pane: the conversation skeleton exists (header, thread, composer)
   but stays hidden until a thread is opened client-side - picking a
   conversation is then a fetch + class flip, not a page load. */
.vb-chat__pane.is-idle .vb-chat__head,
.vb-chat__pane.is-idle .vb-chat__thread,
.vb-chat__pane.is-idle .vb-chat__composer {
	display: none;
}


.vb-chat__pane:not(.is-idle) .vb-chat__pick {
	display: none;
}


.vb-chat__pick {
	padding: 24px 0;
	text-align: center;
}

/* ----- Composer ----- */

.vb-chat__composer {
	/* The shared console form rule lays forms out as a flex ROW — for this
	   stacked composer (chips / bar / hint) that squeezed the input to its
	   intrinsic width. Block, explicitly. */
	display: block;
	position: sticky;
	bottom: 0;
	margin: 0;
	padding-top: 6px;
	background: var(--vb-base, #fbf7f2);
}

.vb-chat__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0 0 8px;
}

.vb-dashboard .vb-chat__chip,
.vb-account .vb-chat__chip {
	padding: 4px 12px;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
	background: transparent;
	color: var(--vb-ink, #30272b);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 600;
	transform: none;
	box-shadow: none;
}

.vb-dashboard .vb-chat__chip:hover,
.vb-account .vb-chat__chip:hover {
	color: #fff;
	background: var(--vb-primary-dark, #68192e);
	border-color: var(--vb-accent-text, #68192e);
}

.vb-chat__bar {
	display: flex;
	align-items: flex-end;
	gap: 8px;
}

.vb-chat__bar textarea {
	box-sizing: border-box;
	flex: 1 1 auto;
	/* A flex item defaults to min-width:auto, and a textarea's intrinsic
	   minimum is its cols (20 characters). With a phone's larger system
	   font that is wider than the space left beside the send button, so
	   the field refused to shrink and pushed the button off-screen. */
	min-width: 0;
	width: 100%;
	min-height: 42px;
	max-height: 200px;
	margin: 0;
	padding: 10px 14px;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-lg, 22px);
	font: inherit;
	line-height: 1.45;
	resize: none;
	overflow-y: auto;
}

/* The send button wakes from quiet grey to brand green once there is
   something to send — state as colour, not as a disabled attribute. */
.vb-dashboard .vb-chat__send,
.vb-account .vb-chat__send {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: 42px;
	height: 42px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--vb-line, #d9c7c1);
	color: var(--vb-muted, #6b5b60);
	transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
	transform: none;
	box-shadow: none;
}

.vb-dashboard .vb-chat__send.is-armed,
.vb-account .vb-chat__send.is-armed {
	background: var(--vb-primary-dark, #68192e);
	color: #fff;
}

.vb-dashboard .vb-chat__send.is-armed:hover,
.vb-account .vb-chat__send.is-armed:hover {
	transform: scale(1.06);
}

.vb-chat__status {
	margin: 6px 0 0;
	font-size: var(--vb-text-small, 0.85rem);
	color: var(--vb-muted, #6b5b60);
}

.vb-chat__status.is-error {
	color: var(--vb-danger-text-strong, #b52216);
}

/* ----- Phone: list OR conversation ----- */

@media ( max-width: 67.99rem ) {
	.vb-chat__layout {
		display: block;
	}

	.vb-chat__list {
		border-right: 0;
		padding-right: 0;
	}

	/* An open thread takes the stage; the list is one tap back. */
	.vb-chat.has-open .vb-chat__list {
		display: none;
	}

	.vb-chat.has-open .vb-chat__back {
		display: inline-block;
	}

	.vb-chat__thread {
		max-height: min(62dvh, 560px);
	}

	.vb-chat__bubble {
		max-width: 84%;
	}
}

/* Nothing inside the conversation may outgrow its column - a long word, a
   pasted URL or a stubborn control would otherwise take the whole page
   sideways with it. */
.vb-chat__pane,
.vb-chat__thread,
.vb-chat__composer,
.vb-chat__bar {
	max-width: 100%;
	min-width: 0;
}


.vb-chat__bubble p {
	overflow-wrap: anywhere;
}

.vb-settings__replies {
	box-sizing: border-box;
	width: 100%;
	max-width: 46rem;
	font: inherit;
}


/* ---------------------------------------------------------------------------
   Patient record: one animal's history behind the patient list. */

.vb-record__backline {
	margin: 0 0 10px;
	font-size: var(--vb-text-small, 0.85rem);
}

.vb-record__head {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 12px 16px;
	margin-bottom: 6px;
	background: var(--vb-base, #fbf7f2);
	border-radius: var(--vb-radius, 16px);
	box-shadow:
		0 1px 2px rgba(48, 39, 43, 0.06 ),
		0 6px 16px -10px rgba(48, 39, 43, 0.22 );
}

.vb-record__head .vb-chat__avatar {
	width: 48px;
	height: 48px;
	font-size: var(--vb-text-body, 1rem);
}

.vb-record__headbody {
	flex: 1 1 auto;
	min-width: 0;
}

.vb-record__name {
	margin: 0;
	font-size: 1.25rem;
}

.vb-record__facts,
.vb-record__owner {
	margin: 2px 0 0;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-small, 0.85rem);
}

.vb-record__book {
	flex: 0 0 auto;
}

.vb-record__stickynote {
	margin: 10px 0 0;
	padding: 8px 12px;
	background: #fcf7e6;
	border-radius: var(--vb-radius-sm, 11px);
	color: #6b5324;
	font-size: var(--vb-text-label, 0.9rem);
}

.vb-record__grid {
	display: grid;
	grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
	gap: 0 22px;
	align-items: start;
	margin-top: 14px;
}

@media ( max-width: 56rem ) {
	.vb-record__grid {
		grid-template-columns: 1fr;
	}
}

.vb-record__form {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0 0 8px;
}

.vb-record__form input[type="number"],
.vb-record__form input[type="text"] {
	flex: 1 1 8rem;
	min-width: 0;
}

.vb-sparkline {
	display: block;
	width: 100%;
	max-width: 300px;
	height: auto;
	color: var(--vb-accent-text, #68192e);
}

.vb-record__weightnow {
	margin: 0 0 6px;
	font-size: var(--vb-text-lead, 1.0625rem);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.vb-record__passlist {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 6px;
	font-size: var(--vb-text-label, 0.9rem);
}

.vb-record__timeline {
	margin: 0;
	padding: 0;
	list-style: none;
}

.vb-record__entry {
	display: flex;
	align-items: baseline;
	gap: 10px;
	padding: 7px 0 7px 14px;
	border-left: 2px solid var(--vb-line, #d9c7c1);
}

.vb-record__entry--visit {
	border-left-color: var(--vb-accent-text, #68192e);
}

.vb-record__entry--vaccination {
	border-left-color: var(--vb-field-line, #8c716e);
}

.vb-record__date {
	flex: 0 0 auto;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-caption, 0.78rem);
	font-variant-numeric: tabular-nums;
}

.vb-record__text {
	flex: 1 1 auto;
	min-width: 0;
	font-size: var(--vb-text-label, 0.9rem);
	overflow-wrap: anywhere;
}

.vb-record__delform {
	margin: 0;
}

.vb-record__create {
	margin: 0 0 14px;
}

.vb-pet__recordlink {
	margin: 4px 0 8px;
	font-size: var(--vb-text-small, 0.85rem);
}


/* ----- Feature introductions (Onboarding\TourNotice) -------------------------
   One line of news under the section title, never a modal. A practice opens
   the console because somebody is on the phone; anything that has to be
   defeated before the calendar appears is a toll, not onboarding.

   The card is quieter than the activation checklist above it on purpose:
   the checklist is work still owed, this is an offer. Same surface, no
   gradient, and the two ways out are text rather than buttons so the one
   thing worth doing is the only thing that looks clickable. */
.vb-tour {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 20px;
	margin: 0 0 18px;
	padding: 14px 18px;
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius-lg, 22px);
	background: var(--vb-primary-soft, #f3e2e7);
	animation: vb-tour-in 0.45s cubic-bezier(0.22, 0.8, 0.3, 1) both;
}


@keyframes vb-tour-in {
	from {
		opacity: 0;
		transform: translateY(6px);
	}

	to {
		opacity: 1;
		transform: none;
	}
}


.vb-tour__body {
	flex: 1 1 22rem;
	min-width: 0;
}


.vb-tour__eyebrow {
	margin: 0 0 4px;
	color: var(--vb-accent-text, #68192e);
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}


.vb-tour__title {
	margin: 0 0 4px;
	font-size: var(--vb-text-body, 1rem);
	line-height: 1.3;
	text-wrap: balance;
}


.vb-tour__text {
	margin: 0;
	max-width: 62ch;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-label, 0.9rem);
	line-height: 1.5;
}


.vb-tour__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 16px;
}


.vb-tour__go {
	padding: 9px 18px;
	border: 0;
	border-radius: var(--vb-radius-pill, 999px);
	background: var(--vb-primary-dark, #68192e);
	color: #fff;
	font: inherit;
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
	cursor: pointer;
}


.vb-tour__go:hover {
	background: var(--vb-primary-darker, #300b17);
}


.vb-tour__later,
.vb-tour__never {
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--vb-muted, #6b5b60);
	font: inherit;
	font-size: var(--vb-text-small, 0.85rem);
	text-decoration: underline;
	cursor: pointer;
}


.vb-tour__later:hover,
.vb-tour__never:hover {
	color: var(--vb-ink, #30272b);
}


/* The way back in, in the help section. */
.vb-tour-reset {
	margin: 22px 0 0;
	padding: 16px 18px;
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius, 16px);
	background: var(--vb-base, #fbf7f2);
}


.vb-tour-reset h3 {
	margin: 0 0 6px;
	font-size: var(--vb-text-body, 1rem);
}


.vb-tour-reset p {
	margin: 0 0 12px;
	max-width: 62ch;
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-label, 0.9rem);
}


.vb-tour-reset__btn {
	padding: 8px 16px;
	border: 1px solid var(--vb-field-line, #8c716e);
	border-radius: var(--vb-radius-pill, 999px);
	background: transparent;
	color: var(--vb-ink, #30272b);
	font: inherit;
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
	cursor: pointer;
}


.vb-tour-reset__btn:hover {
	border-color: var(--vb-accent-text, #68192e);
	color: var(--vb-accent-text, #68192e);
}


@media (prefers-reduced-motion: reduce) {
	.vb-tour {
		animation: none;
	}
}


/* ----- "Which plan am I on" (SubscriptionPanel) ------------------------------
   This block used to appear only for practices with a live billing record.
   Everybody else - admin-assigned tiers, trials, the hidden partner tariffs
   the plan engine exists to support - opened Subscription and read one
   sentence about payment setup, with no way to see their own plan.

   Two questions on two lines: the headline is what is being PAID for, the
   list underneath is what is unlocked TODAY. During a trial those differ,
   and so does a per-practice override, which is the one thing the public
   pricing page can never show. */
.vb-subscription__plan {
	margin: 0 0 18px;
	padding: 16px 18px;
	border: 1px solid var(--vb-line, #d9c7c1);
	border-radius: var(--vb-radius, 16px);
	background: var(--vb-surface, #f2e7df);
}


.vb-subscription__planline {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 4px 14px;
	margin: 0;
}


.vb-subscription__planname {
	font-family: var(--vb-display, inherit);
	font-size: 1.35rem;
	font-weight: 700;
	line-height: 1.1;
}


.vb-subscription__planprice {
	color: var(--vb-muted, #6b5b60);
	font-size: var(--vb-text-body, 1rem);
	font-variant-numeric: tabular-nums;
}


/* The trial line has never had a rule of its own - it inherited paragraph
   styling and read as body copy next to the price it contradicts. */
.vb-subscription__trial {
	margin: 6px 0 0;
	color: var(--vb-warn-ink, #86520a);
	font-size: var(--vb-text-label, 0.9rem);
	font-weight: 600;
}


.vb-subscription__included {
	margin-top: 14px;
	padding-top: 14px;
	border-top: 1px solid var(--vb-line, #d9c7c1);
}


.vb-subscription__included h4 {
	margin: 0 0 10px;
	font-size: var(--vb-text-caption, 0.78rem);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--vb-muted, #6b5b60);
}


.vb-subscription__group {
	margin: 12px 0 5px;
	font-size: var(--vb-text-small, 0.85rem);
	font-weight: 700;
}


.vb-subscription__group:first-of-type {
	margin-top: 0;
}


.vb-subscription__features {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 3px 20px;
	font-size: var(--vb-text-label, 0.9rem);
}


/* Two columns once there is room; one on a phone, where a second column
   would put four words on each line. */
@media (min-width: 44rem) {
	.vb-subscription__features {
		grid-template-columns: 1fr 1fr;
	}
}


.vb-subscription__features li {
	display: flex;
	align-items: baseline;
	gap: 7px;
}


.vb-subscription__features li > span[aria-hidden] {
	color: var(--vb-accent-text, #68192e);
	font-weight: 700;
}


.vb-subscription__featureval {
	color: var(--vb-muted, #6b5b60);
	font-variant-numeric: tabular-nums;
}


.vb-subscription__compare {
	margin: 14px 0 0;
	font-size: var(--vb-text-label, 0.9rem);
}

/* The pension's unit editor rows and the stay-list action buttons. */
.vb-stayunit { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; padding: 10px 0; border-bottom: 1px solid var(--vb-line, #d9c7c1); }
.vb-stayunit label { display: grid; gap: 4px; font-size: var(--vb-text-small, 0.85rem); }
.vb-stayunit input[type="text"] { min-width: 220px; }
.vb-stayunit input[type="number"] { width: 110px; }
.vb-stayaction { display: inline-block; margin: 0 4px 4px 0; }
.vb-btn--small { padding: 4px 10px; font-size: var(--vb-text-small, 0.85rem); }

/* The 30-day occupancy strip: one cell per night, colour is the answer. */
.vb-occupancy__name { margin: 10px 0 4px; font-weight: 600; font-size: var(--vb-text-label, 0.9rem); }
.vb-occupancy__strip { display: flex; flex-wrap: wrap; gap: 3px; }
.vb-occupancy__day { min-width: 26px; padding: 3px 0; text-align: center; border-radius: var(--vb-radius-xs, 6px); font-size: var(--vb-text-caption, 0.78rem); font-variant-numeric: tabular-nums; }
.vb-occupancy__day.is-free { background: var(--vb-tint, #f3e2e7); color: var(--vb-accent-text, #68192e); }
.vb-occupancy__day.is-part { background: var(--vb-warn-soft, #fff0d8); color: var(--vb-warn-text, #86520a); }
.vb-occupancy__day.is-full { background: var(--vb-danger-soft, #ffece6); color: var(--vb-danger-text, #b52216); }

/* The multilingual name field: the site language leads, the rest fold away so
   a list of a dozen services does not become sixty inputs. */
.vb-i18nname__primary { display: block; }
.vb-i18nname { margin: 4px 0 8px; font-size: var(--vb-text-label, 0.9rem); }
.vb-i18nname > summary { cursor: pointer; color: var(--vb-muted, #6b5b60); padding: 2px 0; }
.vb-i18nname__row { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.vb-i18nname__row > span {
	flex: 0 0 2.4em;
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.04em;
	color: var(--vb-muted, #6b5b60);
}
.vb-i18nname__row input { flex: 1 1 auto; }

/* Why a customer cancelled, beside the cancellation itself (M-055). A stored
   reason nobody sees is a column that is written and never read. */
.vb-day__reason {
	font-size: var(--vb-text-small, 0.85rem);
	color: var( --vb-muted, #6b5b60 );
}

/* Video consultations the business starts itself (#373). */
.vb-video-start {
	margin: 0 0 16px;
}

.vb-video-start p {
	margin: 6px 0 0;
}

.vb-video-session__link,
.vb-video-session__share {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}

.vb-video-session__link label {
	flex: 1 0 100%;
	font-weight: 600;
}

.vb-video-session__link input {
	flex: 1 1 16rem;
	min-width: 0;
}

.vb-video-session__close {
	margin-top: 16px;
}

.vb-video-session__figures {
	display: grid;
	grid-template-columns: max-content 1fr;
	gap: 4px 16px;
	margin: 0 0 8px;
}

.vb-video-session__figures dd {
	margin: 0;
	font-weight: 600;
}

/* Somebody waits in the video room (#369 D): impossible to miss, on every
   console page. A short cue when a guest arrives, then a strong still
   notice; without motion where the reader asked for less. */
.vb-video-alert {
	position: sticky;
	top: 0;
	z-index: 1001;
	padding: 10px 16px;
	border: 3px solid var(--vb-warn-ink, #86520a);
	background: var(--vb-warn-soft, #fff0d8);
	color: var(--vb-warn-ink, #86520a);
	font-weight: 700;
}

.vb-video-alert__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 8px 16px;
	max-width: 80rem;
	margin: 0 auto;
}

.vb-video-alert__row + .vb-video-alert__row {
	margin-top: 8px;
}

.vb-video-alert.is-new {
	animation: vb-video-alert-cue 0.8s ease-in-out 4;
}

@keyframes vb-video-alert-cue {
	50% {
		box-shadow: 0 0 0 6px var(--vb-warn-ink, #86520a);
	}
}

@media (prefers-reduced-motion: reduce) {
	.vb-video-alert.is-new {
		animation: none;
	}
}

:root[data-focus="reduced"] .vb-video-alert.is-new {
	animation: none;
}

/* The customer's video link from the day view (#369 B). */
.vb-day__videolink {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 8px;
	margin: 6px 0 0;
}
