/* ===========================================================
   OnFinance, Components
=========================================================== */

/* ============ Site header ============ */
.site-header{
  position: sticky;
  inset-block-start: 0;
  z-index: 100;
  block-size: var(--header-h);
  display: flex;
  /* stretch, not centre. The container has to fill the bar's full height
     so the logo panel can be pinned to the very top of it and hang off
     the bottom. Nav and actions are re-centred inside the container. */
  align-items: stretch;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border-block-end: 1px solid var(--color-border);
  /* The panel deliberately escapes the bar. */
  overflow: visible;
}
.site-header .container{ display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); inline-size: 100%; }

/* Auto-hiding header, below the breakpoint where the nav collapses.
   js/main.js adds .is-tucked while the reader is scrolling down and
   removes it the moment they scroll up. The transform is the only
   thing that moves, so it stays on the compositor and does not
   reflow the page underneath.

   Gated to <1060px on purpose. Above that the full nav is showing and
   there is plenty of screen, so the header simply stays put and the
   class, if present, does nothing. */
@media (max-width: 1059.98px){
  .site-header{
    transition: transform var(--duration-base, 260ms) var(--ease-out-quart, cubic-bezier(0.22, 1, 0.36, 1));
    will-change: transform;
  }
  .site-header.is-tucked{ transform: translateY(-100%); }
}
/* Motion is the entire mechanism here, so reduced motion opts out
   completely rather than snapping the header in and out. */
@media (prefers-reduced-motion: reduce){
  .site-header{ transition: none; }
  .site-header.is-tucked{ transform: none; }
}

/* ---- The logo panel ----
   Themy's logo is a stacked lockup, mark above word above tagline, so
   inside a horizontal bar most of the height is spent stacking rather
   than on the artwork. At 56px in an 84px bar the mark was only ~38px
   and the tagline was unreadable.

   Rather than fatten the bar for every page and every scroll, the logo
   gets its own panel that is pinned to the top of the bar and hangs
   below it. The bar stays the height it was. This works here because
   every page on the site opens with a dark hero, so a light panel over
   it reads as deliberate.

   It retracts on scroll, see .is-scrolled below, which is what stops it
   fighting the auto-hiding header. */
/* The plain brand link. The same markup is reused in the dark mobile
   menu and the dark footer, so this base stays neutral. Everything that
   makes the header version a panel is scoped to .site-header below,
   because an unscoped version put a white box with a drop shadow on
   both of those dark surfaces. */
.brand{
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.65em; text-decoration: none; color: var(--color-text); flex: none;
}
.brand__logo{ display: block; block-size: 56px; inline-size: auto; flex: none; }

/* ---- Header only: the hanging panel ---- */
.site-header .brand{
  /* One knob for the logo height. The retracted padding below is derived
     from it, so the two can never drift apart. */
  --brand-logo-h: 88px;
  align-self: flex-start;          /* pin to the top of the bar, then overhang */
  position: relative; z-index: 2;
  padding: 14px 22px 16px;
  background: var(--surface);
  border: 1px solid var(--color-border);
  border-block-start: 0;
  border-start-start-radius: 0; border-start-end-radius: 0;
  border-end-start-radius: var(--radius-lg); border-end-end-radius: var(--radius-lg);
  box-shadow: 0 16px 30px -20px rgba(20, 24, 28, 0.5);
  transition: padding var(--duration-base, 260ms) var(--ease-out-quart, cubic-bezier(0.22,1,0.36,1)),
              box-shadow var(--duration-base, 260ms) var(--ease-out-quart, cubic-bezier(0.22,1,0.36,1)),
              background-color var(--duration-base, 260ms) var(--ease-out-quart, cubic-bezier(0.22,1,0.36,1)),
              border-color var(--duration-base, 260ms) var(--ease-out-quart, cubic-bezier(0.22,1,0.36,1));
}
.site-header .brand__logo{
  block-size: var(--brand-logo-h);
  transition: block-size var(--duration-base, 260ms) var(--ease-out-quart, cubic-bezier(0.22,1,0.36,1));
}

/* ---- Retracted state ----
   Once the reader has moved off the top of the page the panel folds back
   into the bar. Two reasons. It stops a large white block being dragged
   over the content for the whole scroll, and it means that by the time
   the auto-hide can fire at 140px the panel is already flush, so the
   header tucks away as one clean rectangle instead of leaving a strip
   of panel stranded on screen.

   The vertical padding is calculated rather than typed. The panel keeps
   align-self:flex-start from the expanded state, so a fixed padding left
   it shorter than the bar and pinned to the top, which sat the logo 13px
   above the centre line on a phone while the call button beside it was
   centred. Deriving the padding from the bar height makes the retracted
   panel exactly fill the bar, so the logo centres itself at any bar
   height or logo size, and padding animates where align-self would not. */
.site-header.is-scrolled .brand,
.site-header.is-tucked .brand{
  --brand-logo-h: 56px;
  padding-block: calc((var(--header-h) - var(--brand-logo-h)) / 2);
  padding-inline: 16px;
  box-shadow: none;
  background: transparent;
  border-color: transparent;
}

/* Reduced motion gets the flush panel permanently, not the overhang.
   The scroll handler in main.js is gated off entirely under reduced
   motion, so without this the panel would hang past the bar forever and
   sit over the hero on every page. A calm, ordinary header is the right
   answer here rather than a frozen half-state. */
@media (prefers-reduced-motion: reduce){
  .site-header .brand, .site-header .brand__logo{ transition: none; }
  .site-header .brand{
    --brand-logo-h: 56px;
    padding-block: calc((var(--header-h) - var(--brand-logo-h)) / 2);
    padding-inline: 16px;
    box-shadow: none; background: transparent; border-color: transparent;
  }
}

/* ---- Phones ----
   Sized so the panel is genuinely TALLER than the 84px bar. The first
   attempt used a 64px logo, which made a 90px panel that fitted inside
   the bar, so the overhang silently vanished on phones, which is
   exactly where the logo needed the most help. 76px plus 22px of
   padding gives a 98px panel that still hangs by about 14px, and the
   panel plus the call and menu buttons still clear a 360px screen. */
@media (max-width: 720px){
  .site-header .brand{ --brand-logo-h: 76px; padding: 10px 14px 12px; }
  .site-header.is-scrolled .brand,
  .site-header.is-tucked .brand{ --brand-logo-h: 46px; padding-inline: 10px; }
}
@media (max-width: 400px){
  .site-header .brand{ --brand-logo-h: 70px; padding: 9px 11px 11px; }
}

.nav-primary{ display: none; }
.nav-primary ul{ list-style: none; display: flex; align-items: center; gap: var(--space-md); margin: 0; padding: 0; }
/* inline-block, not inline, and the reason matters.
   The underline below is absolutely positioned against this link. An
   inline box does not establish a normal containing block for that, the
   browser derives one from the line-box fragments instead, and the
   underline collapsed to a 2px stub at the link's leading edge. Visually
   that meant the current-page indicator never drew, leaving only a stray
   red dot under the nav. inline-block gives the underline a real box to
   measure 100% against. */
.nav-primary a{ display: inline-block; text-decoration: none; font-weight: 600; font-size: var(--text-sm); color: var(--color-text); padding: 0.5em 0.1em; position: relative; }
/* scaleX(0) does not reliably collapse to nothing. At some widths the
   rounding leaves a 2px sliver painted at the transform origin, which
   showed up as a stray red dot under the nav. Fading it out as well means
   any residual sliver is invisible. */
.nav-primary a::after{
  content: ""; position: absolute; inset-inline: 0; block-size: 2px; inset-block-end: -2px;
  background: var(--brand-red-500); transform: scaleX(0); transform-origin: left; opacity: 0;
  transition: transform var(--duration-fast) var(--ease-out-quart), opacity var(--duration-fast) var(--ease-out-quart);
}
.nav-primary a:hover::after, .nav-primary a[aria-current="page"]::after{ transform: scaleX(1); opacity: 1; }
.nav-primary a[aria-current="page"]{ color: var(--brand-red-600); }

.header-actions{ display: flex; align-items: center; gap: var(--space-2xs); flex: none; }
.header-actions .btn--sm{ display: none; }
.call-chip{
  display: inline-flex; align-items: center; gap: 0.55em;
  font-weight: 700; font-size: var(--text-sm); text-decoration: none; color: var(--color-text);
  padding: 0.55em 0.9em; border-radius: var(--radius-full); border: 1px solid var(--color-border-strong);
  min-block-size: var(--tap-min); min-inline-size: var(--tap-min); justify-content: center;
  flex: none;
}
.call-chip svg{ inline-size: 1.1em; block-size: 1.1em; color: var(--brand-red-600); flex: none; }
.call-chip:hover{ background: var(--ink-050); }

/* Icon-only call chip below ~480px, the sticky mobile CTA dock already
   carries the full "Call now" label lower on the page at these widths,
   so the header chip only needs to be a compact, reachable tap target. */
@media (max-width: 480px){
  .call-chip span{ display: none; }
  .call-chip{ padding: 0.55em; }
  /* Logo sizing at this width is handled by the panel rules above.
     The old 44px override lived here and, sitting later in the file,
     silently beat them. */
}

.nav-toggle{
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: 44px; block-size: 44px; border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong); background: var(--surface);
}
.nav-toggle svg{ inline-size: 22px; block-size: 22px; }

/* Header row budget.
   Brand and header actions are both flex: none, so neither yields,
   whatever does not fit is pushed off the right edge rather than
   wrapping. The row has to earn each control back as width allows.

   Measured at the current type sizes: brand 215px, seven nav links
   397px of text, call chip 147px, pre-approval button 165px, plus
   the container and action gaps. That totals more than a 900px row
   can hold, which is why the nav now waits for 1060px and the
   button for 1280px, and why the nav gap tightens in between.
   Revisit these numbers if the wordmark size or the link count
   changes again, both have already broken this row once. */
@media (min-width: 1060px){
  .nav-primary{ display: block; }
  .nav-toggle{ display: none; }
}
@media (min-width: 1060px) and (max-width: 1279.98px){
  .nav-primary ul{ gap: var(--space-2xs); }
}
@media (min-width: 1280px) and (max-width: 1439.98px){
  .nav-primary ul{ gap: var(--space-sm); }
}
@media (min-width: 1280px){
  .header-actions .btn--sm{ display: inline-flex; }
}

/* Mobile menu (native <dialog>) */
/* ============ Mobile menu ============
   A full-screen takeover on the site's darkest surface, which is
   also its most confident one: the same ink and the same two
   colour fields as the hero. The old version was a white sheet
   with eleven identical text links, which told a visitor nothing
   about what OnFinance actually does and gave the four things
   they might want equal billing with the privacy policy.

   The four finance products now lead, at a size you can hit with
   a thumb without looking, each with a line saying what it is for.
   Everything else drops to a compact secondary grid. The phone
   number is the last thing above the fold on the way out, because
   for this business a call is the conversion.

   Motion here is deliberate and is the exception to the rule in
   motion.css. The visitor tapped a button and is looking straight
   at the result, so there is no window in which a half-finished
   state can be mistaken for a fault. It is also brief.
=========================================================== */

.menu{
  --menu-inset: var(--gutter);
  border: none; padding: 0; margin: 0; inset: 0;
  inline-size: 100%; max-inline-size: 100%;
  block-size: 100dvh; max-block-size: 100dvh;
  background: var(--ink-950);
  color: var(--color-text-on-dark);
  --color-text: var(--color-text-on-dark);
  --color-text-muted: var(--color-text-on-dark-muted);
  --color-border: rgba(245, 242, 237, 0.14);
  overflow: clip;
}

/* The hero's colour fields, so opening the menu feels like part of
   the same site rather than a system sheet dropped on top of it. */
.menu__field{
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(58% 46% at 88% 6%, color-mix(in srgb, var(--brand-red-600) 40%, transparent), transparent 70%),
    radial-gradient(50% 42% at 4% 96%, color-mix(in srgb, var(--brand-navy-500) 46%, transparent), transparent 72%),
    radial-gradient(34% 28% at 20% 28%, color-mix(in srgb, var(--sand-500) 12%, transparent), transparent 70%);
}

.menu__inner{
  position: relative; z-index: 1;
  block-size: 100%;
  display: flex; flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* ---- Head ---- */
.menu__head{
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--menu-inset) var(--space-2xs);
}
.menu__head .brand__logo{ block-size: 46px; }
.menu__head .brand{ min-block-size: var(--tap-min, 44px); padding-block: 0.2em; }

.menu__close{
  inline-size: 46px; block-size: 46px; flex: none;
  border-radius: 50%;
  border: 1px solid rgba(245, 242, 237, 0.22);
  background: rgba(245, 242, 237, 0.06);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background var(--tactile-duration) var(--ease-cut),
              border-color var(--tactile-duration) var(--ease-cut),
              transform var(--tactile-duration) var(--spring-tap);
}
.menu__close svg{ inline-size: 1.15rem; block-size: 1.15rem; }
.menu__close:hover{ background: rgba(245, 242, 237, 0.12); border-color: rgba(245, 242, 237, 0.4); }
.menu__close:active{ transform: scale(0.92); transition-duration: 60ms; }

/* The default focus ring is a browser blue box that has nothing to
   do with this palette, and on the old menu it was the loudest
   thing on the screen. */
.menu :focus-visible{
  outline: 2px solid var(--sand-500);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* ---- Trading status, reuses the site-wide adaptive slots ---- */
.menu__status{
  display: flex; align-items: center; gap: 0.6em;
  /* Its own air above and below. The vertical-budget squeeze that
     keeps the call CTA above the fold took this pill's breathing
     room with it, and it sat pressed against the brand tagline.
     The footer is pinned, so on a short phone this only adds a
     little scroll, never pushes the phone number away. */
  margin: var(--space-sm) var(--menu-inset);
  padding: 0.6em 0.9em;
  font-size: var(--text-xs);
  line-height: 1.35;
  border-radius: var(--radius-full);
  border: 1px solid rgba(245, 242, 237, 0.16);
  background: rgba(245, 242, 237, 0.05);
  color: var(--color-text-on-dark-muted);
}
.menu__status strong{ color: #fff; font-weight: 700; }
.menu__dot{
  inline-size: 8px; block-size: 8px; border-radius: 50%; flex: none;
  background: #4ADE80;
  box-shadow: 0 0 0 3px rgba(74, 222, 128, 0.18);
}
.menu__status--closed .menu__dot{
  background: var(--sand-500);
  box-shadow: 0 0 0 3px rgba(201, 162, 75, 0.18);
}

/* ---- Section labels ---- */
.menu__eyebrow{
  display: flex; align-items: center; gap: 0.7em;
  margin: 0 var(--menu-inset) var(--space-3xs, 0.25rem);
  font-size: var(--text-2xs, 0.7rem);
  font-weight: 700;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--sand-500);
}
.menu__eyebrow::before{
  content: ""; inline-size: 1.6em; block-size: 2px; flex: none;
  background: var(--brand-red-500);
}
.menu__list + .menu__eyebrow{ margin-block-start: var(--space-sm); }

.menu__nav{ padding-block-end: var(--space-sm); }

/* ---- The four products ---- */
.menu__list{ list-style: none; margin: 0; padding: 0; }

.menu__row{
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-xs);
  padding: 0.6em var(--menu-inset);
  text-decoration: none;
  color: var(--color-text-on-dark);
  border-block-start: 1px solid rgba(245, 242, 237, 0.1);
  position: relative;
  transition: background var(--tactile-duration) var(--ease-cut);
}
.menu__list--feature > li:last-child .menu__row{
  border-block-end: 1px solid rgba(245, 242, 237, 0.1);
}

/* A red edge marks the row under the thumb, and marks the page the
   visitor is already on. */
.menu__row::before{
  content: ""; position: absolute;
  inset-block: 0; inset-inline-start: 0;
  inline-size: 3px;
  background: var(--brand-red-500);
  transform: scaleY(0); transform-origin: 50% 50%;
  transition: transform 200ms var(--ease-cut);
}
.menu__row:hover, .menu__row:active{ background: rgba(245, 242, 237, 0.05); }
.menu__row:hover::before, .menu__row:active::before{ transform: scaleY(1); }
.menu__row[aria-current="page"]{ background: rgba(245, 242, 237, 0.05); }
.menu__row[aria-current="page"]::before{ transform: scaleY(1); }

.menu__icon{
  inline-size: 44px; block-size: 44px; flex: none;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--brand-red-500) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand-red-400) 34%, transparent);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--brand-red-400);
}
.menu__icon svg{ inline-size: 1.35rem; block-size: 1.35rem; }

.menu__label{
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-wrap: balance;
  color: #fff;
}
.menu__desc{
  display: block;
  margin-block-start: 0.15em;
  font-size: var(--text-xs);
  line-height: 1.35;
  color: var(--color-text-on-dark-muted);
}
.menu__arrow{
  inline-size: 1rem; block-size: 1rem; flex: none;
  color: rgba(245, 242, 237, 0.4);
  transition: transform 200ms var(--ease-cut), color 200ms var(--ease-cut);
}
.menu__row:hover .menu__arrow{ transform: translateX(4px); color: var(--brand-red-400); }

/* ---- Everything else, compact ---- */
.menu__list--plain{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  padding-inline: var(--menu-inset);
}
.menu__mini{
  padding: 0.78em 0;
  min-block-size: var(--tap-min, 44px);
  display: flex;
  align-items: center;
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  color: var(--color-text-on-dark-muted);
  border-block-start: 1px solid rgba(245, 242, 237, 0.1);
  transition: color var(--tactile-duration) var(--ease-cut);
}
.menu__mini:hover{ color: #fff; }
.menu__mini[aria-current="page"]{ color: var(--brand-red-400); }

/* ---- Foot ---- */
.menu__foot{
  margin-block-start: auto;
  padding: var(--space-sm) var(--menu-inset) calc(var(--space-sm) + env(safe-area-inset-bottom, 0px));
  border-block-start: 1px solid rgba(245, 242, 237, 0.14);
  background: rgba(11, 27, 46, 0.35);
  display: flex; flex-direction: column; gap: var(--space-xs);
}

/* The number is the point of the whole footer, so it is set as a
   figure rather than as a button label. Sized to hold the full
   number on one line at 320px. */
.menu__call{
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--space-xs);
  padding: 0.7em 0.9em;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(245, 242, 237, 0.18);
  background: rgba(245, 242, 237, 0.05);
  text-decoration: none;
  transition: background var(--tactile-duration) var(--ease-cut),
              border-color var(--tactile-duration) var(--ease-cut),
              transform var(--tactile-duration) var(--spring-tap);
}
.menu__call:hover{ background: rgba(245, 242, 237, 0.1); border-color: rgba(245, 242, 237, 0.34); }
.menu__call:active{ transform: scale(0.98); transition-duration: 60ms; }
.menu__call-icon{
  inline-size: 42px; block-size: 42px; flex: none;
  border-radius: 50%;
  background: var(--brand-red-500);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
}
.menu__call-icon svg{ inline-size: 1.15rem; block-size: 1.15rem; }
.menu__call-label{
  display: block;
  font-size: var(--text-2xs, 0.7rem);
  font-weight: 700;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--sand-500);
}
.menu__call-num{
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.05rem + 1.4vw, 1.6rem);
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.1;
  white-space: nowrap;
  color: #fff;
}

.menu__acts{ display: grid; grid-template-columns: 1.45fr 1fr; gap: var(--space-2xs); }
.menu__acts .btn{
  inline-size: 100%;
  padding-inline: 0.6em;
  font-size: var(--text-sm);
  white-space: nowrap;
}

.menu__fine{
  margin: 0;
  font-size: var(--text-2xs, 0.7rem);
  line-height: 1.5;
  color: rgba(245, 242, 237, 0.5);
  text-align: center;
}

/* A short phone gets the products and the call, and scrolls for the
   rest. A tall one shows the lot without scrolling. */
@media (min-height: 820px){
  .menu__row{ padding-block: 0.9em; }
}
@media (max-height: 640px){
  .menu__desc{ display: none; }
  .menu__row{ padding-block: 0.7em; }
  .menu__icon{ inline-size: 38px; block-size: 38px; }
}

/* ---- Opening ---- */
.menu::backdrop{
  background: rgba(10, 13, 16, 0.55);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}

@media (prefers-reduced-motion: no-preference){
  .menu[open]{ animation: menu-in 340ms var(--ease-cut); }
  @keyframes menu-in{
    from{ opacity: 0; transform: translateY(2.5%) scale(0.985); }
  }
  .menu[open]::backdrop{ animation: menu-backdrop 340ms var(--ease-cut); }
  @keyframes menu-backdrop{ from{ opacity: 0; } }

  /* backwards fill, not both. The row's resting state is the visible
     one, so the animation only ever borrows the offset state during
     its delay and hands the row back afterwards. If it never runs,
     the menu is simply there. Every entrance in the old motion layer
     used both, which is why an interrupted one left a hole. */
  .menu[open] .menu__stagger{
    animation: menu-row-in 360ms var(--ease-cut) backwards;
    animation-delay: calc(60ms + var(--i, 0) * 24ms);
  }
  @keyframes menu-row-in{
    from{ opacity: 0; transform: translateY(12px); }
  }
}


@media (min-width: 620px){
  .menu{ --menu-inset: max(var(--gutter), calc((100% - 580px) / 2)); }
}

/* On a short screen the call is the first thing to fall below the
   fold, which is the wrong thing to lose on a page whose job is to
   get someone to ring. Pinning the footer keeps it reachable at any
   height, and on a screen tall enough to fit everything this does
   nothing at all. */
.menu__foot{
  position: sticky;
  inset-block-end: 0;
  background: color-mix(in srgb, var(--ink-950) 88%, var(--brand-navy-900));
}
@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))){
  .menu__foot{
    background: color-mix(in srgb, var(--ink-950) 72%, transparent);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
            backdrop-filter: blur(14px) saturate(140%);
  }
}
/* ============ Hero ============ */
.hero{
  position: relative;
  padding-block: clamp(2.5rem, 6vw, 5rem) var(--space-2xl);
  overflow: clip;
  background: var(--ink-950);
  --color-text: var(--color-text-on-dark);
  --color-text-muted: var(--color-text-on-dark-muted);
  color: var(--color-text);
}
.hero::before{
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(60% 55% at 84% 12%, color-mix(in srgb, var(--brand-red-600) 32%, transparent), transparent 70%),
    radial-gradient(45% 40% at 8% 90%, color-mix(in srgb, var(--brand-navy-500) 40%, transparent), transparent 70%);
  pointer-events: none;
}
.hero__grid{
  position: relative;
  display: grid; gap: var(--space-xl);
  grid-template-columns: 1fr;
}
@media (min-width: 980px){
  .hero__grid{ grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); align-items: end; }
}
.hero__eyebrow{ color: var(--sand-500); }
.hero__eyebrow::before{ background: var(--sand-500); }
.hero h1{
  font-size: var(--text-4xl);
  color: #fff;
  max-inline-size: 16ch;
}
.hero h1 em{ font-style: normal; color: var(--brand-red-400); }
.hero__lede{ font-size: var(--text-md); color: var(--color-text-on-dark-muted); max-inline-size: 46ch; margin-block-end: var(--space-md); }
.hero__ctas{ display: flex; flex-wrap: wrap; gap: var(--space-xs); margin-block-end: var(--space-lg); }
.hero__trust{ display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-md); font-size: var(--text-xs); color: var(--color-text-on-dark-muted); list-style: none; padding: 0; margin: 0; }
.hero__trust li{ display: flex; align-items: center; gap: 0.5em; }
.hero__trust svg{ inline-size: 1.1em; block-size: 1.1em; color: var(--sand-500); flex: none; }

/* ============ Finance selector, signature interaction ============ */
.selector{
  position: relative;
  background: color-mix(in srgb, #101820 88%, var(--brand-navy-900) 12%);
  border: 1px solid rgba(245,242,237,0.14);
  border-radius: var(--radius-xl);
  padding: var(--space-md);
  box-shadow: var(--shadow-lg);
  container-type: inline-size;
  container-name: selector;
}
.selector__title{ font-family: var(--font-body); font-weight: 700; font-size: var(--text-base); color: #fff; margin-block-end: var(--space-2xs); }
.selector__hint{ font-size: var(--text-sm); color: var(--color-text-on-dark-muted); margin-block-end: var(--space-sm); }
.selector fieldset{ border: none; padding: 0; margin: 0; }
.selector__options{
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2xs);
}
.selector__option{ position: relative; }
.selector__option input{ position: absolute; inset: 0; inline-size: 100%; block-size: 100%; margin: 0; opacity: 0; cursor: pointer; }
.selector__option label{
  /* The three --art-* properties are how the illustration gets its
     colours. Custom properties inherit into the <use> shadow tree,
     which is the only way to reach inside a sprite symbol, since a
     CSS selector cannot cross that boundary. Each symbol paints with
     var(--art-line), var(--art-fill) and var(--art-accent), so the
     selected state below can retint the same drawing. */
  --art-line: rgba(245, 242, 237, 0.92);
  --art-fill: rgba(245, 242, 237, 0.09);
  --art-accent: var(--sand-500);

  display: flex; flex-direction: column; align-items: flex-start; gap: 0.55em;
  padding: var(--space-xs); min-block-size: 118px;
  border-radius: var(--radius-md);
  border: 1px solid rgba(245,242,237,0.16);
  background: rgba(255,255,255,0.03);
  transition: background var(--duration-fast) var(--ease-out-quart), border-color var(--duration-fast) var(--ease-out-quart), transform var(--duration-fast) var(--ease-spring);
  cursor: pointer;
}
/* Fallback for any label that still holds a bare sprite icon rather
   than the illustration medallion. */
.selector__option label > svg{ inline-size: 1.6em; block-size: 1.6em; color: var(--sand-500); }

.selector__art{
  display: grid;
  place-items: center;
  inline-size: 2.85rem;
  block-size: 2.85rem;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(245, 242, 237, 0.13);
  background: rgba(245, 242, 237, 0.05);
  transition: background var(--duration-fast) var(--ease-out-quart),
              border-color var(--duration-fast) var(--ease-out-quart);
}
.selector__art svg{ inline-size: 2rem; block-size: 2rem; }
.selector__name{ font-weight: 700; font-size: var(--text-sm); line-height: 1.2; color: #fff; }
.selector__sub{ font-size: var(--text-xs); line-height: 1.3; color: var(--color-text-on-dark-muted); }

.selector__option:hover label{ background: rgba(255,255,255,0.07); transform: translateY(-2px); }
.selector__option:hover .selector__art{ background: rgba(245, 242, 237, 0.09); }
.selector__option input:checked + label{
  --art-line: #FFFFFF;
  --art-fill: color-mix(in srgb, var(--brand-red-400) 30%, transparent);
  --art-accent: var(--brand-red-400);

  background: color-mix(in srgb, var(--brand-red-500) 22%, transparent);
  border-color: var(--brand-red-400);
}
.selector__option input:checked + label .selector__art{
  background: color-mix(in srgb, var(--brand-red-400) 20%, transparent);
  border-color: color-mix(in srgb, var(--brand-red-400) 55%, transparent);
}
.selector__option input:checked + label .selector__sub{ color: rgba(255, 255, 255, 0.86); }
.selector__option input:focus-visible + label{ outline: 3px solid var(--color-focus); outline-offset: 2px; }

/* A very narrow phone cannot carry the medallion beside a two line
   descriptor without the text getting squeezed, so below 360px the
   descriptor steps out and the tile keeps just the picture and name. */
@media (max-width: 359.98px){
  .selector__sub{ display: none; }
  .selector__option label{ min-block-size: 104px; }
}

.selector__result{
  margin-block-start: var(--space-sm);
  padding-block-start: var(--space-sm);
  border-block-start: 1px dashed rgba(245,242,237,0.2);
}
.selector__result-copy{ font-size: var(--text-sm); color: var(--color-text-on-dark-muted); margin-block-end: var(--space-xs); min-block-size: 2.6em; }
.selector__result-copy strong{ color: #fff; }
.selector__result-ctas{ display: flex; flex-wrap: wrap; gap: var(--space-2xs); }

@container selector (min-width: 420px){
  .selector__options{ grid-template-columns: repeat(4, 1fr); }
}

/* View-transition-friendly named region for selector result copy */
.selector__result-copy{ view-transition-name: selector-result; }

/* ---- Enquiry wizard steps ---- */
[data-enhanced] .selector__result{ display: none; }
.selector__progress{ list-style: none; display: flex; gap: 6px; padding: 0; margin: 0 0 var(--space-xs); }
.selector__progress li{ inline-size: 26px; block-size: 4px; border-radius: 2px; background: rgba(245,242,237,0.18); transition: background var(--duration-fast) var(--ease-standard); }
.selector__progress li.is-active{ background: var(--brand-red-500); }
.selector__q{ font-size: var(--text-sm); font-weight: 700; color: #fff; margin: 0 0 var(--space-3xs); }
.selector__q + .chip-group{ margin-block-end: var(--space-sm); }
.chip-group{ display: flex; flex-wrap: wrap; gap: var(--space-3xs); }
.chip{
  font: inherit; font-weight: 600; font-size: var(--text-sm); color: #fff;
  padding: 0.45em 1em; min-block-size: var(--tap-min); border-radius: var(--radius-full);
  border: 1px solid rgba(245,242,237,0.22); background: rgba(255,255,255,0.04); cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out-quart), border-color var(--duration-fast) var(--ease-out-quart), transform var(--duration-fast) var(--ease-spring);
}
.chip:hover{ background: rgba(255,255,255,0.09); transform: translateY(-1px); }
.chip[aria-pressed="true"]{ background: color-mix(in srgb, var(--brand-red-500) 30%, transparent); border-color: var(--brand-red-400); }
.chip:focus-visible{ outline: 3px solid var(--color-focus); outline-offset: 2px; }
.selector__summary{ font-size: var(--text-sm); color: var(--color-text-on-dark-muted); margin: 0 0 var(--space-xs); }
.selector__summary strong{ color: #fff; }
.selector__finish{ display: grid; gap: var(--space-2xs); }
.selector__form-link{ justify-self: center; font-size: var(--text-sm); margin-block-start: var(--space-3xs); }
.selector__back{
  margin-block-start: var(--space-xs); padding: 0.4em 0;
  background: none; border: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 0.4em;
  font: inherit; font-size: var(--text-sm); font-weight: 600; color: var(--color-text-on-dark-muted);
  transition: color var(--duration-fast) var(--ease-standard);
}
.selector__back:hover{ color: #fff; }
.selector__back svg{ inline-size: 1em; block-size: 1em; }

/* ============ Trust bar ============ */
.trust-bar{ background: var(--surface-sunken); border-block: 1px solid var(--color-border); }
.trust-bar .container{ display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg); align-items: center; justify-content: space-between; padding-block: var(--space-sm); }
.trust-bar__item{ display: flex; align-items: center; gap: 0.6em; font-size: var(--text-xs); font-weight: 600; color: var(--color-text-muted); }
.trust-bar__item svg{ inline-size: 1.2em; block-size: 1.2em; color: var(--brand-red-600); flex: none; }

/* ============ Service cards (container-query aware) ============ */
.card-grid{ display: grid; gap: var(--space-sm); grid-template-columns: repeat(auto-fit, minmax(15.5rem, 1fr)); }

.service-card{
  container-type: inline-size;
  container-name: card;
  background: var(--surface);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  padding: var(--space-md);
  text-decoration: none;
  color: var(--color-text);
  display: flex; flex-direction: column; gap: var(--space-xs);
  transition: transform var(--duration-base) var(--ease-out-quart), box-shadow var(--duration-base) var(--ease-out-quart), border-color var(--duration-base) var(--ease-out-quart);
  view-transition-name: none;
}
.service-card:hover{ transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: transparent; }
.service-card__icon{
  inline-size: 52px; block-size: 52px; border-radius: var(--radius-md);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-red-050); color: var(--brand-red-600); flex: none;
}
.service-card__icon svg{ inline-size: 28px; block-size: 28px; }
.service-card h3{ font-size: var(--text-lg); margin-block-end: 0.1em; }
.service-card p{ color: var(--color-text-muted); font-size: var(--text-sm); margin-block-end: 0; }
/* Optional detail list for a card that spans two bento rows (see
   bento__cell--tall), so the extra height reads as more information
   rather than empty space above the "Learn more" link. */
.service-card__points{ list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55em; }
.service-card__points li{ display: flex; gap: 0.6em; align-items: flex-start; font-size: var(--text-sm); color: var(--color-text-muted); }
.service-card__points svg{ inline-size: 1.15em; block-size: 1.15em; flex: none; color: var(--brand-red-600); margin-block-start: 0.15em; }
.service-card__cta{ margin-block-start: auto; font-weight: 700; color: var(--brand-red-600); font-size: var(--text-sm); display: inline-flex; align-items: center; gap: 0.4em; }
.service-card__cta svg{ inline-size: 1em; block-size: 1em; transition: transform var(--duration-fast) var(--ease-out-quart); }
.service-card:hover .service-card__cta svg{ transform: translateX(3px); }

@container card (min-width: 320px){
  .service-card{ padding: var(--space-lg); }
  .service-card h3{ font-size: var(--text-xl); }
}

/* Mobile bento: instead of a long single-file stack, the four service
   cards form a rhythm of full-width and half-width tiles. */
@media (max-width: 720px){
  .card-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xs); }
  .card-grid > :first-child,
  .card-grid > :last-child{ grid-column: span 2; }
  .service-card{ padding: var(--space-sm); border-radius: var(--radius-md); gap: var(--space-2xs); }
  .service-card__icon{ inline-size: 42px; block-size: 42px; }
  .service-card__icon svg{ inline-size: 22px; block-size: 22px; }
  .service-card h3{ font-size: var(--text-base); }
  .service-card p{ font-size: var(--text-xs); }
}

/* ============ How it helps / steps ============ */
.steps{ list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-sm); grid-template-columns: repeat(auto-fit, minmax(13rem,1fr)); counter-reset: step; }
.steps li{ counter-increment: step; position: relative; padding-inline-start: 3.2rem; }
.steps li::before{
  content: counter(step);
  position: absolute; inset-inline-start: 0; inset-block-start: -0.1em;
  inline-size: 2.4rem; block-size: 2.4rem; border-radius: var(--radius-full);
  background: var(--ink-950); color: #fff; font-family: var(--font-display); font-weight: 700;
  display: flex; align-items: center; justify-content: center; font-size: var(--text-md);
}
.steps h3{ font-size: var(--text-md); margin-block-end: 0.2em; }
.steps p{ color: var(--color-text-muted); font-size: var(--text-sm); }

/* Mobile: the red thread literally connects the numbered steps,
   drawing the eye down the story as you scroll. */
@media (max-width: 720px){
  .steps{ gap: var(--space-md); }
  .steps li:not(:last-child)::after{
    content: ""; position: absolute;
    inset-inline-start: 1.2rem; margin-inline-start: -1px;
    inset-block-start: 2.5rem; block-size: calc(100% + var(--space-md) - 2.6rem);
    inline-size: 2px; border-radius: 2px;
    background: linear-gradient(to bottom, var(--brand-red-500), var(--brand-red-100));
  }
}

/* ============ Experience / motor-industry band ============ */
.band{
  background: var(--ink-950);
  --color-text: var(--color-text-on-dark);
  --color-text-muted: var(--color-text-on-dark-muted);
  color: var(--color-text);
  position: relative; overflow: clip;
}
.band__grid{ display: grid; gap: var(--space-lg); grid-template-columns: minmax(0, 1fr); align-items: center; }
@media (min-width: 900px){ .band__grid{ grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); } }
.band__figure{
  font-family: var(--font-display); font-size: clamp(3.5rem, 4vw + 1rem, 6.5rem); line-height: 1; color: var(--brand-red-400);
}
.band__figure-label{ font-size: var(--text-sm); color: var(--color-text-on-dark-muted); margin-block-start: var(--space-2xs); max-inline-size: 22ch; }

.circumstance-list{ list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2xs); }
.circumstance-list li{ display: flex; gap: 0.7em; align-items: flex-start; font-size: var(--text-sm); color: var(--color-text-on-dark-muted); }
.circumstance-list svg{ inline-size: 1.3em; block-size: 1.3em; flex: none; color: var(--sand-500); margin-block-start: 0.1em; }

/* ============ Calculators ============ */
.calc-grid{ display: grid; gap: var(--space-xs); grid-template-columns: repeat(auto-fit, minmax(15rem,1fr)); }
.calc-card{
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-xs);
  padding: var(--space-sm); border-radius: var(--radius-md); border: 1px solid var(--color-border);
  background: var(--surface); text-decoration: none; color: var(--color-text);
  transition: border-color var(--duration-fast) var(--ease-out-quart), background var(--duration-fast) var(--ease-out-quart);
  min-block-size: var(--tap-min);
}
.calc-card:hover{ border-color: var(--brand-red-400); background: var(--brand-red-050); }
.calc-card span{ font-weight: 600; font-size: var(--text-sm); }
.calc-card svg{ inline-size: 1.1em; block-size: 1.1em; color: var(--brand-red-600); flex: none; }
.calc-card__ext{ font-size: var(--text-xs); color: var(--color-text-muted); font-weight: 500; }

.calc-note{
  display: flex; gap: 0.7em; padding: var(--space-sm); border-radius: var(--radius-md);
  background: var(--brand-navy-100); color: var(--brand-navy-900); font-size: var(--text-sm);
}
.calc-note svg{ inline-size: 1.3em; block-size: 1.3em; flex: none; margin-block-start: 0.1em; }

/* ============ FAQ accordion (native <details>) ============ */
.faq-list{ display: flex; flex-direction: column; gap: var(--space-2xs); }
.faq-item{
  background: var(--surface); border: 1px solid var(--color-border); border-radius: var(--radius-md);
  overflow: clip;
}
.faq-item summary{
  list-style: none; cursor: pointer; padding: var(--space-sm);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm);
  font-weight: 700; font-family: var(--font-display); font-size: var(--text-md);
  min-block-size: var(--tap-min);
}
.faq-item summary::-webkit-details-marker{ display: none; }
.faq-item summary .chev{ flex: none; inline-size: 1.4em; block-size: 1.4em; border-radius: var(--radius-full); border: 1px solid var(--color-border-strong); display: inline-flex; align-items: center; justify-content: center; transition: transform var(--duration-base) var(--ease-spring); }
.faq-item[open] summary .chev{ transform: rotate(45deg); background: var(--brand-red-050); }
.faq-item summary .chev svg{ inline-size: 0.7em; block-size: 0.7em; }
.faq-item__body{ padding: 0 var(--space-sm) var(--space-sm); color: var(--color-text-muted); max-inline-size: 65ch; }
.faq-item[open] summary{ border-block-end: 1px solid var(--color-border); }

@media (prefers-reduced-motion: no-preference){
  @supports (interpolate-size: allow-keywords){
    .faq-item__body{ interpolate-size: allow-keywords; }
    .faq-item::details-content{ block-size: 0; overflow: clip; transition: block-size var(--duration-base) var(--ease-out-quart), content-visibility var(--duration-base); transition-behavior: allow-discrete; }
    .faq-item[open]::details-content{ block-size: auto; }
  }
}

/* ============ Forms ============ */
.form-grid{ display: grid; gap: var(--space-sm); }
.field{ display: flex; flex-direction: column; gap: 0.45em; }
.field label{ font-weight: 700; font-size: var(--text-sm); }
.field .hint{ font-size: var(--text-xs); color: var(--color-text-muted); }
/* inline-size and min-inline-size are load bearing, not tidiness. A bare
   input carries an intrinsic width of roughly twenty characters, and that
   width becomes the min-content of the field, the field row, the form, the
   panel around it and finally the 1fr grid track holding the panel, because
   1fr means minmax(auto, 1fr) and auto floors at min-content. On a 320px
   screen that pushed the contact form about 60px past the right edge. */
.field input, .field textarea, .field select{
  font: inherit; padding: 0.85em 1em; min-block-size: var(--tap-min);
  inline-size: 100%; min-inline-size: 0;
  border-radius: var(--radius-sm); border: 1.5px solid var(--color-border-strong);
  background: var(--surface); color: var(--color-text);
  transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible{
  border-color: var(--color-focus); box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-focus) 18%, transparent); outline: none;
}
.field textarea{ resize: vertical; min-block-size: 8em; }
.field[data-invalid="true"] input, .field[data-invalid="true"] textarea{ border-color: var(--color-error); }
.field__error{ display: none; color: var(--color-error); font-size: var(--text-xs); font-weight: 600; gap: 0.4em; align-items: center; }
/* Size the warning icon explicitly. An inline <svg> with a viewBox but no
   width or height stretches to fill whatever space it is given, and this
   one had no rule of its own while every other icon on the site does. The
   result was a 277px warning triangle appearing next to the field label,
   and only ever at the moment a visitor got something wrong. */
.field__error svg{ inline-size: 1.05em; block-size: 1.05em; flex: none; }
.field[data-invalid="true"] .field__error{ display: flex; }
.field-row{ display: grid; gap: var(--space-sm); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 640px){ .field-row{ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

.consent{ display: flex; gap: 0.7em; align-items: flex-start; font-size: var(--text-xs); color: var(--color-text-muted); }
.consent input{ margin-block-start: 0.25em; inline-size: 18px; block-size: 18px; flex: none; }

.form-status{ display: none; align-items: center; gap: 0.6em; padding: var(--space-sm); border-radius: var(--radius-md); font-weight: 600; font-size: var(--text-sm); }
.form-status[data-state="success"]{ display: flex; background: var(--color-success-bg); color: var(--color-success); }
.form-status[data-state="error"]{ display: flex; background: var(--color-error-bg); color: var(--color-error); }
.form-status svg{ inline-size: 1.3em; block-size: 1.3em; flex: none; }

.btn[data-loading="true"] .btn-label{ visibility: hidden; }
.btn[data-loading="true"]{ position: relative; }
.btn__spinner{ display: none; position: absolute; inset: 0; align-items: center; justify-content: center; }
.btn[data-loading="true"] .btn__spinner{ display: flex; }
.btn__spinner svg{ animation: spin 900ms linear infinite; }
@media (prefers-reduced-motion: reduce){ .btn__spinner svg{ animation-duration: 1800ms; } }
@keyframes spin{ to{ transform: rotate(360deg); } }

/* ============ Footer ============ */
.site-footer{ background: var(--ink-950); color: var(--color-text-on-dark); padding-block: var(--space-2xl) var(--space-lg); }
.site-footer .brand__logo{ block-size: 60px; }
.footer-grid{ display: grid; gap: var(--space-lg); grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr)); margin-block-end: var(--space-lg); }
@media (max-width: 900px){ .footer-grid{ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 560px){ .footer-grid{ grid-template-columns: minmax(0, 1fr); } }
.footer-grid h4{ font-family: var(--font-body); font-size: var(--text-xs); letter-spacing: var(--tracking-wider); text-transform: uppercase; color: var(--color-text-on-dark-muted); margin-block-end: var(--space-xs); }
.footer-grid ul{ list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.55em; }
.footer-grid a{ text-decoration: none; color: var(--color-text-on-dark); font-size: var(--text-sm); }
.footer-grid a:hover{ color: var(--brand-red-400); }
.footer-legal{ font-size: var(--text-xs); color: var(--color-text-on-dark-muted); line-height: var(--leading-relaxed); border-block-start: 1px solid rgba(245,242,237,0.14); padding-block-start: var(--space-md); }
.footer-legal p{ max-inline-size: none; }
.footer-bottom{ display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-xs); margin-block-start: var(--space-sm); font-size: var(--text-xs); color: var(--color-text-on-dark-muted); }
.footer-bottom a{ color: inherit; }

/* ============ Sticky mobile CTA dock ============ */
.cta-dock{
  position: fixed; inset-inline: 0; inset-block-end: 0; z-index: 90;
  display: grid; grid-template-columns: 1fr 1fr 1.35fr; gap: 1px;
  background: var(--color-border);
  border-block-start: 1px solid var(--color-border);
  padding-block-end: env(safe-area-inset-bottom, 0);
  box-shadow: 0 -8px 24px -12px rgba(20,24,28,0.25);
}
.cta-dock a{
  background: var(--surface); color: var(--color-text); text-decoration: none;
  display: flex; align-items: center; justify-content: center; gap: 0.5em;
  font-weight: 700; font-size: var(--text-sm); padding: 0.95em 0.5em; min-block-size: 56px;
}
.cta-dock a.primary{ background: var(--brand-red-500); color: #fff; }
.cta-dock svg{ inline-size: 1.2em; block-size: 1.2em; }
/* The dock retires only once the header carries its own pre-approval
   button at 1280px. Retiring it at 900px, as it used to, left the
   tablet band with no visible call-to-action at all: the header
   button had not appeared yet and the dock was already gone. */
@media (min-width: 1280px){ .cta-dock{ display: none; } }
body.has-cta-dock{ padding-block-end: 62px; }
@media (min-width: 1280px){ body.has-cta-dock{ padding-block-end: 0; } }

/* ============ Editorial artwork ============ */
.art-frame{
  margin: 0; border-radius: var(--radius-xl); overflow: clip;
  box-shadow: var(--shadow-lg); background: var(--surface-sunken);
}
.art-frame img{ display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
.art-frame--landscape{ aspect-ratio: 16 / 9; }
.art-frame--wide{ aspect-ratio: 21 / 9; }
.art-frame--svg{ background: #fff; box-shadow: var(--shadow-md); border: 1px solid var(--color-border); }
.art-frame--svg img{ block-size: auto; object-fit: fill; }
@media (max-width: 640px){
  .art-frame--landscape{ aspect-ratio: 4 / 5; }
  .art-frame--wide{ aspect-ratio: 3 / 2; }
  .art-frame{ border-radius: var(--radius-lg); }
}
/* A feature image that rises up over the foot of a dark page hero */
.page-hero.page-hero--art{ padding-block-end: calc(var(--space-2xl) + var(--space-xl)); }
.feature-art{ position: relative; z-index: 2; margin-block-start: calc(var(--space-2xl) * -1); }

/* ============ Page hero (non-home) ============ */
.page-hero{
  background: var(--ink-950);
  --color-text: var(--color-text-on-dark);
  --color-text-muted: var(--color-text-on-dark-muted);
  color: var(--color-text);
  padding-block: var(--space-xl) var(--space-lg);
}
.breadcrumb{ list-style: none; display: flex; flex-wrap: wrap; gap: 0.5em; padding: 0; margin: 0 0 var(--space-sm); font-size: var(--text-xs); color: var(--color-text-on-dark-muted); }
.breadcrumb a{ color: inherit; text-decoration: none; }
.breadcrumb li:not(:last-child)::after{ content: "/"; margin-inline-start: 0.5em; opacity: 0.6; }
.page-hero h1{ font-size: var(--text-3xl); max-inline-size: 22ch; }
.page-hero p.lede{ color: var(--color-text-on-dark-muted); }
@media (max-width: 720px){
  /* Mobile: keep interior-page heroes to a headline, not a full screen,
     visitors reach the actual content within the first thumb-scroll. */
  .page-hero{ padding-block: var(--space-lg) var(--space-md); }
  .page-hero.page-hero--art{ padding-block-end: calc(var(--space-xl) + var(--space-md)); }
  .page-hero h1{ font-size: var(--text-2xl); }
  .page-hero p.lede{ font-size: var(--text-base); }
}
@media (max-width: 720px){
  .feature-art{ margin-block-start: calc(var(--space-xl) * -1); }
}

/* ============ Badges / pills ============ */
.pill{ display: inline-flex; align-items: center; gap: 0.4em; font-size: var(--text-xs); font-weight: 700; padding: 0.4em 0.9em; border-radius: var(--radius-full); background: var(--brand-red-050); color: var(--brand-red-700); }

/* ============ Legal page ============ */
.legal-card{ display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-sm); padding: var(--space-md); border-radius: var(--radius-lg); border: 1px solid var(--color-border); background: var(--surface); }
.legal-card__meta{ font-size: var(--text-xs); color: var(--color-text-muted); }
.flag-box{ display: flex; gap: 0.8em; padding: var(--space-sm); border-radius: var(--radius-md); background: var(--sand-050); border: 1px solid var(--sand-100); font-size: var(--text-sm); }
.flag-box svg{ inline-size: 1.4em; block-size: 1.4em; flex: none; color: var(--sand-500); }

/* ============ Testimonial-free proof / value props ============ */
.value-grid{ display: grid; gap: var(--space-sm); grid-template-columns: repeat(auto-fit, minmax(14rem,1fr)); }
.value-item{ display: flex; gap: 0.8em; }

/* Mobile bento: value points become compact two-across tiles, with a
   lone trailing tile stretching full width to square the block off. */
@media (max-width: 720px){
  .value-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xs); }
  .value-grid .value-item{
    flex-direction: column; gap: 0.55em;
    padding: var(--space-sm); border-radius: var(--radius-md);
    background: var(--surface); border: 1px solid var(--color-border);
  }
  .value-grid .value-item:last-child:nth-child(odd){ grid-column: span 2; }
  .value-grid .value-item h3{ font-size: var(--text-sm); }
  .value-grid .value-item p{ font-size: var(--text-xs); }
}

/* Below 400px a two across tile leaves under 100px of text measure once
   the padding is taken out, which breaks headings like "We don't lend
   the money" across four lines. Single file reads properly instead. */
@media (max-width: 399.98px){
  .value-grid{ grid-template-columns: minmax(0, 1fr); }
  .value-grid .value-item:last-child:nth-child(odd){ grid-column: auto; }
  .value-grid .value-item{ flex-direction: row; }
  .value-grid .value-item h3{ font-size: var(--text-base); }
  .value-grid .value-item p{ font-size: var(--text-sm); }
}
.value-item svg{ inline-size: 1.6em; block-size: 1.6em; color: var(--brand-red-600); flex: none; margin-block-start: 0.1em; }
.value-item h3{ font-size: var(--text-base); font-family: var(--font-body); font-weight: 700; margin-block-end: 0.15em; }
.value-item p{ font-size: var(--text-sm); color: var(--color-text-muted); }

/* ============ Split section ============ */
/* minmax(0, 1fr) rather than 1fr throughout. A plain 1fr track cannot
   shrink below the min-content of whatever sits in it, so one stubborn
   child silently widens the track past its own container and the page
   overflows sideways with no obvious culprit. */
.split{ display: grid; gap: var(--space-lg); grid-template-columns: minmax(0, 1fr); align-items: center; }
@media (min-width: 900px){ .split{ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
/* Columns centre by default, which is right when a block of text is
   paired with an illustration: the artwork sits against the middle of
   the prose rather than floating at the top. It is wrong when both
   columns are content. On the contact page the form is far shorter
   than the list beside it, and centring dropped it hundreds of pixels
   down the page, so it read as broken rather than composed. */
.split--top{ align-items: start; }
.split--reverse{ direction: rtl; }
.split--reverse > *{ direction: ltr; }
.media-frame{
  aspect-ratio: 4 / 3; border-radius: var(--radius-lg); overflow: clip;
  background: linear-gradient(155deg, var(--brand-navy-900), var(--ink-950));
  position: relative; display: flex; align-items: center; justify-content: center;
}
.media-frame svg{ inline-size: 55%; block-size: 55%; opacity: 0.9; }

/* ============ Call / text CTA block ============ */
.call-cta{
  background: linear-gradient(155deg, var(--ink-950), var(--brand-navy-900));
  --color-text: var(--color-text-on-dark);
  --color-text-muted: var(--color-text-on-dark-muted);
  color: var(--color-text);
  border-radius: var(--radius-xl);
  padding: var(--space-lg);
  text-align: center;
}
.call-cta__kicker{ font-size: var(--text-xs); font-weight: 700; letter-spacing: var(--tracking-wider); text-transform: uppercase; color: var(--sand-500); margin: 0 0 0.4em; }
.call-cta__title{ color: #fff; margin-block-end: 0.3em; }
.call-cta__lede{ color: var(--color-text-on-dark-muted); max-inline-size: 46ch; margin-inline: auto; margin-block-end: var(--space-md); }
.call-cta__actions{ display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-sm); }
.call-cta__btn{
  display: inline-flex; align-items: center; gap: 0.8em;
  padding: 0.7em 1.4em; border-radius: var(--radius-full);
  text-decoration: none; min-block-size: var(--tap-min);
  min-inline-size: 220px; justify-content: center;
  transition: transform var(--duration-fast) var(--ease-out-quart), background-color var(--duration-fast) var(--ease-standard);
}
.call-cta__btn svg{ inline-size: 1.6em; block-size: 1.6em; flex: none; }
.call-cta__btn span{ text-align: start; }
.call-cta__btn strong{ display: block; font-size: var(--text-base); line-height: 1.2; }
.call-cta__btn small{ display: block; font-size: var(--text-sm); opacity: 0.85; font-weight: 400; }
.call-cta__btn:hover{ transform: translateY(-2px); }
.call-cta__btn--call{ background: var(--brand-red-500); color: #fff; }
.call-cta__btn--call:hover{ background: var(--brand-red-600); }
.call-cta__btn--text{ background: rgba(255,255,255,0.08); color: #fff; border: 1px solid rgba(255,255,255,0.24); }
.call-cta__btn--text:hover{ background: rgba(255,255,255,0.14); }
@media (max-width: 640px){
  .call-cta__btn{ inline-size: 100%; }
}

/* ============ Wizard payoff checklist ============
   The hero wizard used to end on a summary of the visitor's own answers and
   three ways to contact us, which meant three taps bought them nothing. This
   block is what they get instead: the documents a lender will actually ask
   for, narrowed by all three answers. It sits above the contact buttons on
   purpose, so the value lands before the ask. */
.checklist{
  margin-block: var(--space-sm);
  padding: var(--space-sm);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.04);
  text-align: start;
}
.checklist__head{
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-base);
  margin: 0 0 var(--space-2xs);
  color: #fff;
}
.checklist__list{ list-style: none; margin: 0; padding: 0; display: grid; gap: 0.7em; }
.checklist__item{
  display: flex;
  align-items: flex-start;
  gap: 0.6em;
  font-size: var(--text-sm);
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.92);
}
.checklist__item svg{
  flex: none;
  inline-size: 1.05em;
  block-size: 1.05em;
  margin-block-start: 0.2em;
  color: var(--brand-red-400);
}
.checklist__item strong{ display: block; font-weight: 700; color: #fff; }
.checklist__detail{
  display: block;
  font-size: 0.94em;
  color: rgba(255, 255, 255, 0.68);
}
.checklist__note{
  margin-block: var(--space-xs) 0;
  padding-block-start: var(--space-xs);
  border-block-start: 1px solid rgba(255, 255, 255, 0.14);
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.82);
}
.checklist__fine{
  margin-block: var(--space-2xs) 0;
  font-size: var(--text-xs);
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.55);
}


/* ============ Google reviews ============
   Modelled closely on the real Google Business Profile review panel,
   because that is the thing a visitor already trusts. The pieces that
   do the persuading are the ones Google itself shows: the four-colour
   G, the score, the distribution (every bar but the five-star one is
   empty, which is the whole story), Google's own auto-generated topic
   chips, and the owner replies underneath each review.

   The wall below scrolls on its own rather than sitting in a grid.
   Twelve written reviews is too many to lay out flat without the
   section eating the page, and a slow drift reads as "there are more
   of these than fit", which a truncated grid does not.

   Motion rules, matching js/motion.js's philosophy:
   1. The resting state is fully readable. The animation only moves
      cards that are already painted, so no-JS and animation-blocked
      browsers still get the full wall.
   2. It pauses on hover AND focus-within, so a keyboard user tabbing
      into a card's link does not have it slide away from under them.
   3. Under prefers-reduced-motion the track stops animating and the
      wall reflows into a plain centred grid, with the duplicate set
      hidden so nothing reads twice.
=========================================================== */
.section--reviews{ background: var(--surface-sunken); overflow: hidden; }

/* ---- Summary panel ---- */
.gr-summary{
  display: grid;
  gap: var(--space-md);
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  align-items: center;
  margin-block-end: var(--space-lg);
  background: var(--surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  box-shadow: var(--shadow-md);
}
@media (min-width: 900px){
  .gr-summary{ grid-template-columns: minmax(0, auto) minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-lg); padding: var(--space-md) var(--space-lg); }
}

/* flex column + align-items, not text-align. base.css resets every
   svg/img to display:block ("img, picture, svg, video{ display: block }"),
   and text-align never centers a block box, only inline content, so the
   G mark was sitting flush against the container's left edge while the
   text beneath it (still inline) centred normally. That mismatch is
   what actually read as "the logo isn't centered" — the mark was fine,
   its container's centering method just didn't apply to it. */
.gr-summary__score{ display: flex; flex-direction: column; align-items: center; }
.gr-summary__g{ inline-size: 34px; block-size: 34px; }
.gr-summary__num{
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(3rem, 2.4rem + 2.4vw, 4.2rem); line-height: 0.95;
  letter-spacing: var(--tracking-tight);
  margin-block: 0.1em 0.05em;
}
.gr-summary__stars{ display: flex; justify-content: center; gap: 0.12em; color: #F2A72E; }
.gr-summary__stars svg{ inline-size: 1.15rem; block-size: 1.15rem; }
.gr-summary__count{ font-size: var(--text-xs); color: var(--color-text-muted); margin-block-start: 0.5em; }

/* ---- Distribution bars ---- */
.gr-bars{ display: flex; flex-direction: column; gap: 0.35em; min-inline-size: 0; }
.gr-bar{ display: flex; align-items: center; gap: 0.5em; font-size: var(--text-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.gr-bar__label{ inline-size: 1ch; flex: none; text-align: end; }
.gr-bar__star{ inline-size: 0.72rem; block-size: 0.72rem; flex: none; color: #F2A72E; }
.gr-bar__track{ flex: 1; block-size: 8px; border-radius: var(--radius-full); background: var(--ink-100, #E7E4DE); overflow: hidden; min-inline-size: 0; }
.gr-bar__fill{ display: block; block-size: 100%; inline-size: var(--pct, 0%); border-radius: inherit; background: #F2A72E; }
.gr-bar__n{ inline-size: 4ch; flex: none; text-align: end; }  /* fits "100%" */

/* ---- Topic chips, the phrases Google itself pulled out of the reviews ---- */
.gr-topics{ display: flex; flex-wrap: wrap; gap: 0.4em; margin-block-end: var(--space-xs); }
.gr-topic{
  display: inline-flex; align-items: center; gap: 0.45em;
  font-size: var(--text-xs); font-weight: 600;
  padding: 0.42em 0.85em;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text);
}
.gr-topic b{ font-weight: 700; color: var(--color-text-muted); }
.gr-aside{ min-inline-size: 0; }
.gr-aside .btn{ inline-size: 100%; justify-content: center; }

@media (max-width: 899.98px){
  .gr-summary{ grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; }
  .gr-bars{ inline-size: min(100%, 22rem); }
  .gr-aside{ inline-size: min(100%, 22rem); }
  .gr-topics{ justify-content: center; }
}

/* ---- The scrolling wall ---- */
.gr-wall{
  --gr-gap: var(--space-sm);
  display: flex; flex-direction: column; gap: var(--gr-gap);
  margin-block-end: var(--space-md);
  /* Fades the cards out at both edges instead of letting them clip on a
     hard line, so the row reads as continuing rather than being cut. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.gr-wall__row{ display: flex; gap: var(--gr-gap); inline-size: max-content; }
/* flex-start, not the default stretch. Stretching every card to the
   tallest in its row left the short reviews as mostly-empty boxes with
   a reply marooned at the bottom. Letting each card be its own height
   reads as a wall of real reviews rather than a table of them. */
/* One row, not two. Two rows of six put roughly ten cards on a desktop
   screen at once, which read as a wall of text rather than as social
   proof. A single row of all twelve shows three or four at a time and
   lets the rest arrive as they drift.
   156s, not 78s: the track now carries twelve cards instead of six, so
   the duration doubles to keep the actual scroll speed unchanged. */
.gr-wall__track{
  display: flex; gap: var(--gr-gap); align-items: flex-start;
  animation: gr-drift 156s linear infinite;
  will-change: transform;
}
/* Both tracks carry the same animation, so when track one has travelled
   exactly its own width plus the gap, track two is sitting precisely
   where track one began. That is what makes the loop seamless. */
@keyframes gr-drift{
  from{ transform: translateX(0); }
  to{ transform: translateX(calc(-100% - var(--gr-gap))); }
}
.gr-wall:hover .gr-wall__track,
.gr-wall:focus-within .gr-wall__track{ animation-play-state: paused; }

/* ---- Review card ---- */
.review-card{
  inline-size: 21rem; flex: none;
  /* The card is a <figure>, and the UA default for that is
     `margin: 1em 40px`. Left unreset it added 80px of phantom width to
     every card in the wall and pushed the whole track off its own
     left edge. */
  margin: 0;
  display: flex; flex-direction: column; gap: 0.7em;
  background: var(--surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-sm);
  transition: box-shadow var(--duration-base) var(--ease-out-quart),
              border-color var(--duration-base) var(--ease-out-quart);
}
.review-card:hover{ box-shadow: var(--shadow-md); border-color: var(--color-border-strong); }
.review-card__head{ display: flex; align-items: center; gap: 0.65em; }
.review-card__avatar{
  inline-size: 38px; block-size: 38px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--av, var(--ink-400));
  font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: #fff;
}
.review-card__who{ flex: 1; min-inline-size: 0; }
.review-card__who strong{ display: block; font-size: var(--text-sm); line-height: 1.3; }
.review-card__meta{ display: block; font-size: 0.7rem; color: var(--color-text-muted); }
.review-card__g{ inline-size: 17px; block-size: 17px; flex: none; align-self: flex-start; }
.review-card__stars{ display: inline-flex; gap: 0.1em; color: #F2A72E; }
.review-card__stars svg{ inline-size: 0.85rem; block-size: 0.85rem; }
.review-card__quote{ font-size: var(--text-sm); line-height: var(--leading-relaxed); margin: 0; }

/* The honesty line under the wall. A rating and a count typed into a
   static page start decaying the day they are written. Stamping them
   with a date turns a claim that quietly becomes false into a statement
   about a moment in time, which stays true, and the link next to it
   sends anyone who cares to the live source. */
.gr-asat{
  font-size: var(--text-xs); color: var(--color-text-muted);
  margin-block-start: var(--space-sm);
  /* base.css caps every <p> at 68ch. Without margin-inline:auto the
     text-align:center on this line only centres the words inside that
     capped box, which sits hard against the left gutter, so the line
     looks left-aligned no matter what text-align says. */
  margin-inline: auto;
}
.gr-asat a{ color: inherit; font-weight: 700; text-decoration: underline;
  text-decoration-color: var(--color-border-strong); text-underline-offset: 0.2em; }
.gr-asat a:hover{ text-decoration-color: currentColor; }

/* The owner's reply, indented under the review exactly as Google shows
   it. It is half the persuasion: it says someone is still answering. */
.review-card__reply{
  padding: 0.7em 0.85em;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  border-inline-start: 2px solid var(--color-border-strong);
}
.review-card__reply-head{
  display: flex; align-items: center; gap: 0.4em;
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: var(--tracking-wider); color: var(--color-text-muted);
  margin-block-end: 0.35em;
}
.review-card__reply p{ font-size: 0.8rem; line-height: 1.55; color: var(--color-text-muted); margin: 0; }

/* ---- Phones do not get the marquee ----
   Two reasons, both practical rather than stylistic. A card is close to
   full width here, so the sentence being read slides out from under the
   reader; and there is no hover on a touch screen, so the pause that
   makes the drift tolerable on desktop does not exist. Sliding text you
   cannot stop is worse than no motion at all.

   So below 720px the wall becomes a plain stack. The second row and the
   tail of the first are dropped, because twelve stacked cards is several
   screens of scrolling: four strong, recent reviews plus the link to the
   full set on Google says the same thing in a fifth of the height. */
@media (max-width: 720px){
  /* The wall sits outside .container so it can run edge to edge while it
     is a marquee. Once it is a stack it needs the container's gutter
     back, so the cards line up with everything above them. */
  .gr-wall{ -webkit-mask-image: none; mask-image: none; padding-inline: var(--gutter); }
  .gr-wall__row{ inline-size: auto; }
  .gr-wall__track{ animation: none; flex-direction: column; inline-size: 100%; }
  .gr-wall__track[aria-hidden="true"]{ display: none; }
  .gr-wall__track > .review-card:nth-child(n+5){ display: none; }
  .review-card{ inline-size: 100%; }
}

/* ---- Reduced motion: stop the drift, reflow into a plain grid ---- */
@media (prefers-reduced-motion: reduce){
  .gr-wall{ -webkit-mask-image: none; mask-image: none; }
  .gr-wall__row{ inline-size: auto; flex-wrap: wrap; justify-content: center; }
  .gr-wall__track{ animation: none; flex-wrap: wrap; justify-content: center; }
  .gr-wall__track[aria-hidden="true"]{ display: none; }
  .review-card{ inline-size: min(100%, 21rem); }
}

/* ============ What we finance ============
   Themy's most common complaint about the old site was that people did
   not know he does anything beyond car loans. This strip answers that
   in one screen, immediately after the hero, with a picture of each
   thing rather than a list of words, because a list of eight nouns is
   read as "etc." and a row of eight objects is not.

   The artwork is the same paper-craft language as the feature images.
   Each was generated at 1024px, then its paper backdrop was shifted to
   exactly --surface-sunken so the eight tiles sit on one continuous
   colour instead of eight slightly different creams. */
.section--ftypes{ background: var(--surface-sunken); }

/* Four across on a phone, not two.
   At two across the tiles were ~165px each and the eight of them ran to
   four rows, so this section alone was most of a phone screen twice
   over and pushed the rest of the page below the fold. The art is a
   bold single object with no fine detail, so it survives being small.
   Four across puts the whole range on one glance in two short rows. */
.ftype-grid{
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--space-3xs);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (min-width: 560px){ .ftype-grid{ gap: var(--space-xs); } }
@media (min-width: 1080px){ .ftype-grid{ grid-template-columns: repeat(8, minmax(0, 1fr)); gap: var(--space-2xs); } }

.ftype{
  display: flex; flex-direction: column; align-items: center; gap: 0.2em;
  text-decoration: none; color: var(--color-text);
  padding: var(--space-2xs) var(--space-3xs) var(--space-xs);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  transition: transform var(--duration-base) var(--ease-out-quart),
              box-shadow var(--duration-base) var(--ease-out-quart),
              border-color var(--duration-base) var(--ease-out-quart),
              background-color var(--duration-base) var(--ease-out-quart);
}
.ftype:hover{
  transform: translateY(-4px);
  border-color: var(--color-border);
  box-shadow: var(--shadow-md);
}
/* Each photo is its own rounded card rather than something trying to
   melt into the page.

   Two earlier attempts tried to make the art's paper backdrop vanish
   against the section: mix-blend-mode: multiply (which darkened
   #F3F1EC against itself and drew the exact grey square it was meant
   to hide), then a flat-field correction of the studio vignette (which
   mis-fits on the images whose object reaches the border). Both were
   fighting for an invisibility worth nothing to a visitor. A visible,
   deliberate card has no seam to get wrong, and reads as a product
   tile, which is what it is. */
.ftype__img{
  inline-size: 100%; block-size: auto; aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-md);
  background: var(--surface);
}
.ftype__label{
  font-weight: 700; font-size: var(--text-sm); text-align: center;
  line-height: 1.25;
}
/* Phones: tighter padding and a smaller label so four tiles fit a
   narrow row without the two-word labels forcing a third line. */
@media (max-width: 559.98px){
  .ftype{ padding: var(--space-3xs) 2px var(--space-2xs); gap: 0.1em; }
  .ftype__label{ font-size: 0.68rem; line-height: 1.2; }
  .section--ftypes .section-head{ margin-block-end: var(--space-md); }
}
@media (prefers-reduced-motion: reduce){
  .ftype:hover{ transform: none; }
}

/* ---- Hero social-proof pill ----
   Sits directly above the hero's main call to action, so the order a
   visitor reads is headline, explanation, proof, then the button. It is
   deliberately quiet, a translucent panel on the dark hero rather than
   a coloured badge, because it is meant to reassure at the moment of
   clicking rather than compete with the CTA next to it.

   Generated by build-reviews.py from data/reviews.json, so the numbers
   here cannot drift away from the ones in the reviews section. */
.gr-pill{
  display: inline-flex; align-items: center; gap: 0.55em;
  margin-block-end: var(--space-sm);
  padding: 0.5em 0.95em;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.18);
  text-decoration: none;
  color: #fff;
  font-size: var(--text-xs);
  line-height: 1;
  transition: background-color var(--duration-fast, 160ms) var(--ease-out-quart, ease),
              border-color var(--duration-fast, 160ms) var(--ease-out-quart, ease),
              transform var(--duration-fast, 160ms) var(--ease-out-quart, ease);
}
.gr-pill:hover{
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.32);
  transform: translateY(-1px);
}
.gr-pill__g{ inline-size: 15px; block-size: 15px; flex: none; }
.gr-pill__stars{ display: inline-flex; gap: 0.08em; color: #F2A72E; flex: none; }
.gr-pill__stars svg{ inline-size: 0.78rem; block-size: 0.78rem; }
.gr-pill__text{ white-space: nowrap; color: rgba(255, 255, 255, 0.82); }
.gr-pill__text strong{ color: #fff; font-weight: 700; }

/* Below ~380px the full sentence pushes the pill wider than the screen,
   so the stars carry the meaning and the wording shortens. */
@media (max-width: 380px){
  .gr-pill{ gap: 0.45em; padding: 0.45em 0.8em; }
  .gr-pill__text{ font-size: 0.68rem; }
}
@media (prefers-reduced-motion: reduce){
  .gr-pill:hover{ transform: none; }
}

/* Small outbound arrow on the hero pill. The pill leaves the site for
   Google, so it says so rather than looking like an in-page jump. */
.gr-pill__out{
  inline-size: 0.72rem; block-size: 0.72rem; flex: none;
  color: rgba(255, 255, 255, 0.55);
  transition: transform var(--duration-fast, 160ms) var(--ease-out-quart, ease);
}
.gr-pill:hover .gr-pill__out{ transform: translateX(2px); }
@media (prefers-reduced-motion: reduce){
  .gr-pill:hover .gr-pill__out{ transform: none; }
}
