/* ─────────────────────────────────────────────────────────────────────────────
   dentures.css: the standalone dentures landing page, and nothing else.

   This page does NOT load the main site's stylesheets. That stack is 250KB and
   was written for eleven pages; this is one page that people reach on a phone
   from a paid click, so it carries only what it draws. The brand is the same
   one: Poppins, #0053A3, square corners, and the GOV.UK focus state.

   Three things differ from the main site, all on purpose:

   - box-sizing IS global here. On the main site it is not. Do not copy rules
     between the two without checking.
   - Brand tokens are restated below. If the brand blue changes in
     moo-components.css, change --blue here as well.
   - Every brand-coloured rule on an interactive element is still written
     :not(:focus), so the yellow focus state can never be beaten.
   ───────────────────────────────────────────────────────────────────────────── */

@font-face { font-family: Poppins; font-style: normal; font-weight: 400; font-display: swap; src: url(Poppins-400.woff2) format("woff2"); }
@font-face { font-family: Poppins; font-style: normal; font-weight: 500; font-display: swap; src: url(Poppins-500.woff2) format("woff2"); }
@font-face { font-family: Poppins; font-style: normal; font-weight: 600; font-display: swap; src: url(Poppins-600.woff2) format("woff2"); }
@font-face { font-family: Poppins; font-style: normal; font-weight: 700; font-display: swap; src: url(Poppins-700.woff2) format("woff2"); }

:root {
  --blue:      #0053a3;   /* 7.59:1 on white */
  --blue-dark: #003f7d;
  --blue-deep: #002b57;
  --ink:       #0b0c0c;
  --text:      #24282c;
  --muted:     #50565c;
  --line:      #d5dbe1;
  --body:      #4a4a4a;   /* the website's secondary text, 8.86:1 on white */
  --mist:      #f3f5f7;
  --tint:      #eaf1f8;
  --on-blue:   #d6e5f5;
  --on-ink:    #dfe3e7;
  --green:     #00703c;
  --focus:     #ffdd00;

  /* The trifold's green ticked box, used by the tick strip under the hero. */
  --tickbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Crect width='20' height='20' fill='%2300703c'/%3E%3Cpath d='M4.6 10.3l3.5 3.5 7.3-7.3' fill='none' stroke='%23ffffff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* The same box for blue fields: white, with a brand-blue tick. */
  --tickbox-white: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Crect width='20' height='20' fill='%23ffffff'/%3E%3Cpath d='M4.6 10.3l3.5 3.5 7.3-7.3' fill='none' stroke='%230053a3' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  --gutter: 16px;
  --ease: cubic-bezier(.16, 1, .3, 1);
  --font: Poppins, Montserrat, "Helvetica Neue", Arial, sans-serif;
}

@media (min-width: 40.0625em) { :root { --gutter: 24px; } }
@media (min-width: 48.0625em) { :root { --gutter: 32px; } }

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: 96px;
}

/* The hero's link down the page glides there, unless the visitor has asked
   for less motion. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--text);
  background: #fff;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, p, ul, ol, dl, dd, figure, fieldset, legend, address { margin: 0; padding: 0; }
ul, ol { list-style: none; }
fieldset { border: 0; min-width: 0; }
address { font-style: normal; }
img { display: block; max-width: 100%; height: auto; }
svg { flex: none; }

::selection { background: var(--blue); color: #fff; }
.band--blue ::selection, .pcta ::selection, .sticker::selection, .shot__flag::selection { background: #fff; color: var(--blue); }

h1, h2, h3, h4 { color: var(--ink); font-weight: 600; text-wrap: balance; }

h1 {
  font-size: clamp(2.25rem, 1.35rem + 4.2vw, 3.75rem);
  line-height: 1.08;
  letter-spacing: -.03em;
}

h2 {
  font-size: clamp(1.875rem, 1.4rem + 2.2vw, 2.75rem);
  line-height: 1.12;
  letter-spacing: -.024em;
}

h3 { font-size: 1.375rem; line-height: 1.25; letter-spacing: -.01em; }

/* "Aesthetic dentures" and the price in the hero heading, in brand blue at the
   client's request. Large text, so 3:1 is the floor; it measures 7.59:1 on
   white. The price never breaks away from "from just". */
.h1__blue { color: var(--blue); }
.h1__blue:last-child { white-space: nowrap; }

/* "From just £399", on a line of its own under the heading, as the client
   wrote it (11 Oct 2026). Smaller than the line above, so the heading is not
   four full lines deep and the tick strip still fits the first screen. */
/* "2 to 3" stays on one line. */
.nb { white-space: nowrap; }

.h1__from { display: block; margin-top: .3em; font-size: .62em; line-height: 1.15; letter-spacing: -.02em; }

p { text-wrap: pretty; }

.lede {
  font-size: clamp(1.1875rem, 1.08rem + .5vw, 1.375rem);
  line-height: 1.5;
}


.tel { white-space: nowrap; font-variant-numeric: tabular-nums; }

.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

[hidden] { display: none !important; }

.wrap {
  width: min(100% - 2 * var(--gutter), 1216px);
  margin-inline: auto;
}

/* ── Links and focus ─────────────────────────────────────────────────────── */

a { text-decoration-thickness: max(1px, .0625rem); text-underline-offset: .18em; }
a:not(:focus) { color: var(--blue); }
a:not(:focus):hover { color: var(--blue-dark); text-decoration-thickness: 3px; }

/* The GOV.UK focus state: yellow block, black underline, black text. */
a:focus, summary:focus {
  outline: 3px solid transparent;
  background-color: var(--focus);
  color: var(--ink);
  box-shadow: 0 -2px var(--focus), 0 4px var(--ink);
  text-decoration: none;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  padding: 12px 16px; font-size: 1rem;
}
.skip:focus { position: static; display: block; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 52px;
  padding: 12px 22px;
  border: 2px solid transparent;
  font: 600 1.0625rem/1.2 var(--font);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color .2s var(--ease), color .2s var(--ease),
              border-color .2s var(--ease), transform .12s var(--ease);
}

.btn--big { min-height: 60px; padding: 14px 28px; font-size: 1.1875rem; }

.btn:active { transform: translateY(2px); }

.btn__go { transition: transform .3s var(--ease); }
.btn:hover .btn__go { transform: translateX(4px); }

/* Primary. The 3px bottom edge is the GOV.UK button, so this button and the
   one waiting in the booking journey are recognisably the same control. */
.btn--solid:not(:focus) { background: var(--blue); color: #fff; box-shadow: 0 3px 0 var(--blue-deep); }
.btn--solid:not(:focus):hover { background: var(--blue-dark); color: #fff; }

.btn--line:not(:focus) { background: #fff; color: var(--blue); border-color: var(--blue); }
.btn--line:not(:focus):hover { background: var(--tint); color: var(--blue-dark); border-color: var(--blue-dark); }

/* On blue fields the pair inverts: white fill for the primary, white outline
   for the phone. Hover restates the colour every time; a background-only
   hover has already cost this project a disappearing label once. */
.btn--white:not(:focus) { background: #fff; color: var(--blue); box-shadow: 0 3px 0 var(--blue-deep); }
.btn--white:not(:focus):hover { background: var(--tint); color: var(--blue-dark); }

.btn--ghost:not(:focus) { background: transparent; color: #fff; border-color: #fff; }
.btn--ghost:not(:focus):hover { background: #fff; color: var(--blue-dark); }

.btn:focus {
  outline: 3px solid transparent;
  background: var(--focus);
  border-color: var(--focus);
  color: var(--ink);
  box-shadow: 0 4px 0 var(--ink);
}

/* ── Phone line status ───────────────────────────────────────────────────── */

.status {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1rem;
  line-height: 1.3;
  color: var(--muted);
}

.status__dot {
  position: relative;
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #8a939b;
}

.status.is-open .status__dot { background: var(--green); }

.anim .status.is-open .status__dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--green);
  animation: ping 2.4s var(--ease) infinite;
}

@keyframes ping {
  0%   { transform: scale(1); opacity: .7; }
  70%, 100% { transform: scale(2.8); opacity: 0; }
}

/* ── Website components ──────────────────────────────────────────────────────
   Copied from moo-components.css at the client's request, so the landing page
   and the website read as one brand: the eyebrow, the live eyebrow with its
   green dot, and the line under the hero buttons. Values are the website's. */

.eyebrow {
  display: block;
  margin: 0 0 10px;
  font-size: .8125rem;
  font-weight: 700;
  line-height: 1.45;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--blue);
}

.eyebrow--live { display: inline-flex; align-items: flex-start; gap: 9px; margin-bottom: 16px; }

.dot {
  flex: none;
  width: 9px;
  height: 9px;
  margin-top: 5px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 3px rgba(0, 112, 60, .18);
}

.urgency { margin-top: 20px; font-size: .875rem; line-height: 1.5; color: var(--body); }

/* 16px on a desktop, at the client's request (11 Oct 2026). The website's
   own line is 14px, and it stays 14px on a phone. */
@media (min-width: 60em) {
  .urgency { font-size: 1rem; }
}

/* ── Header ──────────────────────────────────────────────────────────────── */

.bar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: #fff;
  border-bottom: 1px solid var(--line);
}

.bar__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 68px;
  padding-block: 10px;
}

/* An <img>, not a link. On the main site the logo goes home; here there is
   nowhere to go that is not an exit. */
.bar__logo { width: auto; height: 36px; }

.bar__home { display: block; }
.bar__home:focus { box-shadow: 0 -2px var(--focus), 0 4px var(--ink); }

.bar__right { display: flex; align-items: center; gap: 12px; }

.bar .btn { min-height: 48px; padding: 8px 16px; font-size: 1rem; }

.bar__status, .bar__book { display: none; }

/* WhatsApp, a round button beside the phone number, at the client's request.
   The green is a shade darker than WhatsApp's own #25D366, which is only
   1.98:1 on white; #1DA851 keeps the brand look and clears the 3:1 that a
   control's outline needs. White icon on it, 3.1:1, for a 26px glyph. */
.wa {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  transition: background-color .2s var(--ease), transform .12s var(--ease);
}

.wa:not(:focus) { background: #1da851; color: #fff; }
.wa:not(:focus):hover { background: #168f41; color: #fff; }
.wa:active { transform: scale(.94); }
.wa:focus { background: var(--focus); color: var(--ink); box-shadow: 0 0 0 3px var(--ink); outline: 3px solid transparent; }

/* From tablet up, where there is no bottom bar, the button leaves the header and
   floats in the bottom right corner of the screen, at the client's request.
   It is still the same link in the header's markup, so the order a keyboard or
   screen reader meets it in does not change. */
@media (min-width: 40.0625em) {
  .bar__wa {
    position: fixed;
    right: 24px;
    bottom: 24px;
    z-index: 55;
    width: 60px;
    height: 60px;
    /* A white ring, not a shadow: the client wants no shadows anywhere. It
       keeps the button's edge clear over a photograph or the blue band. */
    box-shadow: 0 0 0 3px #fff;
  }
  .bar__wa svg { width: 32px; height: 32px; }
}

/* On a phone the bar holds logo, number and WhatsApp, so the number loses its
   icon and some padding. The logo takes whatever width is left: the number and
   WhatsApp need about 248px with the gutters and gaps, and the logo is 3.2
   times as wide as it is tall. That gives the desktop's 44px from 390px
   phones up, 40px at 375px and 28px at 320px. */
@media (max-width: 26em) {
  .bar__in { gap: 10px; }
  .bar__logo { height: clamp(28px, (100vw - 248px) / 3.2, 44px); }
  .bar__call { padding-inline: 12px; }
  .bar__call .btn__icon { display: none; }
  .bar__right { gap: 8px; }
}

/* The smallest phones, 320px: a little less of everything, or the bar runs
   10px off the edge. */
@media (max-width: 22em) {
  .bar .bar__call { padding-inline: 10px; font-size: .9375rem; }
  .wa { width: 44px; height: 44px; }
}

@media (min-width: 40.0625em) {
  .bar__logo { height: 44px; }
  .bar__book { display: inline-flex; }
  .bar .btn { padding: 8px 20px; }
}

@media (min-width: 64em) {
  .bar__status { display: flex; margin-right: 12px; }
}

/* ── Hero ────────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  padding-block: clamp(32px, 5vw, 64px) clamp(48px, 7vw, 88px);
  overflow: hidden;
  overflow: clip;
}

.hero__grid { display: grid; gap: 40px; }

.hero .lede { margin-top: 20px; max-width: 35em; }

.actions { display: flex; flex-wrap: wrap; gap: 14px 16px; margin-top: 32px; }
.actions .btn { flex: 1 1 100%; }


.hero__media { position: relative; }

/* The hero picture is the client's own artwork: an upright picture of a
   couple with the logo's smile drawn across its foot (12 Oct 2026, on
   orange and without the logo; the day before it was the same couple on
   lilac with the logo in its corner). It is shown whole, never cropped to a
   wide strip, or the smile would be cut off. On a phone and a tablet it keeps its own shape,
   up to 460px wide. */
.hero__media { max-width: 460px; }

.hero__img {
  width: 100%;
  aspect-ratio: 848 / 1264;
  object-fit: cover;
  object-position: 50% 30%;
}

/* The Aesthetic denture, set against the photograph. It puts the product
   itself in the first screen, under the claim it has to prove.

   On a phone it is a low, wide card tucked under the bottom edge of the
   picture. As a tall card over the corner it covered her face. From 60em it
   becomes that tall card, where the picture is tall enough to spare a corner. */
.shot {
  position: relative;
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  align-items: center;
  width: calc(100% - 32px);
  max-width: 26rem;
  margin: -40px 0 0 16px;
  padding-top: 12px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(11, 12, 12, .08);
}

/* A sticker, not a bar: capitals, straddling the top edge of the card. Brand
   blue, like the band on the Aesthetic card below, at the client's request
   (11 Oct 2026); it was green first. Green now marks only a genuine saving
   and the ticked boxes. White on the blue measures 7.59:1. */
.shot__flag {
  position: absolute;
  top: 0;
  left: 12px;
  z-index: 1;
  padding: 4px 9px;
  background: var(--blue);
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translateY(-50%);
}

.shot img { width: 100%; aspect-ratio: 3 / 2; object-fit: contain; padding: 8px 4px 8px 10px; }

.shot figcaption { padding: 8px 14px; font-size: 1rem; line-height: 1.35; color: var(--text); }

/* The card's name is a link that opens the Aesthetic details sheet, with an
   arrow, at the client's request. Its ::after covers the card, so the whole
   card is the target. The name is ink and the arrow brand blue, both
   :not(:focus) so the yellow focus block still wins. */
.shot__link { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 1rem; font-weight: 600; text-decoration: none; }
.shot__link::after { content: ""; position: absolute; inset: 0; }

/* On a phone the name sits beside a small picture: a size smaller and a
   little less padding keep "Aesthetic Dentures" on one line from 360px up. */
@media (max-width: 26em) {
  .shot figcaption { padding: 8px 12px; }
  .shot__link { gap: 8px; font-size: .9375rem; }
}
.shot__link:not(:focus) { color: var(--ink); }
.shot__link:not(:focus):hover { color: var(--blue); }
.shot__link:not(:focus) .shot__arrow { color: var(--blue); }
.shot__arrow { transition: transform .3s var(--ease); }
.shot__link:hover .shot__arrow { transform: translateX(3px); }

@media (min-width: 30em) {
  .actions .btn { flex: 0 1 auto; }
}

@media (min-width: 60em) {
  /* A hard split: white for the words, a pale blue field behind the picture.
     The photograph straddles the line, which is what gives the hero depth
     without a shadow or a gradient. */
  .hero {
    background: linear-gradient(90deg, #fff calc(50% + 190px), var(--tint) calc(50% + 190px));
  }

  .hero__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 72px;
    align-items: center;
  }

  /* The tick strip under the hero should be on the first screen, at the
     client's request. So the photograph takes the screen's height, less the
     header (about 69px), the strip (about 74px), the hero's padding (88px)
     and a little to spare, instead of a fixed 4:5. It stops at 640px, about
     4:5, on tall screens. The words need 421px, so below that the hero is as
     tall as they are, and the strip still fits a 1366 by 768 laptop. */
  .hero { padding-block: 40px 48px; }

  /* The picture is upright artwork and is never cropped: its sides were
     trimmed on a tall screen at first, which pushed the logo in its corner
     against the edge, and the client noticed. So the box is as wide as the
     picture would be at the height the screen allows (that height times its
     0.6709 shape), or as wide as the column if that is less, and the
     picture fills the box at its own shape. It sits in the middle of its
     column, on the pale blue field. */
  .hero__media {
    justify-self: center;
    width: min(100%, clamp(400px, 100vh - 240px, 640px) * .6709);
    width: min(100%, clamp(400px, 100svh - 240px, 640px) * .6709);
    max-width: none;
  }
  .hero__img { width: 100%; height: auto; }

  /* Smaller than it was, hung a little below the picture's bottom left
     corner, and never reaching more than 23% of the way across it: the
     woman's face starts just past that (24% across in the orange picture),
     and on a short screen the picture is narrow, so a fixed offset put the
     card over her mouth. Check this figure whenever the picture changes. */
  /* 224px, and the name is not allowed to wrap: "Aesthetic Dentures" sits on
     one line beside its arrow, at the client's request. */
  .shot { position: absolute; display: block; left: auto; right: 77%; bottom: -20px; width: 224px; margin: 0; }
  .shot__link { white-space: nowrap; }
  .shot { padding-top: 16px; }
  .shot img { padding: 6px 10px 0; }
  .shot figcaption { padding: 6px 14px 14px; }
}

/* A short desktop screen, such as a 1366 by 768 laptop, which shows about
   657px. The heading is three lines and a price line, so here it is a size
   smaller and the hero's padding is tighter, or the tick strip slips under
   the first screen. */
@media (min-width: 60em) and (max-height: 719px) {
  .hero { padding-block: 24px 32px; }
  .hero h1 { font-size: 3rem; }
}

/* ── Tick strip ──────────────────────────────────────────────────────────── */

.facts { border-block: 1px solid var(--line); }

.facts__list { display: grid; padding-block: 10px; }

.facts__list li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block: 9px;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
}

.facts__list li::before {
  content: "";
  flex: none;
  width: 20px;
  height: 20px;
  background: var(--tickbox) center / contain no-repeat;
}

@media (min-width: 40.0625em) {
  /* Three points, spread evenly across the full width: the first on the
     left edge, the last on the right, equal gaps between. */
  .facts__list { grid-template-columns: repeat(3, auto); justify-content: space-between; column-gap: 24px; padding-block: 14px; }
}

@media (min-width: 72em) {
  .facts__list { padding-block: 16px; }
}

/* On a desktop the strip is the last thing on the first screen, so the
   floating WhatsApp button (60px, 24px from the corner) would sit on the end
   of the third point. Up to about 1440px the page's right margin is narrower
   than the button, so the strip keeps 104px clear of the screen's right edge
   (the button, a 20px gap, room for a scrollbar). Wider screens need nothing. */
@media (min-width: 60em) {
  .facts__list { padding-right: max(0px, 104px - (100vw - min(100vw - 2 * var(--gutter), 1216px)) / 2); }
}

/* ── Bands ───────────────────────────────────────────────────────────────── */

.band { padding-block: clamp(56px, 8vw, 104px); }
.band--mist { background: var(--mist); }
.band--tint { background: var(--tint); }
.band--blue { background: var(--blue); color: #fff; }

.band--blue h2 { color: #fff; }



.head { max-width: 46rem; margin-bottom: clamp(32px, 4vw, 48px); }
.head .lede { margin-top: 16px; }

/* ── What makes it look real ─────────────────────────────────────────────── */

.look { display: grid; gap: 24px; }

.look__figure { position: relative; background: #fff; border: 1px solid var(--line); }

/* 3:2 image in a 3:2 box, so the pins below can be placed by percentage and
   stay on the gum and the teeth at every width. */
.look__figure img { width: 100%; aspect-ratio: 3 / 2; object-fit: contain; }

.pin, .points__n {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  background: var(--blue);
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.pin {
  position: absolute;
  left: var(--x);
  top: var(--y);
  margin: -16px 0 0 -16px;
  box-shadow: 0 0 0 3px #fff;
}

.points li {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  column-gap: 16px;
  padding-block: 18px;
  border-top: 1px solid var(--line);
}

.points li:first-child { padding-top: 4px; border-top: 0; }

.points__n { grid-row: span 2; margin-top: 2px; }

.points h3 { font-size: 1.25rem; }

.points p { margin-top: 2px; }

.look__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
  margin-top: 10px;
  padding-top: 24px;
  border-top: 2px solid var(--ink);
}

.look__price strong { font-weight: 600; color: var(--ink); }

/* The whitening section borrows this layout. Its picture is a 4:3 card
   picture, and its foot carries the two prices and a button, stacked. */
.look__figure--kit img { aspect-ratio: 4 / 3; }
.look__head .eyebrow { margin-bottom: 10px; }
.look__head .lede { margin-top: 14px; }

/* The whitening layout, at the client's request (11 Oct 2026): with the
   heading in the narrow right column the words ran well past the picture.
   The heading now runs across the top, and the picture and the points sit in
   two equal columns of the same height: the picture stretches to the height
   of the words, and the prices and the button sit at the foot of theirs. */
@media (min-width: 60em) {
  /* .look.look--top, not .look--top: the base .look rule for this width comes
     later in the file and would otherwise win. */
  .look.look--top {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "head head" "figure body";
    grid-template-rows: auto auto;
    gap: 36px 56px;
    align-items: stretch;
  }
  .look--top .look__head { max-width: 46rem; }
  .look--top .look__figure img { height: 100%; aspect-ratio: auto; }
  .look--top .look__body { display: flex; flex-direction: column; }
  .look--top .look__foot { margin-top: auto; }
}

/* ── Three simple steps: the picture strip ─────────────────────────────────
   The picture area of the steps section is three photographs side by side,
   one for each step. After BYQ's image strip, at the client's request: with
   the script, the open picture is three times as wide as the other two, and
   the change eases over 0.7s (flex-grow is what moves, with BYQ's easing).
   One is always open. Without the script they are three equal pictures.

   It takes the place of .look__figure, so it fills the row beside the
   points from 60em and is a 4:3 block above them below that. No frame: these
   are photographs, not a product on white. Each picture carries its step's
   number, the same blue square as the list. */
.strip { display: flex; gap: 8px; aspect-ratio: 4 / 3; border: 0; background: none; }

.strip__item { position: relative; flex: 1 1 0; min-width: 0; overflow: hidden; background: var(--line); }
.strip__item img { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; }

.strip__n { position: absolute; left: 10px; top: 10px; }

.strip.is-live .strip__item { cursor: pointer; transition: flex-grow .7s cubic-bezier(.215, .61, .355, 1); }
.strip.is-live .strip__item.is-on { flex-grow: 3; cursor: default; }

/* The open picture carries its step's heading, at the client's request: a
   blue label in its bottom left corner, white on the brand blue (7.59:1).
   It appears once the picture has opened and goes at once when it closes.
   Only with the script, because without it no picture is wide enough. */
.strip__title {
  position: absolute;
  left: 10px;
  bottom: 10px;
  max-width: calc(100% - 20px);
  padding: 6px 12px;
  background: var(--blue);
  color: #fff;
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
}

.strip.is-live .is-on .strip__title { opacity: 1; visibility: visible; transition: opacity .3s linear .4s; }

@media (min-width: 40.0625em) {
  .strip__title { left: 12px; bottom: 12px; padding: 8px 14px; font-size: 1rem; }
}

@media (min-width: 60em) {
  .look--top .strip { aspect-ratio: auto; min-height: 340px; }
}

/* The steps' foot carries the two buttons. */
.look__foot--actions .btn { flex: 1 1 100%; }

@media (min-width: 30em) {
  .look__foot--actions .btn { flex: 0 1 auto; }
}
.look__foot--prices { display: block; padding-top: 0; }
.look__foot--prices .choice__prices { padding-top: 0; }
.look__foot--prices .choice__prices div:first-child { border-top: 0; }
.look__foot--prices .btn { margin-top: 20px; }

@media (min-width: 60em) {
  .look {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-areas: "figure head" "figure body";
    grid-template-rows: auto 1fr;
    gap: 28px 72px;
    align-items: start;
  }
  .look__figure { grid-area: figure; }
  .look__head { grid-area: head; }
  .look__body { grid-area: body; }
}

/* ── Details sheet ─────────────────────────────────────────────────────────
   "What makes it look real?", opened from the Aesthetic card. A native
   <dialog>: a panel down the right-hand side on a desktop, a sheet up from
   the bottom on a phone. Head and foot stay put and the middle scrolls, so
   Close and the calls to action are always on screen. No shadow, the client's
   rule: the dimmed page behind and a rule along the edge set it apart. */
.sheet {
  position: fixed;
  inset: 0 0 0 auto;
  width: min(560px, 100%);
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  border-left: 1px solid var(--line);
  background: #fff;
  color: var(--text);
  overflow: hidden;
}

.sheet[open] { display: flex; flex-direction: column; animation: sheet-right .34s var(--ease); }
.sheet.is-closing { animation: sheet-right-out .22s var(--ease) forwards; }

.sheet::backdrop { background: rgba(11, 12, 12, .6); }
.sheet[open]::backdrop { animation: sheet-fade .3s linear; }
.sheet.is-closing::backdrop { animation: sheet-fade-out .22s linear forwards; }

@keyframes sheet-right { from { transform: translateX(100%); } }
@keyframes sheet-right-out { to { transform: translateX(100%); } }
@keyframes sheet-up { from { transform: translateY(100%); } }
@keyframes sheet-up-out { to { transform: translateY(100%); } }
@keyframes sheet-fade { from { opacity: 0; } }
@keyframes sheet-fade-out { to { opacity: 0; } }

.sheet__head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--line);
}

.sheet__head h2 { font-size: 1.375rem; line-height: 1.2; letter-spacing: -.015em; }

.sheet .sheet__close { flex: none; min-height: 44px; padding: 6px 14px; gap: 8px; font-size: 1rem; }

.sheet__body { flex: 1 1 auto; min-height: 0; padding: 20px; overflow-y: auto; overscroll-behavior: contain; }
.sheet__body .eyebrow { margin-bottom: 12px; }

/* 3:2 image in a 3:2 box, so the pins hold their place on the gum and the
   teeth at every width. */
.sheet__figure { position: relative; margin-bottom: 20px; background: #fff; border: 1px solid var(--line); }
.sheet__figure img { width: 100%; aspect-ratio: 3 / 2; object-fit: contain; }

.sheet__prices { margin-top: 6px; padding-top: 0; border-top: 2px solid var(--ink); }
.sheet__prices div:first-child { border-top: 0; }

.sheet__foot {
  flex: none;
  display: grid;
  gap: 10px;
  padding: 14px 20px calc(14px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: #fff;
}

.sheet__foot .btn { min-height: 52px; }

/* Book gets the wider share, so its label stays on one line. */
@media (min-width: 30em) {
  .sheet__foot { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
}

/* A phone: the sheet comes up from the bottom, as tall as it needs to be and
   never the whole screen, so the page it belongs to still shows above it. */
@media (max-width: 40em) {
  .sheet { inset: auto 0 0 0; width: 100%; height: auto; max-height: 90vh; max-height: 90dvh; border-left: 0; border-top: 4px solid var(--blue); }
  .sheet[open] { animation-name: sheet-up; }
  .sheet.is-closing { animation-name: sheet-up-out; }
}

/* The page behind does not scroll while the sheet is open. */
.has-sheet, .has-sheet body { overflow: hidden; }

/* Without the script, or in a browser without <dialog>, the links to the
   sheet are ordinary links to it, and it shows in place as a plain block. */
.sheet:target:not([open]) {
  display: block;
  position: static;
  width: min(100% - 2 * var(--gutter), 46rem);
  height: auto;
  max-height: none;
  margin: 32px auto;
  border: 1px solid var(--line);
  overflow: visible;
}
.sheet:target:not([open]) .sheet__close { display: none; }

/* ── Empty slots ───────────────────────────────────────────────────────────
   Something the client has still to supply: the patient's video, their
   words, the dentist's portrait. Drawn with a dashed edge and a black flag,
   so nobody can take a slot for the real thing in a preview or a
   screenshot. build-landing.py warns while any is left. */
.slot { display: grid; place-items: center; align-content: center; gap: 12px; padding: 24px; background: #fff; border: 2px dashed #8a939b; text-align: center; color: var(--body); }
.slot svg { color: #8a939b; }
.slot p { max-width: 22em; font-size: .9375rem; line-height: 1.5; }

.slot__flag {
  display: inline-block;
  padding: 3px 8px;
  background: var(--ink);
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* ── Patient story ─────────────────────────────────────────────────────────
   After BYQ's video testimonials, which the client pointed to: one dark
   panel, a small label, a large pull quote with the name beneath it, and a
   tall video beside them. BYQ's panel is dark; here it is the pale blue
   tint, with ink text. A deep blue panel, then the closing section's blue,
   were both tried first and the client found they took all the attention
   so near the top of the page. Square, with no shadow. Ink on the tint
   measures 17:1, the blue label 6.5:1, the grey details 7.8:1. */
.story {
  display: grid;
  gap: 24px;
  padding: 28px 20px 32px;
  background: var(--tint);
}
.story > *, .about > * { min-width: 0; }

/* The section's heading, set as a label: the quote is the headline here. */
.story__label { font-size: .8125rem; font-weight: 700; line-height: 1.4; letter-spacing: .12em; text-transform: uppercase; color: var(--blue); }

.story__media { aspect-ratio: 4 / 5; }
.story__media video { display: block; width: 100%; height: 100%; object-fit: cover; background: #000; }

.story__quote { margin: 0; }
.story__quote blockquote { margin: 0; }

.story__quote blockquote::before {
  content: "\201C";
  display: block;
  height: .55em;
  margin-bottom: 14px;
  font-size: 5rem;
  font-weight: 700;
  line-height: 1;
  color: var(--blue);
}

.story__quote blockquote p { font-size: clamp(1.5rem, 1.1rem + 1.7vw, 2.25rem); font-weight: 500; line-height: 1.25; letter-spacing: -.015em; color: var(--ink); text-wrap: balance; }

.story__by { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; margin-top: 28px; font-size: .9375rem; line-height: 1.45; color: var(--body); }
.story__by strong { font-size: 1.0625rem; font-weight: 600; color: var(--ink); }

.story__foot .btn { width: 100%; }

@media (min-width: 30em) {
  .story__foot .btn { width: auto; }
}

/* The quote's empty slot. */
.story__quote[data-placeholder] { padding: 20px; border: 2px dashed #8a939b; }
.story__quote .slot__flag { margin-bottom: 18px; }

@media (min-width: 40.0625em) {
  .story { padding: 40px; }
}

@media (min-width: 60em) {
  .story {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-areas: "label media" "quote media" "foot media";
    grid-template-rows: auto 1fr auto;
    gap: 24px 64px;
    padding: 56px;
  }
  .story__label { grid-area: label; }
  .story__media { grid-area: media; }
  .story__quote { grid-area: quote; align-self: center; }
  .story__foot { grid-area: foot; }
}

/* ── About ─────────────────────────────────────────────────────────────────
   After two BYQ sections the client pointed to: a tall portrait with a name
   tag on it, and beside it a rule, a small label, a large statement and a
   divided list. Square corners and no shadows, as everywhere on this page. */
.about { display: grid; gap: 28px; }

.about__portrait { position: relative; margin: 0; }
.about__photo { aspect-ratio: 4 / 5; }
.about__portrait img { display: block; width: 100%; aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 15%; }

/* Who it is, on the photograph itself, in its bottom left corner. */
.about__tag {
  position: absolute;
  left: 16px;
  bottom: 16px;
  max-width: calc(100% - 32px);
  padding: 12px 16px;
  background: #fff;
  border-left: 5px solid var(--blue);
  font-size: .875rem;
  line-height: 1.45;
  text-align: left;
  color: var(--body);
}
.about__tag strong { display: block; font-size: 1.0625rem; font-weight: 600; color: var(--ink); }
.about__tag span { display: block; }

.about__copy { padding-top: 24px; border-top: 2px solid var(--ink); }
.about__copy .eyebrow { margin-bottom: 14px; }
.about__text { margin-top: 18px; max-width: 36em; font-size: 1.0625rem; line-height: 1.6; }

.about__list { margin-top: 28px; }

.about__list li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding-block: 16px;
  border-top: 1px solid var(--line);
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.4;
  color: var(--ink);
}

.about__list li:last-child { border-bottom: 1px solid var(--line); }

.about__list li::before {
  content: "";
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  background: var(--tickbox) center / contain no-repeat;
}

.about__actions { display: flex; flex-wrap: wrap; gap: 12px 16px; margin-top: 28px; }
.about__actions .btn { flex: 1 1 100%; }

@media (min-width: 30em) {
  .about__actions .btn { flex: 0 1 auto; }
}

@media (min-width: 40.0625em) and (max-width: 59.99em) {
  .about__portrait { max-width: 420px; }
}

/* Side by side, the portrait is as tall as the words: it is taken out of
   the flow and fills the row, as the photograph in three simple steps does. */
@media (min-width: 60em) {
  .about { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 72px; align-items: stretch; }
  .about__photo, .about__portrait img { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; }
  .about__portrait { min-height: 460px; }
  .about__tag { left: 20px; bottom: 20px; max-width: calc(100% - 40px); }
}

/* ── Prices ──────────────────────────────────────────────────────────────────
   The website's .mo-table, .mo-choice and .mo-flag, restated here with the
   website's values, because this page does not load moo-components.css.

   One change on purpose: no minimum table width. The website's tables are
   given min-width: 32rem and scroll sideways on a phone; these fit instead,
   with tighter cell padding below 40em. */

/* Only the "How you pay" table uses these now. */
.ptable-wrap { background: #fff; border: 1px solid var(--line); }

.ptable { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }

.ptable caption {
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink);
}

.ptable thead th {
  padding: 10px 20px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--body);
}

.ptable tbody th, .ptable tbody td {
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  text-align: left;
  font-size: .9375rem;
  line-height: 1.45;
}

.ptable tbody th { font-weight: 600; color: var(--ink); border-left: 3px solid transparent; }

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

.ptable tbody tr.is-pick { background: rgba(0, 83, 163, .05); }
.ptable tbody tr.is-pick th { border-left-color: var(--blue); }

.price { font-size: 1.0625rem; font-weight: 700; white-space: nowrap; color: var(--ink); }


/* A genuine saving, so it is green and not brand blue. The website's .mo-offer. */
.save {
  display: inline-block;
  padding: 2px 8px;
  background: var(--green);
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: .02em;
  white-space: nowrap;
}

.choices { display: grid; gap: 16px; }

.choice { display: flex; flex-direction: column; background: #fff; border: 1px solid var(--line); }

.choice__media { position: relative; }

.choice__media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: var(--mist); }

.sticker {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 1;
  padding: 3px 8px;
  background: var(--blue);
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.sticker--green { background: var(--green); }

.choice__body { display: flex; flex: 1 1 auto; flex-direction: column; padding: 18px; }

.choice__name { margin: 0 0 8px; font-size: 1.0625rem; font-weight: 700; line-height: 1.3; letter-spacing: 0; }

/* How many appointments and how long, on the card itself, at the client's
   request (11 Oct 2026). It replaced a separate panel in how it works. Small,
   under the name, with a rule beneath so it reads as the card's own facts
   and not as a fourth bullet. */
.choice__meta { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.choice__meta li { display: flex; align-items: center; gap: 6px; font-size: .8125rem; font-weight: 600; line-height: 1.4; color: var(--ink); }
.choice__meta svg { color: var(--blue); }

/* "See what makes it look real", on the Aesthetic card: it opens the details
   sheet. An ordinary link, so the global link and focus rules apply. */
.choice__more { display: inline-flex; align-items: center; gap: 8px; margin-top: 10px; font-size: .9375rem; font-weight: 600; line-height: 1.4; }
.choice__more svg { transition: transform .3s var(--ease); }
.choice__more:hover svg { transform: translateX(3px); }

.choice__list li {
  position: relative;
  margin-bottom: 4px;
  padding-left: 14px;
  font-size: .875rem;
  line-height: 1.55;
  color: var(--body);
}

.choice__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 4px;
  height: 4px;
  background: var(--ink);
}

/* The prices, inside the card: the client's call, in place of a separate
   table. Pushed to the foot of the card so the two cards in a row line up. */
.choice__prices { margin-top: auto; padding-top: 14px; }

.choice__prices div {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  padding-block: 10px;
  border-top: 1px solid var(--line);
}

.choice__prices dt { font-size: .9375rem; font-weight: 500; line-height: 1.4; color: var(--ink); }

/* The optional extra set, inside the card at the client's request. Small and
   quiet, also at the client's request: a tinted row with a large blue price
   took the attention from the denture's own prices. */
/* It does not wrap as a row: in a narrow card the label takes two lines and
   the price stays on the right, instead of dropping under the label. */
.choice__prices .is-extra { flex-wrap: nowrap; padding-block: 8px 0; }
.choice__prices .is-extra dt { font-size: .8125rem; font-weight: 400; color: var(--body); }
.choice__prices .is-extra dd { font-size: .8125rem; font-weight: 600; color: var(--body); }

/* The featured card of a row: the one the page steers people to. A 2px brand
   blue frame, as on the website's featured plan, and a blue band across the
   top. Both rows use the same blue, at the client's request: the Aesthetic
   band was green for a day. White on the blue measures 7.59:1. No shadow: the
   client wants none anywhere on the site. */
.choice--featured { border: 2px solid var(--blue); }

.choice__flag {
  padding: 7px 12px;
  background: var(--blue);
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: .08em;
  text-align: center;
  text-transform: uppercase;
}

/* Side by side, the featured card stands above and below its neighbours by
   the height of its band and a little more, and its own picture, words and
   prices stay level with theirs: 32px of band and a 2px frame against their
   1px, so 33px up; 12px down, 11px of it padding. The row leaves room for
   the band above. */
@media (min-width: 48em) {
  .choices--lift { padding-top: 33px; }
  .choices--lift .choice--featured { margin-top: -33px; margin-bottom: -12px; padding-bottom: 11px; }
}

/* A card whose photograph is not there yet. The box keeps the picture's 4:3,
   so the card still lines up with its neighbours. */
.choice__media--empty { aspect-ratio: 4 / 3; background: #fff; }
.choice__prices dt .save { margin-left: 6px; }

/* "From" before a price that can rise with the case, at the client's request:
   4 or more teeth. Smaller and quieter, so the figure still leads. */
.choice__prices .from { margin-right: 2px; font-size: .875rem; font-weight: 500; color: var(--body); }

.choice__prices dd {
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--blue);
}


.pfoot { display: grid; gap: 16px; margin-top: 40px; }

.pcta {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 16px;
  padding: 24px 20px;
  background: var(--blue);
  color: #fff;
}

.pcta__line { font-size: 1.375rem; font-weight: 600; line-height: 1.25; letter-spacing: -.01em; }

.pcta__actions { display: grid; gap: 12px; }

/* Small checkpoints under the buttons, at the client's request. */
.pcta__regs { display: grid; gap: 8px; padding-top: 4px; }

.pcta__regs li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.4;
  color: #fff;
}

.pcta__regs li::before {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 2px;
  background: var(--tickbox-white) center / contain no-repeat;
}


@media (max-width: 40em) {
  .ptable caption { padding: 14px 12px; }
  .ptable thead th { padding: 10px 8px; }
  .ptable tbody th, .ptable tbody td { padding: 14px 8px; }
  .ptable thead th:first-child, .ptable tbody th { padding-left: 12px; }
}

@media (min-width: 40.0625em) {
  .choices { grid-template-columns: 1fr 1fr; }
  .pcta { padding: 32px; }
}

/* Three cards in a row, for aftercare. One column until there is room for
   three, so a card is never left alone on a second row. */
.choices--3 { grid-template-columns: 1fr; }

@media (min-width: 48em) {
  .choices--3 { grid-template-columns: repeat(3, 1fr); }
}

/* Four cards, for aftercare: one column on a phone, two by two on a tablet,
   four in a row once each is wide enough for its price row. */
.choices--4 { grid-template-columns: 1fr; }

@media (min-width: 40.0625em) {
  .choices--4 { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 64em) {
  .choices--4 { grid-template-columns: repeat(4, 1fr); }
}

@media (min-width: 60em) {
  .pfoot { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 24px; }
}

/* ── Clinic or home ────────────────────────────────────────────────────────
   Two cards with one structure, so they read as a pair: a 4:3 picture, then
   title, where, price and a single outlined button pinned to the foot. */

.venue { display: grid; gap: 16px; }

.vcard { display: flex; flex-direction: column; background: #fff; border: 1px solid var(--line); }

.vcard__media { position: relative; display: block; overflow: hidden; }

.vcard__media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 50% 22%;
  background: var(--mist);
}

/* The map is centred on the clinic, so the pin sits dead centre. Muted a
   little, so the blue pin is the first thing the eye finds. */
.vcard__map img { object-position: 50% 50%; filter: saturate(.55); transition: transform .5s var(--ease); }
.vcard__map:hover img { transform: scale(1.03); }

.vcard__pin {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 30px;
  height: 30px;
  margin: -30px 0 0 -15px;
  border-radius: 50% 50% 50% 0;
  background: var(--blue);
  box-shadow: 0 0 0 3px #fff;
  transform: rotate(-45deg);
  transform-origin: 50% 100%;
}

.vcard__pin::after {
  content: "";
  position: absolute;
  inset: 10px;
  border-radius: 50%;
  background: #fff;
}

.vcard__credit {
  position: absolute;
  right: 0;
  bottom: 0;
  padding: 2px 6px;
  background: rgba(255, 255, 255, .88);
  font-size: .6875rem;
  line-height: 1.4;
  color: var(--text);
}

.vcard__body { display: flex; flex: 1 1 auto; flex-direction: column; padding: 20px 20px 22px; }

.vcard__body h3 { font-size: 1.375rem; }

.vcard__where { margin-top: 8px; line-height: 1.5; color: var(--text); }

.vcard__price { margin-top: 8px; font-weight: 600; color: var(--blue); }

/* Book, then the card's own second action. Both cards carry a Book button,
   at the client's request, so the pair stay matched.

   Pinned to the foot, so the buttons line up across the pair. Whatever
   line comes last before the button keeps 20px clear of it, so a card with
   less text above, like the clinic's, still has room when the cards stack. */
.vcard__actions { display: grid; gap: 12px; margin-top: auto; }
.vcard__body > :nth-last-child(2) { margin-bottom: 20px; }

/* A focused map link shows the focus ring round its picture. */
.vcard__map:focus { outline: 3px solid var(--focus); outline-offset: 0; box-shadow: 0 0 0 6px var(--ink); background: none; }

@media (min-width: 40.0625em) {
  .venue { grid-template-columns: 1fr 1fr; gap: 24px; }
  .vcard__body { padding: 24px 28px 28px; }
}

/* ── Questions ───────────────────────────────────────────────────────────── */

.faq { display: grid; gap: 32px; }


.faq details { border-top: 1px solid var(--line); }
.faq details:last-child { border-bottom: 1px solid var(--line); }

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding-block: 22px;
  font-size: 1.1875rem;
  font-weight: 600;
  line-height: 1.35;
  list-style: none;
  cursor: pointer;
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary:not(:focus) { color: var(--ink); }
.faq summary:not(:focus):hover { color: var(--blue); }

/* A plus that loses its upright when open. Drawn, not a glyph. */
.faq__icon { position: relative; flex: none; width: 20px; height: 20px; }

.faq__icon::before, .faq__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 2.5px;
  margin-top: -1.25px;
  background: currentColor;
  transition: transform .3s var(--ease);
}

.faq__icon::after { transform: rotate(90deg); }
.faq details[open] .faq__icon::after { transform: rotate(0deg); }

/* A clear gap under the question, so the answer never sits against it, even
   when the question has the yellow focus block and its black underline. */
.faq details p { margin-top: 10px; padding-bottom: 26px; max-width: 38em; }

@media (min-width: 60em) {
  .faq { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: 80px; align-items: start; }
  .faq__intro { position: sticky; top: 108px; }
}

/* ── Final call to action ────────────────────────────────────────────────── */

.close__grid { display: grid; gap: 36px; }

/* The client's own artwork, one of a set with the hero's: a woman pointing
   to her smile, with the logo's smile drawn across the picture. Since 12 Oct
   2026 it is the square one on orange, without the logo (the day before, an
   upright one on navy with the logo). Shown whole, at its own shape, like
   the hero's: change the aspect-ratio with the picture. */
.close__media { max-width: 460px; }
.close__media img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }

/* Paper texture on the blue closing section and the blue booking box, at the
   client's request. Two layers of noise drawn
   in an inline SVG: a slow mottle, like the cloud in uncoated paper, and a
   fine grain. Mixed in with overlay at low strength, so the blue stays the
   brand blue and white text on it still measures above 7:1. One tile, drawn
   once; nothing animates. */
.close, .pcta { position: relative; isolation: isolate; }

.close::before,
.pcta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.012' numOctaves='3' seed='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' seed='9' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)' opacity='.55'/%3E%3Crect width='100%25' height='100%25' filter='url(%23g)' opacity='.75'/%3E%3C/svg%3E") 0 0 / 320px 320px;
  mix-blend-mode: overlay;
  opacity: .22;
}

.close h2 { font-size: clamp(2.25rem, 1.4rem + 3.4vw, 3.25rem); line-height: 1.08; letter-spacing: -.03em; }

.close .lede { margin-top: 16px; max-width: 32em; color: #fff; }

/* The live eyebrow, turned for the blue field. */
.close .eyebrow { color: #fff; }
.close .dot { box-shadow: 0 0 0 3px rgba(255, 255, 255, .35); }

/* White ticked boxes, the trifold's on-blue version of the green ones. */
.close__ticks { display: grid; gap: 10px; margin-top: 24px; }

.close__ticks li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.4;
  color: #fff;
}

.close__ticks li::before {
  content: "";
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  background: var(--tickbox-white) center / contain no-repeat;
}

.close .actions { margin-top: 28px; }

.close__note { margin-top: 18px; font-size: 1rem; line-height: 1.5; color: var(--on-blue); }

.close__status { margin-top: 10px; color: var(--on-blue); }
.close__status .status__dot { background: var(--on-blue); }
.close__status.is-open .status__dot,
.anim .close__status.is-open .status__dot::after { background: #fff; }

@media (min-width: 60em) {
  .close__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 72px; align-items: center; }
  .close__media { max-width: none; }
}

/* ── Booking page (/book/) ───────────────────────────────────────────────────
   GOV.UK form patterns in this page's own clothes: labels above fields, hints
   under labels, a thick black input edge, the yellow focus, a red error bar
   on the field and an error summary at the top. Red is GOV.UK's #d4351d,
   measured 4.85:1 on white. */

.bk { padding-block: 24px 72px; }

.bk__wrap { max-width: 40rem; }

.bk h1 { font-size: clamp(2rem, 1.5rem + 2vw, 2.75rem); line-height: 1.12; letter-spacing: -.025em; }

.bk .lede { margin-top: 12px; }

.bk__back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 24px;
  padding-block: 8px;
  font-size: 1rem;
  font-weight: 500;
}

.bk__alt { margin-top: 24px; }

/* The clinic card from the landing page, on the "we do not visit" step. */
.bk__clinic { margin-top: 28px; }
.vcard__body h2 { font-size: 1.375rem; }

.bk__form { margin-top: 8px; }

.field { margin-top: 24px; }

.field__set { margin: 0; padding: 0; border: 0; }

.field__label { display: block; font-size: 1.1875rem; font-weight: 600; line-height: 1.35; color: var(--ink); }
.field__label--sub { font-size: 1.0625rem; }

/* Required fields carry a star, at the client's request, and a note at the top
   of each form says what it means. Screen readers hear "required" from
   aria-required on the input instead of the star. Red is the error red,
   4.85:1 on white. */
.req { margin-left: 2px; font-weight: 700; color: #d4351d; }
.bk__reqnote { margin-top: 20px; font-size: 1rem; color: var(--body); }

.field__hint { margin-top: 2px; font-size: 1rem; line-height: 1.45; color: var(--body); }

.field__error { margin-top: 4px; font-size: 1rem; font-weight: 600; line-height: 1.4; color: #d4351d; }

.input {
  display: block;
  width: 100%;
  max-width: 20rem;
  min-height: 52px;
  margin-top: 8px;
  padding: 10px 12px;
  background: #fff;
  border: 2px solid var(--ink);
  border-radius: 0;
  font: 400 1.1875rem/1.3 var(--font);
  color: var(--ink);
  -webkit-appearance: none;
  appearance: none;
}

.input--wide { max-width: 32rem; }

/* A select in the input's clothes, with a drawn chevron. */
.select {
  padding-right: 44px;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230b0c0c' stroke-width='2.4'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M5 9l7 7 7-7'/%3E%3C/svg%3E") no-repeat right 12px center / 20px 20px;
  cursor: pointer;
}

.input--tel { max-width: 15rem; }
.input--postcode { max-width: 9rem; text-transform: uppercase; }
.input--2 { width: 4rem; }
.input--4 { width: 6rem; }

.input:focus {
  outline: 3px solid var(--focus);
  outline-offset: 0;
  box-shadow: inset 0 0 0 2px var(--ink);
}

.field--error { padding-left: 14px; border-left: 5px solid #d4351d; }
.field--error .input { border-color: #d4351d; }
.field--error .input:focus { border-color: var(--ink); }

.dob { display: flex; gap: 16px; margin-top: 4px; }

/* GOV.UK radios: a 40px target, the circle drawn on the label. The input
   sits on top of the circle, invisible, so the whole row is clickable. */
.radios { display: grid; gap: 10px; margin-top: 10px; }
.radio { position: relative; min-height: 40px; padding-left: 52px; }
.radio__input { position: absolute; top: 0; left: 0; width: 40px; height: 40px; margin: 0; opacity: 0; cursor: pointer; z-index: 1; }
.radio__label { display: inline-block; padding: 8px 4px 6px; font-size: 1.1875rem; line-height: 1.35; color: var(--ink); cursor: pointer; }
.radio__label::before {
  content: "";
  box-sizing: border-box;
  position: absolute;
  top: 0;
  left: 0;
  width: 40px;
  height: 40px;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: #fff;
}
.radio__label::after {
  content: "";
  position: absolute;
  top: 10px;
  left: 10px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--ink);
  opacity: 0;
}
.radio__input:checked + .radio__label::after { opacity: 1; }
.radio__input:focus + .radio__label::before { border-width: 4px; box-shadow: 0 0 0 4px var(--focus); }
.dob__label { display: block; font-size: 1rem; line-height: 1.4; color: var(--ink); }

.bk__address-set { margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--line); }
.bk__legend { margin-bottom: -8px; }

.bk__privacy { margin-top: 28px; font-size: 1rem; line-height: 1.5; color: var(--body); }

.bk__submit { margin-top: 20px; }
.bk__submit:disabled { opacity: .6; cursor: progress; }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.errsum {
  margin-bottom: 32px;
  padding: 18px 20px 20px;
  border: 5px solid #d4351d;
}

.errsum:focus { outline: 3px solid var(--focus); outline-offset: 0; }

.errsum__title { font-size: 1.375rem; }

.errsum__list { margin-top: 12px; display: grid; gap: 8px; }

.errsum__list a:not(:focus) { color: #d4351d; font-weight: 600; }

.bk__fail { margin-top: 24px; padding: 18px 20px 20px; border: 5px solid #d4351d; }
.bk__fail-title { font-size: 1.25rem; }
.bk__fail p { margin-top: 8px; }

/* The GOV.UK confirmation panel, in its green. White on #00703c is 6.21:1. */
.bk__panel { padding: 28px 24px; background: var(--green); color: #fff; }
.bk__panel h1 { color: #fff; }
.bk__panel p { margin-top: 8px; font-size: 1.25rem; }
.bk__panel h1:focus { outline: 3px solid var(--focus); outline-offset: 4px; }

.bk__h2 { margin-top: 36px; font-size: 1.5rem; }

.bk__next { margin-top: 12px; padding-left: 1.4em; list-style: decimal; }
.bk__next li { margin-top: 8px; padding-left: 4px; }

.bk__home { margin-top: 28px; }

.bk h1:focus { outline: none; }

/* ── Legal pages (/privacy/, /terms/, /cancellation/, /cookies/) ──────────────
   Their text is the website's own, GOV.UK classes and all, read from _pages/
   at build time. These rules dress those classes in this page's type. */

.doc { padding-block: 24px 72px; }
.doc__wrap { max-width: 46rem; }

.doc .govuk-caption-xl { display: block; margin-bottom: 6px; font-size: .8125rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--blue); }
.doc h1 { font-size: clamp(2rem, 1.5rem + 2vw, 2.75rem); line-height: 1.12; letter-spacing: -.025em; }
.doc h2 { margin-top: 8px; font-size: 1.5rem; line-height: 1.25; }
.doc h3 { margin-top: 24px; font-size: 1.1875rem; }
.doc .govuk-body-l { margin-top: 12px; font-size: 1.25rem; line-height: 1.5; }
.doc .govuk-body-s { margin-top: 8px; font-size: 1rem; color: var(--body); }
.doc .govuk-body, .doc .govuk-list { margin-top: 14px; }
.doc .govuk-list--bullet { padding-left: 1.3em; list-style: disc; }
.doc .govuk-list li { margin-top: 6px; }
.doc strong { font-weight: 600; color: var(--ink); }

.doc .govuk-section-break { margin: 32px 0 24px; border: 0; border-top: 1px solid var(--line); }

.doc .govuk-inset-text { margin-top: 20px; padding: 14px 18px; border-left: 5px solid var(--blue); background: var(--tint); }

.doc .govuk-warning-text { position: relative; margin-top: 20px; padding: 6px 0 6px 48px; }
.doc .govuk-warning-text__icon {
  position: absolute; left: 0; top: 4px;
  display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--ink); color: #fff; font-weight: 700; font-size: 1.25rem;
}
.doc .govuk-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

.doc .govuk-table { width: 100%; margin-top: 16px; border-collapse: collapse; font-size: 1rem; }
.doc .govuk-table__caption { margin-bottom: 8px; text-align: left; font-size: 1.1875rem; font-weight: 600; color: var(--ink); }
.doc .govuk-table__header, .doc .govuk-table__cell { padding: 10px 12px 10px 0; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.doc .govuk-table__header { font-weight: 600; color: var(--ink); }

/* ── Footer ──────────────────────────────────────────────────────────────── */

.foot { padding-block: 32px; background: var(--ink); color: var(--on-ink); font-size: 1rem; line-height: 1.5; }

.foot__in { display: grid; gap: 16px; }

.foot__line { max-width: 44em; }

.foot__links { display: flex; flex-wrap: wrap; gap: 8px 24px; }

.foot a:not(:focus) { color: #fff; }
.foot a:not(:focus):hover { color: #fff; }

/* "Cookie settings": a button, because it opens CookieYes's preference
   centre (the cky-banner-element class) rather than going anywhere. Drawn
   like the footer links beside it. Hidden without JavaScript, when CookieYes
   cannot run either. */
.foot__btn {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: #fff;
  text-decoration: underline;
  text-underline-offset: .15em;
  cursor: pointer;
}
.foot__btn:focus { outline: 3px solid transparent; color: var(--ink); background: var(--focus); box-shadow: 0 -2px var(--focus), 0 4px var(--ink); text-decoration: none; }
html:not(.js) .foot__btn { display: none; }

/* ── Phone dock ──────────────────────────────────────────────────────────── */

.dock { display: none; }

@media (max-width: 40em) {
  .dock {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
    background: #fff;
    border-top: 1px solid var(--line);
    transition: transform .35s var(--ease), visibility 0s;
  }

  /* While the hero's own buttons are on screen the dock would only repeat
     them, so the script parks it. visibility takes it out of the tab order
     once the slide has finished. */
  .js .dock.is-away {
    transform: translateY(110%);
    visibility: hidden;
    transition: transform .35s var(--ease), visibility 0s .35s;
  }

  /* Clear the dock, so the footer links are never trapped underneath it. */
  .foot { padding-bottom: calc(32px + 76px + env(safe-area-inset-bottom)); }
}

/* ── Motion ──────────────────────────────────────────────────────────────────
   Everything is visible by default. The script adds `.anim` to <html> only
   when it is running and the visitor has not asked for reduced motion, so
   nothing here can ever leave copy hidden.

   One authored moment: the hero. The headline rises, the photograph is
   uncovered from the top, and the price ticket lands last. Below the fold,
   blocks ease up once as they arrive. ──────────────────────────────────────── */

.anim [data-load] {
  animation: rise .9s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 90ms + 60ms);
}

.anim [data-load="wipe"] { animation-name: wipe; animation-duration: 1.2s; }

@keyframes rise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

@keyframes wipe {
  from { clip-path: inset(0 0 100% 0); transform: scale(1.06); }
  to   { clip-path: inset(0); transform: none; }
}

.anim [data-rise] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
  transition-delay: calc(var(--i, 0) * 80ms);
}

.anim [data-rise].is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

@media print {
  .bar, .dock { position: static; }
  .dock { display: none; }
}
