/**
 * mbb-hire.css — the hire island's self-contained stylesheet.
 * CSS-ISOLATION-STANDARD: every rule scoped [data-mbb] .mbb-hire-*, own
 * typography floor, full state contract (hover/focus-visible/disabled/
 * aria-pressed), zero theme assumptions. Loads ONLY on range-kind mounts.
 */

[data-mbb].mbb-hire-widget {
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	font-size: 15px;
	line-height: 1.45;
	color: var(--mbpos-color-heading, #1d2327);
	margin: 0 auto;
}
[data-mbb] .mbb-hire-error,
[data-mbb] .mbb-hire-msg:not(:empty) {
	padding: 10px 12px;
	border-radius: 8px;
	background: var(--mbpos-color-danger-subtle, #fbeaea);
	color: var(--mbpos-color-danger, #8a1f1f);
	margin-top: 10px;
}
[data-mbb] .mbb-hire-lbl {
	display: block;
	font-weight: 600;
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--mbpos-color-text-soft, #50575e);
	margin: 14px 0 6px;
}

/* Blocks */
[data-mbb] .mbb-hire-blocks { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-block {
	appearance: none; border: 1px solid var(--mbpos-color-border, #c3c4c7); background: var(--mbpos-color-surface, #fff); color: var(--mbpos-color-heading, #1d2327);
	border-radius: 999px; padding: 7px 14px; font: inherit; cursor: pointer;
}
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-block:hover { border-color: var(--mbpos-color-border-strong, #8c8f94); }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-block:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 2px; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-block.is-sel { background: var(--mbpos-color-selected, #1d2327); border-color: var(--mbpos-color-selected, #1d2327); color: var(--mbpos-color-selected-text, #fff); }

/* Stepper */
[data-mbb] .mbb-hire-units { display: flex; align-items: center; gap: 10px; }
[data-mbb] .mbb-hire-units .mbb-hire-lbl { margin: 0 auto 0 0; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-step {
	appearance: none; width: 36px; height: 36px; border-radius: 50%;
	border: 1px solid var(--mbpos-color-border, #c3c4c7); background: var(--mbpos-color-surface, #fff); font-size: 18px; line-height: 1;
	cursor: pointer; color: var(--mbpos-color-heading, #1d2327);
}
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-step:hover { border-color: var(--mbpos-color-border-strong, #8c8f94); }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-step:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 2px; }
[data-mbb] .mbb-hire-count { min-width: 72px; text-align: center; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Calendar */
[data-mbb] .mbb-hire-cal { margin-top: 10px; border: 1px solid var(--mbpos-color-border, #e0e0e0); border-radius: 10px; padding: 10px; }
[data-mbb] .mbb-hire-cal-head,
[data-mbb] .mbb-hire-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
[data-mbb] .mbb-hire-cal-head span {
	text-align: center; font-size: 11px; font-weight: 600; color: var(--mbpos-color-text-muted, #787c82);
	text-transform: uppercase; padding-bottom: 4px;
}
/* Paint only. Box and flow live in the containment chain at the foot of this
   file — see [p3a15]; a (0,2,0) selector cannot hold them against a theme. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day {
	appearance: none; border: 1px solid transparent; background: var(--mbb-cell-bg); color: var(--mbb-cell-text);
	border-radius: 8px; font: inherit; cursor: pointer; gap: 0;
}
[data-mbb] .mbb-hire-day-n { font-weight: 600; font-variant-numeric: tabular-nums; }
[data-mbb] .mbb-hire-day-m { font-size: 10px; color: currentColor; opacity: .7; text-transform: uppercase; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day:hover:not(:disabled) { border-color: var(--mbpos-color-border-strong, #8c8f94); background: var(--mbb-cell-hover); color: var(--mbpos-color-primary-hover-text, #1d2327); }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 1px; }
/* [p3a35] The pickup and return days carry a ring so the two ENDS of a range
   are distinguishable from the days between them. Inset, so it costs no
   layout — an outer ring would shift the grid the moment a date is picked,
   which is the bug p3a28 removed. The held ring (p3a25) is declared later
   and deliberately wins: "someone else is booking this" outranks "you picked
   this". */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-sel {
	background: var(--mbpos-color-selected, #1d2327);
	color: var(--mbpos-color-selected-text, #fff);
	box-shadow: inset 0 0 0 2px var(--mbpos-color-selected-strong, #1d2327);
}
[data-mbb] .mbb-hire-day.is-sel .mbb-hire-day-m { color: var(--mbpos-color-selected-text, #c3c4c7); opacity: .8; }
[data-mbb] .mbb-hire-day.is-off { opacity: .35; cursor: not-allowed; text-decoration: line-through; }
[data-mbb] .mbb-hire-cal-pad { min-height: 1px; }

/* Extras */
[data-mbb] .mbb-hire-extras { display: flex; flex-direction: column; gap: 6px; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-extra {
	appearance: none; display: flex; align-items: center; gap: 10px; text-align: left;
	border: 1px solid var(--mbpos-color-border, #c3c4c7); background: var(--mbb-field-bg); color: var(--mbpos-color-text, #1d2327);
	border-radius: 8px; padding: 9px 12px; font: inherit; cursor: pointer;
}
[data-mbb] .mbb-hire-extra em { font-style: normal; color: var(--mbpos-color-text-soft, #50575e); margin-left: auto; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-extra:hover { border-color: var(--mbpos-color-border-strong, #8c8f94); }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-extra:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 2px; }
[data-mbb] .mbb-hire-extra-tick {
	width: 18px; height: 18px; border: 2px solid var(--mbpos-color-border, #c3c4c7); border-radius: 4px; flex: 0 0 auto;
	display: inline-block; position: relative;
}
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-extra.is-sel { border-color: var(--mbpos-color-selected, #1d2327); }
[data-mbb] .mbb-hire-extra.is-sel .mbb-hire-extra-tick { background: var(--mbpos-color-selected, #1d2327); border-color: var(--mbpos-color-selected, #1d2327); color: var(--mbpos-color-selected-text, #fff); }
[data-mbb] .mbb-hire-extra.is-sel .mbb-hire-extra-tick::after {
	content: ""; position: absolute; left: 4px; top: 0; width: 5px; height: 10px;
	border: solid currentColor; border-width: 0 2px 2px 0; transform: rotate(45deg);
}

/* Quote */
[data-mbb] .mbb-hire-quote {
	margin-top: 14px; padding: 12px 14px; border-radius: 10px; background: var(--mbpos-color-surface-2, #f6f7f7);
	display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap;
}
[data-mbb] .mbb-hire-quote--empty { color: var(--mbpos-color-text-muted, #787c82); justify-content: center; }
[data-mbb] .mbb-hire-price { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
[data-mbb] .mbb-hire-price em { font-size: 12px; font-weight: 400; font-style: normal; color: var(--mbpos-color-text-soft, #50575e); }

/* Form */
[data-mbb] .mbb-hire-form { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; }
[data-mbb] .mbb-hire-in {
	appearance: none; border: 1px solid var(--mbpos-color-border, #c3c4c7); border-radius: 8px; padding: 9px 11px;
	font: inherit; color: var(--mbpos-color-text, #1d2327); background: var(--mbb-field-bg); width: 100%; box-sizing: border-box;
}
[data-mbb] .mbb-hire-in:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 1px; }
[data-mbb] .mbb-hire-in[data-hf="name"], [data-mbb] .mbb-hire-in[data-hf="notes"] { grid-column: 1 / -1; }
[data-mbb] .mbb-hire-hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-submit {
	grid-column: 1 / -1; appearance: none; border: 0; border-radius: 8px;
	background: var(--mbpos-color-primary, #1d2327); color: var(--mbpos-color-primary-text, #fff); padding: 12px; font: inherit; font-weight: 600; cursor: pointer;
}
/* [p3a31] Was `background: #000` — darkening an already-dark button reads as
   "less available", and it left the label's contrast unre-checked. The
   hover shade is computed from the base (it LIGHTENS a dark one), and
   hover-text is the pc1 variant that re-runs the contrast pick against that
   computed shade rather than reusing the resting text colour. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-submit:hover:not(:disabled) {
	background: var(--mbpos-color-primary-hover, #000);
	color: var(--mbpos-color-primary-hover-text, #fff);
}
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-submit:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 2px; }
[data-mbb] .mbb-hire-submit:disabled { opacity: .45; cursor: not-allowed; }
[data-mbb] .mbb-hire-msg { grid-column: 1 / -1; min-height: 1px; }

@media (max-width: 420px) {
	[data-mbb] .mbb-hire-form { grid-template-columns: 1fr; }
}

/**
 * [p3a3] Native Woo suppression on injected product pages. This pair lived
 * ONLY in mbb-widget.css, so a hire product — which loads this island
 * instead — kept Woo's quantity box and Add to cart button sitting under
 * the hire widget, offering a second, unbooked way to buy. Each island
 * owns its own copy; there is no shared stylesheet to put it in, and a
 * shared one would load on every covers page for no reason.
 */
form.cart.mbb-native-suppress .quantity,
form.cart.mbb-native-suppress .single_add_to_cart_button { display: none !important; }
form.cart.mbb-native-suppress [data-mbb].mbb-hire-widget { margin: 12px 0; }

/* [p3pos1s6] POS modal gutters.
   The hire island's root carries no horizontal padding — covers pads its own
   root (14px), hire only sets `margin: 0 auto` — so in the POS product modal
   the calendar sat flush against the panel edge while every sibling block was
   inset, and the widget read as escaping the modal rather than belonging to
   it.

   Deliberately NOT padding added to the hire root: that would change the
   product page too, where the theme's container already provides the gutter
   and nobody reported a problem.

   Same token as the EPO block solving this in the same slot (mbpos-epo.css),
   but NOT its selector shape. EPO has to reach for `.mbpos-lightbox__panel
   .mbpos-products-detail__addons >` because it has no variant class of its
   own; the booking mount already carries `mbb-widget--pos`, set by the modal
   renderer and by nothing else. Keying on that is both narrower and
   [data-mbb]-first, so M26's isolation rule holds without widening its
   allowlist — which its own comment says must not grow by reflex.

   Override per template with --mbb-pos-gutter.

   Not applied to the covers mount: it already pads its own root, and adding
   this would double it. */
[data-mbb][data-mbb].mbb-hire-widget.mbb-widget--pos {
	padding-left: var(--mbb-pos-gutter, var(--mbpos-space-2xs, 12px));
	padding-right: var(--mbb-pos-gutter, var(--mbpos-space-2xs, 12px));
}

/* [p3a5] Empty state — why nothing is bookable. */
[data-mbb] .mbb-hire-empty {
	margin: 10px 0 0; padding: 12px 14px; border-radius: 10px;
	background: var(--mbpos-color-warning-subtle, #fcf3e6); border-left: 4px solid var(--mbpos-color-warning-hover, #b25e09); color: var(--mbpos-color-heading, #1d2327);
}
[data-mbb] .mbb-hire-empty p { margin: 0; }
[data-mbb] .mbb-hire-empty-fix {
	margin-top: 8px !important; padding-top: 8px; border-top: 1px solid var(--mbpos-color-border, #e6d5bd);
	font-size: 13px; color: var(--mbpos-color-text-soft, #50575e);
}

/* [p3a7] Month paging + range highlight. */
[data-mbb] .mbb-hire-cal-nav {
	display: flex; align-items: center; justify-content: space-between;
	gap: 8px; margin-bottom: 8px;
}
[data-mbb] .mbb-hire-cal-title { font-weight: 600; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-nav {
	appearance: none; width: 32px; height: 32px; border-radius: 8px;
	border: 1px solid var(--mbpos-color-primary, #c3c4c7); background: var(--mbpos-color-primary, #fff); color: var(--mbpos-color-primary-text, #1d2327);
	font-size: 18px; line-height: 1; cursor: pointer;
}
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-nav:hover:not(:disabled) { background: var(--mbpos-color-primary-hover, #8c8f94); color: var(--mbpos-color-primary-hover-text, #fff); border-color: var(--mbpos-color-primary-hover, #8c8f94); }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-nav:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 2px; }
[data-mbb] .mbb-hire-nav:disabled { opacity: .35; cursor: not-allowed; }
/* [p3a35] The days BETWEEN pickup and return are a selection state, so they
   derive from `selected` — p3a31 skipped these two tints as "no matching
   token", which was wrong and left a hardcoded pale blue that no theme could
   move. `subtle` is the light variant of the same colour, so the range reads
   as a weaker version of its endpoints rather than an unrelated colour.
   The text colour must be set here too: the cell's own --mbb-cell-text is the
   contrast pick for the PRIMARY fill, and would be unreadable on this one. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-in-range {
	background: var(--mbb-range-bg);
	border-color: var(--mbpos-color-selected, #b8cbdd);
	color: var(--mbb-range-text);
}
[data-mbb] .mbb-hire-cal-hint {
	margin: 8px 0 0; font-size: 12px; color: var(--mbpos-color-text-muted, #787c82); text-align: center;
}

/* [p3a8] Per-day rate labels on calendar cells. */
/* [p3a31] The rate label sits at 10px, and 9px in the narrow container tier.
   Small text needs MORE contrast than the ratio alone suggests, so this uses
   the body text token rather than the softer one it had — `text-soft` is for
   secondary prose at normal size, not for a price the customer is reading to
   make a decision. Weight does some of the work too. */
[data-mbb] .mbb-hire-day-r {
	display: block; font-size: 10px; line-height: 1.2;
	/* [p3a34] currentColor, so the price follows whatever contrast pick the
	   cell made. A fixed token here was legible on a near-white cell and
	   invisible on a saturated one. */
	color: currentColor; opacity: .85; font-weight: 600;
	font-variant-numeric: tabular-nums; margin-top: 1px;
}
/* [p3a34] Weekend rates were amber — `warning`, documented as "caution
   notices", which a higher price is not, and unreadable on a coloured cell.
   Weight and full opacity carry the signal instead. */
[data-mbb] .mbb-hire-day.is-wknd .mbb-hire-day-r { opacity: 1; font-weight: 700; }
/* [p3a31] Was a fixed #dcdcde — a light grey picked for one specific selected
   fill, which becomes unreadable the moment that fill changes. primary-text
   is auto-picked for contrast against the fill actually in use. */
[data-mbb] .mbb-hire-day.is-sel .mbb-hire-day-r,
[data-mbb] .mbb-hire-day.is-sel.is-wknd .mbb-hire-day-r { color: var(--mbpos-color-selected-text, #dcdcde); opacity: .9; }

/* [p3a9] Calendar arrows centred (default button padding pushed the glyph
   off-centre), selection ticks, clear control, day length chip. */
[data-mbb] .mbb-hire-nav {
	display: inline-flex; align-items: center; justify-content: center;
	padding: 0; line-height: 1;
}
[data-mbb] .mbb-hire-day { position: relative; }
[data-mbb] .mbb-hire-tick {
	position: absolute; top: 3px; right: 4px; width: 11px; height: 11px;
}
[data-mbb] .mbb-hire-tick::after {
	content: ""; position: absolute; left: 3px; top: 0; width: 4px; height: 8px;
	border: solid var(--mbpos-color-heading, #1d2327); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
[data-mbb] .mbb-hire-day.is-sel .mbb-hire-tick::after { border-color: var(--mbpos-color-surface, #fff); }
[data-mbb] .mbb-hire-cal-clear { margin: 6px 0 0; text-align: center; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-clear {
	appearance: none; background: none; border: 0; padding: 4px 8px;
	font: inherit; font-size: 12px; color: var(--mbpos-color-primary, #2271b1); cursor: pointer; text-decoration: underline;
}
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-clear:focus-visible { outline: 2px solid var(--mbpos-color-primary, #2271b1); outline-offset: 2px; }
[data-mbb] .mbb-hire-len {
	display: inline-block; margin-right: 8px; padding: 2px 8px; border-radius: 999px;
	background: var(--mbpos-color-primary, #1d2327); color: var(--mbpos-color-primary-text, #fff); font-size: 12px; font-weight: 600;
}

/**
 * [p3a13] Containment. The island was authored against a full-width
 * column; auto-mount (p3a12) put it inside the product summary, which on
 * most themes is roughly half that. Two things then broke the calendar out
 * of its own border:
 *
 *   1. Grid children default to `min-width: auto`, which means a cell
 *      REFUSES to shrink below its content — seven cells plus gaps simply
 *      overflowed rather than compressing.
 *   2. The calendar carried padding without `box-sizing: border-box`, so
 *      its 100% width became 100% + 20px.
 *
 * Fixed by sizing rather than by clipping: nothing is hidden, the cells
 * just compress properly. `overflow-wrap` on the shell is a backstop for
 * long add-on labels in a narrow column.
 */
[data-mbb].mbb-hire-widget,
[data-mbb].mbb-hire-widget *,
[data-mbb].mbb-hire-widget *::before,
[data-mbb].mbb-hire-widget *::after { box-sizing: border-box; }

[data-mbb].mbb-hire-widget {
	/* [p3a33] The island's own vocabulary, defaulting to POS tokens. Day
	   cells and text inputs both sat on `surface`, so changing it moved
	   both and there is no POS token that separates them. Naming the two
	   concepts makes them independently retargetable in one line instead
	   of across forty rules. See MBPOS-COLOUR-TOKENS.md. */
	/* [p3a34] Day cells carry the CTA colour. Text on them therefore comes
	   from --mbb-cell-text, the contrast pick for whatever fill is in use —
	   a fixed dark colour would be unreadable the moment the fill is
	   saturated. Selection stays on `selected`, which is what keeps the
	   chosen dates distinguishable from the other thirty. */
	--mbb-cell-bg: var(--mbpos-color-primary, #f6f7f7);
	--mbb-cell-hover: var(--mbpos-color-primary-hover, #fff);
	--mbb-cell-text: var(--mbpos-color-primary-text, #1d2327);
	/* [p3a37] The days between pickup and return. Solid `selected`, same as
	   the two ends: a tinted interior is the usual range-picker convention,
	   but it read as "some of my chosen days are less chosen than others".
	   The ends stay distinguishable by their ring, not by weight. Kept as a
	   variable so switching back to `selected-subtle` is one line. */
	--mbb-range-bg: var(--mbpos-color-selected, #1d2327);
	--mbb-range-text: var(--mbpos-color-selected-text, #fff);
	--mbb-field-bg: var(--mbpos-color-surface, #fff);
	width: 100%;
	max-width: 900px;       /* [p3a16] ceiling only — see D12 */
	overflow-wrap: break-word;
}

[data-mbb] .mbb-hire-cal { max-width: 100%; padding: 8px; }

/* The load-bearing line: let grid cells actually shrink. */
[data-mbb] .mbb-hire-cal-grid,
[data-mbb] .mbb-hire-cal-head { min-width: 0; }
[data-mbb] .mbb-hire-cal-grid > *,
[data-mbb] .mbb-hire-cal-head > * { min-width: 0; }

[data-mbb] .mbb-hire-day-n { line-height: 1.15; }
[data-mbb] .mbb-hire-day-r { white-space: nowrap; }

/* Narrow columns: tighten inside the CALENDAR's own width, not the
   viewport's — the widget can sit in a 320px sidebar on a 1600px screen,
   so a viewport media query would measure the wrong box. */
[data-mbb] .mbb-hire-cal { container-type: inline-size; }

/* Injected into form.cart the theme may impose its own flex/grid; keep the
   island a plain block that fills the row it lands in. */
[data-mbb].mbb-hire-widget.mbb-widget--inject { display: block; flex: 1 1 100%; }

/**
 * [p3a14] Two faults from the p3a13 measurements. The container tier fix
 * (a 430px tier for the width a product-summary column actually is) was
 * correct and still stands. The "hard reset against theme button rules"
 * was not: see [p3a15] below for why it changed nothing.
 *
 * `overflow: hidden` on the cell CLIPPED the price instead of fitting it.
 * Clipping is never the right answer for a number the customer is being
 * asked to agree to: a truncated price is worse than no price.
 */
[data-mbb] .mbb-hire-day-n,
[data-mbb] .mbb-hire-day-r {
	display: block;
	width: 100%;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;   /* if it truly cannot fit, say so visibly */
	white-space: nowrap;
}

/**
 * [p3a15] THE CONTAINMENT CHAIN — one writer for the day cell's box and flow.
 *
 * p3a13 and p3a14 each "hardened" this cell and each changed nothing on the
 * live site. Measured cause, from a rule-level cascade probe in Peter's
 * browser (11,822 rules scanned): the theme's product template carries, in an
 * inline <style>,
 *
 *     .fr-single-product-alpha__cart form.cart button:not(.added_to_cart)
 *         { min-width: var(--btn-width) }              (0,3,2)
 *
 * while every rule this sheet owned was (0,2,0) — [data-mbb] plus one class.
 * It lost on class count, before source order was ever consulted.
 *
 * The sting: `--btn-width` is UNDEFINED on that element. The declaration is
 * invalid at computed-value time, but it has already won the cascade, so it
 * does not fall through to our `min-width: 0` — it falls back to the
 * property's initial value, `min-width: auto`. We were not being beaten by a
 * competing value; we were being beaten by nothing, which resolves to exactly
 * the value we were trying to remove. `min-width: auto` on a grid item floors
 * each track at min-content: seven cells wanted 791px inside a 374px grid.
 *
 * The 20px rate label was the same fault one level down, not a second bug.
 * Nothing else in the document declares `width` on the label; while the cell
 * was min-content-sized, the child's percentage width had no definite basis
 * to resolve against and contributed as `auto`, so the label sized to its
 * text and the cell sized to the label.
 *
 * (0,4,0) clears (0,3,2) on class count regardless of element count. Two
 * near-misses look sufficient and are not: `[data-mbb][data-mbb] .mbb-hire-day`
 * is (0,3,0) and `[data-mbb] .mbb-hire-cal-grid > .mbb-hire-day` is (0,3,1).
 * Fence M29.1 pins the floor rather than the rule's contents, because M26 and
 * M28 both passed for the whole life of this defect.
 *
 * No `!important` and no dependency on the theme's private `--btn-*` names:
 * the first is a ceiling we may want later and cannot climb past, the second
 * couples this island to one theme's internals.
 *
 * LESSON FOR THE STANDARD: CSS isolation and cascade authority are different
 * properties. Scoping every selector to [data-mbb] makes this sheet unable to
 * leak OUT. It does nothing to stop a theme leaking IN.
 */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day {
	min-width: 0;
	width: 100%;
	max-width: 100%;
	margin: 0;
	padding: 5px 1px;
	overflow: visible;          /* never clip a price */
	display: flex;
	flex-direction: column;
	align-items: stretch;       /* children get the cell's width, not their own */
	text-align: center;
}

/* Tiers run WIDEST-FIRST. Both are max-width, both are (0,4,0): below 330px
   they both match and the later one wins, so an ascending order silently
   makes the tighter tier dead code — which is what p3a14 shipped by
   appending the 430 tier after the 330 one. M29.3 pins the ordering. */
@container (max-width: 430px) {
	[data-mbb] .mbb-hire-cal-grid,
	[data-mbb] .mbb-hire-cal-head { gap: 3px; }
	[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day { padding: 4px 0; }
	[data-mbb] .mbb-hire-day { border-radius: 6px; }
	[data-mbb] .mbb-hire-day-n { font-size: 13px; }
	[data-mbb] .mbb-hire-day-r { font-size: 9px; letter-spacing: -0.2px; }
	[data-mbb] .mbb-hire-cal-head span { font-size: 10px; }
	[data-mbb] .mbb-hire-tick { top: 2px; right: 2px; width: 9px; height: 9px; }
	[data-mbb] .mbb-hire-tick::after { left: 2px; width: 3px; height: 6px; }
}

@container (max-width: 330px) {
	[data-mbb] .mbb-hire-cal-grid,
	[data-mbb] .mbb-hire-cal-head { gap: 2px; }
	[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day { padding: 4px 0; }
	[data-mbb] .mbb-hire-day { border-radius: 6px; }
	[data-mbb] .mbb-hire-day-n { font-size: 13px; }
	[data-mbb] .mbb-hire-day-r { font-size: 8px; }
	[data-mbb] .mbb-hire-tick { top: 2px; right: 2px; width: 8px; height: 8px; }
	[data-mbb] .mbb-hire-tick::after { left: 2px; width: 3px; height: 6px; border-width: 0 2px 2px 0; }
	[data-mbb] .mbb-hire-cal-head span { font-size: 9px; }
}

/* [p3a20, revised p3cal1] Base held treatment, now only ever seen through
   .is-locked or .is-mine below. p3a20's "it is bookable" is no longer true
   of a foreign hold and never was — the server refused it the whole time
   while the calendar said "whoever pays first gets the machine". */
/* [hp1d] The length-discount promo.
   -subtle fill with its -strong pair, NOT -text: `success-text` is auto-picked
   for contrast against the saturated base and resolves to white on a light
   theme, which is how the hold notice ended up white-on-pink (p3cal1b). The
   pair travels together or it does not travel.
   Success rather than warning: this is good news, and the amber block already
   means "you cannot have these dates". */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-deal {
	margin: 10px 0;
	padding: 8px 10px;
	border-radius: 8px;
	border: 1px solid var(--mbpos-color-success, #16a34a);
	background: var(--mbpos-color-success-subtle, #f0fdf4);
	color: var(--mbpos-color-success-strong, #14532d);
	font-size: 13px;
}
/* One unit short: the same fact, weighted. Not a different colour — a nudge
   that shouts reads as pressure, and this one is true either way. */
/* [hp2e] The ladder. Tight leading and a modest marker — it is an offer list,
   not a feature grid, and three rungs should read in one glance. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-deal-list {
	margin: 0;
	padding-left: 18px;
	list-style: disc;
}
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-deal-list li { margin: 2px 0; }

/* [hp2e] The next rung, alongside the one that applied — lighter, because the
   confirmation is the news and this is the aside. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-deal-next { font-weight: 400; opacity: .85; }

[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-deal.is-nudge { font-weight: 700; }
/* [hp1e] Applied: the same green, weighted like the nudge — it is the payoff
   the nudge promised, and switching colour at the moment it lands would read
   as a different kind of message rather than the same one resolving. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-deal.is-live { font-weight: 700; }

[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-deal-tag {
	color: var(--mbpos-color-success-strong, #14532d);
	font-style: normal;
	font-weight: 700;
}

[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-held {
	border-color: var(--mbpos-color-warning, #d97706);
	border-style: dashed;
	background: var(--mbpos-color-warning-subtle, #fffbeb);
	/* [p3cal1b] The pair, restated. Every .is-held cell also carries
	   .is-locked or .is-mine today, both of which set a colour, so this is
	   currently unreachable — but a fill without its colour is a bug waiting
	   for the first cell that carries neither, and the whole point of the
	   fix2 invariant is that the pair travels with the fill. */
	color: var(--mbpos-color-warning-strong, #78350f);
}
/* [p3cal1] LOCKED — someone else's live hold. create_hold WILL refuse this
   span, so the calendar must not offer it. Deliberately NOT the .is-off
   treatment (opacity .35 + line-through): that says "the yard never does
   this", when in fact it is available and will be again shortly. Amber and
   solid-edged, cursor forbidden, full opacity — a wait, not a closure. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-held.is-locked {
	border-style: solid;
	border-color: var(--mbpos-color-warning-hover, #b45309);
	background: var(--mbpos-color-warning-subtle, #fffbeb);
	/* [p3cal1b] The pair MUST be restated, exactly as p3a35 says four rules
	   up: --mbb-cell-text is the contrast pick for the PRIMARY fill and is
	   unreadable on this one. Shipped without it, the day number and rate
	   were near-white on a pale tint.
	   -strong, not -text: `warning-text` is auto-picked against the BASE
	   warning colour (saturated), so on a light theme it resolves to white
	   and lands white-on-near-white here. Same defect pc1/pc2 fixed for
	   -hover and -strong elsewhere. The rate follows via currentColor,
	   which is what p3a34 built it for. */
	color: var(--mbpos-color-warning-strong, #78350f);
	cursor: not-allowed;
	opacity: 1;
	text-decoration: none;
}

/* [p3cal1] MINE — this visitor's own cart. p3sb1 makes the server accept
   these, so they stay selectable and get a statement of fact rather than a
   caution: no warning colour, no dashed edge. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-held.is-mine {
	border-style: solid;
	border-color: var(--mbpos-color-border, #E4E1DC);
	/* [p3cal1b] Hand the cell back to its OWN pair rather than inventing a
	   second one. The first draft painted `surface` here and left the colour
	   alone, which is the same mismatch as the locked cell: --mbb-cell-text
	   is picked against --mbb-cell-bg, so overriding one and not the other
	   guarantees the two disagree under some theme. A date in your own cart
	   is an ORDINARY available date wearing a badge; it should look like
	   one. */
	background: var(--mbb-cell-bg);
	color: var(--mbb-cell-text);
}

/* [p3cal1] The p3a25 selection ring is RETIRED. It existed so the held cue
   survived selection — but a foreign hold can no longer BE selected, so the
   rule is unreachable. Its raw #fbbf24 goes with it, which is a token
   standard improvement as a side effect rather than as a goal. Only the
   .is-mine case can now be both held and selected, and it is styled as an
   ordinary selection because that is exactly what it is. */

/**
 * [p3a16] D12 — the island's width is host-derived, not content-derived.
 *
 * MEASURED on SNH: the right column of the product grid is a stable 748px,
 * but the theme's add-to-cart wrapper caps itself with `max-width: max-content`.
 * A max-content cap measures OUR contribution, so the column reported 390px at
 * rest and 560px once the quote line ("Pick up … → return …") appeared — the
 * widget was sizing its own container, and the container was sizing the widget.
 * That is the width oscillation, and also what the p3a13 handover recorded as
 * the puzzling "523/539 after a click".
 *
 * The cap is on the theme's wrapper — our PARENT's parent — and CSS cannot
 * reach upward, so no [data-mbb]-scoped rule can undo it. The suppression
 * script tags that one element `data-mbb-host` (it already walks this DOM to
 * find form.cart), and we clear the cap on exactly that element.
 *
 * DELIBERATE EXCEPTION TO CSS-ISOLATION-STANDARD, the first this module has
 * taken beyond native suppression. The justification is narrow and should stay
 * narrow: the tag is only applied to a form that CONTAINS the island, and by
 * then native suppression has hidden everything else that form held, so the
 * wrapper contains nothing but us. Minimum intervention — ONE property. If a
 * future theme needs more than this to lay the island out, that is a case for
 * mounting outside the summary column (§8), not for growing this rule. M30
 * pins both the exception and its size.
 *
 * `max-width: 900px` on the island is a ceiling, not a target: on a
 * single-column theme the host can be the full page, and a 1300px-wide booking
 * form is not better than a 900px one.
 */
/* [p3a17] Doubled attribute = (0,2,0). MEASURED: the cap is
   `.fr-single-product-alpha__cart` at (0,1,0) in an inline <style>, so the
   single-attribute form tied it and lost on source order — p3a16 pinned this
   exception's SIZE but never that it could WIN, which is the exact gap M29
   closes one level down. Not an ID selector, so no !important is needed.
   M30 now pins the floor. */
[data-mbb-host][data-mbb-host] { max-width: none; }

/* The form is a flex item in that wrapper; on a row-flex host it would size to
   its content even once the cap is gone. Its native controls are already
   display:none by the rule above, so it holds nothing but the island. */
form.cart.mbb-native-suppress { width: 100%; }

/* [p3a25] The same warning in words, for touch users and anyone who does not
   hover. Deliberately calm: a statement of fact, not a countdown. */
[data-mbb] .mbb-hire-warn {
	margin: 0 0 6px;
	padding: 6px 8px;
	border-left: 3px solid var(--mbpos-color-warning, #d97706);
	background: var(--mbpos-color-warning-subtle, #fffbeb);
	/* [p3cal1b] Was warning-TEXT, which is auto-picked for contrast against
	   the BASE warning colour — on a light theme that resolves to white, and
	   this fill is near-white, so the notice rendered white-on-pink. Reported
	   from SNH. -strong is the dark shade of the same hue and is the pairing
	   the gifts modal (pc2) and pickup modal already use on a -subtle fill. */
	color: var(--mbpos-color-warning-strong, #78350f);
	font-size: 12px;
	line-height: 1.35;
}

/* [p3a26] The busy marker on a held date. STATIC once shown: a single
   fade-in draws the eye when the cell first renders and then stops. A looping
   animation would keep the compositor awake for as long as the page is open,
   on a phone, possibly scrolled far past the calendar — the sort of small
   always-on cost that adds up on a shared host. It would also make a true
   statement look like the fake-urgency widgets this deliberately is not. */
/* [p3a27] A filled badge, not punctuation. The dots were too quiet to read
   as a status at 9px inside an already-busy cell. Solid amber against the
   cell's pale fill carries at a glance without moving. */
/* [p3a28] The hidden twin reserves the row height, so a cell is the same
   size whether or not it is held and the grid never resizes when the
   selection changes. */
[data-mbb] .mbb-hire-busy.is-off { visibility: hidden; }
[data-mbb] .mbb-hire-busy {
	display: block;
	margin: 2px -1px -1px;
	padding: 1px 0;
	border-radius: 0 0 5px 5px;
	background: var(--mbpos-color-warning, #d97706);
	color: var(--mbpos-color-surface, #fff);
	font-size: 7px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.4px;
	animation: mbb-hire-fade 240ms ease-out 1;
}
@keyframes mbb-hire-fade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
	[data-mbb] .mbb-hire-busy { animation: none; }
}

/* [p3a27] The notice sits BELOW the calendar (Peter's preferred position),
   present whether or not a date is selected. */
[data-mbb] .mbb-hire-warn { margin: 8px 0 0; }

/* [p3a29] A held date that is currently un-pickable keeps its badge — it is
   still being booked by someone else, and hiding that just because the date
   cannot be clicked right now is how the cue disappeared the moment a pickup
   date was chosen. Muted, not removed. */
/* [p3cal1b] The muted badge repainted its background and kept `surface` as
   its colour — but `surface` was picked to sit on the AMBER base, so under a
   dark theme it is dark-on-grey and under a light one it is white on #a8a29e,
   about 2.3:1. Both fixed, because the grey itself is fixed by design (see
   the p3a31 note below): a token colour on a hardcoded fill can only ever be
   right by luck. */
[data-mbb] .mbb-hire-day.is-off .mbb-hire-busy { background: #a8a29e; color: #1d2327; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-off.is-held { border-color: #a8a29e; }

/* [p3a31] Deliberately NOT tokenised, each for a reason:
   #000 on the submit hover is replaced by primary-hover above — darkening a
   dark button on hover reads as "less available", and the token already
   computes the right direction for a light OR dark base.
   #a8a29e is the muted busy badge on a closed day, and #1d2327 is the text
   that sits on it: both fixed by design, because they must stay legible
   against whatever the theme sets — and a fill fixed by design needs its
   colour fixed by design too, or the pair breaks the moment the theme moves
   (p3cal1b).
   (p3cal1: #fbbf24, the held ring, was listed here too and is GONE — the ring
   existed so the held cue survived selection, and a foreign hold can no
   longer BE selected. An exemption outliving the thing it exempted is worse
   than no exemption: it reads as permission for a colour nobody can find.)
   (p3a35: all three of the tints previously listed here WERE mappable after
   all — the in-range pair derives from `selected`, the divider from `border`.
   "No matching token" was a failure to look, and it left a pale blue range
   that no theme could move.) */

/* [p3a32] THE PAINT FLOOR — why every interactive element above is prefixed
   `[data-mbb][data-mbb].mbb-hire-widget`.
   MEASURED on SNH: the theme's product template carries, in an inline <style>,
     .fr-single-product-alpha__cart form.cart button:not(.added_to_cart)
        { background-color: var(--button-color); color: var(--button-text) }
   at (0,3,2). It matches EVERY button in this island on the add-to-cart mount,
   so the day cells were painted in the theme's button colours and changing the
   MBPOS Appearance theme did nothing visible.
   p3a15 fixed exactly this for the cell's BOX (min-width, padding, display).
   The PAINT stayed at (0,2,0) and kept losing. Doubling the attribute gives
   (0,4,0), which clears (0,3,2) on class count without !important.
   The child spans (-n, -r, -m) are deliberately NOT raised: no theme rule
   targets them, and raising uncontested selectors spends specificity we may
   need later. */

/* [p3a36] The two ends read as one bar rather than two unrelated chips: the
   pickup keeps its left corners, the return its right, and the days between
   square off. Purely visual — the range is still three separate states. */
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-sel:not(.is-end) { border-radius: 8px 2px 2px 8px; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-end { border-radius: 2px 8px 8px 2px; }
[data-mbb][data-mbb].mbb-hire-widget .mbb-hire-day.is-in-range { border-radius: 2px; }
