diff --git a/tests/mobile-homepage.spec.js b/tests/mobile-homepage.spec.js index 2eef6fb..b01fea4 100644 --- a/tests/mobile-homepage.spec.js +++ b/tests/mobile-homepage.spec.js @@ -340,6 +340,88 @@ test("media text keeps its configured ordering at 768px", async ({ page }) => { await expect(contentLocator.locator(".reset")).toHaveCSS("display", "flex"); }); +test("mobile contact card matches the 402px reference geometry", async ({ + page, +}) => { + await page.goto(homepage); + + const cardLocator = page.locator(".contact-block.home-contact"); + const card = await getBox(cardLocator); + const heading = await getBox(cardLocator.locator(".contact-block__text")); + const cta = await getBox(cardLocator.locator(".contact-block__cta")); + const linework = await getBox( + cardLocator.locator(".contact-block__linework"), + ); + const lineworkLocator = cardLocator.locator(".contact-block__linework"); + const backgroundImage = cardLocator.locator(".contact-block__bg-image"); + const bandHeight = await cardLocator.evaluate((element) => + Number.parseFloat(getComputedStyle(element).borderBottomWidth), + ); + + expectNear(card.width, 343, 3); + expectNear(card.height, 502, 5); + expectNear(card.x, (402 - card.width) / 2, 2); + expectNear(bandHeight, 16, 1); + expectNear(heading.x - card.x, 33, 3); + expectNear(heading.y - card.y, 31, 4); + expectNear(cta.x - card.x, 33, 3); + expectNear(cta.y - card.y, 219, 5); + expectNear(cta.width, 173, 4); + expectNear(linework.y - card.y, 300, 5); + expectNear(linework.height, 186, 5); + expect(linework.x).toBeLessThanOrEqual(card.x); + await expect(lineworkLocator).toHaveCSS("overflow", "visible"); + await expect(backgroundImage).toHaveCSS("object-fit", "fill"); + await expect(cardLocator).toHaveCSS("border-radius", "16px 16px 0px 0px"); +}); + +test("mobile contact card scales proportionally and remains contained", async ({ + page, +}) => { + for (const width of [320, 767]) { + await page.setViewportSize({ width, height: 900 }); + await page.goto(homepage); + + const cardLocator = page.locator(".contact-block.home-contact"); + const card = await getBox(cardLocator); + const heading = await getBox( + cardLocator.locator(".contact-block__text"), + ); + + expect(card.x).toBeGreaterThanOrEqual(0); + expect(card.x + card.width).toBeLessThanOrEqual(width); + expectNear(card.width / width, 343 / 402, 0.015); + expectNear(card.height / card.width, 502 / 343, 0.025); + expectNear((heading.x - card.x) / card.width, 33 / 343, 0.01); + } +}); + +test("contact card restores the desktop layout at 768px", async ({ page }) => { + await page.setViewportSize({ width: 768, height: 900 }); + await page.goto(homepage); + + const card = page.locator(".contact-block.home-contact"); + + await expect(card).toHaveCSS("position", "absolute"); + await expect(card).toHaveCSS("border-bottom-width", "16px"); + await expect(card).toHaveCSS("border-radius", "24px 24px 0px 0px"); +}); + +test("mobile contact card matches the supplied visual reference", async ({ + page, +}) => { + await page.goto(homepage); + + await expect(page.locator(".contact-block.home-contact")).toHaveScreenshot( + "contact-reference.png", + { + animations: "disabled", + maxDiffPixelRatio: 0.025, + threshold: 0.08, + }, + ); +}); + test("mobile recent posts exposes previous and next controls", async ({ page, }) => { diff --git a/tests/mobile-homepage.spec.js-snapshots/contact-reference-chromium.png b/tests/mobile-homepage.spec.js-snapshots/contact-reference-chromium.png new file mode 100644 index 0000000..3c159d0 Binary files /dev/null and b/tests/mobile-homepage.spec.js-snapshots/contact-reference-chromium.png differ diff --git a/views/blocks/contact-block/contact-block.css b/views/blocks/contact-block/contact-block.css index 495bacf..03b1edb 100644 --- a/views/blocks/contact-block/contact-block.css +++ b/views/blocks/contact-block/contact-block.css @@ -2,17 +2,24 @@ .contact-block { background-color: var(--color-navy, #0d1f35); - border-bottom: 1rem solid var(--color-orange, #F26B53); + border-bottom: 1rem solid var(--color-orange, #f26b53); overflow: hidden; position: relative; - em { color: var(--color-secondary); font-style: normal; } + em { + color: var(--color-secondary); + font-style: normal; + } .contact-block__media { inset-block: 0; inset-inline-end: 0; mask-image: linear-gradient(to right, transparent 0%, black 30%); - -webkit-mask-image: linear-gradient(to right, transparent 0%, black 30%); + -webkit-mask-image: linear-gradient( + to right, + transparent 0%, + black 30% + ); position: absolute; } @@ -30,10 +37,6 @@ width: auto; } - .contact-block__content { - - } - &.home-contact { bottom: -25%; left: 50%; @@ -45,46 +48,62 @@ @media (max-width: 767px) { .contact-block { - border-bottom-width: 0.75rem; - border-radius: 0.75rem 0.75rem 0 0; + border-bottom-width: calc(100vw * 16 / 402); + border-radius: calc(100vw * 16 / 402) calc(100vw * 16 / 402) 0 0; + box-sizing: border-box; + padding-inline: 0 !important; + padding-top: 0 !important; } .contact-block .contact-block__media { inset: 0; - mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.9) 0%, rgb(0 0 0 / 0.45) 100%); - -webkit-mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.9) 0%, rgb(0 0 0 / 0.45) 100%); + mask-image: none; + -webkit-mask-image: none; } .contact-block .contact-block__bg-image { - object-fit: cover; + object-fit: fill; } .contact-block .contact-block__linework { - bottom: 0.75rem; + bottom: 0; height: auto; - max-width: 112%; - right: -32%; - width: 22rem; + left: calc(100% * -113 / 343); + max-width: none; + overflow: visible; + right: auto; + width: calc(100% * 414 / 343); } - .contact-block .contact-block__content { - min-height: 18.5rem; - padding: 2.25rem 1.5rem 2.75rem !important; + .contact-block.home-contact .contact-block__content { + margin: 0 !important; + max-width: none !important; + padding: calc(100vw * 31 / 402) calc(100vw * 33 / 402) 0 !important; + position: relative; + left: calc(100vw * 33 / 402 - 1rem); + width: 100% !important; + z-index: 2; } .contact-block .contact-block__text { - font-size: clamp(1.9rem, 8.7vw, 2.45rem); - line-height: 1.02; - max-width: 16rem !important; + font-size: calc(100vw * 28 / 402); + line-height: 1.08; + margin-bottom: calc(100vw * 37 / 402); + max-width: calc(100% * 260 / 343) !important; + } + + .contact-block .contact-block__cta { + padding-block: calc(100vw * 8.5 / 402); } .contact-block.home-contact { bottom: auto; + height: calc(100vw * 502 / 402); left: 50%; margin: 2.5rem auto -3.75rem; max-width: none; position: relative; transform: translateX(-50%); - width: min(calc(100vw - 2rem), 22.5rem); + width: calc(100vw * 343 / 402); } }