/**
 * Moving cost calculator.
 *
 * Every colour is written as var(--bm-token, fallback). When the Better Moving
 * theme is active its tokens win; standalone, the fallbacks keep the component
 * correct. That means the calculator can ship before the theme without ever
 * hardcoding a brand value that would need hunting down later.
 *
 * The tokens are on :root, not on .bm-calc, and that is load-bearing.
 *
 * They used to sit on .bm-calc, which was tidy right up until the contact page
 * reused .bm-calc__field for its own form without a .bm-calc anywhere above it.
 * Every var(--c-*) in those rules then resolved to nothing, and an unresolved
 * var does not fall back to the property's previous value — the whole
 * declaration is thrown out at computed-value time. `border: 1px solid
 * var(--c-ink-soft)` therefore became border-style: none, and the result was a
 * white field on a white card: present, focusable, submitting correctly, and
 * completely invisible. It took the focus ring with it, so keyboard users had
 * no idea where they were.
 *
 * Scoping tokens to a component is only safe while nothing outside the
 * component uses the component's classes. That stopped being true, so the
 * tokens moved up. Inheritance means .bm-calc reads them exactly as before.
 */

:root {
	--c-ink: var(--bm-ink-800, #0d3164);
	--c-ink-deep: var(--bm-ink-900, #06172f);
	--c-ink-soft: var(--bm-ink-500, #54687f);
	--c-ink-faint: var(--bm-ink-200, #c3cfe0);
	--c-paper: var(--bm-paper-50, #f7f9fb);
	--c-paper-sunk: var(--bm-paper-100, #eff3f7);
	--c-rule: var(--bm-paper-300, #cbd5e0);
	--c-signal: var(--bm-signal-700, #056a72);
	--c-signal-tint: var(--bm-signal-100, #dff4f6);
	--c-danger: var(--bm-danger, #b3261e);

	--f-body: var(--bm-font-body, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);
	--f-display: var(--bm-font-display, "Poppins", "Segoe UI", system-ui, sans-serif);
}

.bm-calc {
	box-sizing: border-box;
	max-inline-size: 46rem;
	margin-inline: auto;
	font-family: var(--f-body);
	color: var(--c-ink);
	background: var(--c-paper);
	border: 1px solid var(--c-rule);
	border-radius: 18px;
	padding: clamp(1.25rem, 4vw, 2.25rem);
	container-type: inline-size;
}

.bm-calc *,
.bm-calc *::before,
.bm-calc *::after { box-sizing: inherit; }

.bm-calc__progress {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin-block-end: 1.5rem;
}
.bm-calc__track {
	flex: 1;
	block-size: 4px;
	background: var(--c-paper-sunk);
	border-radius: 999px;
	overflow: hidden;
}
.bm-calc__fill {
	display: block;
	block-size: 100%;
	inline-size: 0%;
	background: var(--c-signal);
	border-radius: 999px;
	transition: inline-size 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
.bm-calc__count {
	font-size: 0.75rem;
	font-variant-numeric: tabular-nums;
	color: var(--c-ink-soft);
	white-space: nowrap;
}

.bm-calc__step { display: none; flex-direction: column; gap: 1.25rem; }
.bm-calc__step[data-active="true"] { display: flex; }

.bm-calc__legend {
	padding: 0;
	border: 0;
	font-family: var(--f-display);
	font-size: clamp(1.35rem, 3.5vw, 1.75rem);
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.015em;
	text-wrap: balance;
}
.bm-calc__hint {
	margin: 0.4rem 0 0;
	font-size: 0.9375rem;
	color: var(--c-ink-soft);
	max-inline-size: 52ch;
}
.bm-calc fieldset { border: 0; padding: 0; margin: 0; }

/* --- option cards -------------------------------------------------------- */
.bm-calc__options { display: grid; gap: 0.6rem; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); }
.bm-calc__options--wide { grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
.bm-calc__options--tight { grid-template-columns: repeat(auto-fit, minmax(5rem, 1fr)); }

.bm-calc__opt { position: relative; display: block; }
.bm-calc__opt input {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	inline-size: 100%;
	block-size: 100%;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}
.bm-calc__opt span {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	padding: 0.85rem 1rem;
	/* ink-500 clears the 3:1 non-text contrast requirement; the decorative
	   hairline used elsewhere in the brand does not, so it is not used here. */
	border: 1px solid var(--c-ink-soft);
	border-radius: 10px;
	background: transparent;
	font-size: 0.9375rem;
	line-height: 1.3;
	transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}
.bm-calc__opt small { font-size: 0.8125rem; color: var(--c-ink-soft); }
.bm-calc__opt input:hover + span { background: var(--c-paper-sunk); }
.bm-calc__opt input:focus-visible + span {
	outline: 2px solid var(--c-signal);
	outline-offset: 2px;
}
.bm-calc__opt input:checked + span {
	border-color: var(--c-ink);
	background: var(--c-ink);
	color: var(--c-paper);
	box-shadow: 0 2px 10px rgb(6 23 47 / 14%);
}
.bm-calc__opt input:checked + span small { color: var(--c-ink-faint); }

/* --- plain fields -------------------------------------------------------- */
.bm-calc__fields { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
/* The hint paragraph sits directly above the first field; without this the
   uppercase label collides with the sentence above it. */
.bm-calc__hint + .bm-calc__fields { margin-block-start: 1.1rem; }
.bm-calc__field { display: flex; flex-direction: column; gap: 0.35rem; }
.bm-calc__field label {
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--c-ink-soft);
}
.bm-calc__field input,
.bm-calc__field select,
.bm-calc__field textarea {
	font: inherit;
	font-size: 1rem;
	padding: 0.7rem 0.85rem;
	border: 1px solid var(--c-ink-soft);
	border-radius: 999px;
	background: #fff;
	color: var(--c-ink);
	inline-size: 100%;
}
.bm-calc__field input:focus-visible,
.bm-calc__field select:focus-visible,
.bm-calc__field textarea:focus-visible {
	outline: 2px solid var(--c-signal);
	outline-offset: 1px;
	border-color: var(--c-signal);
}
/*
 * The message box is not a pill.
 *
 * input, select and textarea shared one rule with border-radius: 999px. On a
 * single-line field that is the site's pill and it is right. On a box five rows
 * tall the same value curves the full height into an oval, and the curve eats
 * into the text: the placeholder's first character was being clipped, so
 * "Moving from Marrickville" read as "loving from Marrickville".
 *
 * The theme's own medium radius, so this matches the cards and the tiles rather
 * than inventing a third corner on the page. The fallback matches
 * --bm-radius-md in tokens.css; it is spelled out because this stylesheet has
 * to render if the theme's tokens are ever missing.
 *
 * Padding goes up with it. A pill needs horizontal room for its curve; a
 * rectangle does not, and 0.85rem against a straight edge reads tight.
 */
.bm-calc__field textarea {
	border-radius: var(--bm-radius-md, 10px);
	padding: 0.85rem 1rem;
	min-block-size: 8rem;
	resize: vertical;
}

.bm-calc__field--full { grid-column: 1 / -1; }

/* The box under "Other" in special items. Opened by ticking it. The [hidden]
   rule is restated for the same reason as .bm-calc__nav below: an author
   display rule added here later would otherwise beat the browser's. */
.bm-calc__other { margin-block-start: 1rem; }
.bm-calc__other[hidden] { display: none; }

/* The honeypot. Hidden from people without display:none, which some bots
   check for, and removed from the accessibility tree and tab order. */
.bm-calc__hp {
	position: absolute !important;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* --- navigation ---------------------------------------------------------- */

/* An author display rule beats the browser's [hidden] style. show() hides this
   whole bar on the confirmation step by setting nav.hidden, and without this
   line that had no effect: the Continue button stayed on screen after the
   enquiry had been sent, and pressing it ran show() past the last step, which
   threw and blanked the confirmation and its reference number. */
.bm-calc__nav[hidden] { display: none; }

/* The reason Continue is greyed out. A hint, deliberately not an error: the
   customer has not done anything wrong, they have just not finished yet. So it
   takes the muted ink and no red, and it sits above the button rather than
   below, where it is read before the control it explains. */
.bm-calc__blocked {
	margin-block: 1.25rem 0;
	padding-inline-start: 0.85rem;
	border-inline-start: 2px solid var(--c-signal);
	font-size: 0.9375rem;
	line-height: 1.55;
	color: var(--c-ink-soft);
	max-inline-size: 36rem;
}
.bm-calc__blocked[hidden] { display: none; }

.bm-calc__nav {
	display: flex;
	gap: 0.75rem;
	align-items: center;
	flex-wrap: wrap;
	margin-block-start: 0.5rem;
	padding-block-start: 1.25rem;
	border-block-start: 1px solid var(--c-rule);
}
.bm-calc__btn {
	font: inherit;
	font-size: 0.9375rem;
	font-weight: 600;
	padding: 0.8rem 1.5rem;
	border-radius: 999px;
	border: 1px solid transparent;
	cursor: pointer;
	transition: background-color 140ms ease, transform 90ms ease;
}
.bm-calc__btn:active { transform: translateY(1px); }
.bm-calc__btn:focus-visible { outline: 2px solid var(--c-signal); outline-offset: 2px; }
.bm-calc__btn--go { background: var(--c-ink); color: var(--c-paper); margin-inline-start: auto; }
.bm-calc__btn--go:hover { background: var(--c-ink-deep); }
.bm-calc__btn--go[disabled] { opacity: 0.45; cursor: not-allowed; }
.bm-calc__btn--back { background: transparent; color: var(--c-ink-soft); border-color: var(--c-ink-soft); }
.bm-calc__btn--back:hover { background: var(--c-paper-sunk); }
.bm-calc__btn--text { background: transparent; border: 0; color: var(--c-signal); text-decoration: underline; padding-inline: 0; }

/* --- estimate ------------------------------------------------------------ */
.bm-calc__estimate {
	display: none;
	flex-direction: column;
	gap: 0.5rem;
	padding: 1.25rem 1.35rem;
	margin-block-end: 1.5rem;
	background: var(--c-ink);
	color: var(--c-paper);
	border-radius: 10px;
}
.bm-calc__estimate[data-visible="true"] { display: flex; }
.bm-calc__estimate-label {
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--c-ink-faint);
}
.bm-calc__range {
	font-family: var(--f-display);
	font-size: clamp(1.75rem, 6vw, 2.5rem);
	font-weight: 700;
	line-height: 1.05;
	letter-spacing: -0.02em;
	font-variant-numeric: tabular-nums;
}
.bm-calc__range[data-loading="true"] { opacity: 0.45; }
.bm-calc__meta { font-size: 0.8125rem; color: var(--c-ink-faint); line-height: 1.45; }
/* An author display rule beats the browser's [hidden] style, so hiding must
   be restated here or the empty badge keeps its box. */
.bm-calc__narrow[hidden] { display: none; }
.bm-calc__narrow {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	align-self: flex-start;
	margin-block-start: 0.35rem;
	padding: 0.3rem 0.65rem;
	border-radius: 999px;
	background: rgb(255 255 255 / 12%);
	font-size: 0.75rem;
	font-weight: 600;
}

.bm-calc__result { display: flex; flex-direction: column; gap: 1.25rem; }
.bm-calc__result .bm-calc__estimate { display: flex; margin-block-end: 0; }

.bm-calc__notices { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.4rem; }
.bm-calc__notices li {
	font-size: 0.8125rem;
	color: var(--c-ink-soft);
	padding-inline-start: 1rem;
	position: relative;
	line-height: 1.45;
}
.bm-calc__notices li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: 0.55em;
	inline-size: 5px;
	block-size: 5px;
	border-radius: 50%;
	background: var(--c-ink-faint);
}

.bm-calc__error {
	padding: 0.8rem 1rem;
	border-radius: 999px;
	background: #fdeceb;
	border: 1px solid var(--c-danger);
	color: var(--c-danger);
	font-size: 0.875rem;
}
.bm-calc__error[hidden] { display: none; }

/* Same trap as .bm-calc__nav above. The contact page renders this panel with
   the hidden attribute until a message has actually been sent, so without this
   line every visitor arrived to "Thanks, that has reached us" and an empty
   reference - read out by screen readers, and present in the page text. */
.bm-calc__done[hidden] { display: none; }

.bm-calc__done {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	padding: 1.5rem;
	background: var(--c-signal-tint);
	border-radius: 10px;
}
.bm-calc__done h3 { margin: 0; font-family: var(--f-display); font-size: 1.35rem; }
.bm-calc__done p { margin: 0; font-size: 0.9375rem; color: var(--c-ink-soft); }

@media (prefers-reduced-motion: reduce) {
	.bm-calc *, .bm-calc *::before, .bm-calc *::after {
		transition-duration: 0.01ms !important;
		animation-duration: 0.01ms !important;
	}
}

/* --------------------------------------------------------------------------
   Before the script says it is running.

   The calculator is hidden and a short block offers the two routes that do not
   need it. The script sets data-ready as its last act, which swaps the two.
   Hiding by default rather than revealing by default is the whole point: if
   anything goes wrong, the visitor sees a phone number instead of a form that
   will not submit.
   -------------------------------------------------------------------------- */
.bm-calc:not([data-ready="true"]) .bm-calc__progress,
.bm-calc:not([data-ready="true"]) .bm-calc__estimate,
.bm-calc:not([data-ready="true"]) [data-form],
.bm-calc[data-ready="true"] .bm-calc__fallback {
	display: none;
}

.bm-calc__fallback {
	display: grid;
	gap: 0.85rem;
	padding: 1.75rem;
	border: 1px solid var(--c-rule, #cbd5e0);
	border-radius: 16px;
	background: var(--c-paper, #f7f9fb);
}
.bm-calc__fallback h3 { margin: 0; font-family: var(--f-display); font-size: 1.25rem; }
.bm-calc__fallback p { margin: 0; }
.bm-calc__fallback-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.bm-calc__fallback-note { font-size: 0.875rem; color: var(--c-ink-soft); }

/* --------------------------------------------------------------------------
   Mobile adaptation.

   Everything below 1280px, and nothing at or above it: the query cannot match
   at the desktop line, so what the calculator looks like on a laptop is
   arithmetic rather than a promise somebody has to keep in review.
   -------------------------------------------------------------------------- */
@media (max-width: 79.99rem) {
	/*
	 * The button bar goes to the bottom of the screen and stays there.
	 *
	 * It was static, laid out after the last question, and the questions are
	 * long. Measured against a 320x568 screen: the route step runs about
	 * 900px, the access step about 750px, the details step past 1000px. Back
	 * and Continue were 200 to 450 pixels below the fold on four of the nine
	 * screens, which means the visitor's next move was off screen on nearly
	 * half the form. That is a broken form rather than a scrolling
	 * inconvenience. A control nobody can see is a control nobody presses,
	 * and the one on this bar is the only way through the funnel.
	 *
	 * The ground is opaque and it is the calculator's own paper, which is also
	 * the estimate dialog's surface, so one value is correct whether the
	 * calculator is sitting in the page or has been moved into the modal.
	 * Without it the answers scroll through the bar.
	 *
	 * padding-block-end clears the iOS home indicator. env() resolves to 0px
	 * everywhere it does not apply, and the 0px fallback is spelled out
	 * because a bare env() is an invalid value on a browser that has never
	 * heard of it, and an invalid value throws the whole declaration away.
	 *
	 * z-index stays at 1 deliberately. The suburb listbox is at 40 and has to
	 * stay above this, because the route step is exactly where a pinned bar
	 * would otherwise cover the list the visitor is picking from.
	 */
	.bm-calc__blocked,
	.bm-calc__nav {
		/*
		 * One height, written once and used twice: the bar takes it as a
		 * floor and the message above takes the same number as its offset, so
		 * the two sit flush by arithmetic rather than by eye. 4.75rem is 76px
		 * against a bar that measures 72.6 naturally (20px of padding, a 1px
		 * rule, a 51.6px button), so the floor binds and the number is true
		 * rather than nearly true.
		 */
		--calc-bar-block-size: 4.75rem;
	}

	.bm-calc__nav {
		position: sticky;
		inset-block-end: 0;
		z-index: 1;
		min-block-size: var(--calc-bar-block-size);
		background: var(--c-paper);
		padding-block-end: env(safe-area-inset-bottom, 0px);
	}

	/*
	 * And the reason Continue is greyed out travels with it.
	 *
	 * That is the live region naming which of six fields is still missing. It
	 * sits about 80px above the button, so on the three tallest steps the
	 * visitor saw neither: a disabled control off the bottom of the screen
	 * and the explanation for it off the bottom as well. Pinning the bar on
	 * its own would have rescued the button and left the sentence behind,
	 * which is the worse half to lose, so the pair is pinned together.
	 *
	 * Its own paper ground and a little vertical padding, for the reason the
	 * bar has them: it is now something the answers pass underneath.
	 */
	.bm-calc__blocked {
		position: sticky;
		inset-block-end: calc(var(--calc-bar-block-size) + env(safe-area-inset-bottom, 0px));
		z-index: 1;
		padding-block: 0.5rem;
		background: var(--c-paper);
	}

	/*
	 * Where an advance scrolls to.
	 *
	 * show() brings the progress bar into view rather than the step, because
	 * a step taller than the screen aligns its own top edge and pushes the
	 * counter off. The site header is sticky and 5.25rem tall, so without a
	 * scroll margin the header lands on the counter the scroll just went to.
	 */
	.bm-calc__progress {
		scroll-margin-block-start: calc(var(--bm-header-h, 5.25rem) + 0.5rem);
	}

	/*
	 * The error message is not a pill either.
	 *
	 * The same bug already fixed for the textarea further up this file. One
	 * border-radius of 999px is the site's pill on a single line and an oval
	 * on anything taller, and the curve then cuts into the text. "We could
	 * not reach the server. Please check your connection and try again."
	 * wraps to three lines in a 288px content box, which is the width a
	 * 320px screen leaves, so the first line and the last were both being
	 * clipped by the corner. The theme's own medium radius, so this matches
	 * the cards and the tiles rather than inventing a third corner on the
	 * page, and the fallback is spelled out because this stylesheet has to
	 * render if the theme's tokens are ever missing.
	 */
	.bm-calc__error {
		border-radius: var(--bm-radius-md, 10px);
	}
}

@media (max-width: 29.99rem) {
	/*
	 * Keep the bar to one row on the narrowest screens.
	 *
	 * The bar wraps, and on the details step it would. Back is about 84px and
	 * "Send my answers" about 164px at the standard 1.5rem of side padding,
	 * which with the 0.75rem gap comes to 260px against the 240px a 320px
	 * screen leaves inside the page gutter and the card's own padding. Two
	 * rows would take the bar to roughly 137px, a quarter of a 568px screen,
	 * and would put the blocked message behind it rather than above it, since
	 * the offset above assumes one row.
	 *
	 * 1rem of side padding brings the pair to 228px and it fits. Nothing
	 * drops below a tap target: the buttons keep their full 52px height and
	 * the narrower of the two is still comfortably past 44px wide.
	 */
	.bm-calc__btn { padding-inline: 1rem; }
}
