/* portal.mjmda.eu — built to the structure of mjmda.eu, not to the staff tools.
 *
 * WHY THIS FILE REPLACED page-home.css. The first cut of this site reused the
 * staff platform's base.css and components.css, which meant it inherited the
 * tools' own conventions: a centred shell with a maximum width, uppercase
 * tracked display headings, rounded buttons. Jan's instruction on 10 September
 * 2026 was that the portal should be structured like the practice's own
 * website instead, and he is right — a visitor arriving from mjmda.eu should
 * not feel handed to a different company.
 *
 * SO EVERY RULE BELOW WAS MEASURED FROM mjmda.eu, on 10 September 2026, from
 * the live theme (wp-content/themes/mjmda/dist/styles/main_c1b51152.css) and
 * from the computed styles of the rendered page. What was found:
 *
 *   header .banner      96px tall, white, logo left, nav right
 *   nav links           Calibri 16px, uppercase, #464743, padding 1.6em 0.9em
 *   headings            Roboto Condensed 700, SENTENCE CASE, no tracking
 *                       (the h2 on their home page is 40px)
 *   buttons             #D67437 ground, white, Calibri 14px, padding 0.9em,
 *                       square — border-radius 0 — with a right arrow
 *   footer              #464743, white logo, six link columns, contact block
 *   containers          full-bleed. max-width is `none`; the page runs edge to
 *                       edge and the padding is on inner blocks.
 *   accent bar          .call-back, #D67437, 112px
 *
 * WHAT IS STILL SHARED WITH THE STAFF TOOLS, AND WHY THAT IS NOT A CONTRADICTION.
 * Only css/fonts.css, css/tokens.css, the font files and the brand marks —
 * and those came FROM mjmda.eu in the first place. The colours in tokens.css
 * were sampled from this same theme (#D67437 appears 124 times in it, #464743
 * 64 times), and the faces are the same pairing the site uses. What is not
 * shared any more is structure, which is the thing that was wrong.
 *
 * THE ONE DELIBERATE DEPARTURE, AND IT IS A CONTRAST ONE.
 * mjmda.eu sets white 14px text on the raw brand orange #D67437. That measures
 * 2.99:1, which is below the 4.5:1 WCAG AA asks of body-sized text — so a
 * literal copy would put the site's main call to action below the accessibility
 * floor this workspace holds to. Button FACES therefore take --orange-fill
 * (#B2602E, 4.56:1 behind white), which the eye reads as the same brand orange.
 * The raw #D67437 still carries every non-text use: the accent band, rules and
 * marks, exactly as it does on mjmda.eu. Flagged to Jan; one token to change
 * back if he wants the exact hex. */

/* ── reset ───────────────────────────────────────────────────────────────
   Small and local, rather than pulling in the staff platform's base.css,
   which carries its topbar, its shell and its own button system with it. */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--fb);          /* Carlito — Calibri's metrics, licensed */
  font-size: 16px;                 /* mjmda.eu's body size, measured */
  line-height: 1.6;
  color: var(--dark-grey);
  background: var(--white);        /* their pages are white, not off-white */
  -webkit-text-size-adjust: 100%;
}

img { max-width: 100%; height: auto; }

h1, h2, h3, h4 {
  font-family: var(--ft);          /* Roboto Condensed */
  font-weight: 700;
  line-height: 1.15;
  color: var(--brand-dark);
  margin: 0;
  /* NOT uppercase and NOT tracked. This is the single most visible difference
     from the staff tools, and it is what makes the page read as theirs. */
  text-transform: none;
  letter-spacing: normal;
}

a { color: inherit; }

:focus-visible { outline: 3px solid var(--orange-fill); outline-offset: 2px; }
/* The orange ring is #B2602E, about 1.6:1 against the charcoal — on the hero, the
   statement band, the cards, the footer and the open mobile menu a keyboard user
   could not see where they were. On dark grounds the ring takes MJM|DA's own
   light tint (#F9B68C, 5.39:1); on the orange strip it goes white (4.56:1). */
.hero :focus-visible, .statement :focus-visible, .cardx :focus-visible,
.footer :focus-visible, .header-menu.is-open :focus-visible { outline-color: var(--orange-on-dark); }
.strip :focus-visible { outline-color: #fff; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--surface-dark); color: #fff;
  padding: 0.9em 1.2em; font-size: 14px;
}
.skip-link:focus { left: 0; }

/* ── the shared gutter ───────────────────────────────────────────────────
   mjmda.eu is full-bleed and puts its padding on inner blocks (space1l /
   space2l and so on). This is that idea with one name. */
/* Their outer gutter is .space1l plus .space2l — 3vw and 5vw — so it is exactly
   8vw at every width: 31px on a phone, 115 at 1440, 154 at 1920. It was capped
   at 115px here, which agreed at 1440 and drifted everywhere wider — at 1920 the
   banner and footer sat 38px outside theirs on the left and the footer 62px on
   the right. Never under 1.25rem, which only bites below 250px. */
.pad { padding-left: max(1.25rem, 8vw); padding-right: max(1.25rem, 8vw); }

/* ── header ──────────────────────────────────────────────────────────────
   Their banner: white, logo left, nav right, 96px on a desktop. */
/* No rule beneath: theirs has none, and the 1px made this banner 97px to their
   96. position:relative is what the phone menu hangs from — see the overlay. */
.banner {
  position: relative;
  background: #fff;
}

/* THE ROW IS NOT CENTRED ON THEIRS, AND CENTRING IT WAS THE VISIBLE DIFFERENCE.
   Their banner row stretches every child to the full 96px and each one places
   itself inside that: the logo hangs from the top edge, the menu stands on the
   bottom edge, and Login and the marks rest 24px above the bottom. Centred, the
   menu sat 13px and the Login group 14px higher than theirs, and the logo 8px
   lower — measured at 1440 on 11 September 2026. No gap either: the logo's
   24px margin is all the space before the menu, and a leftover 1.5rem gap had
   pushed the menu 24px right. */
.banner-in {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 0;
  /* 96px exactly, the way theirs is. The nav links carry their own 1.6em of
     vertical padding, so any padding here is added on top and the bar grows —
     it measured 121px before this was removed. */
  min-height: 96px;
  padding-top: 0;
  padding-bottom: 0;
}

/* A block, so the logo hangs from the top edge as theirs does. */
.banner-logo { display: block; flex: 0 0 auto; margin-right: 24px; }
/* Their logo is not a fixed size. Measured: 100px at 1024, 109 at 1280, 116 at
   1366, 122 at 1440 — about 8.5vw, never under 100px. A fixed 122px was too
   heavy everywhere below 1440. */
/* Their logo is an inline image, so the line it sits on hangs a descender under
   it — 4.39px, measured unrounded and the same at every width. Below about
   1660px that is lost inside the 96px. Above it the logo is taller than 91.6px
   and theirs pushes the banner down: 96.67 at 1680, 109.84 at 1920, 145 at 2560.
   The margin is that descender, so this banner grows at the same widths by the
   same amount — and the menu and Login, standing on the bottom edge, go with it. */
.banner-logo img { display: block; width: max(100px, 8.5vw); height: auto; margin-bottom: 4.39px; }

/* ── the menu group ──────────────────────────────────────────────────────
   mjmda.eu's banner, measured at 1440: logo at x=115 (122 wide), nav from
   x=262 running 776 across, and .header-right from x=1038 running 272 to the
   end. So the nav takes the slack and the right-hand group is pinned to the
   far edge — which is what space-between on a growing wrapper gives.

   ONE THING IS REMOVED AND ONLY ONE: Shop, and the cart that belongs to it,
   on Jan's instruction of 10 September 2026. Everything else is their menu in
   their order — Firm, Portfolio, Case Studies, Services, Contact, Careers,
   then Login, Facebook, Instagram, LinkedIn, Google Business. */
.header-menu {
  flex: 1;
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 0;
}

/* The logo at the head of their phone menu. It lives inside the group so it
   opens with it; nowhere else is it shown. */
.menu-logo { display: none; }

/* The nav takes the slack and spreads its items with space-around, as theirs
   does, rather than packing them against the logo. */
/* Their .nav-primary is a column that stands its list on the BOTTOM of the
   96px — flex-grow 1, column, justify-content flex-end. Each link is 70px (1.6em
   above and below an 18.4px line), so they fill 26 to 96 and the labels sit at
   51. Nor is the list centred across: every item stretches to the tallest. That
   matters at 1024, where "Case Studies" wraps to 88px — the hover bar is placed
   25% up the ITEM, so the other five have to be 88px too for their bars to sit
   where theirs do. */
.nav-primary { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: flex-end; }
.nav-primary ul {
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Calibri, 16px, uppercase, #464743, 1.6em/0.9em padding — measured. */
.nav-primary li { position: relative; display: flex; align-items: center; }

/* Side padding is 1vw, not a fixed 0.9em — 10.24px at 1024, 12.8 at 1280, 14.4
   at 1440, all measured. Line-height is 1.15 (their 18.4px): at 1024 their own
   "Case Studies" wraps to two lines and the banner stays 96px. With the body
   line-height it wrapped to 102px and pushed the banner to 103. */
.nav-primary a {
  display: block;
  padding: 1.6em 1vw;
  font-size: 16px;
  line-height: 1.15;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--dark-grey);
}

/* THEIR TOP-BAR HOVER, COPIED RULE FOR RULE.
   It is not a colour change — the label never moves and never recolours. A 2px
   bar in the brand orange sits under the item, inset 1vw either side and 25%
   up from the bottom, and it scales out from the middle:

     li::after      width: calc(100% - 2vw); height: 2px; background: #d67437;
                    bottom: 25%; left: 1vw; transform: scaleX(0);
                    transition: 0.2s ease
     li:hover::after  transform: scaleX(1)

   The first cut here recoloured the text to orange instantly, with no
   transition and no bar. Wrong effect and no animation at all. */
.nav-primary li::after {
  content: '';
  position: absolute;
  width: calc(100% - 2vw);
  left: 1vw;
  bottom: 25%;
  height: 2px;
  background: var(--orange);
  transform: scaleX(0);
  transition: transform 0.2s ease;
}
/* :focus-within is an addition, not a copy — their site draws nothing for a
   keyboard user, and a menu that answers a mouse but not the Tab key is worth
   one extra selector. */
.nav-primary li:focus-within::after,
.nav-primary li:has(a[aria-current="page"])::after { transform: scaleX(1); }

/* HOVER IS GATED ON A POINTER THAT CAN HOVER. On a phone a tap fires :hover and
   leaves it stuck until the next tap elsewhere, so the bar would sit under
   whatever was last touched — their site has exactly that fault. With a mouse
   this is the same rule, unchanged. */
@media (hover: hover) {
  .nav-primary li:hover::after { transform: scaleX(1); }
}

/* ── the right-hand group ────────────────────────────────────────────────
   Their .header-right: Login at 14px with the user mark before it and 15px of
   space after, then the four social marks at 4px either side, each rendered
   about 15px tall. The marks are MJM|DA's own files, taken from their theme
   and served from this origin — the policy allows images from 'self' only, and
   hotlinking their WordPress would break the moment that theme is rebuilt. */
/* Their .header-right is a column pinned to the bottom of the row, holding one
   row with 1.5em — 24px — above and below it. That row is 20px tall on theirs,
   so Login and the marks occupy 52 to 72. Without their cart the tallest thing
   left would be Login's 17px line and the row would shrink to it, so the height
   is held at theirs: 68px, padding included. */
.header-right {
  display: flex;
  align-items: stretch;
  align-self: flex-end;
  height: 68px;
  padding: 24px 0;
}

/* Measured from their .login, which carries the divider itself:
     display:flex; font-size:14px; line-height:17px; color:#464743;
     padding-right:15px; margin-right:15px; border-right:1px solid #d67437
   The divider is as tall as the link — 20px on their banner, 17px in their
   phone menu. This link used to take 12px of padding above and below to reach a
   44px target, and the orange rule grew to 44px with it, more than twice theirs.
   The target is now the ::before further down, which a tap counts as the link
   and the eye never sees.
   THERE IS NO HOVER STATE ON THIS LINK ON THEIR SITE, so there is none here. */
.header-right .login {
  position: relative;
  display: flex;
  justify-content: center;
  font-size: 14px;
  line-height: 17px;
  letter-spacing: 0;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--dark-grey);
  padding-right: 15px;
  margin-right: 15px;
  border-right: 1px solid var(--orange);
}
/* Theirs: the full height of the link, 10px either side, at the file's 12px —
   a 32px box. content-box, because this sheet is border-box, and 20px of
   padding inside a 12px width would leave the mark nothing to draw in. */
.header-right .login img { box-sizing: content-box; width: 12px; height: 100%; padding: 0 10px; }
/* The account holder's name in place of LOGIN (js/nav.js) keeps the banner's one
   line: a long name is cut with an ellipsis, and the whole name is the link's
   title and accessible name. */
.header-right .login-label { min-width: 0; max-width: 14em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Theirs: a column with its content centred, 4px of padding and 2px of margin
   either side, the mark 15px tall. The mark's WIDTH is the width attribute in
   the markup — 13, 26, 25 and 28, their numbers — because nothing in their CSS
   overrides it, so each mark draws centred in a box a little wider than itself
   and the four sit 31 to 38px apart. Following the drawing's own width instead
   (width: auto, as this did) packed them 23 to 30px apart and pushed Login 20px
   right of theirs. */
.header-right .icon {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 4px;
  margin: 0 2px;
}
.header-right .icon img { display: block; height: 15px; }

/* TOUCH TARGETS THAT MOVE NOTHING. Their Login and marks are 20px tall, well
   under the 44px a finger needs. Padding would grow the boxes, and the boxes are
   the layout — and Login's divider. A 44px pseudo-element centred on each link
   is part of the link to a tap and invisible to the eye; sideways it covers the
   margin between neighbours, so the targets meet rather than leave dead gaps. */
.header-right .login::before,
.header-right .icon::before,
.footer-social .icon::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 44px;
  transform: translateY(-50%);
}
.header-right .icon::before { left: -2px; right: -2px; }
.footer-social .icon::before { left: -1px; right: -1px; }
/* No hover: their marks do not react, and inventing one would be the kind of
   small difference that makes two sites feel like two sites. */

/* ── the menu button: their hamburger ────────────────────────────────────
   Copied from mjmda.eu's .open.relative, which is the one that shows on a
   phone (their page carries a second .open.fixed that its own script hides):

     50×50, no background, 20px in from the top and right of the viewport;
     three bars 40×4, radius 40px, #464743, right 5px, 15px apart;
     transition: all 0.4s ease.
   Opened: the bars turn white, the middle one goes, the outer two cross —
     rotate(45deg) translateY(12px) translateX(12px)
     rotate(-45deg) translateY(-10px) translateX(10px)

   It replaced a text button reading "MENU" in a grey box, which looked like
   neither site. It is still a <button> with aria-expanded and a label, which
   their <div> is not — the same thing to see, a better thing to use. */
.nav-toggle {
  display: none;
  position: relative;
  flex: 0 0 auto;
  align-self: flex-start;
  width: 50px;
  height: 50px;
  /* 20px from the top, and 20px from the right edge whatever the gutter is —
     theirs pulls itself into the gutter with margin-right: -8vw. */
  margin: 20px calc(20px - max(1.25rem, 8vw)) 0 auto;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  z-index: 1000;
}
.nav-toggle span {
  position: absolute;
  right: 5px;
  width: 40px;
  height: 4px;
  border-radius: 40px;
  background: var(--dark-grey);
  transition: all 0.4s ease;
}
.nav-toggle span:nth-child(1) { top: 8px; }
.nav-toggle span:nth-child(2) { top: 23px; }
.nav-toggle span:nth-child(3) { top: 38px; }
.nav-toggle.is-open span { background: #fff; }
.nav-toggle.is-open span:nth-child(2) { display: none; }
.nav-toggle.is-open span:nth-child(1) { transform: rotate(45deg) translateY(12px) translateX(12px); }
.nav-toggle.is-open span:nth-child(3) { transform: rotate(-45deg) translateY(-10px) translateX(10px); }

/* Without the script there is nothing to open, so there is no button. */
.has-js .nav-toggle { display: none; }

/* Below 960px. Their menu turns into the desktop row AT 960 — it shows from
   (min-width: 60em) — and max-width: 60rem made 960 itself a phone here. */
@media (width < 60em) {
  /* Their banner does NOT shrink on a phone: still 96px, logo 100px at x=31. */
  .banner-in { min-height: 96px; }
  .banner-logo { margin-right: 0; }
  .banner-logo img { width: 100px; }

  .has-js .nav-toggle { display: block; }

  /* ── the overlay: their .open .sub-menu ──
     Pinned to the banner's top-right corner, it grows from nothing to the full width and
     550px tall, in 90% charcoal, on their overshoot curve:
       transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55)
     It pulls back slightly before opening and overshoots before settling — that
     springiness is the whole feel of their menu; a plain ease reads as another
     site.

     visibility is held until the collapse has finished and then dropped, so a
     closed menu is out of the tab order and out of a screen reader's reach.
     Theirs stays focusable at 0×0; the script also sets inert. */
  .has-js .header-menu {
    position: absolute;
    top: 0;
    right: 0;
    width: 0;
    height: 0;
    z-index: 900;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 0;
    padding: 0 0 32px;
    background: rgba(70, 71, 67, 0.9);
    visibility: hidden;
    transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), visibility 0s linear 0.8s;
  }
  .has-js .header-menu.is-open {
    width: 100vw;
    height: 550px;
    visibility: visible;
    transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), visibility 0s;
  }

  /* ABSOLUTE, NOT FIXED. Theirs hangs off their menu button, pulled out to the
     corner of the page, so it scrolls away with the banner. Fixed, this one
     stayed on screen while the button that closes it scrolled off the top. */

  /* It opens under their white logo — their own file — 8em wide with 2em
     beneath, and the whole stack stands on the bottom edge, so a long list
     lifts the logo out of the top: theirs loses 55px of it, and with Shop gone
     this one loses 5. The image keeps its 119px height attribute — theirs is
     not scaled with the width, so the mark draws centred in a 128 by 119 box —
     and the 4.39px under it is the line box theirs sits in. */
  .has-js .menu-logo { display: block; flex: 0 0 auto; width: 8em; margin-bottom: 2em; }
  .has-js .menu-logo img { display: block; width: 100%; height: 119px; margin-bottom: 4.39px; }

  /* The links arrive from off the right edge — margin-right -130vw to 0 over
     0.5s on the same curve — one after another, 0.05s apart for the first five.
     Their sixth and seventh carry no delay; with Shop gone, the sixth here is
     Careers and it carries none either. */
  .has-js .nav-primary { flex: 0 0 auto; width: 100%; }
  .has-js .nav-primary ul { display: block; width: 100%; }
  .has-js .nav-primary li {
    display: block;
    margin-right: -130vw;
    transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  }
  .has-js .header-menu.is-open .nav-primary li { margin-right: 0; }
  .has-js .nav-primary li:nth-child(1) { transition-delay: 0.05s; }
  .has-js .nav-primary li:nth-child(2) { transition-delay: 0.1s; }
  .has-js .nav-primary li:nth-child(3) { transition-delay: 0.15s; }
  .has-js .nav-primary li:nth-child(4) { transition-delay: 0.2s; }
  .has-js .nav-primary li:nth-child(5) { transition-delay: 0.25s; }

  /* white, 400, uppercase, 1em above and below, centred */
  .has-js .nav-primary a { color: #fff; font-weight: 400; padding: 1em 0; text-align: center; }

  /* Login and the marks sit centred beneath, in white: their .socials-mobile
     inverts the charcoal files rather than carrying a third set, so a filter
     here IS the copy. Login keeps its orange divider. */
  .has-js .header-right { width: 100%; height: auto; align-self: auto; justify-content: center; padding: 1.5em 0; flex-wrap: nowrap; }
  .has-js .header-right .login { color: #fff; }
  .has-js .header-right .login img,
  .has-js .header-right .icon img { filter: invert(1); }
  .has-js .header-right .icon { padding: 0 10px; margin: 0 2px; }

  /* Scripts off: the menu cannot be opened, so it is simply shown — a list
     under the banner in the ordinary colours. */
  html:not(.has-js) .banner-in { flex-wrap: wrap; }
  html:not(.has-js) .header-menu { flex-basis: 100%; flex-direction: column; align-items: stretch; }
  html:not(.has-js) .nav-primary ul { flex-direction: column; align-items: stretch; }
  html:not(.has-js) .header-right { height: auto; align-self: auto; justify-content: flex-start; flex-wrap: wrap; }
}

/* ── buttons ─────────────────────────────────────────────────────────────
   Square, orange, white, Calibri 14px, 0.9em padding, arrow on the right.
   See the contrast note at the top for why the face is --orange-fill. */
/* THEIR BUTTON, INCLUDING THE HOVER, WHICH IS THE PART THAT WAS MISSING.
   Measured from .button-orange: Calibri 14px, white, square, min-width 11.2em,
   height 3.5em, padding 0.9rem, with the label vertically centred and a 15px
   arrow beside it.

   The hover is TWO black panels at 10% opacity wiping in from the left, one
   over 0.1s and one over 0.25s:

     ::before  width: 0 -> 100%, transition 0.25s ease
     ::after   width: 0 -> 100%, transition 0.1s ease

   They stack, so the face darkens in two stages — quick, then settling. That
   layering is the whole character of it, and a single background swap (which is
   what this had) reads as a different site. Both panels are needed; one is not
   a simplification of two. */
.btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 11.2em;
  min-height: 3.5em;
  background: var(--orange-fill);
  color: #fff;
  font-family: var(--fb);
  font-size: 14px;
  line-height: 29px;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.9rem 1.4rem;
  border: 0;
  border-radius: 0;               /* their buttons are square */
  cursor: pointer;
}

.btn::before,
.btn::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 0;
  background: #000;
  opacity: 0.1;
  z-index: 0;
}
.btn::before { transition: width 0.25s ease; }
.btn::after  { transition: width 0.1s ease; }
.btn:focus-visible::before, .btn:focus-visible::after { width: 100%; }
@media (hover: hover) {
  .btn:hover::before, .btn:hover::after { width: 100%; }
}

/* The label and the arrow ride above the panels. */
.btn-label, .btn-arrow { position: relative; z-index: 1; }
.btn-arrow { width: 15px; height: auto; filter: invert(1); }

/* Their .button-transparent: a 2px orange edge that FILLS with orange on
   hover — ::before at full opacity over 0.25s, ::after at 0.3 over 0.1s. The
   fill uses the darkened orange for the reason at the top of this file; the
   movement is theirs exactly. */
.btn-ghost {
  background: transparent;
  color: #fff;
  border: 2px solid var(--orange);
  padding: 0.5rem 1.4rem;
}
.btn-ghost::before { background: var(--orange-fill); opacity: 1; }
.btn-ghost::after  { background: var(--orange-fill); opacity: 0.3; }

/* ── the veil ────────────────────────────────────────────────────────────
   MJM|DA'S SIGNATURE DEVICE, AND IT IS WORTH COPYING PRECISELY.
   On mjmda.eu a section that carries a photograph does not use a CSS
   background. It puts an <img class="background-image"> inside a
   position:relative, overflow:hidden block at z-index 0, and lays the charcoal
   over it with the block's own ::before. Measured on their .text-section-child
   and on every .project card in their three-column row.

   Copying the mechanism rather than the look buys two real things: the picture
   is an <img>, so it takes srcset and gets fetched at the size actually needed;
   and the veil is a colour rather than an opacity on the photo, so the ground
   under the text is known and can be reasoned about.

   AND IT HAS TO BE REASONED ABOUT, BECAUSE A PHOTOGRAPH IS NOT A COLOUR.
   Contrast here is only as good as the brightest pixel behind the words. The
   worst case is a blown-out white sky: under charcoal at 0.88 that composites
   to rgb(92,92,89), and against that white text measures 6.6:1 and #E9E9E8
   measures 5.4:1 — both clear AA whatever photograph is dropped in later.
   At the 0.82 this started on, the muted grey the staff tools use for body
   copy measured 3.3:1 against that same white sky and failed. So the veil is
   0.88 and body copy on a veiled band is #E9E9E8, not the muted grey. Neither
   number is decoration; both are the reason a placeholder photograph can be
   swapped for a real one without re-checking every band. */
.veiled { position: relative; overflow: hidden; isolation: isolate; }

.veiled > .veil-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}

.veiled::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(70, 71, 67, 0.88);
}

/* Body copy on a veiled band is lighter than on the flat charcoal, for the
   reason above. Headings stay white. */
.veiled { color: #E9E9E8; }

/* Their orange wash across a dark panel, kept for the hero only so it stays a
   moment rather than a texture. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 60% at 65% 45%, rgba(214, 116, 55, 0.22), transparent 70%);
}

/* ── sections ────────────────────────────────────────────────────────────
   Full-bleed bands, the way their page is built: charcoal, then white, then
   charcoal over a photograph, then #D5D5D5, then the orange strip. That
   alternation is their rhythm, measured down their own home page. */
.band { padding-top: clamp(3rem, 7vw, 5.5rem); padding-bottom: clamp(3rem, 7vw, 5.5rem); }
.band > h2 { font-size: clamp(1.75rem, 4vw, 2.5rem); margin-bottom: 1rem; }

.measure, .narrow { max-width: 62ch; }
.lede { font-size: 18px; line-height: 1.6; }

.eyebrow {
  display: block;
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--orange-text);
  margin-bottom: 0.75rem;
}
.hero .eyebrow, .statement .eyebrow { color: var(--orange-on-dark); }

/* ── hero ────────────────────────────────────────────────────────────── */
.hero { color: #E9E9E8; }
.hero-in {
  display: grid;
  gap: 2.5rem;
  padding-top: clamp(3.5rem, 9vw, 7rem);
  padding-bottom: clamp(3.5rem, 9vw, 7rem);
}
@media (min-width: 62rem) {
  .hero-in { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 4rem; align-items: center; }
}
.hero h1 { font-size: clamp(2.25rem, 5.5vw, 3.25rem); color: #fff; max-width: 18ch; }
.hero .lede { color: #E9E9E8; margin: 1.5rem 0 0; max-width: 52ch; }
.hero-actions { margin-top: 2rem; display: flex; flex-wrap: wrap; gap: 0.75rem; }
/* nothing to override: .btn-ghost is already white-on-transparent with their
   orange edge, which is what the hero wants. */

/* ── the contents card ─────────────────────────────────────────────────── */
.card {
  background: #fff;
  color: var(--dark-grey);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  /* Lifted off the photograph rather than floating on it — the one shadow on
     this site, and it is doing a job. */
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.28);
}
.card h2 { font-size: 20px; margin-bottom: 1.25rem; }

.steps-list { list-style: none; counter-reset: s; margin: 0; padding: 0; }
.steps-list li {
  counter-increment: s;
  display: grid;
  grid-template-columns: 2.25rem 1fr;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--light-grey);
}
.steps-list li:first-child { border-top: 0; }
.steps-list li::before {
  content: counter(s, decimal-leading-zero);
  font-family: var(--ft);
  font-size: 14px;
  color: var(--orange-text);
}
.card-note {
  margin: 1.25rem 0 0;
  padding-top: 1rem;
  border-top: 2px solid var(--orange);
  font-size: 14px;
  color: var(--mid-grey);
}

/* ── what it addresses ──────────────────────────────────────────────────
   Their .about-text-section, with the oversized display word behind it. On
   their page that word is 144px in #D5D5D5 and animates in; here it simply
   sits there, because a word that moves on arrival is a different decision
   from a word that is part of the page. */
.about { position: relative; overflow: hidden; text-align: center; }
/* The copy clears the watermark rather than sitting in it. Measured: at the
   first attempt the word's baseline finished 5px INTO the eyebrow, which read
   as a collision rather than a backdrop. */
.about-in { position: relative; z-index: 1; max-width: 68ch; margin: 0 auto; padding-top: clamp(3rem, 9vw, 7rem); }

.watermark {
  position: absolute;
  /* INSIDE the section, not above it. At -0.18em the top of the letters was cut
     off by the band's own overflow:hidden and the word straddled the edge of
     the charcoal section above — it read as a rendering fault rather than a
     backdrop. */
  top: 0.12em;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--ft);
  font-weight: 700;
  font-size: clamp(4rem, 13vw, 8.5rem);
  line-height: 1;
  /* Lighter than #D5D5D5: this is a texture behind the section, and their own
     word is barely there. It carries no meaning and is hidden from assistive
     software in the markup. */
  color: #EAEAE9;
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

.addresses {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: grid;
  gap: 0;
  text-align: left;
}
@media (min-width: 46rem) { .addresses { grid-template-columns: 1fr 1fr; column-gap: 2.5rem; } }
.addresses li {
  padding: 0.75rem 0 0.75rem 1.75rem;
  border-top: 1px solid var(--light-grey);
  position: relative;
}
/* Their cross marker, reduced to a rule end — the same square language. */
.addresses li::before {
  content: '';
  position: absolute;
  left: 0; top: 1.35em;
  width: 10px; height: 2px;
  background: var(--orange);
}
.about .after { margin-top: 2rem; color: var(--mid-grey); }

/* ── statement band ─────────────────────────────────────────────────────
   Their .text-section-child: centred, over a photograph, narrow paragraph. */
.statement { color: #E9E9E8; text-align: center; }
.statement-in { max-width: 70ch; margin: 0 auto; }
.statement h2 { color: #fff; font-size: clamp(2rem, 5vw, 3rem); }
.statement .narrow { margin: 1.5rem auto 0; }

/* ── three columns ──────────────────────────────────────────────────────
   Their #D5D5D5 ground carrying three photograph cards. */
.three-cols { background: var(--light-grey); }
.three-cols > h2 { margin-bottom: 2.5rem; }

.cards { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.5rem; }
@media (min-width: 48rem) { .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.cardx {
  display: flex;
  min-height: 20rem;
  color: #E9E9E8;
  /* The photograph is the card. Its own veil sits under the body, so the copy
     reads at a measured contrast rather than against whatever the shot does. */
}
.cardx-body {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 1.75rem;
  width: 100%;
}
/* The copy sits at the foot of the card, so the ground is weighted there —
   transparent at the top, near-solid charcoal under the words. It stacks on
   top of the flat veil rather than replacing it. */
.cardx-body::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom, rgba(70, 71, 67, 0) 30%, rgba(70, 71, 67, 0.75) 100%);
}
.cardx .n {
  font-family: var(--ft);
  font-size: 14px;
  letter-spacing: 0.08em;
  color: var(--orange-on-dark);
}
.cardx h3 { color: #fff; font-size: 22px; margin: 0.4rem 0 0.75rem; }
.cardx p { margin: 0; font-size: 15px; }
.cardx::after {
  /* Their orange rule, sitting on the top edge of the card. */
  content: '';
  position: absolute;
  left: 0; top: 0;
  width: 4.5rem; height: 4px;
  background: var(--orange);
  z-index: 1;
}

/* ── the orange strip ───────────────────────────────────────────────────
   Their .call-back bar: the line on the left, the action on the right, across
   the full width. The ground is the darkened orange rather than the raw one —
   see the contrast note at the top of this file. */
.strip { background: var(--orange-fill); color: #fff; }
.strip-in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  padding-top: 1.75rem;
  padding-bottom: 1.75rem;
}
.strip-head {
  font-family: var(--ft);
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2rem);
  margin: 0;
}
.strip-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }
.btn-on-orange { background: #fff; color: var(--orange-fill); }
.btn-on-orange .btn-arrow { filter: none; }   /* dark arrow on a white face */
.strip-alt { color: #fff; font-size: 14px; text-underline-offset: 3px; }

/* ── footer ──────────────────────────────────────────────────────────────
   Every number here was read off mjmda.eu at 390, 1024, 1280 and 1440 on
   10–11 September 2026.

   Gutters are asymmetric: 8vw on the left and 13vw on the right (115/187 at
   1440, 82/133 at 1024, 31/51 on a phone). The content starts flush with the
   top — their logo's orange bar touches the footer's top edge.

   NO "Designed & Developed by" CREDIT. Their footer carries Keen's, because
   Keen built that site. Repeating it here would credit this one to a company
   that did not build it. */
.footer { background: var(--surface-dark); color: var(--on-dark-muted); font-size: 14px; padding-bottom: 32px; }
.footer-in.pad { display: flex; flex-direction: column; padding-right: max(1.25rem, 13vw); }

/* ── brand block ── */
/* Their footer logo is the transparent 2026 PNG — dim grey letters and the
   orange bar — at about 9vw, never under 100px (100 at 1024 and on a phone, 115
   at 1280, 130 at 1440). The white SVG this used was brighter than theirs by a
   distance you could see from across the room. */
/* 89px on theirs, not the image's 84: their logo is an inline image in a block,
   and the line it sits on adds the font's descender underneath — 4.39px, measured
   unrounded, at every width. Here it is a margin, so it cannot drift with the font.
   As an inline-block it sat on a second line box, measured 97px, and put the
   marks beneath it 8px low. */
.footer-logo { display: block; width: fit-content; }
.footer-logo img { display: block; width: max(100px, 9vw); height: auto; margin-bottom: 4.39px; }

/* Marks: their .social-icons — 32px above and below, 5px of padding and 1px of
   margin either side, 20px tall at the markup's widths (as in the banner). From
   960px the row steps in 5vw, level with the newsletter link and the legal
   lines; it did not, and sat 72px left of theirs. The targets are the ::before
   shared with the banner. */
.footer-social { display: flex; justify-content: flex-start; padding: 32px 0; }
.footer-social .icon {
  position: relative;
  display: flex; flex-direction: column; justify-content: center;
  padding: 0 5px; margin: 0 1px;
}
/* NO FILTER: their footer carries a separate orange set, used as is. */
.footer-social .icon img { display: block; height: 20px; }

/* Their newsletter heading, .form-description: Roboto Condensed 700, 14px on
   19px, white, 16px beneath. Here it is the link to their form. */
.footer-news { margin: 0 0 16px; }
.footer-news a {
  display: block;
  width: fit-content;
  font-family: var(--ft);
  font-weight: 700;
  font-size: 14px;
  line-height: 19px;
  color: #fff;
  text-decoration: none;
  /* 2px more target above and below, given back by the margin, so the words
     start at the top of their 19px line exactly where theirs do. */
  padding: 2px 0;
  margin: -2px 0;
}

/* ── the six columns ── */
/* 4rem above it at every width — their .menu's padding-top. */
.footer-menu { display: flex; flex-direction: column; margin-top: 64px; }
.footer-col { position: relative; }

/* Headings: Calibri 16px on 19px, 400, white, uppercase, 24px beneath — a 43px
   row. Links to the section, as theirs are. */
.footer-col h2 {
  margin: 0;
  font-family: var(--fb);
  font-size: 16px;
  font-weight: 400;
  line-height: 19px;
  text-transform: uppercase;
  letter-spacing: 0;
  color: #fff;
}
/* max-height 43px is theirs. Their "Case Studies" wraps to two lines in its
   84px column at 1024 AND at 1440, but the heading stays a 43px row, so that
   column's links start level with the other five. Uncapped, it grew to 62px
   and dropped its links 19px below the rest. */
.footer-col h2 a {
  position: relative;
  display: inline-block;
  padding-bottom: 24px;
  max-height: 43px;
  color: #fff;
  text-decoration: none;
}

/* THE HEADING HOVER is the same bar as the banner's: 2px of the brand orange,
   15px up from the bottom of the heading, scaling out over 0.2s ease. It is as
   wide as the heading — their computed width is the heading's own, not the
   column's — so it sits under the word. The column links themselves have NO
   hover on their site, and have none here. */
.footer-col h2 a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 15px;
  width: 100%;
  height: 2px;
  background: var(--orange);
  transform: scaleX(0);
  transition: transform 0.2s ease;
}
.footer-col h2 a:focus-visible::after { transform: scaleX(1); }
@media (hover: hover) {
  .footer-col h2 a:hover::after { transform: scaleX(1); }
}

/* ── the accordion toggle: their .cross ──
   A 15×15 plus in two 2px orange bars at the right of each heading row.
   Opening spins the first bar from 90° to 450° over 0.3s linear and the second
   from 0° to 270° over 0.3s ease — different durations and easings, so it
   tumbles on its way to a minus rather than simply turning.

   The button is 44×44 so it can be pressed; it is centred on the spot their
   15px box occupies, so what is drawn sits exactly where theirs does. */
.footer-cross {
  position: absolute;
  top: -14.5px;
  right: -14.5px;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.footer-cross::before,
.footer-cross::after {
  content: '';
  position: absolute;
  top: 14.5px;
  left: 50%;
  width: 2px;
  height: 15px;
  background: var(--orange);
}
.footer-cross::before { transform: rotate(90deg); transition: transform 0.3s linear; }
.footer-cross::after  { transform: rotate(0deg);  transition: transform 0.3s ease; }
.footer-cross.clicked::before { transform: rotate(450deg); }
.footer-cross.clicked::after  { transform: rotate(270deg); }

/* Their column slides open with jQuery's slideToggle("medium") — 400ms. The
   same movement without measuring heights in script: a one-row grid going from
   0fr to 1fr. The last child's margin gives their 24px beneath a column, and
   because it is inside the clipped box it disappears with it. */
.footer-sub { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.4s ease; }
.footer-sub.is-open { grid-template-rows: 1fr; }
.footer-sub-in { min-height: 0; overflow: hidden; }
.footer-sub-in > :last-child { margin-bottom: 24px; }
html:not(.has-js) .footer-sub { grid-template-rows: 1fr; }
html:not(.has-js) .footer-cross { display: none; }

/* Column links: Calibri 14px on 18px, #C4C4C4, with half an em — 7px — above
   and below each: a 32px pitch. All 14px sat underneath before, which kept the
   pitch and put every link 7px higher than theirs. The anchors are inline, as theirs are,
   with 3px of padding above and below: padding on an inline box widens what a
   tap hits and leaves the line alone, so each is a 24px target that moves
   nothing. As inline-blocks with the padding cancelled by margin they nudged
   each line box, and the contact column finished a pixel short of theirs. */
.footer-sub ul { list-style: none; margin: 0; padding: 0; }
.footer-sub li { line-height: 18px; padding: 7px 0; color: var(--on-dark-muted); }
.footer-sub a {
  display: inline;
  padding: 3px 0;
  color: var(--on-dark-muted);
  text-decoration: none;
}
.footer address { font-style: normal; }
/* Contact spacing, measured unrounded: an empty line after the address and after
   the email, and two before Feedback. Their empty line is a line box of 18.39px,
   not the 18px of the text lines around it, so the gaps are 18.39 and 36.78.
   At 18 and 37 Tel and Feedback each landed a pixel above theirs. */
.footer-contact li + li { margin-top: 18.39px; }
.footer-contact .footer-feedback { margin-top: 36.78px; }

/* ── bottom bar ──
   Theirs: Privacy Policy, Terms & Conditions and the copyright stacked, 16px
   lines at a 32px pitch, 16px down from the columns and 32px up from the foot.
   Calibri 14px, white at 53% opacity — which measures 3.9:1 on the charcoal and
   falls under the 4.5:1 AA asks of 14px text. It is 62% here (4.69:1): the same
   quiet grey to the eye, readable to everyone. No divider line — theirs has
   none. */
.footer-bottom.pad { padding-top: 16px; padding-right: max(1.25rem, 13vw); }
.footer-legal { display: flex; flex-direction: column; gap: 16px; }
.footer-legal a,
.footer-legal span {
  font-family: var(--fb);
  font-size: 14px;
  line-height: 16px;
  color: rgba(255, 255, 255, 0.62);
  text-decoration: none;
}
.footer-legal a { display: inline-block; width: fit-content; padding: 4px 0; margin: -4px 0; }

/* ── from 960px: one row ──
   HOW THEIR ROW DIVIDES, MEASURED RATHER THAN GUESSED. It is not a percentage.
   Both halves are ordinary flex items that want more room than the row has —
   their brand block wants 506.1px plus 5vw (their newsletter form's natural
   width, its 5vw step and 64px of padding), and their six columns want 1005.7px
   laid out on one line — so the browser shrinks each in proportion to what it
   wanted. That comes to 286.6px for the brand block at 960, 304.2 at 1024,
   376.1 at 1280, 422.1 at 1440 and 565.2 at 1920. The 37.5% this used agreed
   at 1440 and was 6px out at 1024.
   This page has no form, so left to itself the brand block would want far less
   and the columns would start somewhere else at every width. Both bases are
   therefore theirs, written in, and the same shrinking lands on the same
   pixels. min-width: 0 lets the block go as narrow as theirs does — at 960 the
   newsletter link wraps in the 175px it is left, as their heading does.
   Each column is at most 12% of the row, so long names wrap inside it; the
   newsletter link, the marks and the legal stack step in 5vw. */
@media (min-width: 60em) {
  .footer-in.pad { flex-direction: row; align-items: flex-start; }
  /* From about 1610px up it is their newsletter form, not the columns, that is
     the tallest thing in the row: the logo, its 4.39px, 84px of marks, the 35px
     heading and a 298.55px form. min-height holds that, so the legal lines sit
     where theirs do — 550px down at 1920, not 478. Below that width the columns
     are taller and it has no effect. */
  .footer-brand { flex: 0 1 calc(506.1px + 5vw); min-width: 0; min-height: calc(max(100px, 9vw) * 174 / 267 + 421.94px); padding-right: 64px; }
  .footer-social { padding-left: 5vw; }
  .footer-news { padding-left: 5vw; }
  .footer-menu { flex: 1 1 1005.7px; min-width: 0; flex-direction: row; justify-content: space-between; }
  .footer-col { max-width: 12%; }
  .footer-cross { display: none; }
  .footer-sub, .footer-sub.is-open { grid-template-rows: 1fr; transition: none; }
  .footer-legal { padding-left: 5vw; }
}

/* ── the account page ────────────────────────────────────────────────────
   mjmda.eu has no account page to copy, so this one is built from the parts it
   does have: their type, their square buttons, their rules and their orange.
   One column at a readable width; controls are 16px so a phone does not zoom
   into them when they take focus, and 44px tall so a thumb can hit them. */
.account { padding-top: clamp(3rem, 7vw, 5rem); padding-bottom: clamp(3rem, 7vw, 5rem); }
.account-in { max-width: 34rem; }
/* "Your MJMDA account" and the way home, on one line; the button drops under the
   words only where the line is too narrow for both. */
.account-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem 1.5rem; margin-bottom: 1rem; }
.account-head .eyebrow { margin: 0; }
.account h1 { font-size: clamp(2rem, 5vw, 2.75rem); margin: 0 0 0.75rem; }
.account h1:focus { outline: none; }
.account h2 { font-size: 22px; margin: 2rem 0 0.75rem; }
.account .lede { margin: 0 0 1.5rem; }

.account-form { display: grid; gap: 1.1rem; margin: 0 0 1.5rem; }
.field { display: grid; gap: 0.35rem; }
.field label { font-size: 14px; font-weight: 700; color: var(--dark-grey); }
.field input {
  width: 100%;
  min-height: 44px;
  padding: 0.65rem 0.8rem;
  font: inherit;
  font-size: 16px;
  color: var(--dark-grey);
  background: #fff;
  border: 1px solid #8A8A87;       /* 3.5:1 on white — a control's edge must be seen */
  border-radius: 0;                /* square, like every edge on their site */
}
.field input:focus-visible { outline: 3px solid var(--orange-fill); outline-offset: 1px; border-color: var(--orange-fill); }
/* A list is a control like a box: the same edge, height and type, with the site's own arrow
   in place of each browser's. */
.field select {
  width: 100%;
  min-height: 44px;
  padding: 0.65rem 2.2rem 0.65rem 0.8rem;
  font: inherit;
  font-size: 16px;
  color: var(--dark-grey);
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23464743' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 0.8rem center;
  border: 1px solid #8A8A87;
  border-radius: 0;
  appearance: none;
}
.field select:focus-visible { outline: 3px solid var(--orange-fill); outline-offset: 1px; border-color: var(--orange-fill); }
.field-hint { margin: 0; font-size: 14px; color: var(--mid-grey); }
/* The star on a field that must be filled in, as on the Profiler. */
.req { color: var(--error); font-weight: 700; }
.optional { font-weight: 400; color: var(--mid-grey); }
/* A new account's first password: the details above, then this, then the password. */
#newpw-details { display: grid; gap: 1.1rem; }
#newpw-details[hidden] { display: none; }
#newpw-details-slot { display: grid; gap: 1.1rem; }
#details-who, #details-more { display: grid; gap: 1.1rem; }
.newpw-part { font-size: 22px; margin: 1rem 0 0; }

/* THE NAME, in its parts, with the title beside them: one row where there is room, the title
   narrow; two to a row on a phone, the title still first. */
.name-group { grid-template-columns: 1fr 1fr; }
@media (min-width: 46rem) {
  .account .name-group { grid-template-columns: 7.5rem 1fr 1fr 1fr; }
}
.name-group > .field-hint { grid-column: 1 / -1; }

/* A TELEPHONE: the country's code and the number, side by side. The code's list is wide
   because it names the country; on a phone the two stack. */
.phone-field { margin: 0; padding: 0; border: 0; min-width: 0; }
.phone-field > legend { padding: 0; margin-bottom: 0.35rem; font-size: 14px; font-weight: 700; color: var(--dark-grey); }
.phone-parts { display: grid; gap: 0.6rem 0.75rem; }
.phone-field .phone-parts label { font-weight: 400; color: var(--mid-grey); }
@media (min-width: 34rem) {
  .phone-parts { grid-template-columns: minmax(12rem, 16rem) 1fr; }
}
.account-group > .field-wide { grid-column: 1 / -1; }

/* The honeypot: present for a script that fills in every field, absent for a
   person — off-screen rather than display:none, which some scripts check for. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Turnstile draws a 65px-tall frame; holding the space stops the button below
   jumping when it arrives. */
.captcha { min-height: 65px; }

.notice { margin: 0; padding: 0.75rem 1rem; border-left: 3px solid var(--orange); background: #F5F5F5; color: var(--dark-grey); }
.notice-error { border-left-color: #A4262C; background: #FBEDEE; color: #7A1C21; }

.account-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.5rem; }
.linkish {
  min-height: 44px;
  padding: 0.5rem 0;
  font: inherit;
  color: var(--orange-text);
  background: none;
  border: 0;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.account-note { font-size: 14px; color: var(--mid-grey); }
/* The dashboard's parts, each under its own rule. */
.account-part { margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--light-grey); }
.account-part > h2 { margin-top: 0; }
/* The rest of the record — address, other contacts, identity, company — grouped so a long
   form reads as four short ones. Two fields to a row where the screen allows it. */
.account-group {
  margin: 0; padding: 1rem 1rem 1.25rem; border: 1px solid var(--light-grey);
  display: grid; gap: 1.1rem;
}
.account-group legend { padding: 0 0.5rem; font-weight: 700; color: var(--dark-grey); }
.account-group .field-hint { margin: 0; }
@media (min-width: 34rem) {
  .account-group { grid-template-columns: 1fr 1fr; }
  .account-group > .field-hint, .account-group > p { grid-column: 1 / -1; }
}

/* The sign-in address, shown in the form but not editable there. */
.account-form input[readonly] { background: var(--off-white); color: var(--mid-grey); }
.account-alt { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--light-grey); }
.account-alt p { margin: 0 0 0.75rem; }

/* An info card beside sign-in, closed until asked for: most visitors never need
   it, the few with an old Profiler account need it before anything else. A
   native <details>, so it opens from the keyboard and with scripts off. */
.info-card { margin: 1.5rem 0 0; border: 1px solid var(--light-grey); border-left: 3px solid var(--orange); background: #F5F5F5; }
.info-card > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  min-height: 44px; padding: 0.625rem 1rem; cursor: pointer; list-style: none;
  font-weight: bold; color: var(--dark-grey);
}
.info-card > summary::-webkit-details-marker { display: none; }
.info-card > summary::after {
  content: ""; flex: none; width: 0.5rem; height: 0.5rem; margin-top: -0.25rem;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform 0.15s ease;
}
.info-card[open] > summary::after { transform: rotate(-135deg); margin-top: 0.25rem; }
.info-card > summary:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.info-card-body { padding: 0 1rem 1rem; }
.info-card-body p { margin: 0 0 0.75rem; }
@media (prefers-reduced-motion: reduce) { .info-card > summary::after { transition: none; } }

/* The quiet button: their outlined shape on white, in charcoal. */
.btn-quiet { background: transparent; color: var(--dark-grey); border: 2px solid var(--dark-grey); }

.subs { list-style: none; margin: 0 0 1rem; padding: 0; border-top: 1px solid var(--light-grey); }
.subs li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--light-grey);
}
.subs .ref { font-family: var(--ft); font-size: 14px; letter-spacing: 0.04em; color: var(--mid-grey); }

.danger { margin-top: 2.5rem; padding-top: 1rem; border-top: 1px solid var(--light-grey); }
.danger summary { display: flex; align-items: center; min-height: 44px; font-weight: 700; cursor: pointer; }

/* ── 404 ─────────────────────────────────────────────────────────────── */
.lost { padding-top: clamp(3rem, 8vw, 6rem); padding-bottom: clamp(3rem, 8vw, 6rem); }
.lost h1 { font-size: clamp(2rem, 5vw, 2.75rem); }
.lost p { max-width: 52ch; }

/* The privacy notice: one readable column, each part under its own rule, in
   their type and their greys. */
.legal { padding-top: clamp(3rem, 7vw, 5rem); padding-bottom: clamp(3rem, 7vw, 5rem); }
.legal-in { max-width: 44rem; }
.legal h1 { font-size: clamp(2rem, 5vw, 2.75rem); margin: 0 0 0.75rem; }
.legal h2 { font-size: 22px; margin: 2.5rem 0 0.75rem; padding-top: 1.5rem; border-top: 1px solid var(--light-grey); }
.legal h3 { font-size: 17px; margin: 1.5rem 0 0.5rem; }
.legal p, .legal li { max-width: 68ch; }
.legal ul { margin: 0 0 1rem; padding-left: 1.25rem; }
.legal li + li { margin-top: 0.4rem; }
.legal-date { font-size: 14px; color: var(--mid-grey); }
.legal-kv { display: grid; grid-template-columns: max-content 1fr; gap: 0.5rem 1.5rem; margin: 0 0 1rem; }
.legal-kv dt { font-weight: 700; color: var(--dark-grey); }
.legal-kv dd { margin: 0; }
.legal-home { margin-top: 2.5rem; }
@media (max-width: 30em) {
  .legal-kv { grid-template-columns: 1fr; gap: 0.15rem; }
  .legal-kv dd { margin-bottom: 0.75rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* The quiet alternative beside the strip's button is still a link people press. */
.strip-alt { display: inline-flex; align-items: center; min-height: 44px; }

/* ══ THE PROFILER ═══════════════════════════════════════════════════════
   Stage 14. A long form on somebody else's phone, which is the condition it is
   actually used in: every control is at least 44px, every input is 16px so that
   iOS does not zoom the page when it is focused, and the step rail moves from a
   column beside the form to a row above it under 60rem.

   The cards are labels wrapping a real radio or checkbox. The input itself is
   not display:none — a hidden input cannot be focused, and the focus ring is how
   a keyboard user knows where they are. It is taken out of the flow instead, the
   label carries the checked state through :has(), and a browser without :has()
   still gets the tick. */
.pf-main { padding-top: clamp(2rem, 5vw, 3.5rem); padding-bottom: clamp(3rem, 8vw, 5rem); }
.pf-shell { max-width: var(--shell-max); margin: 0 auto; }
/* ONE COLUMN THAT MAY BE NARROWER THAN ITS CONTENTS. A bare grid column is
   'auto', which is never narrower than the widest thing in it — and on a phone
   that is the row of eight step numbers (389.5px). At a real 375px the whole step
   was wider than the screen and the page scrolled sideways by 45px; the row is
   meant to scroll inside itself instead. Measured 14 September 2026 (earlier
   checks ran in a pane that stretched "375" to 420, where 390 fits). */
.pf { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 3rem); }
@media (min-width: 60rem) { .pf { grid-template-columns: 15rem minmax(0, 1fr); align-items: start; } }

/* ── the rail ─────────────────────────────────────────────────────────── */
.pf-rail { position: sticky; top: 1rem; }
.pf-rail-list { list-style: none; margin: 0; padding: 0; display: flex; gap: 0.25rem; overflow-x: auto; }
@media (min-width: 60rem) { .pf-rail-list { flex-direction: column; overflow: visible; } }
.pf-rail-item {
  display: flex; align-items: center; gap: 0.6rem;
  width: 100%; min-height: 44px; padding: 0.4rem 0.6rem;
  font: inherit; text-align: left; color: var(--mid-grey);
  background: none; border: 0; cursor: pointer; white-space: nowrap;
}
/* Positioned, so a label clipped on a phone (below) is placed inside its own
   button — which sits inside the row that scrolls — and not against the sticky
   rail. Against the rail, the eighth label escaped the row's clipping at 383px
   and made the page 10px wider than a 375px screen (measured 14 September 2026). */
.pf-rail-item { position: relative; }
.pf-rail-item:hover { background: var(--off-white); }
.pf-rail-num {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--ft); font-size: 13px; font-weight: 700;
  background: var(--light-grey); color: var(--dark-grey);
}
.pf-rail-item.is-done .pf-rail-num,
.pf-rail-item.is-here .pf-rail-num { background: var(--orange-fill); color: #fff; }
.pf-rail-item.is-here { color: var(--brand-dark); font-weight: 700; }
.pf-rail-label { font-size: 14px; }
/* CLIPPED, NOT display:none. A label that is display:none is gone from the
   accessibility tree as well as the page, which left every rail button on a
   phone announcing itself as a bare number. */
@media (max-width: 59.99rem) {
  .pf-rail-label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .pf-rail-item { width: auto; }

  /* PINNED, SO IT NEEDS A GROUND. Above the step on a phone or tablet the rail
     stays at the top while the step scrolls, and with no background the
     questions scrolled up THROUGH it — the numbers sat on top of the question
     text (seen 14 September 2026). It is now white and above the step, and
     anything scrolled or focused into view stops below it rather than behind. */
  .pf-rail {
    top: 0; z-index: 5; padding: 0.5rem 0;
    background: var(--white); box-shadow: 0 1px 0 var(--light-grey);
  }
  .pf :is(.pf-q, .pf-head, .pf-banner, input, select, textarea) { scroll-margin-top: 5rem; }
}

/* The way back to this site's home (page-profiler.js). Under the steps beside
   the form; where the steps become a row across the top, a copy sits under that
   row instead, so neither screen carries two. */
.pf-home { justify-content: center; }
.pf-home-rail { width: 100%; margin-top: 1.25rem; }
.pf-home-top { justify-self: start; }
@media (max-width: 59.99rem) { .pf-home-rail { display: none; } }
@media (min-width: 60rem) { .pf-home-top { display: none; } }

/* ── the step ─────────────────────────────────────────────────────────── */
.pf-form { min-width: 0; }
.pf-head { margin: 0 0 1.75rem; }
.pf-title { font-size: clamp(1.75rem, 4vw, 2.5rem); line-height: var(--lh-tight); margin: 0.35rem 0 0.6rem; }
.pf-title:focus { outline: none; }
.pf-form .lede { margin: 0; max-width: var(--measure); }
.pf-qs { display: grid; gap: 2.25rem; }

.pf-q { margin: 0; padding: 0; border: 0; min-width: 0; }
.pf-q-label, .pf-field label, .pf-budget > label {
  display: block; padding: 0;
  font-family: var(--ft); font-size: 18px; font-weight: 700; color: var(--brand-dark);
}
/* The required-answer star: a mark, not a warning, in the error red. */
.pf-req { color: var(--error); font-weight: 700; }
.pf-req-key { margin: 0.6rem 0 0; font-size: 14px; color: var(--mid-grey); }
.pf-hint { margin: 0.3rem 0 0; font-size: 14px; color: var(--mid-grey); max-width: var(--measure); }
.pf-group {
  margin: 1.25rem 0 0.5rem; font-family: var(--ft); font-size: 13px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--mid-grey);
}
.pf-note {
  margin: 0.75rem 0 0; padding: 0.9rem 1rem; font-size: 15px;
  background: var(--info-bg); color: var(--info-ink); border-left: 3px solid var(--info);
}
.pf-note-wide { margin-top: 2rem; max-width: var(--measure); }
.pf-note p { margin: 0; }

/* ── choices ──────────────────────────────────────────────────────────── */
.pf-cards { display: grid; gap: 0.6rem; margin-top: 0.9rem; }
@media (min-width: 40rem) { .pf-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 75rem) { .pf-cards-tight { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.pf-card {
  position: relative; display: flex; align-items: flex-start; gap: 0.7rem;
  min-height: 44px; padding: 0.85rem 1rem;
  background: #fff; border: 1px solid var(--light-grey); cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.pf-card:hover { border-color: var(--mid-grey); }
.pf-card-input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.pf-card-tick {
  flex: 0 0 auto; width: 20px; height: 20px; margin-top: 1px;
  border: 1px solid #8A8A87; background: #fff;
}
.pf-card-input[type="radio"] + .pf-card-tick { border-radius: 50%; }
.pf-card-body { display: grid; gap: 0.15rem; min-width: 0; }
.pf-card-name { font-weight: 700; color: var(--brand-dark); font-size: 15px; }
.pf-card-desc { font-size: 14px; color: var(--mid-grey); line-height: 1.45; }

.pf-card:has(.pf-card-input:checked) { border-color: var(--orange-fill); background: #FDF6F1; }
.pf-card:has(.pf-card-input:checked) .pf-card-tick { background: var(--orange-fill); border-color: var(--orange-fill); }
/* The tick itself, drawn rather than fetched: two strokes rotated. */
.pf-card:has(.pf-card-input:checked) .pf-card-tick::after {
  content: ""; display: block; width: 5px; height: 10px; margin: 2px auto 0;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.pf-card:has(.pf-card-input:focus-visible) { outline: 3px solid var(--orange-fill); outline-offset: 2px; }
.pf-card-whole { grid-column: 1 / -1; }

/* A choice with a photograph. The picture spans the top of the card at 4:3 —
   the crop build-profiler-images.mjs cuts — and the tick and the words sit
   under it as on every other card. The image is last in the markup and first
   on screen, so the input keeps its tick as its neighbour. */
.pf-card-pic { flex-wrap: wrap; padding: 0 0 0.85rem; overflow: hidden; align-content: flex-start; }
.pf-card-pic .pf-card-img {
  order: -1; flex: 1 0 100%; display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover; margin: 0 0 0.75rem; background: var(--off-white);
}
.pf-card-pic .pf-card-tick { margin-left: 1rem; }
.pf-card-pic .pf-card-body { flex: 1 1 0; padding-right: 1rem; }
/* The frame a photograph will fill, while MJM|DA's are on hold — drawn on the
   preview only (page-profiler.js). Same box, same 4:3, so nothing moves when the
   picture arrives. */
.pf-card-img-todo {
  display: flex; align-items: center; justify-content: center;
  border-bottom: 1px dashed #B9B8B4;
}
.pf-card-img-todo span {
  font-family: var(--ft); font-size: 12px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--mid-grey);
}
/* ── files sent with a profile (Matthew, 14 September 2026) ─────────────
   The browser's own file control, dressed as the form's quiet button: it is
   keyboard-reachable, announces itself, and opens the phone's camera roll or
   files as the phone prefers — none of which a hand-made drop zone does. */
.pf-files { display: grid; gap: 0.4rem; margin-top: 0.9rem; max-width: 34rem; }
.pf-files-label { font-weight: 700; color: var(--dark-grey); }
.pf-file-input { width: 100%; min-height: 44px; font: inherit; font-size: 16px; color: var(--dark-grey); }
.pf-file-input::file-selector-button {
  min-height: 44px; margin-right: 0.8rem; padding: 0 1.1rem;
  font: inherit; font-size: 15px; font-weight: 700; color: var(--dark-grey);
  background: #fff; border: 1px solid #8A8A87; border-radius: 0; cursor: pointer;
}
.pf-file-input:focus-visible { outline: 3px solid var(--orange-fill); outline-offset: 2px; }
.pf-file-list { list-style: none; margin: 0.3rem 0 0; padding: 0; border-top: 1px solid var(--light-grey); }
.pf-file {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.8rem;
  padding: 0.2rem 0; border-bottom: 1px solid var(--light-grey); font-size: 15px;
}
.pf-file-name { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; color: var(--dark-grey); }
.pf-file-size { font-family: var(--ft); font-size: 13px; color: var(--mid-grey); font-variant-numeric: tabular-nums; }
.pf-files-said { margin: 0 0 1rem; max-width: var(--measure); }
/* What is kept and for how long, where somebody sends a profile (Stage 15). */
.pf-kept { max-width: var(--measure); font-size: 14px; color: var(--mid-grey); }
.pf-kept a { color: var(--info-ink); text-underline-offset: 3px; }
.sub-files { margin: 0.2rem 0 0; font-size: 15px; color: var(--mid-grey); overflow-wrap: anywhere; }

/* ── fields ───────────────────────────────────────────────────────────── */
.pf-field { display: grid; gap: 0.4rem; margin-top: 0.9rem; max-width: 34rem; }
.pf-input {
  width: 100%; min-height: 44px; padding: 0.65rem 0.8rem;
  font: inherit; font-size: 16px; color: var(--dark-grey);
  background: #fff; border: 1px solid #8A8A87; border-radius: 0;
}
textarea.pf-input { min-height: 6rem; line-height: 1.55; resize: vertical; }
.pf-input:focus-visible { outline: 3px solid var(--orange-fill); outline-offset: 1px; border-color: var(--orange-fill); }

/* Centred on the words, not the top of the row: the label is 44px tall with
   its text centred, so a box pinned to the top sat 11px above the sentence it
   belongs to (Jan, 14 September 2026). */
.pf-tick { display: flex; align-items: center; gap: 0.7rem; margin-top: 0.9rem; }
.pf-tick-input { width: 22px; height: 22px; margin: 0; flex: 0 0 auto; accent-color: var(--orange-fill); }
/* The words are the target, not only the 22px box: measured at 375px on
   14 September 2026, the skip row looked 53px tall and took a tap on 24px of it. */
.pf-tick label { display: flex; align-items: center; min-height: 44px; font-size: 15px; color: var(--dark-grey); max-width: var(--measure); }
.pf-skip {
  display: flex; align-items: center; gap: 0.7rem;
  margin: 0 0 1.5rem; padding: 0.25rem 1rem; background: var(--off-white);
}
.pf-skip label { flex: 1 1 auto; display: flex; align-items: center; min-height: 44px; padding: 0.4rem 0; font-size: 15px; font-weight: 700; color: var(--dark-grey); }

/* ── the budget slider ────────────────────────────────────────────────── */
.pf-budget { margin-top: 0.9rem; max-width: 34rem; }
.pf-budget-figure {
  display: block; margin: 0.5rem 0 0.25rem;
  font-family: var(--ft); font-size: clamp(2rem, 6vw, 2.75rem); font-weight: 700;
  line-height: 1; color: var(--orange-text); font-variant-numeric: tabular-nums;
}
.pf-range { width: 100%; min-height: 44px; accent-color: var(--orange-fill); }
.pf-budget-scale {
  display: flex; justify-content: space-between;
  font-family: var(--ft); font-size: 13px; color: var(--mid-grey);
}

/* ── saying what is wrong ─────────────────────────────────────────────── */
.pf-banner {
  margin: 0 0 1.5rem; padding: 0.9rem 1rem;
  background: var(--error-bg); color: var(--error-ink);
  border-left: 3px solid var(--error); font-size: 15px;
}
.pf-qerr { margin: 0.5rem 0 0; font-size: 14px; font-weight: 700; color: var(--error-ink); }
.pf-q.is-bad .pf-card, .pf-q.is-bad .pf-input { border-color: var(--error); }

/* ── moving on ────────────────────────────────────────────────────────── */
.pf-nav {
  display: flex; flex-wrap: wrap-reverse; gap: 0.75rem; align-items: center;
  margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--light-grey);
}
.pf-booting, .pf-noscript { max-width: var(--measure); }
.pf-noscript { padding: 1.5rem 0; }

/* A browser without :has() never draws the fill, so the tick is the state. */
@supports not selector(:has(*)) {
  .pf-card-input:checked ~ .pf-card-tick { background: var(--orange-fill); border-color: var(--orange-fill); }
  .pf-card-input:focus-visible ~ .pf-card-tick { outline: 3px solid var(--orange-fill); outline-offset: 2px; }
}

/* Coming back to a half-answered form, and the way out of it. Set apart from
   the questions because it is about the form rather than part of it. */
.pf-resumed {
  margin: 0 0 1.5rem; padding: 0.9rem 1rem;
  background: var(--info-bg); color: var(--info-ink);
  border-left: 3px solid var(--info); font-size: 15px;
}
.pf-resumed p { margin: 0 0 0.4rem; max-width: var(--measure); }

/* A button that reads as a link: it is a quiet way out of a form, not a second
   thing to press beside Next. It is still a button, because it does something
   to this page rather than going anywhere. */
.pf-linkish {
  display: inline-flex; align-items: center; min-height: 44px;
  padding: 0; font: inherit; font-size: 15px; font-weight: 700;
  color: var(--info-ink); background: none; border: 0;
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
.pf-linkish:hover { color: var(--brand-dark); }
.pf-pdf-said { margin-top: 0.9rem; max-width: var(--measure); }

/* How much room a long answer has left — shown only near the limit. */
.pf-count { margin: 0; font-size: 14px; color: var(--mid-grey); }

/* The way to clear a finished profile off a shared computer: quiet, below
   everything, because most people will never need it. */
.pf-clear { margin-top: 1.5rem; max-width: var(--measure); font-size: 15px; color: var(--mid-grey); }
.pf-clear p { margin: 0; }

/* ── sending, and after (Stage 15) ────────────────────────────────────── */
.pf-send { margin-top: 2rem; padding: 1.25rem; background: var(--off-white); max-width: var(--measure); }
.pf-send h2, .pf-account h2 { margin: 0 0 0.4rem; font-size: 20px; color: var(--brand-dark); }
.pf-send p { margin: 0 0 0.9rem; }
.pf-ref { font-family: var(--ft); letter-spacing: 0.06em; color: var(--brand-dark); }
.pf-account { margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--light-grey); max-width: var(--measure); }
.pf-account p { margin: 0; }
.pf-account-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 1rem 0 0.5rem; }
.pf-after { margin-top: 2rem; font-weight: 700; }
/* Who is signed in, or that signing in first saves typing — one quiet line. */
.pf-who { margin: 0.75rem 0 0; max-width: var(--measure); font-size: 15px; color: var(--mid-grey); }
.pf-who a { font-weight: 700; color: var(--orange-text); text-underline-offset: 3px; }
.pf-send .pf-who { margin: 0 0 0.9rem; }
.pf-after a { color: var(--orange-text); text-underline-offset: 3px; }

/* A profile in the account, with its answers behind a disclosure. */
.subs li.sub { display: block; }
.sub-top { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.25rem 1rem; }
.sub-what { margin: 0.2rem 0 0; font-size: 15px; color: var(--mid-grey); }
.sub-answers { margin-top: 0.5rem; }
.sub-answers summary {
  display: flex; align-items: center; min-height: 44px;
  font-weight: 700; color: var(--orange-text); cursor: pointer;
}
.sub-answers h3 {
  margin: 1rem 0 0.3rem; font-family: var(--ft); font-size: 13px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--mid-grey);
}
.sub-answers dl { display: grid; gap: 0.1rem 1rem; margin: 0; }
@media (min-width: 40rem) { .sub-answers dl { grid-template-columns: 11rem minmax(0, 1fr); } }
.sub-answers dt { padding-top: 0.35rem; font-size: 14px; color: var(--mid-grey); }
.sub-answers dd { margin: 0; padding-bottom: 0.35rem; white-space: pre-wrap; color: var(--brand-dark); }
@media (min-width: 40rem) { .sub-answers dt, .sub-answers dd { padding: 0.35rem 0; } }
.sub-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; margin-top: 0.75rem; }
.sub-said { font-size: 14px; color: var(--mid-grey); }

/* ── reading back what you said ───────────────────────────────────────── */
.pf-review { margin: 1.75rem 0 0; }
.pf-review-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin: 1.75rem 0 0.5rem; padding-bottom: 0.35rem; border-bottom: 1px solid var(--light-grey);
}
.pf-review-step {
  margin: 0; font-family: var(--ft); font-size: 13px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--mid-grey);
}
.pf-review-head .pf-linkish { min-height: 32px; font-size: 14px; color: var(--orange-text); }
.pf-review-list { display: grid; margin: 0; gap: 0.15rem 1.5rem; }
@media (min-width: 40rem) { .pf-review-list { grid-template-columns: 14rem minmax(0, 1fr); } }
.pf-review-list dt {
  font-size: 14px; font-weight: 700; color: var(--mid-grey); padding: 0.45rem 0 0;
}
.pf-review-list dd {
  margin: 0; padding: 0 0 0.45rem; font-size: 15px; color: var(--brand-dark);
  white-space: pre-wrap;      /* their own line breaks survive being read back */
}
@media (min-width: 40rem) { .pf-review-list dt { padding: 0.45rem 0; } .pf-review-list dd { padding: 0.45rem 0; } }
.pf-review-none { margin: 0.35rem 0 0; font-size: 15px; color: var(--mid-grey); }

/* A slider nobody has moved says so, in the size of a prompt rather than the
   size of a figure — a number that big reads as an answer already given. */
.pf-budget-figure.is-unsaid {
  font-size: clamp(1.1rem, 3vw, 1.35rem); color: var(--mid-grey); font-weight: 400;
}
