/*
  Platform design tokens.

  Colours and type are taken from the desktop XD spec, which is the canonical set —
  the mobile file carried extra colours (olive, slate) that were deliberately dropped.

  Open Sans is a variable font with a width axis, so it covers Light-Bold *and* the
  condensed widths. That lets one family stand in for Open Sans, Open Sans Condensed
  and Avenir Next Condensed, which the design used but is licence-encumbered.
*/
/*
  Open Sans, self-hosted.

  Served from our own origin rather than linked from Google Fonts: a stylesheet link
  would send every Danish visitor's IP to Google on page load, which EU rulings have
  treated as a GDPR problem. The files are the same ones Google serves, just hosted here.

  One variable font covers the whole design: weight 300-800 gives Light through Bold,
  and the width axis (75-100) provides the condensed cut the section labels need — so
  this single family replaces Open Sans, Open Sans Condensed and the licence-encumbered
  Avenir Next Condensed.

  latin-ext is listed first so the browser only fetches it when a glyph needs it;
  æ, ø and å are all in the latin subset.
*/
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 300 800;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url("../fonts/open-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 300 800;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url("../fonts/open-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --c-white: #ffffff;
  --c-black: #000000;
  --c-green: #42b04d;
  --c-green-alt: #42b242;
  /* The search button: the same bar as a filter control, a shade darker. */
  --c-green-dark: #368a3d;

  /*
    The green a section can be filled with, and the only place this darker cut is used.

    Not the brand green: white on #42b04d is 2.78:1 and white on #368a3d is 4.32:1, so
    neither carries body text at AA — and putting near-black on the brand green instead is
    4.15:1, which fails too. This is the brand green at 75%, same hue, 4.67:1 against white.
    Buttons and links keep #42b04d; they are bold, short and not a page of text.
  */
  --c-green-band: #31843a;
  --c-grey-900: #393939;
  --c-grey-700: #4d4d4d;
  --c-grey-500: #8e8e8e;
  --c-grey-400: #919191;
  --c-grey-200: #c1c1c1;
  /* Mobile-only tokens: the quick-link rows use a light grey fill and an olive icon. */
  --c-grey-100: #dedede;
  --c-olive-900: #394017;

  /* Unit detail: the dark badges over the photo, and the slate the icons use. */
  --c-slate-900: #192733;
  --c-slate-700: #2e475a;
  --c-grey-800: #444444;
  /* The navigation dropdown panel and its text. */
  /* Design: the dropdown is a solid grey panel, with its shadow carrying the 9b alpha. */
  --c-nav-panel: #696868;
  --c-nav-panel-shadow: #0000009b;
  --c-grey-600: #696868;

  --shadow-sm: 0 2px 6px #00000029;
  --shadow-lg: 0 8px 24px #00000093;

  --font-body: "Open Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-condensed: "Open Sans", system-ui, sans-serif;

  --measure: 1500px;
  --gutter: 1.25rem;
}

*, *::before, *::after { box-sizing: border-box; }

/*
  A class that sets `display` outranks the browser's own rule for [hidden], so an element
  hidden from script would still be laid out. This puts it back — without it the
  "Avanceret søgning" fields stayed on screen despite being marked hidden.
*/
[hidden] { display: none !important; }

/* Design: Open Sans Regular 20px #4D4D4D — the body style on every artboard. */
/*
  A column at least as tall as the window, with the main region taking up the slack, so a
  short page — a thin section, a 404 — still puts its footer at the bottom of the screen
  rather than halfway up with white below it.

  dvh tracks the mobile address bar showing and hiding; vh is the fallback for anything
  that does not know it.
*/
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.25rem;
  line-height: 1.5;
  color: var(--c-grey-700);
  background: var(--c-white);
}

.site-main { flex: 1 0 auto; }

a { color: inherit; }

/*
  Present to a screen reader and to a crawler, absent on screen. The page's <h1> uses it:
  the design gives a page no visible title, but a document still needs one heading naming
  what it is.

  Clipped rather than display:none or visibility:hidden, both of which take it out of the
  accessibility tree along with the layout.
*/
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- header ---------- */

.site-header {
  background: var(--c-white);
  border-bottom: 1px solid var(--c-grey-200);
}

.site-header__inner {
  /*
    Named because the dropdown needs it: the panel is positioned against its menu item,
    whose box ends where this padding begins, so it adds this back to reach the underside
    of the header. Change it here and the dropdown follows.
  */
  --header-pad-block: 1rem;

  /*
    One gap for the whole bar: logo to menu, and item to item. Fluid, because the six
    labels and the logo are a fixed 911px between them — a fixed gap wide enough to look
    right at 1600 pushes the menu off the edge at 1200. It grows with the window and stops
    at 3.25rem, past which the menu drifts away from the logo it belongs to.
  */
  --nav-gap: clamp(2rem, 3.2vw, 3.25rem);

  max-width: var(--measure);
  margin-inline: auto;
  padding: var(--header-pad-block) var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--nav-gap);
}

.site-header__brand {
  text-decoration: none;
  display: block;
  flex: 0 0 auto;
}

.site-header__logo {
  display: block;
  width: auto;
  height: 3.25rem;
  max-width: 100%;
}

/*
  Sized from the window, not fixed.

  The logo is a wide mark - 480x71, so nearly seven times wider than tall - and a height in
  pixels turns into a width that does not know how big the phone is. At 2.5rem it came out
  270px: fine beside the menu button on a tablet, 72% of a 375px phone, which pushed the
  button onto a second row and made the header 149px tall. Capped at the old width so
  nothing grows, and held to 46% of the window below that, which is the share of the bar
  the mark has in the design.
*/
@media (max-width: 900px) {
  .site-header__logo {
    height: auto;
    width: min(17rem, 46vw);
  }
}

.site-header__toggle {
  margin-inline-start: auto;
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: 0.5rem;
  background: none;
  border: 0;
  cursor: pointer;
}

.site-header__toggle span {
  display: block;
  width: 26px;
  height: 3px;
  background: var(--c-green);
}

/*
  Stretched rather than centred: the brand is taller than the menu, so centring left a few
  pixels of slack under the items — and the dropdown, which measures from its item, opened
  that far above the underside of the header. Filling the height removes the guesswork.
*/
/*
  The menu sits beside the logo, not against the right edge, separated by the header's own
  gap. On a wide screen that leaves empty space to the right of "Kontakt" rather than
  stretching the six items across the whole window, which is how the site is drawn.
*/
.site-nav {
  align-self: stretch;
}

.site-nav__list {
  display: flex;
  align-items: stretch;
  height: 100%;
  gap: var(--nav-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav__item { position: relative; display: flex; align-items: center; }

/* Design: Open Sans Regular 20px #4D4D4D */
.site-nav__link {
  text-decoration: none;
  color: var(--c-grey-700);
  font-size: 1.25rem;
  padding-block: 0.5rem;
  display: inline-block;
}

.site-nav__link:hover,
.site-nav__link.is-active { color: var(--c-green); }

/*
  Design: a translucent dark panel with the items right-aligned, hanging under the parent
  and wide enough to hold "Brugte campingvogne" on one line.
*/
/*
  Centred on the menu item that opens it, but dropping from the underside of the header
  rather than from the link — as the design has it.

  The vertical offset is not simply 100%: the item's box ends where the header's padding
  begins, so that padding and the header's border are added back to reach the header's
  own bottom edge.
*/
.site-nav__sub {
  position: absolute;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  top: calc(100% + var(--header-pad-block) + 1px);
  min-width: 15rem;
  margin: 0;
  padding: 0.75rem 0;
  list-style: none;
  background: var(--c-nav-panel);
  box-shadow: 0 3px 20px var(--c-nav-panel-shadow);
  /*
    The shadow is clipped flat against the top edge. A 20px blur spreads every way,
    including up over the header, and the panel cannot be painted behind the header
    because it sits inside it — so the bleed is cut off instead. The other three sides
    are opened up well past the blur so the shadow itself is untouched.
  */
  clip-path: inset(0 -30px -30px -30px);
  display: none;
  z-index: 20;
}

.site-nav__item--has-children:hover > .site-nav__sub,
.site-nav__item--has-children:focus-within > .site-nav__sub { display: block; }

/*
  An invisible strip bridging the item to the panel below it.

  The panel hangs from the underside of the header, which is lower than the item, so
  moving the mouse straight down crossed a gap where nothing was hovered and the menu
  closed under the pointer. The strip is part of the item, so crossing it keeps the item
  hovered. Same height as the gap: the header's bottom padding plus its border.
*/
.site-nav__item--has-children::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 100%;
  height: calc(var(--header-pad-block) + 1px);
}

.site-nav__sub-link {
  display: block;
  padding: 0.5rem 1.25rem;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 1rem;
  font-weight: 500;
  color: var(--c-white);
  text-align: end;
  text-decoration: none;
}

.site-nav__sub-link:hover { color: var(--c-green); }

/* ---------- blocks ---------- */

.section { padding-block: 2.5rem; }

/*
  A coloured section is a band across the whole window, not a panel the width of the text.

  The 100vw breakout is the hero's, and it is safe for the same reason: body has
  overflow-x: clip, so the extra width a scrollbar would otherwise leave never becomes a
  sideways scroll. The inner keeps the measure, so the text stays in the content column
  while the colour runs to both edges.
*/
.section--colour {
  width: 100vw;
  max-width: 100vw;
  margin-inline: calc(50% - 50vw);
}

/*
  Headings inside a band take the band's own text colour. Without this they keep the near
  black and the grey the palette gives them by level, which is unreadable on the dark and
  green bands and the whole reason the colours are chosen as a pair.
*/
.section--colour .section__heading { color: inherit; }

/*
  What each name looks like. This is the half that is this site's alone — the element type
  and the names are shared with the other nineteen, the values are not.

  Every pair clears 4.5:1, which is the whole point of choosing background and text
  together: white 11.55, grey 8.58, green 4.67, dark 11.55. A site changing these values
  should measure the new ones, or the promise the editor is being given quietly stops being
  true.
*/
/*
  Buttons on a coloured band get a white fill.

  Text contrast was never the problem — a green button keeps its white label wherever it
  sits. Its edge is. Measured on the green band, a green button is 1.08:1 against it: the
  words are readable and the button is not there. On the dark band it is 2.67:1, still under
  the 3:1 a control's own shape is meant to have. White is 4.67:1 on green and 11.55:1 on
  dark, and carries the band's dark text at 11.55:1.

  Ordinary prose links need nothing: "a" already inherits its colour, so on these bands they
  are the band's own white and keep the underline that tells you they are links.
*/
.section--green .btn,
.section--green .cta__button,
.section--dark .btn,
.section--dark .cta__button {
  background: var(--c-white);
  color: var(--c-grey-900);
}

.section--green .btn:hover,
.section--green .cta__button:hover,
.section--dark .btn:hover,
.section--dark .cta__button:hover {
  background: var(--c-grey-100);
}

.section--white { background: var(--c-white); color: var(--c-grey-900); }
.section--grey { background: var(--c-grey-100); color: var(--c-grey-900); }
.section--green { background: var(--c-green-band); color: var(--c-white); }
.section--dark { background: var(--c-grey-900); color: var(--c-white); }

/* A section containing the banner sits flush under the header, with no gap above. */
.section:has(.hero) { padding-block-start: 0; }

.section__inner {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/*
  Section labels — QUICK-LINKS, SØGNING, FREMHÆVET. Dark and bold rather than the grey
  condensed cut the spec panel lists: at 1:1 the design draws these near-black, and the
  grey condensed style belongs to the "AVANCERET SØGNING" link instead.
*/
.section__heading {
  margin: 0 0 1rem;
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--c-grey-900);
}

/*
  A page's h1 takes the ruled bar the design gives the listing page: a short rule, the
  heading, then a rule out to the right edge.

  Keyed to the h1 rather than to the section's contents. It used to be
  `.section:has(.unit-list)`, from when the listing page was the only page with a heading
  worth marking and that heading was the section's own label. Now every page carries an
  Overskrift block set to h1, and scoping by what happened to sit beside it left the
  listing page's h1 ruled and the other eleven plain — the same element, styled two ways,
  for a reason no editor could see.

  Section labels — QUICK-LINKS, SØGNING, FREMHÆVET — stay plain, which is how the design
  draws them.
*/
.section__heading--h1 {
  display: flex;
  align-items: center;
  gap: 1rem;
}

/*
  The rules are drawn as the logo draws its own: a hollow bar with slanted ends, not a
  solid line. Outline and skew rather than a fill, which is what makes it read as the
  same mark at this size.
*/
.section__heading--h1::before,
.section__heading--h1::after {
  content: "";
  height: 0.5rem;
  border: 2px solid currentColor;
  transform: skewX(-18deg);
}

.section__heading--h1::before { flex: 0 0 3.5rem; }
.section__heading--h1::after { flex: 1 1 auto; }

/*
  On a narrow screen there is no room for the mark. The longest heading wraps to two lines
  and the trailing rule is squeezed to nothing, which reads as a broken element rather than
  a deliberate one — measured on "Hjørring Camping & Fritid": one line and a 70px rule at
  560, two lines and a 4px stub at 480.

  This is a width, so it is a guess about text length. A heading much longer than the ones
  the site has now would squash above the breakpoint too.
*/
@media (max-width: 560px) {
  .section__heading--h1 { display: block; }

  .section__heading--h1::before,
  .section__heading--h1::after { content: none; }
}

.rich-text > :first-child { margin-top: 0; }
.rich-text > :last-child { margin-bottom: 0; }

.btn {
  display: inline-block;
  padding: 0.6rem 1.4rem;
  background: var(--c-green);
  color: var(--c-white);
  font-weight: 600;
  text-decoration: none;
  border-radius: 3px;
}

.btn:hover { background: var(--c-green-alt); }

/* hero */

/*
  The banner is full-bleed, so it breaks out of the section's centred column.
  overflow-x: clip on the body stops the 100vw breakout producing a horizontal
  scrollbar; clip rather than hidden so position: sticky keeps working.
*/
body { overflow-x: clip; }

.hero {
  position: relative;
  width: 100vw;
  max-width: 100vw;
  margin-inline: calc(50% - 50vw);
}

.hero__image {
  display: block;
  width: 100%;
  /* dvh tracks the mobile address bar showing and hiding; vh is the fallback for
     browsers without it, where 100vh would leave the bottom of the image cut off. */
  height: 100vh;
  height: 100dvh;
  object-fit: cover;
}

/* Translucent, as the design has it — the meadow shows through the panel. */
.hero__card {
  background: #42b04dcc;
  color: var(--c-white);
  padding: 1.25rem 1.5rem;
  text-align: center;
}

/* Design: Open Sans Bold 21px #FFFFFF */
.hero__heading {
  margin: 0 0 0.75rem;
  padding-bottom: 0.75rem;
  font-size: 1.3125rem;
  font-weight: 700;
  line-height: 1.25;
  border-bottom: 1px solid rgba(255, 255, 255, 0.55);
}

.hero__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.875rem;
}

.hero__text { white-space: pre-line; }

.hero__link {
  color: var(--c-white);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

.hero__link:hover { text-decoration: underline; }

@media (min-width: 901px) {
  /* Card overlays the image, centred near the bottom as the design shows. */
  .hero__card {
    position: absolute;
    left: 50%;
    bottom: 7%;
    transform: translateX(-50%);
    width: min(26rem, 80%);
    background: rgba(66, 176, 77, 0.93);
    box-shadow: var(--shadow-sm);
  }
}

/* card — heading and subtitles sit ON the image, per the design */
.card { height: 100%; }

.card__link,
.card { position: relative; display: block; text-decoration: none; color: inherit; }

/* Design: the quick-link tiles are wide and shallow, about two to one. */
/*
  height:auto is what lets aspect-ratio win, as on .unit-card__image. The img now carries
  width and height attributes so the browser can reserve space before the photo loads, and
  without this the height attribute is taken literally — the tiles went from 196px to 515px
  tall the moment responsive images started supplying intrinsic dimensions.
*/
.card__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 2 / 1;
  object-fit: cover;
}

.card__body {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 1.5rem;
  color: var(--c-white);
  /*
    A flat semi-transparent black layer over the whole image, not a gradient: the collage
    imagery is busy in every corner, so shading only one side left the heading legible and
    the body text sitting on bare photo.

    Weighted to roughly half black — against these collages, which are pale and busy
    everywhere, a lighter wash left the sub-lines barely readable.
  */
  background: #00000080;
}

/* Design: Open Sans Semibold 24px #FFFFFF */
.card__heading {
  margin: 0 0 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--c-white);
  border-bottom: 2px solid var(--c-white);
  align-self: flex-start;
  min-width: 6rem;
}

/* Design: Open Sans Light 18px #FFFFFF */
.card__text {
  margin: 0;
  font-size: 1.125rem;
  font-weight: 300;
  color: var(--c-white);
}

/* Icon is desktop-hidden; the image carries the card there. */
.card__icon { display: none; }

/* ---------- banner ---------- */

/*
  A wide image across the content column, at whatever proportions the file has. No
  aspect-ratio: these are supplied as artwork and cropping them would cut the graphics.
*/
.banner {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------- model card ---------- */

/*
  A model photo with its name ruled off beneath. Deliberately not .card: that one lays
  white text over a photo and needs an image filling the tile, where these sit on white
  and read as a row of choices.
*/
.model-card { height: 100%; }

.model-card__link,
.model-card {
  display: block;
  text-decoration: none;
  color: inherit;
}

.model-card__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 5 / 3;
  object-fit: contain;
}

.model-card__name {
  margin: 0;
  padding-top: 0.625rem;
  border-top: 2px solid var(--c-green);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: center;
  color: var(--c-grey-900);
}

.model-card__link:hover .model-card__name { color: var(--c-green); }

/* ---------- call to action ---------- */

.cta {
  padding: 1rem 0;
  text-align: center;
}

.cta__heading {
  margin: 0 0 0.5rem;
  font-size: 1.5rem;
  font-weight: 400;
  color: var(--c-grey-900);
}

.cta__text {
  margin: 0 auto 1.5rem;
  max-width: 40rem;
  color: var(--c-grey-700);
}

.cta__button {
  display: inline-block;
  min-height: 2.75rem;
  padding: 0.625rem 2.5rem;
  border-radius: 6px;
  /*
    Was --c-green-dark, which is 4.32:1 against the white on it — under AA, and on every
    page rather than only the coloured ones. --c-green-band is the same hue at 4.67:1.
  */
  background: var(--c-green-band);
  color: var(--c-white);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
}

.cta__button:hover { background: var(--c-green); }

@media (max-width: 900px) {
  /*
    Mobile turns the card into a row: grey fill, olive icon, green label. This is a
    different treatment rather than a smaller card — the collage imagery is unreadable
    at phone width, so the design drops it entirely.
  */
  .card,
  .card__link {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-height: 4.5rem;
    padding: 0 1.25rem;
    background: var(--c-grey-100);
    border-radius: 6px;
  }

  .card__image { display: none; }

  .card__icon {
    display: block;
    flex: 0 0 auto;
    font-size: 1.25rem;
    color: var(--c-olive-900);
  }

  .card__body {
    position: static;
    inset: auto;
    padding: 0;
    background: none;
    justify-content: center;
  }

  /*
    Design: Open Sans Bold 20pt #42B04D — the weight and size as drawn, the green a shade
    darker. #42B04D on this grey card is 2.07:1. At 20px bold the label counts as large
    text, so it needs 3:1 rather than 4.5, and it misses even that; #31843a is 3.47:1 and
    still reads as the brand green at a glance. It is the same darker cut the coloured
    section bands use.
  */
  .card__heading {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--c-green-band);
  }

  /*
    One line per card, as the reference draws it: icon, label, nothing else. The lines are
    still in the content and still show on desktop, where the card is a tile with room for
    them — this only takes them off the phone.
  */
  .card__text { display: none; }
}

/* text + image */
.text-image { display: grid; gap: 1.5rem; align-items: center; }

.text-image__media img { display: block; width: 100%; height: auto; }

.text-image__heading { margin: 0 0 0.75rem; }

@media (min-width: 901px) {
  .text-image { grid-template-columns: 1fr 1fr; }
  .text-image--image-right .text-image__media { order: 2; }
}

/* gallery and logos */
.gallery, .logo-grid {
  display: grid;
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.gallery { grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); }

.gallery__item img { display: block; width: 100%; height: auto; }

.logo-grid {
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  align-items: center;
}

.logo-grid__item img { display: block; max-width: 100%; height: auto; margin-inline: auto; }

/* accordion */
.accordion { border-bottom: 1px solid var(--c-grey-200); }

.accordion__summary {
  cursor: pointer;
  padding: 0.875rem 0;
  font-weight: 600;
  color: var(--c-grey-900);
}

.accordion__body { padding-bottom: 1rem; }

/* ---------- unit search ---------- */

/*
  Block layout, not flex: the rows inside are grids that need the full width. As a flex
  container this collapsed the field grid to its content width and the controls stacked
  two-up instead of filling the row.
*/
.unit-search { display: block; }

.unit-search__heading {
  margin: 0;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 1.5rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--c-grey-400);
}

/*
  Three controls to a row, fixed rather than auto-fit: the row should read as thirds
  whatever the container width, and an auto-fit track count changes with it.
*/
.unit-search__fields {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  align-items: start;
}

/*
  Filters carry a top margin so they stack in the listing panel. In a grid that margin
  lands on every control except the first and drops the rest of the row 8px; the grid's
  own gap is what should be spacing them here.
*/
.unit-search__fields .unit-filter + .unit-filter { margin-top: 0; }

.unit-search__fields--advanced { margin-top: 1rem; }

/* The closing row: "Avanceret søgning" left, "Søg" right. */
.unit-search__actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 1rem;
}

/* Design: grey, condensed, uppercase, tracked out. */
.unit-search__advanced {
  display: inline-block;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-grey-400);
  cursor: pointer;
}

.unit-search__advanced:hover { color: var(--c-green); }

/*
  The button is never hidden — the block is only a way in to the listing, so losing it
  at any breakpoint would leave the controls with nowhere to go. `margin-left: auto`
  rather than `justify-content: space-between` on the row: with no advanced filters the
  toggle is not rendered at all, and the button must still sit right.

  Shaped like a filter control — same height, radius and green bar — a shade darker so
  it still reads as the action rather than a fourth thing to choose.
*/
.unit-search__submit {
  display: flex;
  align-items: center;
  /* The icon trails the label rather than sitting at the far edge, so it does not read
     as another caret in the column above it. */
  gap: 2rem;
  margin-left: auto;
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  border: 0;
  border-radius: 6px;
  background: var(--c-green-dark);
  color: var(--c-white);
  font: inherit;
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-align: start;
  cursor: pointer;
}

.unit-search__submit-label { flex: 0 0 auto; }

.unit-search__submit-icon {
  flex: 0 0 auto;
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
}

.unit-search__submit:hover { background: var(--c-green); }

/* A fixed three-track grid cannot reflow itself, so the narrower rows are set here. */
@media (max-width: 960px) {
  .unit-search__fields { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 700px) {
  .unit-search__fields { grid-template-columns: 1fr; }

  /* Stacked, and the button full width — it is the point of the block. */
  .unit-search__actions { flex-direction: column; align-items: stretch; }
  .unit-search__advanced { text-align: left; }
  .unit-search__submit { margin-left: 0; }
}

/* ---------- unit list ---------- */

/*
  Laid out like the front page's search box: the controls three across, the rest behind
  "Avanceret søgning", and one closing row of buttons — on the page itself, with no panel
  drawn around it. The mobile sheet puts the padding and the fill back, since there it
  really does sit over the results.
*/
.unit-list__filters { margin-bottom: 2rem; }

.unit-list__fields {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  align-items: start;
}

/* The stacking margin belongs to the listing panel's old column layout, not to a grid. */
.unit-list__fields .unit-filter + .unit-filter { margin-top: 0; }

.unit-list__fields--advanced { margin-top: 1rem; }

/* Mobile-only chrome: the button that reveals the panel, and the ways back out of it. */
.unit-list__open-row,
.unit-list__close-row,
.unit-list__show { display: none; }

/*
  A filter group's own name, above the controls it holds. Sized like the section labels
  rather than like a page heading: it names a set of fields, it does not introduce a part of
  the page. A group with no name renders none of this and its controls simply follow on.
*/
.unit-list__group-title {
  margin: 1.25rem 0 0.5rem;
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-grey-700);
}

.unit-list__group-title:first-child { margin-top: 0; }

/* ---------- one filter ---------- */

.unit-filter { position: relative; }
.unit-filter + .unit-filter { margin-top: 0.5rem; }

/*
  Design: a solid green bar with a white label, the current selection right-aligned and a
  white caret. The summary can grow long — three selected manufacturers, say — so it
  shrinks and ellipsises while the label keeps its width.
*/
.unit-filter__control {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  border: 0;
  border-radius: 6px;
  background: var(--c-green);
  font: inherit;
  font-size: 1.0625rem;
  color: var(--c-white);
  text-align: start;
  cursor: pointer;
}

.unit-filter__control:hover { background: var(--c-green-alt); }

/* The sort dropdown is a native select, styled to sit in the same row. */
.unit-filter__control--plain {
  cursor: auto;
  appearance: none;
  -webkit-appearance: none;
}

.unit-filter__label { flex: 0 0 auto; }

.unit-filter__summary {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: end;
  font-size: 0.8125rem;
  /* Slightly held back against the label until the visitor has actually chosen. */
  color: #ffffffc4;
}

.unit-filter__summary.is-set { color: var(--c-white); font-weight: 600; }

/* A caret drawn in CSS, so the panel needs no icon font to look finished. */
.unit-filter__caret {
  flex: 0 0 auto;
  width: 0;
  height: 0;
  margin-inline-start: 0.25rem;
  border-inline: 0.4rem solid transparent;
  border-block-start: 0.45rem solid var(--c-white);
  transition: transform 120ms ease;
}

.unit-filter.is-open .unit-filter__caret { transform: rotate(180deg); }

.unit-filter__panel {
  position: absolute;
  z-index: 5;
  inset-inline: 0;
  margin-block-start: 0.25rem;
  padding: 0.75rem;
  border: 1px solid var(--c-grey-200);
  background: var(--c-white);
  box-shadow: var(--shadow-sm);
}

.unit-filter__panel[hidden] { display: none; }

.unit-filter__checks {
  margin: 0;
  padding: 0;
  list-style: none;
  /* Long brand lists scroll inside the panel rather than running off the page. */
  max-height: 14rem;
  overflow-y: auto;
}

.unit-filter__check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.125rem 0;
  font-size: 0.9375rem;
  cursor: pointer;
}

/*
  The from/to boxes under a range slider.

  No spinner arrows: they are drawn differently by every browser, they crowd a field this
  narrow, and the two-handle slider directly above already steps the value — so removing
  them takes nothing away. The keyboard's own up and down arrows still work, and
  inputmode="numeric" on the field brings up the number pad on a phone.
*/
.unit-filter__number {
  width: 100%;
  min-width: 0;
  padding: 0.4375rem 0.625rem;
  border: 1px solid var(--c-grey-200);
  border-radius: 6px;
  background: var(--c-white);
  font: inherit;
  font-size: 0.9375rem;
  color: var(--c-grey-900);
  text-align: end;
  appearance: textfield;
  -moz-appearance: textfield;
  transition: border-color 120ms ease;
}

.unit-filter__number::-webkit-outer-spin-button,
.unit-filter__number::-webkit-inner-spin-button {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
}

.unit-filter__number:hover { border-color: var(--c-grey-500); }

/*
  Focus is the site's green rather than the browser's default ring. :focus, not
  :focus-visible — a text field earns its focus ring however it was reached, including by
  click, which is the opposite of a button.
*/
.unit-filter__number:focus {
  border-color: var(--c-green);
  outline: 2px solid var(--c-green);
  outline-offset: -1px;
}

/* Free text: white field with a green edge, matching the design's odd one out. */
.unit-filter__text {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  border: 1px solid var(--c-green);
  border-radius: 6px;
  background: var(--c-white);
  font: inherit;
  font-size: 1.0625rem;
  color: var(--c-grey-900);
}

/* The design tints the placeholder green rather than the usual grey. */
.unit-filter__text::placeholder { color: var(--c-green); opacity: 1; }

.unit-filter__actions { margin-top: 0.75rem; text-align: end; }

.unit-filter__apply {
  padding: 0.375rem 1.25rem;
  border: 0;
  border-radius: 2px;
  background: var(--c-green);
  color: var(--c-white);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

/* ---------- two-handle range ---------- */

.unit-range__track {
  position: relative;
  height: 1.5rem;
  margin-inline: 0.5rem;
}

/* The rail and the selected span, drawn behind the two native inputs. */
.unit-range__track::before {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline: 0;
  height: 3px;
  transform: translateY(-50%);
  background: var(--c-grey-200);
  border-radius: 3px;
}

.unit-range__fill {
  position: absolute;
  inset-block-start: 50%;
  height: 3px;
  transform: translateY(-50%);
  background: var(--c-green);
  border-radius: 3px;
}

/*
  Two range inputs stacked on one track. The inputs themselves ignore pointer events so the
  upper one does not swallow clicks meant for the lower; only the thumbs are grabbable.
*/
.unit-range__handle {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  width: 100%;
  height: 1.5rem;
  margin: 0;
  background: none;
  appearance: none;
  -webkit-appearance: none;
  pointer-events: none;
}

.unit-range__handle:focus-visible { outline: 2px solid var(--c-green); outline-offset: 2px; }

.unit-range__handle::-webkit-slider-thumb {
  pointer-events: auto;
  appearance: none;
  -webkit-appearance: none;
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--c-white);
  border-radius: 50%;
  background: var(--c-green);
  box-shadow: var(--shadow-sm);
  cursor: grab;
}

.unit-range__handle::-moz-range-thumb {
  pointer-events: auto;
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--c-white);
  border-radius: 50%;
  background: var(--c-green);
  box-shadow: var(--shadow-sm);
  cursor: grab;
}

.unit-range__handle::-webkit-slider-runnable-track { background: none; }
.unit-range__handle::-moz-range-track { background: none; }

.unit-range__inputs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

/* The front page's closing row: the toggle left, the button right, Nulstil beside it. */
.unit-list__actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 1rem;
}

/* Design: grey, condensed, uppercase, tracked out — the same link as on the front page. */
.unit-list__advanced {
  display: inline-block;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-grey-500);
  cursor: pointer;
}

.unit-list__advanced:hover { color: var(--c-green); }

/*
  Pushed right along with the button. `margin-left: auto` on the first of the two rather
  than space-between on the row: the toggle is absent when a block has only the three
  simple filters, and the pair must still sit right.
*/
.unit-list__reset {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  margin-left: auto;
  min-height: 2.75rem;
  padding: 0.5rem 1.25rem;
  border: 1px solid var(--c-green);
  border-radius: 6px;
  background: transparent;
  color: var(--c-green);
  font: inherit;
  /* Matched to the search button, or the pair sits at two different heights. */
  font-size: 1.0625rem;
  font-weight: 600;
  cursor: pointer;
}

.unit-list__reset:hover { background: var(--c-green); color: var(--c-white); }

.unit-list__reset-label { flex: 0 0 auto; }

.unit-list__reset-icon {
  flex: 0 0 auto;
  width: 1.125rem;
  height: 1.125rem;
  fill: currentColor;
}

/* The same green bar as the front page's search button. */
.unit-list__submit {
  display: flex;
  align-items: center;
  gap: 2rem;
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  border: 0;
  border-radius: 6px;
  background: var(--c-green-dark);
  color: var(--c-white);
  font: inherit;
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-align: start;
  cursor: pointer;
}

.unit-list__submit:hover { background: var(--c-green); }

.unit-list__submit-label { flex: 0 0 auto; }

.unit-list__submit-icon {
  flex: 0 0 auto;
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
}

.unit-list__count {
  margin: 0 0 1rem;
  font-size: 0.875rem;
  color: var(--c-grey-500);
}

/* ---------- sorting ---------- */

/*
  A row above the results holding the sort options and the count, as the reference listing
  has it. Ruled top and bottom so it reads as a band separating filters from results.
*/
.unit-sort {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  padding-block: 0.75rem;
  margin-bottom: 1.5rem;
  border-block: 1px solid var(--c-grey-200);
}

.unit-sort__options {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}

.unit-sort__label { font-size: 0.875rem; color: var(--c-grey-500); }

.unit-sort__option {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--c-grey-700);
  cursor: pointer;
}

.unit-sort__option:hover { color: var(--c-green); }

/* The option in use is named in green; its arrow says which way it points. */
.unit-sort__option.is-active { color: var(--c-green); font-weight: 600; }

.unit-sort__arrow { font-size: 0.8125rem; line-height: 1; }

.unit-sort__count {
  margin: 0;
  font-size: 0.875rem;
  color: var(--c-grey-500);
}

.unit-list__error { color: var(--c-grey-900); }

/* Fades while a filter request is in flight, so a slow network still feels answered. */
.unit-list__results[aria-busy="true"] { opacity: 0.55; transition: opacity 120ms ease; }

/*
  Below 992px the panel becomes a full-height sheet that slides in from the left, as the
  reference listing does — a row of filter columns is unusable stacked on a phone. The
  breakpoint matches theirs so the two behave alike on the same devices.
*/
@media (max-width: 991px) {
  .unit-list__open-row {
    display: block;
    margin-bottom: 1rem;
    text-align: end;
  }

  .unit-list__open {
    padding: 0.625rem 1.75rem;
    border: 0;
    border-radius: 2px;
    background: var(--c-green);
    color: var(--c-white);
    font: inherit;
    font-weight: 700;
    text-transform: uppercase;
    cursor: pointer;
  }

  .unit-list__filters {
    position: fixed;
    inset-block: 0;
    /* Parked off-screen rather than hidden, so opening and closing can be animated. */
    inset-inline-start: -100%;
    width: 100%;
    height: 100%;
    z-index: 100;
    margin: 0;
    /* No padding at the top: the close bar sits against the edge and brings its own. */
    padding: 0 1.5rem 1.5rem;
    background: var(--c-grey-100);
    overflow-y: auto;
    transition: inset-inline-start 300ms linear;
  }

  /* One control per row in a sheet this narrow — three across is a desktop layout. */
  .unit-list__fields { grid-template-columns: 1fr; }

  .unit-list__filters.is-open { inset-inline-start: 0; }

  /* Stays put as the sheet scrolls, so the way out is always reachable. */
  .unit-list__close-row {
    display: block;
    position: sticky;
    inset-block-start: 0;
    z-index: 10;
    height: 45px;
    /*
      Full width of the sheet, so the negative side margins stay - they cancel the sheet's
      own padding. The top one had to go: it pulled the bar up over the content behind it,
      and since the bar is opaque and sits above, it painted over the top 24px of the first
      filter. The sheet has no top padding now, so there is nothing left to cancel.
    */
    margin: 0 -1.5rem 1.5rem;
    padding-inline: 0.75rem;
    background: var(--c-grey-100);
    border-bottom: 1px solid var(--c-grey-200);
    text-align: end;
  }

  .unit-list__close {
    height: 45px;
    border: 0;
    background: none;
    font-size: 1.75rem;
    line-height: 1;
    color: var(--c-grey-700);
    cursor: pointer;
  }

  /* The toggle takes a row of its own, then "Vis" and "Nulstil" share the one below. */
  .unit-list__actions {
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
  }

  .unit-list__advanced { width: 100%; text-align: left; }

  /* "Vis" takes the wider share, as it is the one people press. */
  /* Label and tick centred as a pair, the same arrangement its two siblings use. */
  .unit-list__show {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.625rem;
    order: 1;
    width: 55%;
    height: 45px;
    border: 0;
    border-radius: 2px;
    background: var(--c-green);
    color: var(--c-white);
    font: inherit;
    font-weight: 700;
    text-transform: uppercase;
    cursor: pointer;
  }

  .unit-list__show-label { flex: 0 0 auto; }

  .unit-list__show-icon {
    flex: 0 0 auto;
    width: 1.25rem;
    height: 1.25rem;
    fill: currentColor;
  }

  /* The sheet applies filters as they are chosen, so a submit has nothing left to do. */
  .unit-list__submit { display: none; }

  .unit-list__reset { order: 2; margin-left: 0; width: 40%; height: 45px; }
}

/* ---------- unit card ---------- */

/*
  Four across, as the design lays it out. Fixed tracks rather than auto-fill: with only two
  featured units auto-fill still made five columns and left the cards stranded at a third of
  their intended width.
*/
.unit-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.5rem;
}

@media (max-width: 1200px) {
  .unit-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  .unit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .unit-grid { grid-template-columns: 1fr; }
}

/* The card sits directly on the page in the design — no panel, no border, no shadow. */
.unit-card { background: none; }

.unit-card__link {
  display: flex;
  flex-direction: column;
  height: 100%;
  text-decoration: none;
  color: inherit;
}

.unit-card__media { position: relative; }

/*
  height:auto is what lets aspect-ratio win. The img carries width and height attributes so
  the browser can reserve space before the photo loads, and without this the height
  attribute was taken literally — every card rendered 447px tall.
*/
.unit-card__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/*
  "Læs mere" is plain white text over the photo rather than a button. A gradient behind it
  keeps it readable whatever the picture does in that corner — caravans are usually pale.
*/
.unit-card__more {
  position: absolute;
  inset-inline-end: 0.75rem;
  inset-block-end: 0.5rem;
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--c-white);
}

.unit-card__media::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 4rem;
  background: linear-gradient(to top, #00000073, transparent);
  pointer-events: none;
}

.unit-card__flag {
  position: absolute;
  inset-block-start: 0.75rem;
  inset-inline-start: 0;
  z-index: 1;
  padding: 0.25rem 0.75rem;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--c-white);
}

.unit-card__flag--sold { background: var(--c-grey-900); }

.unit-card__body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.875rem 0 0;
  flex: 1 1 auto;
}

/* Design: regular weight, not bold — the price carries the emphasis. */
.unit-card__title {
  margin: 0;
  font-size: 1.1875rem;
  font-weight: 400;
  color: var(--c-grey-900);
}

/* Price left, year right, sharing a baseline. */
.unit-card__price {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: auto 0 0;
}

.unit-card__price-now {
  font-size: 1.1875rem;
  font-weight: 700;
  color: var(--c-grey-900);
}

.unit-card__year { font-size: 0.9375rem; color: var(--c-grey-900); }

.unit-card__before {
  margin: 0;
  font-size: 0.875rem;
  color: var(--c-grey-500);
}

.unit-featured__heading {
  margin: 0 0 1rem;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 1.5rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--c-grey-400);
}

/* ---------- unit detail ---------- */

.unit-detail__inner {
  max-width: var(--measure);
  margin-inline: auto;
  padding: 2rem var(--gutter);
}

/* Design: a short rule, the model name, then a rule running out to the right edge. */
/*
  The same ruled bar a section heading gets: a short mark, the label, then a mark out to
  the edge. Spans rather than pseudo-elements here because the view already writes them,
  but they are drawn identically — hollow, with the logo's slant.
*/
.unit-detail__bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
  color: var(--c-grey-900);
}

.unit-detail__rule {
  flex: 0 0 3.5rem;
  height: 0.5rem;
  border: 2px solid currentColor;
  transform: skewX(-18deg);
}

.unit-detail__rule--grow { flex: 1 1 auto; }

.unit-detail__title {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--c-grey-900);
}

/* The photo and everything the design lays over it. */
.unit-detail__stage { position: relative; }

.unit-detail__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--c-grey-100);
}

/*
  The overlays carry the page: the photo is large, and at the old sizes the year and the
  price read as captions on it rather than as the headline facts they are.
*/

/* Year, top right, on the dark slate the design uses for its badges. */
.unit-detail__badge {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
  padding: 0.875rem 2rem;
  background: var(--c-slate-900);
  color: var(--c-white);
  text-align: center;
}

.unit-detail__badge-value { display: block; font-size: 2.25rem; font-weight: 700; line-height: 1.1; }
.unit-detail__badge-label { display: block; font-size: 1rem; }

/* Price, bottom left, on green. */
.unit-detail__price {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  padding: 1rem 2.25rem;
  background: var(--c-green);
  color: var(--c-white);
}

.unit-detail__price-now { display: block; font-size: 2.25rem; font-weight: 700; line-height: 1.2; }
.unit-detail__price-before { display: block; font-size: 1rem; }

/* Full name, bottom right, on the same slate as the year. */
.unit-detail__name {
  position: absolute;
  inset-block-end: 0;
  inset-inline-end: 0;
  margin: 0;
  padding: 1.125rem 2.25rem;
  background: var(--c-slate-900);
  color: var(--c-white);
  font-size: 1.625rem;
}

.unit-detail__sold {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  padding: 0.875rem 2rem;
  background: var(--c-grey-900);
  color: var(--c-white);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 1.125rem;
}

.unit-detail__arrow {
  position: absolute;
  inset-block-start: 50%;
  transform: translateY(-50%);
  width: 2.75rem;
  height: 2.75rem;
  border: 0;
  border-radius: 50%;
  background: var(--c-green);
  color: var(--c-white);
  font-size: 1.75rem;
  line-height: 1;
  cursor: pointer;
}

.unit-detail__arrow--prev { inset-inline-start: 1rem; }
.unit-detail__arrow--next { inset-inline-end: 1rem; }

/*
  The photo links are the no-script fallback. Once the carousel takes over they are hidden,
  which is why the class is added by script rather than sitting in the markup.
*/
.unit-detail__photo-link { display: block; font-size: 0.875rem; }
.unit-detail__stage.is-interactive .unit-detail__photo-link { display: none; }

/* ---------- specification band ---------- */

/*
  Flex rather than grid: the actions have to sit hard right whatever number of facts the
  unit records, and placing them in a grid's last column left collapsed empty tracks
  between them and the figures.
*/
.unit-specs {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  align-items: start;
  padding-block: 1.75rem;
}

.unit-specs__group { flex: 0 1 auto; min-width: 7rem; }

.unit-specs__label {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--c-grey-500);
}

/* Design: the figure is large and dark, the label small above it. */
.unit-specs__value {
  margin: 0 0 0.75rem;
  font-size: 1.375rem;
  color: var(--c-grey-900);
}

.unit-specs__group--financing .unit-specs__value { font-weight: 400; }

.unit-specs__note {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--c-grey-500);
}

.unit-specs__terms { display: block; }

.unit-specs__icon {
  display: block;
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.5rem;
  fill: var(--c-grey-900);
}

/*
  The calculator opens the financing offer, so it has to be a button — but it should still
  read as the icon the design puts there, not as a control.
*/
.unit-specs__calc {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.unit-specs__calc:hover .unit-specs__icon,
.unit-specs__calc:focus-visible .unit-specs__icon { fill: var(--c-green); }

.unit-specs__actions {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  /* Pushed to the right of the band, as the design places it. */
  margin-inline-start: auto;
  min-width: 12rem;
}

.unit-specs__action {
  padding: 0.5rem 1.25rem;
  border: 0;
  border-radius: 2px;
  background: var(--c-green);
  color: var(--c-white);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.unit-specs__action:hover { background: var(--c-green-alt); }

/* ---------- equipment ---------- */

.unit-equipment {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 2rem;
  padding-block: 1.5rem;
  border-top: 1px solid var(--c-grey-200);
}

.unit-equipment__title {
  margin: 0 0 0.5rem;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--c-green);
}

.unit-equipment__list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
  color: var(--c-grey-900);
}

.unit-equipment__list li { padding-block: 0.125rem; }

.unit-equipment__value { color: var(--c-grey-500); }

/*
  Clipped with a fade until opened. Only applied once the script has decided the column is
  long enough to need it, so a short list is never cut off behind a button that does nothing.
*/
.unit-equipment__list.is-clipped {
  position: relative;
  max-height: 9rem;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 60%, transparent);
  mask-image: linear-gradient(to bottom, #000 60%, transparent);
}

/* Centred under its column, as the design places it. */
.unit-equipment__more {
  display: block;
  width: 100%;
  margin-top: 0.5rem;
  padding: 0;
  border: 0;
  background: none;
  font-size: 1.75rem;
  line-height: 1;
  color: var(--c-green);
  text-align: center;
  cursor: pointer;
}

@media print {
  /* Printing a unit should give the whole specification, not a teaser. */
  .unit-equipment__list.is-clipped { max-height: none; mask-image: none; }
  .unit-equipment__more,
  .unit-specs__actions,
  .unit-detail__arrow,
  .site-header,
  .site-footer,
  .modal { display: none; }
}

.unit-detail__financing { margin: 1rem 0; font-size: 0.9375rem; }
.unit-detail__financing-terms { display: block; font-size: 0.8125rem; color: var(--c-grey-500); }

.unit-detail__facts,
.unit-detail__attributes {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.25rem 1rem;
  margin: 0 0 1.5rem;
}

.unit-detail__facts dt,
.unit-detail__attributes dt { color: var(--c-grey-500); font-size: 0.875rem; }
.unit-detail__facts dd,
.unit-detail__attributes dd { margin: 0; font-size: 0.875rem; color: var(--c-grey-900); }

.unit-detail__attributes { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }

.unit-detail__cta {
  display: inline-block;
  padding: 0.75rem 2rem;
  background: var(--c-green);
  color: var(--c-white);
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
  text-decoration: none;
}

.unit-detail__group-title {
  margin: 2rem 0 1rem;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 1.25rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--c-grey-400);
}

@media (max-width: 900px) {
  /*
    A model name does not fit on one line at this width, and clipping it mid-word — which
    is what nowrap did, silently, because the body clips its overflow — loses the end of
    the name the page is about.
  */
  .unit-detail__bar { flex-wrap: wrap; }
  .unit-detail__title { white-space: normal; }
  .unit-detail__rule--grow { display: none; }

  /* The overlays crowd a phone-width photo, so they sit tighter and smaller. */
  .unit-detail__badge,
  .unit-detail__price,
  .unit-detail__name,
  .unit-detail__sold { padding: 0.375rem 0.75rem; }

  .unit-detail__badge-value,
  .unit-detail__price-now { font-size: 1.25rem; }

  .unit-detail__badge-label,
  .unit-detail__price-before { font-size: 0.8125rem; }

  /*
    Capped so it shares the bottom edge with the price rather than covering it: both are
    anchored to that edge, the name is painted last, and a long one hid the price outright.
  */
  .unit-detail__name {
    max-width: 55%;
    font-size: 0.8125rem;
    line-height: 1.3;
  }

  .unit-detail__sold { font-size: 0.875rem; }

  .unit-detail__arrow { width: 2.25rem; height: 2.25rem; font-size: 1.375rem; }
  .unit-detail__arrow--prev { inset-inline-start: 0.5rem; }
  .unit-detail__arrow--next { inset-inline-end: 0.5rem; }
}

/* ---------- contact form ---------- */

.contact-block__heading {
  margin: 0 0 0.5rem;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 1.5rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--c-grey-400);
}

.contact-form__fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
}

.contact-form__field { display: flex; flex-direction: column; gap: 0.375rem; }
.contact-form__field--wide { grid-column: 1 / -1; }

.contact-form__label { font-size: 0.8125rem; font-weight: 600; color: var(--c-grey-500); }

.contact-form__control {
  width: 100%;
  padding: 0.625rem 0.75rem;
  border: 1px solid var(--c-grey-200);
  border-radius: 2px;
  background: var(--c-white);
  font: inherit;
  color: var(--c-grey-900);
}

.contact-form__submit {
  margin-top: 1rem;
  padding: 0.75rem 2.5rem;
  border: 0;
  border-radius: 2px;
  background: var(--c-green);
  color: var(--c-white);
  font: inherit;
  font-weight: 700;
  text-transform: uppercase;
  cursor: pointer;
}

.contact-form__receipt {
  padding: 1rem;
  background: var(--c-grey-100);
  border-left: 4px solid var(--c-green);
}

.contact-form__error {
  margin: 0 0 1rem;
  padding: 0.75rem 1rem;
  background: var(--c-grey-100);
  border-left: 4px solid var(--c-grey-900);
}

.contact-form__optional { font-weight: 400; color: var(--c-grey-400); }

/* ---------- dialogs ---------- */

/*
  The unit page's two forms and its financing offer. A <dialog>, so the backdrop, the
  focus trap and Escape are the browser's job rather than this stylesheet's.
*/
.modal {
  width: min(46rem, calc(100vw - 2rem));
  max-height: calc(100vh - 4rem);
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: var(--c-white);
  color: var(--c-grey-900);
}

.modal::backdrop { background: rgb(0 0 0 / 0.55); }

/*
  No script: the fragment alone opens it. A closed dialog is display:none in the browser's
  own stylesheet, and any author rule outranks that — so the form is never unreachable.
*/
.modal:not([open]):target {
  display: block;
  margin: 2rem auto;
  box-shadow: 0 2px 24px rgb(0 0 0 / 0.25);
}

/* The box scrolls, not the dialog, so the heading and close button stay put. */
.modal__box {
  max-height: inherit;
  padding: 1.5rem;
  overflow-y: auto;
}

.modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.modal__title {
  margin: 0;
  font-family: var(--font-condensed);
  font-stretch: 75%;
  font-size: 1.375rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--c-grey-900);
}

.modal__close {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--c-grey-100);
  font-size: 1.25rem;
  line-height: 1;
  color: var(--c-grey-700);
  cursor: pointer;
}

.modal__close:hover { background: var(--c-green); color: var(--c-white); }

.modal__lead { margin: 0 0 1.25rem; color: var(--c-grey-500); }

/* ---------- financing offer ---------- */

.financing + .financing {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--c-grey-200);
}

/* The partner's logo beside their name, sized by height so any aspect ratio behaves. */
.financing__head {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  margin-bottom: 0.75rem;
}

.financing__logo {
  flex: 0 0 auto;
  width: auto;
  height: 2rem;
  max-width: 9rem;
  object-fit: contain;
}

.financing__partner { margin: 0; font-size: 1rem; }

/* Five columns do not fit a phone; the table scrolls inside its own box, not the page. */
.financing__scroll { overflow-x: auto; }

.financing__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.financing__table th,
.financing__table td {
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--c-grey-200);
  text-align: start;
  white-space: nowrap;
}

.financing__table th {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-grey-500);
}

.financing__amount { font-weight: 700; color: var(--c-green); }

.financing__terms {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0 1.5rem;
  margin: 1.25rem 0 0;
}

.financing__term {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.375rem 0;
  border-bottom: 1px dotted var(--c-grey-200);
  font-size: 0.875rem;
}

.financing__term dt { color: var(--c-grey-500); }
.financing__term dd { margin: 0; }

.financing__apply {
  display: inline-block;
  margin-top: 1.25rem;
  padding: 0.625rem 1.5rem;
  border-radius: 2px;
  background: var(--c-green);
  color: var(--c-white);
  font-weight: 700;
  text-transform: uppercase;
  text-decoration: none;
}

.financing__note {
  margin: 1.5rem 0 0;
  font-size: 0.75rem;
  color: var(--c-grey-500);
}

/*
  The honeypot. Off-screen rather than display:none — some bots skip fields that are
  hidden the obvious way, and this one is meant to be filled in.
*/
.contact-form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Block Grid layout primitives, driven by the data attributes Umbraco emits. */
.umb-block-grid__layout-container {
  display: grid;
  grid-template-columns: repeat(var(--umb-block-grid--grid-columns, 12), minmax(0, 1fr));
  gap: 1.5rem;
}

.umb-block-grid__layout-item {
  grid-column: span var(--umb-block-grid--item-column-span, 12);
  min-width: 0;
}

.umb-block-grid__area-container {
  display: grid;
  grid-template-columns: repeat(var(--umb-block-grid--area-grid-columns, 12), minmax(0, 1fr));
  gap: 1.5rem;
}

.umb-block-grid__area {
  grid-column: span var(--umb-block-grid--area-column-span, 12);
  min-width: 0;
}

@media (max-width: 900px) {
  .umb-block-grid__layout-item,
  .umb-block-grid__area { grid-column: 1 / -1; }
}

/* ---------- footer ---------- */

.site-footer {
  margin-top: 4rem;
  background: var(--c-grey-900);
  color: var(--c-white);
  font-size: 0.875rem;
}

.site-footer__inner {
  max-width: var(--measure);
  margin-inline: auto;
  padding: 2.5rem var(--gutter);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: 2rem;
}

.site-footer p { margin: 0 0 0.25rem; }

.site-footer a { color: var(--c-white); text-decoration: none; }
.site-footer a:hover { color: var(--c-green); }

.site-footer__company-name { font-weight: 600; }

/*
  Text, then its green icon beside it. Not pushed to the column edge: with the icon at
  the far right it read as belonging to the column rather than to the line it marks.
*/
.site-footer__line {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

.site-footer__icon {
  flex: 0 0 auto;
  width: 1.25rem;
  height: 1.25rem;
  fill: var(--c-green);
}

.site-footer__column ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-footer__column li { margin-bottom: 0.25rem; }

/* ---------- mobile ---------- */

/*
  Touch targets.

  Everything tappable gets 44px of height, which is the smallest a finger reliably hits.
  Applied by padding rather than by height so the text stays where the design puts it and
  only the target around it grows — the footer's link lists, for instance, look unchanged
  but are no longer 19px tall.
*/
@media (hover: none), (max-width: 900px) {
  .site-nav__link,
  .site-nav__sub-link,
  .site-footer a,
  .unit-search__advanced,
  .unit-list__advanced,
  .unit-sort__option {
    min-height: 44px;
    display: flex;
    align-items: center;
  }

  /* The footer's icon rows keep their icon beside the text rather than stacking. */
  .site-footer__line a { display: inline-flex; }

  /*
    One column, and the icons line up down its right edge.

    The rule above puts each icon straight after its own text, which is right when the
    footer is several columns wide - at the far edge it would read as marking the column
    rather than the line. In a single column there is no column for it to be mistaken for,
    and text-length alone was scattering the three icons across 50px of the width. The
    design lines them up.
  */
  .site-footer__inner { grid-template-columns: 1fr; }

  .site-footer__line { justify-content: space-between; }

  .site-footer__line > :first-child { flex: 0 1 auto; }

  .site-header__toggle { min-width: 44px; min-height: 44px; }

  /* Narrow controls: widened rather than made taller, since their height is already fine. */
  .unit-list__close,
  .unit-sort__option { min-width: 44px; justify-content: center; }
}

/*
  The menu collapses well before the rest of the site does, and not at the shared 900px
  breakpoint the other components use.

  The logo and the six labels are 911px of fixed width between them, so with any gap worth
  having the bar stops fitting around 1150 — it was overflowing the window and scrolling
  the page sideways from 900 down, which the auto margin that used to push the menu right
  had hidden rather than solved. Only the header switches here; everything else keeps its
  own breakpoint.
*/
@media (max-width: 1200px) {
  .site-header__toggle { display: flex; }

  .site-nav {
    display: none;
    flex-basis: 100%;
  }

  .site-nav.is-open { display: block; }

  .site-header__inner { flex-wrap: wrap; }

  .site-nav__list { flex-direction: column; gap: 0; height: auto; }

  /*
    Blocks again, not flex rows. The desktop item is a flex row so it can fill the header's
    height; here that put each submenu beside its parent link instead of under it.
  */
  .site-nav__item { display: block; }

  /* Nothing to bridge when the submenu sits directly under its parent in the flow. */
  .site-nav__item--has-children::after { content: none; }

  /* In the stacked menu it is a plain group of links, not a floating panel. */
  .site-nav__sub {
    position: static;
    display: block;
    background: transparent;
    box-shadow: none;
    clip-path: none;
    transform: none;
  }
  .site-nav__sub-link { color: var(--c-grey-700); padding-inline-start: 2rem; }
}


/* ---------- department ---------- */
/*
  A contact card for one Danbase department. Everything in it comes from the gateway, so it
  has to survive any of it being absent — a department with no phone number, no staff
  released to the web, or no opening hours still renders as a heading and whatever is left.
*/
.department {
  height: 100%;
  padding: 1.75rem;
  background: var(--c-white);
  border: 1px solid var(--c-grey-100);
  /* The brand green along the top, the way the section rules carry it elsewhere. */
  border-top: 3px solid var(--c-green);
  border-radius: 6px;
  box-shadow: var(--shadow-sm);
  /*
    Queried on its own width, not the window's. The block can be placed 4, 6 or 12 columns
    wide, so a card can be a third of a wide page — a viewport media query would give that
    narrow card two columns and squeeze both.
  */
  container-type: inline-size;
}

.department__name {
  margin: 0;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--c-grey-100);
  font-family: var(--font-condensed);
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--c-grey-900);
}

.department__description {
  margin: 1rem 0 0;
  color: var(--c-grey-700);
}

.department__body {
  display: grid;
  gap: 1.75rem;
  margin-top: 1.25rem;
}

@container (min-width: 34rem) {
  .department__body {
    grid-template-columns: 1fr 1fr;
    gap: 2.5rem;
  }
}

.department__reach {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/*
  Card type, not page type. The body scale is 20px, which is right for prose and too loud
  for a stack of phone numbers inside a panel.
*/
.department__group { font-size: 1.0625rem; }

.department__subheading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.625rem;
  font-family: var(--font-condensed);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-grey-500);
}

.department__icon {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  fill: var(--c-green);
}

.department__contact,
.department__staff ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.department__contact li {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

.department__contact li + li { margin-top: 0.5rem; }

.department__contact a,
.department__employee-links a {
  color: var(--c-green-dark);
  text-decoration: none;
  /* Long addresses break rather than pushing the card wider than its column. */
  overflow-wrap: anywhere;
}

.department__contact a:hover,
.department__employee-links a:hover,
.department__contact a:focus-visible,
.department__employee-links a:focus-visible { text-decoration: underline; }

/*
  Two columns of their own, sitting next to each other rather than spread across the card:
  most dealers open the same hours all week, so this is usually a single row and a full
  justification would strand the time out on the right.
*/
/*
  Day on the left, hours on the right, filling the column with a hairline between rows —
  the way the times are set out on a door. Hugging each other in the middle of the card, as
  two max-content columns did, read as an accident rather than a table of hours.
*/
.department__hours dl {
  display: grid;
  grid-template-columns: 1fr auto;
  margin: 0;
}

.department__hours dt,
.department__hours dd {
  padding-block: 0.5rem;
  border-top: 1px solid var(--c-grey-100);
}

.department__hours dt:first-of-type,
.department__hours dt:first-of-type + dd { border-top: 0; }

.department__hours dt { color: var(--c-grey-700); }

.department__hours dd {
  margin: 0;
  text-align: right;
  color: var(--c-grey-900);
  font-variant-numeric: tabular-nums;
}

.department__employee {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
  padding-block: 0.875rem;
}

.department__employee:first-child { padding-top: 0; }

.department__employee + .department__employee { border-top: 1px solid var(--c-grey-100); }

/*
  height:auto so the width and height attributes on the img do not fight the sizing here —
  the same trap that made the quick-link tiles 515px tall.

  Cropped, not squashed: Danbase serves 180x240 portraits and the stand-in is square, and
  both have to end up as the same circle.
*/
.department__employee-photo {
  flex: none;
  width: 3rem;
  height: auto;
  aspect-ratio: 1;
  border-radius: 50%;
  object-fit: cover;
  background: var(--c-grey-100);
  box-shadow: 0 0 0 1px var(--c-grey-100);
}

.department__employee-details {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.department__employee-name {
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-grey-900);
}

.department__employee-title {
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--c-grey-500);
}

/* Wraps to a second line before it widens the card. */
.department__employee-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.125rem 1rem;
  margin-top: 0.25rem;
  font-size: 1rem;
}

/* Tap targets: these are links people use on a phone. */
@media (max-width: 900px) {
  .department__contact a,
  .department__employee-links a {
    display: inline-block;
    padding-block: 0.25rem;
  }
}

/* ---------- heading block ---------- */
/*
  The heading block reuses the section heading's treatment — uppercase condensed, the same
  grey — and varies only in size, because the level is both what the heading means and how
  large it is. One decision, not two, so a page's visible hierarchy cannot contradict its
  real one.

  h2 is deliberately the same size as the existing section headings: a heading block placed
  at the top of a section should be indistinguishable from the field it replaces.
*/
.section__heading--h1 { font-size: 1.75rem; margin-bottom: 1.25rem; }
.section__heading--h2 { font-size: 1.0625rem; }
.section__heading--h3 { font-size: 1rem; color: var(--c-grey-700); }
.section__heading--h4 {
  font-size: 0.9375rem;
  color: var(--c-grey-700);
  letter-spacing: 0.06em;
}

@media (max-width: 900px) {
  .section__heading--h1 { font-size: 1.5rem; }
}

/* ---------- printable unit sheet ---------- */

/*
  The sheet at /print/unit/{id}, and the PDF a headless browser makes of it.

  One document rather than two: it is styled here, beside everything else, so it uses the
  same type and the same green as the site instead of drifting into its own look. It is
  written for A4 and renders identically on screen, which is what makes it possible to work
  on without generating a PDF every time.
*/
@page {
  size: A4;
  /* The renderer is told to add none, so the margin is here where it can be seen. */
  margin: 12mm 12mm 10mm;
}

.sheet-body {
  margin: 0;
  background: var(--c-white);
  color: var(--c-grey-900);
  font-size: 9.5pt;
  line-height: 1.35;
}

/*
  On screen the sheet is a piece of A4 on a desk — the full 210x297 with the same margins
  @page uses, so what you are looking at is the page that will come out. In print the page
  box supplies all of that and the frame goes away.

  A column, so the footer can be pushed to the foot of the page rather than sitting under
  whatever the equipment list happened to end at.
*/
.sheet {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 210mm;
  min-height: 297mm;
  margin: 8mm auto;
  padding: 12mm 12mm 10mm;
  background: var(--c-white);
  box-shadow: 0 0 0 1px var(--c-grey-200);
}

@media print {
  .sheet {
    width: auto;
    /*
      A4 less the margins @page already applied, and 2mm short of it. Asking for the exact
      height risks a fraction of a millimetre of rounding tipping the whole sheet onto a
      second page, which is a poor trade for 2mm of white at the bottom.
    */
    min-height: 273mm;
    margin: 0;
    padding: 0;
    box-shadow: none;
  }
}

/* Pushed to the foot of the page, however short the caravan's equipment list is. */
.sheet__foot { margin-top: auto; }

.sheet__head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 6mm;
  padding-bottom: 3mm;
  border-bottom: 2px solid var(--c-green-band);
}

.sheet__logo { width: 42mm; height: auto; }

.sheet__name {
  margin: 0;
  font-size: 15pt;
  font-weight: 700;
  line-height: 1.15;
}

.sheet__brand { margin: 0.5mm 0 0; color: var(--c-grey-700); }

.sheet__price { text-align: right; }

.sheet__price-now {
  margin: 0;
  font-size: 15pt;
  font-weight: 700;
  color: var(--c-green-band);
  white-space: nowrap;
}

.sheet__price-before {
  margin: 0.5mm 0 0;
  color: var(--c-grey-700);
  text-decoration: line-through;
  white-space: nowrap;
}

.sheet__top {
  display: grid;
  grid-template-columns: 1fr 62mm;
  gap: 6mm;
  margin-top: 5mm;
}

/*
  Capped rather than sized: a caravan photographed in portrait would otherwise push
  everything below it off the page.
*/
.sheet__photo {
  display: block;
  width: 100%;
  max-height: 62mm;
  object-fit: cover;
  border-radius: 2px;
}

.sheet__specs {
  width: 100%;
  border-collapse: collapse;
  align-self: start;
}

.sheet__specs th,
.sheet__specs td {
  padding: 1.2mm 0;
  border-bottom: 1px solid var(--c-grey-100);
  text-align: left;
  font-weight: 400;
}

.sheet__specs th { color: var(--c-grey-700); }
.sheet__specs td { text-align: right; font-weight: 700; }

.sheet__promotion {
  margin: 4mm 0 0;
  font-weight: 700;
  color: var(--c-green-band);
}

.sheet__description { margin: 3mm 0 0; }

.sheet__heading {
  margin: 5mm 0 2mm;
  font-size: 10pt;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-grey-900);
  border-bottom: 1px solid var(--c-grey-200);
  padding-bottom: 1mm;
}

/*
  Two columns that flow. The equipment is the part that varies most between one caravan and
  the next — a few lines on a bare one, dozens on a loaded one — so it is the part given the
  room to grow, and it fills both columns evenly rather than running down the left.
*/
.sheet__equipment-columns {
  columns: 2;
  column-gap: 6mm;
}

.sheet__group {
  break-inside: avoid;
  margin-bottom: 2.5mm;
}

.sheet__group-name {
  margin: 0 0 0.5mm;
  font-size: 9.5pt;
  font-weight: 700;
  color: var(--c-green-band);
}

.sheet__group-items { margin: 0; color: var(--c-grey-700); }

.sheet__finance { break-inside: avoid; }

.sheet__finance-line { margin: 0; color: var(--c-grey-700); }

.sheet__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 6mm;
  padding-top: 3mm;
  border-top: 2px solid var(--c-green-band);
}

.sheet__contact p { margin: 0; }

.sheet__company { font-weight: 700; }

.sheet__qr {
  flex: 0 0 auto;
  width: 20mm;
  height: 20mm;
}

.sheet__qr svg { display: block; width: 100%; height: 100%; }

.sheet__finance-table {
  width: 100%;
  margin-top: 2mm;
  border-collapse: collapse;
  font-size: 8.5pt;
}

.sheet__finance-table th,
.sheet__finance-table td {
  padding: 1mm 1.5mm;
  border-bottom: 1px solid var(--c-grey-100);
  text-align: right;
  font-weight: 400;
  white-space: nowrap;
}

.sheet__finance-table thead th { color: var(--c-grey-700); font-weight: 700; }

/*
  The first cell of every row is a label, not a figure, so it reads from the left like the
  three below it. Only the numbers are right-aligned, which is what makes them line up.
*/
.sheet__finance-table th:first-child { text-align: left; color: var(--c-grey-700); }
